private static bool CompileConditionOrLoop(int level, bool debug, Node container, Node node, NanCodeWriter wr, Scope parameterNames) { bool returns = false; if (container.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(container.Children.ElementAt(0)); condition.Text = "()"; var topOfBlock = wr.Position() - 1; var body = new Node(false, -2); for (int i = 1; i < container.Children.Count; i++) { body.AddLast(container.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); }