public EmitSyntax Build(EmitSyntax emit) { var result = emit.Locals.Generate().GetRef(); emit .Local(result.Def, emit.Types.Import(LanguageBase.Fields.tokenKeyToId.FieldType)) .Newobj(() => new Dictionary<object,int>()) .Stloc(result); foreach (var pair in EnumerateTokenKeyToId()) { emit.Ldloc(result); if (pair.Item1 is string) { emit.Ldstr(new QStr((string)pair.Item1)); } else if (pair.Item1 is Type) { emit .Ldtoken(emit.Types.Import((Type)pair.Item1)) .Call((RuntimeTypeHandle h) => Type.GetTypeFromHandle(h)); } else { throw new InvalidOperationException("Internal error: Unsupported token key type"); } emit .Ldc_I4(pair.Item2) .Call((Dictionary<object, int> self, object _key, int _id) => self.Add(_key, _id)) ; } return emit.Ldloc(result); }
public INfaVM IsA(int expected) { emit .Ldloc(inputPump.Value.GetRef()) .Ldc_I4(expected) .Bne_Un(NEXT_THREAD.GetRef()); return(this); }
public static EmitSyntax Swap(this EmitSyntax emit, Def <Locals> x, Def <Locals> y, Def <Locals> tmp) { return (emit .Ldloc(x.GetRef()) .Stloc(tmp.GetRef()) .Ldloc(y.GetRef()) .Stloc(x.GetRef()) .Ldloc(tmp.GetRef()) .Stloc(y.GetRef())); }
/// <summary> /// Pops item and puts on the CLR stack /// </summary> /// <param name="emit"></param> public EmitSyntax Pop(EmitSyntax emit) { return(emit .Ldloc(index.GetRef()) .Ldc_I4_1() .Sub() .Stloc(index.GetRef()) .Ldloc(stack.GetRef()) .Ldloc(index.GetRef()) .Ldelem(itemType) ); }
public void PushFrom(EmitSyntax emit, Def <Locals> local) { emit .Ldloc(stack.GetRef()) .Ldloc(index.GetRef()) .Ldloc(local.GetRef()) .Stelem(itemType) .Ldloc(index.GetRef()) .Ldc_I4_1() .Add() .Stloc(index.GetRef()) ; }
public EmitSyntax Build(EmitSyntax emit) { var result = emit.Locals.Generate().GetRef(); emit .Local(result.Def, emit.Types.Import(LanguageBase.Fields.tokenKeyToId.FieldType)) .Newobj(() => new Dictionary <object, int>()) .Stloc(result); foreach (var pair in EnumerateTokenKeyToId()) { emit.Ldloc(result); if (pair.Item1 is string) { emit.Ldstr(new QStr((string)pair.Item1)); } else if (pair.Item1 is Type) { emit .Ldtoken(emit.Types.Import((Type)pair.Item1)) .Call((RuntimeTypeHandle h) => Type.GetTypeFromHandle(h)); } else { throw new InvalidOperationException("Internal error: Unsupported token key type"); } emit .Ldc_I4(pair.Item2) .Call((Dictionary <object, int> self, object _key, int _id) => self.Add(_key, _id)) ; } return(emit.Ldloc(result)); }
private void FetchNext(EmitSyntax emit, Def <Labels> END_OF_INPUT) { emit .Ldloc(Index.GetRef()) .Ldc_I4_1() .Add() .Stloc(Index.GetRef()) // ++Index // if (Index == count) goto END .Ldloc(Index.GetRef()) .Ldloc(count.GetRef()) .Beq(END_OF_INPUT.GetRef()) .Do(ldarray) .Ldloc(Index.GetRef()) .Ldelem(valueType) .Stloc(Value.GetRef()) ; }
public void LdValue(EmitSyntax emit) { emit.Ldloc(Value.GetRef()); }
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 EmitSyntax LdCount(EmitSyntax emit) { return(emit.Ldloc(index.GetRef())); }
public void LdInstance(EmitSyntax emit) { emit .Ldloc(stack.GetRef()) ; }
public EmitSyntax LdCount(EmitSyntax emit) { return emit.Ldloc(index.GetRef()); }
public void PushFrom(EmitSyntax emit, Def<Locals> local) { emit .Ldloc(stack.GetRef()) .Ldloc(index.GetRef()) .Ldloc(local.GetRef()) .Stelem(itemType) .Ldloc(index.GetRef()) .Ldc_I4_1() .Add() .Stloc(index.GetRef()) ; }
/// <summary> /// Pops item and puts on the CLR stack /// </summary> /// <param name="emit"></param> public EmitSyntax Pop(EmitSyntax emit) { return emit .Ldloc(index.GetRef()) .Ldc_I4_1() .Sub() .Stloc(index.GetRef()) .Ldloc(stack.GetRef()) .Ldloc(index.GetRef()) .Ldelem(itemType) ; }
private void FetchNext(EmitSyntax emit, Def<Labels> END_OF_INPUT) { emit .Ldloc(Index.GetRef()) .Ldc_I4_1() .Add() .Stloc(Index.GetRef()) // ++Index // if (Index == count) goto END .Ldloc(Index.GetRef()) .Ldloc(count.GetRef()) .Beq(END_OF_INPUT.GetRef()) .Do(ldarray) .Ldloc(Index.GetRef()) .Ldelem(valueType) .Stloc(Value.GetRef()) ; }
public EmitSyntax Build(EmitSyntax emit) { var resultVar = emit.Locals.Generate("result"); var partsVar = emit.Locals.Generate("parts"); var symbolVar = emit.Locals.Generate("symbol").GetRef(); var intArrayVar = emit.Locals.Generate("intArray").GetRef(); emit .Local(resultVar, emit.Types.Import(typeof(Grammar))) .Local(partsVar, emit.Types.Import(typeof(int[]))) .Local(symbolVar.Def, emit.Types.Import(typeof(SymbolBase))) .Local(intArrayVar.Def, emit.Types.Array(emit.Types.Int32)) .Newobj(() => new Grammar()) .Stloc(resultVar.GetRef()) ; foreach (var symbol in grammar.Symbols) { if (symbol.IsPredefined) { continue; } if (symbol is Symbol) { var determSymbol = (Symbol)symbol; emit .Ldstr(new QStr(symbol.Name)) .Newobj((string name) => new Symbol(name)) .Stloc(symbolVar) ; if (symbol.Categories != SymbolCategory.None) { emit .Ldloc(symbolVar) .Ldc_I4((int)symbol.Categories) .Stprop((Symbol s) => s.Categories) ; } if (symbol.Precedence != null) { var precedence = symbol.Precedence; emit .Ldloc(symbolVar) .Ldc_I4(precedence.Value) .Ldc_I4((int)precedence.Assoc) .Newobj((int _prec, Associativity _assoc) => new Precedence(_prec, _assoc)) .Stprop((Symbol s) => s.Precedence) ; } } else if (symbol is AmbiguousSymbol) { var ambSymbol = (AmbiguousSymbol)symbol; emit .Ldc_I4(ambSymbol.Tokens.Count) .Newarr(emit.Types.Int32) .Stloc(intArrayVar) ; for (int i = 0; i != ambSymbol.Tokens.Count; ++i) { emit .Ldloc(intArrayVar) .Ldc_I4(i) .Ldc_I4(ambSymbol.Tokens[i]) .Stelem_I4() ; } emit .Ldc_I4(ambSymbol.MainToken) .Ldloc(intArrayVar) .Newobj((int main, int[] tokens) => new AmbiguousSymbol(main, tokens)) .Stloc(symbolVar) ; } else { throw new InvalidOperationException("Internal error: unknown symbol type."); } emit .Ldloc(resultVar.GetRef()) .Ldprop((Grammar g) => g.Symbols) .Ldloc(symbolVar) .Call((SymbolCollection coll, Symbol sym) => coll.Add(sym)) .Pop() ; } if (grammar.Start != null) { emit .Ldloc(resultVar.GetRef()) .Dup() .Ldprop((Grammar g) => g.Symbols) .Ldc_I4(grammar.Start.Index) .Call((SymbolCollection coll, int index) => coll[index]) .Stprop((Grammar g) => g.Start); } foreach (var production in grammar.Productions) { if (production.Outcome.IsAugmentedStart) { // Start rule is defined automatically when first token is defined continue; } emit .Ldc_I4(production.PatternTokens.Length) .Newarr(emit.Types.Int32) .Stloc(partsVar.GetRef()) ; int i = 0; foreach (int part in production.PatternTokens) { emit .Ldloc(partsVar.GetRef()) .Ldc_I4(i) .Ldc_I4(part) .Stelem_I4() ; ++i; } emit .Ldloc(resultVar.GetRef()) .Ldprop((Grammar g) => g.Productions) .Ldc_I4(production.Outcome.Index) .Ldloc(partsVar.GetRef()) .Call((ProductionCollection prods, int l, IEnumerable <int> p) => prods.Define(l, p)) .Pop() ; } return(emit.Ldloc(resultVar.GetRef())); }