예제 #1
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()
                ));
 }
예제 #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(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);
        }
예제 #3
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()
     );
 }
예제 #4
0
        /// <summary>
        /// Helper to produce the rule for converting T to Nullable of T
        /// </summary>
        private void MakeConvertingToTToNullableOfTTarget(Type toType)
        {
            Type valueType = toType.GetGenericArguments()[0];

            // ConvertSelfToT -> Nullable<T>
            if (Action.ResultKind == ConversionResultKind.ExplicitCast)
            {
                var action     = OldConvertToAction.Make(Binder, valueType, Action.ResultKind);
                var conversion = Expression.Dynamic(action, action.ToType, _rule.Context, _rule.Parameters[0]);
                // if the conversion to T fails we just throw
                _rule.Target =
                    _rule.MakeReturn(
                        Binder,
                        Ast.New(
                            toType.GetConstructor(new Type[] { valueType }),
                            conversion
                            )
                        );
            }
            else
            {
                // if the conversion to T succeeds then produce the nullable<T>, otherwise return default(retType)
                var conversion = Expression.Dynamic(OldConvertToAction.Make(Binder, valueType, Action.ResultKind), typeof(object), _rule.Context, _rule.Parameters[0]);

                ParameterExpression tmp = _rule.GetTemporary(typeof(object), "tmp");
                _rule.Target =
                    AstUtils.If(
                        Ast.NotEqual(
                            Ast.Assign(tmp, conversion),
                            Ast.Constant(null)
                            ),
                        _rule.MakeReturn(
                            Binder,
                            Ast.New(
                                toType.GetConstructor(new Type[] { valueType }),
                                Ast.Convert(
                                    tmp,
                                    valueType
                                    )
                                )
                            )
                        ).Else(
                        CompilerHelpers.GetTryConvertReturnValue(Context, _rule)
                        );
            }
        }
예제 #5
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        protected void MakeOperatorGetMemberBody(Type type, string name)
        {
            MethodInfo getMem = GetMethod(type, name);

            if (getMem != null && getMem.IsSpecialName)
            {
                ParameterExpression tmp = Rule.GetTemporary(typeof(object), "getVal");
                AddToBody(
                    AstUtils.If(
                        Ast.NotEqual(
                            Ast.Assign(
                                tmp,
                                Binder.MakeCallExpression(Rule.Context, getMem, Instance, Ast.Constant(StringName))
                                ),
                            Ast.Field(null, typeof(OperationFailed).GetField("Value"))
                            ),
                        Rule.MakeReturn(Binder, tmp)
                        )
                    );
            }
        }
예제 #6
0
        /// <summary> if a member-injector is defined-on or registered-for this type call it </summary>
        private bool MakeOperatorGetMemberBody(Type type, string name)
        {
            MethodInfo delMem = GetMethod(type, name);

            if (delMem != null && delMem.IsSpecialName)
            {
                Expression call = Binder.MakeCallExpression(Rule.Context, delMem, Rule.Parameters[0], Ast.Constant(StringName));
                Expression ret;

                if (delMem.ReturnType == typeof(bool))
                {
                    ret = AstUtils.If(call, Rule.MakeReturn(Binder, Ast.Constant(null)));
                }
                else
                {
                    ret = Rule.MakeReturn(Binder, call);
                }
                AddToBody(ret);
                return(delMem.ReturnType != typeof(bool));
            }
            return(false);
        }
예제 #7
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));
        }