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