Пример #1
0
        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));
        }
Пример #2
0
        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);
        }
Пример #3
0
 private void Clear() {
     _condition = null;
     _restrictions = BindingRestrictions.Empty;
     _result = null;
     _initializations = null;
     _error = false;
     _treatRestrictionsAsConditions = false;
 }
Пример #4
0
        internal void AddInitialization(Expression /*!*/ expression)
        {
            if (_initializations == null)
            {
                _initializations = new AstExpressions();
            }

            _initializations.Add(expression);
        }
Пример #5
0
 private void Clear()
 {
     _condition       = null;
     _restrictions    = BindingRestrictions.Empty;
     _result          = null;
     _initializations = null;
     _error           = false;
     _treatRestrictionsAsConditions = false;
 }
Пример #6
0
        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);
        }
Пример #7
0
            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));
            }
Пример #8
0
            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))
                           ));
            }
Пример #9
0
        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;
        }
Пример #10
0
        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);
        }
Пример #11
0
        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));
        }
Пример #12
0
        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));
            }
        }
Пример #13
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));
        }
Пример #14
0
        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());
        }
Пример #15
0
        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)));
            }
        }
Пример #16
0
        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);
        }
Пример #17
0
        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
                       ));
        }
Пример #18
0
        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;
        }
Пример #19
0
 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;
 }
Пример #20
0
        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);
        }
Пример #21
0
        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;
        }
Пример #22
0
        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);
        }
Пример #23
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(
                        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);
        }
Пример #24
0
        internal void AddInitialization(Expression/*!*/ expression) {
            if (_initializations == null) {
                _initializations = new AstExpressions();
            }

            _initializations.Add(expression);
        }
Пример #25
0
        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);
        }
Пример #26
0
        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;
        }
Пример #27
0
        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);
        }
Пример #28
0
        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));
            }
        }
Пример #29
0
        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));
            }
        }
Пример #30
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);
        }
Пример #31
0
            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))
                );
            }
Пример #32
0
 public static MSA.Expression/*!*/ OpCall(this MethodInfo/*!*/ method, AstExpressions/*!*/ args) {
     return MSA.Expression.Call(method, args);
 }
Пример #33
0
        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();
        }
Пример #34
0
        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);
        }
Пример #35
0
 public static MSA.Expression /*!*/ OpCall(this MethodInfo /*!*/ method, AstExpressions /*!*/ args)
 {
     return(MSA.Expression.Call(method, args));
 }
Пример #36
0
            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);
            }
Пример #37
0
        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;
        }
Пример #38
0
        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);
        }
Пример #39
0
        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);
            }
        }
Пример #40
0
        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
            );
        }
Пример #41
0
 public static AstExpressions/*!*/ Expressions(MSA.Expression/*!*/ expression) {
     var result = new AstExpressions();
     result.Add(expression);
     return result;
 }