private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, AstParameters /*!*/ parameters) { var result = new AstExpressions( _parameters.LeftValues.Count + (_parameters.UnsplattedValue != null ? 1 : 0) + 1 ); bool paramsInArray = HasFormalParametersInArray; for (int i = 0; i < _parameters.LeftValues.Count; i++) { var parameter = paramsInArray ? (MSA.Expression) Ast.ArrayAccess(parameters[HiddenParameterCount], AstUtils.Constant(i)) : parameters[HiddenParameterCount + i]; result.Add(_parameters.LeftValues[i].TransformWrite(gen, parameter)); } if (_parameters.UnsplattedValue != null) { // the last parameter is unsplat: var parameter = parameters[parameters.Count - 1]; result.Add(_parameters.UnsplattedValue.TransformWrite(gen, parameter)); } result.Add(AstUtils.Empty()); return(Ast.Block(result)); }
private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args) { if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All)) { BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args)); if (oper == IndexType.Get) { return(new DynamicMetaObject( Ast.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), restrictions )); } else { return(new DynamicMetaObject( Ast.Assign( Ast.ArrayAccess( args[0].Expression, ConvertIfNeeded(factory, args[1].Expression, typeof(int)) ), ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType()) ), restrictions.Merge(args[1].Restrictions) )); } } return(null); }
private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, MSA.Expression[] /*!*/ parameters) { Assert.NotNull(gen); Assert.NotNullItems(parameters); var result = AstFactory.CreateExpressionArray( _parameters.LeftValues.Count + (_parameters.UnsplattedValue != null ? 1 : 0) + 1 ); int resultIndex = 0; bool paramsInArray = HasFormalParametersInArray; for (int i = 0; i < _parameters.LeftValues.Count; i++) { var parameter = paramsInArray ? Ast.ArrayAccess(parameters[HiddenParameterCount], Ast.Constant(i)) : parameters[HiddenParameterCount + i]; result[resultIndex++] = _parameters.LeftValues[i].TransformWrite(gen, parameter); } if (_parameters.UnsplattedValue != null) { // the last parameter is unsplat: var parameter = parameters[parameters.Length - 1]; result[resultIndex++] = _parameters.UnsplattedValue.TransformWrite(gen, parameter); } result[resultIndex++] = Ast.Empty(); Debug.Assert(resultIndex == result.Length); return(AstFactory.Block(result)); }
private MetaObject MakeArrayIndexRule(string oper, MetaObject[] args) { if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All)) { Restrictions restrictions = Restrictions.GetTypeRestriction(args[0].Expression, args[0].LimitType).Merge(Restrictions.Combine(args)); if (oper == StandardOperators.GetItem) { return(new MetaObject( Ast.ArrayAccess( args[0].Expression, ConvertIfNeeded(args[1].Expression, typeof(int)) ), restrictions )); } else { return(new MetaObject( Ast.Assign( Ast.ArrayAccess( args[0].Expression, ConvertIfNeeded(args[1].Expression, typeof(int)) ), ConvertIfNeeded(args[2].Expression, args[0].LimitType.GetElementType()) ), restrictions.Merge(args[1].Restrictions) )); } } return(null); }
// Function Body Code Generation // // object Func(object self, object[] args) { // object p1 = ...; // object p2 = ...; // ... // object pn = ...; // (..Body..) // } // // <if has_default(p[i]) then> // <p[i]> = <i> < args.Length ? (args[<i>] == void ? <default(p[i])> : args[<i>]) : <default(p[i])>; // <else if any_length_args(p[i]) then> // <if has_name(p[i]) then> // <p[i]> = new Array(args.Skip(<i>)); // <else> // <p[i]> = new UnnamedSpreadArguments(args, <i>); // <end if> // <else> // <p[i]> = <i> < args.Length ? args[<i>] : void; // <end if> public System.Linq.Expressions.Expression <Func <object, object, object[], object> > TransformLambda() { List <Ast> body = new List <Ast>(); for (int i = 0; i < Parameters.Count; i++) { var capCheck = Ast.LessThan(Ast.Constant(i), Ast.Property(_arguments, "Length")); Ast exp; if (Parameters[i].HasDefaultValue) { exp = Ast.Condition(capCheck, Ast.Condition(Ast.TypeEqual(Ast.ArrayAccess(_arguments, Ast.Constant(i)), typeof(Builtins.Void)), Ast.Constant(Parameters[i].DefaultValue, typeof(object)), Ast.ArrayAccess(_arguments, Ast.Constant(i)) ), Ast.Constant(Parameters[i].DefaultValue, typeof(object)) ); } else if (Parameters[i].ExpandToArray) { if (Parameters[i].ParameterVariable.Name != null) { exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Builtins.Array(null)), Ast.Call(new Func <IEnumerable <object>, int, IEnumerable <object> >(Enumerable.Skip).Method, _arguments, Ast.Constant(i)) ); } else { exp = Ast.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Runtime.UnnamedSpreadArguments(null, 0)), _arguments, Ast.Constant(i) ); } } else { exp = Ast.Condition(capCheck, Ast.ArrayAccess(_arguments, Ast.Constant(i)), Ast.Constant(Builtins.Void.Value, typeof(object)) ); } body.Add(Ast.Assign(Parameters[i].ParameterVariable, exp)); } foreach (var statement in Body) { body.Add(statement.Transform()); } body.Add(Ast.Label(ReturnLabel, Ast.Constant(Builtins.Void.Value))); return(Ast.Lambda <Func <object, object, object[], object> >(Ast.Block(_variables.Values.Concat(Parameters.Select(x => x.ParameterVariable)), body), Name, new[] { _global, _context, _arguments })); }
private MSA.Expression /*!*/ GetParameterAccess(AstParameters /*!*/ parameters, MSA.Expression paramsArray, int i) { return((paramsArray != null) ? (MSA.Expression)Ast.ArrayAccess(paramsArray, AstUtils.Constant(i)) : parameters[HiddenParameterCount + i]); }
internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op) { // if we just have a simple named multi-assignment (e.g. a, b = 1,2) // then go ahead and step over the entire statement at once. If we have a // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the // sets individually as they could be property sets the user wants to step // into. TODO: Enable stepping of the right hand side? bool emitIndividualSets = false; foreach (Expression e in _items) { if (IsComplexAssignment(e)) { emitIndividualSets = true; break; } } SourceSpan rightSpan = SourceSpan.None; SourceSpan leftSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; SourceSpan totalSpan = SourceSpan.None; if (emitIndividualSets) { rightSpan = span; leftSpan = SourceSpan.None; totalSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; } // 1. Evaluate the expression and assign the value to the temp. MSAst.ParameterExpression right_temp = Ast.Variable(typeof(object), "unpacking"); // 2. Add the assignment "right_temp = right" into the suite/block MSAst.Expression assignStmt1 = MakeAssignment(right_temp, right); // 3. Call GetEnumeratorValues on the right side (stored in temp) MSAst.Expression enumeratorValues = Expression.Convert(LightExceptions.CheckAndThrow( Expression.Call( emitIndividualSets ? AstMethods.GetEnumeratorValues : AstMethods.GetEnumeratorValuesNoComplexSets, // method // arguments Parent.LocalContext, right_temp, AstUtils.Constant(_items.Length) ) ), typeof(object[])); // 4. Create temporary variable for the array MSAst.ParameterExpression array_temp = Ast.Variable(typeof(object[]), "array"); // 5. Assign the value of the method call (mce) into the array temp // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block MSAst.Expression assignStmt2 = MakeAssignment( array_temp, enumeratorValues, rightSpan ); ReadOnlyCollectionBuilder <MSAst.Expression> sets = new ReadOnlyCollectionBuilder <MSAst.Expression>(_items.Length + 1); for (int i = 0; i < _items.Length; i++) { // target = array_temp[i] Expression target = _items[i]; if (target == null) { continue; } // 6. array_temp[i] MSAst.Expression element = Ast.ArrayAccess( array_temp, // array expression AstUtils.Constant(i) // index ); // 7. target = array_temp[i], and add the transformed assignment into the list of sets MSAst.Expression set = target.TransformSet( emitIndividualSets ? // span target.Span : SourceSpan.None, element, PythonOperationKind.None ); sets.Add(set); } // 9. add the sets as their own block so they can be marked as a single span, if necessary. sets.Add(AstUtils.Empty()); MSAst.Expression itemSet = GlobalParent.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan); // 10. Return the suite statement (block) return(GlobalParent.AddDebugInfo(Ast.Block(new[] { array_temp, right_temp }, assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan)); }
private bool MakeDefaultMemberRule(Operators oper) { if (_types[0].IsArray) { if (Binder.CanConvertFrom(_types[1], typeof(int), false, NarrowingLevel.All)) { if (oper == Operators.GetItem) { _rule.Target = _rule.MakeReturn(Binder, Ast.ArrayAccess( Param0, ConvertIfNeeded(Param1, typeof(int)) ) ); } else { _rule.Target = _rule.MakeReturn(Binder, Ast.Assign( Ast.ArrayAccess( Param0, ConvertIfNeeded(Param1, typeof(int)) ), ConvertIfNeeded(Param2, _types[0].GetElementType()) ) ); } return(true); } } MethodInfo[] defaults = GetMethodsFromDefaults(_types[0].GetDefaultMembers(), oper); if (defaults.Length != 0) { MethodBinder binder = MethodBinder.MakeBinder(Binder, oper == Operators.GetItem ? "get_Item" : "set_Item", defaults); BindingTarget target = binder.MakeBindingTarget(CallTypes.ImplicitInstance, _types); if (target.Success) { if (oper == Operators.GetItem) { _rule.Target = _rule.MakeReturn(Binder, target.MakeExpression(_rule, _rule.Parameters)); } else { _rule.Target = _rule.MakeReturn(Binder, Ast.Block( target.MakeExpression(_rule, _rule.Parameters), _rule.Parameters[2] ) ); } } else { _rule.Target = Binder.MakeInvalidParametersError(target).MakeErrorForRule(_rule, Binder); } return(true); } return(false); }
internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) { var actualArgs = resolver.GetActualArguments(); int splatIndex = actualArgs.SplatIndex; int collapsedCount = actualArgs.CollapsedCount; int firstSplatted = actualArgs.FirstSplattedArg; var result = new Expression[2 + _expandedCount + (collapsedCount > 0 ? 2 : 0)]; var arrayVariable = resolver.GetTemporary(_elementType.MakeArrayType(), "a"); int e = 0; result[e++] = Ast.Assign(arrayVariable, Ast.NewArrayBounds(_elementType, Ast.Constant(_expandedCount + collapsedCount))); int itemIndex = 0; int i = _start; while (true) { // inject loop copying collapsed items: if (i == splatIndex) { var indexVariable = resolver.GetTemporary(typeof(int), "t"); // for (int t = 0; t <= {collapsedCount}; t++) { // a[{itemIndex} + t] = CONVERT<ElementType>(list.get_Item({splatIndex - firstSplatted} + t)) // } result[e++] = Ast.Assign(indexVariable, AstUtils.Constant(0)); result[e++] = AstUtils.Loop( Ast.LessThan(indexVariable, Ast.Constant(collapsedCount)), // TODO: not implemented in the old interpreter // Ast.PostIncrementAssign(indexVariable), Ast.Assign(indexVariable, Ast.Add(indexVariable, AstUtils.Constant(1))), Ast.Assign( Ast.ArrayAccess(arrayVariable, Ast.Add(AstUtils.Constant(itemIndex), indexVariable)), resolver.Convert( new DynamicMetaObject( resolver.GetSplattedItemExpression(Ast.Add(AstUtils.Constant(splatIndex - firstSplatted), indexVariable)), BindingRestrictions.Empty ), null, ParameterInfo, _elementType ) ), null ); itemIndex += collapsedCount; } if (i >= _start + _expandedCount) { break; } Debug.Assert(!hasBeenUsed[i]); hasBeenUsed[i] = true; result[e++] = Ast.Assign( Ast.ArrayAccess(arrayVariable, AstUtils.Constant(itemIndex++)), resolver.Convert(args.GetObject(i), args.GetType(i), ParameterInfo, _elementType) ); i++; } result[e++] = arrayVariable; Debug.Assert(e == result.Length); return(Ast.Block(result)); }