private MSA.Expression /*!*/ MakeExpressionQualifiedRead(AstGenerator /*!*/ gen, int opKind, string /*!*/[] /*!*/ names) { Debug.Assert(_qualifier != null && !(_qualifier is ConstantVariable)); object siteCache; MethodInfo op; if (opKind == OpIsDefined) { siteCache = new ExpressionQualifiedIsDefinedConstantSiteCache(); op = Methods.IsDefinedExpressionQualifiedConstant; } else { siteCache = new ExpressionQualifiedConstantSiteCache(); op = Methods.GetExpressionQualifiedConstant; } var result = op.OpCall( AstUtils.Box(_qualifier.TransformRead(gen)), gen.CurrentScopeVariable, Ast.Constant(siteCache), Ast.Constant(names) ); return(opKind == OpIsDefined?Ast.TryCatch(result, Ast.Catch(typeof(Exception), AstFactory.False)) : result); }
internal MSA.Expression /*!*/ TryCatchAny(MSA.Expression /*!*/ tryBody, MSA.Expression /*!*/ catchBody) { var variable = CurrentScope.DefineHiddenVariable("#value", tryBody.Type); return (Ast.Block( Ast.TryCatch( Ast.Assign(variable, tryBody), Ast.Catch(typeof(Exception), Ast.Assign(variable, catchBody) ) ), variable )); }
/// <summary> /// Wraps the body of a statement which should result in a frame being available during /// exception handling. This ensures the line number is updated as the stack is unwound. /// </summary> internal MSAst.Expression/*!*/ WrapScopeStatements(MSAst.Expression/*!*/ body, bool canThrow) { if (canThrow) { body = Ast.Block( new[] { LineNumberExpression, LineNumberUpdated }, Ast.TryCatch( body, Ast.Catch( _catchException, Ast.Block( GetUpdateTrackbackExpression(_catchException), Ast.Rethrow(body.Type) ) ) ) ); } return body; }
private MSAst.LambdaExpression CreateOuterLambda(Type lambdaType, MSAst.Expression debuggableBody) { List <MSAst.Expression> bodyExpressions = new List <MSAst.Expression>(); List <MSAst.Expression> tryExpressions = new List <MSAst.Expression>(); List <MSAst.Expression> finallyExpressions = new List <MSAst.Expression>(); Type returnType = lambdaType.GetMethod("Invoke").ReturnType; MSAst.LabelTarget returnLabelTarget = Ast.Label(returnType); // Init $funcInfo tryExpressions.Add( Ast.Assign( _funcInfo, Ast.Convert(_functionInfo, typeof(FunctionInfo)) ) ); // Init $traceLocations // $TODO: only do this if we're in TracePoints mode tryExpressions.Add( Ast.Assign( _traceLocations, Ast.Call(typeof(RuntimeOps).GetMethod("GetTraceLocations"), _funcInfo) ) ); // Init sourceFile locals foreach (var entry in _sourceFilesMap) { tryExpressions.Add( Ast.Assign( entry.Value, Ast.Constant(entry.Key, typeof(DebugSourceFile)) ) ); } if (_noPushFrameOptimization) { tryExpressions.Add(_pushFrame); } tryExpressions.Add(Ast.Call( typeof(RuntimeOps).GetMethod("OnFrameEnterTraceEvent"), _thread )); var frameExit = AstUtils.If( Ast.Equal( _debugMarkerLocationMap.Length > 0 ? Ast.Property(_sourceFilesMap[_debugMarkerLocationMap[0].SourceFile], "Mode") : _globalDebugMode, AstUtils.Constant((int)DebugMode.FullyEnabled) ), Ast.Call( typeof(RuntimeOps).GetMethod("OnFrameExitTraceEvent"), _thread, _debugMarker, _retVal != null ? (MSAst.Expression)Ast.Convert(_retVal, typeof(object)) : Ast.Constant(null) ) ); // normal exit tryExpressions.Add( Ast.Block( _retVal != null ? Ast.Assign(_retVal, debuggableBody) : debuggableBody, Ast.Assign(_frameExitException, Ast.Constant(true)), frameExit) ); tryExpressions.Add( _retVal != null ? (MSAst.Expression)Ast.Return(returnLabelTarget, _retVal) : Ast.Empty() ); MSAst.Expression[] popFrame = new MSAst.Expression[] { AstUtils.If( // Fire thead-exit event if PopFrame returns true Ast.AndAlso( Ast.Equal(Ast.Call(typeof(RuntimeOps).GetMethod("PopFrame"), _thread), Ast.Constant(true)), Ast.Equal(_globalDebugMode, AstUtils.Constant((int)DebugMode.FullyEnabled)) ), Ast.Call( typeof(RuntimeOps).GetMethod("OnThreadExitEvent"), _thread ) ) }; if (_noPushFrameOptimization) { finallyExpressions.AddRange(popFrame); } else { finallyExpressions.Add( AstUtils.If( Ast.Equal(_framePushed, Ast.Constant(true)), popFrame ) ); } MSAst.ParameterExpression caughtException; // Run the function body bodyExpressions.Add(Ast.TryCatchFinally( Ast.TryCatch( Ast.Block( ArrayUtils.Append(tryExpressions.ToArray(), Ast.Default(returnType)) ), Ast.Catch( caughtException = Ast.Variable(typeof(Exception), "$caughtException"), Ast.Block( // The expressions below will always throw. // If the exception needs to be cancelled then OnTraceEvent will throw ForceToGeneratorLoopException. // If the exception is not being cancelled then we'll just rethrow at the end of the catch block. AstUtils.If( Ast.Not( Ast.TypeIs( caughtException, typeof(ForceToGeneratorLoopException) ) ), AstUtils.If( Ast.NotEqual(_globalDebugMode, AstUtils.Constant((int)DebugMode.Disabled)), _noPushFrameOptimization ? Ast.Empty() : _conditionalPushFrame, Ast.Call( typeof(RuntimeOps).GetMethod("OnTraceEventUnwind"), _thread, _debugMarker, caughtException ) ), // exception exit AstUtils.If( Ast.Not(_frameExitException), frameExit ) ), Ast.Rethrow(), // Ensuring that the catch block is of the same type as the try block Ast.Default(returnType) ) ) ), Ast.Block(finallyExpressions), Ast.Catch( typeof(ForceToGeneratorLoopException), Ast.TryFinally( // Handle ForceToGeneratorLoopException Ast.Block( returnType != typeof(void) ? Ast.Block( Ast.Assign( _retValFromGeneratorLoop, Ast.Call( typeof(RuntimeOps).GetMethod("GeneratorLoopProc"), _thread ) ), AstUtils.If( Ast.NotEqual( _retValFromGeneratorLoop, Ast.Constant(null) ), Ast.Assign(_retVal, Ast.Convert(_retValFromGeneratorLoop, returnType)), Ast.Return( returnLabelTarget, Ast.Convert(_retValFromGeneratorLoop, returnType) ) ).Else( Ast.Assign(_retVal, Ast.Default(returnType)), Ast.Return( returnLabelTarget, Ast.Default(returnType) ) ) ) : Ast.Block( Ast.Call( typeof(RuntimeOps).GetMethod("GeneratorLoopProc"), _thread ), Ast.Return(returnLabelTarget) ) , // Ensuring that the catch block is of the same type as the try block Ast.Default(returnType) ), // Make sure that the debugMarker is up-to-date after the generator loop Ast.Assign( _debugMarker, Ast.Call( typeof(RuntimeOps).GetMethod("GetCurrentSequencePointForLeafGeneratorFrame"), _thread ) ) ) ) )); MSAst.Expression body = Ast.Block(bodyExpressions); if (body.Type == typeof(void) && returnType != typeof(void)) { body = Ast.Block(body, Ast.Default(returnType)); } return(Ast.Lambda( lambdaType, Ast.Block( _lambdaVars, Ast.Label(returnLabelTarget, body) ), _alias, _lambdaParams)); }