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

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

Issue 2806483003: Implement expression evaluation in Coninuation Passing Style (Closed)
Patch Set: Apply comments 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> {
78 Value eval(Expression expr, Environment env) => expr.accept1(this, env); 79 Configuration eval(Expression expr, ExpressionState state) =>
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 new ContinuationConfiguration(state.continuation, value);
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); 120 if ('print' == node.name.toString()) {
116 Value value = eval(node.value, env); 121 return new ExpressionConfiguration(node.arguments.positional.first,
117 receiver.class_.setProperty(receiver, node.target, value); 122 state.withContinuation(new PrintContinuation(state)));
118 return value; 123 } else {
119 } 124 // Currently supports only static invocations with no arguments.
125 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
126 State statementState = new State.initial()
127 .withExpressionContinuation(state.continuation)
128 .withConfiguration(new ExitConfiguration(state.continuation));
120 129
121 Value visitStaticGet(StaticGet node, env) => defaultExpression(node, env); 130 return new StatementConfiguration(
122 Value visitStaticSet(StaticSet node, env) => defaultExpression(node, env); 131 node.target.function.body, statementState);
123 132 }
124 Value visitStaticInvocation(StaticInvocation node, env) { 133 throw new NotImplemented(
125 if ('print' == node.name.toString()) { 134 'Support for static invocation with arguments is not implemented');
126 // Special evaluation of print.
127 var res = eval(node.arguments.positional[0], env);
128 print(res.value);
129 return Value.nullInstance;
130 } else {
131 throw new NotImplemented('Support for statement type '
132 '${node.runtimeType} is not implemented');
133 } 135 }
134 } 136 }
135 137
136 Value visitMethodInvocation(MethodInvocation node, env) { 138 Configuration visitMethodInvocation(MethodInvocation node, state) {
137 // Currently supports only method invocation with <2 arguments and is used 139 // Currently supports only method invocation with <2 arguments and is used
138 // to evaluate implemented operators for int, double and String values. 140 // to evaluate implemented operators for int, double and String values.
139 var receiver = eval(node.receiver, env); 141 var cont =
140 if (node.arguments.positional.isNotEmpty) { 142 new MethodInvocationContinuation(node.arguments, node.name, state);
141 var argValue = eval(node.arguments.positional.first, env); 143
142 return receiver.invokeMethod(node.name, argValue); 144 return new ExpressionConfiguration(
143 } else { 145 node.receiver, state.withContinuation(cont));
144 return receiver.invokeMethod(node.name);
145 }
146 } 146 }
147 147
148 Value visitConstructorInvocation(ConstructorInvocation node, env) { 148 Configuration visitConstructorInvocation(ConstructorInvocation node, state) {
149 Class class_ = new Class(node.target.enclosingClass.reference); 149 Class class_ = new Class(node.target.enclosingClass.reference);
150 150
151 Environment emptyEnv = new Environment.empty();
152 // Currently we don't support initializers. 151 // Currently we don't support initializers.
153 // TODO: Modify to respect dart semantics for initialization. 152 // TODO: Modify to respect dart semantics for initialization.
154 // 1. Init fields and eval initializers, repeat the same with super. 153 // 1. Init fields and eval initializers, repeat the same with super.
155 // 2. Eval the Function body of the constructor. 154 // 2. Eval the Function body of the constructor.
156 List<Value> fields = class_.instanceFields 155 List<Value> fields = <Value>[];
157 .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
158 .toList(growable: false);
159 156
160 return new ObjectValue(class_, fields); 157 return new ContinuationConfiguration(
158 state.continuation, new ObjectValue(class_, fields));
161 } 159 }
162 160
163 Value visitNot(Not node, env) { 161 Configuration visitNot(Not node, state) {
164 Value operand = eval(node.operand, env).toBoolean(); 162 return new ExpressionConfiguration(
165 return identical(operand, Value.trueInstance) 163 node.operand, state.withContinuation(new NotContinuation(state)));
166 ? Value.falseInstance
167 : Value.trueInstance;
168 } 164 }
169 165
170 Value visitLogicalExpression(LogicalExpression node, env) { 166 Configuration visitLogicalExpression(LogicalExpression node, state) {
171 if ('||' == node.operator) { 167 if ('||' == node.operator) {
172 BoolValue left = eval(node.left, env).toBoolean(); 168 var cont = new OrContinuation(node.right, state);
173 return identical(left, Value.trueInstance) 169 return new ExpressionConfiguration(
174 ? Value.trueInstance 170 node.left, state.withContinuation(cont));
175 : eval(node.right, env).toBoolean();
176 } else { 171 } else {
177 assert('&&' == node.operator); 172 assert('&&' == node.operator);
178 BoolValue left = eval(node.left, env).toBoolean(); 173 var cont = new AndContinuation(node.right, state);
179 return identical(left, Value.falseInstance) 174 return new ExpressionConfiguration(
180 ? Value.falseInstance 175 node.left, state.withContinuation(cont));
181 : eval(node.right, env).toBoolean();
182 } 176 }
183 } 177 }
184 178
185 Value visitConditionalExpression(ConditionalExpression node, env) { 179 Configuration visitConditionalExpression(ConditionalExpression node, state) {
186 var condition = eval(node.condition, env).toBoolean(); 180 var cont = new ConditionalContinuation(node.then, node.otherwise, state);
187 return identical(condition, Value.trueInstance) 181 return new ExpressionConfiguration(
188 ? eval(node.then, env) 182 node.condition, state.withContinuation(cont));
189 : eval(node.otherwise, env);
190 } 183 }
191 184
192 Value visitStringConcatenation(StringConcatenation node, env) { 185 Configuration visitStringConcatenation(StringConcatenation node, state) {
193 StringBuffer res = new StringBuffer(); 186 var cont = new StringConcatenationContinuation(node.expressions, state);
194 for (Expression e in node.expressions) { 187 return new ExpressionConfiguration(
195 res.write(eval(e, env).value); 188 node.expressions.first, state.withContinuation(cont));
196 }
197 return new StringValue(res.toString());
198 } 189 }
199 190
200 // Evaluation of BasicLiterals. 191 // Evaluation of BasicLiterals.
201 Value visitStringLiteral(StringLiteral node, env) => 192 Configuration visitStringLiteral(StringLiteral node, state) {
202 new StringValue(node.value); 193 return new ContinuationConfiguration(
203 Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value); 194 state.continuation, new StringValue(node.value));
204 Value visitDoubleLiteral(DoubleLiteral node, env) => 195 }
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 196
210 Value visitLet(Let node, env) { 197 Configuration visitIntLiteral(IntLiteral node, state) {
211 var value = eval(node.variable.initializer, env); 198 return new ContinuationConfiguration(
212 var letEnv = new Environment(env); 199 state.continuation, new IntValue(node.value));
213 letEnv.expand(node.variable, value); 200 }
214 return eval(node.body, letEnv); 201
202 Configuration visitDoubleLiteral(DoubleLiteral node, state) {
203 return new ContinuationConfiguration(
204 state.continuation, new DoubleValue(node.value));
205 }
206
207 Configuration visitBoolLiteral(BoolLiteral node, state) {
208 Value value = node.value ? Value.trueInstance : Value.falseInstance;
209 return new ContinuationConfiguration(state.continuation, value);
210 }
211
212 Configuration visitNullLiteral(NullLiteral node, state) {
213 return new ContinuationConfiguration(
214 state.continuation, Value.nullInstance);
215 }
216
217 Configuration visitLet(Let node, state) {
218 var letCont = new LetContinuation(node.variable, node.body, state);
219 return new ExpressionConfiguration(
220 node.variable.initializer, state.withContinuation(letCont));
215 } 221 }
216 } 222 }
217 223
218 /// Represents a state which consists of current environment, continuation to be 224 /// Represents a state for statement execution.
219 /// applied and the current label.
220 class State { 225 class State {
221 final Environment environment; 226 final Environment environment;
222 final Label labels; 227 final Label labels;
223 final Continuation continuation; 228 final StatementConfiguration statementConfiguration;
224 229
225 State(this.environment, this.labels, this.continuation); 230 final ExpressionContinuation returnContinuation;
226 State.initial() : this(new Environment.empty(), null, null); 231
232 State(this.environment, this.labels, this.statementConfiguration,
233 this.returnContinuation);
234
235 State.initial() : this(new Environment.empty(), null, null, null);
227 236
228 State withEnvironment(Environment env) { 237 State withEnvironment(Environment env) {
229 return new State(env, labels, continuation); 238 return new State(env, labels, statementConfiguration, returnContinuation);
230 } 239 }
231 240
232 State withBreak(Statement stmt) { 241 State withBreak(Statement stmt) {
242 Label breakLabels = new Label(stmt, statementConfiguration, labels);
233 return new State( 243 return new State(
234 environment, new Label(stmt, continuation, labels), continuation); 244 environment, breakLabels, statementConfiguration, returnContinuation);
235 } 245 }
236 246
237 State withContinuation(Continuation cont) { 247 State withConfiguration(Configuration config) {
238 return new State(environment, labels, cont); 248 return new State(environment, labels, config, returnContinuation);
249 }
250
251 State withExpressionContinuation(ExpressionContinuation cont) {
252 return new State(environment, labels, statementConfiguration, cont);
239 } 253 }
240 254
241 Label lookupLabel(LabeledStatement s) { 255 Label lookupLabel(LabeledStatement s) {
242 assert(labels != null); 256 assert(labels != null);
243 return labels.lookupLabel(s); 257 return labels.lookupLabel(s);
244 } 258 }
245 } 259 }
246 260
247 /// Represent the continuation for execution of statement. 261 /// Represents a state for expression evaluation.
248 class Continuation { 262 class ExpressionState {
249 final Statement statement; 263 /// Environment in which the expression is evaluated.
250 final State state; 264 final Environment environment;
251 265
252 Continuation(this.statement, this.state); 266 /// Next continuation to be applied.
267 final ExpressionContinuation continuation;
268
269 ExpressionState(this.environment, this.continuation);
270
271 ExpressionState.fromStatementState(State state)
272 : this(state.environment,
273 new ExpressionStatementContinuation(state.statementConfiguration));
274
275 ExpressionState withEnvironment(Environment env) {
276 return new ExpressionState(env, continuation);
277 }
278
279 ExpressionState withContinuation(ExpressionContinuation cont) {
280 return new ExpressionState(environment, cont);
281 }
253 } 282 }
254 283
255 /// Represents a labeled statement, the corresponding continuation and the 284 /// Represents a labeled statement, the corresponding continuation and the
256 /// enclosing label. 285 /// enclosing label.
257 class Label { 286 class Label {
258 final LabeledStatement statement; 287 final LabeledStatement statement;
259 final Continuation continuation; 288 final StatementConfiguration configuration;
260 final Label enclosingLabel; 289 final Label enclosingLabel;
261 290
262 Label(this.statement, this.continuation, this.enclosingLabel); 291 Label(this.statement, this.configuration, this.enclosingLabel);
263 292
264 Label lookupLabel(LabeledStatement s) { 293 Label lookupLabel(LabeledStatement s) {
265 if (identical(s, statement)) return this; 294 if (identical(s, statement)) return this;
266 assert(enclosingLabel != null); 295 assert(enclosingLabel != null);
267 return enclosingLabel.lookupLabel(s); 296 return enclosingLabel.lookupLabel(s);
268 } 297 }
269 } 298 }
270 299
300 abstract class Configuration {
301 /// Executes the current and returns the next configuration.
302 Configuration step(StatementExecuter executer);
303 }
304
305 /// Represents the configuration for execution of statement.
306 class StatementConfiguration extends Configuration {
307 final Statement statement;
308 final State state;
309
310 StatementConfiguration(this.statement, this.state);
311
312 Configuration step(StatementExecuter executer) =>
313 executer.exec(statement, state);
314 }
315
316 class ExitConfiguration extends StatementConfiguration {
317 final ExpressionContinuation returnContinuation;
318
319 ExitConfiguration(this.returnContinuation) : super(null, null);
320
321 Configuration step(StatementExecuter executer) {
322 return returnContinuation(Value.nullInstance);
323 }
324 }
325
326 /// Represents the configuration for applying an [ExpressionContinuation].
327 class ContinuationConfiguration extends Configuration {
328 final ExpressionContinuation continuation;
329 final Value value;
330
331 ContinuationConfiguration(this.continuation, this.value);
332
333 Configuration step(StatementExecuter executer) => continuation(value);
334 }
335
336 /// Represents the configuration for evaluating an [Expression].
337 class ExpressionConfiguration extends Configuration {
338 final Expression expression;
339 final ExpressionState state;
340
341 ExpressionConfiguration(this.expression, this.state);
342
343 Configuration step(StatementExecuter executer) =>
344 executer.eval(expression, state);
345 }
346
347 /// Represents an expression continuation.
348 abstract class ExpressionContinuation {
349 Configuration call(Value v);
350 }
351
352 /// Represents a continuation that returns the next [StatementConfiguration]
353 /// to be executed.
354 class ExpressionStatementContinuation extends ExpressionContinuation {
355 final StatementConfiguration configuration;
356
357 ExpressionStatementContinuation(this.configuration);
358
359 Configuration call(Value _) {
360 return configuration;
361 }
362 }
363
364 class PrintContinuation extends ExpressionContinuation {
365 final ExpressionState state;
366
367 PrintContinuation(this.state);
368
369 Configuration call(Value v) {
370 print(v.value);
371 return new ContinuationConfiguration(
372 state.continuation, Value.nullInstance);
373 }
374 }
375
376 class PropertyGetContinuation extends ExpressionContinuation {
377 final Name name;
378 final ExpressionState state;
379
380 PropertyGetContinuation(this.name, this.state);
381
382 Configuration call(Value receiver) {
383 // TODO: CPS the invocation of the getter.
384 Value propertyValue = receiver.class_.lookupGetter(name)(receiver);
385 return new ContinuationConfiguration(state.continuation, propertyValue);
386 }
387 }
388
389 class PropertySetContinuation extends ExpressionContinuation {
390 final Expression value;
391 final Name setterName;
392 final ExpressionState state;
393
394 PropertySetContinuation(this.value, this.setterName, this.state);
395
396 Configuration call(Value receiver) {
397 var cont = new SetterContinuation(receiver, setterName, state);
398 return new ExpressionConfiguration(value, state.withContinuation(cont));
399 }
400 }
401
402 class SetterContinuation extends ExpressionContinuation {
403 final Value receiver;
404 final Name name;
405 final ExpressionState state;
406
407 SetterContinuation(this.receiver, this.name, this.state);
408
409 Configuration call(Value v) {
410 Setter setter = receiver.class_.lookupSetter(name);
411 setter(receiver, v);
412 return new ContinuationConfiguration(state.continuation, v);
413 }
414 }
415
416 class StaticInvocationContinuation extends ExpressionContinuation {
417 final ExpressionState state;
418
419 StaticInvocationContinuation(this.state);
420
421 Configuration call(Value v) {
422 return new ContinuationConfiguration(state.continuation, v);
423 }
424 }
425
426 class MethodInvocationContinuation extends ExpressionContinuation {
427 final Arguments arguments;
428 final Name methodName;
429 final ExpressionState state;
430
431 MethodInvocationContinuation(this.arguments, this.methodName, this.state);
432
433 Configuration call(Value receiver) {
434 if (arguments.positional.isEmpty) {
435 Value returnValue = receiver.invokeMethod(methodName);
436 return new ContinuationConfiguration(state.continuation, returnValue);
437 }
438 var cont =
439 new ArgumentsContinuation(receiver, methodName, arguments, state);
440
441 return new ExpressionConfiguration(
442 arguments.positional.first, state.withContinuation(cont));
443 }
444 }
445
446 class ArgumentsContinuation extends ExpressionContinuation {
447 final Value receiver;
448 final Name methodName;
449 final Arguments arguments;
450 final ExpressionState state;
451
452 ArgumentsContinuation(
453 this.receiver, this.methodName, this.arguments, this.state);
454
455 Configuration call(Value value) {
456 // Currently evaluates only one argument, for simple method invocations
457 // with 1 argument.
458 Value returnValue = receiver.invokeMethod(methodName, value);
459 return new ContinuationConfiguration(state.continuation, returnValue);
460 }
461 }
462
463 class VariableSetContinuation extends ExpressionContinuation {
464 final ExpressionState state;
465 final VariableDeclaration variable;
466
467 VariableSetContinuation(this.state, this.variable);
468
469 Configuration call(Value value) {
470 state.environment.assign(variable, value);
471 return new ContinuationConfiguration(state.continuation, value);
472 }
473 }
474
475 class NotContinuation extends ExpressionContinuation {
476 final ExpressionState state;
477
478 NotContinuation(this.state);
479
480 Configuration call(Value value) {
481 Value notValue = identical(Value.trueInstance, value)
482 ? Value.falseInstance
483 : Value.trueInstance;
484 return new ContinuationConfiguration(state.continuation, notValue);
485 }
486 }
487
488 class OrContinuation extends ExpressionContinuation {
489 final Expression right;
490 final ExpressionState state;
491
492 OrContinuation(this.right, this.state);
493
494 Configuration call(Value left) {
495 return identical(Value.trueInstance, left)
496 ? new ContinuationConfiguration(state.continuation, Value.trueInstance)
497 : new ExpressionConfiguration(right, state);
498 }
499 }
500
501 class AndContinuation extends ExpressionContinuation {
502 final Expression right;
503 final ExpressionState state;
504
505 AndContinuation(this.right, this.state);
506
507 Configuration call(Value left) {
508 return identical(Value.falseInstance, left)
509 ? new ContinuationConfiguration(state.continuation, Value.falseInstance)
510 : new ExpressionConfiguration(right, state);
511 }
512 }
513
514 class ConditionalContinuation extends ExpressionContinuation {
515 final Expression then;
516 final Expression otherwise;
517 final ExpressionState state;
518
519 ConditionalContinuation(this.then, this.otherwise, this.state);
520
521 Configuration call(Value value) {
522 return identical(Value.trueInstance, value)
523 ? new ExpressionConfiguration(then, state)
524 : new ExpressionConfiguration(otherwise, state);
525 }
526 }
527
528 class StringConcatenationContinuation extends ExpressionContinuation {
529 final List<Expression> expressions;
530 final ExpressionState state;
531
532 int _currentPosition = 0;
533 final List<Value> _values = <Value>[];
534
535 StringConcatenationContinuation(this.expressions, this.state);
536
537 Configuration call(Value value) {
538 _values.add(value);
539 if (_values.length == expressions.length) {
540 StringBuffer res = new StringBuffer();
541
542 for (int i = 0; i < expressions.length; i++) {
543 res.write(_values[i].value);
544 }
545
546 Value value = new StringValue(res.toString());
547 return new ContinuationConfiguration(state.continuation, value);
548 }
549 return new ExpressionConfiguration(
550 expressions[++_currentPosition], state.withContinuation(this));
551 }
552 }
553
554 class LetContinuation extends ExpressionContinuation {
555 final VariableDeclaration variable;
556 final Expression letBody;
557 final ExpressionState state;
558
559 LetContinuation(this.variable, this.letBody, this.state);
560
561 Configuration call(Value value) {
562 var letState = state.withEnvironment(new Environment(state.environment));
563 letState.environment.expand(variable, value);
564 return new ExpressionConfiguration(letBody, letState);
565 }
566 }
567
568 /// Represents the continuation for the condition expression in [WhileStatement] .
569 class WhileConditionContinuation extends ExpressionContinuation {
570 final WhileStatement node;
571 final State state;
572
573 WhileConditionContinuation(this.node, this.state);
574
575 StatementConfiguration call(Value v) {
576 if (identical(v, Value.trueInstance)) {
577 // Add configuration for the While statement to the linked list.
578 StatementConfiguration config = new StatementConfiguration(node, state);
579 // Configuration for the body of the loop.
580 return new StatementConfiguration(
581 node.body, state.withConfiguration(config));
582 }
583
584 return state.statementConfiguration;
585 }
586 }
587
588 /// Represents the continuation for the condition expression in [IfStatement].
589 class IfConditionContinuation extends ExpressionContinuation {
590 final Statement then;
591 final Statement otherwise;
592 final State state;
593
594 IfConditionContinuation(this.then, this.otherwise, this.state);
595
596 StatementConfiguration call(Value v) {
597 if (identical(v, Value.trueInstance)) {
598 return new StatementConfiguration(then, state);
599 } else if (otherwise != null) {
600 return new StatementConfiguration(otherwise, state);
601 }
602 return state.statementConfiguration;
603 }
604 }
605
606 /// Represents the continuation for the initializer expression in
607 /// [VariableDeclaration].
608 class VariableInitializerContinuation extends ExpressionContinuation {
609 final VariableDeclaration variable;
610 final Environment environment;
611 final StatementConfiguration nextConfiguration;
612
613 VariableInitializerContinuation(
614 this.variable, this.environment, this.nextConfiguration);
615
616 StatementConfiguration call(Value v) {
617 environment.expand(variable, v);
618 return nextConfiguration;
619 }
620 }
621
271 /// Executes statements. 622 /// Executes statements.
272 /// 623 ///
273 /// Execution of a statement completes in one of the following ways: 624 /// Execution of a statement completes in one of the following ways:
274 /// - it completes normally, in which case the execution proceeds to applying 625 /// - it completes normally, in which case the execution proceeds to applying
275 /// the next continuation 626 /// the next continuation
276 /// - it breaks with a label, in which case the corresponding continuation is 627 /// - it breaks with a label, in which case the corresponding continuation is
277 /// returned and applied 628 /// returned and applied
278 /// - it returns with or without value, TBD 629 /// - it returns with or without value, TBD
279 /// - it throws, TBD 630 /// - it throws, TBD
280 class StatementExecuter extends StatementVisitor1<Continuation> { 631 class StatementExecuter extends StatementVisitor1<Configuration> {
281 Evaluator evaluator = new Evaluator(); 632 Evaluator evaluator = new Evaluator();
282 633
283 void trampolinedExecution(Continuation continuation) { 634 void trampolinedExecution(Configuration configuration) {
284 while (continuation != null) { 635 while (configuration != null) {
285 continuation = exec(continuation.statement, continuation.state); 636 configuration = configuration.step(this);
286 } 637 }
287 } 638 }
288 639
289 Continuation exec(Statement statement, state) => 640 Configuration exec(Statement statement, State state) =>
290 statement.accept1(this, state); 641 statement.accept1(this, state);
291 Value eval(Expression expression, env) => evaluator.eval(expression, env); 642 Configuration eval(Expression expression, ExpressionState state) =>
643 evaluator.eval(expression, state);
292 644
293 Continuation defaultStatement(Statement node, state) { 645 Configuration defaultStatement(Statement node, state) {
294 throw notImplemented( 646 throw notImplemented(
295 m: "Execution is not implemented for statement:\n$node "); 647 m: "Execution is not implemented for statement:\n$node ");
296 } 648 }
297 649
298 Continuation visitInvalidStatement(InvalidStatement node, state) { 650 Configuration visitInvalidStatement(InvalidStatement node, state) {
299 throw "Invalid statement at ${node.location}"; 651 throw "Invalid statement at ${node.location}";
300 } 652 }
301 653
302 Continuation visitExpressionStatement(ExpressionStatement node, state) { 654 Configuration visitExpressionStatement(ExpressionStatement node, state) {
303 eval(node.expression, state.environment); 655 return new ExpressionConfiguration(
304 return state.continuation; 656 node.expression, new ExpressionState.fromStatementState(state));
305 } 657 }
306 658
307 Continuation visitBlock(Block node, state) { 659 Configuration visitBlock(Block node, state) {
308 if (node.statements.isEmpty) { 660 if (node.statements.isEmpty) {
309 return state.continuation; 661 return state.statementConfiguration;
310 } 662 }
311 State blockState = 663 State blockState =
312 state.withEnvironment(new Environment(state.environment)); 664 state.withEnvironment(new Environment(state.environment));
313 Continuation cont = state.continuation; 665 StatementConfiguration configuration = state.statementConfiguration;
314 for (Statement s in node.statements.reversed) { 666 for (Statement s in node.statements.reversed) {
315 cont = new Continuation(s, blockState.withContinuation(cont)); 667 configuration = new StatementConfiguration(
668 s, blockState.withConfiguration(configuration));
316 } 669 }
317 return cont; 670 return configuration;
318 } 671 }
319 672
320 Continuation visitEmptyStatement(EmptyStatement node, state) { 673 Configuration visitEmptyStatement(EmptyStatement node, state) {
321 return state.continuation; 674 return state.statementConfiguration;
322 } 675 }
323 676
324 Continuation visitIfStatement(IfStatement node, state) { 677 Configuration visitIfStatement(IfStatement node, state) {
325 Value cond = eval(node.condition, state.environment).toBoolean(); 678 var expState = new ExpressionState.fromStatementState(state);
326 if (identical(Value.trueInstance, cond)) { 679 var cont = new IfConditionContinuation(node.then, node.otherwise, state);
327 return new Continuation(node.then, state); 680 return new ExpressionConfiguration(
328 } else if (node.otherwise != null) { 681 node.condition, expState.withContinuation(cont));
329 return new Continuation(node.otherwise, state);
330 }
331 return state.continuation;
332 } 682 }
333 683
334 Continuation visitLabeledStatement(LabeledStatement node, state) { 684 Configuration visitLabeledStatement(LabeledStatement node, state) {
335 return new Continuation(node.body, state.withBreak(node)); 685 return new StatementConfiguration(node.body, state.withBreak(node));
336 } 686 }
337 687
338 Continuation visitBreakStatement(BreakStatement node, state) { 688 Configuration visitBreakStatement(BreakStatement node, state) {
339 return state.lookupLabel(node.target).continuation; 689 return state.lookupLabel(node.target).configuration;
340 } 690 }
341 691
342 Continuation visitWhileStatement(WhileStatement node, state) { 692 Configuration visitWhileStatement(WhileStatement node, state) {
343 Value cond = eval(node.condition, state.environment).toBoolean(); 693 var expState = new ExpressionState.fromStatementState(state);
344 if (identical(Value.trueInstance, cond)) { 694 var cont = new WhileConditionContinuation(node, state);
345 // Add continuation for the While statement to the linked list. 695
346 Continuation cont = new Continuation(node, state); 696 return new ExpressionConfiguration(
347 // Continuation for the body of the loop. 697 node.condition, expState.withContinuation(cont));
348 return new Continuation(node.body, state.withContinuation(cont));
349 }
350 return state.continuation;
351 } 698 }
352 699
353 Continuation visitDoStatement(DoStatement node, state) { 700 Configuration visitDoStatement(DoStatement node, state) {
354 WhileStatement whileStatement = 701 WhileStatement whileStatement =
355 new WhileStatement(node.condition, node.body); 702 new WhileStatement(node.condition, node.body);
356 Continuation cont = new Continuation(whileStatement, state); 703 StatementConfiguration configuration =
357 return new Continuation(node.body, state.withContinuation(cont)); 704 new StatementConfiguration(whileStatement, state);
705
706 return new StatementConfiguration(
707 node.body, state.withConfiguration(configuration));
358 } 708 }
359 709
360 Continuation visitVariableDeclaration(VariableDeclaration node, state) { 710 Configuration visitReturnStatement(ReturnStatement node, state) {
361 Value value = node.initializer != null 711 assert(state.returnContinuation != null);
362 ? eval(node.initializer, state.environment) 712 // The new ExpressionState contains the next expression continuation.
363 : Value.nullInstance; 713 var expState = new ExpressionState.fromStatementState(state)
364 state.environment.expand(node, value); 714 .withContinuation(state.returnContinuation);
365 return state.continuation; 715 return new ExpressionConfiguration(
716 node.expression ?? new NullLiteral(), expState);
717 }
718
719 Configuration visitVariableDeclaration(VariableDeclaration node, state) {
720 if (node.initializer != null) {
721 var expState = new ExpressionState.fromStatementState(state);
722 var cont = new VariableInitializerContinuation(
723 node, state.environment, state.statementConfiguration);
724 return new ExpressionConfiguration(
725 node.initializer, expState.withContinuation(cont));
726 }
727 state.environment.expand(node, Value.nullInstance);
728 return state.statementConfiguration;
366 } 729 }
367 } 730 }
368 731
732 // ------------------------------------------------------------------------
733 // VALUES
734 // ------------------------------------------------------------------------
735
369 typedef Value Getter(Value receiver); 736 typedef Value Getter(Value receiver);
370 typedef void Setter(Value receiver, Value value); 737 typedef void Setter(Value receiver, Value value);
371 738
372 class Class { 739 class Class {
373 static final Map<Reference, Class> _classes = <Reference, Class>{}; 740 static final Map<Reference, Class> _classes = <Reference, Class>{};
374 741
375 Class superclass; 742 Class superclass;
376 List<Field> instanceFields = <Field>[]; 743 List<Field> instanceFields = <Field>[];
377 List<Field> staticFields = <Field>[]; 744 List<Field> staticFields = <Field>[];
378 // Implicit getters and setters for instance Fields. 745 // Implicit getters and setters for instance Fields.
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 952
586 class NullValue extends LiteralValue { 953 class NullValue extends LiteralValue {
587 Object get value => null; 954 Object get value => null;
588 955
589 const NullValue(); 956 const NullValue();
590 } 957 }
591 958
592 notImplemented({String m, Object obj}) { 959 notImplemented({String m, Object obj}) {
593 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 960 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
594 } 961 }
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