static void EmitTemplateInclude(ILGenerator gen, StringTemplateAST args) { var name = gen.DeclareLocal(typeof(string)); var ldnull = gen.DefineLabel(); var endinclude = gen.DefineLabel(); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, endinclude); // the dup of a null object already loaded null back on the stack gen.Emit(OpCodes.Call, GetFuncMethodInfo <object, string>((o) => o.ToString())); // at this point, the name is the top item on the evaluation stack gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, endinclude); gen.Emit(OpCodes.Stloc, name); // $value = chunk.GetTemplateInclude(self, name, args); EmitLoadChunk(gen); EmitLoadSelf(gen); gen.Emit(OpCodes.Ldloc, name); // TODO: handle args throw new System.NotImplementedException(); //gen.Emit( OpCodes.Callvirt, typeof( ASTExpr ).GetMethod( "GetTemplateInclude", new System.Type[] { typeof( StringTemplate ), typeof( string ), typeof( StringTemplateAST ) } ) ); //gen.MarkLabel( endinclude ); }
static void EmitAddValueToList(ILGenerator gen, LocalBuilder local) { var label1 = gen.DefineLabel(); var label2 = gen.DefineLabel(); gen.Emit(OpCodes.Dup); gen.Emit(OpCodes.Brfalse_S, label1); gen.Emit(OpCodes.Ldloc, local); gen.Emit(OpCodes.Call, GetActionMethodInfo((object value, List <object> list) => list.Add(value))); gen.Emit(OpCodes.Br_S, label2); gen.MarkLabel(label1); gen.Emit(OpCodes.Pop); gen.MarkLabel(label2); }
static void EmitWriteToString(ILGenerator gen) { // Stack behavior: ..., (object)value => ..., (string)result //System.Func<object, StringTemplate, object> write = ( value, self ) => //{ // StringWriter buf = new StringWriter(); // IStringTemplateWriter sw = self.Group.GetStringTemplateWriter( buf ); // int n = chunk.WriteAttribute( self, value, sw ); // if ( n > 0 ) // return buf.ToString(); // return value; //}; var value = gen.DeclareLocal(typeof(object)); var buf = gen.DeclareLocal(typeof(StringWriter)); var sw = gen.DeclareLocal(typeof(IStringTemplateWriter)); var preserveValue = gen.DefineLabel(); var endOfWrite = gen.DefineLabel(); gen.Emit(OpCodes.Stloc, value); gen.Emit(OpCodes.Newobj, typeof(StringWriter)); gen.Emit(OpCodes.Stloc, buf); EmitLoadSelf(gen); gen.Emit(OpCodes.Call, GetFuncMethodInfo(( StringTemplate self ) => self.Group)); gen.Emit(OpCodes.Ldloc, buf); gen.Emit(OpCodes.Call, GetFuncMethodInfo((StringTemplateGroup group, System.IO.TextWriter writer) => group.GetStringTemplateWriter(writer))); gen.Emit(OpCodes.Stloc, sw); EmitLoadChunk(gen); EmitLoadSelf(gen); gen.Emit(OpCodes.Ldloc, value); gen.Emit(OpCodes.Ldloc, sw); gen.Emit(OpCodes.Call, GetFuncMethodInfo((ASTExpr chunk, StringTemplate self, object o, IStringTemplateWriter writer) => chunk.WriteAttribute(self, o, writer))); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ble, preserveValue); gen.Emit(OpCodes.Ldloc, buf); gen.Emit(OpCodes.Call, GetFuncMethodInfo(( StringWriter writer ) => writer.ToString())); gen.Emit(OpCodes.Br_S, endOfWrite); gen.MarkLabel(preserveValue); gen.Emit(OpCodes.Ldloc, value); gen.MarkLabel(endOfWrite); }
static public void emitMethod(List <MSIL.Instruction> Instructions, System.Reflection.Emit.ILGenerator ILGenerator) { Instructions = new List <MSIL.Instruction>(Instructions); Dictionary <int, System.Reflection.Emit.Label> labels = new Dictionary <int, System.Reflection.Emit.Label>(); Dictionary <int, System.Reflection.LocalVariableInfo> locals = new Dictionary <int, System.Reflection.LocalVariableInfo>(); { HashSet <int> uniqueOffset = new HashSet <int>(); for (int n = 0; n < Instructions.Count; n++) { if (Instructions[n] == null) { continue; } int offset = Instructions[n].Offset; if (uniqueOffset.Contains(offset)) { Dictionary <int, MSIL.Instruction> instructionRemap = new Dictionary <int, MSIL.Instruction>(); // Conflicting offset we need to patch all of them for (n = 0; n < Instructions.Count; n++) { int hash = Instructions[n].GetHashCode(); Instructions[n] = new MSIL.Instruction(Instructions[n].OpCode, Instructions[n].Data) { _Offset = n }; instructionRemap.Add(hash, Instructions[n]); } for (n = 0; n < Instructions.Count; n++) { if (Instructions[n].Data != null && (Instructions[n].Data is MSIL.Instruction)) { Instructions[n].Data = instructionRemap[(Instructions[n].Data as MSIL.Instruction).GetHashCode()]; } } break; } uniqueOffset.Add(offset); } } for (int n = 0; n < Instructions.Count; n++) { if (Instructions[n] == null) { continue; } if (Instructions[n].Data != null && (Instructions[n].Data is MSIL.Instruction)) { int labelPos = (Instructions[n].Data as MSIL.Instruction).Offset; System.Reflection.Emit.Label label; if (!labels.TryGetValue(labelPos, out label)) { label = ILGenerator.DefineLabel(); labels.Add(labelPos, label); } Instructions[n] = new MSIL.Instruction(Instructions[n].OpCode, label) { _Offset = Instructions[n]._Offset }; } else if (Instructions[n].Data != null && (Instructions[n].Data is System.Reflection.LocalVariableInfo)) { int localIndex = (Instructions[n].Data as System.Reflection.LocalVariableInfo).LocalIndex; System.Reflection.LocalVariableInfo local; if (!locals.TryGetValue(localIndex, out local)) { local = ILGenerator.DeclareLocal((Instructions[n].Data as System.Reflection.LocalVariableInfo).LocalType, (Instructions[n].Data as System.Reflection.LocalVariableInfo).IsPinned); locals.Add(localIndex, local); } Instructions[n] = new MSIL.Instruction(Instructions[n].OpCode, local) { _Offset = Instructions[n]._Offset }; } } for (int n = 0; n < Instructions.Count; n++) { System.Reflection.Emit.Label label; if (labels.TryGetValue(Instructions[n].Offset, out label)) { ILGenerator.MarkLabel(label); } Instructions[n].Emit(ILGenerator); } }