/// <summary> /// Gets all matching handle blocks for the given record type. /// </summary> /// <param name="recordTypeName">The name of the record type that should be handled.</param> /// <returns>A list of matching handle blocks.</returns> private IEnumerable <IHandleBlockData> GetHandleBlocks(IRecord eventRecord, string recordTypeName) { // check whether it is an exception bool isException = eventRecord.RecordType.IsType(ExceptionRecord.RECORD_TYPE_NAME); List <IHandleBlockData> listOfHandleBlocks = new List <IHandleBlockData>(); foreach (IScope scope in Memory.Scopes) { INestedScope nestedScope = scope as INestedScope; // check whether the scope is a block-scope that not is terminated if (nestedScope != null && nestedScope.IsTerminated == false) { // check whether the scope is from an OBSERVE-block IObserveScope observeScope = scope as IObserveScope; if (observeScope != null) { // check whether the OBSERVE-block handles the thrown exception var listOfMatchingHandleBlocks = from b in observeScope.HandleBlocks where RecordHelper.IsDerivedType(Memory, recordTypeName, b.HandledRecordType.Name) select b; listOfHandleBlocks.AddRange(listOfMatchingHandleBlocks); } // The behavior for exceptions is different than the behavior for events: // 1. An exception terminates all parent blocks until a HANDLE-block is found. // 2. Only one matching HANDLE-block is required to stop the exception. if (isException == true) { // mark the block as terminated nestedScope.IsTerminated = true; // if a HANDLE-block for the exception was found stop the search for other // HANDLE-blocks because an exception only breaks the current OBSERVE-block. if (listOfHandleBlocks.Count != 0) { return(listOfHandleBlocks); } } } } return(listOfHandleBlocks); }
/// <summary> /// Handles a .NET Exception that occurred during the interpretation of Synery code. /// </summary> /// <param name="exception">The thrown .NET Exception</param> /// <param name="context">The interpretation context that caused the Exception (e.g. used to print the line number).</param> /// <returns> /// false = Exception hasn't been handled, so please re-throw it. /// true = Exception handled. No further action is required. Continue interpretation. /// </returns> private bool HandleException(Exception exception, Antlr4.Runtime.ParserRuleContext context) { INestedScope nestedScope = Memory.Scopes.OfType <INestedScope>().FirstOrDefault(); if (nestedScope != null && nestedScope.IsTerminated == true && !(context is SyneryParser.ThrowStatementContext) && !(exception is InterfaceBoosterException)) { // The current block has already been terminated. // Therefore don't throw or create any new exceptions return(true); } else { if (context is SyneryParser.ObserveBlockContext) { // We're now in an OBSERVE-block. // Try to find a handle block that catches the exception. ExecutionExceptionRecord executionException = new ExecutionExceptionRecord(); executionException.Message = exception.Message; executionException.Line = context.Start.Line; executionException.CharPosition = context.Start.Column; this.HandleSyneryEvent(context, executionException.GetAsSyneryValue()); return(true); } if (exception is SyneryInterpretationException) { // The exception already is an interpretation exception. // Continue re-throwing it. return(false); } /* * It seems that the exception is not an interpretation exception. * Create a new exception and enrich it with the parser-context and a * new message that contains all messages from the nested exceptions. */ string message = string.Format("An unexpected error occurred while interpreting '{1}' on line {2}: {0}{3}", Environment.NewLine, context.GetText(), context.Start.Line, ExceptionHelper.GetNestedExceptionMessages(exception)); throw new SyneryInterpretationException(context, message, exception); } }
public void Run(SyneryParser.ReturnStatementContext context) { IValue returnValue = null; // check for a correct scope if (!(Memory.CurrentScope is INestedScope)) { string message = String.Format( "Return statement is expected to be inside of a block scope. CurrentScope is of type '{0}'", Memory.CurrentScope.GetType().Name); throw new SyneryInterpretationException(context, message); } if (context.expression() != null) { // evaluate expression for getting the value to return returnValue = Controller.Interpret <SyneryParser.ExpressionContext, IValue>(context.expression()); } // broadcast the termination up to the function block IScope scope = Memory.CurrentScope; while (scope is INestedScope) { INestedScope nestedScope = (INestedScope)scope; nestedScope.IsTerminated = true; if (scope is IFunctionScope) { // if its the scope of the function block break the loop and set the return value ((IFunctionScope)scope).ReturnValue = returnValue; break; } // get next scope from the scope tree scope = nestedScope.Parent; } }