private static MetaObject MakeIMembersListRule(Expression codeContext, MetaObject target) { return(new MetaObject( Ast.Call( typeof(BinderOps).GetMethod("GetStringMembers"), Ast.Call( AstUtils.Convert(target.Expression, typeof(IMembersList)), typeof(IMembersList).GetMethod("GetMemberNames"), codeContext ) ), Restrictions.GetTypeRestriction(target.Expression, target.LimitType).Merge(target.Restrictions) )); }
/// <summary> /// Builds the restrictions for calling with a splatted argument array. Ensures that the /// argument is still an ICollection of object and that it has the same number of arguments. /// </summary> private static BindingRestrictions MakeParamsTest(DynamicMetaObject splattee, bool testTypes) { IList <object> list = splattee.Value as IList <object>; if (list == null) { if (splattee.Value == null) { return(BindingRestrictions.GetExpressionRestriction(Ast.Equal(splattee.Expression, AstUtils.Constant(null)))); } return(BindingRestrictions.GetTypeRestriction(splattee.Expression, splattee.Value.GetType())); } BindingRestrictions res = BindingRestrictions.GetExpressionRestriction( Ast.AndAlso( Ast.TypeIs(splattee.Expression, typeof(IList <object>)), Ast.Equal( Ast.Property( Ast.Convert(splattee.Expression, typeof(IList <object>)), typeof(ICollection <object>).GetDeclaredProperty("Count") ), AstUtils.Constant(list.Count) ) ) ); if (testTypes) { for (int i = 0; i < list.Count; i++) { res = res.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Ast.Call( AstUtils.Convert( splattee.Expression, typeof(IList <object>) ), typeof(IList <object>).GetMethod("get_Item"), AstUtils.Constant(i) ), CompilerHelpers.GetType(list[i]) ) ); } } return(res); }
protected override Expression VisitConstant(ConstantExpression node) { if (node.Value is CallSite site) { return(RewriteCallSite(site)); } if (node.Value is IExpressionSerializable exprSerializable) { EnsureConstantPool(); if (!_constantCache.TryGetValue(node.Value, out Expression 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); } if (node.Value is string[] strings) { if (strings.Length == 0) { return(Expression.Field(null, typeof(ArrayUtils).GetDeclaredField("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 override MSAst.Expression Reduce() { // (yield z) becomes: // .comma (1) { // .void ( .yield_statement (_expression) ), // $gen.CheckThrowable() // <-- has return result from send // } return(Ast.Block( AstUtils.YieldReturn( GeneratorLabel, Expression == null ? AstUtils.Constant(null) : AstUtils.Convert(Expression, typeof(object)) ), CreateCheckThrowExpression(Span) // emits ($gen.CheckThrowable()) )); }
private void MakeIMembersListRule() { _rule.Target = _rule.MakeReturn( Binder, Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("GetStringMembers"), Ast.Call( AstUtils.Convert(_rule.Parameters[0], typeof(IMembersList)), typeof(IMembersList).GetMethod("GetMemberNames"), _rule.Context ) ) ); }
private Expression /*!*/ MakeDelegateConstructorCall(Type /*!*/ type, CallArguments /*!*/ args) { if (args.Signature.HasBlock) { return(Methods.CreateDelegateFromProc.OpCall( Ast.Constant(type), AstUtils.Convert(args.GetBlockExpression(), typeof(Proc)) )); } else { // TODO: throw new NotImplementedError("no block given"); } }
public override MSAst.Expression Reduce() { if (HasStarredExpression) { return(UnpackSequenceHelper <SetCollection>(_items, AstMethods.MakeEmptySet, AstMethods.SetAdd, AstMethods.SetUpdate)); } return(Expression.Call( AstMethods.MakeSet, NewArrayInit( typeof(object), ArrayUtils.ConvertAll(_items, x => AstUtils.Convert(x, typeof(object))) ) )); }
internal override void MakeGetExpression(PythonBinder /*!*/ binder, Expression /*!*/ codeContext, DynamicMetaObject instance, DynamicMetaObject /*!*/ owner, ConditionalBuilder /*!*/ builder) { if (Getter.Length != 0 && !Getter[0].IsPublic) { // fallback to runtime call base.MakeGetExpression(binder, codeContext, instance, owner, builder); } else if (NeedToReturnProperty(instance, Getter)) { builder.FinishCondition(AstUtils.Constant(this)); } else if (Getter[0].ContainsGenericParameters) { builder.FinishCondition( DefaultBinder.MakeError( binder.MakeContainsGenericParametersError( MemberTracker.FromMemberInfo(_info) ), typeof(object) ).Expression ); } else if (instance != null) { builder.FinishCondition( AstUtils.Convert( binder.MakeCallExpression( new PythonOverloadResolverFactory(binder, codeContext), Getter[0], instance ).Expression, typeof(object) ) ); } else { builder.FinishCondition( AstUtils.Convert( binder.MakeCallExpression( new PythonOverloadResolverFactory(binder, codeContext), Getter[0] ).Expression, typeof(object) ) ); } }
DynamicMetaObject MakeGetMemberTarget(GetMemberInfo info, DynamicMetaObject target) { var type = target.GetLimitType(); var restrictions = target.Restrictions; var self = target; target = target.Restrict(target.GetLimitType()); var members = MemberGroup.EmptyGroup; // メンバ取得対象が TypeTracker である場合 if (typeof(TypeTracker).IsAssignableFrom(type)) { restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(target.Expression, target.Value)); var tg = target.Value as TypeGroup; if (tg == null || tg.TypesByArity.ContainsKey(0)) { var targetedType = ((TypeTracker)target.Value).Type; members = GetMember(MemberRequestKind.Get, targetedType, info.Name); if (members.Count > 0) { type = targetedType; self = null; } } } // 通常のメンバ一覧を検索 if (members.Count == 0) { members = GetMember(MemberRequestKind.Get, type, info.Name); } // インターフェイスの場合、object メンバを検索 if (members.Count == 0 && type.IsInterface) { members = GetMember(MemberRequestKind.Get, type = typeof(object), info.Name); } // プロパティ・フィールド用に StrongBox を展開し、そこから検索 var expandedSelf = self; if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type) && expandedSelf != null) { expandedSelf = new DynamicMetaObject(Expression.Field(AstUtils.Convert(expandedSelf.Expression, type), type.GetField("Value")), expandedSelf.Restrictions, ((IStrongBox)expandedSelf.Value).Value); type = type.GetGenericArguments()[0]; members = GetMember(MemberRequestKind.Get, type, info.Name); } MakeBodyHelper(info, self, expandedSelf, type, members); return(info.Body.GetMetaObject(restrictions)); }
public override MSAst.Expression Reduce() { var codeObj = GetOrMakeFunctionCode(); var funcCode = GlobalParent.Constant(codeObj); FuncCodeExpr = funcCode; MSAst.Expression lambda; if (EmitDebugSymbols) { lambda = GetLambda(); } else { lambda = NullLambda; ThreadPool.QueueUserWorkItem((x) => { // class defs are almost always run, so start // compiling the code now so it might be ready // when we actually go and execute it codeObj.UpdateDelegate(PyContext, true); }); } MSAst.Expression classDef = Ast.Call( AstMethods.MakeClass, funcCode, lambda, Parent.LocalContext, AstUtils.Constant(_name), Ast.NewArrayInit( typeof(object), ToObjectArray(_bases) ), Metaclass is null ? AstUtils.Constant(null, typeof(object)) : AstUtils.Convert(Metaclass, typeof(object)), AstUtils.Constant(FindSelfNames()) ); classDef = AddDecorators(classDef, Decorators); return(GlobalParent.AddDebugInfoAndVoid( AssignValue(Parent.GetVariableExpression(PythonVariable), classDef), new SourceSpan( GlobalParent.IndexToLocation(StartIndex), GlobalParent.IndexToLocation(HeaderIndex) ) )); }
// TODO: support for IgnoreCase in underlying ScriptScope APIs public override MetaObject BindDeleteMember(DeleteMemberBinder action) { var fallback = action.FallbackDeleteMember(this); return(new MetaObject( Expression.Condition( Expression.Call( AstUtils.Convert(Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("RemoveVariable"), Expression.Constant(action.Name) ), Expression.Empty(), Expression.Convert(fallback.Expression, typeof(void)) ), Restrictions.Merge(Restrictions.GetTypeRestriction(Expression, typeof(ScriptScope))).Merge(fallback.Restrictions) )); }
public static DynamicMetaObject MakeError(ErrorInfo error, BindingRestrictions restrictions, Type type) { switch (error.Kind) { case ErrorInfoKind.Error: return(new ErrorMetaObject(AstUtils.Convert(error.Expression, type), restrictions)); case ErrorInfoKind.Exception: return(new ErrorMetaObject(AstUtils.Convert(Expression.Throw(error.Expression), type), restrictions)); case ErrorInfoKind.Success: return(new ErrorMetaObject(AstUtils.Convert(error.Expression, type), restrictions)); default: throw new InvalidOperationException(); } }
protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { if (args.Target == null) { metaBuilder.Result = Ast.Constant(null); return(true); } var convertedTarget = args.Target as TTargetType; if (convertedTarget != null) { metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(TTargetType)); return(true); } return(false); }
/// <summary> /// Binds to the BoundMemberTracker and uses the instance in the tracker and restricts /// based upon the object instance type. /// </summary> private TargetInfo TryGetBoundMemberTargets(DynamicMetaObject self, DynamicMetaObject[] args, BoundMemberTracker bmt) { if (bmt != null) { Debug.Assert(bmt.Instance == null); // should be null for trackers that leak to user code MethodBase[] targets; // instance is pulled from the BoundMemberTracker and restricted to the correct // type. DynamicMetaObject instance = new DynamicMetaObject( AstUtils.Convert( Expression.Property( Expression.Convert(self.Expression, typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetDeclaredProperty("ObjectInstance") ), bmt.BoundTo.DeclaringType ), self.Restrictions ).Restrict(CompilerHelpers.GetType(bmt.ObjectInstance)); // we also add a restriction to make sure we're going to the same BoundMemberTracker BindingRestrictions restrictions = BindingRestrictions.GetExpressionRestriction( Expression.Equal( Expression.Property( Expression.Convert(self.Expression, typeof(BoundMemberTracker)), typeof(BoundMemberTracker).GetDeclaredProperty("BoundTo") ), AstUtils.Constant(bmt.BoundTo) ) ); switch (bmt.BoundTo.MemberType) { case TrackerTypes.MethodGroup: targets = ((MethodGroup)bmt.BoundTo).GetMethodBases(); break; case TrackerTypes.Method: targets = new MethodBase[] { ((MethodTracker)bmt.BoundTo).Method }; break; default: throw new InvalidOperationException(); // nothing else binds yet } return new TargetInfo(instance, args, restrictions, targets); } return null; }
public Expression /*!*/ MakeAllocatorCall(CallArguments /*!*/ args, Func <Expression> /*!*/ defaultExceptionMessage) { Type type = GetUnderlyingSystemType(); if (_structInfo != null) { return(Methods.AllocateStructInstance.OpCall(AstUtils.Convert(args.TargetExpression, typeof(RubyClass)))); } if (type.IsSubclassOf(typeof(Delegate))) { return(MakeDelegateConstructorCall(type, args)); } ConstructorInfo ctor; if (IsException()) { if ((ctor = type.GetConstructor(new[] { typeof(string) })) != null) { return(Ast.New(ctor, defaultExceptionMessage())); } else if ((ctor = type.GetConstructor(new[] { typeof(string), typeof(Exception) })) != null) { return(Ast.New(ctor, defaultExceptionMessage(), Ast.Constant(null))); } } if ((ctor = type.GetConstructor(new[] { typeof(RubyClass) })) != null) { return(Ast.New(ctor, AstUtils.Convert(args.TargetExpression, typeof(RubyClass)))); } if ((ctor = type.GetConstructor(new[] { typeof(RubyContext) })) != null) { return(Ast.New(ctor, args.ContextExpression)); } if ((ctor = type.GetConstructor(Type.EmptyTypes)) != null) { return(Ast.New(ctor)); } throw RubyExceptions.CreateTypeError(String.Format("allocator undefined for {0}", Name)); }
protected override bool TryImplicitConversion(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { object target = args.Target; if (args.Target == null) { metaBuilder.Result = Ast.Constant(false); return(true); } if (target is bool) { metaBuilder.Result = AstUtils.Convert(args.TargetExpression, typeof(bool)); return(true); } return(true); }
/// <summary> /// OldCallAction on Proc target. /// From control flow perspective it "yields" to the proc. /// </summary> internal void SetCallActionRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { Assert.NotNull(metaBuilder, args); Debug.Assert(!args.Signature.HasBlock); var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(BlockParam)); // test for target type: metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); metaBuilder.Result = AstFactory.YieldExpression( args.GetSimpleArgumentExpressions(), args.GetSplattedArgumentExpression(), args.GetRhsArgumentExpression(), convertedTarget, // block param Ast.Property(convertedTarget, SelfProperty) // self ); }
protected internal override DynamicMetaObject GetBoundValue(OverloadResolverFactory resolverFactory, ActionBinder binder, Type type, DynamicMetaObject instance) { if (IsPublic && DeclaringType.IsVisible) { return(new DynamicMetaObject( AstUtils.Convert( Expression.Field( AstUtils.Convert(instance.Expression, Field.DeclaringType), Field ), typeof(object) ), BindingRestrictions.Empty )); } return(DefaultBinder.MakeError(((DefaultBinder)binder).MakeNonPublicMemberGetError(resolverFactory, this, type, instance), BindingRestrictions.Empty, typeof(object))); }
/// <summary> /// Builds an expression for a call to the provided method using the given expressions. If the /// method is not static the first parameter is used for the instance. /// /// Parameters are converted using the binder's conversion rules. /// /// If an incorrect number of parameters is provided MakeCallExpression returns null. /// </summary> public Expression MakeCallExpression(Expression context, MethodInfo method, IList <Expression> parameters) { ParameterInfo[] infos = method.GetParameters(); Expression callInst = null; int parameter = 0, startArg = 0; Expression[] callArgs = new Expression[infos.Length]; if (!method.IsStatic) { callInst = AstUtils.Convert(parameters[0], method.DeclaringType); parameter = 1; } if (infos.Length > 0 && typeof(CodeContext).IsAssignableFrom(infos[0].ParameterType)) { startArg = 1; callArgs[0] = context; } for (int arg = startArg; arg < infos.Length; arg++) { if (parameter < parameters.Count) { callArgs[arg] = ConvertExpression( parameters[parameter++], infos[arg].ParameterType, ConversionResultKind.ExplicitCast, context ); } else { return(null); } } // check that we used all parameters if (parameter != parameters.Count) { return(null); } return(AstUtils.SimpleCallHelper(callInst, method, callArgs)); }
internal void SetRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args) { RubyModule currentDeclaringModule; string currentMethodName; var scope = args.Scope; object target; scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out target); var targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self"); metaBuilder.AddCondition( Methods.IsSuperCallTarget.OpCall( AstUtils.Convert(args.ScopeExpression, typeof(RubyScope)), Ast.Constant(currentDeclaringModule), AstUtils.Constant(currentMethodName), targetExpression ) ); args.SetTarget(targetExpression, target); Debug.Assert(currentDeclaringModule != null); // target is stored in a local, therefore it cannot be part of the restrictions: metaBuilder.TreatRestrictionsAsConditions = true; metaBuilder.AddTargetTypeTest(target, targetExpression, scope.RubyContext, args.ContextExpression); metaBuilder.TreatRestrictionsAsConditions = false; RubyMemberInfo method = scope.RubyContext.ResolveSuperMethod(target, currentMethodName, currentDeclaringModule); // super calls don't go to method_missing if (method == null) { metaBuilder.SetError(Methods.MakeMissingSuperException.OpCall(Ast.Constant(currentMethodName))); } else { method.InvalidateSitesOnOverride = true; method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule); } }
private static void AddArgument(List <Expression> /*!*/ actualArgs, object arg, Expression /*!*/ expr) { if (arg == null) { actualArgs.Add(Ast.Constant(null)); } else { var type = CompilerHelpers.GetVisibleType(arg); if (type.IsValueType) { actualArgs.Add(expr); } else { actualArgs.Add(AstUtils.Convert(expr, type)); } } }
/// <summary> /// Helper to produce a rule when no conversion is required (the strong type of the expression /// input matches the type we're converting to or has an implicit conversion at the IL level) /// </summary> private static DynamicMetaObject MakeSimpleConversionTarget(Type toType, BindingRestrictions restrictions, DynamicMetaObject arg) { return(new DynamicMetaObject( AstUtils.Convert(arg.Expression, CompilerHelpers.GetVisibleType(toType)), restrictions)); /* * if (toType.IsValueType && _rule.ReturnType == typeof(object) && Expression.Type == typeof(object)) { * // boxed value type is being converted back to object. We've done * // the type check, there's no need to unbox & rebox the value. infact * // it breaks calls on instance methods so we need to avoid it. * _rule.Target = * _rule.MakeReturn( * Binder, * Expression * ); * } * */ }
/// <summary> /// Helper to wrap explicit conversion call into try/catch incase it throws an exception. If /// it throws the default value is returned. /// </summary> private static Expression WrapForThrowingTry(ConversionResultKind kind, bool isImplicit, Expression ret, Type retType) { if (!isImplicit && kind == ConversionResultKind.ExplicitTry) { Expression convFailed = GetTryConvertReturnValue(retType); ParameterExpression tmp = Expression.Variable(convFailed.Type == typeof(object) ? typeof(object) : ret.Type, "tmp"); ret = Expression.Block( new ParameterExpression[] { tmp }, AstUtils.Try( Expression.Assign(tmp, AstUtils.Convert(ret, tmp.Type)) ).Catch( typeof(Exception), Expression.Assign(tmp, convFailed) ), tmp ); } return(ret); }
public MSAst.Expression CreateExpression() { MSAst.Expression[] items = new MSAst.Expression[Count * 2]; int index = 0; foreach (var item in GetItems()) { items[index++] = Utils.Convert(Utils.Constant(item.Value), typeof(object)); items[index++] = Utils.Convert(Utils.Constant(item.Key), typeof(object)); } return(MSAst.Expression.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeConstantDictStorage)), MSAst.Expression.NewArrayInit( typeof(object), items ) )); }
private MetaObject TryNumericComparison(OperatorInfo info, MetaObject[] args) { MethodInfo[] targets = FilterNonMethods( args[0].LimitType, GetMember(OldDoOperationAction.Make(this, info.Operator), args[0].LimitType, "Compare") ); if (targets.Length > 0) { MethodBinder mb = MethodBinder.MakeBinder(this, targets[0].Name, targets); BindingTarget target = mb.MakeBindingTarget(CallTypes.None, args); if (target.Success) { Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int)); switch (info.Operator) { case Operators.GreaterThan: call = Ast.GreaterThan(call, Ast.Constant(0)); break; case Operators.LessThan: call = Ast.LessThan(call, Ast.Constant(0)); break; case Operators.GreaterThanOrEqual: call = Ast.GreaterThanOrEqual(call, Ast.Constant(0)); break; case Operators.LessThanOrEqual: call = Ast.LessThanOrEqual(call, Ast.Constant(0)); break; case Operators.Equals: call = Ast.Equal(call, Ast.Constant(0)); break; case Operators.NotEquals: call = Ast.NotEqual(call, Ast.Constant(0)); break; case Operators.Compare: break; } return(new MetaObject( call, Restrictions.Combine(target.RestrictedArguments) )); } } return(null); }
private DynamicMetaObject TryNumericComparison(OperatorInfo info, OverloadResolverFactory resolverFactory, DynamicMetaObject[] args) { MethodInfo[] targets = FilterNonMethods( args[0].GetLimitType(), GetMember( MemberRequestKind.Operation, args[0].GetLimitType(), "Compare" ) ); if (targets.Length > 0) { var resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None); BindingTarget target = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All); if (target.Success) { Expression call = AstUtils.Convert(target.MakeExpression(), typeof(int)); switch (info.Operator) { case ExpressionType.GreaterThan: call = Expression.GreaterThan(call, AstUtils.Constant(0)); break; case ExpressionType.LessThan: call = Expression.LessThan(call, AstUtils.Constant(0)); break; case ExpressionType.GreaterThanOrEqual: call = Expression.GreaterThanOrEqual(call, AstUtils.Constant(0)); break; case ExpressionType.LessThanOrEqual: call = Expression.LessThanOrEqual(call, AstUtils.Constant(0)); break; case ExpressionType.Equal: call = Expression.Equal(call, AstUtils.Constant(0)); break; case ExpressionType.NotEqual: call = Expression.NotEqual(call, AstUtils.Constant(0)); break; } return(new DynamicMetaObject( call, target.RestrictedArguments.GetAllRestrictions() )); } } return(null); }
public override MetaObject /*!*/ BindInvoke(InvokeBinder /*!*/ action, MetaObject /*!*/[] /*!*/ args) { RubyCallSignature callSignature; if (RubyCallSignature.TryCreate(action.Arguments, out callSignature)) { return(action.FallbackInvoke(this, args)); } var metaBuilder = new MetaObjectBuilder(); var context = new MetaObject( Methods.GetContextFromBlockParam.OpCall(AstUtils.Convert(Expression, typeof(BlockParam))), Restrictions.Empty, RubyOps.GetContextFromBlockParam((BlockParam)Value) ); BlockParam.SetCallActionRule(metaBuilder, new CallArguments(context, this, args, callSignature)); return(metaBuilder.CreateMetaObject(action, args)); }
internal static void SetCallActionRule(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool testTarget) { Assert.NotNull(metaBuilder, args); var convertedTarget = AstUtils.Convert(args.TargetExpression, typeof(Proc)); // test for target type: if (testTarget) { metaBuilder.AddTypeRestriction(args.Target.GetType(), args.TargetExpression); } SetProcCallRule( metaBuilder, convertedTarget, // proc object Ast.Property(convertedTarget, SelfProperty), // self captured by the block closure null, args ); }
/// <summary> /// Helper to wrap explicit conversion call into try/catch incase it throws an exception. If /// it throws the default value is returned. /// </summary> private static MSAst WrapForThrowingTry(ConversionResultKind kind, bool isImplicit, MSAst ret, Type retType) { if (!isImplicit && kind == ConversionResultKind.ExplicitTry) { var convFailed = GetTryConvertReturnValue(retType); //var tmp = MSAst.Variable(convFailed.Type == typeof(object) ? typeof(object) : ret.Type, "tmp"); return(AstUtils.Convert(ret, convFailed.Type == typeof(object) ? typeof(object) : ret.Type)); //ret = MSAst.Block( // new[] { tmp }, // AstUtils.Try( // MSAst.Assign(tmp, AstUtils.Convert(ret, tmp.Type)) // ).Catch( // typeof(Exception), // MSAst.Assign(tmp, convFailed) // ), // tmp // ); } return(ret); }
protected internal static MSAst.BlockExpression UnpackSequenceHelper <T>(IList <Expression> items, MethodInfo makeEmpty, MethodInfo append, MethodInfo extend) { var expressions = new ReadOnlyCollectionBuilder <MSAst.Expression>(items.Count + 2); var varExpr = Expression.Variable(typeof(T), "$coll"); expressions.Add(Expression.Assign(varExpr, Expression.Call(makeEmpty))); foreach (var item in items) { if (item is StarredExpression starredExpression) { expressions.Add(Expression.Call(extend, varExpr, AstUtils.Convert(starredExpression.Value, typeof(object)))); } else { expressions.Add(Expression.Call(append, varExpr, AstUtils.Convert(item, typeof(object)))); } } expressions.Add(varExpr); return(Expression.Block(typeof(T), new MSAst.ParameterExpression[] { varExpr }, expressions)); }