OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library kernel.interpreter; | 4 library kernel.interpreter; |
5 | 5 |
6 import '../ast.dart'; | 6 import '../ast.dart'; |
7 import '../ast.dart' as ast show Class; | 7 import '../ast.dart' as ast show Class; |
8 | 8 |
9 import '../log.dart'; | 9 import '../log.dart'; |
10 export '../log.dart'; | 10 export '../log.dart'; |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 } | 323 } |
324 | 324 |
325 State withReturnContinuation(ExpressionContinuation returnCont) { | 325 State withReturnContinuation(ExpressionContinuation returnCont) { |
326 return new State(labels, exceptionComponents, returnCont, continuation); | 326 return new State(labels, exceptionComponents, returnCont, continuation); |
327 } | 327 } |
328 | 328 |
329 State withContinuation(StatementContinuation cont) { | 329 State withContinuation(StatementContinuation cont) { |
330 return new State(labels, exceptionComponents, returnContinuation, cont); | 330 return new State(labels, exceptionComponents, returnContinuation, cont); |
331 } | 331 } |
332 | 332 |
333 State withException(ExceptionComponents state) { | 333 State withException(ExceptionComponents ecs) { |
334 return new State(labels, state, returnContinuation, continuation); | 334 return new State(labels, ecs, returnContinuation, continuation); |
335 } | 335 } |
336 | 336 |
337 Label lookupLabel(LabeledStatement s) { | 337 Label lookupLabel(LabeledStatement s) { |
338 assert(labels != null); | 338 assert(labels != null); |
339 return labels.lookupLabel(s); | 339 return labels.lookupLabel(s); |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 /// Represents a labeled statement, the corresponding continuation and the | 343 /// Represents a labeled statement, the corresponding continuation and the |
344 /// enclosing label. | 344 /// enclosing label. |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 /// `List<InterpreterValue>`. | 437 /// `List<InterpreterValue>`. |
438 class ApplicationConfiguration extends Configuration { | 438 class ApplicationConfiguration extends Configuration { |
439 final ApplicationContinuation continuation; | 439 final ApplicationContinuation continuation; |
440 final List<InterpreterValue> values; | 440 final List<InterpreterValue> values; |
441 | 441 |
442 ApplicationConfiguration(this.continuation, this.values); | 442 ApplicationConfiguration(this.continuation, this.values); |
443 | 443 |
444 Configuration step(StatementExecuter _) => continuation(values); | 444 Configuration step(StatementExecuter _) => continuation(values); |
445 } | 445 } |
446 | 446 |
| 447 /// Configuration for applying an [ExceptionHandler] to an exception and a |
| 448 /// stack trace. |
447 class ThrowConfiguration extends Configuration { | 449 class ThrowConfiguration extends Configuration { |
448 final ExceptionHandler handler; | 450 final ExceptionHandler handler; |
449 final Value exception; | 451 final Value exception; |
450 final StackTrace stacktrace; | 452 final StackTrace stacktrace; |
451 | 453 |
452 ThrowConfiguration(this.handler, this.exception, this.stacktrace); | 454 ThrowConfiguration(this.handler, this.exception, this.stacktrace); |
453 | 455 |
454 Configuration step(StatementExecuter _) => handler(exception, stacktrace); | 456 Configuration step(StatementExecuter _) => handler(exception, stacktrace); |
455 } | 457 } |
456 | 458 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 | 601 |
600 ConstructorBodySK( | 602 ConstructorBodySK( |
601 this.body, this.environment, this.exceptionComponents, this.continuation); | 603 this.body, this.environment, this.exceptionComponents, this.continuation); |
602 | 604 |
603 Configuration call(Environment _) { | 605 Configuration call(Environment _) { |
604 return new ExecConfiguration(body, environment, | 606 return new ExecConfiguration(body, environment, |
605 new State(null, exceptionComponents, null, continuation)); | 607 new State(null, exceptionComponents, null, continuation)); |
606 } | 608 } |
607 } | 609 } |
608 | 610 |
| 611 /// Represents the statement continuation for execution of the finalizer |
| 612 /// statement. |
| 613 class FinallySK extends StatementContinuation { |
| 614 final Statement finallyStatement; |
| 615 final Environment environment; |
| 616 final State state; |
| 617 |
| 618 FinallySK(this.finallyStatement, this.environment, this.state); |
| 619 Configuration call(Environment _) { |
| 620 return new ExecConfiguration(finallyStatement, environment, state); |
| 621 } |
| 622 } |
| 623 |
| 624 /// Represents the statement continuation that applies the captured handler to |
| 625 /// the current exception. |
| 626 /// |
| 627 /// It is used as next statement continuation for the execution of the finalizer |
| 628 /// statement in [TryFinally] to ensure the finalizer is executed before |
| 629 /// applying the next handler to the current exception. |
| 630 class RethrowSK extends StatementContinuation { |
| 631 final ExceptionHandler handler; |
| 632 final Value exception; |
| 633 final StackTrace stackTrace; |
| 634 |
| 635 RethrowSK(this.handler, this.exception, this.stackTrace); |
| 636 |
| 637 Configuration call(Environment _) { |
| 638 return new ThrowConfiguration(handler, exception, stackTrace); |
| 639 } |
| 640 } |
| 641 |
609 // ------------------------------------------------------------------------ | 642 // ------------------------------------------------------------------------ |
610 // Application Continuations | 643 // Application Continuations |
611 // ------------------------------------------------------------------------ | 644 // ------------------------------------------------------------------------ |
612 | |
613 /// Represents the continuation called after the evaluation of argument | 645 /// Represents the continuation called after the evaluation of argument |
614 /// expressions. | 646 /// expressions. |
615 /// | 647 /// |
616 /// There are various kinds of [ApplicationContinuation] and their names are | 648 /// There are various kinds of [ApplicationContinuation] and their names are |
617 /// suffixed with "A". | 649 /// suffixed with "A". |
618 abstract class ApplicationContinuation extends Continuation { | 650 abstract class ApplicationContinuation extends Continuation { |
619 Configuration call(List<InterpreterValue> values); | 651 Configuration call(List<InterpreterValue> values); |
620 | 652 |
621 /// Binds actual argument values to formal parameters of the function in a | 653 /// Binds actual argument values to formal parameters of the function in a |
622 /// new environment or in the provided initial environment. | 654 /// new environment or in the provided initial environment. |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 final ExceptionComponents exceptionComponents; | 1265 final ExceptionComponents exceptionComponents; |
1234 | 1266 |
1235 ThrowEK(this.exceptionComponents); | 1267 ThrowEK(this.exceptionComponents); |
1236 | 1268 |
1237 Configuration call(Value value) { | 1269 Configuration call(Value value) { |
1238 return new ThrowConfiguration( | 1270 return new ThrowConfiguration( |
1239 exceptionComponents.handler, value, exceptionComponents.stackTrace); | 1271 exceptionComponents.handler, value, exceptionComponents.stackTrace); |
1240 } | 1272 } |
1241 } | 1273 } |
1242 | 1274 |
| 1275 /// Represents the expression continuation that ensures the finalizer of a |
| 1276 /// [TryFinally] node is executed before applying the return continuation to |
| 1277 /// the given value. |
| 1278 /// |
| 1279 /// It executes the captured finalizer statement and adds a statement |
| 1280 /// continuation that will apply the return continuation to the given value |
| 1281 /// when/if reached. |
| 1282 class FinallyReturnEK extends ExpressionContinuation { |
| 1283 final Statement statement; |
| 1284 final Environment environment; |
| 1285 final State state; |
| 1286 |
| 1287 FinallyReturnEK(this.statement, this.environment, this.state); |
| 1288 |
| 1289 Configuration call(Value value) { |
| 1290 return new ExecConfiguration(statement, environment, |
| 1291 state.withContinuation(new ExitSK(state.returnContinuation, value))); |
| 1292 } |
| 1293 } |
| 1294 |
1243 // ------------------------------------------------------------------------ | 1295 // ------------------------------------------------------------------------ |
1244 // Exceptions Handlers | 1296 // Exceptions Handlers |
1245 // ------------------------------------------------------------------------ | 1297 // ------------------------------------------------------------------------ |
1246 | 1298 |
1247 abstract class ExceptionHandler extends Continuation { | 1299 abstract class ExceptionHandler extends Continuation { |
1248 ExceptionHandler get nextHandler; | 1300 Configuration call(Value exception, StackTrace stacktrace); |
1249 | 1301 |
1250 Configuration call(Value exception, StackTrace stacktrace); | 1302 static String errorMessage(Value exception, StackTrace stacktrace) { |
| 1303 return 'Uncaught exception ' |
| 1304 '"${exception.value.runtimeType} : ${exception.value}"\n' |
| 1305 '${stacktrace.toString()}'; |
| 1306 } |
1251 } | 1307 } |
1252 | 1308 |
1253 /// Handler for showing an exception to the user and returning a halting the | 1309 /// Handler for showing an exception to the user and returning a halting the |
1254 /// execution of the program when an exception is not handled. | 1310 /// execution of the program when an exception is not handled. |
1255 class MainHandler extends ExceptionHandler { | 1311 class MainHandler extends ExceptionHandler { |
1256 ExceptionHandler get nextHandler => | 1312 Configuration call(Value exception, StackTrace stacktrace) { |
1257 throw 'The current handler is the main exception handler'; | 1313 var message = ExceptionHandler.errorMessage(exception, stacktrace); |
| 1314 log.info(message); |
| 1315 print(message); |
| 1316 return null; |
| 1317 } |
| 1318 } |
1258 | 1319 |
1259 Configuration call(Value exception, StackTrace stacktrace) { | 1320 /// Represents the handler that either executes a matching catch clause or |
1260 var errorMessage = 'Uncaught exception ' | 1321 /// applies the next handler to the given exception. |
1261 '"${exception.value.runtimeType} : ${exception.value}"\n' | 1322 class CatchHandler extends ExceptionHandler { |
1262 '${stacktrace.toString()}'; | 1323 final List<Catch> catches; |
1263 log.info(errorMessage); | 1324 final Environment environment; |
1264 print(errorMessage); | 1325 final State state; |
1265 return null; | 1326 |
| 1327 CatchHandler(this.catches, this.environment, this.state); |
| 1328 |
| 1329 Configuration call(Value exception, StackTrace stackTrace) { |
| 1330 // TODO(zhivkag): Check if there is a matching catch clause instead. |
| 1331 return new ThrowConfiguration( |
| 1332 state.exceptionComponents.handler, exception, stackTrace); |
| 1333 } |
| 1334 } |
| 1335 |
| 1336 /// Represents the handler that executes the corresponding finalizer before |
| 1337 /// applying the next handler to the given exception. |
| 1338 /// |
| 1339 /// Applying the next handler to the given exception is supported with adding |
| 1340 /// [RethrowSK] as next statement continuation. |
| 1341 class FinallyHandler extends ExceptionHandler { |
| 1342 final Statement finallyStatement; |
| 1343 final Environment environment; |
| 1344 final Label labels; |
| 1345 final ExceptionComponents exceptionComponents; |
| 1346 final ExpressionContinuation expressionContinuation; |
| 1347 |
| 1348 FinallyHandler(this.finallyStatement, this.environment, this.labels, |
| 1349 this.exceptionComponents, this.expressionContinuation); |
| 1350 |
| 1351 Configuration call(Value exception, StackTrace stackTrace) { |
| 1352 // A finally handler can't handle an exception, only execute the |
| 1353 // corresponding finally statement and rethrow. |
| 1354 var cont = |
| 1355 new RethrowSK(exceptionComponents.handler, exception, stackTrace); |
| 1356 var state = |
| 1357 new State(labels, exceptionComponents, expressionContinuation, cont); |
| 1358 return new ExecConfiguration(finallyStatement, environment, state); |
1266 } | 1359 } |
1267 } | 1360 } |
1268 | 1361 |
1269 // ------------------------------------------------------------------------ | 1362 // ------------------------------------------------------------------------ |
1270 // Exceptions | 1363 // Exceptions |
1271 // ------------------------------------------------------------------------ | 1364 // ------------------------------------------------------------------------ |
1272 /// Represents the components for Exception handling. | 1365 /// Represents the components for Exception handling. |
1273 /// | 1366 /// |
1274 /// It contains the list of exception handlers, a stack trace and optional | 1367 /// It contains the list of exception handlers, a stack trace and optional |
1275 /// components, current stacktrace and exception. | 1368 /// components, current stacktrace and exception. |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 assert(conf.state.returnContinuation != null); | 1508 assert(conf.state.returnContinuation != null); |
1416 log.info('return\n'); | 1509 log.info('return\n'); |
1417 if (node.expression == null) { | 1510 if (node.expression == null) { |
1418 return new ValuePassingConfiguration( | 1511 return new ValuePassingConfiguration( |
1419 conf.state.returnContinuation, Value.nullInstance); | 1512 conf.state.returnContinuation, Value.nullInstance); |
1420 } | 1513 } |
1421 return new EvalConfiguration(node.expression, conf.environment, | 1514 return new EvalConfiguration(node.expression, conf.environment, |
1422 conf.state.exceptionComponents, conf.state.returnContinuation); | 1515 conf.state.exceptionComponents, conf.state.returnContinuation); |
1423 } | 1516 } |
1424 | 1517 |
| 1518 Configuration visitTryCatch(TryCatch node, ExecConfiguration conf) { |
| 1519 var handler = new CatchHandler(node.catches, conf.environment, conf.state); |
| 1520 var handlers = new ExceptionComponents( |
| 1521 handler, |
| 1522 conf.state.exceptionComponents.stackTrace, |
| 1523 conf.state.exceptionComponents.currentStackTrace, |
| 1524 conf.state.exceptionComponents.currentException); |
| 1525 var state = conf.state.withException(handlers); |
| 1526 return new ExecConfiguration(node.body, conf.environment, state); |
| 1527 } |
| 1528 |
| 1529 Configuration visitTryFinally(TryFinally node, ExecConfiguration conf) { |
| 1530 // TODO(zhivkag): Add FinallyBreak to break labels. |
| 1531 var cont = new FinallySK(node.finalizer, conf.environment, conf.state); |
| 1532 var returnCont = |
| 1533 new FinallyReturnEK(node.finalizer, conf.environment, conf.state); |
| 1534 return new ExecConfiguration(node.body, conf.environment, |
| 1535 conf.state.withContinuation(cont).withReturnContinuation(returnCont)); |
| 1536 } |
| 1537 |
1425 Configuration visitVariableDeclaration( | 1538 Configuration visitVariableDeclaration( |
1426 VariableDeclaration node, ExecConfiguration conf) { | 1539 VariableDeclaration node, ExecConfiguration conf) { |
1427 if (node.initializer != null) { | 1540 if (node.initializer != null) { |
1428 var cont = new VariableInitializerEK( | 1541 var cont = new VariableInitializerEK( |
1429 node, conf.environment, conf.state.continuation); | 1542 node, conf.environment, conf.state.continuation); |
1430 return new EvalConfiguration(node.initializer, conf.environment, | 1543 return new EvalConfiguration(node.initializer, conf.environment, |
1431 conf.state.exceptionComponents, cont); | 1544 conf.state.exceptionComponents, cont); |
1432 } | 1545 } |
1433 return new ForwardConfiguration(conf.state.continuation, | 1546 return new ForwardConfiguration(conf.state.continuation, |
1434 conf.environment.extend(node, Value.nullInstance)); | 1547 conf.environment.extend(node, Value.nullInstance)); |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 /// Initializes all non initialized fields from the provided class to | 1840 /// Initializes all non initialized fields from the provided class to |
1728 /// `Value.nullInstance` in the provided value. | 1841 /// `Value.nullInstance` in the provided value. |
1729 void _initializeNullFields(Class class_, Value value) { | 1842 void _initializeNullFields(Class class_, Value value) { |
1730 int startIndex = class_.superclass?.instanceSize ?? 0; | 1843 int startIndex = class_.superclass?.instanceSize ?? 0; |
1731 for (int i = startIndex; i < class_.instanceSize; i++) { | 1844 for (int i = startIndex; i < class_.instanceSize; i++) { |
1732 if (value.fields[i].value == null) { | 1845 if (value.fields[i].value == null) { |
1733 value.fields[i].value = Value.nullInstance; | 1846 value.fields[i].value = Value.nullInstance; |
1734 } | 1847 } |
1735 } | 1848 } |
1736 } | 1849 } |
OLD | NEW |