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..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( |