/// <inheritdoc/> public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption options) { if (Arguments != null) { var conversions = ArgumentConversions; for (int i = 0; i < Arguments.Count; i++) { Arguments[i].GenerateCode(generator); var conversion = conversions[i]; if (conversion != null) { generator.EmitConvert(conversion); } } } generator.NewObject(Constructor); int length = Expressions.Count; if (length > 0) { var variable = generator.DeclareVariable(Type); generator.StoreVariable(variable); generator.LoadVariable(variable); var conversions = ArrayConversions; generator.LoadInt32(length); Type type = ElementType; generator.NewArray(type); for (int i = 0; i < length; i++) { generator.Duplicate(); generator.LoadInt32(i); var expression = Expressions[i]; expression.GenerateCode(generator); if (expression.Type.IsValueType && type.IsValueType == false) { generator.Box(expression.Type); } var convertion = conversions[i]; if (convertion != null) { generator.EmitConvert(convertion); } generator.StoreArrayElement(type); } var m = Type.GetMethod("AddRange", Utils.ReflectionUtils.PublicInstance); generator.Call(m); generator.LoadVariable(variable); } }
public static void MakeObjectArray(MethodBodyGenerator generator, ICollection <Expression> expressions) { int i = 0; generator.LoadInt32(expressions.Count); generator.NewArray(typeof(object)); foreach (var expression in expressions) { generator.Duplicate(); generator.LoadInt32(i++); expression.Accept(generator).GenerateCode(generator); if (expression.Type.IsValueType) { generator.Box(expression.Type); } generator.StoreArrayElement(typeof(object)); } }
/// <inheritdoc/> public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption options) { //todo unsigned to signed switch (Value) { case sbyte _: generator.LoadByte((sbyte)Value); generator.NewObject(Utils.ReflectionHelpers.Byte_New); break; case short _: generator.LoadInt16((short)Value); generator.NewObject(Utils.ReflectionHelpers.Short_New); break; case int _: generator.LoadInt32((int)Value); generator.NewObject(Utils.ReflectionHelpers.Integer_New); break; case long _: generator.LoadInt64((long)Value); generator.NewObject(Utils.ReflectionHelpers.Long_New); break; case float _: generator.LoadSingle((float)Value); generator.NewObject(Utils.ReflectionHelpers.Float_New); break; case double _: generator.LoadDouble((double)Value); generator.NewObject(Utils.ReflectionHelpers.Double_New); break; case bool value: generator.LoadField(value ? Utils.ReflectionHelpers.Bool_True : Utils.ReflectionHelpers.Bool_False); break; case char _: generator.LoadChar((char)Value); generator.NewObject(Utils.ReflectionHelpers.Char_New); break; case string _: generator.LoadString(Value.ToString()); generator.NewObject(Utils.ReflectionHelpers.String_New); break; case null: generator.LoadNull(); break; } }
System.Delegate Compile(TypeContext context, System.Type returnType, System.Type[] types, ParameterInfo[] parameters, System.Type delType) { var names = Parameters.Map(para => para.Name).AddFirst("closure"); // Emit First Argument var lamdaVisit = new LamdaVisitor(names); Body.Accept(lamdaVisit); var parameterTypes = types.AddFirst(typeof(Runtime.Closure)); var method = new System.Reflection.Emit.DynamicMethod(Name, returnType, parameterTypes, true); var methodGen = new Generators.DynamicMethodGenerator(method, parameters, null) { SyntaxBody = Body, Context = context }; methodGen.EmitParameterInfo(); var bodyGen = new MethodBodyGenerator(methodGen, method.GetILGenerator()); object[] values = new object[lamdaVisit.HoistedLocals.Count]; if (values.Length > 0) { int index = 0; var field = typeof(Runtime.Closure).GetField("Values"); foreach (var item in lamdaVisit.HoistedLocals) { var value = item.Value; values[index] = value.Accept(ScriptCompiler.Instance); // if binder is null variable or member may not exist if (value.NodeType == ExpressionType.Identifier && ((NameExpression)value).Binder is null) { continue; } var variable = bodyGen.DeclareVariable(value.Type, item.Key); // load closure argument bodyGen.LoadArgument(0); bodyGen.LoadField(field); bodyGen.LoadInt32(index); bodyGen.LoadArrayElement(typeof(object)); bodyGen.UnboxObject(value.Type); bodyGen.StoreVariable(variable); index++; } } bodyGen.Compile(); return(method.CreateDelegate(delType, new Runtime.Closure(values))); }
public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption option) { var target = generator.Method.DeclaringType; IExpressionVisitor <object> visitor = ScriptCompiler.Instance; //pass scoped arguments // refer System.Linq.Expression.Compiler folder var names = Parameters.Map(para => para.Name); // Emit First Argument var lamdaVisit = new LamdaVisitor(names); Body.Accept(lamdaVisit); LamdaGen lamdaGen; if (generator.Method.DeclaringType is Generators.TypeGenerator typeGen) { lamdaGen = typeGen.DefineAnonymousMethod(Types, ReturnType); } else { lamdaGen = AssemblyGen.DynamicAssembly.DefineAnonymousMethod(Types, ReturnType); } var methodGen = new Generators.MethodGenerator(lamdaGen.Method, ParameterInfos, lamdaGen.Type) { SyntaxBody = Body, Context = generator.Context }; methodGen.EmitParameterInfo(); var bodyGen = new MethodBodyGenerator(methodGen, lamdaGen.Method.GetILGenerator()); var values = lamdaVisit.HoistedLocals.Values; // new object[] {} var valVar = generator.DeclareVariable(LamdaGen.ObjectArray); ArrayListExpression.MakeObjectArray(generator, values); generator.StoreVariable(valVar); if (values.Count > 0) { int index = 0; var field = lamdaGen.Values; foreach (var item in lamdaVisit.HoistedLocals) { var value = item.Value; var variable = bodyGen.DeclareVariable(value.Type, item.Key); bodyGen.LoadArgument(0); bodyGen.LoadField(field); bodyGen.LoadInt32(index); bodyGen.LoadArrayElement(TypeProvider.ObjectType); bodyGen.UnboxObject(value.Type); bodyGen.StoreVariable(variable); index++; } } bodyGen.Compile(); var type = lamdaGen.CreateType(); generator.LoadVariable(valVar); if (generator.Method is Generators.DynamicMethodGenerator) { generator.NewObject(type.GetConstructor(LamdaGen.CtorSignature)); generator.LoadFunction(type.GetMethod(ReflectionUtils.InvokeMethod, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic), Type); } else { generator.NewObject(lamdaGen.Constructor); generator.LoadFunction(lamdaGen.Method, Type); } }
//todo working on scope for better emit public System.Delegate Compile(System.Type target, IExpressionVisitor <object> visitor) { //pass scoped arguments // refer System.Linq.Expression.Compiler folder var context = TypeContext.Default; System.Type returnType; if (ReturnSyntax != null) { returnType = ReturnSyntax.ResolveType(context); } else { returnType = TypeProvider.AnyType; } var names = Parameters.Map(para => para.Name).AddFirst("closure"); int length = Parameters.Count; System.Type[] types = new System.Type[length]; var parameters = new ParameterInfo[length]; for (int i = 0; i < Parameters.Count; i++) { var para = Parameters[i]; System.Type type = para.Type == null ? TypeProvider.AnyType : para.Type.ResolveType(context); parameters[i] = new ParameterInfo(para.Name, i + 1, type, para.IsVarArgs); types[i] = type; } // Emit First Argument var lamdaVisit = new LamdaVisitor(names); Body.Accept(lamdaVisit); var parameterTypes = types.AddFirst(typeof(Closure)); var method = new System.Reflection.Emit.DynamicMethod("lambda_method", returnType, parameterTypes, true); var methodGen = new Generators.DynamicMethodGenerator(method, parameters, target) { SyntaxBody = Body, Context = context }; methodGen.EmitParameterInfo(); var bodyGen = new MethodBodyGenerator(methodGen, method.GetILGenerator()); object[] values = new object[lamdaVisit.HoistedLocals.Count]; if (values.Length > 0) { int index = 0; var field = typeof(Closure).GetField("Values"); foreach (var item in lamdaVisit.HoistedLocals) { var value = item.Value; values[index] = value.Accept(visitor); var variable = bodyGen.DeclareVariable(value.Type, item.Key); bodyGen.LoadArgument(0); bodyGen.LoadField(field); bodyGen.LoadInt32(index); bodyGen.LoadArrayElement(typeof(object)); bodyGen.UnboxObject(value.Type); bodyGen.StoreVariable(variable); index++; } } bodyGen.Compile(); var delgateType = DelegateGen.MakeNewDelegate(types, returnType); Type = delgateType; return(method.CreateDelegate(delgateType, new Runtime.Closure(values))); }