Chromium Code Reviews| 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 |