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; } }
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 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; } }