Пример #1
0
        private void CEControlFlow(Parse.ControlFlow Item, Parse.Block Parent, Block Compiled)
        {
            switch (Item.Type)
            {
            case Parse.ControlFlow.eType.Call:
                //A call to a block
                CompileElement(Item.Target, Parent, Compiled);
                break;

            case Parse.ControlFlow.eType.Fail:
                //Return a number of blocks
                Compiled.AddItem(new ReturnBlock(Parent.Depth - Item.Target.Depth + (Item.Target.Type == Parse.Block.eType.Multi ? 0 : 1), false));
                break;

            case Parse.ControlFlow.eType.Succeed:
                //Return a number of blocks
                Compiled.AddItem(new ReturnBlock(Parent.Depth - Item.Target.Depth + 1, true));
                break;

            case Parse.ControlFlow.eType.GoTo:
                //GoTo block - if the common parent is the target then return it and run it again
                var gtb = new GoToBlock(0, 0, null);
                gtb.TargetName = Item.Target.Name;
                //We will add the elements index after the compilation - we might not know a block's index (it is not compiled yet)
                _GoToBackPatches.Add(new GoToBackPatchInfo(Item.Target, Parent, gtb, this));
                Compiled.AddItem(gtb);
                break;

            case Parse.ControlFlow.eType.Continue:
                //GoTo block
                var cont = new GoToBlock(Parent.Depth - Item.Target.Depth, 1, new [] { _BlocksByParse[Item.Target].ForContinue });
                cont.TargetName = Item.Target.Name;
                Compiled.AddItem(cont);
                break;

            default:
                ThrowParseError("Unknown type", Item.Annotation.SourcePosition);
                break;
            }
        }
Пример #2
0
            public GoToBackPatchInfo(Parse.Block newTarget, Parse.Block Parent, GoToBlock newGoToBlock, Compiler Compiler)
            {
                Target    = newTarget;
                GoToBlock = newGoToBlock;

                //Find the common ancestor
                var ancestor = Target.FindCommonAncestor(Parent);

                Runnable[] ar;
                if (Target.Parent == null)
                //GoTo:Function
                {
                    GoToBlock.ParentBlocksReturn = Parent.Depth;
                    GoToBlock.ChildBlocksEnter   = 1;

                    ar    = new Runnable[GoToBlock.ChildBlocksEnter];
                    ar[0] = Compiler.Functions[newTarget.Function].Block.Items[0];
                }
                else
                {
                    if (ancestor != Target)
                    {
                        GoToBlock.ParentBlocksReturn = Parent.Depth - ancestor.Depth;
                        GoToBlock.ChildBlocksEnter   = Target.Depth - ancestor.Depth;
                    }
                    else
                    //GoTo a Parent
                    {
                        GoToBlock.ParentBlocksReturn = Parent.Depth - ancestor.Depth + 1;
                        GoToBlock.ChildBlocksEnter   = 1;
                    }

                    //Get the block indices
                    ar = new Runnable[GoToBlock.ChildBlocksEnter];
                }

                GoToBlock.BlocksEnter = ar;
            }
Пример #3
0
        private void CompileBlock(Parse.Block Item, Block Compiled)
        {
            //Don't try to compile it twice
            if (Compiled.Compiled)
            {
                return;
            }
            _BlocksByParse.Add(Item, Compiled);
            Compiled.Compiled          = true;
            Compiled.ExecuteBlock.Name = Item.Name;

            //Assembly output
            _OutIdent++;
            if (Item.Name != null)
            {
                OutComment("#" + Item.Name + "#");
            }
            else
            {
                OutComment("(unnamed)");
            }

            //Compile elements
            if (Item.Type == Parse.Block.eType.For)
            {
                //Just before the loop increment
                Runnable forContinue = new NOP();
                Compiled.ForContinue = forContinue;
                //When the initializer or loop increment fail succeed
                Runnable onInitIncrFail = new ReturnBlock(1, true);
                //First item of loop's body
                Runnable loopFirst;

                //Keep track the first and last runnables of current element
                int this_exec_begin, this_exec_end;

                this_exec_begin = Compiled.Count;
                //Compile the initializer
                CompileElement(Item.Elements[0], Item, Compiled);
                this_exec_end = Compiled.Count;
                //Set the on fail
                for (int i = this_exec_begin; i < this_exec_end; i++)
                {
                    var it = Compiled.Items[i];
                    if (it.OnFailJumpTo == null)
                    {
                        it.OnFailJumpTo = onInitIncrFail;
                    }
                }

                this_exec_begin = Compiled.Count;
                //Compile the loop body
                CompileElement(Item.Elements[2], Item, Compiled);
                loopFirst = Compiled.Items[this_exec_begin];

                this_exec_begin = Compiled.Count;
                //Compile the loop increment
                Compiled.AddItem(forContinue);
                CompileElement(Item.Elements[1], Item, Compiled);
                this_exec_end = Compiled.Count;
                //Set the on fail
                for (int i = this_exec_begin; i < this_exec_end; i++)
                {
                    var it = Compiled.Items[i];
                    if (it.OnFailJumpTo == null)
                    {
                        it.OnFailJumpTo = onInitIncrFail;
                    }
                }

                //Put the continue command
                var cont = new GoToBlock(0, 1, new[] { loopFirst });
                Compiled.AddItem(cont);

                //Put the on fail
                Compiled.AddItem(onInitIncrFail);
            }
            else
            {
                //Keep track the first and last runnables of current and previous element
                int      this_exec_begin, this_exec_end;
                int      prev_exec_begin = 0, prev_exec_end = 0;
                Runnable this_exec_first;
                for (int i = 0; i < Item.Elements.Count; i++)
                {
                    this_exec_begin = Compiled.Count;
                    //Compile the element
                    CompileElement(Item.Elements[i], Item, Compiled);
                    this_exec_end = Compiled.Count;

                    //Put jumps if it is multi (except on the last part)
                    if ((Item.Type == Parse.Block.eType.Multi))
                    {
                        //Succeed
                        if (i != (Item.Elements.Count - 1))
                        {
                            Compiled.AddItem(new ReturnBlock(1, true));
                        }
                        this_exec_first = Compiled.Items[this_exec_begin];
                        //Update elements to jump to next on fail
                        if (i != 0)
                        {
                            for (int j = prev_exec_begin; j < prev_exec_end; j++)
                            {
                                if (Compiled.Items[j].OnFailJumpTo == null)
                                {
                                    Compiled.Items[j].OnFailJumpTo = this_exec_first;
                                }
                            }
                        }
                    }
                    prev_exec_begin = this_exec_begin;
                    prev_exec_end   = this_exec_end;
                }
            }

            //Move elements to Execute.Block
            Compiled.Done();

            _OutIdent--;
        }
            public GoToBackPatchInfo(Parse.Block newTarget, Parse.Block Parent, GoToBlock newGoToBlock, Compiler Compiler)
            {
                Target = newTarget;
                GoToBlock = newGoToBlock;

                //Find the common ancestor
                var ancestor = Target.FindCommonAncestor(Parent);

                Runnable[] ar;
                if (Target.Parent == null)
                //GoTo:Function
                {
                    GoToBlock.ParentBlocksReturn = Parent.Depth;
                    GoToBlock.ChildBlocksEnter = 1;

                    ar = new Runnable[GoToBlock.ChildBlocksEnter];
                    ar[0] = Compiler.Functions[newTarget.Function].Block.Items[0];
                }
                else
                {
                    if (ancestor != Target)
                    {
                        GoToBlock.ParentBlocksReturn = Parent.Depth - ancestor.Depth;
                        GoToBlock.ChildBlocksEnter = Target.Depth - ancestor.Depth;
                    }
                    else
                    //GoTo a Parent
                    {

                        GoToBlock.ParentBlocksReturn = Parent.Depth - ancestor.Depth + 1;
                        GoToBlock.ChildBlocksEnter = 1;
                    }

                    //Get the block indices
                    ar = new Runnable[GoToBlock.ChildBlocksEnter];
                }

                GoToBlock.BlocksEnter = ar;
            }
        private void CompileBlock(Parse.Block Item, Block Compiled)
        {
            //Don't try to compile it twice
            if (Compiled.Compiled)
                return;
            _BlocksByParse.Add(Item, Compiled);
            Compiled.Compiled = true;
            Compiled.ExecuteBlock.Name = Item.Name;

            //Assembly output
            _OutIdent++;
            if (Item.Name != null)
                OutComment("#" + Item.Name + "#");
            else
                OutComment("(unnamed)");

            //Compile elements
            if (Item.Type == Parse.Block.eType.For)
            {
                //Just before the loop increment
                Runnable forContinue = new NOP();
                Compiled.ForContinue = forContinue;
                //When the initializer or loop increment fail succeed
                Runnable onInitIncrFail = new ReturnBlock(1, true);
                //First item of loop's body
                Runnable loopFirst;

                //Keep track the first and last runnables of current element
                int this_exec_begin, this_exec_end;

                this_exec_begin = Compiled.Count;
                //Compile the initializer
                CompileElement(Item.Elements[0], Item, Compiled);
                this_exec_end = Compiled.Count;
                //Set the on fail
                for (int i = this_exec_begin; i < this_exec_end; i++)
                {
                    var it = Compiled.Items[i];
                    if (it.OnFailJumpTo == null)
                        it.OnFailJumpTo = onInitIncrFail;
                }

                this_exec_begin = Compiled.Count;
                //Compile the loop body
                CompileElement(Item.Elements[2], Item, Compiled);
                loopFirst = Compiled.Items[this_exec_begin];

                this_exec_begin = Compiled.Count;
                //Compile the loop increment
                Compiled.AddItem(forContinue);
                CompileElement(Item.Elements[1], Item, Compiled);
                this_exec_end = Compiled.Count;
                //Set the on fail
                for (int i = this_exec_begin; i < this_exec_end; i++)
                {
                    var it = Compiled.Items[i];
                    if (it.OnFailJumpTo == null)
                        it.OnFailJumpTo = onInitIncrFail;
                }

                //Put the continue command
                var cont = new GoToBlock(0, 1, new[]{loopFirst});
                Compiled.AddItem(cont);

                //Put the on fail
                Compiled.AddItem(onInitIncrFail);
            }
            else
            {
                //Keep track the first and last runnables of current and previous element
                int this_exec_begin, this_exec_end;
                int prev_exec_begin = 0, prev_exec_end = 0;
                Runnable this_exec_first;
                for (int i = 0; i < Item.Elements.Count; i++)
                {
                    this_exec_begin = Compiled.Count;
                    //Compile the element
                    CompileElement(Item.Elements[i], Item, Compiled);
                    this_exec_end = Compiled.Count;

                    //Put jumps if it is multi (except on the last part)
                    if ((Item.Type == Parse.Block.eType.Multi))
                    {
                        //Succeed
                        if (i != (Item.Elements.Count - 1))
                            Compiled.AddItem(new ReturnBlock(1, true));
                        this_exec_first = Compiled.Items[this_exec_begin];
                        //Update elements to jump to next on fail
                        if (i != 0)
                            for (int j = prev_exec_begin; j < prev_exec_end; j++)
                                if (Compiled.Items[j].OnFailJumpTo == null)
                                    Compiled.Items[j].OnFailJumpTo = this_exec_first;
                    }
                    prev_exec_begin = this_exec_begin;
                    prev_exec_end = this_exec_end;
                }
            }

            //Move elements to Execute.Block
            Compiled.Done();

            _OutIdent--;
        }
 private void CEControlFlow(Parse.ControlFlow Item, Parse.Block Parent, Block Compiled)
 {
     switch (Item.Type)
     {
     case Parse.ControlFlow.eType.Call:
         //A call to a block
         CompileElement(Item.Target, Parent, Compiled);
         break;
     case Parse.ControlFlow.eType.Fail:
         //Return a number of blocks
         Compiled.AddItem(new ReturnBlock(Parent.Depth - Item.Target.Depth + (Item.Target.Type == Parse.Block.eType.Multi ? 0 : 1), false));
         break;
     case Parse.ControlFlow.eType.Succeed:
         //Return a number of blocks
         Compiled.AddItem(new ReturnBlock(Parent.Depth - Item.Target.Depth + 1, true));
         break;
     case Parse.ControlFlow.eType.GoTo:
         //GoTo block - if the common parent is the target then return it and run it again
         var gtb = new GoToBlock(0, 0, null);
         gtb.TargetName = Item.Target.Name;
         //We will add the elements index after the compilation - we might not know a block's index (it is not compiled yet)
         _GoToBackPatches.Add(new GoToBackPatchInfo(Item.Target, Parent, gtb, this));
         Compiled.AddItem(gtb);
         break;
     case Parse.ControlFlow.eType.Continue:
         //GoTo block
         var cont = new GoToBlock(Parent.Depth - Item.Target.Depth, 1, new []{_BlocksByParse[Item.Target].ForContinue});
         cont.TargetName = Item.Target.Name;
         Compiled.AddItem(cont);
         break;
     default:
         ThrowParseError("Unknown type", Item.Annotation.SourcePosition);
         break;
     }
 }