예제 #1
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()
                       ));
        }
예제 #2
0
 /// <summary>
 /// Gets the expression for the actual updating of the line number for stack traces to be available
 /// </summary>
 internal MSAst.Expression GetSaveLineNumberExpression(MSAst.ParameterExpression exception, bool preventAdditionalAdds)
 {
     Debug.Assert(exception.Type == typeof(Exception));
     return(Ast.Block(
                AstUtils.If(
                    Ast.Not(
                        LineNumberUpdated
                        ),
                    Ast.Call(
                        AstMethods.UpdateStackTrace,
                        exception,
                        LocalContext,
                        _funcCodeExpr,
                        _GetCurrentMethod,
                        AstUtils.Constant(Name),
                        AstUtils.Constant(GlobalParent.SourceUnit.Path ?? "<string>"),
                        new LastFaultingLineExpression(LineNumberExpression)
                        )
                    ),
                Ast.Assign(
                    LineNumberUpdated,
                    AstUtils.Constant(preventAdditionalAdds)
                    ),
                AstUtils.Empty()
                ));
 }
예제 #3
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));
        }
 internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
 {
     return(AstUtils.IfThenElse(
                _condition.TransformCondition(gen, !_negateCondition),
                _body.Transform(gen),
                _elseStatement != null ? _elseStatement.Transform(gen) : AstUtils.Empty()
                ));
 }
예제 #5
0
        internal sealed override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            string debugString = (IsSingletonDeclaration) ? "SINGLETON" : ((this is ClassDefinition) ? "CLASS" : "MODULE") + " " + QualifiedName.Name;

            ScopeBuilder outerLocals = gen.CurrentScope;

            // definition needs to take place outside the defined lexical scope:
            var definition   = MakeDefinitionExpression(gen);
            var selfVariable = outerLocals.DefineHiddenVariable("#module", typeof(RubyModule));
            var parentScope  = gen.CurrentScopeVariable;

            // inner locals:
            ScopeBuilder scope         = DefineLocals();
            var          scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyScope));

            gen.EnterModuleDefinition(
                scope,
                selfVariable,
                scopeVariable,
                IsSingletonDeclaration
                );

            // transform body:
            MSA.Expression transformedBody = Body.TransformRead(gen);

            // outer local:
            MSA.Expression resultVariable = outerLocals.DefineHiddenVariable("#result", transformedBody.Type);

            // begin with new scope
            //   self = DefineModule/Class(... parent scope here ...)
            //   <body>
            // end
            MSA.Expression result = new AstBlock {
                gen.DebugMarker(debugString),
                Ast.Assign(selfVariable, definition),
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateModuleScope.OpCall(
                        scope.MakeLocalsStorage(),
                        scope.GetVariableNamesExpression(),
                        parentScope,
                        selfVariable
                        ),
                    Ast.Block(
                        Ast.Assign(resultVariable, transformedBody),
                        AstUtils.Empty()
                        )
                    ),
                gen.DebugMarker("END OF " + debugString),
                resultVariable
            };

            gen.LeaveModuleDefinition();

            return(result);
        }
예제 #6
0
        /// <summary>
        /// Gets the expression for the actual updating of the line number for stack traces to be available
        /// </summary>
        internal MSAst.Expression GetSaveLineNumberExpression(bool preventAdditionalAdds)
        {
            MSAst.Expression res;
            if (preventAdditionalAdds)
            {
                res = _saveLineNumberNoAdds;
            }
            else
            {
                res = _saveLineNumberAdds;
            }

            if (res == null)
            {
                res = Ast.Block(
                    AstUtils.If(
                        Ast.Not(
                            LineNumberUpdated
                            ),
                        Ast.Call(
                            AstMethods.UpdateStackTrace,
                            LocalContext,
                            _funcCodeExpr,
                            _GetCurrentMethod,
                            AstUtils.Constant(Name),
                            AstUtils.Constant(GlobalParent.SourceUnit.Path ?? "<string>"),
                            new LastFaultingLineExpression(LineNumberExpression)
                            )
                        ),
                    Ast.Assign(
                        LineNumberUpdated,
                        AstUtils.Constant(preventAdditionalAdds)
                        ),
                    AstUtils.Empty()
                    );

                if (preventAdditionalAdds)
                {
                    _saveLineNumberNoAdds = res;
                }
                else
                {
                    _saveLineNumberAdds = res;
                }
            }

            return(res);
        }
예제 #7
0
 /// <summary>
 /// Gets the expression for the actual updating of the line number for stack traces to be available
 /// </summary>
 internal MSAst.Expression GetSaveLineNumberExpression(MSAst.ParameterExpression exception, bool preventAdditionalAdds) {
     Debug.Assert(exception.Type == typeof(Exception));
     return Ast.Block(
         AstUtils.If(
             Ast.Not(
                 LineNumberUpdated
             ),
             UpdateStackTrace(exception)
         ),
         Ast.Assign(
             LineNumberUpdated,
             AstUtils.Constant(preventAdditionalAdds)
         ),
         AstUtils.Empty()
     );
 }
예제 #8
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));
        }
예제 #9
0
        public override MSAst.Expression Reduce()
        {
            MSAst.Expression destination = _dest;

            if (_expressions.Length == 0)
            {
                MSAst.Expression result;
                if (destination != null)
                {
                    result = Ast.Call(
                        AstMethods.PrintNewlineWithDest,
                        Parent.LocalContext,
                        destination
                        );
                }
                else
                {
                    result = Ast.Call(
                        AstMethods.PrintNewline,
                        Parent.LocalContext
                        );
                }
                return(GlobalParent.AddDebugInfo(result, Span));
            }
            else
            {
                // Create list for the individual statements
                ReadOnlyCollectionBuilder <MSAst.Expression> statements = new ReadOnlyCollectionBuilder <MSAst.Expression>();

                // Store destination in a temp, if we have one
                MSAst.ParameterExpression temp = null;
                if (destination != null)
                {
                    temp = Ast.Variable(typeof(object), "destination");

                    statements.Add(MakeAssignment(temp, destination));

                    destination = temp;
                }
                for (int i = 0; i < _expressions.Length; i++)
                {
                    bool       withComma = (i < _expressions.Length - 1 || _trailingComma);// ? "PrintComma" : "Print";
                    Expression current   = _expressions[i];
                    MSAst.MethodCallExpression mce;

                    if (destination != null)
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintCommaWithDest : AstMethods.PrintWithDest,
                            Parent.LocalContext,
                            destination,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }
                    else
                    {
                        mce = Ast.Call(
                            withComma ? AstMethods.PrintComma : AstMethods.Print,
                            Parent.LocalContext,
                            AstUtils.Convert(current, typeof(object))
                            );
                    }

                    statements.Add(mce);
                }

                statements.Add(AstUtils.Empty());
                MSAst.Expression res;
                if (temp != null)
                {
                    res = Ast.Block(new[] { temp }, statements.ToReadOnlyCollection());
                }
                else
                {
                    res = Ast.Block(statements.ToReadOnlyCollection());
                }
                return(GlobalParent.AddDebugInfo(res, Span));
            }
        }
예제 #10
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 AstBlock();

                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(result);
            }
        }
예제 #11
0
        internal MSA.LambdaExpression /*!*/ TransformBody(AstGenerator /*!*/ gen, RubyScope /*!*/ declaringScope, RubyModule /*!*/ declaringModule)
        {
            string encodedName = RubyStackTraceBuilder.EncodeMethodName(_name, gen.SourcePath, Location, gen.DebugMode);

            AstParameters parameters;
            ScopeBuilder  scope = DefineLocals(out parameters);

            var scopeVariable  = scope.DefineHiddenVariable("#scope", typeof(RubyMethodScope));
            var selfParameter  = parameters[0];
            var blockParameter = parameters[1];

            // exclude block parameter even if it is explicitly specified:
            int visiblePrameterCountAndSignatureFlags = (parameters.Count - 2) << 2;

            if (_parameters.Block != null)
            {
                visiblePrameterCountAndSignatureFlags |= RubyMethodScope.HasBlockFlag;
            }
            if (_parameters.Unsplat != null)
            {
                visiblePrameterCountAndSignatureFlags |= RubyMethodScope.HasUnsplatFlag;
            }

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

            // profiling:
            MSA.Expression profileStart, profileEnd;
            if (gen.Profiler != null)
            {
                int profileTickIndex = gen.Profiler.GetTickIndex(encodedName);
                var stampVariable    = scope.DefineHiddenVariable("#stamp", typeof(long));
                profileStart = Ast.Assign(stampVariable, Methods.Stopwatch_GetTimestamp.OpCall());
                profileEnd   = Methods.UpdateProfileTicks.OpCall(AstUtils.Constant(profileTickIndex), stampVariable);
            }
            else
            {
                profileStart = profileEnd = AstUtils.Empty();
            }

            // tracing:
            MSA.Expression traceCall, traceReturn;
            if (gen.TraceEnabled)
            {
                traceCall = Methods.TraceMethodCall.OpCall(
                    scopeVariable,
                    gen.SourcePathConstant,
                    AstUtils.Constant(Location.Start.Line)
                    );

                traceReturn = Methods.TraceMethodReturn.OpCall(
                    gen.CurrentScopeVariable,
                    gen.SourcePathConstant,
                    AstUtils.Constant(Location.End.Line)
                    );
            }
            else
            {
                traceCall = traceReturn = AstUtils.Empty();
            }

            MSA.ParameterExpression unwinder;

            MSA.Expression body = AstUtils.Try(
                profileStart,
                _parameters.TransformOptionalsInitialization(gen),
                traceCall,
                Body.TransformResult(gen, ResultOperation.Return)
                ).Filter(unwinder = Ast.Parameter(typeof(Exception), "#u"), Methods.IsMethodUnwinderTargetFrame.OpCall(scopeVariable, unwinder),
                         Ast.Return(gen.ReturnLabel, Methods.GetMethodUnwinderReturnValue.OpCall(unwinder))
                         ).Finally(
                // leave frame:
                Methods.LeaveMethodFrame.OpCall(scopeVariable),
                Ast.Empty(),
                profileEnd,
                traceReturn
                );

            body = gen.AddReturnTarget(
                scope.CreateScope(
                    scopeVariable,
                    Methods.CreateMethodScope.OpCall(new AstExpressions {
                scope.MakeLocalsStorage(),
                scope.GetVariableNamesExpression(),
                Ast.Constant(visiblePrameterCountAndSignatureFlags),
                Ast.Constant(declaringScope, typeof(RubyScope)),
                Ast.Constant(declaringModule, typeof(RubyModule)),
                Ast.Constant(_name),
                selfParameter, blockParameter,
                EnterInterpretedFrameExpression.Instance
            }),
                    body
                    )
                );

            gen.LeaveMethodDefinition();

            return(CreateLambda(encodedName, parameters, body));
        }
예제 #12
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/While-Until
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#loop-result", typeof(object));
            MSA.Expression          redoVariable   = gen.CurrentScope.DefineHiddenVariable("#skip-condition", typeof(bool));
            MSA.ParameterExpression unwinder;

            bool isInnerLoop = gen.CurrentLoop != null;

            MSA.LabelTarget breakLabel    = Ast.Label();
            MSA.LabelTarget continueLabel = Ast.Label();

            gen.EnterLoop(redoVariable, resultVariable, breakLabel, continueLabel);
            MSA.Expression transformedBody      = gen.TransformStatements(_statements, ResultOperation.Ignore);
            MSA.Expression transformedCondition = _condition.TransformCondition(gen, true);
            gen.LeaveLoop();

            MSA.Expression conditionPositiveStmt, conditionNegativeStmt;
            if (_isWhileLoop)
            {
                conditionPositiveStmt = AstUtils.Empty();
                conditionNegativeStmt = Ast.Break(breakLabel);
            }
            else
            {
                conditionPositiveStmt = Ast.Break(breakLabel);
                conditionNegativeStmt = AstUtils.Empty();
            }

            // make the loop first:
            MSA.Expression loop = new AstBlock {
                gen.ClearDebugInfo(),
                           Ast.Assign(redoVariable, AstUtils.Constant(_isPostTest)),

                AstFactory.Infinite(breakLabel, continueLabel,
                                    AstUtils.Try(

                                        AstUtils.If(redoVariable,
                                                    Ast.Assign(redoVariable, AstUtils.Constant(false))
                                                    ).ElseIf(transformedCondition,
                                                             conditionPositiveStmt
                                                             ).Else(
                                            conditionNegativeStmt
                                            ),

                                        transformedBody,
                                        AstUtils.Empty()

                                        ).Catch(unwinder = Ast.Parameter(typeof(BlockUnwinder), "#u"),
                                                // redo = u.IsRedo
                                                Ast.Assign(redoVariable, Ast.Field(unwinder, BlockUnwinder.IsRedoField)),
                                                AstUtils.Empty()

                                                ).Filter(unwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                                                         Ast.Equal(Ast.Field(unwinder, EvalUnwinder.ReasonField), AstFactory.BlockReturnReasonBreak),

                                                         // result = unwinder.ReturnValue
                                                         Ast.Assign(resultVariable, Ast.Field(unwinder, EvalUnwinder.ReturnValueField)),
                                                         Ast.Break(breakLabel)
                                                         )
                                    ),
                gen.ClearDebugInfo(),
                AstUtils.Empty(),
            };

            // wrap it to try finally that updates RFC state:
            if (!isInnerLoop)
            {
                loop = AstUtils.Try(
                    Methods.EnterLoop.OpCall(gen.CurrentScopeVariable),
                    loop
                    ).Finally(
                    Methods.LeaveLoop.OpCall(gen.CurrentScopeVariable)
                    );
            }

            return(Ast.Block(loop, resultVariable));
        }