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