Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2806483003: Implement expression evaluation in Coninuation Passing Style (Closed)
Patch Set: Move recursive calls to eval in the trampoline Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
11 11
12 NotImplemented(this.message); 12 NotImplemented(this.message);
13 13
14 String toString() => message; 14 String toString() => message;
15 } 15 }
16 16
17 class Interpreter { 17 class Interpreter {
18 Program program; 18 Program program;
19 StatementExecuter visitor = new StatementExecuter(); 19 StatementExecuter visitor = new StatementExecuter();
20 20
21 Interpreter(this.program); 21 Interpreter(this.program);
22 22
23 void run() { 23 void run() {
24 assert(program.libraries.isEmpty); 24 assert(program.libraries.isEmpty);
25 Procedure mainMethod = program.mainMethod; 25 Procedure mainMethod = program.mainMethod;
26 Statement statementBlock = mainMethod.function.body; 26 Statement statementBlock = mainMethod.function.body;
27 Continuation cont = new Continuation(statementBlock, new State.initial()); 27 StatementConfiguration configuration =
28 visitor.trampolinedExecution(cont); 28 new StatementConfiguration(statementBlock, new State.initial());
29 visitor.trampolinedExecution(configuration);
29 } 30 }
30 } 31 }
31 32
32 class Binding { 33 class Binding {
33 final VariableDeclaration variable; 34 final VariableDeclaration variable;
34 Value value; 35 Value value;
35 36
36 Binding(this.variable, this.value); 37 Binding(this.variable, this.value);
37 } 38 }
38 39
(...skipping 28 matching lines...) Expand all
67 lookupBinding(variable).value = value; 68 lookupBinding(variable).value = value;
68 } 69 }
69 70
70 void expand(VariableDeclaration variable, Value value) { 71 void expand(VariableDeclaration variable, Value value) {
71 assert(!contains(variable)); 72 assert(!contains(variable));
72 bindings.add(new Binding(variable, value)); 73 bindings.add(new Binding(variable, value));
73 } 74 }
74 } 75 }
75 76
76 /// Evaluate expressions. 77 /// Evaluate expressions.
77 class Evaluator extends ExpressionVisitor1<Value> { 78 class Evaluator extends ExpressionVisitor1<Configuration> {
Kevin Millikin (Google) 2017/04/20 10:50:20 We should make ExpressionVisitor1 parameterized ov
zhivkag 2017/04/20 13:21:36 Acknowledged. I will do it in a follow-up CL.
78 Value eval(Expression expr, Environment env) => expr.accept1(this, env); 79 Configuration eval(Expression expr, ExpressionState state) =>
Kevin Millikin (Google) 2017/04/20 10:50:20 ExpressionState is ExpressionConfiguration without
zhivkag 2017/04/20 13:21:36 Acknowledged. I will do it in a follow-up CL.
80 expr.accept1(this, state);
79 81
80 Value defaultExpression(Expression node, env) { 82 Configuration defaultExpression(Expression node, state) {
81 throw new NotImplemented('Evaluation for expressions of type ' 83 throw new NotImplemented('Evaluation for expressions of type '
82 '${node.runtimeType} is not implemented.'); 84 '${node.runtimeType} is not implemented.');
83 } 85 }
84 86
85 Value visitInvalidExpression1(InvalidExpression node, env) { 87 Configuration visitInvalidExpression1(InvalidExpression node, state) {
86 throw 'Invalid expression at ${node.location.toString()}'; 88 throw 'Invalid expression at ${node.location.toString()}';
87 } 89 }
88 90
89 Value visitVariableGet(VariableGet node, env) { 91 Configuration visitVariableGet(VariableGet node, state) {
90 return env.lookup(node.variable); 92 Value value = state.environment.lookup(node.variable);
93 return state.nextConfiguration(value);
Kevin Millikin (Google) 2017/04/20 10:50:20 I think nextConfiguration is only needed because t
zhivkag 2017/04/20 13:21:36 Done.
91 } 94 }
92 95
93 Value visitVariableSet(VariableSet node, env) { 96 Configuration visitVariableSet(VariableSet node, state) {
94 return env.assign(node.variable, eval(node.value, env)); 97 var cont = new VariableSetContinuation(state, node.variable);
98 return new ExpressionConfiguration(
99 node.value, state.withContinuation(cont));
95 } 100 }
96 101
97 Value visitPropertyGet(PropertyGet node, env) { 102 Configuration visitPropertyGet(PropertyGet node, state) {
98 Value receiver = eval(node.receiver, env); 103 var cont = new PropertyGetContinuation(node.name, state);
99 return receiver.class_.lookupGetter(node.name)(receiver); 104 return new ExpressionConfiguration(
105 node.receiver, state.withContinuation(cont));
100 } 106 }
101 107
102 Value visitPropertySet(PropertySet node, env) { 108 Configuration visitPropertySet(PropertySet node, state) {
103 Value receiver = eval(node.receiver, env); 109 var cont = new PropertySetContinuation(node.value, node.name, state);
104 Value value = eval(node.value, env); 110 return new ExpressionConfiguration(
105 receiver.class_.lookupSetter(node.name)(receiver, value); 111 node.receiver, state.withContinuation(cont));
106 return value;
107 } 112 }
108 113
109 Value visitDirectPropertyGet(DirectPropertyGet node, env) { 114 Configuration visitStaticGet(StaticGet node, state) =>
110 Value receiver = eval(node.receiver, env); 115 defaultExpression(node, state);
111 return receiver.class_.getProperty(receiver, node.target); 116 Configuration visitStaticSet(StaticSet node, state) =>
112 } 117 defaultExpression(node, state);
113 118
114 Value visitDirectPropertySet(DirectPropertySet node, env) { 119 Configuration visitStaticInvocation(StaticInvocation node, state) {
115 Value receiver = eval(node.receiver, env);
116 Value value = eval(node.value, env);
117 receiver.class_.setProperty(receiver, node.target, value);
118 return value;
119 }
120
121 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env);
122 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env);
123
124 Value visitStaticInvocation(StaticInvocation node, env) {
125 if ('print' == node.name.toString()) { 120 if ('print' == node.name.toString()) {
126 // Special evaluation of print. 121 return new ExpressionConfiguration(node.arguments.positional.first,
127 var res = eval(node.arguments.positional[0], env); 122 state.withContinuation(new PrintContinuation(state)));
128 print(res.value);
129 return Value.nullInstance;
130 } else { 123 } else {
131 throw new NotImplemented('Support for statement type ' 124 // Currently supports only static invocations with no arguments.
132 '${node.runtimeType} is not implemented'); 125 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
126 return new StatementConfiguration(
127 node.target.function.body,
128 state.statementState
Kevin Millikin (Google) 2017/04/20 10:50:20 This doesn't seem like the right StatementState he
zhivkag 2017/04/20 13:21:36 Done.
129 .withExpressionContinuation(state.continuation));
130 }
131 throw new NotImplemented(
132 'Support for static invocation with arguments is not implemented');
133 } 133 }
134 } 134 }
135 135
136 Value visitMethodInvocation(MethodInvocation node, env) { 136 Configuration visitMethodInvocation(MethodInvocation node, state) {
137 // Currently supports only method invocation with <2 arguments and is used 137 // Currently supports only method invocation with <2 arguments and is used
138 // to evaluate implemented operators for int, double and String values. 138 // to evaluate implemented operators for int, double and String values.
139 var receiver = eval(node.receiver, env); 139 var cont =
140 if (node.arguments.positional.isNotEmpty) { 140 new MethodInvocationContinuation(node.arguments, node.name, state);
141 var argValue = eval(node.arguments.positional.first, env); 141
142 return receiver.invokeMethod(node.name, argValue); 142 return new ExpressionConfiguration(
143 } else { 143 node.receiver, state.withContinuation(cont));
144 return receiver.invokeMethod(node.name);
145 }
146 } 144 }
147 145
148 Value visitConstructorInvocation(ConstructorInvocation node, env) { 146 Configuration visitConstructorInvocation(ConstructorInvocation node, state) {
149 Class class_ = new Class(node.target.enclosingClass.reference); 147 Class class_ = new Class(node.target.enclosingClass.reference);
150 148
151 Environment emptyEnv = new Environment.empty();
152 // Currently we don't support initializers. 149 // Currently we don't support initializers.
153 // TODO: Modify to respect dart semantics for initialization. 150 // TODO: Modify to respect dart semantics for initialization.
154 // 1. Init fields and eval initializers, repeat the same with super. 151 // 1. Init fields and eval initializers, repeat the same with super.
155 // 2. Eval the Function body of the constructor. 152 // 2. Eval the Function body of the constructor.
156 List<Value> fields = class_.instanceFields 153 List<Value> fields = <Value>[];
157 .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
158 .toList(growable: false);
159 154
160 return new ObjectValue(class_, fields); 155 return state.nextConfiguration(new ObjectValue(class_, fields));
161 } 156 }
162 157
163 Value visitNot(Not node, env) { 158 Configuration visitNot(Not node, state) {
164 Value operand = eval(node.operand, env).toBoolean(); 159 return new ExpressionConfiguration(
165 return identical(operand, Value.trueInstance) 160 node.operand, state.withContinuation(new NotContinuation(state)));
166 ? Value.falseInstance
167 : Value.trueInstance;
168 } 161 }
169 162
170 Value visitLogicalExpression(LogicalExpression node, env) { 163 Configuration visitLogicalExpression(LogicalExpression node, state) {
171 if ('||' == node.operator) { 164 if ('||' == node.operator) {
172 BoolValue left = eval(node.left, env).toBoolean(); 165 var cont = new OrContinuation(node.right, state);
173 return identical(left, Value.trueInstance) 166 return new ExpressionConfiguration(
174 ? Value.trueInstance 167 node.left, state.withContinuation(cont));
175 : eval(node.right, env).toBoolean();
176 } else { 168 } else {
177 assert('&&' == node.operator); 169 assert('&&' == node.operator);
178 BoolValue left = eval(node.left, env).toBoolean(); 170 var cont = new AndContinuation(node.right, state);
179 return identical(left, Value.falseInstance) 171 return new ExpressionConfiguration(
180 ? Value.falseInstance 172 node.left, state.withContinuation(cont));
181 : eval(node.right, env).toBoolean();
182 } 173 }
183 } 174 }
184 175
185 Value visitConditionalExpression(ConditionalExpression node, env) { 176 Configuration visitConditionalExpression(ConditionalExpression node, state) {
186 var condition = eval(node.condition, env).toBoolean(); 177 var cont = new ConditionalContinuation(node.then, node.otherwise, state);
187 return identical(condition, Value.trueInstance) 178 return new ExpressionConfiguration(
188 ? eval(node.then, env) 179 node.condition, state.withContinuation(cont));
189 : eval(node.otherwise, env);
190 } 180 }
191 181
192 Value visitStringConcatenation(StringConcatenation node, env) { 182 Configuration visitStringConcatenation(StringConcatenation node, state) {
193 StringBuffer res = new StringBuffer(); 183 var cont = new StringConcatenationContinuation(node.expressions, state);
194 for (Expression e in node.expressions) { 184 return new ExpressionConfiguration(
195 res.write(eval(e, env).value); 185 node.expressions.first, state.withContinuation(cont));
196 }
197 return new StringValue(res.toString());
198 } 186 }
199 187
200 // Evaluation of BasicLiterals. 188 // Evaluation of BasicLiterals.
201 Value visitStringLiteral(StringLiteral node, env) => 189 Configuration visitStringLiteral(StringLiteral node, state) {
202 new StringValue(node.value); 190 return state.nextConfiguration(new StringValue(node.value));
203 Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value); 191 }
204 Value visitDoubleLiteral(DoubleLiteral node, env) =>
205 new DoubleValue(node.value);
206 Value visitBoolLiteral(BoolLiteral node, env) =>
207 node.value ? Value.trueInstance : Value.falseInstance;
208 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance;
209 192
210 Value visitLet(Let node, env) { 193 Configuration visitIntLiteral(IntLiteral node, state) {
211 var value = eval(node.variable.initializer, env); 194 return state.nextConfiguration(new IntValue(node.value));
212 var letEnv = new Environment(env); 195 }
213 letEnv.expand(node.variable, value); 196
214 return eval(node.body, letEnv); 197 Configuration visitDoubleLiteral(DoubleLiteral node, state) {
198 return state.nextConfiguration(new DoubleValue(node.value));
199 }
200
201 Configuration visitBoolLiteral(BoolLiteral node, state) {
202 Value value = node.value ? Value.trueInstance : Value.falseInstance;
203 return state.nextConfiguration(value);
204 }
205
206 Configuration visitNullLiteral(NullLiteral node, state) {
207 return state.nextConfiguration(Value.nullInstance);
208 }
209
210 Configuration visitLet(Let node, state) {
211 var letCont = new LetContinuation(node.variable, node.body, state);
212 return new ExpressionConfiguration(
213 node.variable.initializer, state.withContinuation(letCont));
215 } 214 }
216 } 215 }
217 216
218 /// Represents a state which consists of current environment, continuation to be 217 /// Represents a state for statement execution.
219 /// applied and the current label.
220 class State { 218 class State {
221 final Environment environment; 219 final Environment environment;
222 final Label labels; 220 final Label labels;
223 final Continuation continuation; 221 final Configuration configuration;
Kevin Millikin (Google) 2017/04/20 10:50:20 This is always a StatementConfiguration isn't it (
zhivkag 2017/04/20 13:21:36 Done.
224 222
225 State(this.environment, this.labels, this.continuation); 223 final ExpressionContinuation expressionContinuation;
Dmitry Stefantsov 2017/04/12 12:53:11 It think it would be easier to understand the inte
Kevin Millikin (Google) 2017/04/20 10:50:20 It's 'returnContinuaton', which seems like a good
zhivkag 2017/04/20 13:21:36 Done.
226 State.initial() : this(new Environment.empty(), null, null); 224
225 State(this.environment, this.labels, this.configuration,
226 this.expressionContinuation);
227
228 State.initial() : this(new Environment.empty(), null, null, null);
227 229
228 State withEnvironment(Environment env) { 230 State withEnvironment(Environment env) {
229 return new State(env, labels, continuation); 231 return new State(env, labels, configuration, expressionContinuation);
230 } 232 }
231 233
232 State withBreak(Statement stmt) { 234 State withBreak(Statement stmt) {
235 Label breakLabels = new Label(stmt, configuration, labels);
233 return new State( 236 return new State(
234 environment, new Label(stmt, continuation, labels), continuation); 237 environment, breakLabels, configuration, expressionContinuation);
235 } 238 }
236 239
237 State withContinuation(Continuation cont) { 240 State withConfiguration(Configuration config) {
238 return new State(environment, labels, cont); 241 return new State(environment, labels, config, expressionContinuation);
242 }
243
244 State withExpressionContinuation(ExpressionContinuation cont) {
245 return new State(environment, labels, configuration, cont);
239 } 246 }
240 247
241 Label lookupLabel(LabeledStatement s) { 248 Label lookupLabel(LabeledStatement s) {
242 assert(labels != null); 249 assert(labels != null);
243 return labels.lookupLabel(s); 250 return labels.lookupLabel(s);
244 } 251 }
245 } 252 }
246 253
247 /// Represent the continuation for execution of statement. 254 /// Represents a state for expression evaluation.
248 class Continuation { 255 class ExpressionState {
249 final Statement statement; 256 /// Enclosing statement state.
250 final State state; 257 final State statementState;
Dmitry Stefantsov 2017/04/12 12:53:11 Same as above with "expressionContinuation", I thi
Kevin Millikin (Google) 2017/04/20 10:50:20 I think it's unnecessary as described above.
zhivkag 2017/04/20 13:21:36 Acknowledged.
zhivkag 2017/04/20 13:21:36 Acknowledged.
251 258
252 Continuation(this.statement, this.state); 259 /// Environment in which the expression is evaluated.
260 final Environment environment;
261
262 /// Next continuation to be applied.
263 final ExpressionContinuation continuation;
264
265 ExpressionState(this.statementState, this.environment, this.continuation);
266
267 ExpressionState.fromStatementState(State state)
268 : this(state, state.environment, null);
269
270 ExpressionState withEnvironment(Environment env) {
271 return new ExpressionState(statementState, env, continuation);
272 }
273
274 ExpressionState withContinuation(ExpressionContinuation cont) {
275 return new ExpressionState(statementState, environment, cont);
276 }
277
278 /// Returns the next [Configuration]
279 Configuration nextConfiguration(Value v) {
280 if (continuation != null) {
281 return new ContinuationConfiguration(v, continuation);
282 }
283 return statementState.configuration;
284 }
253 } 285 }
254 286
255 /// Represents a labeled statement, the corresponding continuation and the 287 /// Represents a labeled statement, the corresponding continuation and the
256 /// enclosing label. 288 /// enclosing label.
257 class Label { 289 class Label {
258 final LabeledStatement statement; 290 final LabeledStatement statement;
259 final Continuation continuation; 291 final StatementConfiguration configuration;
260 final Label enclosingLabel; 292 final Label enclosingLabel;
261 293
262 Label(this.statement, this.continuation, this.enclosingLabel); 294 Label(this.statement, this.configuration, this.enclosingLabel);
263 295
264 Label lookupLabel(LabeledStatement s) { 296 Label lookupLabel(LabeledStatement s) {
265 if (identical(s, statement)) return this; 297 if (identical(s, statement)) return this;
266 assert(enclosingLabel != null); 298 assert(enclosingLabel != null);
267 return enclosingLabel.lookupLabel(s); 299 return enclosingLabel.lookupLabel(s);
268 } 300 }
269 } 301 }
270 302
303 abstract class Configuration {
304 /// Executes the current and returns the next configuration.
305 Configuration step(StatementExecuter executer);
306 }
307
308 /// Represents the configuration for execution of statement.
309 class StatementConfiguration extends Configuration {
310 final Statement statement;
311 final State state;
312
313 StatementConfiguration(this.statement, this.state);
314
315 Configuration step(StatementExecuter executer) =>
316 executer.exec(statement, state);
317 }
318
319 /// Represents the configuration for applying an [ExpressionContinuation].
320 class ContinuationConfiguration extends Configuration {
321 final Value value;
322 final ExpressionContinuation continuation;
323
324 ContinuationConfiguration(this.value, this.continuation);
Kevin Millikin (Google) 2017/04/20 10:50:20 I prefer the argument order to be swapped here (sw
zhivkag 2017/04/20 13:21:36 Done.
325
326 Configuration step(StatementExecuter executer) => continuation(value);
327 }
328
329 /// Represents the configuration for evaluating an [Expression].
330 class ExpressionConfiguration extends Configuration {
331 final Expression expression;
332 final ExpressionState state;
333
334 ExpressionConfiguration(this.expression, this.state);
335
336 Configuration step(StatementExecuter executer) =>
337 executer.eval(expression, state);
338 }
339
340 /// Represents an expression continuation.
341 abstract class ExpressionContinuation {
342 ExpressionState get state;
Kevin Millikin (Google) 2017/04/20 10:50:20 I'm not sure that every expression continuation sh
zhivkag 2017/04/20 13:21:36 Done.
343
344 Configuration call(Value v);
345 }
346
347 class PrintContinuation extends ExpressionContinuation {
348 final ExpressionState state;
349
350 PrintContinuation(this.state);
351
352 Configuration call(Value v) {
353 print(v.value);
354 return state.nextConfiguration(Value.nullInstance);
355 }
356 }
357
358 class PropertyGetContinuation extends ExpressionContinuation {
359 final Name name;
360 final ExpressionState state;
361
362 PropertyGetContinuation(this.name, this.state);
363
364 Configuration call(Value receiver) {
365 Value propertyValue = receiver.class_.lookupGetter(name)(receiver);
Kevin Millikin (Google) 2017/04/20 10:50:20 Not for this change, but we will have to find a wa
zhivkag 2017/04/20 13:21:36 Indeed. This is sufficient for now only because we
366 return state.nextConfiguration(propertyValue);
367 }
368 }
369
370 class PropertySetContinuation extends ExpressionContinuation {
371 final Expression value;
372 final Name setterName;
373 final ExpressionState state;
374
375 PropertySetContinuation(this.value, this.setterName, this.state);
376
377 Configuration call(Value receiver) {
378 Setter setter = receiver.class_.lookupSetter(setterName);
Kevin Millikin (Google) 2017/04/20 10:50:20 The spec has that setters are looked up after eval
zhivkag 2017/04/20 13:21:36 Done.
379 var cont = new SetterContinuation(setter, receiver, state);
380 return new ExpressionConfiguration(value, state.withContinuation(cont));
381 }
382 }
383
384 class SetterContinuation extends ExpressionContinuation {
385 final Setter setter;
386 final Value receiver;
387 final ExpressionState state;
388
389 SetterContinuation(this.setter, this.receiver, this.state);
390
391 Configuration call(Value v) {
392 setter(receiver, v);
393 return state.nextConfiguration(v);
394 }
395 }
396
397 class StaticInvocationContinuation extends ExpressionContinuation {
398 final ExpressionState state;
399
400 StaticInvocationContinuation(this.state);
401
402 Configuration call(Value v) {
403 return state.nextConfiguration(v);
404 }
405 }
406
407 class MethodInvocationContinuation extends ExpressionContinuation {
408 final Arguments arguments;
409 final Name methodName;
410 final ExpressionState state;
411
412 MethodInvocationContinuation(this.arguments, this.methodName, this.state);
413
414 Configuration call(Value receiver) {
415 if (arguments.positional.isEmpty) {
416 Value returnValue = receiver.invokeMethod(methodName);
417 return state.nextConfiguration(returnValue);
418 }
419 var cont =
420 new ArgumentsContinuation(receiver, methodName, arguments, state);
421
422 return new ExpressionConfiguration(
423 arguments.positional.first, state.withContinuation(cont));
424 }
425 }
426
427 class ArgumentsContinuation extends ExpressionContinuation {
428 final Value receiver;
429 final Name methodName;
430 final Arguments arguments;
431 final ExpressionState state;
432
433 ArgumentsContinuation(
434 this.receiver, this.methodName, this.arguments, this.state);
435
436 Configuration call(Value value) {
437 // Currently evaluates only one argument, for simple method invocations
438 // with 1 argument.
439 Value returnValue = receiver.invokeMethod(methodName, value);
440 return state.nextConfiguration(returnValue);
441 }
442 }
443
444 class VariableSetContinuation extends ExpressionContinuation {
445 final ExpressionState state;
446 final VariableDeclaration variable;
447
448 VariableSetContinuation(this.state, this.variable);
449
450 Configuration call(Value value) {
451 state.environment.assign(variable, value);
452 return state.nextConfiguration(value);
453 }
454 }
455
456 class NotContinuation extends ExpressionContinuation {
457 final ExpressionState state;
458
459 NotContinuation(this.state);
460
461 Configuration call(Value value) {
462 Value notValue = identical(Value.trueInstance, value)
463 ? Value.falseInstance
464 : Value.trueInstance;
465 return state.nextConfiguration(notValue);
466 }
467 }
468
469 class OrContinuation extends ExpressionContinuation {
470 final Expression right;
471 final ExpressionState state;
472
473 OrContinuation(this.right, this.state);
474
475 Configuration call(Value left) {
476 return identical(Value.trueInstance, left)
477 ? state.nextConfiguration(Value.trueInstance)
478 : new ExpressionConfiguration(right, state);
479 }
480 }
481
482 class AndContinuation extends ExpressionContinuation {
483 final Expression right;
484 final ExpressionState state;
485
486 AndContinuation(this.right, this.state);
487
488 Configuration call(Value left) {
489 return identical(Value.falseInstance, left)
490 ? state.nextConfiguration(Value.falseInstance)
491 : new ExpressionConfiguration(right, state);
492 }
493 }
494
495 class ConditionalContinuation extends ExpressionContinuation {
496 final Expression then;
497 final Expression otherwise;
498 final ExpressionState state;
499
500 ConditionalContinuation(this.then, this.otherwise, this.state);
501
502 Configuration call(Value value) {
503 return identical(Value.trueInstance, value)
504 ? new ExpressionConfiguration(then, state)
505 : new ExpressionConfiguration(otherwise, state);
506 }
507 }
508
509 class StringConcatenationContinuation extends ExpressionContinuation {
510 final List<Expression> expressions;
511 final ExpressionState state;
512
513 int _currentPosition = 0;
514 final List<Value> _values = <Value>[];
515
516 StringConcatenationContinuation(this.expressions, this.state);
517
518 Configuration call(Value value) {
519 _values.add(value);
520 if (_values.length == expressions.length) {
521 StringBuffer res = new StringBuffer();
522
523 for (int i = 0; i < expressions.length; i++) {
524 res.write(_values[i].value);
525 }
526
527 Value value = new StringValue(res.toString());
528 return state.nextConfiguration(value);
529 }
530 return new ExpressionConfiguration(
531 expressions[++_currentPosition], state.withContinuation(this));
532 }
533 }
534
535 class LetContinuation extends ExpressionContinuation {
536 final VariableDeclaration variable;
537 final Expression letBody;
538 final ExpressionState state;
539
540 LetContinuation(this.variable, this.letBody, this.state);
541
542 Configuration call(Value value) {
543 var letState = state.withEnvironment(new Environment(state.environment));
544 letState.environment.expand(variable, value);
545 return new ExpressionConfiguration(letBody, letState);
546 }
547 }
548
549 /// Represents the continuation for the condition expression in [WhileStatement] .
550 class WhileConditionContinuation extends ExpressionContinuation {
551 final WhileStatement node;
552 final ExpressionState state;
553
554 WhileConditionContinuation(this.node, this.state);
555
556 StatementConfiguration call(Value v) {
557 if (identical(v, Value.trueInstance)) {
558 // Add configuration for the While statement to the linked list.
559 StatementConfiguration config =
560 new StatementConfiguration(node, state.statementState);
561 // Configuration for the body of the loop.
562 return new StatementConfiguration(
563 node.body, state.statementState.withConfiguration(config));
564 }
565
566 return state.statementState.configuration;
567 }
568 }
569
570 /// Represents the continuation for the condition expression in [IfStatement].
571 class IfConditionContinuation extends ExpressionContinuation {
572 final Statement then;
573 final Statement otherwise;
574 final ExpressionState state;
575
576 IfConditionContinuation(this.then, this.otherwise, this.state);
577
578 StatementConfiguration call(Value v) {
579 if (identical(v, Value.trueInstance)) {
580 return new StatementConfiguration(then, state.statementState);
581 } else if (otherwise != null) {
582 return new StatementConfiguration(otherwise, state.statementState);
583 }
584 return state.statementState.configuration;
585 }
586 }
587
588 /// Represents the continuation for the initializer expression in
589 /// [VariableDeclaration].
590 class VariableInitializerContinuation extends ExpressionContinuation {
591 final VariableDeclaration variable;
592 final ExpressionState state;
593
594 VariableInitializerContinuation(this.variable, this.state);
595
596 StatementConfiguration call(Value v) {
597 state.statementState.environment.expand(variable, v);
598 return state.statementState.configuration;
599 }
600 }
601
271 /// Executes statements. 602 /// Executes statements.
272 /// 603 ///
273 /// Execution of a statement completes in one of the following ways: 604 /// Execution of a statement completes in one of the following ways:
274 /// - it completes normally, in which case the execution proceeds to applying 605 /// - it completes normally, in which case the execution proceeds to applying
275 /// the next continuation 606 /// the next continuation
276 /// - it breaks with a label, in which case the corresponding continuation is 607 /// - it breaks with a label, in which case the corresponding continuation is
277 /// returned and applied 608 /// returned and applied
278 /// - it returns with or without value, TBD 609 /// - it returns with or without value, TBD
279 /// - it throws, TBD 610 /// - it throws, TBD
280 class StatementExecuter extends StatementVisitor1<Continuation> { 611 class StatementExecuter extends StatementVisitor1<Configuration> {
281 Evaluator evaluator = new Evaluator(); 612 Evaluator evaluator = new Evaluator();
282 613
283 void trampolinedExecution(Continuation continuation) { 614 void trampolinedExecution(Configuration configuration) {
284 while (continuation != null) { 615 while (configuration != null) {
285 continuation = exec(continuation.statement, continuation.state); 616 configuration = configuration.step(this);
286 } 617 }
287 } 618 }
288 619
289 Continuation exec(Statement statement, state) => 620 Configuration exec(Statement statement, State state) =>
290 statement.accept1(this, state); 621 statement.accept1(this, state);
291 Value eval(Expression expression, env) => evaluator.eval(expression, env); 622 Configuration eval(Expression expression, ExpressionState state) =>
623 evaluator.eval(expression, state);
292 624
293 Continuation defaultStatement(Statement node, state) { 625 Configuration defaultStatement(Statement node, state) {
294 throw notImplemented( 626 throw notImplemented(
295 m: "Execution is not implemented for statement:\n$node "); 627 m: "Execution is not implemented for statement:\n$node ");
296 } 628 }
297 629
298 Continuation visitInvalidStatement(InvalidStatement node, state) { 630 Configuration visitInvalidStatement(InvalidStatement node, state) {
299 throw "Invalid statement at ${node.location}"; 631 throw "Invalid statement at ${node.location}";
300 } 632 }
301 633
302 Continuation visitExpressionStatement(ExpressionStatement node, state) { 634 Configuration visitExpressionStatement(ExpressionStatement node, state) {
303 eval(node.expression, state.environment); 635 return new ExpressionConfiguration(
304 return state.continuation; 636 node.expression, new ExpressionState.fromStatementState(state));
305 } 637 }
306 638
307 Continuation visitBlock(Block node, state) { 639 Configuration visitBlock(Block node, state) {
308 if (node.statements.isEmpty) { 640 if (node.statements.isEmpty) {
309 return state.continuation; 641 return state.configuration;
310 } 642 }
311 State blockState = 643 State blockState =
312 state.withEnvironment(new Environment(state.environment)); 644 state.withEnvironment(new Environment(state.environment));
313 Continuation cont = state.continuation; 645 StatementConfiguration configuration = state.configuration;
314 for (Statement s in node.statements.reversed) { 646 for (Statement s in node.statements.reversed) {
315 cont = new Continuation(s, blockState.withContinuation(cont)); 647 configuration = new StatementConfiguration(
648 s, blockState.withConfiguration(configuration));
316 } 649 }
317 return cont; 650 return configuration;
318 } 651 }
319 652
320 Continuation visitEmptyStatement(EmptyStatement node, state) { 653 Configuration visitEmptyStatement(EmptyStatement node, state) {
321 return state.continuation; 654 return state.configuration;
322 } 655 }
323 656
324 Continuation visitIfStatement(IfStatement node, state) { 657 Configuration visitIfStatement(IfStatement node, state) {
325 Value cond = eval(node.condition, state.environment).toBoolean(); 658 var expState = new ExpressionState.fromStatementState(state);
326 if (identical(Value.trueInstance, cond)) { 659 var cont = new IfConditionContinuation(node.then, node.otherwise, expState);
327 return new Continuation(node.then, state); 660 return new ExpressionConfiguration(
328 } else if (node.otherwise != null) { 661 node.condition, expState.withContinuation(cont));
329 return new Continuation(node.otherwise, state);
330 }
331 return state.continuation;
332 } 662 }
333 663
334 Continuation visitLabeledStatement(LabeledStatement node, state) { 664 Configuration visitLabeledStatement(LabeledStatement node, state) {
335 return new Continuation(node.body, state.withBreak(node)); 665 return new StatementConfiguration(node.body, state.withBreak(node));
336 } 666 }
337 667
338 Continuation visitBreakStatement(BreakStatement node, state) { 668 Configuration visitBreakStatement(BreakStatement node, state) {
339 return state.lookupLabel(node.target).continuation; 669 return state.lookupLabel(node.target).configuration;
340 } 670 }
341 671
342 Continuation visitWhileStatement(WhileStatement node, state) { 672 Configuration visitWhileStatement(WhileStatement node, state) {
343 Value cond = eval(node.condition, state.environment).toBoolean(); 673 var expState = new ExpressionState.fromStatementState(state);
344 if (identical(Value.trueInstance, cond)) { 674 var cont = new WhileConditionContinuation(node, expState);
345 // Add continuation for the While statement to the linked list. 675
346 Continuation cont = new Continuation(node, state); 676 return new ExpressionConfiguration(
347 // Continuation for the body of the loop. 677 node.condition, expState.withContinuation(cont));
348 return new Continuation(node.body, state.withContinuation(cont));
349 }
350 return state.continuation;
351 } 678 }
352 679
353 Continuation visitDoStatement(DoStatement node, state) { 680 Configuration visitDoStatement(DoStatement node, state) {
354 WhileStatement whileStatement = 681 WhileStatement whileStatement =
355 new WhileStatement(node.condition, node.body); 682 new WhileStatement(node.condition, node.body);
356 Continuation cont = new Continuation(whileStatement, state); 683 StatementConfiguration configuration =
357 return new Continuation(node.body, state.withContinuation(cont)); 684 new StatementConfiguration(whileStatement, state);
685
686 return new StatementConfiguration(
687 node.body, state.withConfiguration(configuration));
358 } 688 }
359 689
360 Continuation visitVariableDeclaration(VariableDeclaration node, state) { 690 Configuration visitReturnStatement(ReturnStatement node, state) {
361 Value value = node.initializer != null 691 assert(state.expressionContinuation != null);
362 ? eval(node.initializer, state.environment) 692 // The new ExpressionState contains the next expression continuation.
363 : Value.nullInstance; 693 var expState = new ExpressionState.fromStatementState(state)
364 state.environment.expand(node, value); 694 .withContinuation(state.expressionContinuation);
365 return state.continuation; 695 return new ExpressionConfiguration(node.expression, expState);
696 }
697
698 Configuration visitVariableDeclaration(VariableDeclaration node, state) {
699 if (node.initializer != null) {
700 var expState = new ExpressionState.fromStatementState(state);
701 var cont = new VariableInitializerContinuation(node, expState);
702 return new ExpressionConfiguration(
703 node.initializer, expState.withContinuation(cont));
704 }
705 state.environment.expand(node, Value.nullInstance);
706 return state.configuration;
366 } 707 }
367 } 708 }
368 709
710 // ------------------------------------------------------------------------
711 // VALUES
712 // ------------------------------------------------------------------------
713
369 typedef Value Getter(Value receiver); 714 typedef Value Getter(Value receiver);
370 typedef void Setter(Value receiver, Value value); 715 typedef void Setter(Value receiver, Value value);
371 716
372 class Class { 717 class Class {
373 static final Map<Reference, Class> _classes = <Reference, Class>{}; 718 static final Map<Reference, Class> _classes = <Reference, Class>{};
374 719
375 Class superclass; 720 Class superclass;
376 List<Field> instanceFields = <Field>[]; 721 List<Field> instanceFields = <Field>[];
377 List<Field> staticFields = <Field>[]; 722 List<Field> staticFields = <Field>[];
378 // Implicit getters and setters for instance Fields. 723 // Implicit getters and setters for instance Fields.
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 930
586 class NullValue extends LiteralValue { 931 class NullValue extends LiteralValue {
587 Object get value => null; 932 Object get value => null;
588 933
589 const NullValue(); 934 const NullValue();
590 } 935 }
591 936
592 notImplemented({String m, Object obj}) { 937 notImplemented({String m, Object obj}) {
593 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 938 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
594 } 939 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698