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

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

Issue 2980733002: Refactor the interpeter according the specification for Kernel semantics (Closed)
Patch Set: Created 3 years, 5 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 | pkg/kernel/test/interpreter/interpreter.status » ('j') | 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 import '../log.dart'; 9 import '../log.dart';
10 export '../log.dart'; 10 export '../log.dart';
(...skipping 12 matching lines...) Expand all
23 23
24 Interpreter(this.program); 24 Interpreter(this.program);
25 25
26 void run() { 26 void run() {
27 assert(program.libraries.isEmpty); 27 assert(program.libraries.isEmpty);
28 Procedure mainMethod = program.mainMethod; 28 Procedure mainMethod = program.mainMethod;
29 29
30 if (mainMethod == null) return; 30 if (mainMethod == null) return;
31 31
32 Statement statementBlock = mainMethod.function.body; 32 Statement statementBlock = mainMethod.function.body;
33 ExecConfiguration configuration = 33 ExecConfiguration configuration = new ExecConfiguration(
34 new ExecConfiguration(statementBlock, new State.initial()); 34 statementBlock, new Environment.empty(), const State.initial());
35 visitor.trampolinedExecution(configuration); 35 visitor.trampolinedExecution(configuration);
36 } 36 }
37 } 37 }
38 38
39 class Location { 39 class Location {
40 Value value; 40 Value value;
41 41
42 Location(this.value); 42 Location(this.value);
43 } 43 }
44 44
45 class Binding { 45 class Binding {
46 final VariableDeclaration variable; 46 final VariableDeclaration variable;
47 final Location location; 47 final Location location;
48 48
49 Binding(this.variable, this.location); 49 Binding(this.variable, this.location);
50 } 50 }
51 51
52 class Environment { 52 class Environment {
53 final List<Binding> bindings = <Binding>[]; 53 final List<Binding> bindings = <Binding>[];
54 final Environment parent; 54 final Environment parent;
55 55
56 Value get thisInstance => (parent != null) 56 Value get thisInstance {
57 ? parent.thisInstance 57 return containsThis()
58 : throw "Invalid reference to 'this' expression"; 58 ? lookupThis().value
59 : throw "Invalid reference to 'this' expression";
60 }
59 61
60 Environment.empty() : parent = null; 62 Environment.empty() : parent = null;
61 Environment(this.parent); 63 Environment(this.parent);
62 64
63 bool contains(VariableDeclaration variable) { 65 bool contains(VariableDeclaration variable) {
64 for (Binding b in bindings.reversed) { 66 for (Binding b in bindings.reversed) {
65 if (identical(b.variable, variable)) return true; 67 if (identical(b.variable, variable)) return true;
66 } 68 }
67 return parent?.contains(variable) ?? false; 69 return parent?.contains(variable) ?? false;
68 } 70 }
69 71
72 bool containsThis() {
73 for (Binding b in bindings.reversed) {
74 if (identical(b.variable.name, 'this')) return true;
75 }
76 return parent?.containsThis() ?? false;
77 }
78
70 Binding lookupBinding(VariableDeclaration variable) { 79 Binding lookupBinding(VariableDeclaration variable) {
71 assert(contains(variable)); 80 assert(contains(variable));
72 for (Binding b in bindings) { 81 for (Binding b in bindings) {
73 if (identical(b.variable, variable)) return b; 82 if (identical(b.variable, variable)) return b;
74 } 83 }
75 return parent.lookupBinding(variable); 84 return parent.lookupBinding(variable);
76 } 85 }
77 86
87 Location lookupThis() {
88 assert(containsThis());
89 for (Binding b in bindings) {
90 if (identical(b.variable.name, 'this')) return b.location;
91 }
92 return parent.lookupThis();
93 }
94
78 Value lookup(VariableDeclaration variable) { 95 Value lookup(VariableDeclaration variable) {
79 return lookupBinding(variable).location.value; 96 return lookupBinding(variable).location.value;
80 } 97 }
81 98
82 void assign(VariableDeclaration variable, Value value) { 99 void assign(VariableDeclaration variable, Value value) {
83 assert(contains(variable)); 100 assert(contains(variable));
84 lookupBinding(variable).location.value = value; 101 lookupBinding(variable).location.value = value;
85 } 102 }
86 103
87 void expand(VariableDeclaration variable, Value value) { 104 Environment extend(VariableDeclaration variable, Value value) {
88 assert(!contains(variable)); 105 assert(!contains(variable));
89 bindings.add(new Binding(variable, new Location(value))); 106 return new Environment(this)
107 ..bindings.add(new Binding(variable, new Location(value)));
108 }
109
110 Environment extendWithThis(ObjectValue v) {
111 assert(!containsThis());
112 return extend(new VariableDeclaration('this'), v);
90 } 113 }
91 } 114 }
92 115
93 class InstanceEnvironment extends Environment {
94 final ObjectValue _thisInstance;
95 Value get thisInstance => _thisInstance;
96
97 InstanceEnvironment(this._thisInstance, Environment env) : super(env);
98 }
99
100 /// Evaluate expressions. 116 /// Evaluate expressions.
101 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { 117 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
102 Configuration eval(Expression expr, EvalConfiguration config) => 118 Configuration eval(Expression expr, EvalConfiguration config) =>
103 expr.accept1(this, config); 119 expr.accept1(this, config);
104 120
105 Configuration evalList(List<InterpreterExpression> list, Environment env, 121 Configuration evalList(List<InterpreterExpression> list, Environment env,
106 ApplicationContinuation cont) { 122 ApplicationContinuation cont) {
107 if (list.isNotEmpty) { 123 if (list.isNotEmpty) {
108 return new EvalConfiguration(list.first.expression, env, 124 return new EvalConfiguration(list.first.expression, env,
109 new ExpressionListContinuation(list.first, list.skip(1), env, cont)); 125 new ExpressionListEK(list.first, list.skip(1), env, cont));
110 } 126 }
111 return new ApplicationConfiguration(cont, <InterpreterValue>[]); 127 return new ApplicationConfiguration(cont, <InterpreterValue>[]);
112 } 128 }
113 129
114 Configuration defaultExpression(Expression node, EvalConfiguration config) { 130 Configuration defaultExpression(Expression node, EvalConfiguration config) {
115 throw new NotImplemented('Evaluation for expressions of type ' 131 throw new NotImplemented('Evaluation for expressions of type '
116 '${node.runtimeType} is not implemented.'); 132 '${node.runtimeType} is not implemented.');
117 } 133 }
118 134
119 Configuration visitInvalidExpression1( 135 Configuration visitInvalidExpression1(
120 InvalidExpression node, EvalConfiguration config) { 136 InvalidExpression node, EvalConfiguration config) {
121 throw 'Invalid expression at ${node.location.toString()}'; 137 throw 'Invalid expression at ${node.location.toString()}';
122 } 138 }
123 139
124 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { 140 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) {
125 Value value = config.environment.lookup(node.variable); 141 Value value = config.environment.lookup(node.variable);
126 return new ValuePassingConfiguration(config.continuation, value); 142 return new ValuePassingConfiguration(config.continuation, value);
127 } 143 }
128 144
129 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { 145 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) {
130 var cont = new VariableSetContinuation( 146 var cont = new VariableSetEK(
131 node.variable, config.environment, config.continuation); 147 node.variable, config.environment, config.continuation);
132 return new EvalConfiguration(node.value, config.environment, cont); 148 return new EvalConfiguration(node.value, config.environment, cont);
133 } 149 }
134 150
135 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { 151 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) {
136 var cont = new PropertyGetContinuation(node.name, config.continuation); 152 var cont = new PropertyGetEK(node.name, config.continuation);
137 return new EvalConfiguration(node.receiver, config.environment, cont); 153 return new EvalConfiguration(node.receiver, config.environment, cont);
138 } 154 }
139 155
140 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { 156 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) {
141 var cont = new PropertySetContinuation( 157 var cont = new PropertySetEK(
142 node.value, node.name, config.environment, config.continuation); 158 node.value, node.name, config.environment, config.continuation);
143 return new EvalConfiguration(node.receiver, config.environment, cont); 159 return new EvalConfiguration(node.receiver, config.environment, cont);
144 } 160 }
145 161
146 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => 162 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) =>
147 defaultExpression(node, config); 163 defaultExpression(node, config);
148 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => 164 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) =>
149 defaultExpression(node, config); 165 defaultExpression(node, config);
150 166
151 Configuration visitStaticInvocation( 167 Configuration visitStaticInvocation(
152 StaticInvocation node, EvalConfiguration config) { 168 StaticInvocation node, EvalConfiguration config) {
153 if ('print' == node.name.toString()) { 169 if ('print' == node.name.toString()) {
154 var cont = new PrintContinuation(config.continuation); 170 var cont = new PrintEK(config.continuation);
155 return new EvalConfiguration( 171 return new EvalConfiguration(
156 node.arguments.positional.first, config.environment, cont); 172 node.arguments.positional.first, config.environment, cont);
157 } else { 173 } else {
158 log.info('static-invocation-${node.target.name.toString()}\n'); 174 log.info('static-invocation-${node.target.name.toString()}\n');
159 175
160 List<InterpreterExpression> args = 176 List<InterpreterExpression> args =
161 _createArgumentExpressionList(node.arguments, node.target.function); 177 _createArgumentExpressionList(node.arguments, node.target.function);
162 ApplicationContinuation cont = new StaticInvocationApplication( 178 ApplicationContinuation cont =
163 node.target.function, config.continuation); 179 new StaticInvocationA(node.target.function, config.continuation);
164 return new EvalListConfiguration(args, config.environment, cont); 180 return new EvalListConfiguration(args, config.environment, cont);
165 } 181 }
166 } 182 }
167 183
168 Configuration visitMethodInvocation( 184 Configuration visitMethodInvocation(
169 MethodInvocation node, EvalConfiguration config) { 185 MethodInvocation node, EvalConfiguration config) {
170 // Currently supports only method invocation with <2 arguments and is used 186 // Currently supports only method invocation with <2 arguments and is used
171 // to evaluate implemented operators for int, double and String values. 187 // to evaluate implemented operators for int, double and String values.
172 var cont = new MethodInvocationContinuation( 188 var cont = new MethodInvocationEK(
173 node.arguments, node.name, config.environment, config.continuation); 189 node.arguments, node.name, config.environment, config.continuation);
174 190
175 return new EvalConfiguration(node.receiver, config.environment, cont); 191 return new EvalConfiguration(node.receiver, config.environment, cont);
176 } 192 }
177 193
178 Configuration visitConstructorInvocation( 194 Configuration visitConstructorInvocation(
179 ConstructorInvocation node, EvalConfiguration config) { 195 ConstructorInvocation node, EvalConfiguration config) =>
180 ApplicationContinuation cont = 196 defaultExpression(node, config);
181 new ConstructorInvocationApplication(node.target, config.continuation);
182 var args =
183 _createArgumentExpressionList(node.arguments, node.target.function);
184
185 return new EvalListConfiguration(args, config.environment, cont);
186 }
187 197
188 Configuration visitNot(Not node, EvalConfiguration config) { 198 Configuration visitNot(Not node, EvalConfiguration config) {
189 return new EvalConfiguration(node.operand, config.environment, 199 return new EvalConfiguration(
190 new NotContinuation(config.continuation)); 200 node.operand, config.environment, new NotEK(config.continuation));
191 } 201 }
192 202
193 Configuration visitLogicalExpression( 203 Configuration visitLogicalExpression(
194 LogicalExpression node, EvalConfiguration config) { 204 LogicalExpression node, EvalConfiguration config) {
195 if ('||' == node.operator) { 205 if ('||' == node.operator) {
196 var cont = new OrContinuation( 206 var cont = new OrEK(node.right, config.environment, config.continuation);
197 node.right, config.environment, config.continuation);
198 return new EvalConfiguration(node.left, config.environment, cont); 207 return new EvalConfiguration(node.left, config.environment, cont);
199 } else { 208 } else {
200 assert('&&' == node.operator); 209 assert('&&' == node.operator);
201 var cont = new AndContinuation( 210 var cont = new AndEK(node.right, config.environment, config.continuation);
202 node.right, config.environment, config.continuation);
203 return new EvalConfiguration(node.left, config.environment, cont); 211 return new EvalConfiguration(node.left, config.environment, cont);
204 } 212 }
205 } 213 }
206 214
207 Configuration visitConditionalExpression( 215 Configuration visitConditionalExpression(
208 ConditionalExpression node, EvalConfiguration config) { 216 ConditionalExpression node, EvalConfiguration config) {
209 var cont = new ConditionalContinuation( 217 var cont = new ConditionalEK(
210 node.then, node.otherwise, config.environment, config.continuation); 218 node.then, node.otherwise, config.environment, config.continuation);
211 return new EvalConfiguration(node.condition, config.environment, cont); 219 return new EvalConfiguration(node.condition, config.environment, cont);
212 } 220 }
213 221
214 Configuration visitStringConcatenation( 222 Configuration visitStringConcatenation(
215 StringConcatenation node, EvalConfiguration config) { 223 StringConcatenation node, EvalConfiguration config) {
216 var cont = new StringConcatenationContinuation(config.continuation); 224 var cont = new StringConcatenationA(config.continuation);
217 var expressions = node.expressions 225 var expressions = node.expressions
218 .map((Expression e) => new PositionalExpression(e)) 226 .map((Expression e) => new PositionalExpression(e))
219 .toList(); 227 .toList();
220 return new EvalListConfiguration(expressions, config.environment, cont); 228 return new EvalListConfiguration(expressions, config.environment, cont);
221 } 229 }
222 230
223 Configuration visitThisExpression( 231 Configuration visitThisExpression(
224 ThisExpression node, EvalConfiguration config) { 232 ThisExpression node, EvalConfiguration config) {
225 return new ValuePassingConfiguration( 233 return new ValuePassingConfiguration(
226 config.continuation, config.environment.thisInstance); 234 config.continuation, config.environment.thisInstance);
(...skipping 21 matching lines...) Expand all
248 Value value = node.value ? Value.trueInstance : Value.falseInstance; 256 Value value = node.value ? Value.trueInstance : Value.falseInstance;
249 return new ValuePassingConfiguration(config.continuation, value); 257 return new ValuePassingConfiguration(config.continuation, value);
250 } 258 }
251 259
252 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { 260 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) {
253 return new ValuePassingConfiguration( 261 return new ValuePassingConfiguration(
254 config.continuation, Value.nullInstance); 262 config.continuation, Value.nullInstance);
255 } 263 }
256 264
257 Configuration visitLet(Let node, EvalConfiguration config) { 265 Configuration visitLet(Let node, EvalConfiguration config) {
258 var letCont = new LetContinuation( 266 var letCont = new LetEK(
259 node.variable, node.body, config.environment, config.continuation); 267 node.variable, node.body, config.environment, config.continuation);
260 return new EvalConfiguration( 268 return new EvalConfiguration(
261 node.variable.initializer, config.environment, letCont); 269 node.variable.initializer, config.environment, letCont);
262 } 270 }
263 } 271 }
264 272
265 /// Represents a state for statement execution. 273 /// Represents a state for statement execution.
266 class State { 274 class State {
267 final Environment environment;
268 final Label labels; 275 final Label labels;
269 final ExecConfiguration statementConfiguration; 276 // TODO: Add switch labels.
277 // TODO: Add component for exception support
278 final ExpressionContinuation returnContinuation;
279 final StatementContinuation continuation;
270 280
271 final ExpressionContinuation returnContinuation; 281 State(this.labels, this.returnContinuation, this.continuation);
272 282
273 State(this.environment, this.labels, this.statementConfiguration, 283 const State.initial()
274 this.returnContinuation); 284 : labels = null,
285 returnContinuation = null,
286 continuation = null;
275 287
276 State.initial() : this(new Environment.empty(), null, null, null); 288 State withBreak(Statement stmt, Environment env) {
277 289 Label breakLabels = new Label(stmt, env, continuation, labels);
278 State withEnvironment(Environment env) { 290 return new State(breakLabels, returnContinuation, continuation);
279 return new State(env, labels, statementConfiguration, returnContinuation);
280 } 291 }
281 292
282 State withBreak(Statement stmt) { 293 State withReturnContinuation(ExpressionContinuation returnCont) {
283 Label breakLabels = new Label(stmt, statementConfiguration, labels); 294 return new State(labels, returnCont, continuation);
284 return new State(
285 environment, breakLabels, statementConfiguration, returnContinuation);
286 } 295 }
287 296
288 State withConfiguration(Configuration config) { 297 State withContinuation(StatementContinuation cont) {
289 return new State(environment, labels, config, returnContinuation); 298 return new State(labels, returnContinuation, cont);
290 }
291
292 State withExpressionContinuation(ExpressionContinuation cont) {
293 return new State(environment, labels, statementConfiguration, cont);
294 } 299 }
295 300
296 Label lookupLabel(LabeledStatement s) { 301 Label lookupLabel(LabeledStatement s) {
297 assert(labels != null); 302 assert(labels != null);
298 return labels.lookupLabel(s); 303 return labels.lookupLabel(s);
299 } 304 }
300 } 305 }
301 306
302 /// Represents a labeled statement, the corresponding continuation and the 307 /// Represents a labeled statement, the corresponding continuation and the
303 /// enclosing label. 308 /// enclosing label.
304 class Label { 309 class Label {
305 final LabeledStatement statement; 310 final LabeledStatement statement;
306 final ExecConfiguration configuration; 311 final Environment environment;
312 final StatementContinuation continuation;
307 final Label enclosingLabel; 313 final Label enclosingLabel;
308 314
309 Label(this.statement, this.configuration, this.enclosingLabel); 315 Label(
316 this.statement, this.environment, this.continuation, this.enclosingLabel);
310 317
311 Label lookupLabel(LabeledStatement s) { 318 Label lookupLabel(LabeledStatement s) {
312 if (identical(s, statement)) return this; 319 if (identical(s, statement)) return this;
313 assert(enclosingLabel != null); 320 assert(enclosingLabel != null);
314 return enclosingLabel.lookupLabel(s); 321 return enclosingLabel.lookupLabel(s);
315 } 322 }
316 } 323 }
317 324
325 // ------------------------------------------------------------------------
326 // Configurations
327 // ------------------------------------------------------------------------
328
318 abstract class Configuration { 329 abstract class Configuration {
319 /// Executes the current and returns the next configuration. 330 /// Executes the current and returns the next configuration.
320 Configuration step(StatementExecuter executer); 331 Configuration step(StatementExecuter executer);
321 } 332 }
322 333
323 /// Represents the configuration for execution of statement. 334 /// Configuration for evaluating an [Expression].
335 class EvalConfiguration extends Configuration {
336 final Expression expression;
337
338 /// Environment in which the expression is evaluated.
339 final Environment environment;
340
341 /// Next continuation to be applied.
342 final Continuation continuation;
343
344 EvalConfiguration(this.expression, this.environment, this.continuation);
345
346 Configuration step(StatementExecuter executer) =>
347 executer.eval(expression, this);
348 }
349
350 /// Configuration for evaluating a [List<InterpreterExpression>].
351 class EvalListConfiguration extends Configuration {
352 final List<InterpreterExpression> expressions;
353 final Environment environment;
354 final ApplicationContinuation continuation;
355
356 EvalListConfiguration(this.expressions, this.environment, this.continuation);
357
358 Configuration step(StatementExecuter executer) =>
359 executer.evalList(expressions, environment, continuation);
360 }
361
362 /// Configuration for execution of a [Statement].
324 class ExecConfiguration extends Configuration { 363 class ExecConfiguration extends Configuration {
325 final Statement statement; 364 final Statement currentStatement;
365 final Environment environment;
326 final State state; 366 final State state;
327 367
328 ExecConfiguration(this.statement, this.state); 368 ExecConfiguration(this.currentStatement, this.environment, this.state);
329 369
330 Configuration step(StatementExecuter executer) => 370 Configuration step(StatementExecuter executer) =>
331 executer.exec(statement, state); 371 executer.exec(currentStatement, this);
332 } 372 }
333 373
334 class ExitConfiguration extends ExecConfiguration { 374 /// Configuration for applying a [StatementContinuation] to an [Environment].
335 final ExpressionContinuation returnContinuation; 375 class ForwardConfiguration extends Configuration {
376 final StatementContinuation continuation;
377 final Environment environment;
336 378
337 ExitConfiguration(this.returnContinuation) : super(null, null); 379 ForwardConfiguration(this.continuation, this.environment);
338 380
339 Configuration step(StatementExecuter _) { 381 Configuration step(StatementExecuter _) => continuation?.call(environment);
340 return returnContinuation(Value.nullInstance);
341 }
342 } 382 }
343 383
344 class NewInstanceConfiguration extends ExecConfiguration { 384 /// Configuration for applying [ExpressionContinuation] to a [Value].
345 final ExpressionContinuation continuation;
346 final ObjectValue newObject;
347
348 NewInstanceConfiguration(this.continuation, this.newObject)
349 : super(null, new State.initial());
350
351 Configuration step(StatementExecuter _) {
352 return continuation(newObject);
353 }
354 }
355
356 /// Represents the configuration for applying an [ExpressionContinuation].
357 class ValuePassingConfiguration extends Configuration { 385 class ValuePassingConfiguration extends Configuration {
358 final ExpressionContinuation continuation; 386 final ExpressionContinuation continuation;
359 final Value value; 387 final Value value;
360 388
361 ValuePassingConfiguration(this.continuation, this.value); 389 ValuePassingConfiguration(this.continuation, this.value);
362 390
363 Configuration step(StatementExecuter _) => continuation(value); 391 Configuration step(StatementExecuter _) => continuation(value);
364 } 392 }
365 393
366 /// Represents the configuration for applying an [ApplicationContinuation]. 394 /// Configuration for applying an [ApplicationContinuation] to a
395 /// [List<InterpreterValue>].
367 class ApplicationConfiguration extends Configuration { 396 class ApplicationConfiguration extends Configuration {
368 final ApplicationContinuation continuation; 397 final ApplicationContinuation continuation;
369 final List<InterpreterValue> values; 398 final List<InterpreterValue> values;
370 399
371 ApplicationConfiguration(this.continuation, this.values); 400 ApplicationConfiguration(this.continuation, this.values);
372 401
373 Configuration step(StatementExecuter _) => continuation(values); 402 Configuration step(StatementExecuter _) => continuation(values);
374 } 403 }
375 404
376 /// Represents the configuration for evaluating an [Expression]. 405 // ------------------------------------------------------------------------
377 class EvalConfiguration extends Configuration { 406 // Interpreter Expressions and Values
378 final Expression expression; 407 // ------------------------------------------------------------------------
379
380 /// Environment in which the expression is evaluated.
381 final Environment environment;
382
383 /// Next continuation to be applied.
384 final Continuation continuation;
385
386 EvalConfiguration(this.expression, this.environment, this.continuation);
387
388 Configuration step(StatementExecuter executer) =>
389 executer.eval(expression, this);
390 }
391
392 /// Represents the configuration for evaluating a list of expressions.
393 class EvalListConfiguration extends Configuration {
394 final List<InterpreterExpression> expressions;
395 final Environment environment;
396 final Continuation continuation;
397
398 EvalListConfiguration(this.expressions, this.environment, this.continuation);
399
400 Configuration step(StatementExecuter executer) =>
401 executer.evalList(expressions, environment, continuation);
402 }
403 408
404 abstract class InterpreterExpression { 409 abstract class InterpreterExpression {
405 Expression get expression; 410 Expression get expression;
406 411
407 InterpreterValue assignValue(Value v); 412 InterpreterValue assignValue(Value v);
408 } 413 }
409 414
410 class PositionalExpression extends InterpreterExpression { 415 class PositionalExpression extends InterpreterExpression {
411 final Expression expression; 416 final Expression expression;
412 417
413 PositionalExpression(this.expression); 418 PositionalExpression(this.expression);
414 419
415 InterpreterValue assignValue(Value v) => new PositionalValue(v); 420 InterpreterValue assignValue(Value v) => new PositionalValue(v);
416 } 421 }
417 422
418 class NamedExpression extends InterpreterExpression { 423 class NamedExpression extends InterpreterExpression {
419 final String name; 424 final String name;
420 final Expression expression; 425 final Expression expression;
421 426
422 NamedExpression(this.name, this.expression); 427 NamedExpression(this.name, this.expression);
423 InterpreterValue assignValue(Value v) => new NamedValue(name, v); 428 InterpreterValue assignValue(Value v) => new NamedValue(name, v);
424 } 429 }
425 430
426 class LocalInitializerExpression extends InterpreterExpression {
427 final VariableDeclaration variable;
428
429 Expression get expression => variable.initializer;
430
431 LocalInitializerExpression(this.variable);
432
433 InterpreterValue assignValue(Value v) =>
434 new LocalInitializerValue(variable, v);
435 }
436
437 class FieldInitializerExpression extends InterpreterExpression { 431 class FieldInitializerExpression extends InterpreterExpression {
438 final Field field; 432 final Field field;
439 final Expression expression; 433 final Expression expression;
440 434
441 FieldInitializerExpression(this.field, this.expression); 435 FieldInitializerExpression(this.field, this.expression);
442 436
443 InterpreterValue assignValue(Value v) => new FieldInitializerValue(field, v); 437 InterpreterValue assignValue(Value v) => new FieldInitializerValue(field, v);
444 } 438 }
445 439
446 abstract class InterpreterValue { 440 abstract class InterpreterValue {
447 Value get value; 441 Value get value;
448 } 442 }
449 443
450 class PositionalValue extends InterpreterValue { 444 class PositionalValue extends InterpreterValue {
451 final Value value; 445 final Value value;
452 446
453 PositionalValue(this.value); 447 PositionalValue(this.value);
454 } 448 }
455 449
456 class NamedValue extends InterpreterValue { 450 class NamedValue extends InterpreterValue {
457 final String name; 451 final String name;
458 final Value value; 452 final Value value;
459 453
460 NamedValue(this.name, this.value); 454 NamedValue(this.name, this.value);
461 } 455 }
462 456
463 class LocalInitializerValue extends InterpreterValue {
464 final VariableDeclaration variable;
465 final Value value;
466
467 LocalInitializerValue(this.variable, this.value);
468 }
469
470 class FieldInitializerValue extends InterpreterValue { 457 class FieldInitializerValue extends InterpreterValue {
471 final Field field; 458 final Field field;
472 final Value value; 459 final Value value;
473 460
474 FieldInitializerValue(this.field, this.value); 461 FieldInitializerValue(this.field, this.value);
475 } 462 }
476 463
477 abstract class Continuation {} 464 abstract class Continuation {}
478 465
466 // ------------------------------------------------------------------------
467 // Statement Continuations
468 // ------------------------------------------------------------------------
469
470 /// Represents a the continuation for the execution of the next statement of
471 /// the program.
472 ///
473 /// There are various kinds of [StatementContinuation]s and their names are
474 /// suffixed with "SK"
475 abstract class StatementContinuation extends Continuation {
476 Configuration call(Environment env);
477 }
478
479 /// Applies the expression continuation to the provided value.
480 class ExitSK extends StatementContinuation {
481 final ExpressionContinuation continuation;
482 final Value value;
483
484 ExitSK(this.continuation, this.value);
485
486 Configuration call(Environment _) =>
487 new ValuePassingConfiguration(continuation, value);
488 }
489
490 /// Executes the next statement from a block with the corresponding environment
491 /// or proceeds with next statement continuation.
492 class BlockSK extends StatementContinuation {
493 final List<Statement> statements;
494 final Environment enclosingEnv;
495 final State state;
496
497 BlockSK(this.statements, this.enclosingEnv, this.state);
498
499 BlockSK.fromConfig(this.statements, ExecConfiguration conf)
500 : enclosingEnv = conf.environment,
501 state = conf.state;
502
503 Configuration call(Environment env) {
504 if (statements.isEmpty) {
505 return new ForwardConfiguration(state.continuation, enclosingEnv);
506 }
507 // Proceed with the execution statement when there are some remaining to
508 // be executed.
509 var cont = new BlockSK(statements.skip(1).toList(), enclosingEnv, state);
510 return new ExecConfiguration(
511 statements.first, env, state.withContinuation(cont));
512 }
513 }
514
515 class NewSK extends StatementContinuation {
516 final ExpressionContinuation continuation;
517 final Location location;
518
519 NewSK(this.continuation, this.location);
520
521 Configuration call(Environment _) =>
522 new ValuePassingConfiguration(continuation, location.value);
523 }
524
525 class WhileConditionSK extends StatementContinuation {
526 final Expression condition;
527 final Statement body;
528 final Environment enclosingEnv;
529 final State state;
530
531 WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state);
532
533 Configuration call(Environment _) {
534 // Evaluate the condition for the while loop execution.
535 var cont = new WhileConditionEK(condition, body, enclosingEnv, state);
536 return new EvalConfiguration(condition, enclosingEnv, cont);
537 }
538 }
539
540 // ------------------------------------------------------------------------
541 // Application Continuations
542 // ------------------------------------------------------------------------
543
479 /// Represents the continuation called after the evaluation of argument 544 /// Represents the continuation called after the evaluation of argument
480 /// expressions. 545 /// expressions.
546 ///
547 /// There are various kinds of [ApplicationContinuation] and their names are
548 /// suffixed with "A".
481 abstract class ApplicationContinuation extends Continuation { 549 abstract class ApplicationContinuation extends Continuation {
482 Configuration call(List<InterpreterValue> values); 550 Configuration call(List<InterpreterValue> values);
483 551
484 /// Binds actual argument values to formal parameters of the function in a 552 /// Binds actual argument values to formal parameters of the function in a
485 /// new environment or in the provided initial environment. 553 /// new environment or in the provided initial environment.
486 /// TODO: Add checks for validation of arguments according to spec. 554 /// TODO: Add checks for validation of arguments according to spec.
487 static Environment createEnvironment( 555 static Environment createEnvironment(
488 FunctionNode function, List<InterpreterValue> args, 556 FunctionNode function, List<InterpreterValue> args,
489 [Environment parentEnv]) { 557 [Environment parentEnv]) {
490 Environment newEnv = new Environment(parentEnv); 558 Environment newEnv = new Environment(parentEnv ?? new Environment.empty());
559
491 List<PositionalValue> positional = args.reversed 560 List<PositionalValue> positional = args.reversed
492 .where((InterpreterValue av) => av is PositionalValue) 561 .where((InterpreterValue av) => av is PositionalValue)
493 .toList(); 562 .toList();
494 563
495 // Add positional parameters. 564 // Add positional parameters.
496 for (int i = 0; i < positional.length; ++i) { 565 for (int i = 0; i < positional.length; ++i) {
497 newEnv.expand(function.positionalParameters[i], positional[i].value); 566 newEnv =
567 newEnv.extend(function.positionalParameters[i], positional[i].value);
498 } 568 }
499 569
500 Map<String, Value> named = new Map.fromIterable( 570 Map<String, Value> named = new Map.fromIterable(
501 args.where((InterpreterValue av) => av is NamedValue), 571 args.where((InterpreterValue av) => av is NamedValue),
502 key: (NamedValue av) => av.name, 572 key: (NamedValue av) => av.name,
503 value: (NamedValue av) => av.value); 573 value: (NamedValue av) => av.value);
504 574
505 // Add named parameters. 575 // Add named parameters.
506 for (VariableDeclaration v in function.namedParameters) { 576 for (VariableDeclaration v in function.namedParameters) {
507 newEnv.expand(v, named[v.name.toString()]); 577 newEnv = newEnv.extend(v, named[v.name.toString()]);
508 } 578 }
509 579
510 return newEnv; 580 return newEnv;
511 } 581 }
512 } 582 }
513 583
514 /// Represents the application continuation for static invocation.
515 class StaticInvocationApplication extends ApplicationContinuation {
516 final FunctionNode function;
517 final ExpressionContinuation continuation;
518
519 StaticInvocationApplication(this.function, this.continuation);
520
521 Configuration call(List<InterpreterValue> argValues) {
522 Environment functionEnv =
523 ApplicationContinuation.createEnvironment(function, argValues);
524
525 State bodyState = new State.initial()
526 .withExpressionContinuation(continuation)
527 .withConfiguration(new ExitConfiguration(continuation))
528 .withEnvironment(functionEnv);
529 return new ExecConfiguration(function.body, bodyState);
530 }
531 }
532
533 /// Represents the application continuation for constructor invocation applied
534 /// on the list of evaluated arguments.
535 class ConstructorInvocationApplication extends ApplicationContinuation {
536 final Constructor constructor;
537 final ExpressionContinuation continuation;
538
539 ConstructorInvocationApplication(this.constructor, this.continuation);
540
541 Configuration call(List<InterpreterValue> argValues) {
542 Environment ctrEnv = ApplicationContinuation.createEnvironment(
543 constructor.function, argValues);
544
545 var class_ = new Class(constructor.enclosingClass.reference);
546 var newObject =
547 new ObjectValue(class_, new List<Value>(class_.instanceSize));
548
549 return new ObjectInitializationConfiguration(
550 constructor,
551 new InstanceEnvironment(newObject, ctrEnv),
552 new NewInstanceConfiguration(continuation, newObject));
553 }
554 }
555
556 /// Represents the application continuation for redirecting constructor
557 /// invocation applied on the list of evaluated arguments.
558 class RedirectingConstructorApplication extends ApplicationContinuation {
559 final Constructor constructor;
560 final Environment environment;
561 final ExecConfiguration configuration;
562
563 RedirectingConstructorApplication(
564 this.constructor, this.environment, this.configuration);
565
566 Configuration call(List<InterpreterValue> argValues) {
567 Value object = environment.thisInstance;
568 Environment ctrEnv = ApplicationContinuation.createEnvironment(
569 constructor.function,
570 argValues,
571 new InstanceEnvironment(object, new Environment.empty()));
572
573 return new ObjectInitializationConfiguration(
574 constructor, ctrEnv, configuration);
575 }
576 }
577
578 /// Represents the application continuation for super constructor
579 /// invocation applied on the list of evaluated arguments.
580 class SuperConstructorApplication extends ApplicationContinuation {
581 final Constructor constructor;
582 final Environment environment;
583 final ExecConfiguration configuration;
584
585 SuperConstructorApplication(
586 this.constructor, this.environment, this.configuration);
587
588 Configuration call(List<InterpreterValue> argValues) {
589 Value object = environment.thisInstance;
590
591 Environment superEnv = ApplicationContinuation.createEnvironment(
592 constructor.function,
593 argValues,
594 new InstanceEnvironment(object, new Environment.empty()));
595
596 return new ObjectInitializationConfiguration(
597 constructor, superEnv, configuration);
598 }
599 }
600
601 /// Represents the configuration for execution of initializer and
602 /// constructor body statements for initialization of a newly allocated object.
603 class ObjectInitializationConfiguration extends Configuration {
604 final Constructor constructor;
605 final Environment environment;
606 final ExecConfiguration configuration;
607
608 ObjectInitializationConfiguration(
609 this.constructor, this.environment, this.configuration);
610
611 Configuration step(StatementExecuter _) {
612 if (constructor.initializers.isNotEmpty &&
613 constructor.initializers.last is RedirectingInitializer) {
614 // Constructor is redirecting.
615 Initializer initializer = constructor.initializers.first;
616 if (initializer is RedirectingInitializer) {
617 var app = new RedirectingConstructorApplication(
618 initializer.target, environment, configuration);
619 var args = _createArgumentExpressionList(
620 initializer.arguments, initializer.target.function);
621
622 return new EvalListConfiguration(args, environment, app);
623 }
624 // Redirecting initializer is not the only initializer.
625 for (Initializer i in constructor.initializers.reversed.skip(1)) {
626 assert(i is LocalInitializer);
627 }
628 var class_ = new Class(constructor.enclosingClass.reference);
629 var initEnv = new Environment(environment);
630 var cont = new InitializerContinuation(
631 class_, initEnv, constructor.initializers, configuration);
632 return new EvalConfiguration(
633 (initializer as LocalInitializer).variable.initializer,
634 initEnv,
635 cont);
636 }
637
638 // Set head of configurations to be executed to configuration for current
639 // constructor body.
640 var state = new State.initial()
641 .withEnvironment(environment)
642 .withConfiguration(configuration);
643 var bodyConfig = new ExecConfiguration(constructor.function.body, state);
644
645 // Initialize fields in immediately enclosing class.
646 var cont =
647 new InstanceFieldsApplication(constructor, environment, bodyConfig);
648 var fieldExpressions = _createInstanceInitializers(constructor);
649
650 return new EvalListConfiguration(
651 fieldExpressions, new Environment.empty(), cont);
652 }
653
654 /// Creates a list of expressions for instance field initializers in
655 /// immediately enclosing class.
656 static List<InterpreterExpression> _createInstanceInitializers(
657 Constructor ctr) {
658 Class currentClass = new Class(ctr.enclosingClass.reference);
659 List<InterpreterExpression> es = <InterpreterExpression>[];
660
661 for (int i = currentClass.superclass?.instanceSize ?? 0;
662 i < currentClass.instanceSize;
663 i++) {
664 Field current = currentClass.instanceFields[i];
665 if (current.initializer != null) {
666 es.add(new FieldInitializerExpression(current, current.initializer));
667 }
668 }
669
670 return es;
671 }
672 }
673
674 /// Represents the application continuation applied on the list of evaluated
675 /// field initializer expressions.
676 class InstanceFieldsApplication extends ApplicationContinuation {
677 final Constructor constructor;
678 final Environment environment;
679 final ExecConfiguration configuration;
680
681 final Class _currentClass;
682 final ObjectValue _newObject;
683
684 InstanceFieldsApplication(
685 this.constructor, this.environment, this.configuration)
686 : _currentClass = new Class(constructor.enclosingClass.reference),
687 _newObject = environment.thisInstance;
688
689 Configuration call(List<InterpreterValue> fieldValues) {
690 for (FieldInitializerValue current in fieldValues.reversed) {
691 _currentClass.setProperty(_newObject, current.field, current.value);
692 }
693
694 if (constructor.initializers.isEmpty) {
695 _initializeNullFields(_currentClass, _newObject);
696 return configuration;
697 }
698
699 // Produce next configuration.
700 if (constructor.initializers.first is SuperInitializer) {
701 // SuperInitializer appears last in the initializer list.
702 assert(constructor.initializers.length == 1);
703 SuperInitializer current = constructor.initializers.first;
704 var args = _createArgumentExpressionList(
705 current.arguments, current.target.function);
706
707 var superApp = new SuperConstructorApplication(
708 current.target, environment, configuration);
709 _initializeNullFields(_currentClass, _newObject);
710 return new EvalListConfiguration(args, environment, superApp);
711 }
712
713 Class class_ = new Class(constructor.enclosingClass.reference);
714 Environment initEnv = new Environment(environment);
715
716 var cont = new InitializerContinuation(
717 class_, initEnv, constructor.initializers, configuration);
718 return new EvalConfiguration(
719 _getExpression(constructor.initializers.first), initEnv, cont);
720 }
721 }
722
723 /// Represents the expression continuation applied on the list of evaluated
724 /// initializer expressions preceding a super call in the list.
725 class InitializerContinuation extends ExpressionContinuation {
726 final Class currentClass;
727 final Environment initializerEnvironment;
728 final List<Initializer> initializers;
729 final ExecConfiguration configuration;
730
731 InitializerContinuation(this.currentClass, this.initializerEnvironment,
732 this.initializers, this.configuration);
733
734 Configuration call(Value v) {
735 ObjectValue newObject = initializerEnvironment.thisInstance;
736 Initializer current = initializers.first;
737 if (current is FieldInitializer) {
738 currentClass.setProperty(newObject, current.field, v);
739 } else if (current is LocalInitializer) {
740 initializerEnvironment.expand(current.variable, v);
741 } else {
742 throw 'Assigning value $v to ${current.runtimeType}';
743 }
744
745 if (initializers.length <= 1) {
746 _initializeNullFields(currentClass, newObject);
747 return configuration;
748 }
749
750 Initializer next = initializers[1];
751
752 if (next is RedirectingInitializer) {
753 // RedirectingInitializer appears last in the initializer list.
754 assert(initializers.length == 2);
755 var app = new RedirectingConstructorApplication(
756 next.target, initializerEnvironment, configuration);
757 var args =
758 _createArgumentExpressionList(next.arguments, next.target.function);
759 return new EvalListConfiguration(args, initializerEnvironment, app);
760 }
761
762 if (next is SuperInitializer) {
763 // SuperInitializer appears last in the initializer list.
764 assert(initializers.length == 2);
765 var args =
766 _createArgumentExpressionList(next.arguments, next.target.function);
767 var superApp = new SuperConstructorApplication(
768 next.target, initializerEnvironment, configuration);
769 _initializeNullFields(currentClass, newObject);
770 return new EvalListConfiguration(args, initializerEnvironment, superApp);
771 }
772
773 var cont = new InitializerContinuation(currentClass, initializerEnvironment,
774 initializers.skip(1).toList(), configuration);
775 return new EvalConfiguration(
776 _getExpression(next), initializerEnvironment, cont);
777 }
778 }
779
780 /// Represents the application continuation called after the evaluation of all 584 /// Represents the application continuation called after the evaluation of all
781 /// argument expressions for an invocation. 585 /// argument expressions for an invocation.
782 class ValueApplication extends ApplicationContinuation { 586 class ValueA extends ApplicationContinuation {
783 final InterpreterValue value; 587 final InterpreterValue value;
784 final ApplicationContinuation applicationContinuation; 588 final ApplicationContinuation applicationContinuation;
785 589
786 ValueApplication(this.value, this.applicationContinuation); 590 ValueA(this.value, this.applicationContinuation);
787 591
788 Configuration call(List<InterpreterValue> args) { 592 Configuration call(List<InterpreterValue> args) {
789 args.add(value); 593 args.add(value);
790 return new ApplicationConfiguration(applicationContinuation, args); 594 return new ApplicationConfiguration(applicationContinuation, args);
791 } 595 }
792 } 596 }
793 597
598 class StringConcatenationA extends ApplicationContinuation {
599 final ExpressionContinuation continuation;
600
601 StringConcatenationA(this.continuation);
602
603 Configuration call(List<InterpreterValue> values) {
604 StringBuffer result = new StringBuffer();
605 for (InterpreterValue v in values.reversed) {
606 result.write(v.value.value);
607 }
608 return new ValuePassingConfiguration(
609 continuation, new StringValue(result.toString()));
610 }
611 }
612
613 /// Represents the application continuation for static invocation.
614 class StaticInvocationA extends ApplicationContinuation {
615 final FunctionNode function;
616 final ExpressionContinuation continuation;
617
618 StaticInvocationA(this.function, this.continuation);
619
620 Configuration call(List<InterpreterValue> argValues) {
621 Environment functionEnv =
622 ApplicationContinuation.createEnvironment(function, argValues);
623 State bodyState = new State(
624 null, continuation, new ExitSK(continuation, Value.nullInstance));
625
626 return new ExecConfiguration(function.body, functionEnv, bodyState);
627 }
628 }
629
630 // ------------------------------------------------------------------------
631 // Expression Continuations
632 // ------------------------------------------------------------------------
633
794 /// Represents an expression continuation. 634 /// Represents an expression continuation.
635 ///
636 /// There are various kinds of [ExpressionContinuation]s and their names are
637 /// suffixed with "EK".
795 abstract class ExpressionContinuation extends Continuation { 638 abstract class ExpressionContinuation extends Continuation {
796 Configuration call(Value v); 639 Configuration call(Value v);
797 } 640 }
798 641
799 /// Represents a continuation that returns the next [ExecConfiguration] 642 /// Represents a continuation that returns the next [ExecConfiguration]
800 /// to be executed. 643 /// to be executed.
801 class ExpressionStatementContinuation extends ExpressionContinuation { 644 class ExpressionSK extends ExpressionContinuation {
802 final ExecConfiguration configuration; 645 final StatementContinuation continuation;
646 final Environment environment;
803 647
804 ExpressionStatementContinuation(this.configuration); 648 ExpressionSK(this.continuation, this.environment);
805 649
806 Configuration call(Value _) { 650 Configuration call(Value _) {
807 return configuration; 651 return new ForwardConfiguration(continuation, environment);
808 } 652 }
809 } 653 }
810 654
811 class PrintContinuation extends ExpressionContinuation { 655 class PrintEK extends ExpressionContinuation {
812 final ExpressionContinuation continuation; 656 final ExpressionContinuation continuation;
813 657
814 PrintContinuation(this.continuation); 658 PrintEK(this.continuation);
815 659
816 Configuration call(Value v) { 660 Configuration call(Value v) {
817 log.info('print(${v.value.runtimeType}: ${v.value})\n'); 661 log.info('print(${v.value.runtimeType}: ${v.value})\n');
818 print(v.value); 662 print(v.value);
819 return new ValuePassingConfiguration(continuation, Value.nullInstance); 663 return new ValuePassingConfiguration(continuation, Value.nullInstance);
820 } 664 }
821 } 665 }
822 666
823 class PropertyGetContinuation extends ExpressionContinuation { 667 class PropertyGetEK extends ExpressionContinuation {
824 final Name name; 668 final Name name;
825 final ExpressionContinuation continuation; 669 final ExpressionContinuation continuation;
826 670
827 PropertyGetContinuation(this.name, this.continuation); 671 PropertyGetEK(this.name, this.continuation);
828 672
829 Configuration call(Value receiver) { 673 Configuration call(Value receiver) {
830 // TODO: CPS the invocation of the getter. 674 // TODO: CPS the invocation of the getter.
831 Value propertyValue = receiver.class_.lookupGetter(name)(receiver); 675 Value propertyValue = receiver.class_.lookupGetter(name)(receiver);
832 return new ValuePassingConfiguration(continuation, propertyValue); 676 return new ValuePassingConfiguration(continuation, propertyValue);
833 } 677 }
834 } 678 }
835 679
836 class PropertySetContinuation extends ExpressionContinuation { 680 class PropertySetEK extends ExpressionContinuation {
837 final Expression value; 681 final Expression value;
838 final Name setterName; 682 final Name setterName;
839 final Environment environment; 683 final Environment environment;
840 final ExpressionContinuation continuation; 684 final ExpressionContinuation continuation;
841 685
842 PropertySetContinuation( 686 PropertySetEK(
843 this.value, this.setterName, this.environment, this.continuation); 687 this.value, this.setterName, this.environment, this.continuation);
844 688
845 Configuration call(Value receiver) { 689 Configuration call(Value receiver) {
846 var cont = new SetterContinuation(receiver, setterName, continuation); 690 var cont = new SetterEK(receiver, setterName, continuation);
847 return new EvalConfiguration(value, environment, cont); 691 return new EvalConfiguration(value, environment, cont);
848 } 692 }
849 } 693 }
850 694
851 class SetterContinuation extends ExpressionContinuation { 695 class SetterEK extends ExpressionContinuation {
852 final Value receiver; 696 final Value receiver;
853 final Name name; 697 final Name name;
854 final ExpressionContinuation continuation; 698 final ExpressionContinuation continuation;
855 699
856 SetterContinuation(this.receiver, this.name, this.continuation); 700 SetterEK(this.receiver, this.name, this.continuation);
857 701
858 Configuration call(Value v) { 702 Configuration call(Value v) {
859 Setter setter = receiver.class_.lookupSetter(name); 703 Setter setter = receiver.class_.lookupSetter(name);
860 setter(receiver, v); 704 setter(receiver, v);
861 return new ValuePassingConfiguration(continuation, v); 705 return new ValuePassingConfiguration(continuation, v);
862 } 706 }
863 } 707 }
864 708
865 /// Represents a continuation to be called after the evaluation of an actual 709 /// Represents a continuation to be called after the evaluation of an actual
866 /// argument for function invocation. 710 /// argument for function invocation.
867 class ExpressionListContinuation extends ExpressionContinuation { 711 class ExpressionListEK extends ExpressionContinuation {
868 final InterpreterExpression currentExpression; 712 final InterpreterExpression currentExpression;
869 final List<InterpreterExpression> expressions; 713 final List<InterpreterExpression> expressions;
870 final Environment environment; 714 final Environment environment;
871 final ApplicationContinuation applicationContinuation; 715 final ApplicationContinuation applicationContinuation;
872 716
873 ExpressionListContinuation(this.currentExpression, this.expressions, 717 ExpressionListEK(this.currentExpression, this.expressions, this.environment,
874 this.environment, this.applicationContinuation); 718 this.applicationContinuation);
875 719
876 Configuration call(Value v) { 720 Configuration call(Value v) {
877 ValueApplication app = new ValueApplication( 721 ValueA app =
878 currentExpression.assignValue(v), applicationContinuation); 722 new ValueA(currentExpression.assignValue(v), applicationContinuation);
879 return new EvalListConfiguration(expressions, environment, app); 723 return new EvalListConfiguration(expressions, environment, app);
880 } 724 }
881 } 725 }
882 726
883 class MethodInvocationContinuation extends ExpressionContinuation { 727 class MethodInvocationEK extends ExpressionContinuation {
884 final Arguments arguments; 728 final Arguments arguments;
885 final Name methodName; 729 final Name methodName;
886 final Environment environment; 730 final Environment environment;
887 final ExpressionContinuation continuation; 731 final ExpressionContinuation continuation;
888 732
889 MethodInvocationContinuation( 733 MethodInvocationEK(
890 this.arguments, this.methodName, this.environment, this.continuation); 734 this.arguments, this.methodName, this.environment, this.continuation);
891 735
892 Configuration call(Value receiver) { 736 Configuration call(Value receiver) {
893 if (arguments.positional.isEmpty) { 737 if (arguments.positional.isEmpty) {
894 Value returnValue = receiver.invokeMethod(methodName); 738 Value returnValue = receiver.invokeMethod(methodName);
895 return new ValuePassingConfiguration(continuation, returnValue); 739 return new ValuePassingConfiguration(continuation, returnValue);
896 } 740 }
897 var cont = new ArgumentsContinuation( 741 var cont = new ArgumentsEK(
898 receiver, methodName, arguments, environment, continuation); 742 receiver, methodName, arguments, environment, continuation);
899 743
900 return new EvalConfiguration(arguments.positional.first, environment, cont); 744 return new EvalConfiguration(arguments.positional.first, environment, cont);
901 } 745 }
902 } 746 }
903 747
904 class ArgumentsContinuation extends ExpressionContinuation { 748 class ArgumentsEK extends ExpressionContinuation {
905 final Value receiver; 749 final Value receiver;
906 final Name methodName; 750 final Name methodName;
907 final Arguments arguments; 751 final Arguments arguments;
908 final Environment environment; 752 final Environment environment;
909 final ExpressionContinuation continuation; 753 final ExpressionContinuation continuation;
910 754
911 ArgumentsContinuation(this.receiver, this.methodName, this.arguments, 755 ArgumentsEK(this.receiver, this.methodName, this.arguments, this.environment,
912 this.environment, this.continuation); 756 this.continuation);
913 757
914 Configuration call(Value value) { 758 Configuration call(Value value) {
915 // Currently evaluates only one argument, for simple method invocations 759 // Currently evaluates only one argument, for simple method invocations
916 // with 1 argument. 760 // with 1 argument.
917 Value returnValue = receiver.invokeMethod(methodName, value); 761 Value returnValue = receiver.invokeMethod(methodName, value);
918 return new ValuePassingConfiguration(continuation, returnValue); 762 return new ValuePassingConfiguration(continuation, returnValue);
919 } 763 }
920 } 764 }
921 765
922 class VariableSetContinuation extends ExpressionContinuation { 766 class VariableSetEK extends ExpressionContinuation {
923 final VariableDeclaration variable; 767 final VariableDeclaration variable;
924 final Environment environment; 768 final Environment environment;
925 final ExpressionContinuation continuation; 769 final ExpressionContinuation continuation;
926 770
927 VariableSetContinuation(this.variable, this.environment, this.continuation); 771 VariableSetEK(this.variable, this.environment, this.continuation);
928 772
929 Configuration call(Value value) { 773 Configuration call(Value value) {
930 environment.assign(variable, value); 774 environment.assign(variable, value);
931 return new ValuePassingConfiguration(continuation, value); 775 return new ValuePassingConfiguration(continuation, value);
932 } 776 }
933 } 777 }
934 778
935 class NotContinuation extends ExpressionContinuation { 779 class NotEK extends ExpressionContinuation {
936 final ExpressionContinuation continuation; 780 final ExpressionContinuation continuation;
937 781
938 NotContinuation(this.continuation); 782 NotEK(this.continuation);
939 783
940 Configuration call(Value value) { 784 Configuration call(Value value) {
941 Value notValue = identical(Value.trueInstance, value) 785 Value notValue = identical(Value.trueInstance, value)
942 ? Value.falseInstance 786 ? Value.falseInstance
943 : Value.trueInstance; 787 : Value.trueInstance;
944 return new ValuePassingConfiguration(continuation, notValue); 788 return new ValuePassingConfiguration(continuation, notValue);
945 } 789 }
946 } 790 }
947 791
948 class OrContinuation extends ExpressionContinuation { 792 class OrEK extends ExpressionContinuation {
949 final Expression right; 793 final Expression right;
950 final Environment environment; 794 final Environment environment;
951 final ExpressionContinuation continuation; 795 final ExpressionContinuation continuation;
952 796
953 OrContinuation(this.right, this.environment, this.continuation); 797 OrEK(this.right, this.environment, this.continuation);
954 798
955 Configuration call(Value left) { 799 Configuration call(Value left) {
956 return identical(Value.trueInstance, left) 800 return identical(Value.trueInstance, left)
957 ? new ValuePassingConfiguration(continuation, Value.trueInstance) 801 ? new ValuePassingConfiguration(continuation, Value.trueInstance)
958 : new EvalConfiguration(right, environment, continuation); 802 : new EvalConfiguration(right, environment, continuation);
959 } 803 }
960 } 804 }
961 805
962 class AndContinuation extends ExpressionContinuation { 806 class AndEK extends ExpressionContinuation {
963 final Expression right; 807 final Expression right;
964 final Environment environment; 808 final Environment environment;
965 final ExpressionContinuation continuation; 809 final ExpressionContinuation continuation;
966 810
967 AndContinuation(this.right, this.environment, this.continuation); 811 AndEK(this.right, this.environment, this.continuation);
968 812
969 Configuration call(Value left) { 813 Configuration call(Value left) {
970 return identical(Value.falseInstance, left) 814 return identical(Value.falseInstance, left)
971 ? new ValuePassingConfiguration(continuation, Value.falseInstance) 815 ? new ValuePassingConfiguration(continuation, Value.falseInstance)
972 : new EvalConfiguration(right, environment, continuation); 816 : new EvalConfiguration(right, environment, continuation);
973 } 817 }
974 } 818 }
975 819
976 class ConditionalContinuation extends ExpressionContinuation { 820 class ConditionalEK extends ExpressionContinuation {
977 final Expression then; 821 final Expression then;
978 final Expression otherwise; 822 final Expression otherwise;
979 final Environment environment; 823 final Environment environment;
980 final ExpressionContinuation continuation; 824 final ExpressionContinuation continuation;
981 825
982 ConditionalContinuation( 826 ConditionalEK(this.then, this.otherwise, this.environment, this.continuation);
983 this.then, this.otherwise, this.environment, this.continuation);
984 827
985 Configuration call(Value value) { 828 Configuration call(Value value) {
986 return identical(Value.trueInstance, value) 829 return identical(Value.trueInstance, value)
987 ? new EvalConfiguration(then, environment, continuation) 830 ? new EvalConfiguration(then, environment, continuation)
988 : new EvalConfiguration(otherwise, environment, continuation); 831 : new EvalConfiguration(otherwise, environment, continuation);
989 } 832 }
990 } 833 }
991 834
992 class StringConcatenationContinuation extends ApplicationContinuation { 835 class LetEK extends ExpressionContinuation {
993 final ExpressionContinuation continuation;
994
995 StringConcatenationContinuation(this.continuation);
996
997 Configuration call(List<InterpreterValue> values) {
998 StringBuffer result = new StringBuffer();
999 for (InterpreterValue v in values.reversed) {
1000 result.write(v.value.value);
1001 }
1002 return new ValuePassingConfiguration(
1003 continuation, new StringValue(result.toString()));
1004 }
1005 }
1006
1007 class LetContinuation extends ExpressionContinuation {
1008 final VariableDeclaration variable; 836 final VariableDeclaration variable;
1009 final Expression letBody; 837 final Expression letBody;
1010 final Environment environment; 838 final Environment environment;
1011 final ExpressionContinuation continuation; 839 final ExpressionContinuation continuation;
1012 840
1013 LetContinuation( 841 LetEK(this.variable, this.letBody, this.environment, this.continuation);
1014 this.variable, this.letBody, this.environment, this.continuation);
1015 842
1016 Configuration call(Value value) { 843 Configuration call(Value value) {
1017 var letEnv = new Environment(environment); 844 var letEnv = new Environment(environment);
1018 letEnv.expand(variable, value); 845 letEnv.extend(variable, value);
1019 return new EvalConfiguration(letBody, letEnv, continuation); 846 return new EvalConfiguration(letBody, letEnv, continuation);
1020 } 847 }
1021 } 848 }
1022 849
1023 /// Represents the continuation for the condition expression in [WhileStatement] . 850 /// Represents the continuation for the condition expression in [WhileStatement] .
1024 class WhileConditionContinuation extends ExpressionContinuation { 851 class WhileConditionEK extends ExpressionContinuation {
1025 final WhileStatement node; 852 final Expression condition;
853 final Statement body;
854 final Environment enclosingEnv;
1026 final State state; 855 final State state;
1027 856
1028 WhileConditionContinuation(this.node, this.state); 857 WhileConditionEK(this.condition, this.body, this.enclosingEnv, this.state);
1029 858
1030 ExecConfiguration call(Value v) { 859 Configuration call(Value v) {
1031 if (identical(v, Value.trueInstance)) { 860 if (identical(v, Value.falseInstance)) {
1032 // Add configuration for the While statement to the linked list. 861 return new ForwardConfiguration(state.continuation, enclosingEnv);
1033 ExecConfiguration config = new ExecConfiguration(node, state);
1034 // Configuration for the body of the loop.
1035 return new ExecConfiguration(node.body, state.withConfiguration(config));
1036 } 862 }
1037 863 var cont = new WhileConditionSK(condition, body, enclosingEnv, state);
1038 return state.statementConfiguration; 864 return new ExecConfiguration(
865 body, enclosingEnv, state.withContinuation(cont));
1039 } 866 }
1040 } 867 }
1041 868
1042 /// Represents the continuation for the condition expression in [IfStatement]. 869 /// Represents the continuation for the condition expression in [IfStatement].
1043 class IfConditionContinuation extends ExpressionContinuation { 870 class IfConditionEK extends ExpressionContinuation {
1044 final Statement then; 871 final Statement then;
1045 final Statement otherwise; 872 final Statement otherwise;
873 final Environment environment;
1046 final State state; 874 final State state;
1047 875
1048 IfConditionContinuation(this.then, this.otherwise, this.state); 876 IfConditionEK(this.then, this.otherwise, this.environment, this.state);
1049 877
1050 ExecConfiguration call(Value v) { 878 Configuration call(Value v) {
1051 if (identical(v, Value.trueInstance)) { 879 if (identical(v, Value.trueInstance)) {
1052 log.info("if-then\n"); 880 log.info("if-then\n");
1053 return new ExecConfiguration(then, state); 881 return new ExecConfiguration(then, environment, state);
1054 } else if (otherwise != null) { 882 } else if (otherwise != null) {
1055 log.info("if-otherwise\n"); 883 log.info("if-otherwise\n");
1056 return new ExecConfiguration(otherwise, state); 884 return new ExecConfiguration(otherwise, environment, state);
1057 } 885 }
1058 return state.statementConfiguration; 886 return new ForwardConfiguration(state.continuation, environment);
1059 } 887 }
1060 } 888 }
1061 889
1062 /// Represents the continuation for the initializer expression in 890 /// Represents the continuation for the initializer expression in
1063 /// [VariableDeclaration]. 891 /// [VariableDeclaration].
1064 class VariableInitializerContinuation extends ExpressionContinuation { 892 class VariableInitializerEK extends ExpressionContinuation {
1065 final VariableDeclaration variable; 893 final VariableDeclaration variable;
1066 final Environment environment; 894 final Environment environment;
1067 final ExecConfiguration nextConfiguration; 895 final StatementContinuation continuation;
1068 896
1069 VariableInitializerContinuation( 897 VariableInitializerEK(this.variable, this.environment, this.continuation);
1070 this.variable, this.environment, this.nextConfiguration);
1071 898
1072 ExecConfiguration call(Value v) { 899 Configuration call(Value v) {
1073 environment.expand(variable, v); 900 return new ForwardConfiguration(
1074 return nextConfiguration; 901 continuation, environment.extend(variable, v));
1075 } 902 }
1076 } 903 }
1077 904
1078 /// Executes statements. 905 /// Executes statements.
1079 /// 906 ///
1080 /// Execution of a statement completes in one of the following ways: 907 /// Execution of a statement completes in one of the following ways:
1081 /// - it completes normally, in which case the execution proceeds to applying 908 /// - it completes normally, in which case the execution proceeds to applying
1082 /// the next continuation 909 /// the next continuation
1083 /// - it breaks with a label, in which case the corresponding continuation is 910 /// - it breaks with a label, in which case the corresponding continuation is
1084 /// returned and applied 911 /// returned and applied
1085 /// - it returns with or without value, TBD 912 /// - it returns with or without value, TBD
1086 /// - it throws, TBD 913 /// - it throws, TBD
1087 class StatementExecuter extends StatementVisitor1<Configuration, State> { 914 class StatementExecuter
915 extends StatementVisitor1<Configuration, ExecConfiguration> {
1088 Evaluator evaluator = new Evaluator(); 916 Evaluator evaluator = new Evaluator();
1089 917
1090 void trampolinedExecution(Configuration configuration) { 918 void trampolinedExecution(Configuration configuration) {
1091 while (configuration != null) { 919 while (configuration != null) {
1092 configuration = configuration.step(this); 920 configuration = configuration.step(this);
1093 } 921 }
922 ;
1094 } 923 }
1095 924
1096 Configuration exec(Statement statement, State state) => 925 Configuration exec(Statement statement, ExecConfiguration conf) =>
1097 statement.accept1(this, state); 926 statement.accept1(this, conf);
1098 Configuration eval(Expression expression, EvalConfiguration config) => 927 Configuration eval(Expression expression, EvalConfiguration config) =>
1099 evaluator.eval(expression, config); 928 evaluator.eval(expression, config);
1100 Configuration evalList( 929 Configuration evalList(
1101 List<InterpreterExpression> es, Environment env, Continuation cont) => 930 List<InterpreterExpression> es, Environment env, Continuation cont) =>
1102 evaluator.evalList(es, env, cont); 931 evaluator.evalList(es, env, cont);
1103 932
1104 Configuration defaultStatement(Statement node, State state) { 933 Configuration defaultStatement(Statement node, ExecConfiguration conf) {
1105 throw notImplemented( 934 throw notImplemented(
1106 m: "Execution is not implemented for statement:\n$node "); 935 m: "Execution is not implemented for statement:\n$node ");
1107 } 936 }
1108 937
1109 Configuration visitInvalidStatement(InvalidStatement node, State state) { 938 Configuration visitInvalidStatement(
939 InvalidStatement node, ExecConfiguration conf) {
1110 throw "Invalid statement at ${node.location}"; 940 throw "Invalid statement at ${node.location}";
1111 } 941 }
1112 942
1113 Configuration visitExpressionStatement( 943 Configuration visitExpressionStatement(
1114 ExpressionStatement node, State state) { 944 ExpressionStatement node, ExecConfiguration conf) {
1115 var cont = 945 var cont = new ExpressionSK(conf.state.continuation, conf.environment);
1116 new ExpressionStatementContinuation(state.statementConfiguration); 946 return new EvalConfiguration(node.expression, conf.environment, cont);
1117 return new EvalConfiguration(node.expression, state.environment, cont);
1118 } 947 }
1119 948
1120 Configuration visitBlock(Block node, State state) { 949 Configuration visitBlock(Block node, ExecConfiguration conf) {
1121 if (node.statements.isEmpty) { 950 if (node.statements.isEmpty) {
1122 return state.statementConfiguration; 951 return new ForwardConfiguration(
952 conf.state.continuation, conf.environment);
1123 } 953 }
1124 State blockState = 954
1125 state.withEnvironment(new Environment(state.environment)); 955 var env = new Environment(conf.environment);
1126 ExecConfiguration configuration = state.statementConfiguration; 956 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf);
1127 for (Statement s in node.statements.reversed) { 957 return new ExecConfiguration(node.statements.first, env,
1128 configuration = 958 new State(conf.state.labels, conf.state.returnContinuation, cont));
1129 new ExecConfiguration(s, blockState.withConfiguration(configuration));
1130 }
1131 return configuration;
1132 } 959 }
1133 960
1134 Configuration visitEmptyStatement(EmptyStatement node, State state) { 961 Configuration visitEmptyStatement(
1135 return state.statementConfiguration; 962 EmptyStatement node, ExecConfiguration conf) {
963 return new ForwardConfiguration(conf.state.continuation, conf.environment);
1136 } 964 }
1137 965
1138 Configuration visitIfStatement(IfStatement node, State state) { 966 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) {
1139 var cont = new IfConditionContinuation(node.then, node.otherwise, state); 967 var cont = new IfConditionEK(
968 node.then, node.otherwise, conf.environment, conf.state);
1140 969
1141 return new EvalConfiguration(node.condition, state.environment, cont); 970 return new EvalConfiguration(node.condition, conf.environment, cont);
1142 } 971 }
1143 972
1144 Configuration visitLabeledStatement(LabeledStatement node, State state) { 973 Configuration visitLabeledStatement(
1145 return new ExecConfiguration(node.body, state.withBreak(node)); 974 LabeledStatement node, ExecConfiguration conf) {
975 var l = new Label(
976 node, conf.environment, conf.state.continuation, conf.state.labels);
977 return new ExecConfiguration(node.body, conf.environment,
978 new State(l, conf.state.returnContinuation, conf.state.continuation));
1146 } 979 }
1147 980
1148 Configuration visitBreakStatement(BreakStatement node, State state) { 981 Configuration visitBreakStatement(
1149 return state.lookupLabel(node.target).configuration; 982 BreakStatement node, ExecConfiguration conf) {
983 Label l = conf.state.lookupLabel(node.target);
984 return new ForwardConfiguration(l.continuation, l.environment);
1150 } 985 }
1151 986
1152 Configuration visitWhileStatement(WhileStatement node, State state) { 987 Configuration visitWhileStatement(
1153 var cont = new WhileConditionContinuation(node, state); 988 WhileStatement node, ExecConfiguration conf) {
989 var cont = new WhileConditionEK(
990 node.condition, node.body, conf.environment, conf.state);
1154 991
1155 return new EvalConfiguration(node.condition, state.environment, cont); 992 return new EvalConfiguration(node.condition, conf.environment, cont);
1156 } 993 }
1157 994
1158 Configuration visitDoStatement(DoStatement node, State state) { 995 Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) {
1159 WhileStatement whileStatement = 996 var cont = new WhileConditionSK(
1160 new WhileStatement(node.condition, node.body); 997 node.condition, node.body, conf.environment, conf.state);
1161 ExecConfiguration configuration =
1162 new ExecConfiguration(whileStatement, state);
1163 998
1164 return new ExecConfiguration( 999 return new ExecConfiguration(node.body, conf.environment,
1165 node.body, state.withConfiguration(configuration)); 1000 new State(conf.state.labels, conf.state.returnContinuation, cont));
1166 } 1001 }
1167 1002
1168 Configuration visitReturnStatement(ReturnStatement node, State state) { 1003 Configuration visitReturnStatement(
1169 assert(state.returnContinuation != null); 1004 ReturnStatement node, ExecConfiguration conf) {
1005 assert(conf.state.returnContinuation != null);
1170 log.info('return\n'); 1006 log.info('return\n');
1171 if (node.expression == null) { 1007 if (node.expression == null) {
1172 return new ValuePassingConfiguration( 1008 return new ValuePassingConfiguration(
1173 state.returnContinuation, Value.nullInstance); 1009 conf.state.returnContinuation, Value.nullInstance);
1174 } 1010 }
1175 1011
1176 return new EvalConfiguration( 1012 return new EvalConfiguration(
1177 node.expression, state.environment, state.returnContinuation); 1013 node.expression, conf.environment, conf.state.returnContinuation);
1178 } 1014 }
1179 1015
1180 Configuration visitVariableDeclaration( 1016 Configuration visitVariableDeclaration(
1181 VariableDeclaration node, State state) { 1017 VariableDeclaration node, ExecConfiguration conf) {
1182 if (node.initializer != null) { 1018 if (node.initializer != null) {
1183 var cont = new VariableInitializerContinuation( 1019 var cont = new VariableInitializerEK(
1184 node, state.environment, state.statementConfiguration); 1020 node, conf.environment, conf.state.continuation);
1185 return new EvalConfiguration(node.initializer, state.environment, cont); 1021 return new EvalConfiguration(node.initializer, conf.environment, cont);
1186 } 1022 }
1187 state.environment.expand(node, Value.nullInstance); 1023 return new ForwardConfiguration(conf.state.continuation,
1188 return state.statementConfiguration; 1024 conf.environment.extend(node, Value.nullInstance));
1189 } 1025 }
1190 } 1026 }
1191 1027
1192 // ------------------------------------------------------------------------ 1028 // ------------------------------------------------------------------------
1193 // VALUES 1029 // VALUES
1194 // ------------------------------------------------------------------------ 1030 // ------------------------------------------------------------------------
1195 1031
1196 typedef Value Getter(Value receiver); 1032 typedef Value Getter(Value receiver);
1197 typedef void Setter(Value receiver, Value value); 1033 typedef void Setter(Value receiver, Value value);
1198 1034
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 void _initializeNullFields(Class class_, ObjectValue newObject) { 1312 void _initializeNullFields(Class class_, ObjectValue newObject) {
1477 int superClassSize = class_.superclass?.instanceSize ?? 0; 1313 int superClassSize = class_.superclass?.instanceSize ?? 0;
1478 for (int i = superClassSize; i < class_.instanceSize; i++) { 1314 for (int i = superClassSize; i < class_.instanceSize; i++) {
1479 Field field = class_.instanceFields[i]; 1315 Field field = class_.instanceFields[i];
1480 if (class_.getProperty(newObject, field) == null) { 1316 if (class_.getProperty(newObject, field) == null) {
1481 assert(field.initializer == null); 1317 assert(field.initializer == null);
1482 class_.setProperty(newObject, field, Value.nullInstance); 1318 class_.setProperty(newObject, field, Value.nullInstance);
1483 } 1319 }
1484 } 1320 }
1485 } 1321 }
OLDNEW
« no previous file with comments | « no previous file | pkg/kernel/test/interpreter/interpreter.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698