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 29 matching lines...) Expand all Loading... | |
| 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 class Environment { |
| 47 final List<Binding> bindings = <Binding>[]; | 47 final List<Binding> bindings = <Binding>[]; |
| 48 final Environment parent; | 48 final Environment parent; |
| 49 | 49 |
| 50 Value get thisInstance => (parent != null) | |
| 51 ? parent.thisInstance | |
| 52 : throw "Invalid reference to 'this' expression"; | |
| 53 | |
| 50 Environment.empty() : parent = null; | 54 Environment.empty() : parent = null; |
| 51 Environment(this.parent); | 55 Environment(this.parent); |
| 52 | 56 |
| 53 bool contains(VariableDeclaration variable) { | 57 bool contains(VariableDeclaration variable) { |
| 54 for (Binding b in bindings.reversed) { | 58 for (Binding b in bindings.reversed) { |
| 55 if (identical(b.variable, variable)) return true; | 59 if (identical(b.variable, variable)) return true; |
| 56 } | 60 } |
| 57 return parent?.contains(variable) ?? false; | 61 return parent?.contains(variable) ?? false; |
| 58 } | 62 } |
| 59 | 63 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 73 assert(contains(variable)); | 77 assert(contains(variable)); |
| 74 lookupBinding(variable).value = value; | 78 lookupBinding(variable).value = value; |
| 75 } | 79 } |
| 76 | 80 |
| 77 void expand(VariableDeclaration variable, Value value) { | 81 void expand(VariableDeclaration variable, Value value) { |
| 78 assert(!contains(variable)); | 82 assert(!contains(variable)); |
| 79 bindings.add(new Binding(variable, value)); | 83 bindings.add(new Binding(variable, value)); |
| 80 } | 84 } |
| 81 } | 85 } |
| 82 | 86 |
| 87 class InstanceEnvironment extends Environment { | |
| 88 final ObjectValue _thisInstance; | |
| 89 Value get thisInstance => _thisInstance; | |
| 90 | |
| 91 InstanceEnvironment(this._thisInstance, Environment env) : super(env); | |
| 92 } | |
| 93 | |
| 83 /// Evaluate expressions. | 94 /// Evaluate expressions. |
| 84 class Evaluator | 95 class Evaluator |
| 85 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { | 96 extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { |
| 86 Configuration eval(Expression expr, ExpressionConfiguration config) => | 97 Configuration eval(Expression expr, ExpressionConfiguration config) => |
| 87 expr.accept1(this, config); | 98 expr.accept1(this, config); |
| 88 | 99 |
| 89 Configuration evalList(List<InterpreterExpression> list, Environment env, | 100 Configuration evalList(List<InterpreterExpression> list, Environment env, |
| 90 ApplicationContinuation cont) { | 101 ApplicationContinuation cont) { |
| 91 if (list.isNotEmpty) { | 102 if (list.isNotEmpty) { |
| 92 return new ExpressionConfiguration(list.first.expression, env, | 103 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 | 173 // Currently supports only method invocation with <2 arguments and is used |
| 163 // to evaluate implemented operators for int, double and String values. | 174 // to evaluate implemented operators for int, double and String values. |
| 164 var cont = new MethodInvocationContinuation( | 175 var cont = new MethodInvocationContinuation( |
| 165 node.arguments, node.name, config.environment, config.continuation); | 176 node.arguments, node.name, config.environment, config.continuation); |
| 166 | 177 |
| 167 return new ExpressionConfiguration(node.receiver, config.environment, cont); | 178 return new ExpressionConfiguration(node.receiver, config.environment, cont); |
| 168 } | 179 } |
| 169 | 180 |
| 170 Configuration visitConstructorInvocation( | 181 Configuration visitConstructorInvocation( |
| 171 ConstructorInvocation node, ExpressionConfiguration config) { | 182 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 ApplicationContinuation cont = | 183 ApplicationContinuation cont = |
| 180 new ConstructorInvocationApplication(node.target, config.continuation); | 184 new ConstructorInvocationApplication(node.target, config.continuation); |
| 181 | |
| 182 var args = | 185 var args = |
| 183 _createArgumentExpressionList(node.arguments, node.target.function); | 186 _createArgumentExpressionList(node.arguments, node.target.function); |
| 184 | 187 |
| 185 return new ExpressionListConfiguration(args, config.environment, cont); | 188 return new ExpressionListConfiguration(args, config.environment, cont); |
| 186 } | 189 } |
| 187 | 190 |
| 188 Configuration visitNot(Not node, ExpressionConfiguration config) { | 191 Configuration visitNot(Not node, ExpressionConfiguration config) { |
| 189 return new ExpressionConfiguration(node.operand, config.environment, | 192 return new ExpressionConfiguration(node.operand, config.environment, |
| 190 new NotContinuation(config.continuation)); | 193 new NotContinuation(config.continuation)); |
| 191 } | 194 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 215 Configuration visitStringConcatenation( | 218 Configuration visitStringConcatenation( |
| 216 StringConcatenation node, ExpressionConfiguration config) { | 219 StringConcatenation node, ExpressionConfiguration config) { |
| 217 var cont = new StringConcatenationContinuation(config.continuation); | 220 var cont = new StringConcatenationContinuation(config.continuation); |
| 218 var expressions = node.expressions | 221 var expressions = node.expressions |
| 219 .map((Expression e) => new PositionalExpression(e)) | 222 .map((Expression e) => new PositionalExpression(e)) |
| 220 .toList(); | 223 .toList(); |
| 221 return new ExpressionListConfiguration( | 224 return new ExpressionListConfiguration( |
| 222 expressions, config.environment, cont); | 225 expressions, config.environment, cont); |
| 223 } | 226 } |
| 224 | 227 |
| 228 Configuration visitThisExpression( | |
| 229 ThisExpression node, ExpressionConfiguration config) { | |
| 230 return new ContinuationConfiguration( | |
| 231 config.continuation, config.environment.thisInstance); | |
| 232 } | |
| 233 | |
| 225 // Evaluation of BasicLiterals. | 234 // Evaluation of BasicLiterals. |
| 226 Configuration visitStringLiteral( | 235 Configuration visitStringLiteral( |
| 227 StringLiteral node, ExpressionConfiguration config) { | 236 StringLiteral node, ExpressionConfiguration config) { |
| 228 return new ContinuationConfiguration( | 237 return new ContinuationConfiguration( |
| 229 config.continuation, new StringValue(node.value)); | 238 config.continuation, new StringValue(node.value)); |
| 230 } | 239 } |
| 231 | 240 |
| 232 Configuration visitIntLiteral( | 241 Configuration visitIntLiteral( |
| 233 IntLiteral node, ExpressionConfiguration config) { | 242 IntLiteral node, ExpressionConfiguration config) { |
| 234 return new ContinuationConfiguration( | 243 return new ContinuationConfiguration( |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 | 337 |
| 329 Configuration step(StatementExecuter executer) => | 338 Configuration step(StatementExecuter executer) => |
| 330 executer.exec(statement, state); | 339 executer.exec(statement, state); |
| 331 } | 340 } |
| 332 | 341 |
| 333 class ExitConfiguration extends StatementConfiguration { | 342 class ExitConfiguration extends StatementConfiguration { |
| 334 final ExpressionContinuation returnContinuation; | 343 final ExpressionContinuation returnContinuation; |
| 335 | 344 |
| 336 ExitConfiguration(this.returnContinuation) : super(null, null); | 345 ExitConfiguration(this.returnContinuation) : super(null, null); |
| 337 | 346 |
| 338 Configuration step(StatementExecuter executer) { | 347 Configuration step(StatementExecuter _) { |
| 339 return returnContinuation(Value.nullInstance); | 348 return returnContinuation(Value.nullInstance); |
| 340 } | 349 } |
| 341 } | 350 } |
| 342 | 351 |
| 352 class NewInstanceConfiguration extends StatementConfiguration { | |
| 353 final ExpressionContinuation continuation; | |
| 354 final ObjectValue newObject; | |
| 355 | |
| 356 NewInstanceConfiguration(this.continuation, this.newObject) | |
| 357 : super(null, new State.initial()); | |
| 358 | |
| 359 Configuration step(StatementExecuter _) { | |
| 360 return continuation(newObject); | |
| 361 } | |
| 362 } | |
| 363 | |
| 343 /// Represents the configuration for applying an [ExpressionContinuation]. | 364 /// Represents the configuration for applying an [ExpressionContinuation]. |
| 344 class ContinuationConfiguration extends Configuration { | 365 class ContinuationConfiguration extends Configuration { |
| 345 final ExpressionContinuation continuation; | 366 final ExpressionContinuation continuation; |
| 346 final Value value; | 367 final Value value; |
| 347 | 368 |
| 348 ContinuationConfiguration(this.continuation, this.value); | 369 ContinuationConfiguration(this.continuation, this.value); |
| 349 | 370 |
| 350 Configuration step(StatementExecuter _) => continuation(value); | 371 Configuration step(StatementExecuter _) => continuation(value); |
| 351 } | 372 } |
| 352 | 373 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 FieldInitializerValue(this.field, this.value); | 483 FieldInitializerValue(this.field, this.value); |
| 463 } | 484 } |
| 464 | 485 |
| 465 abstract class Continuation {} | 486 abstract class Continuation {} |
| 466 | 487 |
| 467 /// Represents the continuation called after the evaluation of argument | 488 /// Represents the continuation called after the evaluation of argument |
| 468 /// expressions. | 489 /// expressions. |
| 469 abstract class ApplicationContinuation extends Continuation { | 490 abstract class ApplicationContinuation extends Continuation { |
| 470 Configuration call(List<InterpreterValue> values); | 491 Configuration call(List<InterpreterValue> values); |
| 471 | 492 |
| 472 /// Creates an environment binding actual argument values to formal parameters | 493 /// Binds actual argument values to formal parameters of the function in a |
| 473 /// of the function in a new environment, which is used to execute the | 494 /// new environment or in the provided initial environment. |
| 474 /// body od the function. | |
| 475 /// TODO: Add checks for validation of arguments according to spec. | 495 /// TODO: Add checks for validation of arguments according to spec. |
| 476 static Environment createEnvironment( | 496 static Environment createEnvironment( |
| 477 FunctionNode function, List<InterpreterValue> args) { | 497 FunctionNode function, List<InterpreterValue> args, |
| 478 Environment newEnv = new Environment.empty(); | 498 [Environment parentEnv]) { |
| 499 Environment newEnv = new Environment(parentEnv); | |
| 479 List<PositionalValue> positional = args.reversed | 500 List<PositionalValue> positional = args.reversed |
| 480 .where((InterpreterValue av) => av is PositionalValue) | 501 .where((InterpreterValue av) => av is PositionalValue) |
| 481 .toList(); | 502 .toList(); |
| 482 | 503 |
| 483 // Add positional parameters. | 504 // Add positional parameters. |
| 484 for (int i = 0; i < positional.length; ++i) { | 505 for (int i = 0; i < positional.length; ++i) { |
| 485 newEnv.expand(function.positionalParameters[i], positional[i].value); | 506 newEnv.expand(function.positionalParameters[i], positional[i].value); |
| 486 } | 507 } |
| 487 | 508 |
| 488 Map<String, Value> named = new Map.fromIterable( | 509 Map<String, Value> named = new Map.fromIterable( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 ConstructorInvocationApplication(this.constructor, this.continuation); | 548 ConstructorInvocationApplication(this.constructor, this.continuation); |
| 528 | 549 |
| 529 Configuration call(List<InterpreterValue> argValues) { | 550 Configuration call(List<InterpreterValue> argValues) { |
| 530 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 551 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| 531 constructor.function, argValues); | 552 constructor.function, argValues); |
| 532 | 553 |
| 533 var class_ = new Class(constructor.enclosingClass.reference); | 554 var class_ = new Class(constructor.enclosingClass.reference); |
| 534 var newObject = | 555 var newObject = |
| 535 new ObjectValue(class_, new List<Value>(class_.instanceSize)); | 556 new ObjectValue(class_, new List<Value>(class_.instanceSize)); |
| 536 | 557 |
| 537 var cont = | 558 return new ObjectInitializationConfiguration( |
| 538 new ObjectInitializationContinuation(constructor, ctrEnv, continuation); | 559 constructor, |
| 539 | 560 new InstanceEnvironment(newObject, ctrEnv), |
| 540 return new ContinuationConfiguration(cont, newObject); | 561 new NewInstanceConfiguration(continuation, newObject)); |
|
Dmitry Stefantsov
2017/05/18 12:56:51
I think this statement would be hard to translate
| |
| 541 } | 562 } |
| 542 } | 563 } |
| 543 | 564 |
| 544 /// Represents the application continuation for redirecting constructor | 565 /// Represents the application continuation for redirecting constructor |
| 545 /// invocation applied on the list of evaluated arguments. | 566 /// invocation applied on the list of evaluated arguments. |
| 546 class RedirectingConstructorApplication extends ApplicationContinuation { | 567 class RedirectingConstructorApplication extends ApplicationContinuation { |
| 547 final ObjectValue newObject; | |
| 548 final Constructor constructor; | 568 final Constructor constructor; |
| 549 final ExpressionContinuation continuation; | 569 final Environment environment; |
| 570 final StatementConfiguration configuration; | |
| 550 | 571 |
| 551 RedirectingConstructorApplication( | 572 RedirectingConstructorApplication( |
| 552 this.newObject, this.constructor, this.continuation); | 573 this.constructor, this.environment, this.configuration); |
| 553 | 574 |
| 554 Configuration call(List<InterpreterValue> argValues) { | 575 Configuration call(List<InterpreterValue> argValues) { |
| 576 Value object = environment.thisInstance; | |
| 555 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 577 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| 556 constructor.function, argValues); | 578 constructor.function, |
| 557 var cont = | 579 argValues, |
| 558 new ObjectInitializationContinuation(constructor, ctrEnv, continuation); | 580 new InstanceEnvironment(object, new Environment.empty())); |
| 559 return new ContinuationConfiguration(cont, newObject); | 581 |
| 582 return new ObjectInitializationConfiguration( | |
| 583 constructor, ctrEnv, configuration); | |
| 560 } | 584 } |
| 561 } | 585 } |
| 562 | 586 |
| 563 /// Represents the application continuation for super constructor | 587 /// Represents the application continuation for super constructor |
| 564 /// invocation applied on the list of evaluated arguments. | 588 /// invocation applied on the list of evaluated arguments. |
| 565 class SuperConstructorApplication extends ApplicationContinuation { | 589 class SuperConstructorApplication extends ApplicationContinuation { |
| 566 final ObjectValue newObject; | |
| 567 final Constructor constructor; | 590 final Constructor constructor; |
| 568 // TODO: remember to execute body of previous ctr. | 591 final Environment environment; |
| 569 final ExpressionContinuation continuation; | 592 final StatementConfiguration configuration; |
| 570 | 593 |
| 571 SuperConstructorApplication( | 594 SuperConstructorApplication( |
| 572 this.newObject, this.constructor, this.continuation); | 595 this.constructor, this.environment, this.configuration); |
| 573 | 596 |
| 574 Configuration call(List<InterpreterValue> argValues) { | 597 Configuration call(List<InterpreterValue> argValues) { |
| 575 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 598 Value object = environment.thisInstance; |
| 576 constructor.function, argValues); | 599 |
| 577 var cont = | 600 Environment superEnv = ApplicationContinuation.createEnvironment( |
| 578 new ObjectInitializationContinuation(constructor, ctrEnv, continuation); | 601 constructor.function, |
| 579 return new ContinuationConfiguration(cont, newObject); | 602 argValues, |
| 603 new InstanceEnvironment(object, new Environment.empty())); | |
| 604 | |
| 605 return new ObjectInitializationConfiguration( | |
| 606 constructor, superEnv, configuration); | |
| 580 } | 607 } |
| 581 } | 608 } |
| 582 | 609 |
| 583 class ObjectInitializationContinuation extends ExpressionContinuation { | 610 /// Represents the configuration for execution of initializer and |
| 611 /// constructor body statements for initialization of a newly allocated object. | |
| 612 class ObjectInitializationConfiguration extends Configuration { | |
| 584 final Constructor constructor; | 613 final Constructor constructor; |
| 585 final Environment environment; | 614 final Environment environment; |
| 586 final ExpressionContinuation continuation; | 615 final StatementConfiguration configuration; |
| 587 | 616 |
| 588 ObjectInitializationContinuation( | 617 ObjectInitializationConfiguration( |
| 589 this.constructor, this.environment, this.continuation); | 618 this.constructor, this.environment, this.configuration); |
| 590 | 619 |
| 591 Configuration call(Value v) { | 620 Configuration step(StatementExecuter _) { |
| 592 if (constructor.initializers.isNotEmpty && | 621 if (constructor.initializers.isNotEmpty && |
| 593 constructor.initializers.last is RedirectingInitializer) { | 622 constructor.initializers.last is RedirectingInitializer) { |
| 594 // Constructor is redirecting. | 623 // Constructor is redirecting. |
| 595 Initializer initializer = constructor.initializers.first; | 624 Initializer initializer = constructor.initializers.first; |
| 596 if (initializer is RedirectingInitializer) { | 625 if (initializer is RedirectingInitializer) { |
| 597 var app = new RedirectingConstructorApplication( | 626 var app = new RedirectingConstructorApplication( |
| 598 v, initializer.target, continuation); | 627 initializer.target, environment, configuration); |
| 599 var args = _createArgumentExpressionList( | 628 var args = _createArgumentExpressionList( |
| 600 initializer.arguments, initializer.target.function); | 629 initializer.arguments, initializer.target.function); |
| 601 | 630 |
| 602 return new ExpressionListConfiguration(args, environment, app); | 631 return new ExpressionListConfiguration(args, environment, app); |
| 603 } | 632 } |
| 604 // Redirecting initializer is not the only initializer. | 633 // Redirecting initializer is not the only initializer. |
| 605 for (Initializer i in constructor.initializers.reversed.skip(1)) { | 634 for (Initializer i in constructor.initializers.reversed.skip(1)) { |
| 606 assert(i is LocalInitializer); | 635 assert(i is LocalInitializer); |
| 607 } | 636 } |
| 608 var class_ = new Class(constructor.enclosingClass.reference); | 637 var class_ = new Class(constructor.enclosingClass.reference); |
| 638 var initEnv = new Environment(environment); | |
| 609 var cont = new InitializerContinuation( | 639 var cont = new InitializerContinuation( |
| 610 v, class_, environment, constructor.initializers, continuation); | 640 class_, initEnv, constructor.initializers, configuration); |
| 611 return new ExpressionConfiguration( | 641 return new ExpressionConfiguration( |
| 612 (initializer as LocalInitializer).variable.initializer, | 642 (initializer as LocalInitializer).variable.initializer, |
| 613 environment, | 643 initEnv, |
| 614 cont); | 644 cont); |
| 615 } | 645 } |
| 616 | 646 |
| 647 // Set head of configurations to be executed to configuration for current | |
| 648 // constructor body. | |
| 649 var state = new State.initial() | |
| 650 .withEnvironment(environment) | |
| 651 .withConfiguration(configuration); | |
| 652 var bodyConfig = | |
| 653 new StatementConfiguration(constructor.function.body, state); | |
| 654 | |
| 617 // Initialize fields in immediately enclosing class. | 655 // Initialize fields in immediately enclosing class. |
| 618 var cont = new InstanceFieldsApplication( | 656 var cont = |
| 619 v, constructor, environment, continuation); | 657 new InstanceFieldsApplication(constructor, environment, bodyConfig); |
| 620 var fieldExpressions = _createInstanceInitializers(constructor); | 658 var fieldExpressions = _createInstanceInitializers(constructor); |
| 621 | 659 |
| 622 return new ExpressionListConfiguration( | 660 return new ExpressionListConfiguration( |
| 623 fieldExpressions, new Environment.empty(), cont); | 661 fieldExpressions, new Environment.empty(), cont); |
| 624 } | 662 } |
| 625 | 663 |
| 626 /// Creates a list of expressions for instance field initializers in | 664 /// Creates a list of expressions for instance field initializers in |
| 627 /// immediately enclosing class. | 665 /// immediately enclosing class. |
| 628 static List<InterpreterExpression> _createInstanceInitializers( | 666 static List<InterpreterExpression> _createInstanceInitializers( |
| 629 Constructor ctr) { | 667 Constructor ctr) { |
| 630 Class currentClass = new Class(ctr.enclosingClass.reference); | 668 Class currentClass = new Class(ctr.enclosingClass.reference); |
| 631 List<InterpreterExpression> es = <InterpreterExpression>[]; | 669 List<InterpreterExpression> es = <InterpreterExpression>[]; |
| 632 | 670 |
| 633 for (int i = currentClass.superclass?.instanceSize ?? 0; | 671 for (int i = currentClass.superclass?.instanceSize ?? 0; |
| 634 i < currentClass.instanceSize; | 672 i < currentClass.instanceSize; |
| 635 i++) { | 673 i++) { |
| 636 Field current = currentClass.instanceFields[i]; | 674 Field current = currentClass.instanceFields[i]; |
| 637 if (current.initializer != null) { | 675 if (current.initializer != null) { |
| 638 es.add(new FieldInitializerExpression(current, current.initializer)); | 676 es.add(new FieldInitializerExpression(current, current.initializer)); |
| 639 } | 677 } |
| 640 } | 678 } |
| 641 | 679 |
| 642 return es; | 680 return es; |
| 643 } | 681 } |
| 644 } | 682 } |
| 645 | 683 |
| 646 /// Represents the application continuation applied on the list of evaluated | 684 /// Represents the application continuation applied on the list of evaluated |
| 647 /// field initializer expressions. | 685 /// field initializer expressions. |
| 648 class InstanceFieldsApplication extends ApplicationContinuation { | 686 class InstanceFieldsApplication extends ApplicationContinuation { |
| 649 final ObjectValue newObject; | |
| 650 final Constructor constructor; | 687 final Constructor constructor; |
| 651 final Environment environment; | 688 final Environment environment; |
| 652 final ExpressionContinuation expressionContinuation; | 689 final StatementConfiguration configuration; |
| 653 | 690 |
| 654 final Class _currentClass; | 691 final Class _currentClass; |
| 692 final ObjectValue _newObject; | |
| 655 | 693 |
| 656 InstanceFieldsApplication(this.newObject, this.constructor, this.environment, | 694 InstanceFieldsApplication( |
| 657 this.expressionContinuation) | 695 this.constructor, this.environment, this.configuration) |
| 658 : _currentClass = new Class(constructor.enclosingClass.reference); | 696 : _currentClass = new Class(constructor.enclosingClass.reference), |
| 697 _newObject = environment.thisInstance; | |
| 659 | 698 |
| 660 Configuration call(List<InterpreterValue> fieldValues) { | 699 Configuration call(List<InterpreterValue> fieldValues) { |
| 661 for (FieldInitializerValue current in fieldValues.reversed) { | 700 for (FieldInitializerValue current in fieldValues.reversed) { |
| 662 _currentClass.setProperty(newObject, current.field, current.value); | 701 _currentClass.setProperty(_newObject, current.field, current.value); |
| 663 } | 702 } |
| 664 | 703 |
| 665 if (constructor.initializers.isEmpty) { | 704 if (constructor.initializers.isEmpty) { |
| 666 _initializeNullFields(_currentClass, newObject); | 705 _initializeNullFields(_currentClass, _newObject); |
| 667 return new ContinuationConfiguration(expressionContinuation, newObject); | 706 return configuration; |
| 668 } | 707 } |
| 669 | 708 |
| 709 // Produce next configuration. | |
| 670 if (constructor.initializers.first is SuperInitializer) { | 710 if (constructor.initializers.first is SuperInitializer) { |
| 671 // SuperInitializer appears last in the initializer list. | 711 // SuperInitializer appears last in the initializer list. |
| 672 assert(constructor.initializers.length == 1); | 712 assert(constructor.initializers.length == 1); |
| 673 SuperInitializer current = constructor.initializers.first; | 713 SuperInitializer current = constructor.initializers.first; |
| 674 var args = _createArgumentExpressionList( | 714 var args = _createArgumentExpressionList( |
| 675 current.arguments, current.target.function); | 715 current.arguments, current.target.function); |
| 716 | |
| 676 var superApp = new SuperConstructorApplication( | 717 var superApp = new SuperConstructorApplication( |
| 677 newObject, current.target, expressionContinuation); | 718 current.target, environment, configuration); |
| 678 _initializeNullFields(_currentClass, newObject); | 719 _initializeNullFields(_currentClass, _newObject); |
| 679 return new ExpressionListConfiguration(args, environment, superApp); | 720 return new ExpressionListConfiguration(args, environment, superApp); |
| 680 } | 721 } |
| 681 | 722 |
| 682 Class class_ = new Class(constructor.enclosingClass.reference); | 723 Class class_ = new Class(constructor.enclosingClass.reference); |
| 683 Environment initEnv = new Environment(environment); | 724 Environment initEnv = new Environment(environment); |
| 684 | 725 |
| 685 var cont = new InitializerContinuation(newObject, class_, initEnv, | 726 var cont = new InitializerContinuation( |
| 686 constructor.initializers, expressionContinuation); | 727 class_, initEnv, constructor.initializers, configuration); |
| 687 return new ExpressionConfiguration( | 728 return new ExpressionConfiguration( |
| 688 _getExpression(constructor.initializers.first), initEnv, cont); | 729 _getExpression(constructor.initializers.first), initEnv, cont); |
| 689 } | 730 } |
| 690 } | 731 } |
| 691 | 732 |
| 692 /// Represents the expression continuation applied on the list of evaluated | 733 /// Represents the expression continuation applied on the list of evaluated |
| 693 /// initializer expressions preceding a super call in the list. | 734 /// initializer expressions preceding a super call in the list. |
| 694 class InitializerContinuation extends ExpressionContinuation { | 735 class InitializerContinuation extends ExpressionContinuation { |
| 695 final ObjectValue newObject; | |
| 696 final Class currentClass; | 736 final Class currentClass; |
| 697 final Environment initializerEnvironment; | 737 final Environment initializerEnvironment; |
| 698 final List<Initializer> initializers; | 738 final List<Initializer> initializers; |
| 699 final ExpressionContinuation continuation; | 739 final StatementConfiguration configuration; |
| 700 | 740 |
| 701 InitializerContinuation(this.newObject, this.currentClass, | 741 InitializerContinuation(this.currentClass, this.initializerEnvironment, |
| 702 this.initializerEnvironment, this.initializers, this.continuation); | 742 this.initializers, this.configuration); |
| 703 | 743 |
| 704 Configuration call(Value v) { | 744 Configuration call(Value v) { |
| 745 ObjectValue newObject = initializerEnvironment.thisInstance; | |
| 705 Initializer current = initializers.first; | 746 Initializer current = initializers.first; |
| 706 if (current is FieldInitializer) { | 747 if (current is FieldInitializer) { |
| 707 currentClass.setProperty(newObject, current.field, v); | 748 currentClass.setProperty(newObject, current.field, v); |
| 708 } else if (current is LocalInitializer) { | 749 } else if (current is LocalInitializer) { |
| 709 initializerEnvironment.expand(current.variable, v); | 750 initializerEnvironment.expand(current.variable, v); |
| 710 } else { | 751 } else { |
| 711 throw 'Assigning value $v to ${current.runtimeType}'; | 752 throw 'Assigning value $v to ${current.runtimeType}'; |
| 712 } | 753 } |
| 713 | 754 |
| 714 if (initializers.length <= 1) { | 755 if (initializers.length <= 1) { |
| 715 // todo: return configuration for body of ctr. | |
| 716 _initializeNullFields(currentClass, newObject); | 756 _initializeNullFields(currentClass, newObject); |
| 717 return new ContinuationConfiguration(continuation, newObject); | 757 return configuration; |
| 718 } | 758 } |
| 719 | 759 |
| 720 Initializer next = initializers[1]; | 760 Initializer next = initializers[1]; |
| 721 | 761 |
| 722 if (next is RedirectingInitializer) { | 762 if (next is RedirectingInitializer) { |
| 723 // RedirectingInitializer appears last in the initializer list. | 763 // RedirectingInitializer appears last in the initializer list. |
| 724 assert(initializers.length == 2); | 764 assert(initializers.length == 2); |
| 725 var cont = new RedirectingConstructorApplication( | 765 var app = new RedirectingConstructorApplication( |
| 726 newObject, next.target, continuation); | 766 next.target, initializerEnvironment, configuration); |
| 727 var args = | 767 var args = |
| 728 _createArgumentExpressionList(next.arguments, next.target.function); | 768 _createArgumentExpressionList(next.arguments, next.target.function); |
| 729 return new ExpressionListConfiguration( | 769 return new ExpressionListConfiguration(args, initializerEnvironment, app); |
| 730 args, initializerEnvironment, cont); | |
| 731 } | 770 } |
| 732 | 771 |
| 733 if (next is SuperInitializer) { | 772 if (next is SuperInitializer) { |
| 734 // SuperInitializer appears last in the initializer list. | 773 // SuperInitializer appears last in the initializer list. |
| 735 assert(initializers.length == 2); | 774 assert(initializers.length == 2); |
| 736 var args = | 775 var args = |
| 737 _createArgumentExpressionList(next.arguments, next.target.function); | 776 _createArgumentExpressionList(next.arguments, next.target.function); |
| 738 var superApp = | 777 var superApp = new SuperConstructorApplication( |
| 739 new SuperConstructorApplication(newObject, next.target, continuation); | 778 next.target, initializerEnvironment, configuration); |
| 740 _initializeNullFields(currentClass, newObject); | 779 _initializeNullFields(currentClass, newObject); |
| 741 return new ExpressionListConfiguration( | 780 return new ExpressionListConfiguration( |
| 742 args, initializerEnvironment, superApp); | 781 args, initializerEnvironment, superApp); |
| 743 } | 782 } |
| 744 | 783 |
| 745 var cont = new InitializerContinuation(newObject, currentClass, | 784 var cont = new InitializerContinuation(currentClass, initializerEnvironment, |
| 746 initializerEnvironment, initializers.skip(1).toList(), continuation); | 785 initializers.skip(1).toList(), configuration); |
| 747 return new ExpressionConfiguration( | 786 return new ExpressionConfiguration( |
| 748 _getExpression(next), initializerEnvironment, cont); | 787 _getExpression(next), initializerEnvironment, cont); |
| 749 } | 788 } |
| 750 } | 789 } |
| 751 | 790 |
| 752 /// Represents the application continuation called after the evaluation of all | 791 /// Represents the application continuation called after the evaluation of all |
| 753 /// argument expressions for an invocation. | 792 /// argument expressions for an invocation. |
| 754 class ValueApplication extends ApplicationContinuation { | 793 class ValueApplication extends ApplicationContinuation { |
| 755 final InterpreterValue value; | 794 final InterpreterValue value; |
| 756 final ApplicationContinuation applicationContinuation; | 795 final ApplicationContinuation applicationContinuation; |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1453 void _initializeNullFields(Class class_, ObjectValue newObject) { | 1492 void _initializeNullFields(Class class_, ObjectValue newObject) { |
| 1454 int superClassSize = class_.superclass?.instanceSize ?? 0; | 1493 int superClassSize = class_.superclass?.instanceSize ?? 0; |
| 1455 for (int i = superClassSize; i < class_.instanceSize; i++) { | 1494 for (int i = superClassSize; i < class_.instanceSize; i++) { |
| 1456 Field field = class_.instanceFields[i]; | 1495 Field field = class_.instanceFields[i]; |
| 1457 if (class_.getProperty(newObject, field) == null) { | 1496 if (class_.getProperty(newObject, field) == null) { |
| 1458 assert(field.initializer == null); | 1497 assert(field.initializer == null); |
| 1459 class_.setProperty(newObject, field, Value.nullInstance); | 1498 class_.setProperty(newObject, field, Value.nullInstance); |
| 1460 } | 1499 } |
| 1461 } | 1500 } |
| 1462 } | 1501 } |
| OLD | NEW |