コード例 #1
0
ファイル: Foreach.cs プロジェクト: jeffpanici75/FastTemplate
        protected override void OnGenerate()
        {
            var var = (CommonTree) T.Children[0];
            if (var.Type == 0)
            {
                Errors.ErrorParse((CommonErrorNode) var);
                return;
            }
            var exp = (CommonTree) T.Children[1];
            if (exp.Type == 0)
            {
                Errors.ErrorParse((CommonErrorNode) exp);
                return;
            }

            var defaultBlock = (CommonTree) T.Children[2];
            var blocks = new Dictionary<LoopDirective, CommonTree>();
            for (var i = 3; i < T.Children.Count; i++)
            {
                var targeted = (CommonTree) T.Children[i];
                var ins = targeted.Children[0];
                var tBlock = (CommonTree) targeted.Children[1];
                LoopDirective d;
                if (!Enum.TryParse(ins.Text, true, out d))
                {
                    Errors.ErrorUnknownLoopDirective(ins.Text);
                    continue;
                }
                blocks[d] = tBlock;
            }
            if (Errors.ContainsError())
                return;

            var endOfLoop = Ctx.Sink.DefineLabel();
            var continuePoint = Ctx.Sink.DefineLabel();
            var top = Ctx.Sink.DefineLabel();
            var endOfBlock = Ctx.Sink.DefineLabel();
            var oddEvenVar = Ctx.Sink.DeclareLocal(typeof (int));

            var iter = Ctx.Sink.DeclareLocal(typeof (IEnumerator));
            var current = Ctx.Sink.DeclareLocal(typeof (ITemplateType));

            Ctx.PushNewJumpScope(continuePoint, endOfLoop);
            try
            {
                //init part here
                var enumerableExp = new Expression(exp);
                Errors.AddRange(enumerableExp.Generate(Ctx));
                Ctx.Sink.FastEmitStoreLocal(current.LocalIndex);

                Ctx.Sink.Emit(OpCodes.Ldarg_0);
                Ctx.Sink.FastEmitLoadLocal(current.LocalIndex);
                Ctx.EmitVTFunctionCall("CheckIsEnumerable");
                Ctx.Sink.Emit(OpCodes.Brfalse, endOfBlock);

                Ctx.Sink.Emit(OpCodes.Ldarg_0);
                Ctx.Sink.FastEmitLoadLocal(current.LocalIndex);
                Ctx.EmitVTFunctionCall("PrimeIter");
                Ctx.Sink.FastEmitStoreLocal(iter.LocalIndex);

                Ctx.Sink.FastEmitConstInt(0);
                Ctx.Sink.FastEmitStoreLocal(oddEvenVar.LocalIndex);

                var noDataSkip = Ctx.Sink.DefineLabel();
                Ctx.Sink.FastEmitLoadLocal(iter.LocalIndex);
                Ctx.EmitIterMoveNext();
                Ctx.Sink.Emit(OpCodes.Brfalse, noDataSkip);

                var skipStart = Ctx.Sink.DefineLabel();

                Ctx.Sink.Emit(OpCodes.Ldarg_0);
                Ctx.Sink.FastEmitLoadLocal(iter.LocalIndex);
                Ctx.EmitVTFunctionCall("CurrentToTType");
                Ctx.Sink.FastEmitStoreLocal(current.LocalIndex);
                var s = new Statement(var);
                Errors.AddRange(s.GenerateSet(Ctx, current.LocalIndex));

                TryEmitBlock(LoopDirective.BeforeAll, blocks);
                Ctx.Sink.Emit(OpCodes.Br, skipStart);

                Ctx.Sink.MarkLabel(top);
                Ctx.Sink.Emit(OpCodes.Nop);

                Ctx.Sink.Emit(OpCodes.Ldarg_0);
                Ctx.Sink.FastEmitLoadLocal(iter.LocalIndex);
                Ctx.EmitVTFunctionCall("CurrentToTType");
                Ctx.Sink.FastEmitStoreLocal(current.LocalIndex);
                s = new Statement(var);
                s.GenerateSet(Ctx, current.LocalIndex);

                Ctx.Sink.MarkLabel(skipStart);
                Ctx.Sink.Emit(OpCodes.Nop);

                if (blocks.ContainsKey(LoopDirective.Between))
                {
                    var skipFirstBetween = Ctx.Sink.DefineLabel();
                    Ctx.Sink.FastEmitLoadLocal(oddEvenVar.LocalIndex);
                    Ctx.Sink.FastEmitConstInt(0);
                    Ctx.Sink.Emit(OpCodes.Ceq);
                    Ctx.Sink.Emit(OpCodes.Brtrue, skipFirstBetween);
                    TryEmitBlock(LoopDirective.Between, blocks);
                    Ctx.Sink.MarkLabel(skipFirstBetween);
                }

                TryEmitBlock(LoopDirective.Before, blocks);

                //even odd
                if (blocks.ContainsKey(LoopDirective.Even)
                    || blocks.ContainsKey(LoopDirective.Odd))
                {
                    var oddBlock = Ctx.Sink.DefineLabel();
                    var endOddEvenBlock = Ctx.Sink.DefineLabel();

                    Ctx.Sink.FastEmitLoadLocal(oddEvenVar.LocalIndex);
                    Ctx.Sink.FastEmitConstInt(2);
                    Ctx.Sink.Emit(OpCodes.Rem);
                    Ctx.Sink.FastEmitConstInt(0);
                    Ctx.Sink.Emit(OpCodes.Ceq);
                    Ctx.Sink.Emit(OpCodes.Brfalse, oddBlock);

                    TryEmitBlock(LoopDirective.Even, blocks);
                    Ctx.Sink.Emit(OpCodes.Br, endOddEvenBlock);

                    Ctx.Sink.MarkLabel(oddBlock);
                    TryEmitBlock(LoopDirective.Odd, blocks);
                    Ctx.Sink.MarkLabel(endOddEvenBlock);
                }

                var defaultBlk = new Block(defaultBlock.Children[0]);
                Errors.AddRange(defaultBlk.Generate(Ctx));

                TryEmitBlock(LoopDirective.Each, blocks);

                TryEmitBlock(LoopDirective.After, blocks);

                Ctx.Sink.MarkLabel(continuePoint);

                //increment odd even var
                Ctx.Sink.Emit(OpCodes.Ldc_I4_1);
                Ctx.Sink.FastEmitLoadLocal(oddEvenVar.LocalIndex);
                Ctx.Sink.Emit(OpCodes.Add);
                Ctx.Sink.FastEmitStoreLocal(oddEvenVar.LocalIndex);

                //increment
                //check condidtion
                Ctx.Sink.FastEmitLoadLocal(iter.LocalIndex);
                Ctx.EmitIterMoveNext();
                Ctx.Sink.Emit(OpCodes.Brtrue, top);

                Ctx.Sink.MarkLabel(endOfLoop);

                TryEmitBlock(LoopDirective.AfterAll, blocks);

                Ctx.Sink.Emit(OpCodes.Br, endOfBlock);

                Ctx.Sink.MarkLabel(noDataSkip);
                TryEmitBlock(LoopDirective.NoData, blocks);
                Ctx.Sink.MarkLabel(endOfBlock);
            }
            finally
            {
                Ctx.PopJumpScope();
            }
        }
コード例 #2
0
ファイル: Control.cs プロジェクト: jeffpanici75/FastTemplate
 protected override void OnGenerate()
 {
     Errors.Clear();
     var child = (CommonTree) T.Children[0];
     switch (child.Type)
     {
         case 0:
         {
             Ctx.EmitNullRef();
             Errors.ErrorParse((CommonErrorNode) child);
             break;
         }
         case TemplateLexer.Pragma:
         {
             var a = new Pragma(child);
             Errors.AddRange(a.Generate(Ctx));
             break;
         }
         case TemplateLexer.Assert:
         {
             Ctx.Sink.Emit(OpCodes.Ldarg_0);
             var a = new Assert(child);
             Errors.AddRange(a.Generate(Ctx));
             Ctx.EmitAppendToBuffer();
             break;
         }
         case TemplateLexer.Continue:
         {
             if (!Ctx.InJumpableBlock)
             {
                 Errors.ErrorInvalidJump("continue", child.Token);
                 break;
             }
             Ctx.Sink.Emit(OpCodes.Br, Ctx.GetContinueLabel());
             break;
         }
         case TemplateLexer.Break:
         {
             if (!Ctx.InJumpableBlock)
             {
                 Errors.ErrorInvalidJump("break", child.Token);
                 break;
             }
             Ctx.Sink.Emit(OpCodes.Br, Ctx.GetBreakLabel());
             break;
         }
         case TemplateLexer.Stop:
         {
             Ctx.Sink.Emit(OpCodes.Br, Ctx.EndOfTemplate);
             break;
         }
         case TemplateLexer.Parse:
         {
             var args = (CommonTree) child.Children[0];
             if (args.Type == 0)
             {
                 Errors.ErrorParse((CommonErrorNode) args);
                 break;
             }
             Ctx.Sink.Emit(OpCodes.Ldarg_0);
             Ctx.EmitArgList(args);
             Ctx.EmitVTFunctionCall("InvokeParse");
             break;
         }
         case TemplateLexer.Include:
         {
             var args = (CommonTree) child.Children[0];
             if (args.Type == 0)
             {
                 Errors.ErrorParse((CommonErrorNode) args);
                 break;
             }
             Ctx.Sink.Emit(OpCodes.Ldarg_0);
             Ctx.EmitArgList(args);
             Ctx.EmitVTFunctionCall("InvokeInclude");
             break;
         }
         case TemplateLexer.Set:
         {
             var target = child.Children[0];
             if (target.Type == 0)
             {
                 Errors.ErrorParse((CommonErrorNode) target);
                 break;
             }
             var source = child.Children[1];
             if (source.Type == 0)
             {
                 Errors.ErrorParse((CommonErrorNode) source);
                 break;
             }
             var s = new Statement(target);
             var exp = new Expression(source);
             Errors.AddRange(s.GenerateSet(Ctx, exp));
             break;
         }
         case TemplateLexer.If:
         {
             var ifControl = new If(child);
             Errors.AddRange(ifControl.Generate(Ctx));
             break;
         }
         case TemplateLexer.Loop:
         {
             var loop = new Loop(child);
             Errors.AddRange(loop.Generate(Ctx));
             break;
         }
         case TemplateLexer.Foreach:
         {
             var loop = new Foreach(child);
             Errors.AddRange(loop.Generate(Ctx));
             break;
         }
     }
 }