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

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

Issue 2880343002: Add support for execution of constructor body (Closed)
Patch Set: Created 3 years, 7 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/constructor_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 d5b63b5b98b7c90f7163f8480f0bfb5c18c34c61..3cccb82698fa7e7292ba345fabb340178aa0e43b 100644
--- a/pkg/kernel/lib/interpreter/interpreter.dart
+++ b/pkg/kernel/lib/interpreter/interpreter.dart
@@ -43,12 +43,18 @@ class Binding {
Binding(this.variable, this.value);
}
-class Environment {
+abstract class Environment {
Dmitry Stefantsov 2017/05/16 08:07:50 I'd rather handle the case of 'this' with a couple
zhivkag 2017/05/16 10:51:13 I see the limitations the previous hierarchy intro
Dmitry Stefantsov 2017/05/16 11:06:52 To me, additional methods look simpler and easier
final List<Binding> bindings = <Binding>[];
- final Environment parent;
+ Environment get parent;
- Environment.empty() : parent = null;
- Environment(this.parent);
+ Environment();
+ factory Environment.withParent(Environment parent) {
+ if (parent is StaticEnvironment) {
+ return new StaticEnvironment(parent);
+ }
+ assert(parent is InstanceEnvironment);
+ return new InstanceEnvironment(parent);
+ }
bool contains(VariableDeclaration variable) {
for (Binding b in bindings.reversed) {
@@ -80,6 +86,22 @@ class Environment {
}
}
+class StaticEnvironment extends Environment {
+ final StaticEnvironment parent;
+ StaticEnvironment.empty() : parent = null;
+ StaticEnvironment(this.parent);
+}
+
+class InstanceEnvironment extends Environment {
+ final Value _thisInstance;
+ final InstanceEnvironment parent;
+
+ get thisInstance => _thisInstance ?? parent.thisInstance;
Dmitry Stefantsov 2017/05/16 08:07:50 Just in case we decide to go with environment clas
zhivkag 2017/05/16 10:51:13 Done.
+
+ InstanceEnvironment.initial(this._thisInstance) : parent = null;
+ InstanceEnvironment(this.parent) : _thisInstance = null;
+}
+
/// Evaluate expressions.
class Evaluator
extends ExpressionVisitor1<Configuration, ExpressionConfiguration> {
@@ -169,20 +191,13 @@ class Evaluator
Configuration visitConstructorInvocation(
ConstructorInvocation node, ExpressionConfiguration config) {
- // Currently, the bodies of the constructors are not executed.
- // Currently initializer list is executed only for redirecting
- // constructors.
- if (node.target.function.body is! EmptyStatement) {
- throw 'Execution for body of constructor is not implemented.';
- }
-
var class_ = new Class(node.target.enclosingClass.reference);
var newObject =
new ObjectValue(class_, new List<Value>(class_.instanceSize));
-
+ var nextConfig =
+ new NewInstanceConfiguration(config.continuation, newObject);
ApplicationContinuation cont = new ConstructorInvocationApplication(
- newObject, node.target, config.continuation);
-
+ newObject, node.target, nextConfig);
Dmitry Stefantsov 2017/05/16 08:07:50 I think it's better to keep 'config.continuation'
zhivkag 2017/05/16 10:51:13 Acknowledged.
var args =
_createArgumentExpressionList(node.arguments, node.target.function);
@@ -224,6 +239,12 @@ class Evaluator
node.expressions.first, config.environment, cont);
}
+ Configuration visitThisExpression(
+ ThisExpression node, ExpressionConfiguration config) {
+ InstanceEnvironment env = config.environment;
+ return new ContinuationConfiguration(config.continuation, env.thisInstance);
+ }
+
// Evaluation of BasicLiterals.
Configuration visitStringLiteral(
StringLiteral node, ExpressionConfiguration config) {
@@ -274,7 +295,7 @@ class State {
State(this.environment, this.labels, this.statementConfiguration,
this.returnContinuation);
- State.initial() : this(new Environment.empty(), null, null, null);
+ State.initial() : this(new StaticEnvironment.empty(), null, null, null);
State withEnvironment(Environment env) {
return new State(env, labels, statementConfiguration, returnContinuation);
@@ -337,11 +358,23 @@ class ExitConfiguration extends StatementConfiguration {
ExitConfiguration(this.returnContinuation) : super(null, null);
- Configuration step(StatementExecuter executer) {
+ Configuration step(StatementExecuter _) {
return returnContinuation(Value.nullInstance);
}
}
+class NewInstanceConfiguration extends StatementConfiguration {
Dmitry Stefantsov 2017/05/16 08:07:50 In case we decide to keep the intermediate configu
Dmitry Stefantsov 2017/05/16 09:59:24 Thank you for the explanation offline about the 'N
zhivkag 2017/05/16 10:51:13 I assume some of the other comments were clarified
+ final ExpressionContinuation continuation;
+ final ObjectValue newObject;
+
+ NewInstanceConfiguration(this.continuation, this.newObject)
+ : super(null, new State.initial());
+
+ Configuration step(StatementExecuter _) {
+ return continuation(newObject);
+ }
+}
+
/// Represents the configuration for applying an [ExpressionContinuation].
class ContinuationConfiguration extends Configuration {
final ExpressionContinuation continuation;
@@ -471,13 +504,13 @@ abstract class Continuation {}
abstract class ApplicationContinuation extends Continuation {
Configuration call(List<InterpreterValue> values);
- /// Creates an environment binding actual argument values to formal parameters
- /// of the function in a new environment, which is used to execute the
- /// body od the function.
+ /// Binds actual argument values to formal parameters of the function in a
+ /// new environment or in the provided initial environment.
/// TODO: Add checks for validation of arguments according to spec.
static Environment createEnvironment(
- FunctionNode function, List<InterpreterValue> args) {
- Environment newEnv = new Environment.empty();
+ FunctionNode function, List<InterpreterValue> args,
+ [initialEnv]) {
+ Environment newEnv = initialEnv ?? new StaticEnvironment.empty();
List<PositionalArgumentValue> positional = args.reversed
.where((InterpreterValue av) => av is PositionalArgumentValue)
.toList();
@@ -525,14 +558,15 @@ class StaticInvocationApplication extends ApplicationContinuation {
class ConstructorInvocationApplication extends ApplicationContinuation {
final ObjectValue newObject;
final Constructor constructor;
- final ExpressionContinuation expressionContinuation;
+ final StatementConfiguration configuration;
Dmitry Stefantsov 2017/05/16 08:07:50 I think it's better to keep 'ExpressionContinuatio
zhivkag 2017/05/16 10:51:13 Acknowledged.
ConstructorInvocationApplication(
- this.newObject, this.constructor, this.expressionContinuation);
+ this.newObject, this.constructor, this.configuration);
Configuration call(List<InterpreterValue> argValues) {
- Environment ctrEnv = ApplicationContinuation.createEnvironment(
- constructor.function, argValues);
+ var bodyEnv = new InstanceEnvironment.initial(newObject);
+ InstanceEnvironment ctrEnv = ApplicationContinuation.createEnvironment(
+ constructor.function, argValues, bodyEnv);
if (constructor.initializers.isNotEmpty &&
constructor.initializers.last is RedirectingInitializer) {
@@ -540,7 +574,7 @@ class ConstructorInvocationApplication extends ApplicationContinuation {
Initializer initializer = constructor.initializers.first;
if (initializer is RedirectingInitializer) {
var app = new ConstructorInvocationApplication(
- newObject, initializer.target, expressionContinuation);
+ newObject, initializer.target, configuration);
var args = _createArgumentExpressionList(
initializer.arguments, initializer.target.function);
@@ -551,15 +585,24 @@ class ConstructorInvocationApplication extends ApplicationContinuation {
assert(i is LocalInitializer);
}
var class_ = new Class(constructor.enclosingClass.reference);
- var cont = new InitializerContinuation(newObject, class_, ctrEnv,
- constructor.initializers, expressionContinuation);
+ var cont = new InitializerContinuation(
+ newObject, class_, ctrEnv, constructor.initializers, configuration);
return new ExpressionConfiguration(
(initializer as LocalInitializer).variable.initializer, ctrEnv, cont);
}
+ var newState = configuration.state
+ .withEnvironment(bodyEnv)
+ .withConfiguration(configuration);
Dmitry Stefantsov 2017/05/16 08:07:50 Here we might have used 'withExpressionContinuatio
zhivkag 2017/05/16 10:51:13 Acknowledged.
+
+ // Set head of configurations to be executed to configuration for current
+ // constructor body.
+ var nextConfiguration =
+ new StatementConfiguration(constructor.function.body, newState);
Dmitry Stefantsov 2017/05/16 08:07:50 Here we may assume that the body of constructor ha
zhivkag 2017/05/16 10:51:13 Acknowledged.
+
// Initialize fields in immediately enclosing class.
var cont = new InstanceFieldsApplication(
- newObject, constructor, ctrEnv, expressionContinuation);
+ newObject, constructor, ctrEnv, nextConfiguration);
var fieldExpressions = _createInstanceInitializers(constructor);
return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont);
@@ -590,13 +633,13 @@ class ConstructorInvocationApplication extends ApplicationContinuation {
class InstanceFieldsApplication extends ApplicationContinuation {
final ObjectValue newObject;
final Constructor constructor;
- final Environment environment;
- final ExpressionContinuation expressionContinuation;
+ final InstanceEnvironment environment;
+ final StatementConfiguration configuration;
final Class _currentClass;
- InstanceFieldsApplication(this.newObject, this.constructor, this.environment,
- this.expressionContinuation)
+ InstanceFieldsApplication(
+ this.newObject, this.constructor, this.environment, this.configuration)
: _currentClass = new Class(constructor.enclosingClass.reference);
Configuration call(List<InterpreterValue> fieldValues) {
@@ -606,7 +649,7 @@ class InstanceFieldsApplication extends ApplicationContinuation {
if (constructor.initializers.isEmpty) {
_initializeNullFields(_currentClass, newObject);
- return new ContinuationConfiguration(expressionContinuation, newObject);
+ return configuration;
}
if (constructor.initializers.first is SuperInitializer) {
@@ -616,16 +659,16 @@ class InstanceFieldsApplication extends ApplicationContinuation {
var args = _createArgumentExpressionList(
current.arguments, current.target.function);
var superApp = new ConstructorInvocationApplication(
- newObject, current.target, expressionContinuation);
+ newObject, current.target, configuration);
_initializeNullFields(_currentClass, newObject);
return new ExpressionListConfiguration(args, environment, superApp);
}
Class class_ = new Class(constructor.enclosingClass.reference);
- Environment initEnv = new Environment(environment);
+ InstanceEnvironment initEnv = new Environment.withParent(environment);
- var cont = new InitializerContinuation(newObject, class_, initEnv,
- constructor.initializers, expressionContinuation);
+ var cont = new InitializerContinuation(
+ newObject, class_, initEnv, constructor.initializers, configuration);
return new ExpressionConfiguration(
_getExpression(constructor.initializers.first), initEnv, cont);
}
@@ -636,12 +679,12 @@ class InstanceFieldsApplication extends ApplicationContinuation {
class InitializerContinuation extends ExpressionContinuation {
final ObjectValue newObject;
final Class currentClass;
- final Environment initializerEnvironment;
+ final InstanceEnvironment initializerEnvironment;
final List<Initializer> initializers;
- final ExpressionContinuation continuation;
+ final StatementConfiguration configuration;
InitializerContinuation(this.newObject, this.currentClass,
- this.initializerEnvironment, this.initializers, this.continuation);
+ this.initializerEnvironment, this.initializers, this.configuration);
Configuration call(Value v) {
Initializer current = initializers.first;
@@ -654,9 +697,8 @@ class InitializerContinuation extends ExpressionContinuation {
}
if (initializers.length <= 1) {
- // todo: return configuration for body of ctr.
_initializeNullFields(currentClass, newObject);
- return new ContinuationConfiguration(continuation, newObject);
+ return configuration;
}
Initializer next = initializers[1];
@@ -665,7 +707,7 @@ class InitializerContinuation extends ExpressionContinuation {
// RedirectingInitializer appears last in the initializer list.
assert(initializers.length == 2);
var cont = new ConstructorInvocationApplication(
- newObject, next.target, continuation);
+ newObject, next.target, configuration);
var args =
_createArgumentExpressionList(next.arguments, next.target.function);
return new ExpressionListConfiguration(
@@ -678,14 +720,14 @@ class InitializerContinuation extends ExpressionContinuation {
var args =
_createArgumentExpressionList(next.arguments, next.target.function);
var superApp = new ConstructorInvocationApplication(
- newObject, next.target, continuation);
+ newObject, next.target, configuration);
_initializeNullFields(currentClass, newObject);
return new ExpressionListConfiguration(
args, initializerEnvironment, superApp);
}
var cont = new InitializerContinuation(newObject, currentClass,
- initializerEnvironment, initializers.skip(1).toList(), continuation);
+ initializerEnvironment, initializers.skip(1).toList(), configuration);
return new ExpressionConfiguration(
_getExpression(next), initializerEnvironment, cont);
}
@@ -943,7 +985,7 @@ class LetContinuation extends ExpressionContinuation {
this.variable, this.letBody, this.environment, this.continuation);
Configuration call(Value value) {
- var letEnv = new Environment(environment);
+ var letEnv = new Environment.withParent(environment);
letEnv.expand(variable, value);
return new ExpressionConfiguration(letBody, letEnv, continuation);
}
@@ -1053,7 +1095,7 @@ class StatementExecuter extends StatementVisitor1<Configuration, State> {
return state.statementConfiguration;
}
State blockState =
- state.withEnvironment(new Environment(state.environment));
+ state.withEnvironment(new Environment.withParent(state.environment));
StatementConfiguration configuration = state.statementConfiguration;
for (Statement s in node.statements.reversed) {
configuration = new StatementConfiguration(
« no previous file with comments | « no previous file | pkg/kernel/testcases/interpreter/constructor_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698