/// <summary> /// Throws an exception. /// </summary> /// <param name="thrown"> /// The object to throw. It's recommended that this be a dictionary with a /// "name" parameter at the least. /// </param> public void throwException( State state, object thrown ) { // We want to have stack traces, so this is necessary... but we also want to // throw data objects and not C# objects. So we have to convert back and forth. if( !(thrown is CoralException) ) thrown = new CoralException( thrown ); var cex = (CoralException)thrown; if( cex.trace == null ) cex.setStackTrace( state ); thrown = cex.data; state.pushAction( new Step( this, st => { // We'll want to hold on to the finally runner if there is one. This will // let us properly handle nested exceptions. Step finallyStep = null; st.unwindActions( step => IsTryMarker( step ), this.finallyBlock != null ); if( this.finallyBlock != null ) finallyStep = st.popAction(); // The except block may have a parameter. if( this.exceptIdentifer != null ) { IScope exceptScope = new ParameterScope( st.scope, new string[] { this.exceptIdentifer } ); exceptScope.set( this.exceptIdentifer, thrown ); state.pushActionAndScope( new Step( this, a => {}, "except: scope" ), exceptScope ); } this.exceptBlock.run( st ); if( finallyStep != null ) { finallyStep.description = "finally block"; st.pushAction( finallyStep ); } }, "throw" ) ); }
public override void run( State state ) { // We execute by first evaluating the loopOver and then pushing one iteration of // the loop onto the action stack. Each iteration, if it completes successfully, // will push the next on. The array and current index are curried. We also push // a for loop marker on so that break works. state.pushAction( new Step( this, st => { object over = LValue.Deref( st ); IEnumerable<object> overTyped; if( over is List<object> ) overTyped = (IEnumerable<object>)over; else if( over is Dictionary<object,object> ) overTyped = ((Dictionary<object,object>)over).Keys; else throw CoralException.GetArg( "Value is not enumerable" ); IScope forScope = new ParameterScope( st.scope, new string[] { this.loopVariable } ); state.pushActionAndScope( new Step( this, a => {}, ScopeMarker ), forScope ); state.scope.set( this.loopVariable, null ); oneIteration( st, overTyped, 0 ); } ) ); this.loopOver.run( state ); }