| 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 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 | 528 |
| 529 ConstructorInvocationApplication( | 529 ConstructorInvocationApplication( |
| 530 this.newObject, this.constructor, this.expressionContinuation); | 530 this.newObject, this.constructor, this.expressionContinuation); |
| 531 | 531 |
| 532 Configuration call(List<InterpreterValue> argValues) { | 532 Configuration call(List<InterpreterValue> argValues) { |
| 533 Environment ctrEnv = ApplicationContinuation.createEnvironment( | 533 Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| 534 constructor.function, argValues); | 534 constructor.function, argValues); |
| 535 | 535 |
| 536 if (constructor.initializers.isNotEmpty && | 536 if (constructor.initializers.isNotEmpty && |
| 537 constructor.initializers.last is RedirectingInitializer) { | 537 constructor.initializers.last is RedirectingInitializer) { |
| 538 var cont = new RedirectingConstructorInvocationApplication(newObject, | 538 // Constructor is redirecting. |
| 539 constructor.initializers.last, ctrEnv, expressionContinuation); | 539 Initializer initializer = constructor.initializers.first; |
| 540 var es = _createLocalInitializerExpressionList( | 540 if (initializer is RedirectingInitializer) { |
| 541 constructor.initializers.take(constructor.initializers.length - 1)); | 541 var app = new ConstructorInvocationApplication( |
| 542 return new ExpressionListConfiguration(es, ctrEnv, cont); | 542 newObject, initializer.target, expressionContinuation); |
| 543 var args = _createArgumentExpressionList( |
| 544 initializer.arguments, initializer.target.function); |
| 545 |
| 546 return new ExpressionListConfiguration(args, ctrEnv, app); |
| 547 } |
| 548 // Redirecting initializer is not the only initializer. |
| 549 for (Initializer i in constructor.initializers.reversed.skip(1)) { |
| 550 assert(i is LocalInitializer); |
| 551 } |
| 552 var class_ = new Class(constructor.enclosingClass.reference); |
| 553 var cont = new InitializerContinuation(newObject, class_, ctrEnv, |
| 554 constructor.initializers, expressionContinuation); |
| 555 return new ExpressionConfiguration( |
| 556 (initializer as LocalInitializer).variable.initializer, ctrEnv, cont); |
| 543 } | 557 } |
| 544 | 558 |
| 559 // Initialize fields in immediately enclosing class. |
| 545 var cont = new InstanceFieldsApplication( | 560 var cont = new InstanceFieldsApplication( |
| 546 newObject, constructor, ctrEnv, expressionContinuation); | 561 newObject, constructor, ctrEnv, expressionContinuation); |
| 547 var fieldExpressions = _createInstanceInitializers(constructor); | 562 var fieldExpressions = _createInstanceInitializers(constructor); |
| 548 | 563 |
| 549 return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont); | 564 return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont); |
| 550 } | 565 } |
| 551 | 566 |
| 552 /// Creates a list of expressions for local initializers. | |
| 553 static List<InterpreterExpression> _createLocalInitializerExpressionList( | |
| 554 List<LocalInitializer> initializers) { | |
| 555 List<InterpreterExpression> es = <InterpreterExpression>[]; | |
| 556 | |
| 557 for (int i = 0; i < initializers.length; i++) { | |
| 558 var current = initializers[i]; | |
| 559 es.add(new LocalInitializerExpression(current.variable)); | |
| 560 } | |
| 561 return es; | |
| 562 } | |
| 563 | |
| 564 /// Creates a list of expressions for instance field initializers in | 567 /// Creates a list of expressions for instance field initializers in |
| 565 /// immediately enclosing class. | 568 /// immediately enclosing class. |
| 566 static List<InterpreterExpression> _createInstanceInitializers( | 569 static List<InterpreterExpression> _createInstanceInitializers( |
| 567 Constructor ctr) { | 570 Constructor ctr) { |
| 568 Class currentClass = new Class(ctr.enclosingClass.reference); | 571 Class currentClass = new Class(ctr.enclosingClass.reference); |
| 569 List<InterpreterExpression> es = <InterpreterExpression>[]; | 572 List<InterpreterExpression> es = <InterpreterExpression>[]; |
| 570 | 573 |
| 571 for (int i = currentClass.superclass?.instanceSize ?? 0; | 574 for (int i = currentClass.superclass?.instanceSize ?? 0; |
| 572 i < currentClass.instanceSize; | 575 i < currentClass.instanceSize; |
| 573 i++) { | 576 i++) { |
| 574 Field current = currentClass.instanceFields[i]; | 577 Field current = currentClass.instanceFields[i]; |
| 575 if (current.initializer != null) { | 578 if (current.initializer != null) { |
| 576 es.add(new FieldInitializerExpression(current, current.initializer)); | 579 es.add(new FieldInitializerExpression(current, current.initializer)); |
| 577 } | 580 } |
| 578 } | 581 } |
| 579 | 582 |
| 580 return es; | 583 return es; |
| 581 } | 584 } |
| 582 } | 585 } |
| 583 | 586 |
| 584 /// Represents the application continuation applied on the list of evaluated | 587 /// Represents the application continuation applied on the list of evaluated |
| 585 /// local initializer expressions. | |
| 586 class RedirectingConstructorInvocationApplication | |
| 587 extends ApplicationContinuation { | |
| 588 final ObjectValue newObject; | |
| 589 final RedirectingInitializer initializer; | |
| 590 final Environment environment; | |
| 591 final ExpressionContinuation expressionContinuation; | |
| 592 | |
| 593 RedirectingConstructorInvocationApplication(this.newObject, this.initializer, | |
| 594 this.environment, this.expressionContinuation); | |
| 595 | |
| 596 Configuration call(List<InterpreterValue> localValues) { | |
| 597 for (LocalInitializerValue current in localValues.reversed) { | |
| 598 environment.expand(current.variable, current.value); | |
| 599 } | |
| 600 var cont = new ConstructorInvocationApplication( | |
| 601 newObject, initializer.target, expressionContinuation); | |
| 602 var args = _createArgumentExpressionList( | |
| 603 initializer.arguments, initializer.target.function); | |
| 604 | |
| 605 return new ExpressionListConfiguration(args, environment, cont); | |
| 606 } | |
| 607 } | |
| 608 | |
| 609 /// Represents the application continuation applied on the list of evaluated | |
| 610 /// field initializer expressions. | 588 /// field initializer expressions. |
| 611 class InstanceFieldsApplication extends ApplicationContinuation { | 589 class InstanceFieldsApplication extends ApplicationContinuation { |
| 612 final ObjectValue newObject; | 590 final ObjectValue newObject; |
| 613 final Constructor constructor; | 591 final Constructor constructor; |
| 614 final Environment environment; | 592 final Environment environment; |
| 615 final ExpressionContinuation expressionContinuation; | 593 final ExpressionContinuation expressionContinuation; |
| 616 | 594 |
| 617 final Class _currentClass; | 595 final Class _currentClass; |
| 618 | 596 |
| 619 InstanceFieldsApplication(this.newObject, this.constructor, this.environment, | 597 InstanceFieldsApplication(this.newObject, this.constructor, this.environment, |
| 620 this.expressionContinuation) | 598 this.expressionContinuation) |
| 621 : _currentClass = new Class(constructor.enclosingClass.reference); | 599 : _currentClass = new Class(constructor.enclosingClass.reference); |
| 622 | 600 |
| 623 Configuration call(List<InterpreterValue> fieldValues) { | 601 Configuration call(List<InterpreterValue> fieldValues) { |
| 624 for (FieldInitializerValue current in fieldValues.reversed) { | 602 for (FieldInitializerValue current in fieldValues.reversed) { |
| 625 _currentClass.setProperty(newObject, current.field, current.value); | 603 _currentClass.setProperty(newObject, current.field, current.value); |
| 626 } | 604 } |
| 627 | 605 |
| 628 var es = _createInitializerListExpressions(constructor.initializers); | 606 if (constructor.initializers.isEmpty || |
| 629 List<Initializer> initializers = constructor.initializers.skip(es.length); | 607 constructor.initializers.first is SuperInitializer) { |
| 608 // todo: eval super args or constructor body configuration. |
| 609 return new ContinuationConfiguration(expressionContinuation, newObject); |
| 610 } |
| 630 | 611 |
| 631 ApplicationContinuation cont = new InitializerListApplication(newObject, | 612 Class class_ = new Class(constructor.enclosingClass.reference); |
| 632 constructor, environment, initializers, expressionContinuation); | 613 Environment initEnv = new Environment(environment); |
| 633 | 614 |
| 634 return new ExpressionListConfiguration(es, environment, cont); | 615 var cont = new InitializerContinuation(newObject, class_, initEnv, |
| 616 constructor.initializers, expressionContinuation); |
| 617 return new ExpressionConfiguration( |
| 618 _getExpression(constructor.initializers.first), initEnv, cont); |
| 635 } | 619 } |
| 636 } | 620 } |
| 637 | 621 |
| 638 /// Represents the application continuation applied on the list of evaluated | 622 /// Represents the expression continuation applied on the list of evaluated |
| 639 /// initializer expressions preceding a super call in the list. | 623 /// initializer expressions preceding a super call in the list. |
| 640 class InitializerListApplication extends ApplicationContinuation { | 624 class InitializerContinuation extends ExpressionContinuation { |
| 641 final ObjectValue newObject; | 625 final ObjectValue newObject; |
| 642 final Constructor constructor; | 626 final Class currentClass; |
| 643 final Environment environment; | 627 final Environment initializerEnvironment; |
| 644 final List<Initializer> remainingInitializers; | 628 final List<Initializer> initializers; |
| 645 final ExpressionContinuation expressionContinuation; | 629 final ExpressionContinuation continuation; |
| 646 | 630 |
| 647 final Class _currentClass; | 631 InitializerContinuation(this.newObject, this.currentClass, |
| 632 this.initializerEnvironment, this.initializers, this.continuation); |
| 648 | 633 |
| 649 InitializerListApplication(this.newObject, this.constructor, this.environment, | 634 Configuration call(Value v) { |
| 650 this.remainingInitializers, this.expressionContinuation) | 635 Initializer current = initializers.first; |
| 651 : _currentClass = new Class(constructor.enclosingClass.reference); | 636 if (current is FieldInitializer) { |
| 652 | 637 currentClass.setProperty(newObject, current.field, v); |
| 653 Configuration call(List<InterpreterValue> values) { | 638 } else if (current is LocalInitializer) { |
| 654 var initEnv = new Environment(environment); | 639 initializerEnvironment.expand(current.variable, v); |
| 655 | 640 } else { |
| 656 // Apply values from evaluation to object or/and initializer environment. | 641 throw 'Assigning value $v to ${current.runtimeType}'; |
| 657 for (InterpreterValue current in values.reversed) { | |
| 658 if (current is LocalInitializerValue) { | |
| 659 initEnv.expand(current.variable, current.value); | |
| 660 } else if (current is FieldInitializerValue) { | |
| 661 _currentClass.setProperty(newObject, current.field, current.value); | |
| 662 } else { | |
| 663 throw '${current.runtimeType} in InitializerListApplication'; | |
| 664 } | |
| 665 } | 642 } |
| 666 | 643 |
| 667 if (remainingInitializers.isNotEmpty) { | 644 if (initializers.length <= 1) { |
| 668 assert(remainingInitializers.first is SuperInitializer); | 645 // todo: return configuration for body of ctr. |
| 669 // todo: Evaluate arguments for super invocation. | 646 return new ContinuationConfiguration(continuation, newObject); |
| 670 } | 647 } |
| 671 | 648 |
| 672 return new ContinuationConfiguration(expressionContinuation, newObject); | 649 Initializer next = initializers[1]; |
| 650 |
| 651 if (next is RedirectingInitializer) { |
| 652 var cont = new ConstructorInvocationApplication( |
| 653 newObject, next.target, continuation); |
| 654 var args = |
| 655 _createArgumentExpressionList(next.arguments, next.target.function); |
| 656 return new ExpressionListConfiguration( |
| 657 args, initializerEnvironment, cont); |
| 658 } |
| 659 |
| 660 if (next is SuperInitializer) { |
| 661 // todo: eval args for super. |
| 662 if (currentClass.superclass.superclass != null) { |
| 663 throw 'Super initializer invocation is not supported.'; |
| 664 } |
| 665 return new ContinuationConfiguration(continuation, newObject); |
| 666 } |
| 667 |
| 668 var cont = new InitializerContinuation(newObject, currentClass, |
| 669 initializerEnvironment, initializers.skip(1), continuation); |
| 670 return new ExpressionConfiguration( |
| 671 _getExpression(next), initializerEnvironment, cont); |
| 673 } | 672 } |
| 674 } | 673 } |
| 675 | 674 |
| 676 /// Represents the application continuation called after the evaluation of all | 675 /// Represents the application continuation called after the evaluation of all |
| 677 /// argument expressions for an invocation. | 676 /// argument expressions for an invocation. |
| 678 class ValueApplication extends ApplicationContinuation { | 677 class ValueApplication extends ApplicationContinuation { |
| 679 final InterpreterValue value; | 678 final InterpreterValue value; |
| 680 final ApplicationContinuation applicationContinuation; | 679 final ApplicationContinuation applicationContinuation; |
| 681 | 680 |
| 682 ValueApplication(this.value, this.applicationContinuation); | 681 ValueApplication(this.value, this.applicationContinuation); |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1368 args.add(new NamedArgumentExpression(current.name, current.value)); | 1367 args.add(new NamedArgumentExpression(current.name, current.value)); |
| 1369 namedFormals.remove(current.name); | 1368 namedFormals.remove(current.name); |
| 1370 } | 1369 } |
| 1371 | 1370 |
| 1372 // Add missing optional named initializers. | 1371 // Add missing optional named initializers. |
| 1373 args.addAll(namedFormals.values); | 1372 args.addAll(namedFormals.values); |
| 1374 | 1373 |
| 1375 return args; | 1374 return args; |
| 1376 } | 1375 } |
| 1377 | 1376 |
| 1378 List<InterpreterExpression> _createInitializerListExpressions( | 1377 Expression _getExpression(Initializer initializer) { |
| 1379 List<Initializer> initializers) { | 1378 if (initializer is FieldInitializer) { |
| 1380 List<InterpreterExpression> es = <InterpreterExpression>[]; | 1379 return initializer.value; |
| 1381 | 1380 } |
| 1382 for (Initializer current in initializers) { | 1381 if (initializer is LocalInitializer) { |
| 1383 if (current is FieldInitializer) { | 1382 return initializer.variable.initializer; |
| 1384 es.add(new FieldInitializerExpression(current.field, current.value)); | |
| 1385 } else if (current is LocalInitializer) { | |
| 1386 es.add(new LocalInitializerExpression(current.variable)); | |
| 1387 } else { | |
| 1388 assert(current is SuperInitializer); | |
| 1389 return es; | |
| 1390 } | |
| 1391 } | 1383 } |
| 1392 | 1384 |
| 1393 return es; | 1385 throw '${initializer.runtimeType} has no epxression.'; |
| 1394 } | 1386 } |
| OLD | NEW |