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 eval(Expression expression, env) => evaluator.eval(expression, env); |
| 232 |
| 233 defaultStatement(Statement node, env) { |
| 234 throw notImplemented( |
| 235 m: "Execution is not implemented for statement:\n$node "); |
| 236 } |
| 237 |
| 238 visitInvalidStatement(InvalidStatement node, env) { |
| 239 throw "Invalid statement at ${node.location}"; |
| 240 } |
| 241 |
| 242 visitExpressionStatement(ExpressionStatement node, env) { |
| 243 return eval(node.expression, env); |
| 244 } |
| 245 |
| 246 visitBlock(Block node, env) { |
| 247 Environment blockEnv = new Environment(env); |
| 248 for (Statement s in node.statements) { |
| 249 exec(s, blockEnv); |
| 250 } |
| 251 } |
| 252 |
| 253 visitEmptyStatement(EmptyStatement node, env) {} |
| 254 |
| 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 } |
| 263 |
| 264 visitVariableDeclaration(VariableDeclaration node, env) { |
| 265 Value value = node.initializer != null |
| 266 ? eval(node.initializer, env) |
| 267 : Value.nullInstance; |
| 268 env.expand(node, value); |
| 269 } |
| 270 } |
| 271 |
244 typedef Value Getter(Value receiver); | 272 typedef Value Getter(Value receiver); |
245 typedef void Setter(Value receiver, Value value); | 273 typedef void Setter(Value receiver, Value value); |
246 | 274 |
247 // TODO(zhivkag): Change misleading name. | 275 // TODO(zhivkag): Change misleading name. |
248 // This is representation of a class in the interpreter, not a declaration. | 276 // This is representation of a class in the interpreter, not a declaration. |
249 class ClassDeclaration { | 277 class ClassDeclaration { |
250 static final Map<Reference, ClassDeclaration> _classes = | 278 static final Map<Reference, ClassDeclaration> _classes = |
251 <Reference, ClassDeclaration>{}; | 279 <Reference, ClassDeclaration>{}; |
252 | 280 |
253 ClassDeclaration superclass; | 281 ClassDeclaration superclass; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 493 |
466 class NullValue extends LiteralValue { | 494 class NullValue extends LiteralValue { |
467 Object get value => null; | 495 Object get value => null; |
468 | 496 |
469 const NullValue(); | 497 const NullValue(); |
470 } | 498 } |
471 | 499 |
472 notImplemented({String m, Object obj}) { | 500 notImplemented({String m, Object obj}) { |
473 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); | 501 throw new NotImplemented(m ?? 'Evaluation for $obj is not implemented'); |
474 } | 502 } |
OLD | NEW |