OLD | NEW |
---|---|
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 | 7 |
8 class NotImplemented { | 8 class NotImplemented { |
9 String message; | 9 String message; |
10 | 10 |
11 NotImplemented(this.message); | 11 NotImplemented(this.message); |
12 | 12 |
13 String toString() => message; | 13 String toString() => message; |
14 } | 14 } |
15 | 15 |
16 class Interpreter { | 16 class Interpreter { |
17 Program program; | 17 Program program; |
18 Evaluator evaluator = new Evaluator(); | 18 StatementExecuter visitor = new StatementExecuter(); |
19 Environment env = new Environment.empty(); | |
19 | 20 |
20 Interpreter(this.program); | 21 Interpreter(this.program); |
21 | 22 |
22 void run() { | 23 void run() { |
23 assert(program.libraries.isEmpty); | 24 assert(program.libraries.isEmpty); |
24 Procedure mainMethod = program.mainMethod; | 25 Procedure mainMethod = program.mainMethod; |
25 Statement statementBlock = mainMethod.function.body; | 26 Statement statementBlock = mainMethod.function.body; |
26 // Executes only ExpressionStatements and VariableDeclarations in the top | 27 visitor.exec(statementBlock, env); |
27 // BlockStatement. | |
28 if (statementBlock is Block) { | |
29 var env = new Environment.empty(); | |
30 | |
31 for (Statement s in statementBlock.statements) { | |
32 if (s is ExpressionStatement) { | |
33 evaluator.eval(s.expression, env); | |
34 } else if (s is VariableDeclaration) { | |
35 var value = evaluator.eval(s.initializer ?? new NullLiteral(), env); | |
36 env.expand(s, value); | |
37 } else { | |
38 throw new NotImplemented('Evaluation for statement type ' | |
39 '${s.runtimeType} is not implemented.'); | |
40 } | |
41 } | |
42 } else { | |
43 throw new NotImplemented('Evaluation for statement type ' | |
44 '${statementBlock.runtimeType} is not implemented.'); | |
45 } | |
46 } | 28 } |
47 } | 29 } |
48 | 30 |
49 class InvalidExpressionError { | 31 class InvalidExpressionError { |
50 InvalidExpression expression; | 32 InvalidExpression expression; |
51 | 33 |
52 InvalidExpressionError(this.expression); | 34 InvalidExpressionError(this.expression); |
53 | 35 |
54 String toString() => | 36 String toString() => |
55 'Invalid expression at ${expression.location.toString()}'; | 37 'Invalid expression at ${expression.location.toString()}'; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance; | 216 Value visitNullLiteral(NullLiteral node, env) => Value.nullInstance; |
235 | 217 |
236 Value visitLet(Let node, env) { | 218 Value visitLet(Let node, env) { |
237 var value = eval(node.variable.initializer, env); | 219 var value = eval(node.variable.initializer, env); |
238 var letEnv = new Environment(env); | 220 var letEnv = new Environment(env); |
239 letEnv.expand(node.variable, value); | 221 letEnv.expand(node.variable, value); |
240 return eval(node.body, letEnv); | 222 return eval(node.body, letEnv); |
241 } | 223 } |
242 } | 224 } |
243 | 225 |
226 /// Executes statements. | |
227 class StatementExecuter extends StatementVisitor1 { | |
228 Evaluator evaluator = new Evaluator(); | |
229 | |
230 exec(Statement statement, env) => statement.accept1(this, env); | |
231 | |
232 defaultStatement(Statement node, env) {} | |
Kevin Millikin (Google)
2017/03/28 07:11:21
Do you want to throw some kind of 'not implemented
zhivkag
2017/03/28 08:21:31
Done.
| |
233 visitInvalidStatement(InvalidStatement node, env) => | |
234 defaultStatement(node, env); | |
Kevin Millikin (Google)
2017/03/28 07:11:21
I don't think this should occur, so we could just
zhivkag
2017/03/28 08:21:31
Done.
| |
235 | |
236 visitExpressionStatement(ExpressionStatement node, env) => | |
Kevin Millikin (Google)
2017/03/28 07:11:21
As a style issue, I would suggest to make either a
zhivkag
2017/03/28 08:21:31
Done.
| |
237 evaluator.eval(node.expression, env); | |
238 visitBlock(Block node, env) { | |
239 Environment blockEnv = new Environment(env); | |
240 for (Statement s in node.statements) { | |
241 exec(s, blockEnv); | |
242 } | |
243 } | |
244 | |
245 visitEmptyStatement(EmptyStatement node, env) {} | |
246 | |
247 visitIfStatement(IfStatement node, env) { | |
248 Value condition = evaluator.eval(node.condition, env).toBoolean(); | |
249 if (identical(Value.trueInstance, condition)) { | |
250 exec(node.then, env); | |
251 } else { | |
252 exec(node.otherwise, env); | |
253 } | |
254 } | |
255 | |
256 visitVariableDeclaration(VariableDeclaration node, env) { | |
257 Value value = evaluator.eval(node.initializer ?? new NullLiteral(), env); | |
Kevin Millikin (Google)
2017/03/28 07:11:21
It amounts to the same thing, but we probably want
zhivkag
2017/03/28 08:21:31
Done.
| |
258 env.expand(node, value); | |
259 } | |
260 } | |
261 | |
244 typedef Value Getter(Value receiver); | 262 typedef Value Getter(Value receiver); |
245 typedef void Setter(Value receiver, Value value); | 263 typedef void Setter(Value receiver, Value value); |
246 | 264 |
247 // TODO(zhivkag): Change misleading name. | 265 // TODO(zhivkag): Change misleading name. |
248 // This is representation of a class in the interpreter, not a declaration. | 266 // This is representation of a class in the interpreter, not a declaration. |
249 class ClassDeclaration { | 267 class ClassDeclaration { |
250 static final Map<Reference, ClassDeclaration> _classes = | 268 static final Map<Reference, ClassDeclaration> _classes = |
251 <Reference, ClassDeclaration>{}; | 269 <Reference, ClassDeclaration>{}; |
252 | 270 |
253 ClassDeclaration superclass; | 271 ClassDeclaration superclass; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 | 483 |
466 class NullValue extends LiteralValue { | 484 class NullValue extends LiteralValue { |
467 Object get value => null; | 485 Object get value => null; |
468 | 486 |
469 const NullValue(); | 487 const NullValue(); |
470 } | 488 } |
471 | 489 |
472 notImplemented({String m, Object obj}) { | 490 notImplemented({String m, Object obj}) { |
473 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); | 491 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); |
474 } | 492 } |
OLD | NEW |