public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; Ref <Labels> END = emit.Labels.Generate().GetRef(); Ref <Labels>[] labels = new Ref <Labels> [rows]; for (int i = 0; i != rows; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(labels) .Ldc_I4(-1) .Br(END) ; var columnRange = new IntInterval(0, columns - 1); var columnFrequency = new UniformIntFrequency(columnRange); for (int i = 0; i != rows; ++i) { var switchEmitter = SwitchGenerator.Sparse(table.GetRow(i), columnRange, columnFrequency); emit.Label(labels[i].Def); switchEmitter.Build(emit, LdCol, SwitchGenerator.LdValueAction(END)); } return(emit.Label(END.Def)); }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; Ref<Labels> END = emit.Labels.Generate().GetRef(); Ref<Labels>[] labels = new Ref<Labels>[rows]; for (int i = 0; i != rows; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(labels) .Ldc_I4(-1) .Br(END) ; var columnRange = new IntInterval(0, columns - 1); var columnFrequency = new UniformIntFrequency(columnRange); for (int i = 0; i != rows; ++i) { var switchEmitter = SwitchGenerator.Sparse(table.GetRow(i), columnRange, columnFrequency); emit.Label(labels[i].Def); switchEmitter.Build(emit, LdCol, SwitchGenerator.LdValueAction(END)); } return emit .Label(END.Def); }
public EmitSyntax EmitLoopPass(EmitSyntax emit, bool loop) { emit.Label(START); FetchNext(emit, END); body(emit); if (loop) { emit.Br(START.GetRef()); } return(emit .Label(END) .Nop()); }
public INfaVM Label(Def <Labels> label) { emit.Label(label); if (!indexToLabel.Contains(label)) { indexToLabel.Add(label); } return(this); }
private static EmitSyntax EmitAst(EmitSyntax emit, AstNode ast, Ref <Args> input) { var settings = new ILCompilerSettings { LdInput = il => il.Ldarg(input), SUCCESS = emit.Labels.Generate(), FAILURE = emit.Labels.Generate(), }; var _ = new ILNfaCompiler(ast, emit, settings); emit .Label(settings.SUCCESS) .Ldc_I4_1() .Ret() .Label(settings.FAILURE) .Ldc_I4_0() .Ret(); return(emit); }
protected override void DoBuild(EmitSyntax emit, Pipe<EmitSyntax> ldvalue, SwitchGeneratorAction action) { var labels = new Ref<Labels>[map.Length]; for (int i = 0; i != labels.Length; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(ldvalue) .Switch(labels) ; action(emit, defaultValue); for (int i = 0; i != labels.Length; ++i) { emit.Label(labels[i].Def); action(emit, map[i]); } }
protected override void DoBuild(EmitSyntax emit, Pipe <EmitSyntax> ldvalue, SwitchGeneratorAction action) { var labels = new Ref <Labels> [map.Length]; for (int i = 0; i != labels.Length; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(ldvalue) .Switch(labels) ; action(emit, defaultValue); for (int i = 0; i != labels.Length; ++i) { emit.Label(labels[i].Def); action(emit, map[i]); } }
public ILNfaCompiler(AstNode node, EmitSyntax emit, ILCompilerSettings settings) { this.Scanner = new StemScanner(); this.emit = emit; this.settings = settings; var labels = emit.Labels; NEXT_THREAD = labels.Generate(); RESUME_ALL = labels.Generate(); NEXT_INPUT = labels.Generate(); THREAD_SUSPEND = labels.Generate(); THREAD_DISPATCH = labels.Generate(); var LABEL0 = labels.Generate(); var LABEL1 = labels.Generate(); var POSTCOMPILEINIT = labels.Generate(); var POSTCOMPILEINIT_BACK = labels.Generate(); var locals = emit.Locals; slots = locals.Generate(); labelIndexToLocation = locals.Generate(); intTmp = locals.Generate(); threadTmp = locals.Generate(); INfaVM code = this; this.inputPump = new ArrayLoopGenerator( valueType: emit.Types.Int32, ldarray: settings.LdInput, body: il => il .Do(matchedStack.Clear) .Br(RESUME_ALL.GetRef()) ); this.runningStack = new StackGenerator(emit, typeof(Thread)); this.suspendedStack = new StackGenerator(emit, typeof(Thread)); this.matchedStack = new StackGenerator(emit, typeof(Thread)); this.tmpStack = new StackGenerator(emit, typeof(Thread), nullContainer: true); emit .Local(intTmp, emit.Types.Int32) .Local(slots, emit.Types.Import(typeof(int[]))) .Local(labelIndexToLocation, emit.Types.Import(typeof(int[]))) .Br(POSTCOMPILEINIT.GetRef()) .Label(POSTCOMPILEINIT_BACK) .Local(threadTmp, emit.Types.Import(typeof(Thread))) .Ldloca(threadTmp.GetRef()) .Initobj(emit.Types.Import(typeof(Thread))) .Do(inputPump.EmitInitialization) ; new RegularNfaVMCompiler().Compile(node, code); int LabelCount = Math.Max(1, indexToLabel.Count); this.runningStack.SetSize(LabelCount); this.suspendedStack.SetSize(LabelCount); this.matchedStack.SetSize(LabelCount); this.tmpStack.SetSize(LabelCount); emit .Label(POSTCOMPILEINIT) .Do(runningStack.Init) .Do(suspendedStack.Init) .Do(matchedStack.Init) .Do(tmpStack.Init) .Ldc_I4(slotCount) .Newarr(emit.Types.Int32) .Stloc(slots.GetRef()) .Ldc_I4(LabelCount) .Newarr(emit.Types.Int32) .Stloc(labelIndexToLocation.GetRef()) // Fill labelIndexToLocation with -1 : .Ldc_I4(LabelCount).Stloc(intTmp.GetRef()) .Label(LABEL1) .Ldloc(intTmp.GetRef()) .Ldc_I4_0() .Beq(LABEL0.GetRef()) .Ldloc(intTmp.GetRef()) .Ldc_I4(1) .Sub() .Stloc(intTmp.GetRef()) .Ldloc(labelIndexToLocation.GetRef()) .Ldloc(intTmp.GetRef()) .Ldc_I4(int.MinValue) .Stelem_I4() .Br(LABEL1.GetRef()) .Label(LABEL0) .Br(POSTCOMPILEINIT_BACK.GetRef()); // Save thread as suspended (stack should already contain label index to suspend) emit.Label(THREAD_SUSPEND); StThreadValueByRuntimeLabelIndex(); emit // Don't add thread if same thread (same label index // with current input location) already exists in a list. .Ldloc(labelIndexToLocation.GetRef()) .Ldloca(threadTmp.GetRef()) .Ldfld(LabelIndexField) .Ldelem_I4() .Ldloc(inputPump.Index.GetRef()) .Beq(NEXT_THREAD.GetRef()) // Mark label index as visited .Ldloc(labelIndexToLocation.GetRef()) .Ldloca(threadTmp.GetRef()) .Ldfld(LabelIndexField) .Ldloc(inputPump.Index.GetRef()) .Stelem_I4() ; suspendedStack.PushFrom(emit, threadTmp); emit .Br(NEXT_THREAD.GetRef()) .Label(RESUME_ALL) .Swap(suspendedStack.Stack, runningStack.Stack, tmpStack.Stack) .Swap(suspendedStack.Index, runningStack.Index, tmpStack.Index) .Label(NEXT_THREAD) ; runningStack .StackLoop( emit, (emit2, thread) => { emit2 .Ldloca(thread.GetRef()) .Ldfld(LabelIndexField) .Label(THREAD_DISPATCH) .Switch(indexToLabel.Select(def => def.GetRef()).ToArray()) .Br(settings.FAILURE.GetRef()); }) ; emit .Br(NEXT_INPUT.GetRef()) ; emit .Label(NEXT_INPUT) ; inputPump.EmitLoopPass(emit, false); emit // Check if there are matched threads: .Do(matchedStack.LdCount) .Ldc_I4_0() .Beq(settings.FAILURE.GetRef()) .Br(settings.SUCCESS.GetRef()); }
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 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() ; }
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 EmitSyntax EmitLoopPass(EmitSyntax emit, bool loop) { emit.Label(START); FetchNext(emit, END); body(emit); if (loop) { emit.Br(START.GetRef()); } return emit .Label(END) .Nop(); }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; // Dispatch info index Ref<Labels> DISP_INFO = emit.Labels.Generate().GetRef(); // Return no-data result Ref<Labels> RET_NONE = emit.Labels.Generate().GetRef(); // Exit Ref<Labels> END = emit.Labels.Generate().GetRef(); Ref<Labels>[] rowLabels = new Ref<Labels>[rows]; for (int i = 0; i != rows; ++i) { rowLabels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(rowLabels) .Br(RET_NONE) ; for (int i = 0; i != rows; ++i) { emit .Label(rowLabels[i].Def) .Ldc_I4(table.RowToOffset[i]) .Br(DISP_INFO); } int infoCount = table.Info.Count; var infoLabels = new Ref<Labels>[infoCount]; for (int i = 0; i != infoCount; ++i) { infoLabels[i] = emit.Labels.Generate().GetRef(); } emit .Label(DISP_INFO.Def) // Row offset should already be in stack .Do(LdCol) .Add() .Switch(infoLabels) .Br(RET_NONE); for (int i = 0; i != infoCount; ++i) { emit .Label(infoLabels[i].Def) .Do(LdRow) .Ldc_I4(table.Check[i]) .Bne_Un(RET_NONE) .Ldc_I4(table.Info[i]) .Br(END) ; } emit .Label(RET_NONE.Def) .Ldc_I4(0) ; return emit.Label(END.Def); }
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(); }
private static EmitSyntax EmitAst(EmitSyntax emit, AstNode ast, Ref<Args> input) { var settings = new ILCompilerSettings { LdInput = il => il.Ldarg(input), SUCCESS = emit.Labels.Generate(), FAILURE = emit.Labels.Generate(), }; var _ = new ILNfaCompiler(ast, emit, settings); emit .Label(settings.SUCCESS) .Ldc_I4_1() .Ret() .Label(settings.FAILURE) .Ldc_I4_0() .Ret(); return emit; }
void IDecisionVisitor.Visit(ActionDecision decision) { emit.Label(GetNodeLabel(decision).Def); this.action(emit, decision.Action); }
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() ; }
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 EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; // Dispatch info index Ref <Labels> DISP_INFO = emit.Labels.Generate().GetRef(); // Return no-data result Ref <Labels> RET_NONE = emit.Labels.Generate().GetRef(); // Exit Ref <Labels> END = emit.Labels.Generate().GetRef(); Ref <Labels>[] rowLabels = new Ref <Labels> [rows]; for (int i = 0; i != rows; ++i) { rowLabels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(rowLabels) .Br(RET_NONE) ; for (int i = 0; i != rows; ++i) { emit .Label(rowLabels[i].Def) .Ldc_I4(table.RowToOffset[i]) .Br(DISP_INFO); } int infoCount = table.Info.Count; var infoLabels = new Ref <Labels> [infoCount]; for (int i = 0; i != infoCount; ++i) { infoLabels[i] = emit.Labels.Generate().GetRef(); } emit .Label(DISP_INFO.Def) // Row offset should already be in stack .Do(LdCol) .Add() .Switch(infoLabels) .Br(RET_NONE); for (int i = 0; i != infoCount; ++i) { emit .Label(infoLabels[i].Def) .Do(LdRow) .Ldc_I4(table.Check[i]) .Bne_Un(RET_NONE) .Ldc_I4(table.Info[i]) .Br(END) ; } emit .Label(RET_NONE.Def) .Ldc_I4(0) ; return(emit.Label(END.Def)); }
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."); } }