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

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

Issue 2997563002: Implement support for static accessors (Closed)
Patch Set: Remove dill Created 3 years, 4 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 | « no previous file | pkg/kernel/testcases/interpreter/function_expressions_test.dart » ('j') | 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 2c03f2512c2bf68f0684509e931872d7175d606d..8fd6ff83d731adcc78f9b7ebce394e3d1ef8965a 100644
--- a/pkg/kernel/lib/interpreter/interpreter.dart
+++ b/pkg/kernel/lib/interpreter/interpreter.dart
@@ -21,6 +21,10 @@ class Interpreter {
Program program;
StatementExecuter visitor = new StatementExecuter();
+ // The execution of the program starts with empty main environment.
+ static MainEnvironment mainEnvironment =
+ new MainEnvironment(<Member, Location>{});
+
Interpreter(this.program);
void run() {
@@ -50,6 +54,32 @@ class Binding {
Binding(this.variable, this.location);
}
+/// Represents the top level environment that binds previously accessed or set
+/// static fields to the location that stores their value.
+class MainEnvironment {
+ final Map<Member, Location> _staticFields;
+
+ MainEnvironment(this._staticFields);
+
+ bool contains(Member member) => _staticFields[member] != null;
+
+ Value lookup(Member member) {
+ assert(contains(member));
+ return _staticFields[member].value;
+ }
+
+ void updateStore(Member member, Value value) {
+ assert(contains(member));
+ _staticFields[member].value = value;
+ }
+
+ MainEnvironment extend(Member member, Value value) {
+ var newMap = new Map<Member, Location>.from(_staticFields);
+ newMap[member] = new Location(value);
+ return new MainEnvironment(newMap);
+ }
+}
+
class Environment {
final List<Binding> bindings = <Binding>[];
final Environment parent;
@@ -97,7 +127,7 @@ class Environment {
return lookupBinding(variable).location.value;
}
- void assign(VariableDeclaration variable, Value value) {
+ void updateStore(VariableDeclaration variable, Value value) {
assert(contains(variable));
lookupBinding(variable).location.value = value;
}
@@ -167,10 +197,64 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
node.receiver, config.environment, config.exceptionComponents, cont);
}
- Configuration visitStaticGet(StaticGet node, EvalConfiguration config) =>
- defaultExpression(node, config);
- Configuration visitStaticSet(StaticSet node, EvalConfiguration config) =>
- defaultExpression(node, config);
+ Configuration visitStaticGet(StaticGet node, EvalConfiguration config) {
+ Member member = node.target;
+
+ if (member is Procedure && !member.isAccessor) {
+ // Create a closure for the method tear off.
+ var v = new FunctionValue(member.function, new Environment.empty());
+ return new ValuePassingConfiguration(config.continuation, v);
+ }
+
+ if (member is Procedure && member.isGetter) {
+ // Execute the body of the getter.
+ var state = new State.initial()
+ .withReturnContinuation(config.continuation)
+ .withContinuation(new ExitSK(config.continuation, Value.nullInstance))
+ .withException(config.exceptionComponents);
+ return new ExecConfiguration(
+ member.function.body, new Environment.empty(), state);
+ }
+
+ assert(member is Field);
+ if (Interpreter.mainEnvironment.contains(member)) {
+ // Read the value for the member in the main environment.
+ return new ValuePassingConfiguration(
+ config.continuation, Interpreter.mainEnvironment.lookup(member));
+ }
+
+ // Otherwise, the static field is accessed for the first time.
+ // We extend the main environment with a new binding.
+ Interpreter.mainEnvironment =
+ Interpreter.mainEnvironment.extend(member, Value.nullInstance);
+
+ if ((member as Field).initializer == null) {
+ return new ValuePassingConfiguration(
+ config.continuation, Value.nullInstance);
+ }
+
+ // The initializer expression is evaluated otherwise.
+ var cont = new StaticSetEK(member, config.continuation);
+ return new EvalConfiguration((member as Field).initializer,
+ new Environment.empty(), config.exceptionComponents, cont);
+ }
+
+ Configuration visitStaticSet(StaticSet node, EvalConfiguration config) {
+ Member member = node.target;
+ ExpressionContinuation cont;
+
+ if (member is Procedure) {
+ assert(member.isSetter);
+ cont = new StaticSetterEK(
+ member.function, config.exceptionComponents, config.continuation);
+ } else {
+ assert(member is Field);
+ cont = new StaticSetEK(member, config.continuation);
+ }
+
+ return new EvalConfiguration(
+ node.value, config.environment, config.exceptionComponents, cont);
+ }
Configuration visitStaticInvocation(
StaticInvocation node, EvalConfiguration config) {
@@ -263,6 +347,12 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> {
node.expression, config.environment, config.exceptionComponents, cont);
}
+ Configuration visitFunctionExpression(
+ FunctionExpression node, EvalConfiguration config) {
+ var val = new FunctionValue(node.function, config.environment);
+ return new ValuePassingConfiguration(config.continuation, val);
+ }
+
// Evaluation of BasicLiterals.
Configuration visitStringLiteral(
StringLiteral node, EvalConfiguration config) {
@@ -415,8 +505,9 @@ class ExecConfiguration extends Configuration {
ExecConfiguration(this.currentStatement, this.environment, this.state);
- Configuration step(StatementExecuter executer) =>
- executer.exec(currentStatement, this);
+ Configuration step(StatementExecuter executer) {
+ return executer.exec(currentStatement, this);
+ }
}
/// Configuration for applying a [StatementContinuation] to an [Environment].
@@ -892,6 +983,24 @@ class InstanceFieldsA extends ApplicationContinuation {
return new EvalConfiguration(expr, environment, exceptionComponents, cont);
}
}
+
+class FunctionValueA extends ApplicationContinuation {
+ final FunctionValue receiver;
+ final ExceptionComponents exceptionComponents;
+ final ExpressionContinuation returnContinuation;
+
+ FunctionValueA(
+ this.receiver, this.exceptionComponents, this.returnContinuation);
+
+ Configuration call(List<InterpreterValue> vs) {
+ Environment env = ApplicationContinuation.createEnvironment(
+ receiver.function, vs, receiver.environment);
+ var scont = new ExitSK(returnContinuation, Value.nullInstance);
+ var state = new State(null, exceptionComponents, returnContinuation, scont);
+ return new ExecConfiguration(receiver.function.body, env, state);
+ }
+}
+
// ------------------------------------------------------------------------
// Expression Continuations
// ------------------------------------------------------------------------
@@ -971,6 +1080,44 @@ class SetterEK extends ExpressionContinuation {
}
}
+class StaticSetEK extends ExpressionContinuation {
+ final Member member;
+ final ExpressionContinuation continuation;
+
+ StaticSetEK(this.member, this.continuation);
+
+ Configuration call(Value v) {
+ if (Interpreter.mainEnvironment.contains(member)) {
+ Interpreter.mainEnvironment.updateStore(member, v);
+ } else {
+ Interpreter.mainEnvironment =
+ Interpreter.mainEnvironment.extend(member, v);
+ }
+ return new ValuePassingConfiguration(continuation, v);
+ }
+}
+
+class StaticSetterEK extends ExpressionContinuation {
+ final FunctionNode setter;
+ final ExceptionComponents exceptionComponents;
+ final ExpressionContinuation expressionContinuation;
+
+ StaticSetterEK(
+ this.setter, this.exceptionComponents, this.expressionContinuation);
+
+ Configuration call(Value v) {
+ VariableDeclaration arg = setter.positionalParameters.first;
+ var env = new Environment.empty().extend(arg, v);
+ var state = new State.initial()
+ .withException(exceptionComponents)
+ .withReturnContinuation(expressionContinuation)
+ .withContinuation(
+ new ExitSK(expressionContinuation, Value.nullInstance));
+
+ return new ExecConfiguration(setter.body, env, state);
+ }
+}
+
/// Represents a continuation to be called after the evaluation of an actual
/// argument for function invocation.
class ExpressionListEK extends ExpressionContinuation {
@@ -1002,6 +1149,16 @@ class MethodInvocationEK extends ExpressionContinuation {
this.exceptionComponents, this.continuation);
Configuration call(Value receiver) {
+ if (receiver is FunctionValue) {
+ // TODO(zhivkag): use method lookup instead.
+ assert(methodName.toString() == 'call');
+ var args = _getArgumentExpressions(arguments, receiver.function);
+ var acont =
+ new FunctionValueA(receiver, exceptionComponents, continuation);
+ return new EvalListConfiguration(
+ args, environment, exceptionComponents, acont);
+ }
+
if (arguments.positional.isEmpty) {
Value returnValue = receiver.invokeMethod(methodName);
return new ValuePassingConfiguration(continuation, returnValue);
@@ -1040,7 +1197,7 @@ class VariableSetEK extends ExpressionContinuation {
VariableSetEK(this.variable, this.environment, this.continuation);
Configuration call(Value value) {
- environment.assign(variable, value);
+ environment.updateStore(variable, value);
return new ValuePassingConfiguration(continuation, value);
}
}
@@ -1122,8 +1279,7 @@ class LetEK extends ExpressionContinuation {
this.continuation);
Configuration call(Value value) {
- var letEnv = new Environment(environment);
- letEnv.extend(variable, value);
+ var letEnv = environment.extend(variable, value);
return new EvalConfiguration(
letBody, letEnv, exceptionComponents, continuation);
}
@@ -1500,10 +1656,9 @@ class StatementExecuter
conf.state.continuation, conf.environment);
}
- var env = new Environment(conf.environment);
var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf);
- return new ExecConfiguration(
- node.statements.first, env, conf.state.withContinuation(cont));
+ return new ExecConfiguration(node.statements.first, conf.environment,
+ conf.state.withContinuation(cont));
}
Configuration visitEmptyStatement(
@@ -1599,6 +1754,14 @@ class StatementExecuter
return new ForwardConfiguration(conf.state.continuation,
conf.environment.extend(node, Value.nullInstance));
}
+
+ Configuration visitFunctionDeclaration(
+ FunctionDeclaration node, ExecConfiguration conf) {
+ var newEnv = conf.environment.extend(node.variable, Value.nullInstance);
+ var fun = new FunctionValue(node.function, newEnv);
+ newEnv.updateStore(node.variable, fun);
+ return new ForwardConfiguration(conf.state.continuation, newEnv);
+ }
}
// ------------------------------------------------------------------------
@@ -1734,6 +1897,18 @@ class ObjectValue extends Value {
}
}
+class FunctionValue extends Value {
+ Class get class_ => throw 'Class for FunctionValue is not defined';
+ List<Location> get fields => throw 'FunctionValue has no fields.';
+
+ FunctionValue get value => this;
+
+ final FunctionNode function;
+ final Environment environment;
+
+ FunctionValue(this.function, this.environment);
+}
+
abstract class LiteralValue extends Value {
Class get class_ =>
notImplemented(m: "Loading class for literal is not implemented.");
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/function_expressions_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698