Chromium Code Reviews| 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..151ab7c5342645099bc8fca35fc08737bb0ac6cd 100644 |
| --- a/pkg/kernel/lib/interpreter/interpreter.dart |
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart |
| @@ -47,6 +47,10 @@ class Environment { |
| final List<Binding> bindings = <Binding>[]; |
| final Environment parent; |
| + Value get thisInstance => (parent != null) |
| + ? parent.thisInstance |
| + : throw "Invalid reference to 'this' expression"; |
| + |
| Environment.empty() : parent = null; |
| Environment(this.parent); |
| @@ -80,6 +84,13 @@ class Environment { |
| } |
| } |
| +class InstanceEnvironment extends Environment { |
| + final ObjectValue _thisInstance; |
| + Value get thisInstance => _thisInstance; |
| + |
| + InstanceEnvironment(this._thisInstance, Environment env) : super(env); |
| +} |
| + |
| /// Evaluate expressions. |
| class Evaluator |
| extends ExpressionVisitor1<Configuration, ExpressionConfiguration> { |
| @@ -169,20 +180,14 @@ 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)); |
| - |
| - ApplicationContinuation cont = new ConstructorInvocationApplication( |
| - newObject, node.target, config.continuation); |
| + var env = new InstanceEnvironment( |
| + new ObjectValue(class_, new List<Value>(class_.instanceSize)), |
| + new Environment.empty()); |
| + var nextConfig = new NewInstanceConfiguration(config.continuation, env); |
| + ApplicationContinuation cont = |
| + new ConstructorInvocationApplication(env, node.target, nextConfig); |
| var args = |
| _createArgumentExpressionList(node.arguments, node.target.function); |
| @@ -224,6 +229,12 @@ class Evaluator |
| node.expressions.first, config.environment, cont); |
| } |
| + Configuration visitThisExpression( |
| + ThisExpression node, ExpressionConfiguration config) { |
| + return new ContinuationConfiguration( |
| + config.continuation, config.environment.thisInstance); |
| + } |
| + |
| // Evaluation of BasicLiterals. |
| Configuration visitStringLiteral( |
| StringLiteral node, ExpressionConfiguration config) { |
| @@ -337,11 +348,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 { |
| + final ExpressionContinuation continuation; |
| + final Environment environment; |
| + |
| + NewInstanceConfiguration(this.continuation, this.environment) |
| + : super(null, new State.initial()); |
| + |
| + Configuration step(StatementExecuter _) { |
| + return continuation(environment.thisInstance); |
| + } |
| +} |
| + |
| /// Represents the configuration for applying an [ExpressionContinuation]. |
| class ContinuationConfiguration extends Configuration { |
| final ExpressionContinuation continuation; |
| @@ -471,13 +494,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, |
| + [parentEnv]) { |
| + Environment newEnv = new Environment(parentEnv); |
| List<PositionalArgumentValue> positional = args.reversed |
| .where((InterpreterValue av) => av is PositionalArgumentValue) |
| .toList(); |
| @@ -523,16 +546,16 @@ class StaticInvocationApplication extends ApplicationContinuation { |
| /// Represents the application continuation for constructor invocation applied |
| /// on the list of evaluated arguments. |
| class ConstructorInvocationApplication extends ApplicationContinuation { |
| - final ObjectValue newObject; |
| + final InstanceEnvironment instanceEnvironment; |
| final Constructor constructor; |
| - final ExpressionContinuation expressionContinuation; |
| + final StatementConfiguration configuration; |
| ConstructorInvocationApplication( |
| - this.newObject, this.constructor, this.expressionContinuation); |
| + this.instanceEnvironment, this.constructor, this.configuration); |
| Configuration call(List<InterpreterValue> argValues) { |
| Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| - constructor.function, argValues); |
| + constructor.function, argValues, instanceEnvironment); |
| if (constructor.initializers.isNotEmpty && |
| constructor.initializers.last is RedirectingInitializer) { |
| @@ -540,7 +563,7 @@ class ConstructorInvocationApplication extends ApplicationContinuation { |
| Initializer initializer = constructor.initializers.first; |
| if (initializer is RedirectingInitializer) { |
| var app = new ConstructorInvocationApplication( |
| - newObject, initializer.target, expressionContinuation); |
| + instanceEnvironment, initializer.target, configuration); |
| var args = _createArgumentExpressionList( |
| initializer.arguments, initializer.target.function); |
| @@ -551,15 +574,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(instanceEnvironment, class_, |
| + ctrEnv, constructor.initializers, configuration); |
| return new ExpressionConfiguration( |
| (initializer as LocalInitializer).variable.initializer, ctrEnv, cont); |
| } |
| + var newState = configuration.state |
| + .withEnvironment(ctrEnv) |
| + .withConfiguration(configuration); |
| + |
| + // Set head of configurations to be executed to configuration for current |
| + // constructor body. |
| + var nextConfiguration = |
| + new StatementConfiguration(constructor.function.body, newState); |
| + |
| // Initialize fields in immediately enclosing class. |
| var cont = new InstanceFieldsApplication( |
| - newObject, constructor, ctrEnv, expressionContinuation); |
| + instanceEnvironment, constructor, ctrEnv, nextConfiguration); |
| var fieldExpressions = _createInstanceInitializers(constructor); |
| return new ExpressionListConfiguration(fieldExpressions, ctrEnv, cont); |
| @@ -588,25 +620,26 @@ class ConstructorInvocationApplication extends ApplicationContinuation { |
| /// Represents the application continuation applied on the list of evaluated |
| /// field initializer expressions. |
| class InstanceFieldsApplication extends ApplicationContinuation { |
| - final ObjectValue newObject; |
| + final InstanceEnvironment instanceEnvironment; |
| final Constructor constructor; |
| final Environment environment; |
| - final ExpressionContinuation expressionContinuation; |
| + final StatementConfiguration configuration; |
| final Class _currentClass; |
| - InstanceFieldsApplication(this.newObject, this.constructor, this.environment, |
| - this.expressionContinuation) |
| + InstanceFieldsApplication(this.instanceEnvironment, this.constructor, |
| + this.environment, this.configuration) |
| : _currentClass = new Class(constructor.enclosingClass.reference); |
| Configuration call(List<InterpreterValue> fieldValues) { |
| + Value newObject = instanceEnvironment.thisInstance; |
| for (FieldInitializerValue current in fieldValues.reversed) { |
| _currentClass.setProperty(newObject, current.field, current.value); |
| } |
| if (constructor.initializers.isEmpty) { |
| _initializeNullFields(_currentClass, newObject); |
| - return new ContinuationConfiguration(expressionContinuation, newObject); |
| + return configuration; |
| } |
| if (constructor.initializers.first is SuperInitializer) { |
| @@ -616,7 +649,7 @@ class InstanceFieldsApplication extends ApplicationContinuation { |
| var args = _createArgumentExpressionList( |
| current.arguments, current.target.function); |
| var superApp = new ConstructorInvocationApplication( |
| - newObject, current.target, expressionContinuation); |
| + instanceEnvironment, current.target, configuration); |
| _initializeNullFields(_currentClass, newObject); |
| return new ExpressionListConfiguration(args, environment, superApp); |
| } |
| @@ -624,8 +657,8 @@ class InstanceFieldsApplication extends ApplicationContinuation { |
| Class class_ = new Class(constructor.enclosingClass.reference); |
| Environment initEnv = new Environment(environment); |
| - var cont = new InitializerContinuation(newObject, class_, initEnv, |
| - constructor.initializers, expressionContinuation); |
| + var cont = new InitializerContinuation(instanceEnvironment, class_, initEnv, |
| + constructor.initializers, configuration); |
| return new ExpressionConfiguration( |
| _getExpression(constructor.initializers.first), initEnv, cont); |
| } |
| @@ -634,16 +667,17 @@ class InstanceFieldsApplication extends ApplicationContinuation { |
| /// Represents the expression continuation applied on the list of evaluated |
| /// initializer expressions preceding a super call in the list. |
| class InitializerContinuation extends ExpressionContinuation { |
| - final ObjectValue newObject; |
| + final InstanceEnvironment instanceEnvironment; |
| final Class currentClass; |
| final Environment initializerEnvironment; |
|
Dmitry Stefantsov
2017/05/16 11:06:52
Having two environments in the same continuation r
|
| final List<Initializer> initializers; |
| - final ExpressionContinuation continuation; |
| + final StatementConfiguration configuration; |
| - InitializerContinuation(this.newObject, this.currentClass, |
| - this.initializerEnvironment, this.initializers, this.continuation); |
| + InitializerContinuation(this.instanceEnvironment, this.currentClass, |
| + this.initializerEnvironment, this.initializers, this.configuration); |
| Configuration call(Value v) { |
| + Value newObject = instanceEnvironment.thisInstance; |
| Initializer current = initializers.first; |
| if (current is FieldInitializer) { |
| currentClass.setProperty(newObject, current.field, v); |
| @@ -654,9 +688,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 +698,7 @@ class InitializerContinuation extends ExpressionContinuation { |
| // RedirectingInitializer appears last in the initializer list. |
| assert(initializers.length == 2); |
| var cont = new ConstructorInvocationApplication( |
| - newObject, next.target, continuation); |
| + instanceEnvironment, next.target, configuration); |
| var args = |
| _createArgumentExpressionList(next.arguments, next.target.function); |
| return new ExpressionListConfiguration( |
| @@ -678,14 +711,14 @@ class InitializerContinuation extends ExpressionContinuation { |
| var args = |
| _createArgumentExpressionList(next.arguments, next.target.function); |
| var superApp = new ConstructorInvocationApplication( |
| - newObject, next.target, continuation); |
| + instanceEnvironment, next.target, configuration); |
| _initializeNullFields(currentClass, newObject); |
| return new ExpressionListConfiguration( |
| args, initializerEnvironment, superApp); |
| } |
| - var cont = new InitializerContinuation(newObject, currentClass, |
| - initializerEnvironment, initializers.skip(1).toList(), continuation); |
| + var cont = new InitializerContinuation(instanceEnvironment, currentClass, |
| + initializerEnvironment, initializers.skip(1).toList(), configuration); |
| return new ExpressionConfiguration( |
| _getExpression(next), initializerEnvironment, cont); |
| } |