mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 02:17:14 +00:00
Add support for finalizer of TryFinally in labeled statements
When a break is encountered in the body of a TryFinally statement to an enclosing label, the finalizer statement of the TryFinally is executed. BUG= R=dmitryas@google.com Review-Url: https://codereview.chromium.org/2991113002 .
This commit is contained in:
parent
771415a7c0
commit
115232ada2
|
@ -317,7 +317,8 @@ class State {
|
|||
continuation = null;
|
||||
|
||||
State withBreak(Statement stmt, Environment env) {
|
||||
Label breakLabels = new Label(stmt, env, continuation, labels);
|
||||
var cont = new BreakBK(continuation, env);
|
||||
Label breakLabels = new Label(stmt, cont, labels);
|
||||
return new State(
|
||||
breakLabels, exceptionComponents, returnContinuation, continuation);
|
||||
}
|
||||
|
@ -344,18 +345,23 @@ class State {
|
|||
/// enclosing label.
|
||||
class Label {
|
||||
final LabeledStatement statement;
|
||||
final Environment environment;
|
||||
final StatementContinuation continuation;
|
||||
final BreakContinuation continuation;
|
||||
final Label enclosingLabel;
|
||||
|
||||
Label(
|
||||
this.statement, this.environment, this.continuation, this.enclosingLabel);
|
||||
Label(this.statement, this.continuation, this.enclosingLabel);
|
||||
|
||||
Label lookupLabel(LabeledStatement s) {
|
||||
if (identical(s, statement)) return this;
|
||||
assert(enclosingLabel != null);
|
||||
return enclosingLabel.lookupLabel(s);
|
||||
}
|
||||
|
||||
// Recursively install finally break to all labels.
|
||||
Label withFinalizer(Statement finalizer, Environment env, State state) {
|
||||
var label = enclosingLabel?.withFinalizer(finalizer, env, state);
|
||||
var finallyCont = new FinallyBK(finalizer, env, state, continuation);
|
||||
return new Label(statement, finallyCont, label);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -456,6 +462,50 @@ class ThrowConfiguration extends Configuration {
|
|||
Configuration step(StatementExecuter _) => handler(exception, stacktrace);
|
||||
}
|
||||
|
||||
class BreakConfiguration extends Configuration {
|
||||
final BreakContinuation continuation;
|
||||
|
||||
BreakConfiguration(this.continuation);
|
||||
|
||||
Configuration step(StatementExecuter _) => continuation();
|
||||
}
|
||||
|
||||
abstract class BreakContinuation extends Continuation {
|
||||
Configuration call();
|
||||
}
|
||||
|
||||
class BreakBK extends BreakContinuation {
|
||||
final StatementContinuation continuation;
|
||||
final Environment environment;
|
||||
|
||||
BreakBK(this.continuation, this.environment);
|
||||
|
||||
Configuration call() => new ForwardConfiguration(continuation, environment);
|
||||
}
|
||||
|
||||
class FinallyBK extends BreakContinuation {
|
||||
final Statement finalizer;
|
||||
final Environment environment;
|
||||
final State state;
|
||||
final BreakContinuation continuation;
|
||||
|
||||
FinallyBK(this.finalizer, this.environment, this.state, this.continuation);
|
||||
|
||||
Configuration call() {
|
||||
var cont = new BreakSK(continuation);
|
||||
return new ExecConfiguration(
|
||||
finalizer, environment, state.withContinuation(cont));
|
||||
}
|
||||
}
|
||||
|
||||
class BreakSK extends StatementContinuation {
|
||||
final BreakContinuation continuation;
|
||||
|
||||
BreakSK(this.continuation);
|
||||
|
||||
Configuration call(Environment _) => new BreakConfiguration(continuation);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Interpreter Expressions and Values
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -1341,21 +1391,16 @@ class CatchHandler extends ExceptionHandler {
|
|||
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);
|
||||
final State state;
|
||||
|
||||
FinallyHandler(this.finallyStatement, this.environment, this.state);
|
||||
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);
|
||||
new RethrowSK(state.exceptionComponents.handler, exception, stackTrace);
|
||||
var newState = state.withContinuation(cont);
|
||||
return new ExecConfiguration(finallyStatement, environment, newState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1364,7 +1409,7 @@ class FinallyHandler extends ExceptionHandler {
|
|||
// ------------------------------------------------------------------------
|
||||
/// Represents the components for Exception handling.
|
||||
///
|
||||
/// It contains the list of exception handlers, a stack trace and optional
|
||||
/// It contains the current of exception handler, a stack trace and optional
|
||||
/// components, current stacktrace and exception.
|
||||
class ExceptionComponents {
|
||||
final ExceptionHandler handler;
|
||||
|
@ -1483,7 +1528,7 @@ class StatementExecuter
|
|||
Configuration visitBreakStatement(
|
||||
BreakStatement node, ExecConfiguration conf) {
|
||||
Label l = conf.state.lookupLabel(node.target);
|
||||
return new ForwardConfiguration(l.continuation, l.environment);
|
||||
return new BreakConfiguration(l.continuation);
|
||||
}
|
||||
|
||||
Configuration visitWhileStatement(
|
||||
|
@ -1517,22 +1562,30 @@ class StatementExecuter
|
|||
|
||||
Configuration visitTryCatch(TryCatch node, ExecConfiguration conf) {
|
||||
var handler = new CatchHandler(node.catches, conf.environment, conf.state);
|
||||
var handlers = new ExceptionComponents(
|
||||
var exceptionComponents = new ExceptionComponents(
|
||||
handler,
|
||||
conf.state.exceptionComponents.stackTrace,
|
||||
conf.state.exceptionComponents.currentStackTrace,
|
||||
conf.state.exceptionComponents.currentException);
|
||||
var state = conf.state.withException(handlers);
|
||||
var state = conf.state.withException(exceptionComponents);
|
||||
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));
|
||||
var labels = conf.state.labels
|
||||
?.withFinalizer(node.finalizer, conf.environment, conf.state);
|
||||
var handler =
|
||||
new FinallyHandler(node.finalizer, conf.environment, conf.state);
|
||||
var exceptionComponents = new ExceptionComponents(
|
||||
handler,
|
||||
conf.state.exceptionComponents.stackTrace,
|
||||
conf.state.exceptionComponents.currentStackTrace,
|
||||
conf.state.exceptionComponents.currentException);
|
||||
var state = new State(labels, exceptionComponents, returnCont, cont);
|
||||
return new ExecConfiguration(node.body, conf.environment, state);
|
||||
}
|
||||
|
||||
Configuration visitVariableDeclaration(
|
||||
|
|
18
pkg/kernel/testcases/interpreter/break_test.dart
Normal file
18
pkg/kernel/testcases/interpreter/break_test.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
main() {
|
||||
int i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
if (i == 5) {
|
||||
break;
|
||||
}
|
||||
} catch (e, _) {} finally {
|
||||
print('Finally with i=$i');
|
||||
}
|
||||
print(i);
|
||||
i++;
|
||||
}
|
||||
}
|
12
pkg/kernel/testcases/interpreter/break_test.dart.expect
Normal file
12
pkg/kernel/testcases/interpreter/break_test.dart.expect
Normal file
|
@ -0,0 +1,12 @@
|
|||
print(String: Finally with i=0)
|
||||
print(int: 0)
|
||||
print(String: Finally with i=1)
|
||||
print(int: 1)
|
||||
print(String: Finally with i=2)
|
||||
print(int: 2)
|
||||
print(String: Finally with i=3)
|
||||
print(int: 3)
|
||||
print(String: Finally with i=4)
|
||||
print(int: 4)
|
||||
if-then
|
||||
print(String: Finally with i=5)
|
Loading…
Reference in a new issue