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 |