private static void CompileMemoryFunction(int level, bool debug, Node node, NanCodeWriter wr, Scope parameterNames) { // Check for special increment mode if (node.Text == "set" && Optimisations.IsSmallIncrement(node, out var incr, out var target)) { wr.Increment(incr, target); return; } // Pivot the node's children into 1st child, with the rest as 1st child's children var child = new Node(false, node.SourceLocation) { Text = node.Children.First.Value.Text }; var paramCount = node.Children.Count - 1; for (int i = paramCount; i > 0; i--) { child.AddLast(node.Children.ElementAt(i)); } wr.Merge(Compile(child, level + 1, debug, parameterNames, null, Context.MemoryAccess)); if (debug) { wr.Comment("// Memory function : " + node.Text); } wr.Memory(node.Text[0], child.Text, paramCount); }
private static bool CompileConditionOrLoop(int level, bool debug, Node node, NanCodeWriter wr, Scope parameterNames) { bool returns = false; if (node.Children.Count < 1) { throw new ArgumentException(node.Text + " required parameter(s)"); } bool isLoop = node.Text == "while"; var context = isLoop ? Context.Loop : Context.Condition; var condition = new Node(false, -2); condition.AddLast(node.Children.ElementAt(0)); condition.Text = "()"; var topOfBlock = wr.Position() - 1; var body = new Node(false, -2); for (int i = 1; i < node.Children.Count; i++) { body.AddLast(node.Children.ElementAt(i)); } body.Text = "()"; var compiledBody = Compile(body, level + 1, debug, parameterNames, null, context); returns |= compiledBody.ReturnsValues; var opCodeCount = compiledBody.OpCodeCount(); if (isLoop) { opCodeCount++; // also skip the end unconditional jump } if (debug) { wr.Comment("// Compare condition for : " + node.Text + ", If false, skip " + compiledBody.OpCodeCount() + " element(s)"); } if (Optimisations.IsSimpleComparion(condition, opCodeCount)) { // output just the arguments var argNodes = Optimisations.ReadSimpleComparison(condition, out var cmpOp, out var argCount); var conditionArgs = Compile(argNodes, level + 1, debug, parameterNames, null, context); wr.Merge(conditionArgs); wr.CompoundCompareJump(cmpOp, argCount, (ushort)opCodeCount); } else { var conditionCode = Compile(condition, level + 1, debug, parameterNames, null, context); if (debug) { wr.Comment("// Condition for : " + node.Text); } wr.Merge(conditionCode); wr.CompareJump(opCodeCount); } wr.Merge(compiledBody); if (debug) { wr.Comment("// End : " + node.Text); } if (isLoop) { var distance = wr.Position() - topOfBlock; wr.UnconditionalJump((uint)distance); } return(returns); }