private void TransformBody(AstGenerator/*!*/ gen) {
            ScopeBuilder scope = DefineLocals();

            var scopeVariable = gen.TopLevelScope.Builder.DefineHiddenVariable("#scope", typeof(RubyScope));
            
            gen.EnterFileInitializer(
                scope,
                gen.TopLevelScope.SelfVariable,
                scopeVariable
            );

            // visit nested initializers depth-first:
            var body = gen.TransformStatements(_statements, ResultOperation.Ignore);

            gen.LeaveFileInitializer();

            gen.AddFileInitializer(
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateFileInitializerScope.OpCall(
                        scope.MakeLocalsStorage(), 
                        scope.GetVariableNamesExpression(), 
                        gen.TopLevelScope.RuntimeScopeVariable
                    ),
                    body
                )
            );
        }
        internal static MSA.Expression/*!*/ TransformConcatentation(AstGenerator/*!*/ gen, List<Expression>/*!*/ parts, 
            Func<string, MethodInfo>/*!*/ opFactory, MSA.Expression additionalArg) {

            var opSuffix = new StringBuilder(Math.Min(parts.Count, 4));

            List<MSA.Expression> merged = ConcatLiteralsAndTransform(gen, parts, opSuffix);

            if (merged.Count <= RubyOps.MakeStringParamCount) {
                if (merged.Count == 0) {
                    merged.Add(Ast.Constant(String.Empty));
                    opSuffix.Append(RubyOps.SuffixBinary);
                }

                if (opSuffix.IndexOf(RubyOps.SuffixEncoded) != -1) {
                    merged.Add(Ast.Constant(RubyEncoding.GetCodePage(gen.Encoding)));
                }

                if (additionalArg != null) {
                    merged.Add(additionalArg);
                }

                return opFactory(opSuffix.ToString()).OpCall(merged);
            } else {
                var paramArray = Ast.NewArrayInit(typeof(object), merged);
                var codePage = Ast.Constant(RubyEncoding.GetCodePage(gen.Encoding));
                
                return (additionalArg != null) ?
                    opFactory("N").OpCall(paramArray, codePage, additionalArg) :
                    opFactory("N").OpCall(paramArray, codePage);
            } 
        }
Beispiel #3
0
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     return Methods.MatchString.OpCall(
         Ast.Dynamic(ConvertToStrAction.Make(gen.Context), typeof(MutableString), _expression.Transform(gen)),
         _regex.Transform(gen),
         gen.CurrentScopeVariable
     );
 }
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     return AstFactory.Condition(
         Methods.IsFalse.OpCall(AstFactory.Box(_condition.TransformRead(gen))),
         gen.TransformStatementsToExpression(_statements),
         gen.TransformStatementsToExpression(_elseClause != null ? _elseClause.Statements : null)
     );
 }
        internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
            string setterName = _memberName + "=";

            MSA.Expression transformedLeftTarget = _leftTarget.TransformRead(gen);
            MSA.Expression transformedRight = _right.TransformRead(gen);

            MSA.Expression leftTemp = gen.CurrentScope.DefineHiddenVariable(String.Empty, transformedLeftTarget.Type);

            bool leftIsSelf = _leftTarget.NodeType == NodeTypes.SelfReference;

            // lhs &&= rhs  -->  left.member && (left.member = rhs)
            // lhs ||= rhs  -->  left.member || (left.member = rhs)
            if (Operation == Symbols.And || Operation == Symbols.Or) {
                MSA.Expression leftMemberRead = MethodCall.TransformRead(this, gen, false, _memberName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, null);
                MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, leftTemp, null, null, null, transformedRight);

                if (Operation == Symbols.And) {
                    return AndExpression.TransformRead(gen, leftMemberRead, transformedWrite);
                } else {
                    return OrExpression.TransformRead(gen, leftMemberRead, transformedWrite);
                }
            } else {
                // left.member= left.member().op(right)
                MSA.Expression leftMemberRead = MethodCall.TransformRead(this, gen, false, _memberName, leftTemp, null, null, null, null);
                MSA.Expression operationCall = MethodCall.TransformRead(this, gen, false, Operation, leftMemberRead, null, null, transformedRight, null);
                MSA.Expression transformedWrite = MethodCall.TransformRead(this, gen, leftIsSelf, setterName, Ast.Assign(leftTemp, transformedLeftTarget), null, null, null, operationCall);
                return transformedWrite;
            }
        }
 internal override MSA.Expression/*!*/ Transform(AstGenerator/*!*/ gen) {
     return AstUtils.IfThenElse(
         _condition.TransformCondition(gen, !_negateCondition), 
         _body.Transform(gen),
         _elseStatement != null ? _elseStatement.Transform(gen) : AstUtils.Empty()
     );
 }
Beispiel #7
0
        internal MSA.Expression/*!*/ TransformOptionalsInitialization(AstGenerator/*!*/ gen) {
            Assert.NotNull(gen);

            if (_optional.Length == 0) {
                return AstUtils.Empty();
            }

            MSA.Expression singleton = gen.CurrentScope.DefineHiddenVariable("#default", typeof(object));

            MSA.Expression result = AstUtils.Empty();
            for (int i = 0; i < _optional.Length; i++) {
                result = AstUtils.IfThen(
                    Ast.Equal(_optional[i].Left.TransformRead(gen), singleton),
                    Ast.Block(
                        result,
                        _optional[i].TransformRead(gen) // assignment
                    )
                );
            }
            
            return Ast.Block(
                Ast.Assign(singleton, Ast.Field(null, Fields.DefaultArgument)),
                result,
                AstUtils.Empty()
            );
        }
Beispiel #8
0
        internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {

            MSA.Expression result;

            int i = _elseIfClauses.Count - 1;

            if (i >= 0 && _elseIfClauses[i].Condition == null) {
                // ... else body end
                result = gen.TransformStatementsToExpression(_elseIfClauses[i].Statements);
                i--;
            } else {
                // no else clause => the result of the if-expression is nil:
                result = AstUtils.Constant(null);
            }

            while (i >= 0) {
                // emit: else (if (condition) body else result)
                result = AstFactory.Condition(
                    _elseIfClauses[i].Condition.TransformCondition(gen, true),
                    gen.TransformStatementsToExpression(_elseIfClauses[i].Statements),
                    result
                );
                i--;
            }

            // if (condition) body else result
            return AstFactory.Condition(
                _condition.TransformCondition(gen, true),
                gen.TransformStatementsToExpression(_body),
                result
            );
        }
Beispiel #9
0
 MSA.Expression/*!*/ StringConstructor.IFactory.CreateExpressionN(AstGenerator/*!*/ gen, IEnumerable<MSA.Expression>/*!*/ args) {
     return Methods.CreateRegex("N").OpCall(
         Ast.NewArrayInit(typeof(MutableString), args),
         AstUtils.Constant(_options), 
         AstUtils.Constant(new StrongBox<RubyRegex>(null))
     );
 }
Beispiel #10
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Break
        internal override MSA.Expression/*!*/ Transform(AstGenerator/*!*/ gen) {

            MSA.Expression transformedReturnValue = TransformReturnValue(gen);

            // eval:
            if (gen.CompilerOptions.IsEval) {
                return Methods.EvalBreak.OpCall(gen.CurrentRfcVariable, AstFactory.Box(transformedReturnValue));
            }

            // loop:
            if (gen.CurrentLoop != null) {
                return Ast.Block(
                    Ast.Assign(
                        gen.CurrentLoop.ResultVariable,
                        Ast.Convert(transformedReturnValue, gen.CurrentLoop.ResultVariable.Type)
                    ),
                    Ast.Break(gen.CurrentLoop.BreakLabel),
                    Ast.Empty()
                );
            }

            // block:
            if (gen.CurrentBlock != null) {
                return gen.Return(Methods.BlockBreak.OpCall(gen.CurrentBlock.BfcVariable, AstFactory.Box(transformedReturnValue)));
            }

            // primary frame:
            return Methods.MethodBreak.OpCall(AstFactory.Box(transformedReturnValue));
        }
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     return AstFactory.Condition(
         _condition.TransformReadBoolean(gen, true),
         _trueExpression.TransformRead(gen),
         _falseExpression.TransformRead(gen)
     );
 }
Beispiel #12
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Next
        /*!*/
        internal override MSA.Expression Transform(AstGenerator/*!*/ gen)
        {
            MSA.Expression transformedReturnValue = TransformReturnValue(gen);

            // eval:
            if (gen.CompilerOptions.IsEval) {
                return Methods.EvalNext.OpCall(gen.CurrentScopeVariable, AstUtils.Box(transformedReturnValue));
            }

            // loop:
            if (gen.CurrentLoop != null) {
                return Ast.Block(
                    transformedReturnValue, // evaluate for side-effects
                    Ast.Continue(gen.CurrentLoop.ContinueLabel),
                    AstUtils.Empty()
                );
            }

            // block:
            if (gen.CurrentBlock != null) {
                return gen.Return(transformedReturnValue);
            }

            // method:
            return Methods.MethodNext.OpCall(gen.CurrentScopeVariable, AstUtils.Box(transformedReturnValue));
        }
Beispiel #13
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Yield
        internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
            MSA.Expression bfcVariable = gen.CurrentScope.DefineHiddenVariable("#yielded-bfc", typeof(BlockParam));
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#result", typeof(object));
            
            MSA.Expression postYield;

            if (gen.CompilerOptions.IsEval) {
                // eval:
                postYield = Methods.EvalYield.OpCall(gen.CurrentScopeVariable, bfcVariable, resultVariable);
            } else if (gen.CurrentBlock != null) {
                // block:
                postYield = Methods.BlockYield.OpCall(gen.CurrentScopeVariable, gen.CurrentBlock.BfcVariable, bfcVariable, resultVariable);
            } else {
                // method:
                postYield = Methods.MethodYield.OpCall(gen.CurrentScopeVariable, bfcVariable, resultVariable);
            }

            return new AstBlock {
                gen.DebugMarker("#RB: yield begin"),

                Ast.Assign(bfcVariable, Methods.CreateBfcForYield.OpCall(gen.MakeMethodBlockParameterRead())),

                Ast.Assign(
                    resultVariable, 
                    (Arguments ?? Arguments.Empty).TransformToYield(gen, bfcVariable, gen.MakeMethodBlockParameterSelfRead())
                ),

                AstUtils.IfThen(postYield, gen.Return(resultVariable)),

                gen.DebugMarker("#RB: yield end"),

                resultVariable
            };
        }
Beispiel #14
0
        private MSA.Expression/*!*/ TransformBody(AstGenerator/*!*/ gen, MSA.Expression/*!*/ methodDefinitionVariable) {
            string encodedName = RubyExceptionData.EncodeMethodName(gen.SourceUnit, _name, Location);
            
            ScopeBuilder scope = new ScopeBuilder();
            MSA.Expression parentScope = gen.CurrentScopeVariable;

            MSA.ParameterExpression[] parameters = DefineParameters(gen, scope);
            MSA.Expression currentMethodVariable = scope.DefineHiddenVariable("#method", typeof(RubyMethodInfo));
            MSA.Expression rfcVariable = scope.DefineHiddenVariable("#rfc", typeof(RuntimeFlowControl));
            MSA.Expression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyMethodScope));
            MSA.Expression selfParameter = parameters[0];
            MSA.Expression blockParameter = parameters[1];

            gen.EnterMethodDefinition(
                scope,
                selfParameter,
                scopeVariable,
                blockParameter,
                rfcVariable,
                currentMethodVariable,
                _name,
                _parameters
            );

            DefinedScope.TransformLocals(scope);

            MSA.ParameterExpression unwinder = scope.DefineHiddenVariable("#unwinder", typeof(MethodUnwinder));

            MSA.Expression body = AstFactory.MakeUserMethodBody(
                gen, Location.End.Line,
                blockParameter,
                rfcVariable,
                unwinder,
                Ast.Block(
                    Ast.Assign(currentMethodVariable, methodDefinitionVariable),

                    Ast.Assign(scopeVariable, Methods.CreateMethodScope.OpCall(
                        scope.VisibleVariables(), parentScope, currentMethodVariable, rfcVariable, selfParameter, blockParameter)
                    ),
                
                    _parameters.TransformOptionalsInitialization(gen),
                    gen.TraceEnabled ? Methods.TraceMethodCall.OpCall(scopeVariable, Ast.Convert(AstUtils.Constant(gen.SourceUnit.Path), typeof(string)), AstUtils.Constant(Location.Start.Line)) : AstUtils.Empty(),
                    Body.TransformResult(gen, ResultOperation.Return),
                    AstUtils.Empty()
                ),
                ResultOperation.Return,
                (gen.Profiler != null) ? gen.Profiler.GetTickIndex(encodedName) : -1,
                (gen.Profiler != null) ? scope.DefineHiddenVariable("#stamp", typeof(long)) : null,
                gen.ReturnLabel
            );

            body = gen.AddReturnTarget(scope.CreateScope(body));
            gen.LeaveMethodDefinition();

            return CreateLambda(
                encodedName, 
                parameters, 
                body
            );
        }
Beispiel #15
0
 MSA.Expression/*!*/ StringConstructor.IFactory.CreateExpressionM(AstGenerator/*!*/ gen, MSAst.ExpressionCollectionBuilder/*!*/ args) {
     string suffix = new String('M', args.Count);
     args.Add(gen.Encoding.Expression);
     args.Add(AstUtils.Constant(_options));
     args.Add(AstUtils.Constant(new StrongBox<RubyRegex>(null)));
     return Methods.CreateRegex(suffix).OpCall(args);
 }
Beispiel #16
0
        /*!*/
        internal override MSA.Expression TransformWriteVariable(AstGenerator/*!*/ gen, MSA.Expression/*!*/ rightValue)
        {
            Assert.NotNull(gen, rightValue);

            // no-op
            return rightValue;
        }
Beispiel #17
0
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     return AstFactory.Condition(
         _condition.TransformCondition(gen, false),            
         gen.TransformStatementsToExpression(_statements),
         gen.TransformStatementsToExpression(_elseClause != null ? _elseClause.Statements : null)
     );
 }
Beispiel #18
0
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     return Ast.Condition(
         _condition.TransformReadBoolean(gen, !_negateCondition),
         AstUtils.Box(_body.TransformRead(gen)),
         (_elseStatement != null) ? AstUtils.Box(_elseStatement.TransformRead(gen)) : (MSA.Expression)AstUtils.Constant(null)
     );
 }
Beispiel #19
0
 internal override MSA.Expression/*!*/ TransformWriteVariable(AstGenerator/*!*/ gen, MSA.Expression/*!*/ rightValue) {
     if (gen.CompilerOptions.IsEval || gen.GetCurrentNonSingletonModule() != null) {
         return Methods.SetClassVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name));
     } else {
         return Methods.SetObjectClassVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name));
     }
 }
Beispiel #20
0
        // arguments: complex arguments (expressions, maplets, splat, block) 
        // singleArgument: siple argument (complex are not used)
        // assignmentRhsArgument: rhs of the assignment: target.method=(rhs)
        internal static MSA.Expression/*!*/ TransformRead(Expression/*!*/ node, AstGenerator/*!*/ gen, bool hasImplicitSelf, 
            string/*!*/ methodName, MSA.Expression/*!*/ transformedTarget,
            Arguments arguments, Block block, MSA.Expression singleArgument, MSA.Expression assignmentRhsArgument) {

            Debug.Assert(assignmentRhsArgument == null || block == null, "Block not allowed in assignment");
            Debug.Assert(singleArgument == null || arguments == null && assignmentRhsArgument == null);
            Assert.NotNull(gen, transformedTarget);
            Assert.NotEmpty(methodName);

            // Pass args in this order:
            // 1. instance
            // 2. block (if present)
            // 3. passed args: normal args, maplets, array
            // 4. RHS of assignment (if present)

            MSA.Expression blockArgVariable;
            MSA.Expression transformedBlock;

            if (block != null) {
                blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#block-def", typeof(Proc));
                transformedBlock = block.Transform(gen);
            } else {
                blockArgVariable = transformedBlock = null;
            }

            var siteBuilder = new CallSiteBuilder(gen, transformedTarget, blockArgVariable);

            if (arguments != null) {
                arguments.TransformToCall(gen, siteBuilder);
            } else if (singleArgument != null) {
                siteBuilder.Add(singleArgument);
            }

            MSA.Expression rhsVariable = null;
            if (assignmentRhsArgument != null) {
                rhsVariable = gen.CurrentScope.DefineHiddenVariable("#rhs", assignmentRhsArgument.Type);
                siteBuilder.RhsArgument = Ast.Assign(rhsVariable, assignmentRhsArgument);
            }

            var dynamicSite = siteBuilder.MakeCallAction(methodName, hasImplicitSelf);
#if FEATURE_CALL_SITE_TRACER
            if (gen.Context.CallSiteCreated != null) {
                gen.Context.CallSiteCreated(node, dynamicSite);
            }
#endif

            MSA.Expression result = gen.DebugMark(dynamicSite, methodName);

            if (block != null) {
                result = gen.DebugMark(MakeCallWithBlockRetryable(gen, result, blockArgVariable, transformedBlock, block.IsDefinition),
                    "#RB: method call with a block ('" + methodName + "')");
            }

            if (assignmentRhsArgument != null) {
                result = Ast.Block(result, rhsVariable);
            }

            return result;
        }
Beispiel #21
0
 private static MethodInfo/*!*/ GetOp(AstGenerator/*!*/ gen, int/*!*/ opKind) {
     switch (opKind) {
         case OpTryGet: return Methods.TryGetClassVariable;
         case OpGet: return Methods.GetClassVariable;
         case OpIsDefined: return Methods.IsDefinedClassVariable;
         default: throw Assert.Unreachable;
     }
 }
Beispiel #22
0
        private MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen, int/*!*/ opKind) {
            // eval or in a non-singleton module/class declaration 
            // -> we find the right scope at runtime by walking the hierarchy
            // otherwise
            // -> variable is on Object

            return GetOp(gen, opKind).OpCall(gen.CurrentScopeVariable, AstUtils.Constant(Name));
        }
Beispiel #23
0
 internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
     if (_isCondition) {
         return TransformReadCondition(gen);
     } else {
         return (_isExclusive ? Methods.CreateExclusiveRange : Methods.CreateInclusiveRange).
             OpCall(gen.CurrentScopeVariable, AstFactory.Box(_begin.TransformRead(gen)), AstFactory.Box(_end.TransformRead(gen)));
     }
 }
Beispiel #24
0
 /*!*/
 internal MSA.Expression Transform(AstGenerator/*!*/ gen)
 {
     if (_value is string) {
         return Ast.Constant(_value, typeof(string));
     } else {
         return Methods.ConvertSymbolToClrString.OpCall(((StringConstructor)_value).TransformRead(gen));
     }
 }
Beispiel #25
0
 internal override MSA.Expression/*!*/ Transform(AstGenerator/*!*/ gen) {
     Assert.NotNull(gen);
     return Ast.Dynamic(
         ConvertToProcAction.Instance,
         typeof(Proc),
         gen.CurrentScopeVariable, _expression.TransformRead(gen)
     );
 }
Beispiel #26
0
 internal override MSA.Expression/*!*/ Transform(AstGenerator/*!*/ gen) {
     MSA.Expression[] result = new MSA.Expression[_items.Count + 1];
     for (int i = 0; i < _items.Count; i++) {
         result[i] = Methods.UndefineMethod.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(_items[i].Name));
     }
     result[_items.Count] = AstUtils.Empty();
     return Ast.Block(result);
 }
        internal override MSA.Expression/*!*/ TransformRead(AstGenerator/*!*/ gen) {
            var result = StringConstructor.TransformConcatentation(gen, _pattern, Methods.CreateRegex, Ast.Constant(_options));

            if (_isCondition) {
                result = Methods.MatchLastInputLine.OpCall(result, gen.CurrentScopeVariable);
            }

            return result;
        }
Beispiel #28
0
 internal override MSA.Expression/*!*/ TransformWriteVariable(AstGenerator/*!*/ gen, MSA.Expression/*!*/ rightValue) {
     if (_transformed != null) {
         // static lookup:
         return Ast.Assign(_transformed, AstUtils.Convert(rightValue, _transformed.Type));
     } else {
         // dynamic lookup:
         return Methods.SetLocalVariable.OpCall(AstFactory.Box(rightValue), gen.CurrentScopeVariable, AstUtils.Constant(Name));
     }
 }
Beispiel #29
0
 internal override string/*!*/ GetNodeName(AstGenerator/*!*/ gen) {
     if (_value == null) {
         return "nil";
     } else if (_value is bool) {
         return (bool)_value ? "true" : "false";
     } else {
         return base.GetNodeName(gen);
     }
 }
Beispiel #30
0
 internal override MSA.Expression/*!*/ TransformReadVariable(AstGenerator/*!*/ gen, bool tryRead) {
     if (_transformed != null) {
         // static lookup:
         return _transformed;
     } else {
         // dynamic lookup:
         return Methods.GetLocalVariable.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(Name));
     }
 }
Beispiel #31
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            Assert.NotNull(gen);

            if (_maplets != null)
            {
                return(gen.MakeHashOpCall(gen.TransformMapletsToExpressions(_maplets)));
            }
            else if (_expressions != null)
            {
                return(gen.MakeHashOpCall(gen.TranformExpressions(_expressions)));
            }
            else
            {
                return(Methods.MakeHash0.OpCall(gen.CurrentScopeVariable));
            }
        }
Beispiel #32
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedTarget;
            bool           hasImplicitSelf;

            if (_target != null)
            {
                transformedTarget = _target.TransformRead(gen);
                hasImplicitSelf   = false;
            }
            else
            {
                transformedTarget = gen.CurrentSelfVariable;
                hasImplicitSelf   = true;
            }
            return(TransformRead(this, gen, hasImplicitSelf, _methodName, transformedTarget, Arguments, Block, null, null));
        }
Beispiel #33
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) +
                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.Block != null)
            {
                result.Add(_parameters.Block.TransformWrite(gen, GetParameterAccess(parameters, paramsArray, parameterIndex)));
                parameterIndex++;
            }

            if (_parameters.Unsplat != null)
            {
                // the last parameter is unsplat:
                result.Add(_parameters.Unsplat.TransformWrite(gen, parameters[parameters.Count - 1]));
            }

            result.Add(AstUtils.Empty());
            return(Ast.Block(result));
        }
Beispiel #34
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     if (IsAscii || gen.Encoding == BinaryEncoding.Instance)
     {
         return(Methods.CreateMutableStringB.OpCall(Ast.Constant(_value)));
     }
     else if (IsUTF8 || gen.Encoding == BinaryEncoding.UTF8)
     {
         return(Methods.CreateMutableStringU.OpCall(Ast.Constant(_value)));
     }
     else
     {
         return(Methods.CreateMutableStringE.OpCall(
                    Ast.Constant(_value), Ast.Constant(RubyEncoding.GetCodePage(gen.Encoding))
                    ));
     }
 }
Beispiel #35
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            Assert.NotNull(gen);

            MSA.Expression transformedBlock = _block.Transform(gen);

            MSA.Expression blockArgVariable = gen.CurrentScope.DefineHiddenVariable("#forloop-block", typeof(Proc));

            MSA.Expression result = CallSiteBuilder.InvokeMethod(gen.Context, "each", RubyCallSignature.WithScopeAndBlock(0),
                                                                 gen.CurrentScopeVariable,
                                                                 _list.TransformRead(gen),
                                                                 blockArgVariable
                                                                 );

            return(gen.DebugMark(MethodCall.MakeCallWithBlockRetryable(gen, result, blockArgVariable, transformedBlock, true),
                                 "#RB: method call with a block ('for-loop')"));
        }
        internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke,
                                                                        MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition)
        {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder;

            MSA.LabelTarget retryLabel = Ast.Label("retry");

            var result = new AstBlock {
                Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),

                Ast.Label(retryLabel),

                (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null,

                AstUtils.Try(
                    Ast.Assign(resultVariable, invoke)
                    ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                            Ast.Assign(
                                resultVariable,
                                Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                )
                            ),

                Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)),
                           Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable),
                                          // retry:
                                          AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable),
                                                              RetryStatement.TransformRetry(gen),
                                                              Ast.Goto(retryLabel)
                                                              ),
                                          // return:
                                          gen.Return(ReturnStatement.Propagate(gen, resultVariable))
                                          )
                           ),

                resultVariable
            };

            return(result);
        }
Beispiel #37
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            Assert.NotNull(gen);

            if (HasExceptionHandling)
            {
                MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#block-result", typeof(object));

                return(Ast.Block(
                           TransformExceptionHandling(gen, ResultOperation.Store(resultVariable)),
                           resultVariable
                           ));
            }
            else
            {
                return(gen.TransformStatementsToExpression(_statements));
            }
        }
Beispiel #38
0
        private static List <MSA.Expression> /*!*/ ConcatLiteralsAndTransform(AstGenerator /*!*/ gen, List <Expression> /*!*/ parts, StringBuilder /*!*/ opName)
        {
            var result         = new List <MSA.Expression>();
            var literals       = new List <string>();
            int concatLength   = 0;
            var concatEncoding = StringLiteralEncoding.Ascii;

            ConcatLiteralsAndTransformRecursive(gen, parts, literals, ref concatLength, ref concatEncoding, result, opName);

            // finish trailing literals:
            if (literals.Count > 0)
            {
                result.Add(Ast.Constant(Concat(literals, concatLength)));
                opName.Append(OpSuffix(gen, concatEncoding));
            }

            return(result);
        }
Beispiel #39
0
        internal MSA.Expression /*!*/ TransformToYield(AstGenerator /*!*/ gen, MSA.Expression /*!*/ bfcVariable, MSA.Expression /*!*/ selfExpression)
        {
            var args = (_expressions != null) ? gen.TranformExpressions(_expressions) : new AstExpressions();

            if (_maplets != null)
            {
                args.Add(gen.TransformToHashConstructor(_maplets));
            }

            return(AstFactory.YieldExpression(
                       gen.Context,
                       args,
                       (_array != null) ? _array.TransformRead(gen) : null,  // splatted argument
                       null,                                                 // rhs argument
                       bfcVariable,
                       selfExpression
                       ));
        }
Beispiel #40
0
        // when <expr0>, *<expr1>, ..., <exprN>
        // generates:
        // <MakeTest>(<expr0>) || <MakeArrayTest>(<expr1>) || ... [ || <MakeTest>(<exprN>) ]
        internal static MSA.Expression /*!*/ TransformWhenCondition(AstGenerator /*!*/ gen, Expression /*!*/[] /*!*/ comparisons, MSA.Expression value)
        {
            MSA.Expression result;
            if (comparisons.Length > 0)
            {
                result = MakeTest(gen, comparisons[comparisons.Length - 1], value);
                for (int i = comparisons.Length - 2; i >= 0; i--)
                {
                    result = Ast.OrElse(MakeTest(gen, comparisons[i], value), result);
                }
            }
            else
            {
                result = Ast.Constant(false);
            }

            return(result);
        }
Beispiel #41
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression result;
            if (_elseStatements != null)
            {
                // ... else body end
                result = gen.TransformStatementsToExpression(_elseStatements);
            }
            else
            {
                // no else clause => the result of the if-expression is nil:
                result = AstUtils.Constant(null);
            }

            MSA.Expression value;
            if (_value != null)
            {
                value = gen.CurrentScope.DefineHiddenVariable("#case-compare-value", typeof(object));
            }
            else
            {
                value = null;
            }

            for (int i = _whenClauses.Length - 1; i >= 0; i--)
            {
                // emit: else (if (condition) body else result)
                result = AstFactory.Condition(
                    TransformWhenCondition(gen, _whenClauses[i].Comparisons, value),
                    gen.TransformStatementsToExpression(_whenClauses[i].Statements),
                    result
                    );
            }

            if (_value != null)
            {
                result = Ast.Block(
                    Ast.Assign(value, Ast.Convert(_value.TransformRead(gen), typeof(object))),
                    result
                    );
            }

            return(result);
        }
Beispiel #42
0
        private MSA.Expression /*!*/ TransformWrite(AstGenerator /*!*/ gen, MSA.Expression /*!*/ transformedRight, bool isSimpleRhs)
        {
            var writes = new AstBlock();

            MSA.Expression rightList = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(IList));
            MSA.Expression result;

            if (isSimpleRhs)
            {
                // 1.9 returns the RHS, not an unsplatted array, if there is just a single RHS:
                result = gen.CurrentScope.DefineHiddenVariable("#pr", transformedRight.Type);
                writes.Add(Ast.Assign(result, transformedRight));

                transformedRight = AstUtils.LightDynamic(ImplicitSplatAction.Make(gen.Context), typeof(IList), result);
            }
            else
            {
                result = rightList;
            }

            writes.Add(Ast.Assign(rightList, transformedRight));

            for (int i = 0; i < _unsplattedValueIndex; i++)
            {
                writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetArrayItem.OpCall(rightList, AstUtils.Constant(i))));
            }

            if (HasUnsplattedValue)
            {
                MSA.Expression explicitCount = AstUtils.Constant(_leftValues.Length - 1);

                // remaining RHS values:
                MSA.Expression array = Methods.GetArrayRange.OpCall(rightList, AstUtils.Constant(_unsplattedValueIndex), explicitCount);
                writes.Add(_leftValues[_unsplattedValueIndex].TransformWrite(gen, array));

                for (int i = _unsplattedValueIndex + 1; i < _leftValues.Length; i++)
                {
                    writes.Add(_leftValues[i].TransformWrite(gen, Methods.GetTrailingArrayItem.OpCall(rightList, AstUtils.Constant(_leftValues.Length - i), explicitCount)));
                }
            }

            writes.Add(result);
            return(writes);
        }
Beispiel #43
0
        /// <code>
        /// End-exclusive range:
        ///   if state
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     state = IsTrue({begin})
        ///   end
        ///
        /// End-inclusive range:
        ///   if state || IsTrue({begin})
        ///     state = IsFalse({end})
        ///     true
        ///   else
        ///     false
        ///   end
        /// </code>
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            var begin = AstUtils.Box(_range.Begin.TransformRead(gen));
            var end   = AstUtils.Box(_range.End.TransformRead(gen));

            // state:
            // false <=> null
            // true <=> non-null
            if (_range.IsExclusive)
            {
                return(Ast.Condition(
                           Ast.ReferenceNotEqual(
                               _stateVariable.TransformReadVariable(gen, false),
                               AstUtils.Constant(null)
                               ),
                           Ast.Block(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfTrue.OpCall(end)),
                               AstUtils.Constant(true)
                               ),
                           Ast.ReferenceNotEqual(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfFalse.OpCall(begin)),
                               AstUtils.Constant(null)
                               )
                           ));
            }
            else
            {
                return(Ast.Condition(
                           Ast.OrElse(
                               Ast.ReferenceNotEqual(
                                   _stateVariable.TransformReadVariable(gen, false),
                                   AstUtils.Constant(null)
                                   ),
                               Methods.IsTrue.OpCall(begin)
                               ),
                           Ast.Block(
                               _stateVariable.TransformWriteVariable(gen, Methods.NullIfTrue.OpCall(end)),
                               AstUtils.Constant(true)
                               ),
                           AstUtils.Constant(false)
                           ));
            }
        }
Beispiel #44
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Return
        internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedReturnValue = TransformReturnValue(gen);

            // eval:
            if (gen.CompilerOptions.IsEval)
            {
                return(gen.Return(Methods.EvalReturn.OpCall(gen.CurrentScopeVariable, AstUtils.Box(transformedReturnValue))));
            }

            // block:
            if (gen.CurrentBlock != null)
            {
                return(gen.Return(Methods.BlockReturn.OpCall(gen.CurrentBlock.BfcVariable, AstUtils.Box(transformedReturnValue))));
            }

            // method:
            return(gen.Return(transformedReturnValue));
        }
Beispiel #45
0
        internal virtual MSA.Expression /*!*/ MakeDefinitionExpression(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedQualifier;
            MSA.Expression name = QualifiedName.TransformName(gen);

            switch (QualifiedName.TransformQualifier(gen, out transformedQualifier))
            {
            case StaticScopeKind.Global:
                return(Methods.DefineGlobalModule.OpCall(gen.CurrentScopeVariable, name));

            case StaticScopeKind.EnclosingModule:
                return(Methods.DefineNestedModule.OpCall(gen.CurrentScopeVariable, name));

            case StaticScopeKind.Explicit:
                return(Methods.DefineModule.OpCall(gen.CurrentScopeVariable, AstUtils.Box(transformedQualifier), name));
            }

            throw Assert.Unreachable;
        }
Beispiel #46
0
 private static char OpSuffix(AstGenerator /*!*/ gen, StringLiteralEncoding encoding)
 {
     if (encoding == StringLiteralEncoding.Ascii)
     {
         return(RubyOps.SuffixBinary);
     }
     else if (encoding == StringLiteralEncoding.UTF8 || gen.Encoding == Encoding.UTF8)
     {
         return(RubyOps.SuffixUTF8);
     }
     else if (gen.Encoding == BinaryEncoding.Instance)
     {
         return(RubyOps.SuffixBinary);
     }
     else
     {
         return(RubyOps.SuffixEncoded);
     }
 }
Beispiel #47
0
        internal override MSA.Expression /*!*/ TransformWriteVariable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ rightValue)
        {
            MSA.Expression transformedName = TransformName(gen);
            MSA.Expression transformedQualifier;

            switch (TransformQualifier(gen, out transformedQualifier))
            {
            case StaticScopeKind.Global:
                return(Methods.SetGlobalConstant.OpCall(AstUtils.Box(rightValue), gen.CurrentScopeVariable, transformedName));

            case StaticScopeKind.EnclosingModule:
                return(Methods.SetUnqualifiedConstant.OpCall(AstUtils.Box(rightValue), gen.CurrentScopeVariable, transformedName));

            case StaticScopeKind.Explicit:
                return(Methods.SetQualifiedConstant.OpCall(AstUtils.Box(rightValue), transformedQualifier, gen.CurrentScopeVariable, transformedName));
            }

            throw Assert.Unreachable;
        }
Beispiel #48
0
        //
        // Traverses expressions in "parts" and concats all contiguous literal strings.
        // Notes:
        //  - Instead of usign StringBuilder we place the string values that can be concatenated so far in to "literals" list and keep track
        //    of their total length in "concatLength" and encoding in "concatEncoding".
        //    If we reach a non-literal expression and we have some literals ready in "literals" array we do the concat and clear the list
        //    and "concatLength" and "concatEncoding".
        //  - "result" list contains argument expressions to the CreateMutableString* overloads.
        //  - "opName" contains the name of the operation. This method appends suffix based on the argument types (see RubyOps.Suffix*).
        //
        private static void ConcatLiteralsAndTransformRecursive(AstGenerator /*!*/ gen, List <Expression> /*!*/ parts,
                                                                List <string> /*!*/ literals, ref int concatLength, ref StringLiteralEncoding concatEncoding, List <MSA.Expression> /*!*/ result,
                                                                StringBuilder /*!*/ opName)
        {
            for (int i = 0; i < parts.Count; i++)
            {
                Expression        part = parts[i];
                StringLiteral     literal;
                StringConstructor ctor;

                if ((literal = part as StringLiteral) != null)
                {
                    literals.Add(literal.Value);
                    concatEncoding = CombineEncoding(concatEncoding, literal);
                    concatLength  += literal.Value.Length;
                }
                else if ((ctor = part as StringConstructor) != null)
                {
                    ConcatLiteralsAndTransformRecursive(gen, ctor.Parts, literals, ref concatLength, ref concatEncoding, result, opName);
                }
                else
                {
                    if (literals.Count > 0)
                    {
                        result.Add(Ast.Constant(Concat(literals, concatLength)));
                        opName.Append(OpSuffix(gen, concatEncoding));
                        concatLength   = 0;
                        concatEncoding = StringLiteralEncoding.Ascii;
                        literals.Clear();
                    }

                    result.Add(
                        Ast.Dynamic(
                            ConvertToSAction.Instance,
                            typeof(MutableString),
                            gen.CurrentScopeVariable, part.TransformRead(gen)
                            )
                        );
                    opName.Append(RubyOps.SuffixMutable);
                }
            }
        }
Beispiel #49
0
        internal override MSA.Expression /*!*/ MakeDefinitionExpression(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedQualifier;
            MSA.Expression name             = QualifiedName.TransformName(gen);
            MSA.Expression transformedSuper = (_superClass != null) ? AstUtils.Box(_superClass.TransformRead(gen)) : AstUtils.Constant(null);

            switch (QualifiedName.TransformQualifier(gen, out transformedQualifier))
            {
            case StaticScopeKind.Global:
                return(Methods.DefineGlobalClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper));

            case StaticScopeKind.EnclosingModule:
                return(Methods.DefineNestedClass.OpCall(gen.CurrentScopeVariable, name, transformedSuper));

            case StaticScopeKind.Explicit:
                return(Methods.DefineClass.OpCall(gen.CurrentScopeVariable, transformedQualifier, name, transformedSuper));
            }

            throw Assert.Unreachable;
        }
Beispiel #50
0
        private MSA.ParameterExpression[] /*!*/ DefineParameters(AstGenerator /*!*/ gen, ScopeBuilder /*!*/ scope)
        {
            // user defined locals/args:
            MSA.ParameterExpression[] parameters = DefinedScope.TransformParameters(_parameters, HiddenParameterCount);
            scope.AddVisibleParameters(parameters, HiddenParameterCount);

            parameters[0] = Ast.Parameter(typeof(object), "#self");

            if (_parameters.Block != null)
            {
                // map user defined proc parameter to the special param #1:
                parameters[1] = _parameters.Block.TransformBlockParameterDefinition();
            }
            else
            {
                parameters[1] = Ast.Parameter(typeof(Proc), "#block");
            }

            return(parameters);
        }
Beispiel #51
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            switch (_index)
            {
            case MatchData:
                return(Methods.GetCurrentMatchData.OpCall(gen.CurrentScopeVariable));

            case MatchLastGroup:
                return(Methods.GetCurrentMatchLastGroup.OpCall(gen.CurrentScopeVariable));

            case PreMatch:
                return(Methods.GetCurrentPreMatch.OpCall(gen.CurrentScopeVariable));

            case PostMatch:
                return(Methods.GetCurrentPostMatch.OpCall(gen.CurrentScopeVariable));

            default:
                return(Methods.GetCurrentMatchGroup.OpCall(gen.CurrentScopeVariable, AstUtils.Constant(_index)));
            }
        }
Beispiel #52
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            switch (_kind)
            {
            case StringKind.Mutable:
                return(TransformConcatentation(gen, _parts, Methods.CreateMutableString, null));

            case StringKind.Immutable:
                return(TransformConcatentation(gen, _parts, Methods.CreateSymbol, null));

            case StringKind.Command:
                return(Ast.Dynamic(RubyCallAction.Make("`", new RubyCallSignature(1, RubyCallFlags.HasScope | RubyCallFlags.HasImplicitSelf)), typeof(object),
                                   gen.CurrentScopeVariable,
                                   gen.CurrentSelfVariable,
                                   TransformConcatentation(gen, _parts, Methods.CreateMutableString, null)
                                   ));
            }

            throw Assert.Unreachable;
        }
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            switch (_kind)
            {
            case StringKind.Mutable:
                return(TransformConcatentation(gen, _parts, StringFactory.Instance));

            case StringKind.Symbol:
                return(TransformConcatentation(gen, _parts, SymbolFactory.Instance));

            case StringKind.Command:
                return(CallSiteBuilder.InvokeMethod(gen.Context, "`", new RubyCallSignature(1, RubyCallFlags.HasScope | RubyCallFlags.HasImplicitSelf),
                                                    gen.CurrentScopeVariable,
                                                    gen.CurrentSelfVariable,
                                                    TransformConcatentation(gen, _parts, StringFactory.Instance)
                                                    ));
            }

            throw Assert.Unreachable;
        }
Beispiel #54
0
        internal void TransformToCall(AstGenerator /*!*/ gen, CallBuilder callBuilder)
        {
            if (_expressions != null)
            {
                foreach (var arg in _expressions)
                {
                    callBuilder.Add(arg.TransformRead(gen));
                }
            }

            if (_maplets != null)
            {
                callBuilder.Add(gen.TransformToHashConstructor(_maplets));
            }

            if (_array != null)
            {
                callBuilder.SplattedArgument = _array.TransformRead(gen);
            }
        }
Beispiel #55
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            int intBegin, intEnd;

            if (IsIntegerRange(out intBegin, out intEnd))
            {
                return((_isExclusive ? Methods.CreateExclusiveIntegerRange : Methods.CreateInclusiveIntegerRange).OpCall(
                           AstUtils.Constant(intBegin), AstUtils.Constant(intEnd)
                           ));
            }
            else
            {
                return((_isExclusive ? Methods.CreateExclusiveRange : Methods.CreateInclusiveRange).OpCall(
                           AstUtils.Box(_begin.TransformRead(gen)),
                           AstUtils.Box(_end.TransformRead(gen)),
                           gen.CurrentScopeVariable,
                           AstUtils.Constant(new BinaryOpStorage(gen.Context))
                           ));
            }
        }
Beispiel #56
0
        internal void TransformToCall(AstGenerator /*!*/ gen, CallSiteBuilder /*!*/ siteBuilder)
        {
            if (_expressions != null)
            {
                foreach (var arg in _expressions)
                {
                    siteBuilder.Add(arg.TransformRead(gen));
                }
            }

            if (_maplets != null)
            {
                siteBuilder.Add(gen.TransformToHashConstructor(_maplets));
            }

            if (_array != null)
            {
                siteBuilder.SplattedArgument =
                    AstUtils.LightDynamic(SplatAction.Make(gen.Context), typeof(IList), _array.TransformRead(gen));
            }
        }
Beispiel #57
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Yield
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression bfcVariable    = gen.CurrentScope.DefineHiddenVariable("#yielded-bfc", typeof(BlockParam));
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#result", typeof(object));
            MSA.Expression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            MSA.Expression postYield;

            if (gen.CompilerOptions.IsEval)
            {
                // eval:
                postYield = Methods.EvalYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }
            else if (gen.CurrentBlock != null)
            {
                // block:
                postYield = Methods.BlockYield.OpCall(gen.CurrentRfcVariable, gen.CurrentBlock.BfcVariable, bfcVariable, resultVariable);
            }
            else
            {
                // method:
                postYield = Methods.MethodYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }

            return(AstFactory.Block(
                       gen.DebugMarker("#RB: yield begin"),

                       Ast.Assign(bfcVariable, Methods.CreateBfcForYield.OpCall(gen.MakeMethodBlockParameterRead())),

                       Ast.Assign(resultVariable, (Arguments ?? Arguments.Empty).TransformToYield(gen, bfcVariable,
                                                                                                  Ast.Property(AstUtils.Convert(gen.MakeMethodBlockParameterRead(), typeof(Proc)), Proc.SelfProperty)
                                                                                                  )),

                       AstUtils.IfThen(postYield, gen.Return(resultVariable)),

                       gen.DebugMarker("#RB: yield end"),

                       resultVariable
                       ));
        }
Beispiel #58
0
 // when <expr>
 //   generates into:
 //   RubyOps.IsTrue(<expr>) if the case has no value, otherise:
 //   RubyOps.IsTrue(Call("===", <expr>, <value>))
 private static MSA.Expression /*!*/ MakeTest(AstGenerator /*!*/ gen, Expression /*!*/ expr, MSA.Expression value)
 {
     MSA.Expression transformedExpr = expr.TransformRead(gen);
     if (expr is SplattedArgument)
     {
         if (value != null)
         {
             return(Methods.ExistsUnsplatCompare.OpCall(
                        Ast.Constant(CallSite <Func <CallSite, object, object, object> > .Create(
                                         RubyCallAction.Make(gen.Context, "===", RubyCallSignature.WithImplicitSelf(2))
                                         )),
                        AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr),
                        AstUtils.Box(value)
                        ));
         }
         else
         {
             return(Methods.ExistsUnsplat.OpCall(
                        AstUtils.LightDynamic(ExplicitTrySplatAction.Make(gen.Context), transformedExpr)
                        ));
         }
     }
     else
     {
         if (value != null)
         {
             return(AstFactory.IsTrue(
                        CallSiteBuilder.InvokeMethod(gen.Context, "===", RubyCallSignature.WithScope(1),
                                                     gen.CurrentScopeVariable,
                                                     transformedExpr,
                                                     value
                                                     )
                        ));
         }
         else
         {
             return(AstFactory.IsTrue(transformedExpr));
         }
     }
 }
Beispiel #59
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);
        }
Beispiel #60
0
        private MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen, int opKind)
        {
            ConstantVariable constantQualifier = _qualifier as ConstantVariable;

            if (constantQualifier != null)
            {
                ConstantVariable constant;
                List <string>    names = new List <string>();
                names.Add(Name);
                do
                {
                    names.Add(constantQualifier.Name);
                    constant          = constantQualifier;
                    constantQualifier = constantQualifier.Qualifier as ConstantVariable;
                } while (constantQualifier != null);

                if (constant.Qualifier != null)
                {
                    // {expr}::A::B
                    return(constant.MakeExpressionQualifiedRead(gen, opKind, names.ToReverseArray()));
                }
                else
                {
                    // A::B
                    return(MakeCachedRead(gen, opKind, constant.IsGlobal, true, Ast.Constant(names.ToReverseArray())));
                }
            }
            else if (_qualifier != null)
            {
                // {expr}::A
                return(MakeExpressionQualifiedRead(gen, opKind, new[] { Name }));
            }
            else
            {
                // A
                // ::A
                return(MakeCachedRead(gen, opKind, IsGlobal, false, Ast.Constant(Name)));
            }
        }