Chromium Code Reviews| 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 25 matching lines...) Expand all Loading... | |
| 36 } | 36 } |
| 37 } | 37 } |
| 38 | 38 |
| 39 class Binding { | 39 class Binding { |
| 40 final VariableDeclaration variable; | 40 final VariableDeclaration variable; |
| 41 Value value; | 41 Value value; |
| 42 | 42 |
| 43 Binding(this.variable, this.value); | 43 Binding(this.variable, this.value); |
| 44 } | 44 } |
| 45 | 45 |
| 46 class Environment { | 46 abstract class Environment { |
|
Dmitry Stefantsov
2017/05/16 08:07:50
I'd rather handle the case of 'this' with a couple
zhivkag
2017/05/16 10:51:13
I see the limitations the previous hierarchy intro
Dmitry Stefantsov
2017/05/16 11:06:52
To me, additional methods look simpler and easier
| |
| 47 final List<Binding> bindings = <Binding>[]; | 47 final List<Binding> bindings = <Binding>[]; |
| 48 final Environment parent; | 48 Environment get parent; |
| 49 | 49 |
| 50 Environment.empty() : parent = null; | 50 Environment(); |
| 51 Environment(this.parent); | 51 factory Environment.withParent(Environment parent) { |
| 52 if (parent is StaticEnvironment) { | |
| 53 return new StaticEnvironment(parent); | |
| 54 } | |
| 55 assert(parent is InstanceEnvironment); | |
| 56 return new InstanceEnvironment(parent); | |
| 57 } | |
| 52 | 58 |
| 53 bool contains(VariableDeclaration variable) { | 59 bool contains(VariableDeclaration variable) { |
| 54 for (Binding b in bindings.reversed) { | 60 for (Binding b in bindings.reversed) { |
| 55 if (identical(b.variable, variable)) return true; | 61 if (identical(b.variable, variable)) return true; |
| 56 } | 62 } |
| 57 return parent?.contains(variable) ?? false; | 63 return parent?.contains(variable) ?? false; |
| 58 } | 64 } |
| 59 | 65 |
| 60 Binding lookupBinding(VariableDeclaration variable) { | 66 Binding lookupBinding(VariableDeclaration variable) { |
| 61 assert(contains(variable)); | 67 assert(contains(variable)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 73 assert(contains(variable)); | 79 assert(contains(variable)); |
| 74 lookupBinding(variable).value = value; | 80 lookupBinding(variable).value = value; |
| 75 } | 81 } |
| 76 | 82 |
| 77 void expand(VariableDeclaration variable, Value value) { | 83 void expand(VariableDeclaration variable, Value value) { |
| 78 assert(!contains(variable)); | 84 assert(!contains(variable)); |
| 79 bindings.add(new Binding(variable, value)); | 85 bindings.add(new Binding(variable, value)); |
| 80 } | 86 } |
| 81 } | 87 } |
| 82 | 88 |
| 89 class StaticEnvironment extends Environment { | |
| 90 final StaticEnvironment parent; | |
| 91 StaticEnvironment.empty() : parent = null; | |
| 92 StaticEnvironment(this.parent); | |
| 93 } | |
| 94 | |
| 95 class InstanceEnvironment extends Environment { | |
| 96 final Value _thisInstance; | |
| 97 final InstanceEnvironment parent; | |
| 98 | |
| 99 get thisInstance => _thisInstance ?? parent.thisInstance; | |
|
Dmitry Stefantsov
2017/05/16 08:07:50
Just in case we decide to go with environment clas
zhivkag
2017/05/16 10:51:13
Done.
| |
| 100 | |
| 101 InstanceEnvironment.initial(this._thisInstance) : parent = null; | |
| 102 InstanceEnvironment(this.parent) : _thisInstance = null; | |
| 103 } | |
| 104 | |
| 83 /// Evaluate expressions. | 105 /// Evaluate expressions. |
| 84 class Evaluator | 106 class Evaluator |
| 85 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { | 107 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { |
| 86 Configuration eval(Expression expr, ExpressionConfiguration config) => | 108 Configuration eval(Expression expr, ExpressionConfiguration config) => |
| 87 expr.accept1(this, config); | 109 expr.accept1(this, config); |
| 88 | 110 |
| 89 Configuration evalList(List<InterpreterExpression> list, Environment env, | 111 Configuration evalList(List<InterpreterExpression> list, Environment env, |
| 90 ApplicationContinuation cont) { | 112 ApplicationContinuation cont) { |
| 91 if (list.isNotEmpty) { | 113 if (list.isNotEmpty) { |
| 92 return new ExpressionConfiguration(list.first.expression, env, | 114 return new ExpressionConfiguration(list.first.expression, env, |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 // Currently supports only method invocation with <2 arguments and is used | 184 // Currently supports only method invocation with <2 arguments and is used |
| 163 // to evaluate implemented operators for int, double and String values. | 185 // to evaluate implemented operators for int, double and String values. |
| 164 var cont = new MethodInvocationContinuation( | 186 var cont = new MethodInvocationContinuation( |
| 165 node.arguments, node.name, config.environment, config.continuation); | 187 node.arguments, node.name, config.environment, config.continuation); |
| 166 | 188 |
| 167 return new ExpressionConfiguration(node.receiver, config.environment, cont); | 189 return new ExpressionConfiguration(node.receiver, config.environment, cont); |
| 168 } | 190 } |
| 169 | 191 |
| 170 Configuration visitConstructorInvocation( | 192 Configuration visitConstructorInvocation( |
| 171 ConstructorInvocation node, ExpressionConfiguration config) { | 193 ConstructorInvocation node, ExpressionConfiguration config) { |
| 172 // Currently, the bodies of the constructors are not executed. | |
| 173 // Currently initializer list is executed only for redirecting | |
| 174 // constructors. | |
| 175 if (node.target.function.body is! EmptyStatement) { | |
| 176 throw 'Execution for body of constructor is not implemented.'; | |
| 177 } | |
| 178 | |
| 179 var class_ = new Class(node.target.enclosingClass.reference); | 194 var class_ = new Class(node.target.enclosingClass.reference); |
| 180 var newObject = | 195 var newObject = |
| 181 new ObjectValue(class_, new List<Value>(class_.instanceSize)); | 196 new ObjectValue(class_, new List<Value>(class_.instanceSize)); |
| 182 | 197 var nextConfig = |
| 198 new NewInstanceConfiguration(config.continuation, newObject); | |
| 183 ApplicationContinuation cont = new ConstructorInvocationApplication( | 199 ApplicationContinuation cont = new ConstructorInvocationApplication( |
| 184 newObject, node.target, config.continuation); | 200 newObject, node.target, nextConfig); |
|
Dmitry Stefantsov
2017/05/16 08:07:50
I think it's better to keep 'config.continuation'
zhivkag
2017/05/16 10:51:13
Acknowledged.
| |
| 185 | |
| 186 var args = | 201 var args = |
| 187 _createArgumentExpressionList(node.arguments, node.target.function); | 202 _createArgumentExpressionList(node.arguments, node.target.function); |
| 188 | 203 |
| 189 return new ExpressionListConfiguration(args, config.environment, cont); | 204 return new ExpressionListConfiguration(args, config.environment, cont); |
| 190 } | 205 } |
| 191 | 206 |
| 192 Configuration visitNot(Not node, ExpressionConfiguration config) { | 207 Configuration visitNot(Not node, ExpressionConfiguration config) { |
| 193 return new ExpressionConfiguration(node.operand, config.environment, | 208 return new ExpressionConfiguration(node.operand, config.environment, |
| 194 new NotContinuation(config.continuation)); | 209 new NotContinuation(config.continuation)); |
| 195 } | 210 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 217 } | 232 } |
| 218 | 233 |
| 219 Configuration visitStringConcatenation( | 234 Configuration visitStringConcatenation( |
| 220 StringConcatenation node, ExpressionConfiguration config) { | 235 StringConcatenation node, ExpressionConfiguration config) { |
| 221 var cont = new StringConcatenationContinuation( | 236 var cont = new StringConcatenationContinuation( |
| 222 node.expressions, config.environment, config.continuation); | 237 node.expressions, config.environment, config.continuation); |
| 223 return new ExpressionConfiguration( | 238 return new ExpressionConfiguration( |
| 224 node.expressions.first, config.environment, cont); | 239 node.expressions.first, config.environment, cont); |
| 225 } | 240 } |
| 226 | 241 |
| 242 Configuration visitThisExpression( | |
| 243 ThisExpression node, ExpressionConfiguration config) { | |
| 244 InstanceEnvironment env = config.environment; | |
| 245 return new ContinuationConfiguration(config.continuation, env.thisInstance); | |
| 246 } | |
| 247 | |
| 227 // Evaluation of BasicLiterals. | 248 // Evaluation of BasicLiterals. |
| 228 Configuration visitStringLiteral( | 249 Configuration visitStringLiteral( |
| 229 StringLiteral node, ExpressionConfiguration config) { | 250 StringLiteral node, ExpressionConfiguration config) { |
| 230 return new ContinuationConfiguration( | 251 return new ContinuationConfiguration( |
| 231 config.continuation, new StringValue(node.value)); | 252 config.continuation, new StringValue(node.value)); |
| 232 } | 253 } |
| 233 | 254 |
| 234 Configuration visitIntLiteral( | 255 Configuration visitIntLiteral( |
| 235 IntLiteral node, ExpressionConfiguration config) { | 256 IntLiteral node, ExpressionConfiguration config) { |
| 236 return new ContinuationConfiguration( | 257 return new ContinuationConfiguration( |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 267 class State { | 288 class State { |
| 268 final Environment environment; | 289 final Environment environment; |
| 269 final Label labels; | 290 final Label labels; |
| 270 final StatementConfiguration statementConfiguration; | 291 final StatementConfiguration statementConfiguration; |
| 271 | 292 |
| 272 final ExpressionContinuation returnContinuation; | 293 final ExpressionContinuation returnContinuation; |
| 273 | 294 |
| 274 State(this.environment, this.labels, this.statementConfiguration, | 295 State(this.environment, this.labels, this.statementConfiguration, |
| 275 this.returnContinuation); | 296 this.returnContinuation); |
| 276 | 297 |
| 277 State.initial() : this(new Environment.empty(), null, null, null); | 298 State.initial() : this(new StaticEnvironment.empty(), null, null, null); |
| 278 | 299 |
| 279 State withEnvironment(Environment env) { | 300 State withEnvironment(Environment env) { |
| 280 return new State(env, labels, statementConfiguration, returnContinuation); | 301 return new State(env, labels, statementConfiguration, returnContinuation); |
| 281 } | 302 } |
| 282 | 303 |
| 283 State withBreak(Statement stmt) { | 304 State withBreak(Statement stmt) { |
| 284 Label breakLabels = new Label(stmt, statementConfiguration, labels); | 305 Label breakLabels = new Label(stmt, statementConfiguration, labels); |
| 285 return new State( | 306 return new State( |
| 286 environment, breakLabels, statementConfiguration, returnContinuation); | 307 environment, breakLabels, statementConfiguration, returnContinuation); |
| 287 } | 308 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 330 | 351 |
| 331 Configuration step(StatementExecuter executer) => | 352 Configuration step(StatementExecuter executer) => |
| 332 executer.exec(statement, state); | 353 executer.exec(statement, state); |
| 333 } | 354 } |
| 334 | 355 |
| 335 class ExitConfiguration extends StatementConfiguration { | 356 class ExitConfiguration extends StatementConfiguration { |
| 336 final ExpressionContinuation returnContinuation; | 357 final ExpressionContinuation returnContinuation; |
| 337 | 358 |
| 338 ExitConfiguration(this.returnContinuation) : super(null, null); | 359 ExitConfiguration(this.returnContinuation) : super(null, null); |
| 339 | 360 |
| 340 Configuration step(StatementExecuter executer) { | 361 Configuration step(StatementExecuter _) { |
| 341 return returnContinuation(Value.nullInstance); | 362 return returnContinuation(Value.nullInstance); |
| 342 } | 363 } |
| 343 } | 364 } |
| 344 | 365 |
| 366 class NewInstanceConfiguration extends StatementConfiguration { | |
|
Dmitry Stefantsov
2017/05/16 08:07:50
In case we decide to keep the intermediate configu
Dmitry Stefantsov
2017/05/16 09:59:24
Thank you for the explanation offline about the 'N
zhivkag
2017/05/16 10:51:13
I assume some of the other comments were clarified
| |
| 367 final ExpressionContinuation continuation; | |
| 368 final ObjectValue newObject; | |
| 369 | |
| 370 NewInstanceConfiguration(this.continuation, this.newObject) | |
| 371 : super(null, new State.initial()); | |
| 372 | |
| 373 Configuration step(StatementExecuter _) { | |
| 374 return continuation(newObject); | |
| 375 } | |
| 376 } | |
| 377 | |
| 345 /// Represents the configuration for applying an [ExpressionContinuation]. | 378 /// Represents the configuration for applying an [ExpressionContinuation]. |
| 346 class ContinuationConfiguration extends Configuration { | 379 class ContinuationConfiguration extends Configuration { |
| 347 final ExpressionContinuation continuation; | 380 final ExpressionContinuation continuation; |
| 348 final Value value; | 381 final Value value; |
| 349 | 382 |
| 350 ContinuationConfiguration(this.continuation, this.value); | 383 ContinuationConfiguration(this.continuation, this.value); |
| 351 | 384 |
| 352 Configuration step(StatementExecuter _) => continuation(value); | 385 Configuration step(StatementExecuter _) => continuation(value); |
| 353 } | 386 } |
| 354 | 387 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 FieldInitializerValue(this.field, this.value); | 497 FieldInitializerValue(this.field, this.value); |
| 465 } | 498 } |
| 466 | 499 |
| 467 abstract class Continuation {} | 500 abstract class Continuation {} |
| 468 | 501 |
| 469 /// Represents the continuation called after the evaluation of argument | 502 /// Represents the continuation called after the evaluation of argument |
| 470 /// expressions. | 503 /// expressions. |
| 471 abstract class ApplicationContinuation extends Continuation { | 504 abstract class ApplicationContinuation extends Continuation { |
| 472 Configuration call(List<InterpreterValue> values); | 505 Configuration call(List<InterpreterValue> values); |
| 473 | 506 |
| 474 /// Creates an environment binding actual argument values to formal parameters | 507 /// Binds actual argument values to formal parameters of the function in a |
| 475 /// of the function in a new environment, which is used to execute the | 508 /// new environment or in the provided initial environment. |
| 476 /// body od the function. | |
| 477 /// TODO: Add checks for validation of arguments according to spec. | 509 /// TODO: Add checks for validation of arguments according to spec. |
| 478 static Environment createEnvironment( | 510 static Environment createEnvironment( |
| 479 FunctionNode function, List<InterpreterValue> args) { | 511 FunctionNode function, List<InterpreterValue> args, |
| 480 Environment newEnv = new Environment.empty(); | 512 [initialEnv]) { |
| 513 Environment newEnv = initialEnv ?? new StaticEnvironment.empty(); | |
| 481 List<PositionalArgumentValue> positional = args.reversed | 514 List<PositionalArgumentValue> positional = args.reversed |
| 482 .where((InterpreterValue av) => av is PositionalArgumentValue) | 515 .where((InterpreterValue av) => av is PositionalArgumentValue) |
| 483 .toList(); | 516 .toList(); |
| 484 | 517 |
| 485 // Add positional parameters. | 518 // Add positional parameters. |
| 486 for (int i = 0; i < positional.length; ++i) { | 519 for (int i = 0; i < positional.length; ++i) { |
| 487 newEnv.expand(function.positionalParameters[i], positional[i].value); | 520 newEnv.expand(function.positionalParameters[i], positional[i].value); |
| 488 } | 521 } |
| 489 | 522 |
| 490 Map<String, Value> named = new Map.fromIterable( | 523 Map<String, Value> named = new Map.fromIterable( |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 518 .withEnvironment(functionEnv); | 551 .withEnvironment(functionEnv); |
| 519 return new StatementConfiguration(function.body, bodyState); | 552 return new StatementConfiguration(function.body, bodyState); |
| 520 } | 553 } |
| 521 } | 554 } |
| 522 | 555 |
| 523 /// Represents the application continuation for constructor invocation applied | 556 /// Represents the application continuation for constructor invocation applied |
| 524 /// on the list of evaluated arguments. | 557 /// on the list of evaluated arguments. |
| 525 class ConstructorInvocationApplication extends ApplicationContinuation { | 558 class ConstructorInvocationApplication extends ApplicationContinuation { |
| 526 final ObjectValue newObject; | 559 final ObjectValue newObject; |
| 527 final Constructor constructor; | 560 final Constructor constructor; |
| 528 final ExpressionContinuation expressionContinuation; | 561 final StatementConfiguration configuration; |
|
Dmitry Stefantsov
2017/05/16 08:07:50
I think it's better to keep 'ExpressionContinuatio
zhivkag
2017/05/16 10:51:13
Acknowledged.
| |
| 529 | 562 |
| 530 ConstructorInvocationApplication( | 563 ConstructorInvocationApplication( |
| 531 this.newObject, this.constructor, this.expressionContinuation); | 564 this.newObject, this.constructor, this.configuration); |
| 532 | 565 |
| 533 Configuration call(List<InterpreterValue> argValues) { | 566 Configuration call(List<InterpreterValue> argValues) { |
| 534 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 567 var bodyEnv = new InstanceEnvironment.initial(newObject); |
| 535 constructor.function, argValues); | 568 InstanceEnvironment ctrEnv = ApplicationContinuation.createEnvironment( |
| 569 constructor.function, argValues, bodyEnv); | |
| 536 | 570 |
| 537 if (constructor.initializers.isNotEmpty && | 571 if (constructor.initializers.isNotEmpty && |
| 538 constructor.initializers.last is RedirectingInitializer) { | 572 constructor.initializers.last is RedirectingInitializer) { |
| 539 // Constructor is redirecting. | 573 // Constructor is redirecting. |
| 540 Initializer initializer = constructor.initializers.first; | 574 Initializer initializer = constructor.initializers.first; |
| 541 if (initializer is RedirectingInitializer) { | 575 if (initializer is RedirectingInitializer) { |
| 542 var app = new ConstructorInvocationApplication( | 576 var app = new ConstructorInvocationApplication( |
| 543 newObject, initializer.target, expressionContinuation); | 577 newObject, initializer.target, configuration); |
| 544 var args = _createArgumentExpressionList( | 578 var args = _createArgumentExpressionList( |
| 545 initializer.arguments, initializer.target.function); | 579 initializer.arguments, initializer.target.function); |
| 546 | 580 |
| 547 return new ExpressionListConfiguration(args, ctrEnv, app); | 581 return new ExpressionListConfiguration(args, ctrEnv, app); |
| 548 } | 582 } |
| 549 // Redirecting initializer is not the only initializer. | 583 // Redirecting initializer is not the only initializer. |
| 550 for (Initializer i in constructor.initializers.reversed.skip(1)) { | 584 for (Initializer i in constructor.initializers.reversed.skip(1)) { |
| 551 assert(i is LocalInitializer); | 585 assert(i is LocalInitializer); |
| 552 } | 586 } |
| 553 var class_ = new Class(constructor.enclosingClass.reference); | 587 var class_ = new Class(constructor.enclosingClass.reference); |
| 554 var cont = new InitializerContinuation(newObject, class_, ctrEnv, | 588 var cont = new InitializerContinuation( |
| 555 constructor.initializers, expressionContinuation); | 589 newObject, class_, ctrEnv, constructor.initializers, configuration); |
| 556 return new ExpressionConfiguration( | 590 return new ExpressionConfiguration( |
| 557 (initializer as LocalInitializer).variable.initializer, ctrEnv, cont); | 591 (initializer as LocalInitializer).variable.initializer, ctrEnv, cont); |
| 558 } | 592 } |
| 559 | 593 |
| 594 var newState = configuration.state | |
| 595 .withEnvironment(bodyEnv) | |
| 596 .withConfiguration(configuration); | |
|
Dmitry Stefantsov
2017/05/16 08:07:50
Here we might have used 'withExpressionContinuatio
zhivkag
2017/05/16 10:51:13
Acknowledged.
| |
| 597 | |
| 598 // Set head of configurations to be executed to configuration for current | |
| 599 // constructor body. | |
| 600 var nextConfiguration = | |
| 601 new StatementConfiguration(constructor.function.body, newState); | |
|
Dmitry Stefantsov
2017/05/16 08:07:50
Here we may assume that the body of constructor ha
zhivkag
2017/05/16 10:51:13
Acknowledged.
| |
| 602 | |
| 560 // Initialize fields in immediately enclosing class. | 603 // Initialize fields in immediately enclosing class. |
| 561 var cont = new InstanceFieldsApplication( | 604 var cont = new InstanceFieldsApplication( |
| 562 newObject, constructor, ctrEnv, expressionContinuation); | 605 newObject, constructor, ctrEnv, nextConfiguration); |
| 563 var fieldExpressions = _createInstanceInitializers(constructor); | 606 var fieldExpressions = _createInstanceInitializers(constructor); |
| 564 | 607 |
| 565 return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont); | 608 return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont); |
| 566 } | 609 } |
| 567 | 610 |
| 568 /// Creates a list of expressions for instance field initializers in | 611 /// Creates a list of expressions for instance field initializers in |
| 569 /// immediately enclosing class. | 612 /// immediately enclosing class. |
| 570 static List<InterpreterExpression> _createInstanceInitializers( | 613 static List<InterpreterExpression> _createInstanceInitializers( |
| 571 Constructor ctr) { | 614 Constructor ctr) { |
| 572 Class currentClass = new Class(ctr.enclosingClass.reference); | 615 Class currentClass = new Class(ctr.enclosingClass.reference); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 583 | 626 |
| 584 return es; | 627 return es; |
| 585 } | 628 } |
| 586 } | 629 } |
| 587 | 630 |
| 588 /// Represents the application continuation applied on the list of evaluated | 631 /// Represents the application continuation applied on the list of evaluated |
| 589 /// field initializer expressions. | 632 /// field initializer expressions. |
| 590 class InstanceFieldsApplication extends ApplicationContinuation { | 633 class InstanceFieldsApplication extends ApplicationContinuation { |
| 591 final ObjectValue newObject; | 634 final ObjectValue newObject; |
| 592 final Constructor constructor; | 635 final Constructor constructor; |
| 593 final Environment environment; | 636 final InstanceEnvironment environment; |
| 594 final ExpressionContinuation expressionContinuation; | 637 final StatementConfiguration configuration; |
| 595 | 638 |
| 596 final Class _currentClass; | 639 final Class _currentClass; |
| 597 | 640 |
| 598 InstanceFieldsApplication(this.newObject, this.constructor, this.environment, | 641 InstanceFieldsApplication( |
| 599 this.expressionContinuation) | 642 this.newObject, this.constructor, this.environment, this.configuration) |
| 600 : _currentClass = new Class(constructor.enclosingClass.reference); | 643 : _currentClass = new Class(constructor.enclosingClass.reference); |
| 601 | 644 |
| 602 Configuration call(List<InterpreterValue> fieldValues) { | 645 Configuration call(List<InterpreterValue> fieldValues) { |
| 603 for (FieldInitializerValue current in fieldValues.reversed) { | 646 for (FieldInitializerValue current in fieldValues.reversed) { |
| 604 _currentClass.setProperty(newObject, current.field, current.value); | 647 _currentClass.setProperty(newObject, current.field, current.value); |
| 605 } | 648 } |
| 606 | 649 |
| 607 if (constructor.initializers.isEmpty) { | 650 if (constructor.initializers.isEmpty) { |
| 608 _initializeNullFields(_currentClass, newObject); | 651 _initializeNullFields(_currentClass, newObject); |
| 609 return new ContinuationConfiguration(expressionContinuation, newObject); | 652 return configuration; |
| 610 } | 653 } |
| 611 | 654 |
| 612 if (constructor.initializers.first is SuperInitializer) { | 655 if (constructor.initializers.first is SuperInitializer) { |
| 613 // SuperInitializer appears last in the initializer list. | 656 // SuperInitializer appears last in the initializer list. |
| 614 assert(constructor.initializers.length == 1); | 657 assert(constructor.initializers.length == 1); |
| 615 SuperInitializer current = constructor.initializers.first; | 658 SuperInitializer current = constructor.initializers.first; |
| 616 var args = _createArgumentExpressionList( | 659 var args = _createArgumentExpressionList( |
| 617 current.arguments, current.target.function); | 660 current.arguments, current.target.function); |
| 618 var superApp = new ConstructorInvocationApplication( | 661 var superApp = new ConstructorInvocationApplication( |
| 619 newObject, current.target, expressionContinuation); | 662 newObject, current.target, configuration); |
| 620 _initializeNullFields(_currentClass, newObject); | 663 _initializeNullFields(_currentClass, newObject); |
| 621 return new ExpressionListConfiguration(args, environment, superApp); | 664 return new ExpressionListConfiguration(args, environment, superApp); |
| 622 } | 665 } |
| 623 | 666 |
| 624 Class class_ = new Class(constructor.enclosingClass.reference); | 667 Class class_ = new Class(constructor.enclosingClass.reference); |
| 625 Environment initEnv = new Environment(environment); | 668 InstanceEnvironment initEnv = new Environment.withParent(environment); |
| 626 | 669 |
| 627 var cont = new InitializerContinuation(newObject, class_, initEnv, | 670 var cont = new InitializerContinuation( |
| 628 constructor.initializers, expressionContinuation); | 671 newObject, class_, initEnv, constructor.initializers, configuration); |
| 629 return new ExpressionConfiguration( | 672 return new ExpressionConfiguration( |
| 630 _getExpression(constructor.initializers.first), initEnv, cont); | 673 _getExpression(constructor.initializers.first), initEnv, cont); |
| 631 } | 674 } |
| 632 } | 675 } |
| 633 | 676 |
| 634 /// Represents the expression continuation applied on the list of evaluated | 677 /// Represents the expression continuation applied on the list of evaluated |
| 635 /// initializer expressions preceding a super call in the list. | 678 /// initializer expressions preceding a super call in the list. |
| 636 class InitializerContinuation extends ExpressionContinuation { | 679 class InitializerContinuation extends ExpressionContinuation { |
| 637 final ObjectValue newObject; | 680 final ObjectValue newObject; |
| 638 final Class currentClass; | 681 final Class currentClass; |
| 639 final Environment initializerEnvironment; | 682 final InstanceEnvironment initializerEnvironment; |
| 640 final List<Initializer> initializers; | 683 final List<Initializer> initializers; |
| 641 final ExpressionContinuation continuation; | 684 final StatementConfiguration configuration; |
| 642 | 685 |
| 643 InitializerContinuation(this.newObject, this.currentClass, | 686 InitializerContinuation(this.newObject, this.currentClass, |
| 644 this.initializerEnvironment, this.initializers, this.continuation); | 687 this.initializerEnvironment, this.initializers, this.configuration); |
| 645 | 688 |
| 646 Configuration call(Value v) { | 689 Configuration call(Value v) { |
| 647 Initializer current = initializers.first; | 690 Initializer current = initializers.first; |
| 648 if (current is FieldInitializer) { | 691 if (current is FieldInitializer) { |
| 649 currentClass.setProperty(newObject, current.field, v); | 692 currentClass.setProperty(newObject, current.field, v); |
| 650 } else if (current is LocalInitializer) { | 693 } else if (current is LocalInitializer) { |
| 651 initializerEnvironment.expand(current.variable, v); | 694 initializerEnvironment.expand(current.variable, v); |
| 652 } else { | 695 } else { |
| 653 throw 'Assigning value $v to ${current.runtimeType}'; | 696 throw 'Assigning value $v to ${current.runtimeType}'; |
| 654 } | 697 } |
| 655 | 698 |
| 656 if (initializers.length <= 1) { | 699 if (initializers.length <= 1) { |
| 657 // todo: return configuration for body of ctr. | |
| 658 _initializeNullFields(currentClass, newObject); | 700 _initializeNullFields(currentClass, newObject); |
| 659 return new ContinuationConfiguration(continuation, newObject); | 701 return configuration; |
| 660 } | 702 } |
| 661 | 703 |
| 662 Initializer next = initializers[1]; | 704 Initializer next = initializers[1]; |
| 663 | 705 |
| 664 if (next is RedirectingInitializer) { | 706 if (next is RedirectingInitializer) { |
| 665 // RedirectingInitializer appears last in the initializer list. | 707 // RedirectingInitializer appears last in the initializer list. |
| 666 assert(initializers.length == 2); | 708 assert(initializers.length == 2); |
| 667 var cont = new ConstructorInvocationApplication( | 709 var cont = new ConstructorInvocationApplication( |
| 668 newObject, next.target, continuation); | 710 newObject, next.target, configuration); |
| 669 var args = | 711 var args = |
| 670 _createArgumentExpressionList(next.arguments, next.target.function); | 712 _createArgumentExpressionList(next.arguments, next.target.function); |
| 671 return new ExpressionListConfiguration( | 713 return new ExpressionListConfiguration( |
| 672 args, initializerEnvironment, cont); | 714 args, initializerEnvironment, cont); |
| 673 } | 715 } |
| 674 | 716 |
| 675 if (next is SuperInitializer) { | 717 if (next is SuperInitializer) { |
| 676 // SuperInitializer appears last in the initializer list. | 718 // SuperInitializer appears last in the initializer list. |
| 677 assert(initializers.length == 2); | 719 assert(initializers.length == 2); |
| 678 var args = | 720 var args = |
| 679 _createArgumentExpressionList(next.arguments, next.target.function); | 721 _createArgumentExpressionList(next.arguments, next.target.function); |
| 680 var superApp = new ConstructorInvocationApplication( | 722 var superApp = new ConstructorInvocationApplication( |
| 681 newObject, next.target, continuation); | 723 newObject, next.target, configuration); |
| 682 _initializeNullFields(currentClass, newObject); | 724 _initializeNullFields(currentClass, newObject); |
| 683 return new ExpressionListConfiguration( | 725 return new ExpressionListConfiguration( |
| 684 args, initializerEnvironment, superApp); | 726 args, initializerEnvironment, superApp); |
| 685 } | 727 } |
| 686 | 728 |
| 687 var cont = new InitializerContinuation(newObject, currentClass, | 729 var cont = new InitializerContinuation(newObject, currentClass, |
| 688 initializerEnvironment, initializers.skip(1).toList(), continuation); | 730 initializerEnvironment, initializers.skip(1).toList(), configuration); |
| 689 return new ExpressionConfiguration( | 731 return new ExpressionConfiguration( |
| 690 _getExpression(next), initializerEnvironment, cont); | 732 _getExpression(next), initializerEnvironment, cont); |
| 691 } | 733 } |
| 692 } | 734 } |
| 693 | 735 |
| 694 /// Represents the application continuation called after the evaluation of all | 736 /// Represents the application continuation called after the evaluation of all |
| 695 /// argument expressions for an invocation. | 737 /// argument expressions for an invocation. |
| 696 class ValueApplication extends ApplicationContinuation { | 738 class ValueApplication extends ApplicationContinuation { |
| 697 final InterpreterValue value; | 739 final InterpreterValue value; |
| 698 final ApplicationContinuation applicationContinuation; | 740 final ApplicationContinuation applicationContinuation; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 936 class LetContinuation extends ExpressionContinuation { | 978 class LetContinuation extends ExpressionContinuation { |
| 937 final VariableDeclaration variable; | 979 final VariableDeclaration variable; |
| 938 final Expression letBody; | 980 final Expression letBody; |
| 939 final Environment environment; | 981 final Environment environment; |
| 940 final ExpressionContinuation continuation; | 982 final ExpressionContinuation continuation; |
| 941 | 983 |
| 942 LetContinuation( | 984 LetContinuation( |
| 943 this.variable, this.letBody, this.environment, this.continuation); | 985 this.variable, this.letBody, this.environment, this.continuation); |
| 944 | 986 |
| 945 Configuration call(Value value) { | 987 Configuration call(Value value) { |
| 946 var letEnv = new Environment(environment); | 988 var letEnv = new Environment.withParent(environment); |
| 947 letEnv.expand(variable, value); | 989 letEnv.expand(variable, value); |
| 948 return new ExpressionConfiguration(letBody, letEnv, continuation); | 990 return new ExpressionConfiguration(letBody, letEnv, continuation); |
| 949 } | 991 } |
| 950 } | 992 } |
| 951 | 993 |
| 952 /// Represents the continuation for the condition expression in [WhileStatement] . | 994 /// Represents the continuation for the condition expression in [WhileStatement] . |
| 953 class WhileConditionContinuation extends ExpressionContinuation { | 995 class WhileConditionContinuation extends ExpressionContinuation { |
| 954 final WhileStatement node; | 996 final WhileStatement node; |
| 955 final State state; | 997 final State state; |
| 956 | 998 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1046 new ExpressionStatementContinuation(state.statementConfiguration); | 1088 new ExpressionStatementContinuation(state.statementConfiguration); |
| 1047 return new ExpressionConfiguration( | 1089 return new ExpressionConfiguration( |
| 1048 node.expression, state.environment, cont); | 1090 node.expression, state.environment, cont); |
| 1049 } | 1091 } |
| 1050 | 1092 |
| 1051 Configuration visitBlock(Block node, State state) { | 1093 Configuration visitBlock(Block node, State state) { |
| 1052 if (node.statements.isEmpty) { | 1094 if (node.statements.isEmpty) { |
| 1053 return state.statementConfiguration; | 1095 return state.statementConfiguration; |
| 1054 } | 1096 } |
| 1055 State blockState = | 1097 State blockState = |
| 1056 state.withEnvironment(new Environment(state.environment)); | 1098 state.withEnvironment(new Environment.withParent(state.environment)); |
| 1057 StatementConfiguration configuration = state.statementConfiguration; | 1099 StatementConfiguration configuration = state.statementConfiguration; |
| 1058 for (Statement s in node.statements.reversed) { | 1100 for (Statement s in node.statements.reversed) { |
| 1059 configuration = new StatementConfiguration( | 1101 configuration = new StatementConfiguration( |
| 1060 s, blockState.withConfiguration(configuration)); | 1102 s, blockState.withConfiguration(configuration)); |
| 1061 } | 1103 } |
| 1062 return configuration; | 1104 return configuration; |
| 1063 } | 1105 } |
| 1064 | 1106 |
| 1065 Configuration visitEmptyStatement(EmptyStatement node, State state) { | 1107 Configuration visitEmptyStatement(EmptyStatement node, State state) { |
| 1066 return state.statementConfiguration; | 1108 return state.statementConfiguration; |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1409 void _initializeNullFields(Class class_, ObjectValue newObject) { | 1451 void _initializeNullFields(Class class_, ObjectValue newObject) { |
| 1410 int superClassSize = class_.superclass?.instanceSize ?? 0; | 1452 int superClassSize = class_.superclass?.instanceSize ?? 0; |
| 1411 for (int i = superClassSize; i < class_.instanceSize; i++) { | 1453 for (int i = superClassSize; i < class_.instanceSize; i++) { |
| 1412 Field field = class_.instanceFields[i]; | 1454 Field field = class_.instanceFields[i]; |
| 1413 if (class_.getProperty(newObject, field) == null) { | 1455 if (class_.getProperty(newObject, field) == null) { |
| 1414 assert(field.initializer == null); | 1456 assert(field.initializer == null); |
| 1415 class_.setProperty(newObject, field, Value.nullInstance); | 1457 class_.setProperty(newObject, field, Value.nullInstance); |
| 1416 } | 1458 } |
| 1417 } | 1459 } |
| 1418 } | 1460 } |
| OLD | NEW |