internal Expression MakeExpression(RestrictedArguments restrictedArgs) { bool[] usageMarkers; Expression[] spilledArgs; Expression[] callArgs = GetArgumentExpressions(restrictedArgs, out usageMarkers, out spilledArgs); Expression call; MethodBase mb = _overload.ReflectionInfo; // TODO: make MakeExpression virtual on OverloadInfo? if (mb == null) { throw new InvalidOperationException("Cannot generate an expression for an overload w/o MethodBase"); } MethodInfo mi = mb as MethodInfo; if (mi != null) { Expression instance; if (mi.IsStatic) { instance = null; } else { Debug.Assert(mi != null); instance = _instanceBuilder.ToExpression(ref mi, _resolver, restrictedArgs, usageMarkers); Debug.Assert(instance != null, "Can't skip instance expression"); } if (CompilerHelpers.IsVisible(mi)) { call = AstUtils.SimpleCallHelper(instance, mi, callArgs); } else { call = Ast.Call( typeof(BinderOps).GetMethod("InvokeMethod"), AstUtils.Constant(mi), instance != null ? AstUtils.Convert(instance, typeof(object)) : AstUtils.Constant(null), AstUtils.NewArrayHelper(typeof(object), callArgs) ); } } else { ConstructorInfo ci = (ConstructorInfo)mb; if (CompilerHelpers.IsVisible(ci)) { call = AstUtils.SimpleNewHelper(ci, callArgs); } else { call = Ast.Call( typeof(BinderOps).GetMethod("InvokeConstructor"), AstUtils.Constant(ci), AstUtils.NewArrayHelper(typeof(object), callArgs) ); } } if (spilledArgs != null) { call = Expression.Block(spilledArgs.AddLast(call)); } Expression ret = _returnBuilder.ToExpression(_resolver, _argBuilders, restrictedArgs, call); List <Expression> updates = null; for (int i = 0; i < _argBuilders.Count; i++) { Expression next = _argBuilders[i].UpdateFromReturn(_resolver, restrictedArgs); if (next != null) { if (updates == null) { updates = new List <Expression>(); } updates.Add(next); } } if (updates != null) { if (ret.Type != typeof(void)) { ParameterExpression temp = Ast.Variable(ret.Type, "$ret"); updates.Insert(0, Ast.Assign(temp, ret)); updates.Add(temp); ret = Ast.Block(new[] { temp }, updates.ToArray()); } else { updates.Insert(0, ret); ret = Ast.Block(typeof(void), updates.ToArray()); } } if (_resolver.Temps != null) { ret = Ast.Block(_resolver.Temps, ret); } return(ret); }
internal override Expression ToExpression(ParameterBinder parameterBinder, IList <ArgBuilder> args, IList <Expression> parameters, Expression ret) { List <Expression> sets = new List <Expression>(); ParameterExpression tmp = parameterBinder.GetTemporary(ret.Type, "val"); sets.Add( Ast.Assign(tmp, ret) ); for (int i = 0; i < _indexesUsed.Length; i++) { Expression value = parameters[parameters.Count - _kwArgCount + _indexesUsed[i]]; switch (_membersSet[i].MemberType) { case MemberTypes.Field: FieldInfo fi = (FieldInfo)_membersSet[i]; if (!fi.IsLiteral && !fi.IsInitOnly) { sets.Add( Ast.Assign( Ast.Field(tmp, fi), ConvertToHelper(parameterBinder, value, fi.FieldType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), Ast.Constant(true), Ast.Constant(fi.Name) ), fi.FieldType ) ); } break; case MemberTypes.Property: PropertyInfo pi = (PropertyInfo)_membersSet[i]; if (pi.GetSetMethod(_privateBinding) != null) { sets.Add( Ast.Assign( Ast.Property(tmp, pi), ConvertToHelper(parameterBinder, value, pi.PropertyType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), Ast.Constant(false), Ast.Constant(pi.Name) ), pi.PropertyType ) ); } break; } } sets.Add( tmp ); Expression newCall = Ast.Block( sets.ToArray() ); return(_builder.ToExpression(parameterBinder, args, parameters, newCall)); }
internal override Expression ToExpression(OverloadResolver resolver, IList <ArgBuilder> builders, RestrictedArguments args, Expression ret) { List <Expression> sets = new List <Expression>(); ParameterExpression tmp = resolver.GetTemporary(ret.Type, "val"); sets.Add( Ast.Assign(tmp, ret) ); for (int i = 0; i < _indexesUsed.Length; i++) { Expression value = args.GetObject(args.Length - _kwArgCount + _indexesUsed[i]).Expression; PropertyInfo pi; FieldInfo fi; if ((fi = _membersSet[i] as FieldInfo) != null) { if (!fi.IsLiteral && !fi.IsInitOnly) { sets.Add( Ast.Assign( Ast.Field(tmp, fi), ConvertToHelper(resolver, value, fi.FieldType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), AstUtils.Constant(true), AstUtils.Constant(fi.Name) ), fi.FieldType ) ); } } else if ((pi = _membersSet[i] as PropertyInfo) != null) { if (pi.GetSetMethod(_privateBinding) != null) { sets.Add( Ast.Assign( Ast.Property(tmp, pi), ConvertToHelper(resolver, value, pi.PropertyType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), AstUtils.Constant(false), AstUtils.Constant(pi.Name) ), pi.PropertyType ) ); } } } sets.Add( tmp ); Expression newCall = Ast.Block( sets.ToArray() ); return(_builder.ToExpression(resolver, builders, args, newCall)); }
internal Expression MakeExpression(ParameterBinder parameterBinder, IList <Expression> parameters) { bool[] usageMarkers; Expression[] spilledArgs; Expression[] args = GetArgumentExpressions(parameterBinder, parameters, out usageMarkers, out spilledArgs); MethodBase mb = Method; MethodInfo mi = mb as MethodInfo; Expression ret, call; if (!mb.IsPublic || (mb.DeclaringType != null && !mb.DeclaringType.IsVisible)) { if (mi != null) { mi = CompilerHelpers.GetCallableMethod(mi, _binder._binder.PrivateBinding); if (mi != null) { mb = mi; } } } ConstructorInfo ci = mb as ConstructorInfo; Debug.Assert(mi != null || ci != null); if (mb.IsPublic && (mb.DeclaringType == null || mb.DeclaringType.IsVisible)) { // public method if (mi != null) { Expression instance = mi.IsStatic ? null : _instanceBuilder.ToExpression(parameterBinder, parameters, usageMarkers); call = AstUtils.SimpleCallHelper(instance, mi, args); } else { call = AstUtils.SimpleNewHelper(ci, args); } } else { // Private binding, invoke via reflection if (mi != null) { Expression instance = mi.IsStatic ? Ast.Constant(null) : _instanceBuilder.ToExpression(parameterBinder, parameters, usageMarkers); Debug.Assert(instance != null, "Can't skip instance expression"); call = Ast.Call( typeof(BinderOps).GetMethod("InvokeMethod"), Ast.Constant(mi), AstUtils.Convert(instance, typeof(object)), AstUtils.NewArrayHelper(typeof(object), args) ); } else { call = Ast.Call( typeof(BinderOps).GetMethod("InvokeConstructor"), Ast.Constant(ci), AstUtils.NewArrayHelper(typeof(object), args) ); } } if (spilledArgs != null) { call = Expression.Block(spilledArgs.AddLast(call)); } ret = _returnBuilder.ToExpression(parameterBinder, _argBuilders, parameters, call); List <Expression> updates = null; for (int i = 0; i < _argBuilders.Count; i++) { Expression next = _argBuilders[i].UpdateFromReturn(parameterBinder, parameters); if (next != null) { if (updates == null) { updates = new List <Expression>(); } updates.Add(next); } } if (updates != null) { if (ret.Type != typeof(void)) { ParameterExpression temp = Ast.Variable(ret.Type, "$ret"); updates.Insert(0, Ast.Assign(temp, ret)); updates.Add(temp); ret = Ast.Block(new [] { temp }, updates.ToArray()); } else { updates.Insert(0, ret); ret = Ast.Convert( Ast.Block(updates.ToArray()), typeof(void) ); } } if (parameterBinder.Temps != null) { ret = Ast.Block(parameterBinder.Temps, ret); } return(ret); }