private void Generate(AbstractNode node) { var debugNodeTypes = new NodeType[] { /*NodeType.Block, * NodeType.Literal, * NodeType.Identifier, * NodeType.Loop, * NodeType.Operation,*/ }; if (debugNodeTypes.Contains(node.Type)) { Debug(node.ToString()); } switch (node.Type) { case NodeType.Block: ((BlockNode)node).Statements.ForEach(Generate); break; case NodeType.Operation: var operation = (OperationNode)node; // Operations that require two integer as input var integerOperations = new[] { OperatorType.BitwiseAnd, OperatorType.AndAlso, OperatorType.BitwiseOr, OperatorType.OrElse }; var outputIntegerOperations = new[] { OperatorType.Equals, OperatorType.Greater, OperatorType.NotGreater, OperatorType.Less, OperatorType.NotLess, OperatorType.NotEquals }; /* * We accept floating only, sometimes we need integer (logical and/or) * In this case, we cast the floating into an integer and cast back the result into a floating one. */ var requireInteger = integerOperations.Contains(operation.Operator); var requireOutputTransform = outputIntegerOperations.Contains(operation.Operator); Generate(operation.LeftOperand); if (requireInteger) { Write("ftoi"); } Generate(operation.RightOperand); if (requireInteger) { Write("ftoi"); } switch (operation.Operator) { case OperatorType.Add: Write("add.f"); break; case OperatorType.Sub: Write("sub.f"); break; case OperatorType.Mul: Write("mul.f"); break; case OperatorType.Div: Write("div.f"); break; case OperatorType.BitwiseAnd: case OperatorType.AndAlso: Write("and"); break; case OperatorType.BitwiseOr: case OperatorType.OrElse: Write("or"); break; case OperatorType.Equals: Write("cmpeq.f"); break; case OperatorType.NotEquals: Write("cmpne.f"); break; case OperatorType.NotGreater: Write("cmple.f"); break; case OperatorType.Less: Write("cmplt.f"); break; case OperatorType.NotLess: Write("cmpge.f"); break; case OperatorType.Greater: Write("cmpgt.f"); break; case OperatorType.EuclidianDiv: Write(Drop()); Write(Drop()); Generate(BuiltinFunctions.EuclidianDiv(operation.LeftOperand, operation.RightOperand)); break; case OperatorType.Mod: Write(Drop()); Write(Drop()); Generate(BuiltinFunctions.Mod(operation.LeftOperand, operation.RightOperand)); break; case OperatorType.Pow: Write(Drop()); Write(Drop()); Generate(BuiltinFunctions.Pow(operation.LeftOperand, operation.RightOperand)); break; } if (requireInteger || requireOutputTransform) { Write("itof"); } break; case NodeType.Declaration: var dcl = (AddressableDeclarationNode)node; switch (dcl.Identifier.Symbol.Type) { case ObjectType.Floating: Generate(dcl.Expression); Write ( Set(dcl.Identifier.Symbol.Pointer) ); break; case ObjectType.Pointer: var indexExpressions = ((MultiExpressionNode)dcl.Expression).Expressions; indexExpressions.Reverse(); AbstractExpressionNode finalExpression = LiteralNode.One; for (var i = 0; i < indexExpressions.Count - 1; i++) { finalExpression = new OperationNode ( OperatorType.Mul, new OperationNode ( OperatorType.Add, LiteralNode.One, indexExpressions[i] ), finalExpression ); } finalExpression = new OperationNode ( OperatorType.Mul, indexExpressions.Last(), finalExpression ); Generate(BuiltinFunctions.BorrowMemory(finalExpression)); Write(Set(dcl.Identifier.Symbol.Pointer)); var tempVar = new AddressableIdentifierNode(new PrimitiveVariableSymbol("", PointerIndex + 1)); Write(Pushf()); Generate(BuiltinFunctions.BorrowMemory(new LiteralNode(indexExpressions.Count))); Write(Set(tempVar.Symbol.Pointer)); indexExpressions.Reverse(); for (var i = 0; i < indexExpressions.Count; i++) { Generate ( new PointerAssignationNode ( new OperationNode ( OperatorType.Add, tempVar, new LiteralNode(i) ), indexExpressions[i] ) ); } /* * var a = bmem(6); * var b = bmem(2); * :b = 2; * :b + 1 = 2; * init_array(a, b, 2); */ Generate(BuiltinFunctions.InitArray(dcl.Identifier, tempVar, new LiteralNode(indexExpressions.Count))); Write(Get(tempVar.Symbol.Pointer)); Generate(BuiltinFunctions.RecoverMemory(tempVar)); break; } break; case NodeType.Reference: var refnode = (ReferenceNode)node; Write ( Pushf(refnode.Identifier.Symbol.Pointer) ); break; case NodeType.Dereference: var deref = (DereferenceNode)node; Generate(deref.Expression); Writes ( Ftoi(), MemRead(), Itof() ); break; case NodeType.Assignation: var assign = (AssignationNode)node; Generate(assign.ValueExpression); Write ( Set(assign.Identifier.Symbol.Pointer) ); break; case NodeType.Drop: Write(Drop()); break; case NodeType.PointerAssignation: var ptrAssign = (PointerAssignationNode)node; Generate(ptrAssign.AddressExpression); Write ( Ftoi() ); Generate(ptrAssign.ValueExpression); Writes ( Ftoi(), MemWrite() ); break; case NodeType.Literal: var lit = (LiteralNode)node; Write(Pushf(lit.Value)); break; case NodeType.Identifier: var ident = (AddressableIdentifierNode)node; Write ( Get(ident.Symbol.Pointer) ); break; case NodeType.Crash: Write("halt"); break; case NodeType.Print: if (node is PrintExpressionNode) { var printe = (PrintExpressionNode)node; Generate(printe.Expression); Write("out.f"); } else { var prints = (PrintStringNode)node; foreach (var c in prints.Content) { Write($"push.i {(int)c}"); Write("out.c"); } } Write("push.i 10"); Write("out.c"); break; case NodeType.Loop: var loop = (LoopNode)node; { Write(DeclareLabel(BeginLoop(loop.UniqueId))); Generate(loop.Conditional); Write(DeclareLabel(IterationLoop(loop.UniqueId))); Generate(loop.Iteration); Write(Jump(BeginLoop(loop.UniqueId))); Write(DeclareLabel(EndLoop(loop.UniqueId))); } break; case NodeType.Break: var breakNode = (BreakNode)node; Write(Jump(EndLoop(breakNode.LoopId))); break; case NodeType.Continue: var cont = (ContinueNode)node; Write(Jump(EndIf(cont.CondId))); break; case NodeType.Conditional: var cond = (ConditionalNode)node; { Generate(cond.Expression); Write(JumpFalse(Else(cond.UniqueId))); Generate(cond.TrueStatement); Write(Jump(EndIf(cond.UniqueId))); Write(DeclareLabel(Else(cond.UniqueId))); Generate(cond.FalseStatement); Write(DeclareLabel(EndIf(cond.UniqueId))); } break; case NodeType.MultiExpression: var multi = (MultiExpressionNode)node; foreach (var expression in multi.Expressions) { Generate(expression); } break; case NodeType.Function: var fun = (FunctionNode)node; Write(DeclareLabel(fun.Identifier.Symbol.Name)); PointerIndex = fun.Arguments.Count - 1; PreGenerate(fun.Statement); Generate(fun.Statement); if (fun.Identifier.Symbol.Name != "start") { Write(Pushf()); Write(Ret()); } else { Write(Halt()); } break; case NodeType.Return: var ret = (ReturnNode)node; Generate(ret.Expression); Write(Ret()); break; case NodeType.Call: var call = (CallNode)node; Write(Prep(call.Target.Symbol.Name)); foreach (var arg in call.Parameters) { Generate(arg); } Write(Call(call.Parameters.Count)); break; case NodeType.Root: var root = (RootNode)node; foreach (var f in root.Functions) { Generate(f); } break; } }
public override AbstractStatementNode ReleaseInstruction() { return(BuiltinFunctions.RecoverMemory(new AddressableIdentifierNode(this))); }