protected override void BuildLeaveStateEntry(ILBuilderContext ilBuilderContext, StateEntry stateEntry) { if (stateEntry == null || stateEntry.SkipStack) { return; } var parserStateEntry = stateEntry as ParserStateEntry; var parserEntry = parserStateEntry?.ParserEntryData; if (parserEntry != null && parserEntry.FlatIndex != -1) { var parserProduction = parserEntry.ParserProduction; var argumentBuilder = parserProduction.Binder.Template[parserEntry.FlatIndex]; if (!(argumentBuilder is ParserArgumentBuilder parserArgumentBuilder)) { throw new InvalidOperationException(); } ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Call, ConsumeEntryMethodInfo); if (parserProduction.Binder.TryReturn) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Call, OnAfterConsumeValueMethodInfo); } } }
private void EmitConsumeEntry(ILBuilderContext ilBuilderContext, ParserStateEntry parserStateEntry, LocalBuilder resultLocal) { var parserEntry = parserStateEntry?.ParserEntryData; if (parserEntry == null || parserEntry.FlatIndex == -1) { return; } var parserProduction = parserEntry.ParserProduction; var argumentBuilder = parserProduction.Binder.Template[parserEntry.FlatIndex]; if (!(argumentBuilder is ParserArgumentBuilder parserArgumentBuilder)) { throw new InvalidOperationException(); } ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, PeekStateEntryMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, ProductionInstanceBuilderArgumentsFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Ldelem_Ref); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); parserArgumentBuilder.EmitConsumeValue(ilBuilderContext); if (parserProduction.Binder.TryReturn) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Call, OnAfterConsumeValueMethodInfo); } }
private static void EmitGetInstructionSpan(ILBuilderContext ilBuilderContext) { var lexemeLocal = ilBuilderContext.IL.DeclareLocal(typeof(Lexeme <TToken> *)); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, GetInstructionReferenceMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, lexemeLocal); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, TextSourceFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldloc, lexemeLocal); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LexemeStartFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldloc, lexemeLocal); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LexemeEndFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Callvirt, TextSourceGetSpanMethodInfo); }
protected override void BuildBeginExecutionPath(ILBuilderContext ilBuilderContext, int stackDelta) { if (stackDelta > 0) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, stackDelta); ilBuilderContext.IL.Emit(OpCodes.Call, EnsureStateEntrySizeMethodInfo); } }
protected override void BuildEnterStateEntry(ILBuilderContext ilBuilderContext, StateEntry stateEntry) { if (stateEntry == null || stateEntry.SkipStack) { return; } if (!(stateEntry is ParserStateEntry parserStateEntry) || parserStateEntry.ParserEntryData.FlatIndex == -1) { return; } ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, StateEntryIndexFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4_1); ilBuilderContext.IL.Emit(OpCodes.Add); ilBuilderContext.IL.Emit(OpCodes.Stfld, StateEntryIndexFieldInfo); }
private static void EmitGetLexemeText(LocalBuilder lexemeLocal, ILBuilderContext ilBuilderContext) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, TextSourceFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldloc, lexemeLocal); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LexemeStartFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldloc, lexemeLocal); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LexemeEndFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Callvirt, TextSourceGetTextMethodInfo); }
private void BuildConsumeResult(ILBuilderContext ilBuilderContext, LocalBuilder resultLocal, ParserEntryData parserEntry) { if (parserEntry == null || parserEntry.FlatIndex == -1) { return; } var parserProduction = parserEntry.ParserProduction; var parserTransition = parserProduction; var argumentBuilder = parserTransition.Binder.Template[parserEntry.FlatIndex]; ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, PeekStateEntryMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, ProductionInstanceBuilderArgumentsFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Ldelem_Ref); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultGetResultMethodInfo); if (argumentBuilder is ParserArgumentBuilder parserArgumentBuilder) { parserArgumentBuilder.EmitConsumeValue(ilBuilderContext); } else if (argumentBuilder is LexerArgumentBuilder lexerArgumentBuilder) { ilBuilderContext.IL.Emit(OpCodes.Unbox_Any, typeof(Lexeme <>).MakeGenericType(lexerArgumentBuilder.TokenType)); lexerArgumentBuilder.EmitConsumeValue(this, ilBuilderContext); } if (parserProduction.Binder.TryReturn) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Call, OnAfterConsumeValueMethodInfo); } }
protected override void BuildEnterProduction(ILBuilderContext ilBuilderContext, Production production) { if (!(production is ParserProduction parserProduction)) { return; } if (parserProduction.IsInline) { return; } var pushMethod = parserProduction.LeftRecursionEntry != null ? PushLeftRecursionProductionInstanceBuilderMethodInfo : PushProductionInstanceBuilderMethodInfo; ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserProduction.ProductionIndex); ilBuilderContext.IL.Emit(OpCodes.Call, pushMethod); }
private static void EmitDebug(ILBuilderContext ilBuilderContext) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, DebugMethodInfo); }
private DynamicMethod BuildMain(ExecutionPath executionPath, out object[] closure) { var ilBuilderContext = new ILBuilderContext(ContextFieldInfo); if (executionPath.EnterReturnNodes.Length > 0) { if (IsOverriden(nameof(BuildBeginExecutionPath))) { BuildBeginExecutionPath(ilBuilderContext, executionPath.StackEvalDelta); } ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, executionPath.StackEvalDelta); ilBuilderContext.IL.Emit(OpCodes.Call, EnsureDeltaMethodInfo); } { if (executionPath.PathSourceNode is LeaveStateNode leaveStateNode) { EmitDebugNode(ilBuilderContext, executionPath.PathSourceNode, executionPath); var subGraph = leaveStateNode.SubGraph; if (subGraph.StateEntry != null) { if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, subGraph.StateEntry); } } } } EmitDebugExecutionPath(ilBuilderContext, executionPath); for (var index = 0; index < executionPath.Nodes.Length; index++) { var node = executionPath.Nodes[index]; switch (node) { case LeaveStateNode leaveStateNode: { EmitDebugNode(ilBuilderContext, executionPath.PathSourceNode, executionPath); var subGraph = leaveStateNode.SubGraph; if (subGraph.StateEntry != null) { if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, subGraph.StateEntry); } } break; } case ActionNode actionNode: { var action = actionNode.ActionEntry.Action; if (action.Target != null) { ilBuilderContext.EmitLdValue(action.Target); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Callvirt, action.Method); } else { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, action.Method); } break; } case BeginStateNode beginStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); break; } case BeginProductionNode beginProductionNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildEnterProduction))) { BuildEnterProduction(ilBuilderContext, beginProductionNode.Production); } break; } case EndProductionNode endProductionNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildLeaveProduction))) { BuildLeaveProduction(ilBuilderContext, endProductionNode.Production); } break; } case EnterStateNode enterStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var subGraph = enterStateNode.SubGraph; if (IsOverriden(nameof(BuildEnterStateEntry))) { BuildEnterStateEntry(ilBuilderContext, subGraph.StateEntry); } //stack.Push(subGraph); ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, subGraph.Id); ilBuilderContext.IL.Emit(OpCodes.Call, PushSafeIdMethodInfo); break; } case InlineEnterStateNode inlineEnterStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var stateEntry = inlineEnterStateNode.StateEntry; if (IsOverriden(nameof(BuildEnterStateEntry))) { BuildEnterStateEntry(ilBuilderContext, stateEntry); } break; } case InlineLeaveStateNode inlineLeaveStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var stateEntry = inlineLeaveStateNode.StateEntry; if (IsOverriden(nameof(BuildLeaveStateEntry))) { BuildLeaveStateEntry(ilBuilderContext, stateEntry); } break; } case OperandNode operandNode: { EmitDebugNode(ilBuilderContext, node, executionPath); if (IsOverriden(nameof(BuildInvoke))) { BuildInvoke(ilBuilderContext, operandNode.MatchEntry, true); } //_instructionPointer.MoveNext(); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, MoveNextMethodInfo); break; } case PredicateNode predicateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); //if (predicate.Predicate.Predicate(Context) == false) // return null; var returnPredicateLabel = ilBuilderContext.IL.DefineLabel(); var callPredicateLabel = ilBuilderContext.IL.DefineLabel(); var predicate = predicateNode.PredicateEntry; var consumeResult = predicate.ConsumeResult && IsOverriden(nameof(BuildConsumePredicateResult)); var trueLabel = ilBuilderContext.IL.DefineLabel(); var forkLabel = ilBuilderContext.IL.DefineLabel(); var resultLocal = ilBuilderContext.IL.DeclareLocal(typeof(PredicateResult)); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, ExecuteThreadQueueFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, callPredicateLabel); // Get Result from Process Result Queue if (consumeResult) { // if (predicate.PopResult == false) // return ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, ShouldPopPredicateResultMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, returnPredicateLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, ProcessDequePredicateResultMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); BuildConsumePredicateResult(ilBuilderContext, resultLocal, predicateNode.PredicateEntry.GetActualPredicateEntry()); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } ilBuilderContext.IL.Emit(OpCodes.Br, returnPredicateLabel); ilBuilderContext.IL.MarkLabel(callPredicateLabel); ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, CallPredicateMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Brtrue, forkLabel); ilBuilderContext.IL.Emit(OpCodes.Ldnull); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(forkLabel); // ForkPredicate ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultIsForkMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, trueLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, index); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, BuildForkNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(trueLabel); if (consumeResult) { BuildConsumePredicateResult(ilBuilderContext, resultLocal, predicateNode.PredicateEntry.GetActualPredicateEntry()); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } else { ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultDisposeMethodInfo); } ilBuilderContext.IL.MarkLabel(returnPredicateLabel); break; } case ReturnStateNode returnStateNode: { EmitDebugNode(ilBuilderContext, node, executionPath); var lastNode = index == executionPath.Nodes.Length - 1; var leaveNodeLocal = lastNode ? ilBuilderContext.IL.DeclareLocal(typeof(Node)) : null; ilBuilderContext.EmitLdStack(); if (lastNode) { ilBuilderContext.IL.Emit(OpCodes.Call, PopSafeNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, leaveNodeLocal); } else { ilBuilderContext.IL.Emit(OpCodes.Call, PopSafeMethodInfo); } if (lastNode) { ilBuilderContext.IL.Emit(OpCodes.Ldloc, leaveNodeLocal); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); } break; } } } ilBuilderContext.EmitLdValue(executionPath.Output); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); }
private DynamicMethod BuildParallel(ExecutionPath executionPath, out object[] closure) { var ilBuilderContext = new ILBuilderContext(ContextFieldInfo); for (var index = 0; index < executionPath.Nodes.Length; index++) { var node = executionPath.Nodes[index]; switch (node) { case EnterStateNode enterStateNode: { var subGraph = enterStateNode.SubGraph; //stack.Push(subGraph); ilBuilderContext.EmitLdStack(); ilBuilderContext.EmitLdValue(subGraph); ilBuilderContext.IL.Emit(OpCodes.Call, PushMethodInfo); break; } case ActionNode actionNode: { var action = actionNode.ActionEntry.Action; if (action.Target != null) { ilBuilderContext.EmitLdValue(action.Target); ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Callvirt, action.Method); } else { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, action.Method); } break; } case OperandNode operandNode: { if (IsOverriden(nameof(BuildInvoke))) { BuildInvoke(ilBuilderContext, operandNode.MatchEntry, false); } //_instructionPointer.MoveNext(); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Call, MoveNextMethodInfo); break; } case PredicateNode predicateNode: { //if (predicate.Predicate.Predicate(Context) == false) // return null; var predicate = predicateNode.PredicateEntry; var trueLabel = ilBuilderContext.IL.DefineLabel(); var forkLabel = ilBuilderContext.IL.DefineLabel(); var resultLocal = ilBuilderContext.IL.DeclareLocal(typeof(PredicateResult)); ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Call, CallPredicateMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Stloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Brtrue, forkLabel); ilBuilderContext.IL.Emit(OpCodes.Ldnull); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(forkLabel); // ForkPredicate ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Callvirt, PredicateResultIsForkMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Brfalse, trueLabel); ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, index); ilBuilderContext.EmitExecutionPath(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, BuildForkNodeMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ret); ilBuilderContext.IL.MarkLabel(trueLabel); if (predicate.ConsumeResult) { ilBuilderContext.EmitLdProcess(); ilBuilderContext.IL.Emit(OpCodes.Ldloc, resultLocal); ilBuilderContext.IL.Emit(OpCodes.Call, ProcessEnqueuePredicateResultMethodInfo); } break; } case ReturnStateNode _: { //return stack.Pop().LeaveNode; ilBuilderContext.EmitLdStack(); ilBuilderContext.IL.Emit(OpCodes.Call, PopMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LeaveNodeFieldInfo); if (index == executionPath.Nodes.Length - 1) { ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); } ilBuilderContext.IL.Emit(OpCodes.Pop); break; } } } ilBuilderContext.EmitLdValue(executionPath.Output); ilBuilderContext.IL.Emit(OpCodes.Ret); closure = ilBuilderContext.Values.ToArray(); return(ilBuilderContext.DynMethod); }
private static void EmitLdTextSource(ILBuilderContext ilBuilderContext) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldfld, TextSourceFieldInfo); }
private static void EmitGetInstructionToken(ILBuilderContext ilBuilderContext) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, GetInstructionReferenceMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, LexemeTokenFieldInfo); }
private static void EmitGetInstructionText(ILBuilderContext ilBuilderContext) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, GetInstructionTextMethodInfo); }
private void EmitDebugValue(ILBuilderContext ilBuilderContext, object value) { ilBuilderContext.EmitLdContext(); ilBuilderContext.EmitLdValue(value); ilBuilderContext.IL.Emit(OpCodes.Call, DebugMethodInfo); }
protected override void BuildInvoke(ILBuilderContext ilBuilderContext, MatchEntry matchEntry, bool main) { if (main == false) { return; } var parserEntry = matchEntry switch { ParserSingleMatchEntry s => s.ParserEntryData, ParserSetMatchEntry s => s.ParserEntryData, _ => throw new ArgumentOutOfRangeException() }; if (parserEntry.FlatIndex == -1) { return; } var parserProduction = parserEntry.ParserProduction; if (parserProduction == null) { return; } if (parserProduction.IsInline) { return; } var entryBuilder = parserProduction.Binder.Template[parserEntry.FlatIndex]; if (entryBuilder == null) { return; } if (!(entryBuilder is LexerArgumentBuilder lexerArgumentBuilder)) { throw new InvalidOperationException(); } ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Call, PeekStateEntryMethodInfo); ilBuilderContext.IL.Emit(OpCodes.Ldfld, ProductionInstanceBuilderArgumentsFieldInfo); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Ldelem_Ref); lexerArgumentBuilder.EmitConsumeValue(this, ilBuilderContext); if (parserProduction.Binder.TryReturn) { ilBuilderContext.EmitLdContext(); ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserEntry.FlatIndex); ilBuilderContext.IL.Emit(OpCodes.Call, OnAfterConsumeValueMethodInfo); } //ilBuilderContext.EmitLdContext(); //ilBuilderContext.IL.Emit(OpCodes.Ldc_I4, parserStateEntry.FlatIndex); //ilBuilderContext.IL.Emit(OpCodes.Call, ConsumeLexerEntryMethodInfo); }