| Index: pkg/kernel/lib/interpreter/interpreter.dart
|
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
|
| index d31d5d154aaa6d99a45aa92e7b6804a1fd64a2bb..6d88dd25abc92be2a0b161ffcc51b96aa29f8bf9 100644
|
| --- a/pkg/kernel/lib/interpreter/interpreter.dart
|
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart
|
| @@ -330,8 +330,8 @@ class State {
|
| return new State(labels, exceptionComponents, returnContinuation, cont);
|
| }
|
|
|
| - State withException(ExceptionComponents state) {
|
| - return new State(labels, state, returnContinuation, continuation);
|
| + State withException(ExceptionComponents ecs) {
|
| + return new State(labels, ecs, returnContinuation, continuation);
|
| }
|
|
|
| Label lookupLabel(LabeledStatement s) {
|
| @@ -444,6 +444,8 @@ class ApplicationConfiguration extends Configuration {
|
| Configuration step(StatementExecuter _) => continuation(values);
|
| }
|
|
|
| +/// Configuration for applying an [ExceptionHandler] to an exception and a
|
| +/// stack trace.
|
| class ThrowConfiguration extends Configuration {
|
| final ExceptionHandler handler;
|
| final Value exception;
|
| @@ -606,10 +608,40 @@ class ConstructorBodySK extends StatementContinuation {
|
| }
|
| }
|
|
|
| +/// Represents the statement continuation for execution of the finalizer
|
| +/// statement.
|
| +class FinallySK extends StatementContinuation {
|
| + final Statement finallyStatement;
|
| + final Environment environment;
|
| + final State state;
|
| +
|
| + FinallySK(this.finallyStatement, this.environment, this.state);
|
| + Configuration call(Environment _) {
|
| + return new ExecConfiguration(finallyStatement, environment, state);
|
| + }
|
| +}
|
| +
|
| +/// Represents the statement continuation that applies the captured handler to
|
| +/// the current exception.
|
| +///
|
| +/// It is used as next statement continuation for the execution of the finalizer
|
| +/// statement in [TryFinally] to ensure the finalizer is executed before
|
| +/// applying the next handler to the current exception.
|
| +class RethrowSK extends StatementContinuation {
|
| + final ExceptionHandler handler;
|
| + final Value exception;
|
| + final StackTrace stackTrace;
|
| +
|
| + RethrowSK(this.handler, this.exception, this.stackTrace);
|
| +
|
| + Configuration call(Environment _) {
|
| + return new ThrowConfiguration(handler, exception, stackTrace);
|
| + }
|
| +}
|
| +
|
| // ------------------------------------------------------------------------
|
| // Application Continuations
|
| // ------------------------------------------------------------------------
|
| -
|
| /// Represents the continuation called after the evaluation of argument
|
| /// expressions.
|
| ///
|
| @@ -1240,32 +1272,93 @@ class ThrowEK extends ExpressionContinuation {
|
| }
|
| }
|
|
|
| +/// Represents the expression continuation that ensures the finalizer of a
|
| +/// [TryFinally] node is executed before applying the return continuation to
|
| +/// the given value.
|
| +///
|
| +/// It executes the captured finalizer statement and adds a statement
|
| +/// continuation that will apply the return continuation to the given value
|
| +/// when/if reached.
|
| +class FinallyReturnEK extends ExpressionContinuation {
|
| + final Statement statement;
|
| + final Environment environment;
|
| + final State state;
|
| +
|
| + FinallyReturnEK(this.statement, this.environment, this.state);
|
| +
|
| + Configuration call(Value value) {
|
| + return new ExecConfiguration(statement, environment,
|
| + state.withContinuation(new ExitSK(state.returnContinuation, value)));
|
| + }
|
| +}
|
| +
|
| // ------------------------------------------------------------------------
|
| // Exceptions Handlers
|
| // ------------------------------------------------------------------------
|
|
|
| abstract class ExceptionHandler extends Continuation {
|
| - ExceptionHandler get nextHandler;
|
| -
|
| Configuration call(Value exception, StackTrace stacktrace);
|
| +
|
| + static String errorMessage(Value exception, StackTrace stacktrace) {
|
| + return 'Uncaught exception '
|
| + '"${exception.value.runtimeType} : ${exception.value}"\n'
|
| + '${stacktrace.toString()}';
|
| + }
|
| }
|
|
|
| /// Handler for showing an exception to the user and returning a halting the
|
| /// execution of the program when an exception is not handled.
|
| class MainHandler extends ExceptionHandler {
|
| - ExceptionHandler get nextHandler =>
|
| - throw 'The current handler is the main exception handler';
|
| -
|
| Configuration call(Value exception, StackTrace stacktrace) {
|
| - var errorMessage = 'Uncaught exception '
|
| - '"${exception.value.runtimeType} : ${exception.value}"\n'
|
| - '${stacktrace.toString()}';
|
| - log.info(errorMessage);
|
| - print(errorMessage);
|
| + var message = ExceptionHandler.errorMessage(exception, stacktrace);
|
| + log.info(message);
|
| + print(message);
|
| return null;
|
| }
|
| }
|
|
|
| +/// Represents the handler that either executes a matching catch clause or
|
| +/// applies the next handler to the given exception.
|
| +class CatchHandler extends ExceptionHandler {
|
| + final List<Catch> catches;
|
| + final Environment environment;
|
| + final State state;
|
| +
|
| + CatchHandler(this.catches, this.environment, this.state);
|
| +
|
| + Configuration call(Value exception, StackTrace stackTrace) {
|
| + // TODO(zhivkag): Check if there is a matching catch clause instead.
|
| + return new ThrowConfiguration(
|
| + state.exceptionComponents.handler, exception, stackTrace);
|
| + }
|
| +}
|
| +
|
| +/// Represents the handler that executes the corresponding finalizer before
|
| +/// applying the next handler to the given exception.
|
| +///
|
| +/// Applying the next handler to the given exception is supported with adding
|
| +/// [RethrowSK] as next statement continuation.
|
| +class FinallyHandler extends ExceptionHandler {
|
| + final Statement finallyStatement;
|
| + final Environment environment;
|
| + final Label labels;
|
| + final ExceptionComponents exceptionComponents;
|
| + final ExpressionContinuation expressionContinuation;
|
| +
|
| + FinallyHandler(this.finallyStatement, this.environment, this.labels,
|
| + this.exceptionComponents, this.expressionContinuation);
|
| +
|
| + Configuration call(Value exception, StackTrace stackTrace) {
|
| + // A finally handler can't handle an exception, only execute the
|
| + // corresponding finally statement and rethrow.
|
| + var cont =
|
| + new RethrowSK(exceptionComponents.handler, exception, stackTrace);
|
| + var state =
|
| + new State(labels, exceptionComponents, expressionContinuation, cont);
|
| + return new ExecConfiguration(finallyStatement, environment, state);
|
| + }
|
| +}
|
| +
|
| // ------------------------------------------------------------------------
|
| // Exceptions
|
| // ------------------------------------------------------------------------
|
| @@ -1422,6 +1515,26 @@ class StatementExecuter
|
| conf.state.exceptionComponents, conf.state.returnContinuation);
|
| }
|
|
|
| + Configuration visitTryCatch(TryCatch node, ExecConfiguration conf) {
|
| + var handler = new CatchHandler(node.catches, conf.environment, conf.state);
|
| + var handlers = new ExceptionComponents(
|
| + handler,
|
| + conf.state.exceptionComponents.stackTrace,
|
| + conf.state.exceptionComponents.currentStackTrace,
|
| + conf.state.exceptionComponents.currentException);
|
| + var state = conf.state.withException(handlers);
|
| + return new ExecConfiguration(node.body, conf.environment, state);
|
| + }
|
| +
|
| + Configuration visitTryFinally(TryFinally node, ExecConfiguration conf) {
|
| + // TODO(zhivkag): Add FinallyBreak to break labels.
|
| + var cont = new FinallySK(node.finalizer, conf.environment, conf.state);
|
| + var returnCont =
|
| + new FinallyReturnEK(node.finalizer, conf.environment, conf.state);
|
| + return new ExecConfiguration(node.body, conf.environment,
|
| + conf.state.withContinuation(cont).withReturnContinuation(returnCont));
|
| + }
|
| +
|
| Configuration visitVariableDeclaration(
|
| VariableDeclaration node, ExecConfiguration conf) {
|
| if (node.initializer != null) {
|
|
|