Beispiel #1
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);
        }
Beispiel #2
0
        private EmitSyntax BuildNodeInvocation(ref int startArgIndex, EmitSyntax emit, Ref <Args>[] args, SppfNode node)
        {
            if (node.IsTerminal)
            {
                return(emit.Ldarg(args[startArgIndex++]));
            }

            int count = node.Children.Length;

            for (int i = 0; i != count; ++i)
            {
                emit = BuildNodeInvocation(ref startArgIndex, emit, args, node.Children[i]);
            }

            return(emit);
        }
Beispiel #3
0
        public void Build(EmitSyntax emit)
        {
            // Debug.WriteLine("DFA for " + descriptor.Name + ":");
            // Debug.WriteLine(dfa);
            int failState = dfa.StateCount;

            var locals = emit.Locals;
            var labels = emit.Labels;

            var FIN     = labels.Generate();
            var current = locals.Generate("ch");

            var Lgoto = new Ref <Labels> [dfa.StateCount + 1]; // label for incrementing ch position
            var Mgoto = new Ref <Labels> [dfa.StateCount];     // assing ch using current position
            var Tgoto = new Ref <Labels> [dfa.StateCount];     // transition dispatching switch-code

            for (int i = 0; i != dfa.StateCount; ++i)
            {
                Lgoto[i] = labels.Generate().GetRef();
                Mgoto[i] = labels.Generate().GetRef();
                Tgoto[i] = labels.Generate().GetRef();
            }

            Lgoto[failState] = FIN.GetRef();

            emit
            .Local(current, emit.Types.Char)
            .Ldarg(0).Ldfld((ScanCursor c) => c.InnerState)
            .Switch(Mgoto)
            .Br(Lgoto[0])
            ;

            foreach (var S in dfa.EnumerateStates())
            {
                int state = S.Index;

                emit
                .Label(Lgoto[state].Def);

                if (state != dfa.Start)
                {
                    // ++Cursor
                    emit
                    .Ldarg(0)     // for Stfld
                    .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor)
                    .Ldc_I4_1()
                    .Add()
                    .Stfld((ScanCursor c) => c.Cursor)
                    ;
                }

                // If state is accepring then remember position
                // in Marker and save corresponding ActionId.
                if (S.IsAccepting)
                {
                    int actionCount = 0;
                    foreach (var action in S.Actions)
                    {
                        emit
                        .Ldarg(0)
                        .Ldfld((ScanCursor c) => c.Actions)
                        .Ldc_I4(actionCount++)
                        .Ldc_I4(action)
                        .Stelem_I4()
                        ;
                    }

                    emit
                    .Ldarg(0)
                    .Ldc_I4(actionCount)
                    .Stfld((ScanCursor c) => c.ActionCount)
                    ;

                    emit
                    .Ldarg(0)
                    .Ldc_I4(S.EnvelopeId)
                    .Stfld((ScanCursor c) => c.EnvelopeId)
                    ;

                    emit
                    .Ldarg(0)
                    .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor)
                    .Stfld((ScanCursor c) => c.Marker);

                    // Save line/column information

                    emit
                    // cursor.MarkerLine = cursor.CursorLine;
                    .Ldarg(0)
                    .Ldarg(0)
                    .Ldfld((ScanCursor c) => c.CursorLine)
                    .Stfld((ScanCursor c) => c.MarkerLine)
                    // cursor.MarkerLineStart = cursor.CursorLineStart;
                    .Ldarg(0)
                    .Ldarg(0)
                    .Ldfld((ScanCursor c) => c.CursorLineStart)
                    .Stfld((ScanCursor c) => c.MarkerLineStart)
                    ;
                }

                if (S.IsNewline)
                {
                    emit
                    // ++cursor.CursorLine;
                    .Ldarg(0)
                    .Ldarg(0)
                    .Ldfld((ScanCursor c) => c.CursorLine)
                    .Ldc_I4_1()
                    .Add()
                    .Stfld((ScanCursor c) => c.CursorLine)
                    // cursor.CursorLineStart = cursor.Cursor;
                    .Ldarg(0)
                    .Ldarg(0)
                    .Ldfld((ScanCursor c) => c.Cursor)
                    .Stfld((ScanCursor c) => c.CursorLineStart)
                    ;
                }

                emit
                .Label(Mgoto[state].Def)
                // Get current input symbol
                .Ldarg(0).Ldfld((ScanCursor c) => c.Buffer)
                .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor)
                .Ldelem_U2()
                .Stloc(current.GetRef())
                // Label for tunneling
                .Label(Tgoto[state].Def)
                ;

                if (S.IsFinal && state != 0)
                {
                    emit
                    .Br(FIN.GetRef());
                    continue;
                }

                int checkSentinelState = failState + 1;

                var stateRealTransitions = dfa.EnumerateRealTransitions(S).ToList();


                // Find custom sentinel transtion
                int customSentinelToState         = -1;
                var customSentinelTransitionIndex =
                    stateRealTransitions.FindIndex(pair => pair.Key.Contains(Sentinel));
                if (customSentinelTransitionIndex >= 0)
                {
                    customSentinelToState = stateRealTransitions[customSentinelTransitionIndex].Value;
                }

                // Sentinel check transiiton
                var sentinelTransition = new IntArrow <int>(Sentinel, checkSentinelState);
                stateRealTransitions.Insert(0, sentinelTransition);

                var generator = SwitchGenerator.Sparse(
                    stateRealTransitions.ToArray(),
                    failState,
                    UnicodeIntSetType.UnicodeInterval,
                    frequency: UnicodeFrequency.Default);
                generator.Build(
                    emit,
                    il => il.Ldloc(current.GetRef()),
                    (EmitSyntax il, int value) =>
                {
                    if (value == checkSentinelState)
                    {
                        var handleSentinelCharLabel =
                            (customSentinelToState >= 0)
                                    ? Lgoto[customSentinelToState]
                                    : FIN.GetRef();

                        // return for buffer filling if Cursor == Limit,
                        // otherwise transite on char
                        il
                        .Ldarg(0).Ldfld((ScanCursor c) => c.Limit)
                        .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor)
                        .Bne_Un(handleSentinelCharLabel)

                        // Return for buffer filling
                        .Ldarg(0)
                        .Ldc_I4(state)
                        .Stfld((ScanCursor c) => c.InnerState)
                        .Ldc_I4(1)
                        .Ret()
                        ;
                    }
                    else if (value == failState && S.Tunnel >= 0)
                    {
                        // Tunnel-jump to other state and verify current
                        // input again in that state.
                        il.Br(Tgoto[S.Tunnel]);
                    }
                    else
                    {
                        // Transite to the valid or failed state
                        il.Br(Lgoto[value]);
                    }
                });
            }

            // Return to the last accepted position and report accept stage
            emit
            .Label(FIN)
            .Ldc_I4(0)
            .Ret()
            ;
        }
        public void BuildBody(
            EmitSyntax emit, 
            LanguageData data,
            Ref<Args> tokenId,
            Ref<Args> oldValue,
            Ref<Args> newValue,
            Ref<Args> ctx,
            Ref<Args> lookbackStart)
        {
            var mergers = data.Grammar.Mergers;

            if (mergers.Count == 0)
            {
                emit
                    .Ldarg(oldValue)
                    .Ret();

                return;
            }

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

            IActionCode code = new MergeCode(emit, contextResolverCode)
            {
                LoadOldValue = il => il.Ldarg(oldValue),
                LoadNewValue = il => il.Ldarg(newValue),
            };

            var tokenToRuleIndex = new MutableIntMap<int>(
                                        mergers.Select(
                                            merger =>
                                                new IntArrow<int>(merger.Symbol.Index, merger.Index)));
            tokenToRuleIndex.DefaultValue = -1;

            var ids = mergers.Select(m => m.Symbol.Index);
            IntInterval possibleBounds = new IntInterval(ids.Min(), ids.Max());
            var switchGenerator = SwitchGenerator.Sparse(tokenToRuleIndex, possibleBounds);
            switchGenerator.Build(
                emit,
                il => il.Ldarg(tokenId),
                (il, value) =>
                {
                    if (value < 0)
                    {
                        emit
                            .Ldarg(newValue)
                            .Ret();
                    }
                    else
                    {
                        var merger = mergers[value];
                        var binding = merger.Joint.The<CilMerger>();
                        code = code
                            .Do(binding.Context.Load)
                            .Do(binding.ActionBuilder)
                            .Emit(il2 => il2.Ret())
                            ;
                    }
                });

            emit
                .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;
        }
Beispiel #6
0
        public void BuildBody(
            EmitSyntax emit,
            LanguageData data,
            Ref <Args> tokenId,
            Ref <Args> oldValue,
            Ref <Args> newValue,
            Ref <Args> ctx,
            Ref <Args> lookbackStart)
        {
            var mergers = data.Grammar.Mergers;

            if (mergers.Count == 0)
            {
                emit
                .Ldarg(oldValue)
                .Ret();

                return;
            }

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

            IActionCode code = new MergeCode(emit, contextResolverCode)
            {
                LoadOldValue = il => il.Ldarg(oldValue),
                LoadNewValue = il => il.Ldarg(newValue),
            };

            var tokenToRuleIndex = new MutableIntMap <int>(
                mergers.Select(
                    merger =>
                    new IntArrow <int>(merger.Symbol.Index, merger.Index)));

            tokenToRuleIndex.DefaultValue = -1;

            var         ids             = mergers.Select(m => m.Symbol.Index);
            IntInterval possibleBounds  = new IntInterval(ids.Min(), ids.Max());
            var         switchGenerator = SwitchGenerator.Sparse(tokenToRuleIndex, possibleBounds);

            switchGenerator.Build(
                emit,
                il => il.Ldarg(tokenId),
                (il, value) =>
            {
                if (value < 0)
                {
                    emit
                    .Ldarg(newValue)
                    .Ret();
                }
                else
                {
                    var merger  = mergers[value];
                    var binding = merger.Joint.The <CilMerger>();
                    code        = code
                                  .Do(binding.Context.Load)
                                  .Do(binding.ActionBuilder)
                                  .Emit(il2 => il2.Ret())
                    ;
                }
            });

            emit
            .Ret();
        }
        public void Build(EmitSyntax emit)
        {
            // Debug.WriteLine("DFA for " + descriptor.Name + ":");
            // Debug.WriteLine(dfa);
            int failState  = dfa.StateCount;

            var locals = emit.Locals;
            var labels = emit.Labels;

            var FIN     = labels.Generate();
            var current = locals.Generate("ch");

            var Lgoto = new Ref<Labels>[dfa.StateCount + 1]; // label for incrementing ch position
            var Mgoto = new Ref<Labels>[dfa.StateCount];     // assing ch using current position
            var Tgoto = new Ref<Labels>[dfa.StateCount];     // transition dispatching switch-code

            for (int i = 0; i != dfa.StateCount; ++i)
            {
                Lgoto[i] = labels.Generate().GetRef();
                Mgoto[i] = labels.Generate().GetRef();
                Tgoto[i] = labels.Generate().GetRef();
            }

            Lgoto[failState] = FIN.GetRef();

            emit
                .Local(current, emit.Types.Char)
                .Ldarg(0) .Ldfld((ScanCursor c) => c.InnerState)
                .Switch(Mgoto)
                .Br(Lgoto[0])
                ;

            foreach (var S in dfa.EnumerateStates())
            {
                int state = S.Index;

                emit
                    .Label(Lgoto[state].Def);

                if (state != dfa.Start)
                {
                    // ++Cursor
                    emit
                        .Ldarg(0) // for Stfld
                        .Ldarg(0).Ldfld((ScanCursor c) => c.Cursor)
                        .Ldc_I4_1()
                        .Add()
                        .Stfld((ScanCursor c) => c.Cursor)
                    ;
                }

                // If state is accepring then remember position
                // in Marker and save corresponding ActionId.
                if (S.IsAccepting)
                {
                    int actionCount = 0;
                    foreach (var action in S.Actions)
                    {
                        emit
                            .Ldarg(0)
                            .Ldfld((ScanCursor c) => c.Actions)
                            .Ldc_I4(actionCount++)
                            .Ldc_I4(action)
                            .Stelem_I4()
                            ;
                    }

                    emit
                        .Ldarg(0)
                        .Ldc_I4(actionCount)
                        .Stfld((ScanCursor c) => c.ActionCount)
                        ;

                    emit
                        .Ldarg(0)
                        .Ldc_I4(S.EnvelopeId)
                        .Stfld((ScanCursor c) => c.EnvelopeId)
                        ;

                    emit
                        .Ldarg(0)
                        .Ldarg(0) .Ldfld((ScanCursor c) => c.Cursor)
                        .Stfld((ScanCursor c) => c.Marker);

                    // Save line/column information

                    emit
                        // cursor.MarkerLine = cursor.CursorLine;
                        .Ldarg(0)
                        .Ldarg(0)
                        .Ldfld((ScanCursor c) => c.CursorLine)
                        .Stfld((ScanCursor c) => c.MarkerLine)
                        // cursor.MarkerLineStart = cursor.CursorLineStart;
                        .Ldarg(0)
                        .Ldarg(0)
                        .Ldfld((ScanCursor c) => c.CursorLineStart)
                        .Stfld((ScanCursor c) => c.MarkerLineStart)
                        ;
                }

                if (S.IsNewline)
                {
                    emit
                        // ++cursor.CursorLine;
                        .Ldarg(0)
                        .Ldarg(0)
                        .Ldfld((ScanCursor c) => c.CursorLine)
                        .Ldc_I4_1()
                        .Add()
                        .Stfld((ScanCursor c) => c.CursorLine)
                        // cursor.CursorLineStart = cursor.Cursor;
                        .Ldarg(0)
                        .Ldarg(0)
                        .Ldfld((ScanCursor c) => c.Cursor)
                        .Stfld((ScanCursor c) => c.CursorLineStart)
                        ;
                }

                emit
                    .Label(Mgoto[state].Def)
                // Get current input symbol
                    .Ldarg(0) .Ldfld((ScanCursor c) => c.Buffer)
                    .Ldarg(0) .Ldfld((ScanCursor c) => c.Cursor)
                    .Ldelem_U2()
                    .Stloc(current.GetRef())
                // Label for tunneling
                    .Label(Tgoto[state].Def)
                    ;

                if (S.IsFinal && state != 0)
                {
                    emit
                        .Br(FIN.GetRef());
                    continue;
                }

                int checkSentinelState = failState + 1;

                var stateRealTransitions = dfa.EnumerateRealTransitions(S).ToList();

                // Find custom sentinel transtion
                int customSentinelToState = -1;
                var customSentinelTransitionIndex =
                    stateRealTransitions.FindIndex(pair => pair.Key.Contains(Sentinel));
                if (customSentinelTransitionIndex >= 0)
                {
                    customSentinelToState = stateRealTransitions[customSentinelTransitionIndex].Value;
                }

                // Sentinel check transiiton
                var sentinelTransition = new IntArrow<int>(Sentinel, checkSentinelState);
                stateRealTransitions.Insert(0, sentinelTransition);

                var generator = SwitchGenerator.Sparse(
                                    stateRealTransitions.ToArray(),
                                    failState,
                                    UnicodeIntSetType.UnicodeInterval,
                                    frequency: UnicodeFrequency.Default);
                generator.Build(
                    emit,
                    il => il.Ldloc(current.GetRef()),
                    (EmitSyntax il, int value) =>
                    {
                        if (value == checkSentinelState)
                        {
                            var handleSentinelCharLabel =
                                    (customSentinelToState >= 0)
                                    ? Lgoto[customSentinelToState]
                                    : FIN.GetRef();

                            // return for buffer filling if Cursor == Limit,
                            // otherwise transite on char
                            il
                                .Ldarg(0) .Ldfld((ScanCursor c) => c.Limit)
                                .Ldarg(0) .Ldfld((ScanCursor c) => c.Cursor)
                                .Bne_Un(handleSentinelCharLabel)

                                // Return for buffer filling
                                .Ldarg(0)
                                .Ldc_I4(state)
                                .Stfld((ScanCursor c) => c.InnerState)
                                .Ldc_I4(1)
                                .Ret()
                                ;
                        }
                        else if (value == failState && S.Tunnel >= 0)
                        {
                            // Tunnel-jump to other state and verify current
                            // input again in that state.
                            il.Br(Tgoto[S.Tunnel]);
                        }
                        else
                        {
                            // Transite to the valid or failed state
                            il.Br(Lgoto[value]);
                        }
                    });
            }

            // Return to the last accepted position and report accept stage
            emit
                .Label(FIN)
                .Ldc_I4(0)
                .Ret()
                ;
        }