112 lines
No EOL
4.6 KiB
C#
112 lines
No EOL
4.6 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Compiler.Parser;
|
|
using Compiler.Parser.Nodes;
|
|
|
|
namespace Compiler.Generator
|
|
{
|
|
public class Generator
|
|
{
|
|
public string Generate(Node rootNode)
|
|
{
|
|
string s = "";
|
|
switch (rootNode.NodeType)
|
|
{
|
|
case NodeType.ProgramNode:
|
|
foreach (Node rootNodeChild in rootNode.Children)
|
|
{
|
|
s += Generate(rootNodeChild);
|
|
}
|
|
|
|
break;
|
|
case NodeType.FunctionNode:
|
|
string identifier = ((FunctionNode) rootNode).Name;
|
|
string functionBody = "";
|
|
foreach (Node rootNodeChild in rootNode.Children)
|
|
{
|
|
functionBody += Generate(rootNodeChild);
|
|
}
|
|
|
|
s = $".globl {identifier}\n" +
|
|
$"{identifier}:\n" +
|
|
$"{functionBody}";
|
|
break;
|
|
case NodeType.ReturnStatementNode:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"ret\n";
|
|
break;
|
|
case NodeType.ExpressionNode:
|
|
s = Generate(rootNode.Children[0]);
|
|
break;
|
|
case NodeType.ConstantNode:
|
|
s = $"movl ${((ConstantNode) rootNode).value.ToString()}, %eax\n";
|
|
break;
|
|
case NodeType.UnaryOperatorNode:
|
|
switch (((UnaryOperatorNode) rootNode).OperatorType)
|
|
{
|
|
case OperatorType.Negation:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"neg %eax\n";
|
|
break;
|
|
case OperatorType.BitwiseComplement:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"not %eax\n";
|
|
break;
|
|
case OperatorType.LogicalNegation:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"cmpl $0, %eax\n" +
|
|
"movl $0, %eax\n" +
|
|
"sete %al\n";
|
|
break;
|
|
default:
|
|
throw new NotSpecifiedException(NodeType.UnaryOperatorNode,
|
|
((UnaryOperatorNode) rootNode).OperatorType);
|
|
}
|
|
|
|
break;
|
|
case NodeType.BinaryOperatorNode:
|
|
switch (((BinaryOperatorNode) rootNode).OperatorType)
|
|
{
|
|
case OperatorType.Addition:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"push %rax\n" +
|
|
$"{Generate(rootNode.Children[1])}" +
|
|
"pop %rcx\n" +
|
|
"add %ecx, %eax\n";
|
|
break;
|
|
case OperatorType.Subtraction:
|
|
s = $"{Generate(rootNode.Children[1])}" +
|
|
"push %rax\n" +
|
|
$"{Generate(rootNode.Children[0])}" +
|
|
"pop %rcx\n" +
|
|
"sub %ecx, %eax\n";
|
|
break;
|
|
case OperatorType.Multiplication:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"push %rax\n" +
|
|
$"{Generate(rootNode.Children[1])}" +
|
|
"pop %rcx\n" +
|
|
"imul %rcx, %rax\n";
|
|
break;
|
|
case OperatorType.Division:
|
|
s = $"{Generate(rootNode.Children[0])}" +
|
|
"push %rax\n" +
|
|
$"{Generate(rootNode.Children[1])}" +
|
|
"movl %eax, %ecx\n" + //move calculated divisor to %ecx
|
|
"pop %rax\n" + //pop divident do %eax
|
|
"cdq\n" +
|
|
"idivl %ecx\n"; //eax contains the result, edx the rest
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
break;
|
|
default:
|
|
throw new NotSpecifiedException(rootNode.NodeType);
|
|
}
|
|
|
|
return s;
|
|
}
|
|
}
|
|
} |