private void LdTid(EmitSyntax emit, CilSymbolRef tid)
        {
            if (tid.Type != null)
            {
                emit
                .Ldtoken(emit.Types.Import(tid.Type))
                .Call((RuntimeTypeHandle h) => Type.GetTypeFromHandle(h))
                ;
            }
            else
            {
                emit.Ldnull();
            }

            if (tid.Literal == null)
            {
                emit.Ldnull();
            }
            else
            {
                emit.Ldstr(new QStr(tid.Literal));
            }

            emit
            .Newobj(() => new CilSymbolRef(default(Type), default(string)));
        }
예제 #2
0
 public IActionCode SkipAction()
 {
     emit
     .Ldnull()
     .Br(RETURN);
     return(this);
 }
예제 #3
0
 private static EmitSyntax LdMethodDelegate(
     this EmitSyntax emit,
     Pipe <IMethodNs, DoneMethodSig> methodSig,
     Type delegateType)
 {
     return(emit
            .Ldnull()
            .Ldftn(emit.Methods.Method(methodSig))
            .NewDelegate(delegateType));
 }
예제 #4
0
        private EmitSyntax EmitFactoryCode(
            EmitSyntax emit,
            PlannedClass contextPlannedClass,
            Type type,
            bool nullAllowed)
        {
            if (type == typeof(void))
            {
            }
            else if (type == typeof(int))
            {
                emit = emit.Ldc_I4_0();
            }
            else if (type.IsValueType)
            {
                var resultType = emit.Types.Import(type);
                var resultLoc  = emit.Locals.Generate("result");

                emit = emit
                       .Local(resultLoc, resultType)
                       .Ldloca(resultLoc.GetRef())
                       .Initobj(resultType)
                       .Ldloc(resultLoc.GetRef())
                ;
            }
            else if (nullAllowed)
            {
                emit.Ldnull();
            }
            else if (!type.IsAbstract && !type.IsInterface)
            {
                emit = emit.Newobj(
                    emit.Types.Import(type));
            }
            else if (contextPlannedClass != null && contextPlannedClass.Implements(type))
            {
                emit = emit.Ldarg(0);
            }
            else if (plan.Exists(e => e.Implements(type)))
            {
                var otherEntry = plan.Find(e => e.Implements(type));
                emit = emit.Newobj(
                    emit.Types.Class_(
                        ClassName.Parse(
                            otherEntry.ClassName)));
            }
            else
            {
                throw new InvalidOperationException(
                          "Internal error: non-planned abstract result type");
            }

            return(emit);
        }
        public void Build(
            EmitSyntax emit,
            Pipe <EmitSyntax> ldCursor,
            Pipe <EmitSyntax> ldTokenPtr)
        {
            var labels = emit.Labels;
            var locals = emit.Locals;

            var RETURN = labels.Generate();

            var valueTmp = locals.Generate();
            var tokenId  = locals.Generate();

            emit
            .Local(valueTmp, emit.Types.Object)
            .Ldnull()
            .Stloc(valueTmp.GetRef())

            .Local(tokenId, emit.Types.Int32)
            .Ldc_I4(-1)
            .Stloc(tokenId.GetRef())
            ;

            int ruleCount = data.Grammar.Conditions.Sum(cond => cond.Matchers.Count);

            var action = new Ref <Labels> [ruleCount];

            for (int i = 0; i != ruleCount; ++i)
            {
                action[i] = labels.Generate().GetRef();
            }

            emit
            .Do(ldCursor)
            .Ldfld((ScanCursor c) => c.CurrentActionId)
            .Switch(action)
            ;

            foreach (var cond in data.Grammar.Conditions)
            {
                var contextResolver = new ContextCode(
                    emit,
                    il => il
                    .Do(ldCursor)
                    .Ldfld((ScanCursor c) => c.RootContext),
                    null,
                    data,
                    cond.ContextProvider);
                IActionCode code = new MatcherCode(
                    emit,
                    contextResolver,
                    ldCursor,
                    declaringType,
                    data.Grammar.Conditions,
                    RETURN.GetRef());

                foreach (var matcher in cond.Matchers)
                {
                    emit
                    .Label(action[matcher.Index].Def)
                    .Ldc_I4(matcher.Outcome == null ? -1 : matcher.Outcome.Index)
                    .Stloc(tokenId.GetRef())
                    ;

                    var productionBinding = matcher.Joint.The <CilMatcher>();
                    code = code
                           .Do(productionBinding.Context.Load)
                           .Do(productionBinding.ActionBuilder);
                }
            }

            // Load null value for incorrectly implemented actions
            emit.Ldnull();

            emit
            .Label(RETURN)

            .Stloc(valueTmp.GetRef())
            .Do(ldTokenPtr)
            .Ldloc(valueTmp.GetRef())
            .Stind_Ref()

            .Ldloc(tokenId.GetRef())
            .Ret()
            ;
        }
예제 #6
0
        public void BuildBody(
            EmitSyntax emit,
            LanguageData data,
            Ref <Args> ruleId,
            Ref <Args> ruleArgs,
            Ref <Args> argsStart,
            Ref <Args> ctx,
            Ref <Args> lookbackStart)
        {
            Def <Labels> returnLabel = emit.Labels.Generate();

            var contextCode = new ContextCode(
                emit,
                il => il.Ldarg(ctx),
                il => il.Ldarg(lookbackStart),
                data,
                data.Grammar.GlobalContextProvider,
                data.LocalParseContexts);

            IActionCode code = new ProductionCode(
                emit,
                contextCode,
                ldRuleArgs:  il => il.Ldarg(ruleArgs),
                ldArgsStart: il => il.Ldarg(argsStart),
                returnLabel: returnLabel);

            var defaultLabel             = emit.Labels.Generate();
            var endWithSingleResultLabel = emit.Labels.Generate();
            var jumpTable = new Ref <Labels> [data.Grammar.Productions.Count];

            for (int i = 0; i != jumpTable.Length; ++i)
            {
                jumpTable[i] = emit.Labels.Generate().GetRef();
            }

            emit
            .Do(il => il.Ldarg(ruleId))
            .Switch(jumpTable)
            .Br(defaultLabel.GetRef());

            foreach (var prod in data.Grammar.Productions)
            {
                emit.Label(jumpTable[prod.Index].Def);

                if (0 == prod.Actions.Count)
                {
                    // Augumented start rule has null action and should never be invoked.
                    // Also it is possible that for some platforms production may have default
                    // action.
                    emit.Ldnull();
                }
                else
                {
                    foreach (var action in prod.Actions)
                    {
                        code = GenerateActionCode(code, action);
                    }
                }

                emit.Br(endWithSingleResultLabel.GetRef());
            }

            emit
            .Label(defaultLabel)
            .Ldnull()
            .Label(endWithSingleResultLabel)
            .Label(returnLabel)
            .Ret();
        }
        public void BuildBody(
            EmitSyntax emit, 
            LanguageData data,
            Ref<Args> ruleId,
            Ref<Args> ruleArgs,
            Ref<Args> argsStart,
            Ref<Args> ctx,
            Ref<Args> lookbackStart)
        {
            Def<Labels> returnLabel = emit.Labels.Generate();

            var contextCode = new ContextCode(
                emit,
                il => il.Ldarg(ctx),
                il => il.Ldarg(lookbackStart),
                data,
                data.Grammar.GlobalContextProvider,
                data.LocalParseContexts);

            IActionCode code = new ProductionCode(
                emit,
                contextCode,
                ldRuleArgs:  il => il.Ldarg(ruleArgs),
                ldArgsStart: il => il.Ldarg(argsStart),
                returnLabel: returnLabel);

            var defaultLabel = emit.Labels.Generate();
            var endWithSingleResultLabel = emit.Labels.Generate();
            var jumpTable = new Ref<Labels>[data.Grammar.Productions.Count];
            for (int i = 0; i != jumpTable.Length; ++i)
            {
                jumpTable[i] = emit.Labels.Generate().GetRef();
            }

            emit
                .Do(il => il.Ldarg(ruleId))
                .Switch(jumpTable)
                .Br(defaultLabel.GetRef());

            foreach (var prod in data.Grammar.Productions)
            {
                emit.Label(jumpTable[prod.Index].Def);

                if (0 == prod.Actions.Count)
                {
                    // Augumented start rule has null action and should never be invoked.
                    // Also it is possible that for some platforms production may have default
                    // action.
                    emit.Ldnull();
                }
                else
                {
                    foreach (var action in prod.Actions)
                    {
                        code = GenerateActionCode(code, action);
                    }
                }

                emit.Br(endWithSingleResultLabel.GetRef());
            }

            emit
                .Label(defaultLabel)
                .Ldnull()
                .Label(endWithSingleResultLabel)
                .Label(returnLabel)
                .Ret();
        }
        public void Build(
            EmitSyntax          emit,
            Pipe<EmitSyntax>    ldCursor,
            Pipe<EmitSyntax>    ldTokenPtr)
        {
            var labels = emit.Labels;
            var locals = emit.Locals;

            var RETURN = labels.Generate();

            var valueTmp = locals.Generate();
            var tokenId  = locals.Generate();

            emit
                .Local(valueTmp, emit.Types.Object)
                .Ldnull()
                .Stloc(valueTmp.GetRef())

                .Local(tokenId, emit.Types.Int32)
                .Ldc_I4(-1)
                .Stloc(tokenId.GetRef())
                ;

            int ruleCount = data.Grammar.Conditions.Sum(cond => cond.Matchers.Count);

            var action = new Ref<Labels>[ruleCount];
            for (int i = 0; i != ruleCount; ++i)
            {
                action[i] = labels.Generate().GetRef();
            }

            emit
                .Do(ldCursor)
                .Ldfld((ScanCursor c) => c.CurrentActionId)
                .Switch(action)
                ;

            foreach (var cond in data.Grammar.Conditions)
            {
                var contextResolver = new ContextCode(
                                        emit,
                                        il => il
                                            .Do(ldCursor)
                                            .Ldfld((ScanCursor c) => c.RootContext),
                                        null,
                                        data,
                                        cond.ContextProvider);
                IActionCode code = new MatcherCode(
                                emit,
                                contextResolver,
                                ldCursor,
                                declaringType,
                                data.Grammar.Conditions,
                                RETURN.GetRef());

                foreach (var matcher in cond.Matchers)
                {
                    emit
                        .Label(action[matcher.Index].Def)
                        .Ldc_I4(matcher.Outcome == null ? -1 : matcher.Outcome.Index)
                        .Stloc(tokenId.GetRef())
                        ;

                    var productionBinding = matcher.Joint.The<CilMatcher>();
                    code = code
                        .Do(productionBinding.Context.Load)
                        .Do(productionBinding.ActionBuilder);
                }
            }

            // Load null value for incorrectly implemented actions
            emit.Ldnull();

            emit
                .Label(RETURN)

                .Stloc(valueTmp.GetRef())
                .Do(ldTokenPtr)
                .Ldloc(valueTmp.GetRef())
                .Stind_Ref()

                .Ldloc(tokenId.GetRef())
                .Ret()
                ;
        }
        private EmitSyntax EmitFactoryCode(
            EmitSyntax   emit,
            PlannedClass contextPlannedClass,
            Type         type,
            bool         nullAllowed)
        {
            if (type == typeof(void))
            {
            }
            else if (type == typeof(int))
            {
                emit = emit.Ldc_I4_0();
            }
            else if (type.IsValueType)
            {
                var resultType = emit.Types.Import(type);
                var resultLoc = emit.Locals.Generate("result");

                emit = emit
                    .Local(resultLoc, resultType)
                    .Ldloca(resultLoc.GetRef())
                    .Initobj(resultType)
                    .Ldloc(resultLoc.GetRef())
                    ;
            }
            else if (nullAllowed)
            {
                emit.Ldnull();
            }
            else if (!type.IsAbstract && !type.IsInterface)
            {
                emit = emit.Newobj(
                         emit.Types.Import(type));
            }
            else if (contextPlannedClass != null && contextPlannedClass.Implements(type))
            {
                emit = emit.Ldarg(0);
            }
            else if (plan.Exists(e => e.Implements(type)))
            {
                var otherEntry = plan.Find(e => e.Implements(type));
                emit = emit.Newobj(
                         emit.Types.Class_(
                            ClassName.Parse(
                                otherEntry.ClassName)));
            }
            else
            {
                throw new InvalidOperationException(
                    "Internal error: non-planned abstract result type");
            }

            return emit;
        }
        private void LdTid(EmitSyntax emit, CilSymbolRef tid)
        {
            if (tid.Type != null)
            {
                emit
                    .Ldtoken(emit.Types.Import(tid.Type))
                    .Call((RuntimeTypeHandle h) => Type.GetTypeFromHandle(h))
                    ;
            }
            else
            {
                emit.Ldnull();
            }

            if (tid.Literal == null)
            {
                emit.Ldnull();
            }
            else
            {
                emit.Ldstr(new QStr(tid.Literal));
            }

            emit
                .Newobj(() => new CilSymbolRef(default(Type), default(string)));
        }