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)); }
public MSA.Expression /*!*/ MakeLocalsStorage() { // TODO: use a factory instead of Ast.New to improve interpreter perf: MSA.Expression result = Ast.Assign( _localsTuple, LiftedVisibleVariableCount == 0 ? (MSA.Expression)Ast.Constant(null, _localsTuple.Type) : Ast.New(_localsTuple.Type) ); if (_parameters != null) { var initializers = new AstExpressions(); initializers.Add(result); // parameters map to the initial elements of the array: for (int i = _firstClosureParam, j = 0; i < _parameters.Count; i++, j++) { initializers.Add(Ast.Assign(GetVariableAccessor(_localsTuple, j), _parameters[i])); } initializers.Add(_localsTuple); result = Ast.Block(initializers); } return(result); }
private void Clear() { _condition = null; _restrictions = BindingRestrictions.Empty; _result = null; _initializations = null; _error = false; _treatRestrictionsAsConditions = false; }
internal void AddInitialization(Expression /*!*/ expression) { if (_initializations == null) { _initializations = new AstExpressions(); } _initializations.Add(expression); }
public AstExpressions /*!*/ GetSimpleArgumentExpressions() { int count = SimpleArgumentCount; var result = new AstExpressions(count); for (int i = 0, j = GetSimpleArgumentIndex(0); i < count; j++, i++) { result.Add(_args[j].Expression); } return(result); }
public override DynamicMetaObject /*!*/ Bind(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args) { Debug.Assert(args.Length > 1); var exprs = new AstExpressions(); exprs.Add(AstUtils.LightDynamic(_getMember, typeof(object), target.Expression)); exprs.Add(args.ToExpressions()); return(new DynamicMetaObject(AstUtils.LightDynamic(_setIndex, typeof(object), exprs), BindingRestrictions.Empty)); }
public override DynamicMetaObject /*!*/ FallbackInvoke(DynamicMetaObject /*!*/ target, DynamicMetaObject /*!*/[] /*!*/ args, DynamicMetaObject errorSuggestion) { AstExpressions exprs = new AstExpressions(); exprs.Add(target.Expression); exprs.Add(args.ToExpressions()); return(new DynamicMetaObject( AstUtils.LightDynamic(_context.MetaBinderFactory.InteropReturn(CallInfo), typeof(object), exprs), target.Restrictions.Merge(BindingRestrictions.Combine(args)) )); }
private AstExpressions/*!*/ MakeSimpleArgumentExpressionList(AstGenerator/*!*/ gen) { var args = new AstExpressions(); if (_expressions != null) { gen.TranformExpressions(_expressions, args); } if (_maplets != null) { args.Add(gen.TransformToHashConstructor(_maplets)); } return args; }
private AstExpressions /*!*/ MakeSimpleArgumentExpressionList(AstGenerator /*!*/ gen) { var args = new AstExpressions(); if (_expressions != null) { gen.TranformExpressions(_expressions, args); } if (_maplets != null) { args.Add(gen.TransformToHashConstructor(_maplets)); } return(args); }
private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, AstParameters /*!*/ parameters) { var result = new AstExpressions( ParameterCount + (_parameters.Optional.Length > 0 ? 1 : 0) + (_parameters.Unsplat != null ? 1 : 0) + (_parameters.Block != null ? 1 : 0) + 1 ); // TODO: we can skip parameters that are locals (need to be defined as parameters, not as #n): var paramsArray = HasFormalParametersInArray ? parameters[HiddenParameterCount] : null; int parameterIndex = 0; for (int i = 0; i < _parameters.Mandatory.Length; i++) { result.Add(_parameters.Mandatory[i].TransformWrite(gen, GetParameterAccess(parameters, paramsArray, parameterIndex))); parameterIndex++; } if (_parameters.Optional.Length > 0) { for (int i = 0; i < _parameters.Optional.Length; i++) { result.Add(_parameters.Optional[i].Left.TransformWrite(gen, GetParameterAccess(parameters, paramsArray, parameterIndex))); parameterIndex++; } result.Add(_parameters.TransformOptionalsInitialization(gen)); } if (_parameters.Unsplat != null) { // the last parameter is unsplat: result.Add(_parameters.Unsplat.TransformWrite(gen, parameters[parameters.Count - (_parameters.Block != null ? 2 : 1)])); } if (_parameters.Block != null) { result.Add(_parameters.Block.TransformWrite(gen, parameters[parameters.Count - 1])); parameterIndex++; } result.Add(AstUtils.Empty()); return(Ast.Block(result)); }
private void BuildCall(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue); if (metaBuilder.Error) { return; } metaBuilder.AddRestriction( Ast.Equal( Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), VersionProperty), Ast.Constant(_version) ) ); if (_function == IntPtr.Zero) { metaBuilder.SetError(Ast.Throw(new Func <Exception>(UninitializedFunctionError).Method.OpCall(), typeof(object))); return; } if (_signature.Length != actualArgs.Count) { metaBuilder.SetError(Ast.Throw(new Func <int, int, Exception>(InvalidParameterCountError).Method.OpCall( Ast.Constant(_signature.Length), Ast.Constant(actualArgs.Count)), typeof(object) )); return; } var calliArgs = new AstExpressions(); calliArgs.Add(Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), FunctionProperty)); for (int i = 0; i < actualArgs.Count; i++) { calliArgs.Add(MarshalArgument(metaBuilder, actualArgs[i], _signature[i])); } metaBuilder.Result = Ast.Call(EmitCalliStub(), calliArgs); // MRI returns 0 if void return type is given: if (_returnType == ArgType.None) { metaBuilder.Result = Ast.Block(metaBuilder.Result, AstUtils.Constant(0)); } }
internal static MSA.Expression /*!*/ YieldExpression( RubyContext /*!*/ context, ICollection <MSA.Expression> /*!*/ arguments, MSA.Expression splattedArgument, MSA.Expression rhsArgument, MSA.Expression blockArgument, MSA.Expression /*!*/ bfcVariable, MSA.Expression /*!*/ selfArgument) { Assert.NotNull(arguments, bfcVariable, selfArgument); bool hasArgumentArray; var opMethod = Methods.Yield(arguments.Count, splattedArgument != null, rhsArgument != null, out hasArgumentArray); var args = new AstExpressions(); foreach (var arg in arguments) { args.Add(AstUtils.Box(arg)); } if (hasArgumentArray) { args = new AstExpressions { Ast.NewArrayInit(typeof(object), args) }; } if (splattedArgument != null) { args.Add(AstUtils.LightDynamic(ExplicitSplatAction.Make(context), typeof(IList), splattedArgument)); } if (rhsArgument != null) { args.Add(AstUtils.Box(rhsArgument)); } args.Add(blockArgument != null ? AstUtils.Convert(blockArgument, typeof(Proc)) : AstFactory.NullOfProc); args.Add(AstUtils.Box(selfArgument)); args.Add(bfcVariable); return(Ast.Call(opMethod, args)); }
internal ReadOnlyCollection <Expression> /*!*/ GetCallSiteArguments(Expression /*!*/ targetExpression) { // context, target, arguments: var result = new AstExpressions(CallSiteArgumentCount); if (_hasScopeOrContextArg) { result.Add(_signature.HasScope ? MetaScope.Expression : MetaContext.Expression); } result.Add(targetExpression); for (int j = FirstArgumentIndex; j < _args.Length; j++) { result.Add(_args[j].Expression); } return(result.ToReadOnlyCollection()); }
public MSA.Expression /*!*/ CreateScope(MSA.Expression /*!*/ scopeVariable, MSA.Expression /*!*/ scopeInitializer, MSA.Expression /*!*/ body) { // #locals variable already assigned (in MakeClosureDefinition). // We need to initialize #closureN variables. if (_closures != null) { if (_closures.Count == 1) { return(Ast.Block(_hiddenVariables, Ast.Block( Ast.Assign( _closures[0], AstUtils.Convert(Methods.GetParentLocals.OpCall(Ast.Assign(scopeVariable, scopeInitializer)), _closures[0].Type) ), body ))); } else { var result = new AstExpressions(); MSA.Expression tempScope = DefineHiddenVariable("#s", typeof(RubyScope)); result.Add(Ast.Assign(scopeVariable, scopeInitializer)); for (int i = 0; i < _closures.Count; i++) { result.Add( Ast.Assign( _closures[i], AstUtils.Convert( Methods.GetLocals.OpCall(Ast.Assign(tempScope, Methods.GetParentScope.OpCall(i == 0 ? scopeVariable : tempScope))), _closures[i].Type ) ) ); } result.Add(body); return(Ast.Block(_hiddenVariables, result)); } } else { return(Ast.Block(_hiddenVariables, Ast.Block(Ast.Assign(scopeVariable, scopeInitializer), body))); } }
internal static MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen, AstExpressions /*!*/ rightValues, MSA.Expression splattedValue, bool doSplat) { Assert.NotNull(gen, rightValues); MSA.Expression result; // We need to distinguish various special cases here. // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment". // R(0,*)? bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null; // R(1,-)? bool rightOneNone = rightValues.Count == 1 && splattedValue == null; if (rightNoneSplat) { result = AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue); if (doSplat) { result = Methods.Splat.OpCall(result); } } else if (rightOneNone && doSplat) { result = rightValues[0]; } else { result = Methods.MakeArrayOpCall(rightValues); if (splattedValue != null) { result = Methods.SplatAppend.OpCall(result, AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue)); } } return(result); }
private static MSA.LambdaExpression /*!*/ CreateLambda(string /*!*/ name, AstParameters /*!*/ parameters, MSA.Expression /*!*/ body) { var result = MethodDispatcher.CreateRubyMethodLambda(body, name, parameters); if (result != null) { return(result); } // to many parameters for Func<> delegate -> use object[]: MSA.ParameterExpression array = Ast.Parameter(typeof(object[]), "#params"); var actualParameters = new AstParameters() { parameters[0], parameters[1], array }; parameters.RemoveAt(0); parameters.RemoveAt(1); var bodyWithParamInit = new AstExpressions(parameters.Count + 1); for (int i = 0; i < parameters.Count; i++) { bodyWithParamInit[i] = Ast.Assign(parameters[i], Ast.ArrayIndex(array, AstUtils.Constant(i))); } bodyWithParamInit[parameters.Count] = body; return(Ast.Lambda <Func <object, Proc, object[], object> >( Ast.Block( parameters, bodyWithParamInit ), name, actualParameters )); }
public MSA.Expression/*!*/ MakeLocalsStorage() { MSA.Expression result = Ast.Assign( _localsTuple, LiftedVisibleVariableCount == 0 ? (MSA.Expression)Ast.Constant(null, _localsTuple.Type) : Ast.New(_localsTuple.Type) ); if (_parameters != null) { var initializers = new AstExpressions(); initializers.Add(result); // parameters map to the initial elements of the array: for (int i = _firstClosureParam, j = 0; i < _parameters.Count; i++, j++) { initializers.Add(Ast.Assign(GetVariableAccessor(_localsTuple, j), _parameters[i])); } initializers.Add(_localsTuple); result = Ast.Block(initializers); } return result; }
public AstExpressions/*!*/ GetSimpleArgumentExpressions() { int count = SimpleArgumentCount; var result = new AstExpressions(count); for (int i = 0, j = GetSimpleArgumentsIndex(0); i < count; j++, i++) { result.Add(_args[j].Expression); } return result; }
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); }
internal AstExpressions/*!*/ TransformMapletsToExpressions(IList<Maplet>/*!*/ maplets, AstExpressions/*!*/ result) { Assert.NotNullItems(maplets); Assert.NotNull(result); foreach (Maplet entry in maplets) { result.Add(entry.Key.TransformRead(this)); result.Add(entry.Value.TransformRead(this)); } return result; }
private MSA.Expression/*!*/ TransformStatementsToExpression(Statements statements, bool toBoolean, bool positive) { if (statements == null || statements.Count == 0) { return toBoolean ? AstUtils.Constant(!positive) : AstUtils.Constant(null); } var last = toBoolean ? statements.Last.TransformCondition(this, positive) : statements.Last.TransformReadStep(this); if (statements.Count == 1) { return last; } var result = new AstExpressions(statements.Count); foreach (var statement in statements.AllButLast) { result.Add(statement.Transform(this)); } result.Add(last); return Ast.Block(result); }
private MSA.Expression/*!*/ TransformWrite(AstGenerator/*!*/ gen, AstExpressions/*!*/ rightValues, MSA.Expression splattedValue) { // We need to distinguish various special cases here. // Each of the bool variables defined below is true iff the corresponding special form of LHS/RHS occurs. // These flags drive the DLR AST being produced by this method. // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment". // L(0,-) not applicable Debug.Assert(!(_leftValues.Count == 0 && _unsplattedValue == null)); // L(1,-)? bool leftOneNone = _leftValues.Count == 1 && _unsplattedValue == null; // L(0,*)? bool leftNoneSplat = _leftValues.Count == 0 && _unsplattedValue != null; // R(0,*)? bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null; // R(1,-)? bool rightOneNone = rightValues.Count == 1 && splattedValue == null; // R(1,*)? bool rightOneSplat = rightValues.Count == 1 && splattedValue != null; // R(0,-) not applicable Debug.Assert(!(rightValues.Count == 0 && splattedValue == null)); MSA.Expression resultExpression; if (leftOneNone) { // L(1,-): // recurse right away (X) = RHS is equivalent to X = RHS: CompoundLeftValue compound = _leftValues[0] as CompoundLeftValue; if (compound != null) { return compound.TransformWrite(gen, rightValues, splattedValue); } if (rightOneSplat) { // R(1,*) resultExpression = Methods.SplatPair.OpCall( AstFactory.Box(rightValues[0]), Ast.Dynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue) ); } else { // case 1: R(1,-) // case 2: R(0,*) // case 3: otherwise resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, true /* Splat */); } return _leftValues[0].TransformWrite(gen, resultExpression); } bool optimizeReads = true; if (rightOneNone && !leftNoneSplat) { // R(1,-) && !L(0,*) resultExpression = Methods.Unsplat.OpCall( Ast.Dynamic(ConvertToArraySplatAction.Make(gen.Context), typeof(object), rightValues[0]) ); optimizeReads = false; } else { // case 1: R(0,*) = L // case 2: otherwise resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, false /* Unsplat */); optimizeReads = !rightNoneSplat; } int writesCount = _leftValues.Count + (_unsplattedValue != null ? 1 : 0); if (writesCount == 0) { return resultExpression; } var writes = new MSA.Expression[ 1 + // store result to a temp writesCount + 1 // load from the temp ]; int writeIndex = 0; MSA.Expression result = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList)); writes[writeIndex++] = Ast.Assign(result, resultExpression); MethodInfo itemGetter = typeof(IList).GetMethod("get_Item"); for (int i = 0; i < _leftValues.Count; i++) { MSA.Expression rvalue; if (optimizeReads) { if (i < rightValues.Count) { // unchecked get item: rvalue = Ast.Call(result, itemGetter, AstUtils.Constant(i)); } else if (splattedValue != null) { // checked get item: rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i)); } else { // missing item: rvalue = AstUtils.Constant(null); } } else { rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i)); } writes[writeIndex++] = _leftValues[i].TransformWrite(gen, rvalue); } // unsplatting the rest of rhs values into an array: if (_unsplattedValue != null) { // copies the rest of resulting array to the *LHS; // the resulting array contains splatted *RHS - no need for additional appending: MSA.Expression array = Methods.GetArraySuffix.OpCall(result, AstUtils.Constant(_leftValues.Count)); // assign the array (possibly empty) to *LHS: writes[writeIndex++] = _unsplattedValue.TransformWrite(gen, array); } writes[writeIndex++] = result; Debug.Assert(writes.Length == writeIndex); return AstFactory.Block(writes); }
internal void AddInitialization(Expression/*!*/ expression) { if (_initializations == null) { _initializations = new AstExpressions(); } _initializations.Add(expression); }
private MSA.Expression/*!*/ MakeParametersInitialization(AstGenerator/*!*/ gen, AstParameters/*!*/ parameters) { var result = new AstExpressions( ParameterCount + (_parameters.Optional.Length > 0 ? 1 : 0) + (_parameters.Unsplat != null ? 1 : 0) + (_parameters.Block != null ? 1 : 0) + 1 ); // TODO: we can skip parameters that are locals (need to be defined as parameters, not as #n): var paramsArray = HasFormalParametersInArray ? parameters[HiddenParameterCount] : null; int parameterIndex = 0; for (int i = 0; i < _parameters.Mandatory.Length; i++) { result.Add(_parameters.Mandatory[i].TransformWrite(gen, GetParameterAccess(parameters, paramsArray, parameterIndex))); parameterIndex++; } if (_parameters.Optional.Length > 0) { for (int i = 0; i < _parameters.Optional.Length; i++) { result.Add(_parameters.Optional[i].Left.TransformWrite(gen, GetParameterAccess(parameters, paramsArray, parameterIndex))); parameterIndex++; } result.Add(_parameters.TransformOptionalsInitialization(gen)); } if (_parameters.Unsplat != null) { // the last parameter is unsplat: result.Add(_parameters.Unsplat.TransformWrite(gen, parameters[parameters.Count - (_parameters.Block != null ? 2 : 1)])); } if (_parameters.Block != null) { result.Add(_parameters.Block.TransformWrite(gen, parameters[parameters.Count - 1])); parameterIndex++; } result.Add(AstUtils.Empty()); return Ast.Block(result); }
internal static MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen, AstExpressions/*!*/ rightValues, MSA.Expression splattedValue, bool doSplat) { Assert.NotNull(gen, rightValues); MSA.Expression result; // We need to distinguish various special cases here. // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment". // R(0,*)? bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null; // R(1,-)? bool rightOneNone = rightValues.Count == 1 && splattedValue == null; if (rightNoneSplat) { result = Ast.Dynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue); if (doSplat) { result = Methods.Splat.OpCall(result); } } else if (rightOneNone && doSplat) { result = rightValues[0]; } else { result = Methods.MakeArrayOpCall(rightValues); if (splattedValue != null) { result = Methods.SplatAppend.OpCall(result, Ast.Dynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue)); } } return result; }
internal AstExpressions /*!*/ TransformMapletsToExpressions(IList <Maplet> /*!*/ maplets, AstExpressions /*!*/ result) { Assert.NotNullItems(maplets); Assert.NotNull(result); foreach (Maplet entry in maplets) { result.Add(entry.Key.TransformRead(this)); result.Add(entry.Value.TransformRead(this)); } return(result); }
public MSA.Expression/*!*/ CreateScope(MSA.Expression/*!*/ scopeVariable, MSA.Expression/*!*/ scopeInitializer, MSA.Expression/*!*/ body) { // #locals variable already assigned (in MakeClosureDefinition). // We need to initialize #closureN variables. if (_closures != null) { if (_closures.Count == 1) { return Ast.Block(_hiddenVariables, Ast.Block( Ast.Assign( _closures[0], AstUtils.Convert(Methods.GetParentLocals.OpCall(Ast.Assign(scopeVariable, scopeInitializer)), _closures[0].Type) ), body )); } else { var result = new AstExpressions(); MSA.Expression tempScope = DefineHiddenVariable("#s", typeof(RubyScope)); result.Add(Ast.Assign(scopeVariable, scopeInitializer)); for (int i = 0; i < _closures.Count; i++) { result.Add( Ast.Assign( _closures[i], AstUtils.Convert( Methods.GetLocals.OpCall(Ast.Assign(tempScope, Methods.GetParentScope.OpCall(i == 0 ? scopeVariable : tempScope))), _closures[i].Type ) ) ); } result.Add(body); return Ast.Block(_hiddenVariables, result); } } else { return Ast.Block(_hiddenVariables, Ast.Block(Ast.Assign(scopeVariable, scopeInitializer), body)); } }
private void BuildCall(MetaObjectBuilder/*!*/ metaBuilder, CallArguments/*!*/ args, string/*!*/ name) { var actualArgs = RubyOverloadResolver.NormalizeArguments(metaBuilder, args, 0, Int32.MaxValue); if (metaBuilder.Error) { return; } metaBuilder.AddRestriction( Ast.Equal( Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), VersionProperty), Ast.Constant(_version) ) ); if (_function == IntPtr.Zero) { metaBuilder.SetError(Ast.Throw(new Func<Exception>(UninitializedFunctionError).Method.OpCall(), typeof(object))); return; } if (_signature.Length != actualArgs.Count) { metaBuilder.SetError(Ast.Throw(new Func<int, int, Exception>(InvalidParameterCountError).Method.OpCall( Ast.Constant(_signature.Length), Ast.Constant(actualArgs.Count)), typeof(object) )); return; } var calliArgs = new AstExpressions(); calliArgs.Add(Ast.Property(Ast.Convert(args.TargetExpression, typeof(Win32API)), FunctionProperty)); for (int i = 0; i < actualArgs.Count; i++) { calliArgs.Add(MarshalArgument(metaBuilder, actualArgs[i], _signature[i])); } metaBuilder.Result = Ast.Call(EmitCalliStub(), calliArgs); // MRI returns 0 if void return type is given: if (_returnType == ArgType.None) { metaBuilder.Result = Ast.Block(metaBuilder.Result, AstUtils.Constant(0)); } }
private MSA.Expression /*!*/ TransformWrite(AstGenerator /*!*/ gen, AstExpressions /*!*/ rightValues, MSA.Expression splattedValue) { // We need to distinguish various special cases here. // Each of the bool variables defined below is true iff the corresponding special form of LHS/RHS occurs. // These flags drive the DLR AST being produced by this method. // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment". // L(0,-) not applicable Debug.Assert(!(_leftValues.Count == 0 && _unsplattedValue == null)); // L(1,-)? bool leftOneNone = _leftValues.Count == 1 && _unsplattedValue == null; // L(0,*)? bool leftNoneSplat = _leftValues.Count == 0 && _unsplattedValue != null; // R(0,*)? bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null; // R(1,-)? bool rightOneNone = rightValues.Count == 1 && splattedValue == null; // R(1,*)? bool rightOneSplat = rightValues.Count == 1 && splattedValue != null; // R(0,-) not applicable Debug.Assert(!(rightValues.Count == 0 && splattedValue == null)); MSA.Expression resultExpression; if (leftOneNone) { // L(1,-): // recurse right away (X) = RHS is equivalent to X = RHS: CompoundLeftValue compound = _leftValues[0] as CompoundLeftValue; if (compound != null) { return(compound.TransformWrite(gen, rightValues, splattedValue)); } if (rightOneSplat) { // R(1,*) resultExpression = Methods.SplatPair.OpCall( AstUtils.Box(rightValues[0]), AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), splattedValue) ); } else { // case 1: R(1,-) // case 2: R(0,*) // case 3: otherwise resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, true /* Splat */); } return(_leftValues[0].TransformWrite(gen, resultExpression)); } bool optimizeReads = true; if (rightOneNone && !leftNoneSplat) { // R(1,-) && !L(0,*) resultExpression = Methods.Unsplat.OpCall( AstUtils.LightDynamic(ConvertToArraySplatAction.Make(gen.Context), rightValues[0]) ); optimizeReads = false; } else { // case 1: R(0,*) = L // case 2: otherwise resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, false /* Unsplat */); optimizeReads = !rightNoneSplat; } var writes = new AstBlock(); MSA.Expression result = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList)); writes.Add(Ast.Assign(result, resultExpression)); MethodInfo itemGetter = Methods.IList_get_Item; for (int i = 0; i < _leftValues.Count; i++) { MSA.Expression rvalue; if (optimizeReads) { if (i < rightValues.Count) { // unchecked get item: rvalue = Ast.Call(result, itemGetter, AstUtils.Constant(i)); } else if (splattedValue != null) { // checked get item: rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i)); } else { // missing item: rvalue = AstUtils.Constant(null); } } else { rvalue = Methods.GetArrayItem.OpCall(result, AstUtils.Constant(i)); } writes.Add(_leftValues[i].TransformWrite(gen, rvalue)); } // unsplatting the rest of rhs values into an array: if (_unsplattedValue != null) { // copies the rest of resulting array to the *LHS; // the resulting array contains splatted *RHS - no need for additional appending: MSA.Expression array = Methods.GetArraySuffix.OpCall(result, AstUtils.Constant(_leftValues.Count)); // assign the array (possibly empty) to *LHS: writes.Add(_unsplattedValue.TransformWrite(gen, array)); } writes.Add(result); return(writes); }
public override DynamicMetaObject/*!*/ FallbackInvoke(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args, DynamicMetaObject errorSuggestion) { AstExpressions exprs = new AstExpressions(); exprs.Add(target.Expression); exprs.Add(args.ToExpressions()); return new DynamicMetaObject( AstUtils.LightDynamic(_context.MetaBinderFactory.InteropReturn(CallInfo), typeof(object), exprs), target.Restrictions.Merge(BindingRestrictions.Combine(args)) ); }
public static MSA.Expression/*!*/ OpCall(this MethodInfo/*!*/ method, AstExpressions/*!*/ args) { return MSA.Expression.Call(method, args); }
internal ReadOnlyCollection<Expression>/*!*/ GetCallSiteArguments(Expression/*!*/ targetExpression) { // context, target, arguments: var result = new AstExpressions(CallSiteArgumentCount); if (_hasScopeOrContextArg) { result.Add(_signature.HasScope ? MetaScope.Expression : MetaContext.Expression); } result.Add(targetExpression); for (int j = FirstArgumentIndex; j < _args.Length; j++) { result.Add(_args[j].Expression); } return result.ToReadOnlyCollection(); }
internal static MSA.Expression/*!*/ YieldExpression( RubyContext/*!*/ context, AstExpressions/*!*/ arguments, MSA.Expression splattedArgument, MSA.Expression rhsArgument, MSA.Expression/*!*/ bfcVariable, MSA.Expression/*!*/ selfArgument) { Assert.NotNull(arguments, bfcVariable, selfArgument); bool hasArgumentArray; var opMethod = Methods.Yield(arguments.Count, splattedArgument != null, rhsArgument != null, out hasArgumentArray); var args = new AstExpressions(); foreach (var arg in arguments) { args.Add(AstUtils.Box(arg)); } if (hasArgumentArray) { args = new AstExpressions { Ast.NewArrayInit(typeof(object), args) }; } if (splattedArgument != null) { args.Add(AstUtils.LightDynamic(SplatAction.Make(context), typeof(IList), splattedArgument)); } if (rhsArgument != null) { args.Add(AstUtils.Box(rhsArgument)); } args.Add(AstUtils.Box(selfArgument)); args.Add(bfcVariable); return Ast.Call(opMethod, args); }
public static MSA.Expression /*!*/ OpCall(this MethodInfo /*!*/ method, AstExpressions /*!*/ args) { return(MSA.Expression.Call(method, args)); }
public override DynamicMetaObject/*!*/ Bind(DynamicMetaObject/*!*/ target, DynamicMetaObject/*!*/[]/*!*/ args) { Debug.Assert(args.Length > 1); var exprs = new AstExpressions(); exprs.Add(AstUtils.LightDynamic(_getMember, typeof(object), target.Expression)); exprs.Add(args.ToExpressions()); return new DynamicMetaObject(AstUtils.LightDynamic(_setIndex, typeof(object), exprs), BindingRestrictions.Empty); }
internal AstExpressions/*!*/ TranformExpressions(IList<Expression>/*!*/ arguments, AstExpressions/*!*/ result) { Assert.NotNullItems(arguments); Assert.NotNull(result); foreach (Expression arg in arguments) { result.Add(arg.TransformRead(this)); } return result; }
internal AstExpressions /*!*/ TranformExpressions(IList <Expression> /*!*/ arguments, AstExpressions /*!*/ result) { Assert.NotNullItems(arguments); Assert.NotNull(result); foreach (Expression arg in arguments) { result.Add(arg.TransformRead(this)); } return(result); }
internal MSA.Expression/*!*/ TransformStatements(MSA.Expression prologue, Statements/*!*/ statements, MSA.Expression epilogue, ResultOperation resultOperation) { Assert.NotNull(statements); int count = statements.Count + (prologue != null ? 1 : 0) + (epilogue != null ? 1 : 0); if (count == 0) { if (resultOperation.IsIgnore) { return AstUtils.Empty(); } else if (resultOperation.Variable != null) { return Ast.Assign(resultOperation.Variable, AstUtils.Constant(null, resultOperation.Variable.Type)); } else { return Ast.Return(CurrentFrame.ReturnLabel, AstUtils.Constant(null)); } } else if (count == 1) { if (prologue != null) { return prologue; } if (epilogue != null) { return epilogue; } if (resultOperation.IsIgnore) { return statements.First.Transform(this); } else { return statements.First.TransformResult(this, resultOperation); } } else { var result = new AstExpressions(count + 1); if (prologue != null) { result.Add(prologue); } // transform all but the last statement if it is an expression stmt: foreach (var statement in statements.AllButLast) { result.Add(statement.Transform(this)); } if (statements.Count > 0) { if (resultOperation.IsIgnore) { result.Add(statements.Last.Transform(this)); } else { result.Add(statements.Last.TransformResult(this, resultOperation)); } } if (epilogue != null) { result.Add(epilogue); } result.Add(AstUtils.Empty()); return Ast.Block(result); } }
private static MSA.LambdaExpression/*!*/ CreateLambda(string/*!*/ name, AstParameters/*!*/ parameters, MSA.Expression/*!*/ body) { var result = MethodDispatcher.CreateRubyMethodLambda(body, name, parameters); if (result != null) { return result; } // to many parameters for Func<> delegate -> use object[]: MSA.ParameterExpression array = Ast.Parameter(typeof(object[]), "#params"); var actualParameters = new AstParameters() { parameters[0], parameters[1], array }; parameters.RemoveAt(0); parameters.RemoveAt(1); var bodyWithParamInit = new AstExpressions(parameters.Count + 1); for (int i = 0; i < parameters.Count; i++) { bodyWithParamInit[i] = Ast.Assign(parameters[i], Ast.ArrayIndex(array, AstUtils.Constant(i))); } bodyWithParamInit[parameters.Count] = body; return Ast.Lambda<Func<object, Proc, object[], object>>( Ast.Block( parameters, bodyWithParamInit ), name, actualParameters ); }
public static AstExpressions/*!*/ Expressions(MSA.Expression/*!*/ expression) { var result = new AstExpressions(); result.Add(expression); return result; }