public static Convert ( Expression expression, Type type ) : Expression | ||
expression | Expression | |
type | Type | |
return | Expression |
private static MethodMissingBinding BindToKernelMethodMissing(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName, RubyMemberInfo methodMissing, RubyMethodVisibility incompatibleVisibility, bool isSuperCall) { // TODO: better specialization of method_missing methods if (methodMissing == null || methodMissing.DeclaringModule == methodMissing.Context.BasicObjectClass && methodMissing is RubyLibraryMethodInfo) { if (isSuperCall) { metaBuilder.SetError(Methods.MakeMissingSuperException.OpCall(AstUtils.Constant(methodName))); } else if (incompatibleVisibility == RubyMethodVisibility.Private) { metaBuilder.SetError(Methods.MakePrivateMethodCalledError.OpCall( AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), args.TargetExpression, AstUtils.Constant(methodName)) ); } else if (incompatibleVisibility == RubyMethodVisibility.Protected) { metaBuilder.SetError(Methods.MakeProtectedMethodCalledError.OpCall( AstUtils.Convert(args.MetaContext.Expression, typeof(RubyContext)), args.TargetExpression, AstUtils.Constant(methodName)) ); } else { return(MethodMissingBinding.Fallback); } return(MethodMissingBinding.Error); } return(MethodMissingBinding.Custom); }
// Returns true if the call was bound (with success or failure), false if fallback should be performed. internal static bool BuildAccess(MetaObjectBuilder /*!*/ metaBuilder, string /*!*/ methodName, CallArguments /*!*/ args, bool defaultFallback, bool callClrMethods) { RubyMemberInfo methodMissing; var method = Resolve(metaBuilder, methodName, args, out methodMissing); if (method.Found) { if (!callClrMethods && !method.Info.IsRubyMember) { return(false); } if (method.Info.IsDataMember) { method.Info.BuildCall(metaBuilder, args, methodName); } else { metaBuilder.Result = Methods.CreateBoundMember.OpCall( AstUtils.Convert(args.TargetExpression, typeof(object)), Ast.Constant(method.Info, typeof(RubyMemberInfo)), Ast.Constant(methodName) ); } return(true); } else { // Ruby doesn't have "attribute_missing" so we will always use method_missing and return a bound method object: return(BuildMethodMissingAccess(metaBuilder, args, methodName, methodMissing, method.IncompatibleVisibility, false, defaultFallback)); } }
// Returns true if the call was bound (with success or failure), false if fallback should be performed. internal static bool BuildMethodMissingAccess(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ methodName, RubyMemberInfo methodMissing, RubyMethodVisibility incompatibleVisibility, bool isSuperCall, bool defaultFallback) { switch (BindToKernelMethodMissing(metaBuilder, args, methodName, methodMissing, incompatibleVisibility, isSuperCall)) { case MethodMissingBinding.Custom: // we pretend we found the member and return a method that calls method_missing: Debug.Assert(!metaBuilder.Error); metaBuilder.Result = Methods.CreateBoundMissingMember.OpCall( AstUtils.Convert(args.TargetExpression, typeof(object)), Ast.Constant(methodMissing, typeof(RubyMemberInfo)), Ast.Constant(methodName) ); return(true); case MethodMissingBinding.Error: // method_missing is defined in Kernel, error has been reported: return(true); case MethodMissingBinding.Fallback: // method_missing is defined in Kernel: if (defaultFallback) { metaBuilder.SetError(Methods.MakeMissingMemberError.OpCall(Ast.Constant(methodName))); return(true); } return(false); } throw Assert.Unreachable; }
private DynamicMetaObject DynamicTryGetMember(string name, Expression fallback, Func <Expression, Expression> transform) { var temp = Expression.Parameter(typeof(object)); return(new DynamicMetaObject( Expression.Block( new[] { temp }, Expression.Condition( Expression.NotEqual( Expression.Assign( temp, Expression.Invoke( Expression.Constant(new Func <T, string, object>(TryGetMember)), Convert(Expression, typeof(T)), Expression.Constant(name) ) ), Expression.Constant(_getFailed) ), AstUtils.Convert(transform(temp), typeof(object)), AstUtils.Convert(fallback, typeof(object)) ) ), GetRestrictions() )); }
private DynamicMetaObject TryBindGetMember(string name) { if (_lib.HasMember(name)) { BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction( Expression, typeof(ComTypeLibDesc) ).Merge( BindingRestrictions.GetExpressionRestriction( Expression.Equal( Expression.Property( AstUtils.Convert( Expression, typeof(ComTypeLibDesc) ), typeof(ComTypeLibDesc).GetProperty("Guid") ), AstUtils.Constant(_lib.Guid) ) ) ); return(new DynamicMetaObject( AstUtils.Constant( ((ComTypeLibDesc)Value).GetTypeLibObjectDesc(name) ), restrictions )); } return(null); }
/// <summary> /// Takes current result and wraps it into try-filter(MethodUnwinder)-finally block that ensures correct "break" behavior for /// Ruby method calls with a block given in arguments. /// /// Sets up a RFC frame similarly to MethodDeclaration. /// </summary> public static void RuleControlFlowBuilder(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Debug.Assert(args.Signature.HasBlock); if (metaBuilder.Error) { return; } // TODO (improvement): // We don't special case null block here, although we could (we would need a test for that then). // We could also statically know (via call-site flag) that the current method is not a proc-converter (passed by ref), // which would make such calls faster. var rfcVariable = metaBuilder.GetTemporary(typeof(RuntimeFlowControl), "#rfc"); var resultVariable = metaBuilder.GetTemporary(typeof(object), "#result"); MSA.ParameterExpression unwinder; metaBuilder.Result = Ast.Block( // initialize frame (RFC): Ast.Assign(rfcVariable, Methods.CreateRfcForMethod.OpCall(AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)))), AstUtils.Try( Ast.Assign(resultVariable, metaBuilder.Result) ).Filter(unwinder = Ast.Parameter(typeof(MethodUnwinder), "#unwinder"), Ast.Equal(Ast.Field(unwinder, MethodUnwinder.TargetFrameField), rfcVariable), // return unwinder.ReturnValue; Ast.Assign(resultVariable, Ast.Field(unwinder, MethodUnwinder.ReturnValueField)) ).Finally( // we need to mark the RFC dead snce the block might escape and break later: Methods.LeaveMethodFrame.OpCall(rfcVariable) ), resultVariable ); }
public override MSAst.Expression Reduce() { MSAst.Expression left = _left; MSAst.Expression right = _right; Type t = Type; MSAst.ParameterExpression tmp = Ast.Variable(t, "__all__"); return(Ast.Block( new [] { tmp }, Ast.Condition( GlobalParent.Convert( typeof(bool), ConversionResultKind.ExplicitCast, Ast.Assign( tmp, AstUtils.Convert( left, t ) ) ), AstUtils.Convert( right, t ), tmp ) )); }
public override MSAst.Expression Reduce() { MSAst.MethodCallExpression call; if (_locals == null && _globals == null) { // exec code call = Ast.Call( AstMethods.UnqualifiedExec, Parent.LocalContext, AstUtils.Convert(_code, typeof(object)) ); } else { // exec code in globals [ , locals ] // We must have globals now (locals is last and may be absent) Debug.Assert(_globals != null); call = Ast.Call( AstMethods.QualifiedExec, Parent.LocalContext, AstUtils.Convert(_code, typeof(object)), TransformAndDynamicConvert(_globals, typeof(PythonDictionary)), TransformOrConstantNull(_locals, typeof(object)) ); } return(GlobalParent.AddDebugInfo(call, Span)); }
/// <summary> /// Gets an expression which is used for accessing this slot. If the slot lookup fails the error expression /// is used again. /// /// The default implementation just calls the TryGetValue method. Subtypes of PythonTypeSlot can override /// this and provide a more optimal implementation. /// </summary> internal virtual void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder) { ParameterExpression tmp = Ast.Variable(typeof(object), "slotTmp"); Expression call = Ast.Call( typeof(PythonOps).GetMethod("SlotTryGetValue"), codeContext, AstUtils.Convert(AstUtils.WeakConstant(this), typeof(PythonTypeSlot)), instance != null ? instance.Expression : AstUtils.Constant(null), owner.Expression, tmp ); builder.AddVariable(tmp); if (!GetAlwaysSucceeds) { builder.AddCondition( call, tmp ); } else { builder.FinishCondition(Ast.Block(call, tmp)); } }
private DynamicMetaObject /*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder /*!*/ conversion, Type toType, Type genericType) { ParameterExpression tmp = Ast.Variable(toType, "res"); DynamicMetaObject self = Restrict(typeof(OldInstance)); return(new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Ast.NotEqual( Ast.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldInstanceConvertToIEnumerableOfTNonThrowing").MakeGenericMethod(genericType), AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext), self.Expression ) ), AstUtils.Constant(null) ), tmp, AstUtils.Convert( AstUtils.Convert( FallbackConvert(conversion).Expression, typeof(object) ), toType ) ) ), self.Restrictions )); }
internal static bool BuildConversion(MetaObjectBuilder /*!*/ metaBuilder, DynamicMetaObject /*!*/ target, Expression /*!*/ contextExpression, Type /*!*/ toType, bool defaultFallback) { Expression expr = TryImplicitConversion(target, toType); if (expr != null) { metaBuilder.Result = expr; metaBuilder.AddObjectTypeRestriction(target.Value, target.Expression); return(true); } if (defaultFallback) { metaBuilder.AddObjectTypeRestriction(target.Value, target.Expression); metaBuilder.SetError(Methods.MakeTypeConversionError.OpCall( contextExpression, AstUtils.Convert(target.Expression, typeof(object)), Ast.Constant(toType, typeof(Type)) )); return(true); } return(false); }
private DynamicMetaObject /*!*/ MakeConvertToIEnumerable(DynamicMetaObjectBinder /*!*/ conversion) { ParameterExpression tmp = Ast.Variable(typeof(IEnumerable), "res"); DynamicMetaObject self = Restrict(typeof(OldInstance)); return(new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Ast.NotEqual( Ast.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldInstanceConvertToIEnumerableNonThrowing"), AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext), self.Expression ) ), AstUtils.Constant(null) ), tmp, AstUtils.Convert( AstUtils.Convert( // first to object (incase it's a throw), then to IEnumerable FallbackConvert(conversion).Expression, typeof(object) ), typeof(IEnumerable) ) ) ), self.Restrictions )); }
/// <summary> /// Provides default binding for performing a call on the specified meta objects. /// </summary> /// <param name="signature">The signature describing the call</param> /// <param name="target">The meta object to be called.</param> /// <param name="args"> /// Additional meta objects are the parameters for the call as specified by the CallSignature in the CallAction. /// </param> /// <param name="resolverFactory">Overload resolver factory.</param> /// <param name="errorSuggestion">The result should the object be uncallable.</param> /// <returns>A MetaObject representing the call or the error.</returns> public DynamicMetaObject Call(CallSignature signature, DynamicMetaObject errorSuggestion, OverloadResolverFactory resolverFactory, DynamicMetaObject target, params DynamicMetaObject[] args) { ContractUtils.RequiresNotNullItems(args, "args"); ContractUtils.RequiresNotNull(resolverFactory, "resolverFactory"); TargetInfo targetInfo = GetTargetInfo(target, args); if (targetInfo != null) { // we're calling a well-known MethodBase DynamicMetaObject res = MakeMetaMethodCall(signature, resolverFactory, targetInfo); if (res.Expression.Type.IsValueType) { res = new DynamicMetaObject( AstUtils.Convert(res.Expression, typeof(object)), res.Restrictions ); } return(res); } else { // we can't call this object return(errorSuggestion ?? MakeCannotCallRule(target, target.GetLimitType())); } }
private void SplatDictionaryArgument(IList <string> splattedNames, IList <DynamicMetaObject> splattedArgs) { Assert.NotNull(splattedNames, splattedArgs); DynamicMetaObject dictMo = GetArgument(_signature.ArgumentCount - 1); IDictionary dict = (IDictionary)dictMo.Value; IDictionaryEnumerator dictEnum = dict.GetEnumerator(); while (dictEnum.MoveNext()) { DictionaryEntry de = dictEnum.Entry; if (de.Key is string) { splattedNames.Add((string)de.Key); splattedArgs.Add( DynamicMetaObject.Create( de.Value, Ast.Call( AstUtils.Convert(dictMo.Expression, typeof(IDictionary)), typeof(IDictionary).GetMethod("get_Item"), AstUtils.Constant(de.Key as string) ) ) ); } } }
// TODO: revisit /// <summary> /// Converts the provided expression to the given type. The expression is safe to evaluate multiple times. /// </summary> public virtual Expression ConvertExpression(Expression expr, Type toType, ConversionResultKind kind, OverloadResolverFactory resolverFactory) { ContractUtils.RequiresNotNull(expr, "expr"); ContractUtils.RequiresNotNull(toType, "toType"); Type exprType = expr.Type; if (toType == typeof(object)) { if (exprType.IsValueType()) { return(AstUtils.Convert(expr, toType)); } else { return(expr); } } if (toType.IsAssignableFrom(exprType)) { return(expr); } return(Expression.Convert(expr, CompilerHelpers.GetVisibleType(toType))); }
public DynamicMetaObject Create(CallSignature signature, DynamicMetaObject target, DynamicMetaObject[] args, Expression contextExpression) { Type t = GetTargetType(target.Value); if (t != null) { if (typeof(Delegate).IsAssignableFrom(t) && args.Length == 1) { // PythonOps.GetDelegate(CodeContext context, object callable, Type t); return(new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod("GetDelegate"), contextExpression, AstUtils.Convert(args[0].Expression, typeof(object)), Expression.Constant(t) ), target.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)) )); } return(CallMethod( new PythonOverloadResolver( this, args, signature, contextExpression ), CompilerHelpers.GetConstructors(t, PrivateBinding), target.Restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)) )); } return(null); }
/// <summary> /// Called when the user is accessing a protected or private member on a get. /// /// The default implementation allows access to the fields or properties using reflection. /// </summary> public virtual ErrorInfo MakeNonPublicMemberGetError(OverloadResolverFactory resolverFactory, MemberTracker member, Type type, DynamicMetaObject instance) { switch (member.MemberType) { case TrackerTypes.Field: FieldTracker ft = (FieldTracker)member; return(ErrorInfo.FromValueNoError( Ast.Call( AstUtils.Convert(AstUtils.Constant(ft.Field), typeof(FieldInfo)), typeof(FieldInfo).GetMethod("GetValue"), AstUtils.Convert(instance.Expression, typeof(object)) ) )); case TrackerTypes.Property: PropertyTracker pt = (PropertyTracker)member; return(ErrorInfo.FromValueNoError( MemberTracker.FromMemberInfo(pt.GetGetMethod(true)).Call(resolverFactory, this, instance).Expression )); default: throw new InvalidOperationException(); } }
public override DynamicMetaObject BindGetMember(GetMemberBinder binder) { ContractUtils.RequiresNotNull(binder, "binder"); string name = binder.Name; if (name == _info.Name) { name = "TypeLibDesc"; } else if (name != "Guid" && name != "Name" && name != "VersionMajor" && name != "VersionMinor") { return(binder.FallbackGetMember(this)); } return(new DynamicMetaObject( Expression.Convert( Expression.Property( AstUtils.Convert(Expression, typeof(ComTypeLibInfo)), typeof(ComTypeLibInfo).GetProperty(name) ), typeof(object) ), ComTypeLibInfoRestrictions(this) )); }
private DynamicMetaObject /*!*/ MakeConvertToBool(DynamicMetaObjectBinder /*!*/ conversion) { DynamicMetaObject self = Restrict(typeof(OldInstance)); ParameterExpression tmp = Ast.Variable(typeof(bool?), "tmp"); DynamicMetaObject fallback = FallbackConvert(conversion); Type resType = BindingHelpers.GetCompatibleType(typeof(bool), fallback.Expression.Type); return(new DynamicMetaObject( Ast.Block( new ParameterExpression[] { tmp }, Ast.Condition( Ast.NotEqual( Ast.Assign( tmp, Ast.Call( typeof(PythonOps).GetMethod("OldInstanceConvertToBoolNonThrowing"), AstUtils.Constant(PythonContext.GetPythonContext(conversion).SharedContext), self.Expression ) ), AstUtils.Constant(null) ), AstUtils.Convert(tmp, resType), AstUtils.Convert(fallback.Expression, resType) ) ), self.Restrictions )); }
public override MSAst.LambdaExpression ReduceAst(PythonAst instance, string name) { return(Ast.Lambda <Func <CodeContext, FunctionCode, object> >( AstUtils.Convert(instance.ReduceWorker(), typeof(object)), name, PythonAst._arrayFuncParams )); }
private Expression RewriteTryCatch(TryExpression node) { // we inline the catch handlers after the catch blocks and use labels // to branch around and propagate the result out. // // goto tryDone( // try { // if (LightExceptions.IsLightException(_lastValue = someCall)) { // goto ehLabel; // } else { // _lastValue // } // } catch(Exception e) { // handler; // } // ) // // ehLabel: // if ((e = GetLightException(_lastValue) as Exception)) != null) { // handler; // } else { // // unhandled exception, propagate up, either: // goto _returnValue(_lastValue); // // if we weren't in a nested exception handler or if we were: // goto _ehLabelOuter; // } // tryDone: // // yields either the value of the try block or the real catch block // // from the goto tryDone or it gets it's default value from ehLabel // // which is branched to when an exception is detected. // var ehLabel = Expression.Label(typeof(void), GetEhLabelName("lightEh")); var tryDoneLabel = Expression.Label(node.Body.Type, GetEhLabelName("tryDone")); Expression body = Expression.Block( Expression.Goto( tryDoneLabel, Expression.TryCatch(RewriteTryBody(node, ehLabel), VisitHandlers(node, true)) ), Expression.Label( tryDoneLabel, Expression.Block( Expression.Label(ehLabel), Utils.Convert( LightCatch(VisitHandlers(node, false)), node.Body.Type ) ) ) ); // if we have a finally wrap the whole thing up now. if (node.Finally != null) { body = RewriteTryFinally(body, node.Finally); } return body; }
internal MSAst.Expression /*!*/ AddReturnTarget(MSAst.Expression /*!*/ expression) { if (_hasReturn) { return(Ast.Label(_returnLabel, AstUtils.Convert(expression, typeof(object)))); } return(expression); }
private void CreateFunctionInstructions(LightCompiler compiler) { // emit context if we have a special local context CodeContext globalContext = null; compiler.Compile(Parent.LocalContext); // emit name if necessary PythonGlobalVariableExpression name = GetVariableExpression(_nameVariable) as PythonGlobalVariableExpression; PythonGlobal globalName = null; if (name == null) { compiler.Compile(((IPythonGlobalExpression)GetVariableExpression(_nameVariable)).RawValue()); } else { globalName = name.Global; } // emit defaults int defaultCount = 0; for (int i = _parameters.Length - 1; i >= 0; i--) { var param = _parameters[i]; if (param.DefaultValue != null) { compiler.Compile(AstUtils.Convert(param.DefaultValue, typeof(object))); defaultCount++; } } // emit annotations int annotationCount = 0; if (ReturnAnnotation != null) { compiler.Compile(AstUtils.Convert(ReturnAnnotation, typeof(object))); compiler.Compile(AstUtils.Constant("return", typeof(string))); annotationCount++; } for (int i = _parameters.Length - 1; i >= 0; i--) { var param = _parameters[i]; if (param.Annotation != null) { compiler.Compile(AstUtils.Convert(param.Annotation, typeof(object))); compiler.Compile(AstUtils.Constant(param.Name, typeof(string))); annotationCount++; } } compiler.Instructions.Emit(new FunctionDefinitionInstruction(globalContext, this, defaultCount, annotationCount, globalName)); }
public override LightLambdaExpression ReduceAst(PythonAst instance, string name) { return(Utils.LightLambda <LookupCompilationDelegate>( typeof(object), AstUtils.Convert(instance.ReduceWorker(), typeof(object)), name, PythonAst._arrayFuncParams )); }
protected override Expression VisitConstant(ConstantExpression node) { var site = node.Value as CallSite; if (site != null) { return(RewriteCallSite(site)); } var exprSerializable = node.Value as IExpressionSerializable; if (exprSerializable != null) { EnsureConstantPool(); Expression res; if (!_constantCache.TryGetValue(node.Value, out res)) { Expression serialized = exprSerializable.CreateExpression(); _constants.Add(serialized); _constantCache[node.Value] = res = AstUtils.Convert( Expression.ArrayAccess(_constantPool, AstUtils.Constant(_constants.Count - 1)), serialized.Type ); } return(res); } var strings = node.Value as string[]; if (strings != null) { if (strings.Length == 0) { return(Expression.Field(null, typeof(ArrayUtils).GetField("EmptyStrings"))); } _constants.Add( Expression.NewArrayInit( typeof(string), new ReadOnlyCollection <Expression>( strings.Map(s => Expression.Constant(s, typeof(string))) ) ) ); return(AstUtils.Convert( Expression.ArrayAccess(_constantPool, AstUtils.Constant(_constants.Count - 1)), typeof(string[]) )); } return(base.VisitConstant(node)); }
public virtual ErrorInfo MakeConversionError(Type toType, Expression value) { return(ErrorInfo.FromException( Expression.Call( new Func <Type, object, Exception>(ScriptingRuntimeHelpers.CannotConvertError).GetMethod(), AstUtils.Constant(toType), AstUtils.Convert(value, typeof(object)) ) )); }
public override MSAst.Expression Reduce() { return(Expression.Call( AstMethods.MakeSet, Ast.NewArrayInit( typeof(object), ArrayUtils.ConvertAll(_items, x => AstUtils.Convert(x, typeof(object))) ) )); }
public override Expression Reduce() { return Expression.Condition( Expression.Block( Expression.Assign(LightExceptionRewriter._lastValue, _expr), IsLightExceptionExpression.Instance ), Expression.Goto(_target, _lastValue, _retType), Utils.Convert(LightExceptionRewriter._lastValue, _retType) ); }
internal CallSiteBuilder(AstGenerator /*!*/ gen, MSA.Expression /*!*/ instance, MSA.Expression block) { Assert.NotNull(gen, instance); _hasBlock = block != null; _gen = gen; // scope variable can be typed to a subclass of RubyScope: Add(AstUtils.Convert(_gen.CurrentScopeVariable, typeof(RubyScope))); Add(instance); Add(block); }
protected override Ast Body(MSAst.ParameterExpression res) { return(GlobalParent.AddDebugInfo( Ast.Call( AstMethods.SetAddForComprehension, res, AstUtils.Convert(_item, typeof(object)) ), _item.Span )); }