예제 #1
0
        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);
        }