void IMember.Compile() { var bodyGen = new MethodBodyGenerator(this, builder.GetILGenerator()); foreach (FieldGenerator generator in Declaring.Members.Where(mem => mem.MemberType == System.Reflection.MemberTypes.Field && mem.IsStatic == IsStatic)) { if (generator.DefaultValue != null) { if (IsStatic == false) { bodyGen.LoadArgument(0); } generator.MethodBody = bodyGen; ((IMember)generator).Compile(); generator.DefaultValue.GenerateCode(bodyGen, Expression.AssignOption); bodyGen.StoreField(generator.FieldInfo); } } if (IsStatic == false && Declaring.IsClass) { // if not call to super or this call if (!(SyntaxBody is BlockStatement body && body.Statements.Count > 0 && body.Statements[0] is ExpressionStatement statement && statement.Expression is InvocationExpression exp && (exp.Target.NodeType == ExpressionType.Super || exp.Target.NodeType == ExpressionType.This))) { var baseCtor = Declaring.BaseType.GetConstructor(new System.Type[0]); bodyGen.LoadArgument(0); bodyGen.Call(baseCtor); } } bodyGen.Compile(); }
public void GenerateGet(Expression target, MethodBodyGenerator generator, MethodCompileOption option) { if ((option & MethodCompileOption.EmitStartAddress) == MethodCompileOption.EmitStartAddress && parameter.Type.IsValueType) { if (generator.Method.IsStatic) { generator.LoadAddressOfArgument(parameter.Index); } else { generator.LoadAddressOfArgument(parameter.Index + 1); } } else { if (generator.Method.IsStatic) { generator.LoadArgument(parameter.Index); } else { generator.LoadArgument(parameter.Index + 1); } } }
/// <inheritdoc/> public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption option) { // for static no binder if (Binder != null) { if ((Binder.Attributes & Binders.BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } Binder.GenerateGet(null, generator, option); } }
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) { if (Method.IsAbstract && Method.DeclaringType == typeof(IDynamicInvocable)) { Target.GenerateCode(generator); if (Target.Type.IsValueType) { generator.Box(Target.Type); } } else { Target.GenerateCode(generator, MethodCompileOption.EmitStartAddress); } if (Target.NodeType == ExpressionType.MemberAccess) { MemberExpression target = (MemberExpression)Target; if (target.Target.Type.IsValueType) { switch (target.Target.NodeType) { case ExpressionType.Indexer: case ExpressionType.MemberAccess: var temp = generator.DeclareVariable(target.Target.Type); generator.StoreVariable(temp); generator.LoadAddressOfVariable(temp); break; } } } else if (Target.NodeType == ExpressionType.Identifier) { // if it an identifier expression this might be local member call var exp = (NameExpression)Target; if (exp.Binder == null && Method.IsStatic == false) { generator.LoadArgument(0); } } generator.EmitArguments(Arguments, Conversions); generator.Call(Method); // if current value must not be returned for assigment if ((option & MethodCompileOption.Return) == 0 && Type is object && Type != TypeProvider.VoidType) { generator.Pop(); } }
public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption option) { if (Left.NodeType == ExpressionType.Identifier) { var exp = (NameExpression)Left; var binder = exp.Binder; // binder is null create new local variable if (binder is null) { exp.Binder = binder = new Binders.VariableBinder(generator.DeclareVariable(Right.Type, exp.Name)); } if ((binder.Attributes & Binders.BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } Right.GenerateCode(generator, Option); if (Conversion != null) { generator.EmitConvert(Conversion); } binder.GenerateSet(Right, generator, option); } else if (Left.NodeType == ExpressionType.MemberAccess) { var exp = (MemberExpression)Left; exp.Target.GenerateCode(generator); // member assign for dynamic to be Any if ((exp.Binder.Attributes & Binders.BindingAttributes.Dynamic) == Binders.BindingAttributes.Dynamic) { generator.Box(TypeProvider.AnyType); } Right.GenerateCode(generator, Option); if (Conversion != null) { generator.EmitConvert(Conversion); } exp.Binder.GenerateSet(Right, generator, option); } else if (Left.NodeType == ExpressionType.Indexer) { GenerateIndexer(generator); } }
public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption options) { if (generator.Method is Generators.DynamicMethodGenerator) { // for annonymous type // if this is used in anonymous function or objects var variable = generator.GetLocalVariable("__value"); if (variable.Type.IsValueType && (options & MethodCompileOption.EmitStartAddress) == MethodCompileOption.EmitStartAddress) { generator.LoadAddressOfVariable(variable); } else { generator.LoadVariable(variable); } } else { generator.LoadArgument(0); } }
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))); }
public override void GenerateCode(MethodBodyGenerator generator, MethodCompileOption option) { if (NodeType == ExpressionType.Parenthesized) { Operand.GenerateCode(generator, option); return; } var operand = Operand; IBinder binder = null; if (operand.NodeType == ExpressionType.Identifier) { //todo only for get; set; member //i++ or Member++ binder = ((NameExpression)operand).Binder; } else if (operand.NodeType == ExpressionType.MemberAccess) { binder = ((MemberExpression)operand).Binder; } // todo: Conversion if value is short, byte lower data type switch (NodeType) { case ExpressionType.PostfixMinusMinus: case ExpressionType.PostfixPlusPlus: if (binder == null) { throw new NullReferenceException(nameof(binder)); } if ((binder.Attributes & BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } operand.GenerateCode(generator, MethodCompileOption.Dupplicate); if ((binder.Attributes & BindingAttributes.Member) != 0) { CallPostFixMember(generator, binder, option); return; } if ((option & MethodCompileOption.Dupplicate) != 0) { generator.Duplicate(); } // call the operator generator.CallStatic(Method); // update value binder.GenerateSet(operand, generator); break; case ExpressionType.PrefixMinusMinus: case ExpressionType.PrefixPlusPlus: if (binder == null) { throw new NullReferenceException(nameof(binder)); } if ((binder.Attributes & BindingAttributes.HasThis) != 0) { generator.LoadArgument(0); } operand.GenerateCode(generator, MethodCompileOption.Dupplicate); // call the operator generator.CallStatic(Method); if ((binder.Attributes & BindingAttributes.Member) != 0) { CallPreFixMember(generator, binder, option); return; } if ((option & MethodCompileOption.Dupplicate) != 0) { generator.Duplicate(); } // update value binder.GenerateSet(Operand, generator); break; default: // call the operator operand.GenerateCode(generator, AssignOption); generator.CallStatic(Method); break; } }