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 class NotImplemented { | 9 class NotImplemented { |
10 String message; | 10 String message; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 lookupBinding(variable).value = value; | 68 lookupBinding(variable).value = value; |
69 } | 69 } |
70 | 70 |
71 void expand(VariableDeclaration variable, Value value) { | 71 void expand(VariableDeclaration variable, Value value) { |
72 assert(!contains(variable)); | 72 assert(!contains(variable)); |
73 bindings.add(new Binding(variable, value)); | 73 bindings.add(new Binding(variable, value)); |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 /// Evaluate expressions. | 77 /// Evaluate expressions. |
78 class Evaluator extends ExpressionVisitor1<Configuration> { | 78 class Evaluator extends ExpressionVisitor1<Configuration, ExpressionState> { |
79 Configuration eval(Expression expr, ExpressionState state) => | 79 Configuration eval(Expression expr, ExpressionState state) => |
80 expr.accept1(this, state); | 80 expr.accept1(this, state); |
81 | 81 |
82 Configuration defaultExpression(Expression node, state) { | 82 Configuration defaultExpression(Expression node, ExpressionState state) { |
83 throw new NotImplemented('Evaluation for expressions of type ' | 83 throw new NotImplemented('Evaluation for expressions of type ' |
84 '${node.runtimeType} is not implemented.'); | 84 '${node.runtimeType} is not implemented.'); |
85 } | 85 } |
86 | 86 |
87 Configuration visitInvalidExpression1(InvalidExpression node, state) { | 87 Configuration visitInvalidExpression1( |
| 88 InvalidExpression node, ExpressionState state) { |
88 throw 'Invalid expression at ${node.location.toString()}'; | 89 throw 'Invalid expression at ${node.location.toString()}'; |
89 } | 90 } |
90 | 91 |
91 Configuration visitVariableGet(VariableGet node, state) { | 92 Configuration visitVariableGet(VariableGet node, ExpressionState state) { |
92 Value value = state.environment.lookup(node.variable); | 93 Value value = state.environment.lookup(node.variable); |
93 return new ContinuationConfiguration(state.continuation, value); | 94 return new ContinuationConfiguration(state.continuation, value); |
94 } | 95 } |
95 | 96 |
96 Configuration visitVariableSet(VariableSet node, state) { | 97 Configuration visitVariableSet(VariableSet node, ExpressionState state) { |
97 var cont = new VariableSetContinuation(state, node.variable); | 98 var cont = new VariableSetContinuation(state, node.variable); |
98 return new ExpressionConfiguration( | 99 return new ExpressionConfiguration( |
99 node.value, state.withContinuation(cont)); | 100 node.value, state.withContinuation(cont)); |
100 } | 101 } |
101 | 102 |
102 Configuration visitPropertyGet(PropertyGet node, state) { | 103 Configuration visitPropertyGet(PropertyGet node, ExpressionState state) { |
103 var cont = new PropertyGetContinuation(node.name, state); | 104 var cont = new PropertyGetContinuation(node.name, state); |
104 return new ExpressionConfiguration( | 105 return new ExpressionConfiguration( |
105 node.receiver, state.withContinuation(cont)); | 106 node.receiver, state.withContinuation(cont)); |
106 } | 107 } |
107 | 108 |
108 Configuration visitPropertySet(PropertySet node, state) { | 109 Configuration visitPropertySet(PropertySet node, ExpressionState state) { |
109 var cont = new PropertySetContinuation(node.value, node.name, state); | 110 var cont = new PropertySetContinuation(node.value, node.name, state); |
110 return new ExpressionConfiguration( | 111 return new ExpressionConfiguration( |
111 node.receiver, state.withContinuation(cont)); | 112 node.receiver, state.withContinuation(cont)); |
112 } | 113 } |
113 | 114 |
114 Configuration visitStaticGet(StaticGet node, state) => | 115 Configuration visitStaticGet(StaticGet node, ExpressionState state) => |
115 defaultExpression(node, state); | 116 defaultExpression(node, state); |
116 Configuration visitStaticSet(StaticSet node, state) => | 117 Configuration visitStaticSet(StaticSet node, ExpressionState state) => |
117 defaultExpression(node, state); | 118 defaultExpression(node, state); |
118 | 119 |
119 Configuration visitStaticInvocation(StaticInvocation node, state) { | 120 Configuration visitStaticInvocation( |
| 121 StaticInvocation node, ExpressionState state) { |
120 if ('print' == node.name.toString()) { | 122 if ('print' == node.name.toString()) { |
121 return new ExpressionConfiguration(node.arguments.positional.first, | 123 return new ExpressionConfiguration(node.arguments.positional.first, |
122 state.withContinuation(new PrintContinuation(state))); | 124 state.withContinuation(new PrintContinuation(state))); |
123 } else { | 125 } else { |
124 // Currently supports only static invocations with no arguments. | 126 // Currently supports only static invocations with no arguments. |
125 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) { | 127 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) { |
126 State statementState = new State.initial() | 128 State statementState = new State.initial() |
127 .withExpressionContinuation(state.continuation) | 129 .withExpressionContinuation(state.continuation) |
128 .withConfiguration(new ExitConfiguration(state.continuation)); | 130 .withConfiguration(new ExitConfiguration(state.continuation)); |
129 | 131 |
130 return new StatementConfiguration( | 132 return new StatementConfiguration( |
131 node.target.function.body, statementState); | 133 node.target.function.body, statementState); |
132 } | 134 } |
133 throw new NotImplemented( | 135 throw new NotImplemented( |
134 'Support for static invocation with arguments is not implemented'); | 136 'Support for static invocation with arguments is not implemented'); |
135 } | 137 } |
136 } | 138 } |
137 | 139 |
138 Configuration visitMethodInvocation(MethodInvocation node, state) { | 140 Configuration visitMethodInvocation( |
| 141 MethodInvocation node, ExpressionState state) { |
139 // Currently supports only method invocation with <2 arguments and is used | 142 // Currently supports only method invocation with <2 arguments and is used |
140 // to evaluate implemented operators for int, double and String values. | 143 // to evaluate implemented operators for int, double and String values. |
141 var cont = | 144 var cont = |
142 new MethodInvocationContinuation(node.arguments, node.name, state); | 145 new MethodInvocationContinuation(node.arguments, node.name, state); |
143 | 146 |
144 return new ExpressionConfiguration( | 147 return new ExpressionConfiguration( |
145 node.receiver, state.withContinuation(cont)); | 148 node.receiver, state.withContinuation(cont)); |
146 } | 149 } |
147 | 150 |
148 Configuration visitConstructorInvocation(ConstructorInvocation node, state) { | 151 Configuration visitConstructorInvocation( |
| 152 ConstructorInvocation node, ExpressionState state) { |
149 Class class_ = new Class(node.target.enclosingClass.reference); | 153 Class class_ = new Class(node.target.enclosingClass.reference); |
150 | 154 |
151 // Currently we don't support initializers. | 155 // Currently we don't support initializers. |
152 // TODO: Modify to respect dart semantics for initialization. | 156 // TODO: Modify to respect dart semantics for initialization. |
153 // 1. Init fields and eval initializers, repeat the same with super. | 157 // 1. Init fields and eval initializers, repeat the same with super. |
154 // 2. Eval the Function body of the constructor. | 158 // 2. Eval the Function body of the constructor. |
155 List<Value> fields = <Value>[]; | 159 List<Value> fields = <Value>[]; |
156 | 160 |
157 return new ContinuationConfiguration( | 161 return new ContinuationConfiguration( |
158 state.continuation, new ObjectValue(class_, fields)); | 162 state.continuation, new ObjectValue(class_, fields)); |
159 } | 163 } |
160 | 164 |
161 Configuration visitNot(Not node, state) { | 165 Configuration visitNot(Not node, ExpressionState state) { |
162 return new ExpressionConfiguration( | 166 return new ExpressionConfiguration( |
163 node.operand, state.withContinuation(new NotContinuation(state))); | 167 node.operand, state.withContinuation(new NotContinuation(state))); |
164 } | 168 } |
165 | 169 |
166 Configuration visitLogicalExpression(LogicalExpression node, state) { | 170 Configuration visitLogicalExpression( |
| 171 LogicalExpression node, ExpressionState state) { |
167 if ('||' == node.operator) { | 172 if ('||' == node.operator) { |
168 var cont = new OrContinuation(node.right, state); | 173 var cont = new OrContinuation(node.right, state); |
169 return new ExpressionConfiguration( | 174 return new ExpressionConfiguration( |
170 node.left, state.withContinuation(cont)); | 175 node.left, state.withContinuation(cont)); |
171 } else { | 176 } else { |
172 assert('&&' == node.operator); | 177 assert('&&' == node.operator); |
173 var cont = new AndContinuation(node.right, state); | 178 var cont = new AndContinuation(node.right, state); |
174 return new ExpressionConfiguration( | 179 return new ExpressionConfiguration( |
175 node.left, state.withContinuation(cont)); | 180 node.left, state.withContinuation(cont)); |
176 } | 181 } |
177 } | 182 } |
178 | 183 |
179 Configuration visitConditionalExpression(ConditionalExpression node, state) { | 184 Configuration visitConditionalExpression( |
| 185 ConditionalExpression node, ExpressionState state) { |
180 var cont = new ConditionalContinuation(node.then, node.otherwise, state); | 186 var cont = new ConditionalContinuation(node.then, node.otherwise, state); |
181 return new ExpressionConfiguration( | 187 return new ExpressionConfiguration( |
182 node.condition, state.withContinuation(cont)); | 188 node.condition, state.withContinuation(cont)); |
183 } | 189 } |
184 | 190 |
185 Configuration visitStringConcatenation(StringConcatenation node, state) { | 191 Configuration visitStringConcatenation( |
| 192 StringConcatenation node, ExpressionState state) { |
186 var cont = new StringConcatenationContinuation(node.expressions, state); | 193 var cont = new StringConcatenationContinuation(node.expressions, state); |
187 return new ExpressionConfiguration( | 194 return new ExpressionConfiguration( |
188 node.expressions.first, state.withContinuation(cont)); | 195 node.expressions.first, state.withContinuation(cont)); |
189 } | 196 } |
190 | 197 |
191 // Evaluation of BasicLiterals. | 198 // Evaluation of BasicLiterals. |
192 Configuration visitStringLiteral(StringLiteral node, state) { | 199 Configuration visitStringLiteral(StringLiteral node, ExpressionState state) { |
193 return new ContinuationConfiguration( | 200 return new ContinuationConfiguration( |
194 state.continuation, new StringValue(node.value)); | 201 state.continuation, new StringValue(node.value)); |
195 } | 202 } |
196 | 203 |
197 Configuration visitIntLiteral(IntLiteral node, state) { | 204 Configuration visitIntLiteral(IntLiteral node, ExpressionState state) { |
198 return new ContinuationConfiguration( | 205 return new ContinuationConfiguration( |
199 state.continuation, new IntValue(node.value)); | 206 state.continuation, new IntValue(node.value)); |
200 } | 207 } |
201 | 208 |
202 Configuration visitDoubleLiteral(DoubleLiteral node, state) { | 209 Configuration visitDoubleLiteral(DoubleLiteral node, ExpressionState state) { |
203 return new ContinuationConfiguration( | 210 return new ContinuationConfiguration( |
204 state.continuation, new DoubleValue(node.value)); | 211 state.continuation, new DoubleValue(node.value)); |
205 } | 212 } |
206 | 213 |
207 Configuration visitBoolLiteral(BoolLiteral node, state) { | 214 Configuration visitBoolLiteral(BoolLiteral node, ExpressionState state) { |
208 Value value = node.value ? Value.trueInstance : Value.falseInstance; | 215 Value value = node.value ? Value.trueInstance : Value.falseInstance; |
209 return new ContinuationConfiguration(state.continuation, value); | 216 return new ContinuationConfiguration(state.continuation, value); |
210 } | 217 } |
211 | 218 |
212 Configuration visitNullLiteral(NullLiteral node, state) { | 219 Configuration visitNullLiteral(NullLiteral node, ExpressionState state) { |
213 return new ContinuationConfiguration( | 220 return new ContinuationConfiguration( |
214 state.continuation, Value.nullInstance); | 221 state.continuation, Value.nullInstance); |
215 } | 222 } |
216 | 223 |
217 Configuration visitLet(Let node, state) { | 224 Configuration visitLet(Let node, ExpressionState state) { |
218 var letCont = new LetContinuation(node.variable, node.body, state); | 225 var letCont = new LetContinuation(node.variable, node.body, state); |
219 return new ExpressionConfiguration( | 226 return new ExpressionConfiguration( |
220 node.variable.initializer, state.withContinuation(letCont)); | 227 node.variable.initializer, state.withContinuation(letCont)); |
221 } | 228 } |
222 } | 229 } |
223 | 230 |
224 /// Represents a state for statement execution. | 231 /// Represents a state for statement execution. |
225 class State { | 232 class State { |
226 final Environment environment; | 233 final Environment environment; |
227 final Label labels; | 234 final Label labels; |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 | 628 |
622 /// Executes statements. | 629 /// Executes statements. |
623 /// | 630 /// |
624 /// Execution of a statement completes in one of the following ways: | 631 /// Execution of a statement completes in one of the following ways: |
625 /// - it completes normally, in which case the execution proceeds to applying | 632 /// - it completes normally, in which case the execution proceeds to applying |
626 /// the next continuation | 633 /// the next continuation |
627 /// - it breaks with a label, in which case the corresponding continuation is | 634 /// - it breaks with a label, in which case the corresponding continuation is |
628 /// returned and applied | 635 /// returned and applied |
629 /// - it returns with or without value, TBD | 636 /// - it returns with or without value, TBD |
630 /// - it throws, TBD | 637 /// - it throws, TBD |
631 class StatementExecuter extends StatementVisitor1<Configuration> { | 638 class StatementExecuter extends StatementVisitor1<Configuration, State> { |
632 Evaluator evaluator = new Evaluator(); | 639 Evaluator evaluator = new Evaluator(); |
633 | 640 |
634 void trampolinedExecution(Configuration configuration) { | 641 void trampolinedExecution(Configuration configuration) { |
635 while (configuration != null) { | 642 while (configuration != null) { |
636 configuration = configuration.step(this); | 643 configuration = configuration.step(this); |
637 } | 644 } |
638 } | 645 } |
639 | 646 |
640 Configuration exec(Statement statement, State state) => | 647 Configuration exec(Statement statement, State state) => |
641 statement.accept1(this, state); | 648 statement.accept1(this, state); |
642 Configuration eval(Expression expression, ExpressionState state) => | 649 Configuration eval(Expression expression, ExpressionState state) => |
643 evaluator.eval(expression, state); | 650 evaluator.eval(expression, state); |
644 | 651 |
645 Configuration defaultStatement(Statement node, state) { | 652 Configuration defaultStatement(Statement node, State state) { |
646 throw notImplemented( | 653 throw notImplemented( |
647 m: "Execution is not implemented for statement:\n$node "); | 654 m: "Execution is not implemented for statement:\n$node "); |
648 } | 655 } |
649 | 656 |
650 Configuration visitInvalidStatement(InvalidStatement node, state) { | 657 Configuration visitInvalidStatement(InvalidStatement node, State state) { |
651 throw "Invalid statement at ${node.location}"; | 658 throw "Invalid statement at ${node.location}"; |
652 } | 659 } |
653 | 660 |
654 Configuration visitExpressionStatement(ExpressionStatement node, state) { | 661 Configuration visitExpressionStatement( |
| 662 ExpressionStatement node, State state) { |
655 return new ExpressionConfiguration( | 663 return new ExpressionConfiguration( |
656 node.expression, new ExpressionState.fromStatementState(state)); | 664 node.expression, new ExpressionState.fromStatementState(state)); |
657 } | 665 } |
658 | 666 |
659 Configuration visitBlock(Block node, state) { | 667 Configuration visitBlock(Block node, State state) { |
660 if (node.statements.isEmpty) { | 668 if (node.statements.isEmpty) { |
661 return state.statementConfiguration; | 669 return state.statementConfiguration; |
662 } | 670 } |
663 State blockState = | 671 State blockState = |
664 state.withEnvironment(new Environment(state.environment)); | 672 state.withEnvironment(new Environment(state.environment)); |
665 StatementConfiguration configuration = state.statementConfiguration; | 673 StatementConfiguration configuration = state.statementConfiguration; |
666 for (Statement s in node.statements.reversed) { | 674 for (Statement s in node.statements.reversed) { |
667 configuration = new StatementConfiguration( | 675 configuration = new StatementConfiguration( |
668 s, blockState.withConfiguration(configuration)); | 676 s, blockState.withConfiguration(configuration)); |
669 } | 677 } |
670 return configuration; | 678 return configuration; |
671 } | 679 } |
672 | 680 |
673 Configuration visitEmptyStatement(EmptyStatement node, state) { | 681 Configuration visitEmptyStatement(EmptyStatement node, State state) { |
674 return state.statementConfiguration; | 682 return state.statementConfiguration; |
675 } | 683 } |
676 | 684 |
677 Configuration visitIfStatement(IfStatement node, state) { | 685 Configuration visitIfStatement(IfStatement node, State state) { |
678 var expState = new ExpressionState.fromStatementState(state); | 686 var expState = new ExpressionState.fromStatementState(state); |
679 var cont = new IfConditionContinuation(node.then, node.otherwise, state); | 687 var cont = new IfConditionContinuation(node.then, node.otherwise, state); |
680 return new ExpressionConfiguration( | 688 return new ExpressionConfiguration( |
681 node.condition, expState.withContinuation(cont)); | 689 node.condition, expState.withContinuation(cont)); |
682 } | 690 } |
683 | 691 |
684 Configuration visitLabeledStatement(LabeledStatement node, state) { | 692 Configuration visitLabeledStatement(LabeledStatement node, State state) { |
685 return new StatementConfiguration(node.body, state.withBreak(node)); | 693 return new StatementConfiguration(node.body, state.withBreak(node)); |
686 } | 694 } |
687 | 695 |
688 Configuration visitBreakStatement(BreakStatement node, state) { | 696 Configuration visitBreakStatement(BreakStatement node, State state) { |
689 return state.lookupLabel(node.target).configuration; | 697 return state.lookupLabel(node.target).configuration; |
690 } | 698 } |
691 | 699 |
692 Configuration visitWhileStatement(WhileStatement node, state) { | 700 Configuration visitWhileStatement(WhileStatement node, State state) { |
693 var expState = new ExpressionState.fromStatementState(state); | 701 var expState = new ExpressionState.fromStatementState(state); |
694 var cont = new WhileConditionContinuation(node, state); | 702 var cont = new WhileConditionContinuation(node, state); |
695 | 703 |
696 return new ExpressionConfiguration( | 704 return new ExpressionConfiguration( |
697 node.condition, expState.withContinuation(cont)); | 705 node.condition, expState.withContinuation(cont)); |
698 } | 706 } |
699 | 707 |
700 Configuration visitDoStatement(DoStatement node, state) { | 708 Configuration visitDoStatement(DoStatement node, State state) { |
701 WhileStatement whileStatement = | 709 WhileStatement whileStatement = |
702 new WhileStatement(node.condition, node.body); | 710 new WhileStatement(node.condition, node.body); |
703 StatementConfiguration configuration = | 711 StatementConfiguration configuration = |
704 new StatementConfiguration(whileStatement, state); | 712 new StatementConfiguration(whileStatement, state); |
705 | 713 |
706 return new StatementConfiguration( | 714 return new StatementConfiguration( |
707 node.body, state.withConfiguration(configuration)); | 715 node.body, state.withConfiguration(configuration)); |
708 } | 716 } |
709 | 717 |
710 Configuration visitReturnStatement(ReturnStatement node, state) { | 718 Configuration visitReturnStatement(ReturnStatement node, State state) { |
711 assert(state.returnContinuation != null); | 719 assert(state.returnContinuation != null); |
712 // The new ExpressionState contains the next expression continuation. | 720 // The new ExpressionState contains the next expression continuation. |
713 var expState = new ExpressionState.fromStatementState(state) | 721 var expState = new ExpressionState.fromStatementState(state) |
714 .withContinuation(state.returnContinuation); | 722 .withContinuation(state.returnContinuation); |
715 return new ExpressionConfiguration( | 723 return new ExpressionConfiguration( |
716 node.expression ?? new NullLiteral(), expState); | 724 node.expression ?? new NullLiteral(), expState); |
717 } | 725 } |
718 | 726 |
719 Configuration visitVariableDeclaration(VariableDeclaration node, state) { | 727 Configuration visitVariableDeclaration( |
| 728 VariableDeclaration node, State state) { |
720 if (node.initializer != null) { | 729 if (node.initializer != null) { |
721 var expState = new ExpressionState.fromStatementState(state); | 730 var expState = new ExpressionState.fromStatementState(state); |
722 var cont = new VariableInitializerContinuation( | 731 var cont = new VariableInitializerContinuation( |
723 node, state.environment, state.statementConfiguration); | 732 node, state.environment, state.statementConfiguration); |
724 return new ExpressionConfiguration( | 733 return new ExpressionConfiguration( |
725 node.initializer, expState.withContinuation(cont)); | 734 node.initializer, expState.withContinuation(cont)); |
726 } | 735 } |
727 state.environment.expand(node, Value.nullInstance); | 736 state.environment.expand(node, Value.nullInstance); |
728 return state.statementConfiguration; | 737 return state.statementConfiguration; |
729 } | 738 } |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 | 961 |
953 class NullValue extends LiteralValue { | 962 class NullValue extends LiteralValue { |
954 Object get value => null; | 963 Object get value => null; |
955 | 964 |
956 const NullValue(); | 965 const NullValue(); |
957 } | 966 } |
958 | 967 |
959 notImplemented({String m, Object obj}) { | 968 notImplemented({String m, Object obj}) { |
960 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); | 969 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); |
961 } | 970 } |
OLD | NEW |