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

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

Issue 2806483003: Implement expression evaluation in Coninuation Passing Style (Closed)
Patch Set: Refactor Executer placement 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 static StatementExecuter visitor = new StatementExecuter();
Dmitry Stefantsov 2017/04/10 14:05:53 Why is it made static?
zhivkag 2017/04/11 11:37:39 This is a remainder from some initial experiments
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 cont =
28 new StatementConfiguration(statementBlock, new State.initial());
28 visitor.trampolinedExecution(cont); 29 visitor.trampolinedExecution(cont);
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 }
(...skipping 29 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 ExpressionConfiguration(value, state.continuation);
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 eval(node.value, state.withContinuation(cont));
95 } 99 }
96 100
97 Value visitPropertyGet(PropertyGet node, env) { 101 Configuration visitPropertyGet(PropertyGet node, state) {
98 Value receiver = eval(node.receiver, env); 102 var cont = new PropertyGetContinuation(node.name, state);
99 return receiver.class_.lookupGetter(node.name)(receiver); 103 return eval(node.receiver, state.continuation(cont));
100 } 104 }
101 105
102 Value visitPropertySet(PropertySet node, env) { 106 Configuration visitPropertySet(PropertySet node, state) {
103 Value receiver = eval(node.receiver, env); 107 var cont = new PropertySetContinuation(node.value, node.name, state, this);
104 Value value = eval(node.value, env); 108 return eval(node.receiver, state.withContinuation(cont));
105 receiver.class_.lookupSetter(node.name)(receiver, value);
106 return value;
107 } 109 }
108 110
109 Value visitDirectPropertyGet(DirectPropertyGet node, env) { 111 Configuration visitStaticGet(StaticGet node, state) =>
110 Value receiver = eval(node.receiver, env); 112 defaultExpression(node, state);
111 return receiver.class_.getProperty(receiver, node.target); 113 Configuration visitStaticSet(StaticSet node, state) =>
112 } 114 defaultExpression(node, state);
113 115
114 Value visitDirectPropertySet(DirectPropertySet node, env) { 116 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()) { 117 if ('print' == node.name.toString()) {
126 // Special evaluation of print. 118 return eval(node.arguments.positional.first,
127 var res = eval(node.arguments.positional[0], env); 119 state.withContinuation(new PrintContinuation(state.statementState)));
128 print(res.value);
129 return Value.nullInstance;
130 } else { 120 } else {
131 throw new NotImplemented('Support for statement type ' 121 // Currently supports only static invocations with no arguments.
132 '${node.runtimeType} is not implemented'); 122 if (node.arguments.positional.isEmpty && node.arguments.named.isEmpty) {
123 var cont = new StaticInvocationContinuation(state);
124 return new StatementConfiguration(node.target.function.body,
125 state.statementState.withExpressionContinuation(cont));
126 }
127 throw new NotImplemented(
128 'Support for static invocation with arguments is not implemented');
133 } 129 }
134 } 130 }
135 131
136 Value visitMethodInvocation(MethodInvocation node, env) { 132 Configuration visitMethodInvocation(MethodInvocation node, state) {
137 // Currently supports only method invocation with <2 arguments and is used 133 // Currently supports only method invocation with <2 arguments and is used
138 // to evaluate implemented operators for int, double and String values. 134 // to evaluate implemented operators for int, double and String values.
139 var receiver = eval(node.receiver, env); 135 var cont = new MethodInvocationContinuation(
140 if (node.arguments.positional.isNotEmpty) { 136 node.arguments, node.name, state, this);
141 var argValue = eval(node.arguments.positional.first, env); 137
142 return receiver.invokeMethod(node.name, argValue); 138 return eval(node.receiver, state.withContinuation(cont));
143 } else {
144 return receiver.invokeMethod(node.name);
145 }
146 } 139 }
147 140
148 Value visitConstructorInvocation(ConstructorInvocation node, env) { 141 Configuration visitConstructorInvocation(ConstructorInvocation node, state) {
149 Class class_ = new Class(node.target.enclosingClass.reference); 142 Class class_ = new Class(node.target.enclosingClass.reference);
150 143
151 Environment emptyEnv = new Environment.empty();
152 // Currently we don't support initializers. 144 // Currently we don't support initializers.
153 // TODO: Modify to respect dart semantics for initialization. 145 // TODO: Modify to respect dart semantics for initialization.
154 // 1. Init fields and eval initializers, repeat the same with super. 146 // 1. Init fields and eval initializers, repeat the same with super.
155 // 2. Eval the Function body of the constructor. 147 // 2. Eval the Function body of the constructor.
156 List<Value> fields = class_.instanceFields 148 List<Value> fields = <Value>[];
157 .map((Field f) => eval(f.initializer ?? new NullLiteral(), emptyEnv))
158 .toList(growable: false);
159 149
160 return new ObjectValue(class_, fields); 150 return new ExpressionConfiguration(
151 new ObjectValue(class_, fields), state.continuation);
161 } 152 }
162 153
163 Value visitNot(Not node, env) { 154 Configuration visitNot(Not node, state) {
164 Value operand = eval(node.operand, env).toBoolean(); 155 return eval(node.operand,
165 return identical(operand, Value.trueInstance) 156 state.withContinuation(new NotContinuation(state.continuation)));
166 ? Value.falseInstance
167 : Value.trueInstance;
168 } 157 }
169 158
170 Value visitLogicalExpression(LogicalExpression node, env) { 159 Configuration visitLogicalExpression(LogicalExpression node, state) {
171 if ('||' == node.operator) { 160 if ('||' == node.operator) {
172 BoolValue left = eval(node.left, env).toBoolean(); 161 var cont = new OrContinuation(state, node.right, this);
173 return identical(left, Value.trueInstance) 162 return eval(node.left, state.withContinuation(cont));
174 ? Value.trueInstance
175 : eval(node.right, env).toBoolean();
176 } else { 163 } else {
177 assert('&&' == node.operator); 164 assert('&&' == node.operator);
178 BoolValue left = eval(node.left, env).toBoolean(); 165 var cont = new AndContinuation(state, node.right, this);
179 return identical(left, Value.falseInstance) 166 return eval(node.left, state.withContinuation(cont));
180 ? Value.falseInstance
181 : eval(node.right, env).toBoolean();
182 } 167 }
183 } 168 }
184 169
185 Value visitConditionalExpression(ConditionalExpression node, env) { 170 Configuration visitConditionalExpression(ConditionalExpression node, state) {
186 var condition = eval(node.condition, env).toBoolean(); 171 var cont =
187 return identical(condition, Value.trueInstance) 172 new ConditionalContinuation(node.then, node.otherwise, state, this);
188 ? eval(node.then, env) 173 return eval(node.condition, state.withContinuation(cont));
189 : eval(node.otherwise, env);
190 } 174 }
191 175
192 Value visitStringConcatenation(StringConcatenation node, env) { 176 Configuration visitStringConcatenation(StringConcatenation node, state) {
193 StringBuffer res = new StringBuffer(); 177 var cont =
194 for (Expression e in node.expressions) { 178 new StringConcatenationContinuation(node.expressions, state, this);
195 res.write(eval(e, env).value); 179 return eval(node.expressions.first, state.withContinuation(cont));
196 }
197 return new StringValue(res.toString());
198 } 180 }
199 181
200 // Evaluation of BasicLiterals. 182 // Evaluation of BasicLiterals.
201 Value visitStringLiteral(StringLiteral node, env) => 183 Configuration visitStringLiteral(StringLiteral node, state) {
202 new StringValue(node.value); 184 return new ExpressionConfiguration(
203 Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value); 185 new StringValue(node.value), state.continuation);
204 Value visitDoubleLiteral(DoubleLiteral node, env) => 186 }
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 187
210 Value visitLet(Let node, env) { 188 Configuration visitIntLiteral(IntLiteral node, state) {
211 var value = eval(node.variable.initializer, env); 189 return new ExpressionConfiguration(
212 var letEnv = new Environment(env); 190 new IntValue(node.value), state.continuation);
213 letEnv.expand(node.variable, value); 191 }
214 return eval(node.body, letEnv); 192
193 Configuration visitDoubleLiteral(DoubleLiteral node, state) {
194 return new ExpressionConfiguration(
195 new DoubleValue(node.value), state.continuation);
196 }
197
198 Configuration visitBoolLiteral(BoolLiteral node, state) {
199 Value value = node.value ? Value.trueInstance : Value.falseInstance;
200 return new ExpressionConfiguration(value, state.continuation);
201 }
202
203 Configuration visitNullLiteral(NullLiteral node, state) {
204 return new ExpressionConfiguration(Value.nullInstance, state.continuation);
205 }
206
207 Configuration visitLet(Let node, state) {
208 var value = eval(node.variable.initializer, state);
209 var letState = state.withEnvironment(new Environment(state.environment));
210 letState.environment.expand(node.variable, value);
211 return eval(node.body, letState);
215 } 212 }
216 } 213 }
217 214
218 /// Represents a state which consists of current environment, continuation to be 215 /// Represents a state for statement execution.
219 /// applied and the current label.
220 class State { 216 class State {
221 final Environment environment; 217 final Environment environment;
222 final Label labels; 218 final Label labels;
223 final Continuation continuation; 219 final Configuration configuration;
224 220
225 State(this.environment, this.labels, this.continuation); 221 final ExpressionContinuation expressionContinuation;
226 State.initial() : this(new Environment.empty(), null, null); 222
223 State(this.environment, this.labels, this.configuration,
224 this.expressionContinuation);
225 State.initial() : this(new Environment.empty(), null, null, null);
227 226
228 State withEnvironment(Environment env) { 227 State withEnvironment(Environment env) {
229 return new State(env, labels, continuation); 228 return new State(env, labels, configuration, expressionContinuation);
230 } 229 }
231 230
232 State withBreak(Statement stmt) { 231 State withBreak(Statement stmt) {
232 Label breakLabels = new Label(stmt, configuration, labels);
233 return new State( 233 return new State(
234 environment, new Label(stmt, continuation, labels), continuation); 234 environment, breakLabels, configuration, expressionContinuation);
235 } 235 }
236 236
237 State withContinuation(Continuation cont) { 237 State withConfiguration(Configuration cont) {
Dmitry Stefantsov 2017/04/10 14:05:53 Maybe "cont" ==> "configuration"? We may use forms
zhivkag 2017/04/11 11:37:38 Done.
238 return new State(environment, labels, cont); 238 return new State(environment, labels, cont, expressionContinuation);
239 }
240
241 State withExpressionContinuation(ExpressionContinuation cont) {
242 return new State(environment, labels, configuration, cont);
239 } 243 }
240 244
241 Label lookupLabel(LabeledStatement s) { 245 Label lookupLabel(LabeledStatement s) {
242 assert(labels != null); 246 assert(labels != null);
243 return labels.lookupLabel(s); 247 return labels.lookupLabel(s);
244 } 248 }
245 } 249 }
246 250
247 /// Represent the continuation for execution of statement. 251 /// Represents a state for expression evaluation.
248 class Continuation { 252 class ExpressionState {
249 final Statement statement; 253 /// Enclosing statement state.
250 final State state; 254 final State statementState;
251 255
252 Continuation(this.statement, this.state); 256 /// Environment in which the expression is evaluated.
257 final Environment environment;
258
259 /// Next continuation to be evaluated.
260 final ExpressionContinuation continuation;
261
262 ExpressionState(this.statementState, this.environment, this.continuation);
263
264 ExpressionState.withStatementState(State state)
Dmitry Stefantsov 2017/04/10 14:05:53 Maybe rename it to "fromStatementState", because "
zhivkag 2017/04/11 11:37:38 Done.
265 : this(state, state.environment, state.expressionContinuation);
266
267 ExpressionState withEnvironment(Environment env) {
268 return new ExpressionState(statementState, env, continuation);
269 }
270
271 ExpressionState withContinuation(ExpressionContinuation cont) {
272 return new ExpressionState(statementState, environment, cont);
273 }
253 } 274 }
254 275
255 /// Represents a labeled statement, the corresponding continuation and the 276 /// Represents a labeled statement, the corresponding continuation and the
256 /// enclosing label. 277 /// enclosing label.
257 class Label { 278 class Label {
258 final LabeledStatement statement; 279 final LabeledStatement statement;
259 final Continuation continuation; 280 final StatementConfiguration continuation;
Dmitry Stefantsov 2017/04/10 14:05:53 "continuation" ==> "configuration"
zhivkag 2017/04/11 11:37:38 Done.
260 final Label enclosingLabel; 281 final Label enclosingLabel;
261 282
262 Label(this.statement, this.continuation, this.enclosingLabel); 283 Label(this.statement, this.continuation, this.enclosingLabel);
263 284
264 Label lookupLabel(LabeledStatement s) { 285 Label lookupLabel(LabeledStatement s) {
265 if (identical(s, statement)) return this; 286 if (identical(s, statement)) return this;
266 assert(enclosingLabel != null); 287 assert(enclosingLabel != null);
267 return enclosingLabel.lookupLabel(s); 288 return enclosingLabel.lookupLabel(s);
268 } 289 }
269 } 290 }
270 291
292 abstract class Configuration {
293 /// Executes the current and returns the next configuration.
294 Configuration step(StatementExecuter executer);
295 }
296
297 /// Represents the configuration for execution of statement.
298 class StatementConfiguration extends Configuration {
299 final Statement statement;
300 final State state;
301
302 StatementConfiguration(this.statement, this.state);
303
304 Configuration step(StatementExecuter executer) =>
305 executer.exec(statement, state);
306 }
307
308 /// Represents the configuration for applying an Expression continuation.
309 class ExpressionConfiguration extends Configuration {
310 final Value value;
311 final ExpressionContinuation continuation;
312
313 ExpressionConfiguration(this.value, this.continuation);
314
315 Configuration step(StatementExecuter executer) => continuation(value);
316 }
317
318 /// Represents an expression continuation.
319 abstract class ExpressionContinuation {
320 Configuration call(Value v);
321 }
322
323 class PrintContinuation extends ExpressionContinuation {
324 final State state;
Dmitry Stefantsov 2017/04/10 14:05:53 I think it's better to have ExpressionState rather
zhivkag 2017/04/11 11:37:39 Done.
325
326 PrintContinuation(this.state);
327
328 Configuration call(Value v) {
329 print(v.value);
330 return state.configuration;
331 }
332 }
333
334 class PropertyGetContinuation extends ExpressionContinuation {
335 final Name name;
336 final ExpressionState state;
337
338 PropertyGetContinuation(this.name, this.state);
339
340 Configuration call(Value value) {
341 Value propertyValue = value.class_.lookupGetter(name)(value);
342 return new ExpressionConfiguration(propertyValue, state.continuation);
343 }
344 }
345
346 class PropertySetContinuation extends ExpressionContinuation {
347 final Expression value;
348 final Name setterName;
349 final ExpressionState state;
350 final Evaluator evaluator;
Dmitry Stefantsov 2017/04/10 14:05:53 I don't think we want to have an Evaluator in a fi
zhivkag 2017/04/11 11:37:39 As we discussed offline, we couldn't see an obviou
351
352 PropertySetContinuation(
353 this.value, this.setterName, this.state, this.evaluator);
354
355 Configuration call(Value receiver) {
356 Setter setter = receiver.class_.lookupSetter(setterName);
357 var cont = new SetterContinuation(setter, receiver, state);
358 return evaluator.eval(value, state.withContinuation(cont));
359 }
360 }
361
362 class SetterContinuation extends ExpressionContinuation {
363 final Setter setter;
364 final Value receiver;
365 final ExpressionState state;
366
367 SetterContinuation(this.setter, this.receiver, this.state);
368
369 Configuration call(Value value) {
370 setter(receiver, value);
371 if (state.continuation != null) {
Dmitry Stefantsov 2017/04/10 14:05:53 I think we may write lines 371-374 as a method "Co
zhivkag 2017/04/11 11:37:38 Done.
372 return new ExpressionConfiguration(value, state.continuation);
373 }
374 return state.statementState.configuration;
375 }
376 }
377
378 class StaticInvocationContinuation extends ExpressionContinuation {
Dmitry Stefantsov 2017/04/10 14:05:53 Shouldn't this class have a reference to the metho
zhivkag 2017/04/11 11:37:38 With the current implementation we only support ca
379 final ExpressionState state;
380
381 StaticInvocationContinuation(this.state);
382
383 Configuration call(Value value) {
384 if (state.continuation != null) {
385 return new ExpressionConfiguration(value, state.continuation);
386 }
387 return state.statementState.configuration;
388 }
389 }
390
391 class MethodInvocationContinuation extends ExpressionContinuation {
392 final Arguments arguments;
393 final Name methodName;
394 final ExpressionState state;
395 final Evaluator evaluator;
396
397 MethodInvocationContinuation(
398 this.arguments, this.methodName, this.state, this.evaluator);
399
400 Configuration call(Value value) {
401 if (arguments.positional.isEmpty) {
Dmitry Stefantsov 2017/04/10 14:05:53 I think we may turn this if-statement into a case
zhivkag 2017/04/11 11:37:38 Acknowledged.
402 Value returnValue = value.invokeMethod(methodName);
403 return new ExpressionConfiguration(returnValue, state.continuation);
404 }
405 var cont = new ArgumentsContinuation(value, methodName, state);
406 return evaluator.eval(
407 arguments.positional.first, state.withContinuation(cont));
408 }
409 }
410
411 // Currently evaluates only one argument, for simple method invocations with 1
412 // argument.
413 class ArgumentsContinuation extends ExpressionContinuation {
414 final Value receiver;
415 final Name methodName;
416 final ExpressionState state;
417 //final Evaluator evaluator;
418
419 ArgumentsContinuation(this.receiver, this.methodName, this.state);
420
421 Configuration call(Value value) {
422 Value returnValue = receiver.invokeMethod(methodName, value);
423 return new ExpressionConfiguration(returnValue, state.continuation);
424 }
425 }
426
427 class VariableDeclarationContinuation extends ExpressionContinuation {
Dmitry Stefantsov 2017/04/10 14:05:53 I think variable declaration is not an expression,
zhivkag 2017/04/11 11:37:38 Done.
428 final VariableDeclaration variable;
429 final State state;
430
431 VariableDeclarationContinuation(this.variable, this.state);
432
433 Configuration call(Value value) {
434 state.environment.expand(variable, value);
435 return state.configuration;
436 }
437 }
438
439 class VariableSetContinuation extends ExpressionContinuation {
440 final ExpressionState state;
441 final VariableDeclaration variable;
442
443 VariableSetContinuation(this.state, this.variable);
444
445 Configuration call(Value value) {
446 state.environment.assign(variable, value);
447 return new ExpressionConfiguration(value, state.continuation);
448 }
449 }
450
451 class NotContinuation extends ExpressionContinuation {
452 final ExpressionContinuation continuation;
453
454 NotContinuation(this.continuation);
455
456 Configuration call(Value value) {
457 Value notValue = identical(Value.trueInstance, value)
458 ? Value.falseInstance
459 : Value.trueInstance;
460 return new ExpressionConfiguration(notValue, continuation);
461 }
462 }
463
464 class OrContinuation extends ExpressionContinuation {
465 final ExpressionState state;
466 final Expression right;
467 final Evaluator evaluator;
468
469 OrContinuation(this.state, this.right, this.evaluator);
470
471 Configuration call(Value left) {
472 return identical(Value.trueInstance, left)
473 ? new ExpressionConfiguration(Value.trueInstance, state.continuation)
474 : evaluator.eval(right, state);
475 }
476 }
477
478 class AndContinuation extends ExpressionContinuation {
479 final ExpressionState state;
480 final Expression right;
481 final Evaluator evaluator; // wth??
482
483 AndContinuation(this.state, this.right, this.evaluator);
484
485 Configuration call(Value left) {
486 return identical(Value.falseInstance, left)
487 ? new ExpressionConfiguration(Value.falseInstance, state.continuation)
488 : evaluator.eval(right, state);
489 }
490 }
491
492 class ConditionalContinuation extends ExpressionContinuation {
493 final Expression then;
494 final Expression otherwise;
495 final ExpressionState state;
496 final Evaluator evaluator;
497
498 ConditionalContinuation(
499 this.then, this.otherwise, this.state, this.evaluator);
500
501 Configuration call(Value value) {
502 return identical(Value.trueInstance, value)
503 ? evaluator.eval(then, state)
504 : evaluator.eval(otherwise, state);
505 }
506 }
507
508 class StringConcatenationContinuation extends ExpressionContinuation {
509 final List<Expression> expressions;
510 final ExpressionState state;
511 final Evaluator evaluator;
512
513 int _currentPosition = 0;
514 final List<Value> _values = <Value>[];
515
516 StringConcatenationContinuation(this.expressions, this.state, this.evaluator);
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 new ExpressionConfiguration(value, state.continuation);
529 }
530 return evaluator.eval(
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 final Evaluator evaluator;
540
541 LetContinuation(this.variable, this.letBody, this.state, this.evaluator);
542
543 Configuration call(Value value) {
544 var letState = state.withEnvironment(new Environment(state.environment));
545 letState.environment.expand(variable, value);
546 return evaluator.eval(letBody, letState);
547 }
548 }
549
271 /// Executes statements. 550 /// Executes statements.
272 /// 551 ///
273 /// Execution of a statement completes in one of the following ways: 552 /// Execution of a statement completes in one of the following ways:
274 /// - it completes normally, in which case the execution proceeds to applying 553 /// - it completes normally, in which case the execution proceeds to applying
275 /// the next continuation 554 /// the next continuation
276 /// - it breaks with a label, in which case the corresponding continuation is 555 /// - it breaks with a label, in which case the corresponding continuation is
277 /// returned and applied 556 /// returned and applied
278 /// - it returns with or without value, TBD 557 /// - it returns with or without value, TBD
279 /// - it throws, TBD 558 /// - it throws, TBD
280 class StatementExecuter extends StatementVisitor1<Continuation> { 559 class StatementExecuter extends StatementVisitor1<Configuration> {
281 Evaluator evaluator = new Evaluator(); 560 Evaluator evaluator = new Evaluator();
282 561
283 void trampolinedExecution(Continuation continuation) { 562 void trampolinedExecution(Configuration continuation) {
Dmitry Stefantsov 2017/04/10 14:05:53 "continuation" ==> "configuration"
zhivkag 2017/04/11 11:37:38 Done.
284 while (continuation != null) { 563 while (continuation != null) {
285 continuation = exec(continuation.statement, continuation.state); 564 continuation = continuation.step(this);
286 } 565 }
287 } 566 }
288 567
289 Continuation exec(Statement statement, state) => 568 Configuration exec(Statement statement, State state) =>
290 statement.accept1(this, state); 569 statement.accept1(this, state);
291 Value eval(Expression expression, env) => evaluator.eval(expression, env); 570 Configuration eval(Expression expression, ExpressionState state) =>
571 evaluator.eval(expression, state);
292 572
293 Continuation defaultStatement(Statement node, state) { 573 Configuration defaultStatement(Statement node, state) {
294 throw notImplemented( 574 throw notImplemented(
295 m: "Execution is not implemented for statement:\n$node "); 575 m: "Execution is not implemented for statement:\n$node ");
296 } 576 }
297 577
298 Continuation visitInvalidStatement(InvalidStatement node, state) { 578 Configuration visitInvalidStatement(InvalidStatement node, state) {
299 throw "Invalid statement at ${node.location}"; 579 throw "Invalid statement at ${node.location}";
300 } 580 }
301 581
302 Continuation visitExpressionStatement(ExpressionStatement node, state) { 582 Configuration visitExpressionStatement(ExpressionStatement node, state) {
303 eval(node.expression, state.environment); 583 return eval(node.expression, new ExpressionState.withStatementState(state));
304 return state.continuation;
305 } 584 }
306 585
307 Continuation visitBlock(Block node, state) { 586 Configuration visitBlock(Block node, state) {
308 if (node.statements.isEmpty) { 587 if (node.statements.isEmpty) {
309 return state.continuation; 588 return state.configuration;
310 } 589 }
311 State blockState = 590 State blockState =
312 state.withEnvironment(new Environment(state.environment)); 591 state.withEnvironment(new Environment(state.environment));
313 Continuation cont = state.continuation; 592 StatementConfiguration cont = state.configuration;
Dmitry Stefantsov 2017/04/10 14:05:53 "cont" ==> "configuration"
zhivkag 2017/04/11 11:37:39 Done.
314 for (Statement s in node.statements.reversed) { 593 for (Statement s in node.statements.reversed) {
315 cont = new Continuation(s, blockState.withContinuation(cont)); 594 cont = new StatementConfiguration(s, blockState.withConfiguration(cont));
316 } 595 }
317 return cont; 596 return cont;
318 } 597 }
319 598
320 Continuation visitEmptyStatement(EmptyStatement node, state) { 599 Configuration visitEmptyStatement(EmptyStatement node, state) {
321 return state.continuation; 600 return state.configuration;
322 } 601 }
323 602
324 Continuation visitIfStatement(IfStatement node, state) { 603 Configuration visitIfStatement(IfStatement node, state) {
325 Value cond = eval(node.condition, state.environment).toBoolean(); 604 // shortcutting
326 if (identical(Value.trueInstance, cond)) { 605 ExpressionConfiguration cont = eval(node.condition, state);
Dmitry Stefantsov 2017/04/10 14:05:53 The variable "state" here is most likely a State,
Dmitry Stefantsov 2017/04/10 14:05:53 "cont" ==> "configuration"
zhivkag 2017/04/11 11:37:38 Here and below are some calls to eval that I misse
zhivkag 2017/04/11 11:37:39 Done.
327 return new Continuation(node.then, state); 606 if (identical(Value.trueInstance, cont.value)) {
607 return new StatementConfiguration(node.then, state);
328 } else if (node.otherwise != null) { 608 } else if (node.otherwise != null) {
329 return new Continuation(node.otherwise, state); 609 return new StatementConfiguration(node.otherwise, state);
330 } 610 }
331 return state.continuation; 611 return state.configuration;
332 } 612 }
333 613
334 Continuation visitLabeledStatement(LabeledStatement node, state) { 614 Configuration visitLabeledStatement(LabeledStatement node, state) {
335 return new Continuation(node.body, state.withBreak(node)); 615 return new StatementConfiguration(node.body, state.withBreak(node));
336 } 616 }
337 617
338 Continuation visitBreakStatement(BreakStatement node, state) { 618 Configuration visitBreakStatement(BreakStatement node, state) {
339 return state.lookupLabel(node.target).continuation; 619 return state.lookupLabel(node.target).configuration;
340 } 620 }
341 621
342 Continuation visitWhileStatement(WhileStatement node, state) { 622 Configuration visitWhileStatement(WhileStatement node, state) {
343 Value cond = eval(node.condition, state.environment).toBoolean(); 623 // shortcutting
344 if (identical(Value.trueInstance, cond)) { 624 ExpressionConfiguration cont = eval(node.condition, state.environment);
Dmitry Stefantsov 2017/04/10 14:05:53 Does "eval" accepts an Environment as the second a
Dmitry Stefantsov 2017/04/10 14:05:53 "cont" ==> "configuration"
zhivkag 2017/04/11 11:37:38 eval takes an Expression and an ExpressionState, i
zhivkag 2017/04/11 11:37:38 Done.
625 if (identical(Value.trueInstance, cont.value)) {
345 // Add continuation for the While statement to the linked list. 626 // Add continuation for the While statement to the linked list.
346 Continuation cont = new Continuation(node, state); 627 StatementConfiguration cont = new StatementConfiguration(node, state);
347 // Continuation for the body of the loop. 628 // Continuation for the body of the loop.
348 return new Continuation(node.body, state.withContinuation(cont)); 629 return new StatementConfiguration(
630 node.body, state.withConfiguration(cont));
349 } 631 }
350 return state.continuation; 632 return state.configuration;
351 } 633 }
352 634
353 Continuation visitDoStatement(DoStatement node, state) { 635 Configuration visitDoStatement(DoStatement node, state) {
354 WhileStatement whileStatement = 636 WhileStatement whileStatement =
355 new WhileStatement(node.condition, node.body); 637 new WhileStatement(node.condition, node.body);
356 Continuation cont = new Continuation(whileStatement, state); 638 StatementConfiguration cont =
357 return new Continuation(node.body, state.withContinuation(cont)); 639 new StatementConfiguration(whileStatement, state);
640 return new StatementConfiguration(node.body, state.withConfiguration(cont));
358 } 641 }
359 642
360 Continuation visitVariableDeclaration(VariableDeclaration node, state) { 643 Configuration visitReturnStatement(ReturnStatement node, state) {
361 Value value = node.initializer != null 644 assert(state.expressionContinuation != null);
362 ? eval(node.initializer, state.environment) 645 var expState = new ExpressionState.withStatementState(state);
363 : Value.nullInstance; 646 return eval(node.expression, expState);
364 state.environment.expand(node, value); 647 }
365 return state.continuation; 648
649 Configuration visitVariableDeclaration(VariableDeclaration node, state) {
650 if (node.initializer != null) {
651 var cont = new VariableDeclarationContinuation(node, state);
Dmitry Stefantsov 2017/04/10 14:05:53 I don't think we should have "VariableDeclarationC
zhivkag 2017/04/11 11:37:38 Done.
652 return eval(node.initializer,
653 new ExpressionState.withStatementState(state).withContinuation(cont));
654 } else {
655 state.environment.expand(node, Value.nullInstance);
656 return state.configuration;
657 }
366 } 658 }
367 } 659 }
368 660
661 // ------------------------------------------------------------------------
662 // VALUES
663 // ------------------------------------------------------------------------
664
369 typedef Value Getter(Value receiver); 665 typedef Value Getter(Value receiver);
370 typedef void Setter(Value receiver, Value value); 666 typedef void Setter(Value receiver, Value value);
371 667
372 class Class { 668 class Class {
373 static final Map<Reference, Class> _classes = <Reference, Class>{}; 669 static final Map<Reference, Class> _classes = <Reference, Class>{};
374 670
375 Class superclass; 671 Class superclass;
376 List<Field> instanceFields = <Field>[]; 672 List<Field> instanceFields = <Field>[];
377 List<Field> staticFields = <Field>[]; 673 List<Field> staticFields = <Field>[];
378 // Implicit getters and setters for instance Fields. 674 // Implicit getters and setters for instance Fields.
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 881
586 class NullValue extends LiteralValue { 882 class NullValue extends LiteralValue {
587 Object get value => null; 883 Object get value => null;
588 884
589 const NullValue(); 885 const NullValue();
590 } 886 }
591 887
592 notImplemented({String m, Object obj}) { 888 notImplemented({String m, Object obj}) {
593 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 889 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
594 } 890 }
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