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

Unified Diff: pkg/kernel/lib/interpreter/interpreter.dart

Issue 2740433006: Implement support for variables and evaluation of logic expressions (Closed)
Patch Set: Apply some suggestions from CR Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/kernel/bin/eval.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/interpreter/interpreter.dart
diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart
index f4f87794487782fad8e299b6762d142050ce8dcd..c6c5881a1a2c8591e210b371ed056ebbc6343a8f 100644
--- a/pkg/kernel/lib/interpreter/interpreter.dart
+++ b/pkg/kernel/lib/interpreter/interpreter.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
library kernerl.interpreter;
-import 'dart:collection';
import '../ast.dart';
class NotImplemented {
@@ -16,24 +15,33 @@ class NotImplemented {
class Interpreter {
Program program;
+ Evaluator evaluator = new Evaluator();
Interpreter(this.program);
- void evalProgram() {
+ void run() {
assert(program.libraries.isEmpty);
Procedure mainMethod = program.mainMethod;
Statement statementBlock = mainMethod.function.body;
- // Evaluate only statement with one expression, ExpressionStatement, which
- // is StaticInvocation of the method print.
+ // Executes only ExpressionStatements and VariableDeclarations in the top
+ // BlockStatement.
if (statementBlock is Block) {
- Statement statement = statementBlock.statements.first;
- if (statement is ExpressionStatement) {
- statement.expression.accept1(new ExpressionEval1(),
- new ExpressionState(new HashMap<String, Object>()));
+ var env = new Environment.empty();
+
+ for (Statement s in statementBlock.statements) {
+ if (s is ExpressionStatement) {
+ evaluator.eval(s.expression, env);
+ } else if (s is VariableDeclaration) {
+ var value = evaluator.eval(s.initializer ?? new NullLiteral(), env);
+ env.expand(s, value);
+ } else {
+ throw new NotImplemented('Evaluation for statement type '
+ '${s.runtimeType} is not implemented.');
+ }
}
} else {
throw new NotImplemented('Evaluation for statement type '
- '${statementBlock.runtimeType} is not implemented');
+ '${statementBlock.runtimeType} is not implemented.');
}
}
}
@@ -43,41 +51,181 @@ class InvalidExpressionError {
InvalidExpressionError(this.expression);
- String toString() => 'Invalid expression at '
- '${expression.location.toString()}';
+ String toString() =>
+ 'Invalid expression at ${expression.location.toString()}';
}
-class ExpressionState {
- Map<String, Object> environment;
+class Binding {
+ final VariableDeclaration variable;
+ Value value;
- ExpressionState(this.environment);
+ Binding(this.variable, this.value);
}
-class ExpressionEval1 extends ExpressionVisitor1<Object> {
- @override
- Object defaultExpression(Expression node, arg) {
+class Environment {
+ final List<Binding> bindings = <Binding>[];
+ final Environment parent;
+
+ Environment.empty() : parent = null;
+ Environment(this.parent);
+
+ bool contains(VariableDeclaration variable) {
+ for (Binding b in bindings.reversed) {
+ if (identical(b.variable, variable)) return true;
+ }
+ return parent?.contains(variable) ?? false;
+ }
+
+ Binding lookupBinding(VariableDeclaration variable) {
+ assert(contains(variable));
+ for (Binding b in bindings) {
+ if (identical(b.variable, variable)) return b;
+ }
+ return parent.lookupBinding(variable);
+ }
+
+ Value lookup(VariableDeclaration variable) {
+ return lookupBinding(variable).value;
+ }
+
+ void assign(VariableDeclaration variable, Value value) {
+ assert(contains(variable));
+ lookupBinding(variable).value = value;
+ }
+
+ void expand(VariableDeclaration variable, Value value) {
+ assert(!contains(variable));
+ bindings.add(new Binding(variable, value));
+ }
+}
+
+class Evaluator extends ExpressionVisitor1<Value> {
+ Value eval(Expression expr, Environment env) => expr.accept1(this, env);
+
+ Value defaultExpression(Expression node, env) {
throw new NotImplemented('Evaluation for expressions of type '
'${node.runtimeType} is not implemented.');
}
- Object visitInvalidExpression1(InvalidExpression node, arg) =>
- throw new InvalidExpressionError(node);
+ Value visitInvalidExpression1(InvalidExpression node, env) {
+ throw new InvalidExpressionError(node);
+ }
+
+ Value visitVariableGet(VariableGet node, env) {
+ return env.lookup(node.variable);
+ }
- Object visitStaticInvocation(StaticInvocation node, arg) {
+ Value visitVariableSet(VariableSet node, env) {
+ return env.assign(node.variable, eval(node.value, env));
+ }
+
+ Value visitStaticInvocation(StaticInvocation node, env) {
if ('print' == node.name.toString()) {
// Special evaluation of print.
- var res = node.arguments.positional[0].accept1(this, arg);
- print(res);
+ var res = eval(node.arguments.positional[0], env);
+ print(res.value);
+ return new NullValue();
} else {
throw new NotImplemented('Support for statement type '
'${node.runtimeType} is not implemented');
}
}
+ Value visitNot(Not node, env) {
+ return new BoolValue(!eval(node.operand, env).asBool);
+ }
+
+ Value visitLogicalExpression(LogicalExpression node, env) {
+ if ('||' == node.operator) {
+ bool left = eval(node.left, env).asBool;
+ return left
+ ? new BoolValue(true)
+ : new BoolValue(eval(node.right, env).asBool);
+ } else {
+ assert('&&' == node.operator);
+ bool left = eval(node.left, env).asBool;
+ return !left
+ ? new BoolValue(false)
+ : new BoolValue(eval(node.right, env).asBool);
+ }
+ }
+
+ Value visitConditionalExpression(ConditionalExpression node, env) {
+ if (eval(node.condition, env).asBool) {
+ return eval(node.then, env);
+ } else {
+ return eval(node.otherwise, env);
+ }
+ }
+
+ Value visitStringConcatenation(StringConcatenation node, env) {
+ StringBuffer res = new StringBuffer();
+ for (Expression e in node.expressions) {
+ res.write(eval(e, env).value);
+ }
+ return new StringValue(res.toString());
+ }
+
// Evaluation of BasicLiterals.
- Object visitStringLiteral(StringLiteral node, arg) => node.value;
- Object visitIntLiteral(IntLiteral node, arg) => node.value;
- Object visitDoubleLiteral(DoubleLiteral node, arg) => node.value;
- Object visitBoolLiteral(BoolLiteral node, arg) => node.value;
- Object visitNullLiteral(NullLiteral node, arg) => node.value;
+ Value visitStringLiteral(StringLiteral node, env) =>
+ new StringValue(node.value);
+ Value visitIntLiteral(IntLiteral node, env) => new IntValue(node.value);
+ Value visitDoubleLiteral(DoubleLiteral node, env) =>
+ new DoubleValue(node.value);
+ Value visitBoolLiteral(BoolLiteral node, env) => new BoolValue(node.value);
+ Value visitNullLiteral(NullLiteral node, env) => new NullValue();
+
+ Value visitLet(Let node, env) {
+ var value = eval(node.variable.initializer, env);
+ var letEnv = new Environment(env);
+ letEnv.expand(node.variable, value);
+ return eval(node.body, letEnv);
+ }
+}
+
+abstract class Value {
+ Object get value;
+ bool get asBool;
+}
+
+class StringValue extends Value {
+ String value;
+
+ bool get asBool => false;
+
+ StringValue(this.value);
+}
+
+class IntValue extends Value {
+ int value;
+
+ bool get asBool => false;
+
+ IntValue(this.value);
+}
+
+class DoubleValue extends Value {
+ double value;
+
+ bool get asBool => false;
+
+ DoubleValue(this.value);
+}
+
+class BoolValue extends Value {
+ bool value;
+
+ bool get asBool => value;
+
+ BoolValue(this.value);
+}
+
+class NullValue extends Value {
+ Object get value => null;
+ bool get asBool => false;
+}
+
+Object error(obj) {
+ // TODO: Implement accordingly with support for error handling.
+ throw new ArgumentError(obj);
}
« no previous file with comments | « pkg/kernel/bin/eval.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698