private static CodeStatement GenerateMainLoop <TDfa, TDfaState>(TDfa dfa,
                                                                        CodeVariableReferenceExpression lexerStateVariable)
            where TDfa : AbstractDfa <TDfaState, char>
            where TDfaState : AbstractDfaState <TDfaState, char>
        {
            var switchGenerator = new SwitchGenerator <TDfa, TDfaState>(dfa, lexerStateVariable);

            return(switchGenerator.MakeStatement());
        }
Example #2
0
        public void GenerateCurrentSwitchOff()
        {
            var context = Substitute.For <ICircuitContext>();

            context.ModelsRegistry.FindModel <CurrentSwitchModel>(Arg.Any <string>()).Returns(new CurrentSwitchModel("WModel"));

            var parameters = new ParameterCollection
            {
                new ValueParameter("1"),
                new ValueParameter("0"),
                new IdentifierParameter("V3"),
                new WordParameter("model"),
                new WordParameter("Off"),
            };

            var generator = new SwitchGenerator();
            var @switch   = generator.Generate("w1", "w1", "w", parameters, context);

            Assert.NotNull(@switch);
            Assert.IsType <CurrentSwitch>(@switch);
            Assert.False(@switch.ParameterSets.Get <SpiceSharp.Components.SwitchBehaviors.BaseParameters>().ZeroState);
        }
Example #3
0
        public void GenerateVoltageSwitch()
        {
            var context = Substitute.For <ICircuitContext>();

            context.ModelsRegistry.FindModel <VoltageSwitchModel>(Arg.Any <string>()).Returns(new VoltageSwitchModel("SModel"));

            var parameters = new ParameterCollection
            {
                new ValueParameter("1"),
                new ValueParameter("0"),
                new ValueParameter("2"),
                new ValueParameter("0"),
                new WordParameter("model"),
                new WordParameter("On"),
            };

            var generator = new SwitchGenerator();
            var @switch   = generator.Generate("s1", "s1", "s", parameters, context);

            Assert.NotNull(@switch);
            Assert.IsType <VoltageSwitch>(@switch);
            Assert.True(@switch.ParameterSets.Get <SpiceSharp.Components.SwitchBehaviors.BaseParameters>().ZeroState);
        }
Example #4
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()
            ;
        }
Example #5
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();
        }
Example #6
0
        public void LdContext(string contextName)
        {
            var contextRef = new ForeignContextRef(contextName);

            if (localContexts != null && localContexts.Length != 0)
            {
                var locals = localContexts.Where(lc => lc.Consumer.Equals(contextRef)).ToArray();
                if (locals.Length != 0)
                {
                    var END    = emit.Labels.Generate().GetRef();
                    var labels = new Ref <Labels> [locals.Length + 1];
                    for (int i = 0; i != labels.Length; ++i)
                    {
                        labels[i] = emit.Labels.Generate().GetRef();
                    }

                    var map =
                        (from i in Enumerable.Range(0, locals.Length)
                         let lc = locals[i]
                                  select new IntArrow <int>(lc.StackState, i))
                        .ToArray();

                    var switchGenerator = SwitchGenerator.Sparse(
                        map,
                        labels.Length - 1,
                        new IntInterval(0, short.MaxValue));
                    Expression <Action <IStackLookback <Msg> > > lookback = lb => lb.GetParentState();
                    switchGenerator.Build(
                        emit,
                        new Pipe <EmitSyntax>(il => il.Do(ldLookback).Call <IStackLookback <Msg> >(lookback)),
                        (il, value) =>
                    {
                        il.Label(labels[value].Def);

                        if (value == locals.Length)
                        {
                            if (LdGlobalContext(contextName))
                            {
                                il.Br(END);
                            }
                            else
                            {
                                il
                                .Ldstr(new QStr("Internal error: missing global context : " + contextRef.UniqueName))
                                .Newobj((string msg) => new Exception(msg))
                                .Throw()
                                ;
                            }
                        }
                        else
                        {
                            var lc       = locals[value];
                            var provider = lc.Provider.Joint.The <CilContextProvider>();
                            var context  = provider.GetContext(contextName);
                            context.Ld(
                                il,
                                il2 => il2
                                // Lookback for getting parent instance
                                .Do(ldLookback)
                                .Ldc_I4(lc.StackLookback)
                                .Call((IStackLookback <Msg> lb, int backOffset)
                                      => lb.GetValueAt(backOffset))
                                .Ldfld((Msg msg) => msg.Value));
                            il.Br(END);
                        }
                    });

                    emit.Label(END.Def);
                    return;
                }
            }

            if (!LdGlobalContext(contextName))
            {
                throw new InvalidOperationException(
                          "Context '" + contextName + "' is not accessible.");
            }
        }