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

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

Issue 2790063002: Implement flow control with breaks (Closed)
Patch Set: Apply comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 library kernel.interpreter; 4 library kernel.interpreter;
5 5
6 import '../ast.dart'; 6 import '../ast.dart';
7 import '../ast.dart' as ast show Class; 7 import '../ast.dart' as ast show Class;
8 8
9 class NotImplemented { 9 class NotImplemented {
10 String message; 10 String message;
11 11
12 NotImplemented(this.message); 12 NotImplemented(this.message);
13 13
14 String toString() => message; 14 String toString() => message;
15 } 15 }
16 16
17 class Interpreter { 17 class Interpreter {
18 Program program; 18 Program program;
19 StatementExecuter visitor = new StatementExecuter(); 19 StatementExecuter visitor = new StatementExecuter();
20 Environment env = new Environment.empty();
21 20
22 Interpreter(this.program); 21 Interpreter(this.program);
23 22
24 void run() { 23 void run() {
25 assert(program.libraries.isEmpty); 24 assert(program.libraries.isEmpty);
26 Procedure mainMethod = program.mainMethod; 25 Procedure mainMethod = program.mainMethod;
27 Statement statementBlock = mainMethod.function.body; 26 Statement statementBlock = mainMethod.function.body;
28 visitor.exec(statementBlock, env); 27 Continuation cont = new Continuation(statementBlock, new State.initial());
28 visitor.trampolinedExecution(cont);
29 } 29 }
30 } 30 }
31 31
32 class InvalidExpressionError {
33 InvalidExpression expression;
34
35 InvalidExpressionError(this.expression);
36
37 String toString() =>
38 'Invalid expression at ${expression.location.toString()}';
39 }
40
41 class Binding { 32 class Binding {
42 final VariableDeclaration variable; 33 final VariableDeclaration variable;
43 Value value; 34 Value value;
44 35
45 Binding(this.variable, this.value); 36 Binding(this.variable, this.value);
46 } 37 }
47 38
48 class Environment { 39 class Environment {
49 final List<Binding> bindings = <Binding>[]; 40 final List<Binding> bindings = <Binding>[];
50 final Environment parent; 41 final Environment parent;
(...skipping 24 matching lines...) Expand all
75 assert(contains(variable)); 66 assert(contains(variable));
76 lookupBinding(variable).value = value; 67 lookupBinding(variable).value = value;
77 } 68 }
78 69
79 void expand(VariableDeclaration variable, Value value) { 70 void expand(VariableDeclaration variable, Value value) {
80 assert(!contains(variable)); 71 assert(!contains(variable));
81 bindings.add(new Binding(variable, value)); 72 bindings.add(new Binding(variable, value));
82 } 73 }
83 } 74 }
84 75
76 /// Evaluate expressions.
85 class Evaluator extends ExpressionVisitor1<Value> { 77 class Evaluator extends ExpressionVisitor1<Value> {
86 Value eval(Expression expr, Environment env) => expr.accept1(this, env); 78 Value eval(Expression expr, Environment env) => expr.accept1(this, env);
87 79
88 Value defaultExpression(Expression node, env) { 80 Value defaultExpression(Expression node, env) {
89 throw new NotImplemented('Evaluation for expressions of type ' 81 throw new NotImplemented('Evaluation for expressions of type '
90 '${node.runtimeType} is not implemented.'); 82 '${node.runtimeType} is not implemented.');
91 } 83 }
92 84
93 Value visitInvalidExpression1(InvalidExpression node, env) { 85 Value visitInvalidExpression1(InvalidExpression node, env) {
94 throw new InvalidExpressionError(node); 86 throw 'Invalid expression at ${node.location.toString()}';
95 } 87 }
96 88
97 Value visitVariableGet(VariableGet node, env) { 89 Value visitVariableGet(VariableGet node, env) {
98 return env.lookup(node.variable); 90 return env.lookup(node.variable);
99 } 91 }
100 92
101 Value visitVariableSet(VariableSet node, env) { 93 Value visitVariableSet(VariableSet node, env) {
102 return env.assign(node.variable, eval(node.value, env)); 94 return env.assign(node.variable, eval(node.value, env));
103 } 95 }
104 96
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance; 208 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance;
217 209
218 Value visitLet(Let node, env) { 210 Value visitLet(Let node, env) {
219 var value = eval(node.variable.initializer, env); 211 var value = eval(node.variable.initializer, env);
220 var letEnv = new Environment(env); 212 var letEnv = new Environment(env);
221 letEnv.expand(node.variable, value); 213 letEnv.expand(node.variable, value);
222 return eval(node.body, letEnv); 214 return eval(node.body, letEnv);
223 } 215 }
224 } 216 }
225 217
218 /// Represents a state which consists of current environment, continuation to be
219 /// applied and the current label.
220 class State {
221 final Environment environment;
222 final Label labels;
223 final Continuation continuation;
224
225 State(this.environment, this.labels, this.continuation);
226 State.initial() : this(new Environment.empty(), null, null);
227
228 State withEnvironment(Environment env) {
229 return new State(env, labels, continuation);
230 }
231
232 State withBreak(Statement stmt) {
233 return new State(
234 environment, new Label(stmt, continuation, labels), continuation);
235 }
236
237 State withContinuation(Continuation cont) {
238 return new State(environment, labels, cont);
239 }
240
241 Label lookupLabel(LabeledStatement s) {
242 assert(labels != null);
243 return labels.lookupLabel(s);
244 }
245 }
246
247 /// Represent the continuation for execution of statement.
248 class Continuation {
249 final Statement statement;
250 final State state;
251
252 Continuation(this.statement, this.state);
253 }
254
255 /// Represents a labeled statement, the corresponding continuation and the
256 /// enclosing label.
257 class Label {
258 final LabeledStatement statement;
259 final Continuation continuation;
260 final Label enclosingLabel;
261
262 Label(this.statement, this.continuation, this.enclosingLabel);
263
264 Label lookupLabel(LabeledStatement s) {
265 if (identical(s, statement)) return this;
266 assert(enclosingLabel != null);
267 return enclosingLabel.lookupLabel(s);
268 }
269 }
270
226 /// Executes statements. 271 /// Executes statements.
227 class StatementExecuter extends StatementVisitor1 { 272 ///
273 /// Execution of a statement completes in one of the following ways:
274 /// - it completes normally, in which case the execution proceeds to applying
275 /// the next continuation
276 /// - it breaks with a label, in which case the corresponding continuation is
277 /// returned and applied
278 /// - it returns with or without value, TBD
279 /// - it throws, TBD
280 class StatementExecuter extends StatementVisitor1<Continuation> {
228 Evaluator evaluator = new Evaluator(); 281 Evaluator evaluator = new Evaluator();
229 282
230 exec(Statement statement, env) => statement.accept1(this, env); 283 void trampolinedExecution(Continuation continuation) {
231 eval(Expression expression, env) => evaluator.eval(expression, env); 284 while (continuation != null) {
285 continuation = exec(continuation.statement, continuation.state);
286 }
287 }
232 288
233 defaultStatement(Statement node, env) { 289 Continuation exec(Statement statement, state) =>
290 statement.accept1(this, state);
291 Value eval(Expression expression, env) => evaluator.eval(expression, env);
292
293 Continuation defaultStatement(Statement node, state) {
234 throw notImplemented( 294 throw notImplemented(
235 m: "Execution is not implemented for statement:\n$node "); 295 m: "Execution is not implemented for statement:\n$node ");
236 } 296 }
237 297
238 visitInvalidStatement(InvalidStatement node, env) { 298 Continuation visitInvalidStatement(InvalidStatement node, state) {
239 throw "Invalid statement at ${node.location}"; 299 throw "Invalid statement at ${node.location}";
240 } 300 }
241 301
242 visitExpressionStatement(ExpressionStatement node, env) { 302 Continuation visitExpressionStatement(ExpressionStatement node, state) {
243 return eval(node.expression, env); 303 eval(node.expression, state.environment);
304 return state.continuation;
244 } 305 }
245 306
246 visitBlock(Block node, env) { 307 Continuation visitBlock(Block node, state) {
247 Environment blockEnv = new Environment(env); 308 if (node.statements.isEmpty) {
248 for (Statement s in node.statements) { 309 return state.continuation;
249 exec(s, blockEnv);
250 } 310 }
311 State blockState =
312 state.withEnvironment(new Environment(state.environment));
313 Continuation cont = state.continuation;
314 for (Statement s in node.statements.reversed) {
315 cont = new Continuation(s, blockState.withContinuation(cont));
316 }
317 return cont;
251 } 318 }
252 319
253 visitEmptyStatement(EmptyStatement node, env) {} 320 Continuation visitEmptyStatement(EmptyStatement node, state) {
254 321 return state.continuation;
255 visitIfStatement(IfStatement node, env) {
256 Value condition = eval(node.condition, env).toBoolean();
257 if (identical(Value.trueInstance, condition)) {
258 exec(node.then, env);
259 } else {
260 exec(node.otherwise, env);
261 }
262 } 322 }
263 323
264 visitVariableDeclaration(VariableDeclaration node, env) { 324 Continuation visitIfStatement(IfStatement node, state) {
325 Value cond = eval(node.condition, state.environment).toBoolean();
326 if (identical(Value.trueInstance, cond)) {
327 return new Continuation(node.then, state);
328 } else if (node.otherwise != null) {
329 return new Continuation(node.otherwise, state);
330 }
331 return state.continuation;
332 }
333
334 Continuation visitLabeledStatement(LabeledStatement node, state) {
335 return new Continuation(node.body, state.withBreak(node));
336 }
337
338 Continuation visitBreakStatement(BreakStatement node, state) {
339 return state.lookupLabel(node.target).continuation;
340 }
341
342 Continuation visitWhileStatement(WhileStatement node, state) {
343 Value cond = eval(node.condition, state.environment).toBoolean();
344 if (identical(Value.trueInstance, cond)) {
345 // Add continuation for the While statement to the linked list.
346 Continuation cont = new Continuation(node, state);
347 // Continuation for the body of the loop.
348 return new Continuation(node.body, state.withContinuation(cont));
349 }
350 return state.continuation;
351 }
352
353 Continuation visitDoStatement(DoStatement node, state) {
354 WhileStatement whileStatement =
355 new WhileStatement(node.condition, node.body);
356 Continuation cont = new Continuation(whileStatement, state);
357 return new Continuation(node.body, state.withContinuation(cont));
358 }
359
360 Continuation visitVariableDeclaration(VariableDeclaration node, state) {
265 Value value = node.initializer != null 361 Value value = node.initializer != null
266 ? eval(node.initializer, env) 362 ? eval(node.initializer, state.environment)
267 : Value.nullInstance; 363 : Value.nullInstance;
268 env.expand(node, value); 364 state.environment.expand(node, value);
365 return state.continuation;
269 } 366 }
270 } 367 }
271 368
272 typedef Value Getter(Value receiver); 369 typedef Value Getter(Value receiver);
273 typedef void Setter(Value receiver, Value value); 370 typedef void Setter(Value receiver, Value value);
274 371
275 // TODO(zhivkag): Change misleading name.
276 // This is representation of a class in the interpreter, not a declaration.
277 class Class { 372 class Class {
278 static final Map<Reference, Class> _classes = <Reference, Class>{}; 373 static final Map<Reference, Class> _classes = <Reference, Class>{};
279 374
280 Class superclass; 375 Class superclass;
281 List<Field> instanceFields = <Field>[]; 376 List<Field> instanceFields = <Field>[];
282 List<Field> staticFields = <Field>[]; 377 List<Field> staticFields = <Field>[];
283 // Implicit getters and setters for instance Fields. 378 // Implicit getters and setters for instance Fields.
284 Map<Name, Getter> getters = <Name, Getter>{}; 379 Map<Name, Getter> getters = <Name, Getter>{};
285 Map<Name, Setter> setters = <Name, Setter>{}; 380 Map<Name, Setter> setters = <Name, Setter>{};
286 // The initializers of static fields are evaluated the first time the field 381 // The initializers of static fields are evaluated the first time the field
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 585
491 class NullValue extends LiteralValue { 586 class NullValue extends LiteralValue {
492 Object get value => null; 587 Object get value => null;
493 588
494 const NullValue(); 589 const NullValue();
495 } 590 }
496 591
497 notImplemented({String m, Object obj}) { 592 notImplemented({String m, Object obj}) {
498 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); 593 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented');
499 } 594 }
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