Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(377)

Unified Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2985383002: Add partial support for TryFinally and TryCatch statements (Closed)
Patch Set: Merge Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/try_catch_finally_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/try_catch_finally_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698