Index: pkg/kernel/lib/interpreter/interpreter.dart |
diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart |
index 28ec77ac289dbea03df028274ce35cea1b7c5bb7..73330c1b15e9da5f9b846f9085bad20bb465094f 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,16 +180,8 @@ 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.'; |
- } |
- |
ApplicationContinuation cont = |
new ConstructorInvocationApplication(node.target, config.continuation); |
- |
var args = |
_createArgumentExpressionList(node.arguments, node.target.function); |
@@ -222,6 +225,12 @@ class Evaluator |
expressions, 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) { |
@@ -335,11 +344,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 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; |
@@ -469,13 +490,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, |
+ [Environment parentEnv]) { |
+ Environment newEnv = new Environment(parentEnv); |
List<PositionalValue> positional = args.reversed |
.where((InterpreterValue av) => av is PositionalValue) |
.toList(); |
@@ -534,68 +555,76 @@ class ConstructorInvocationApplication extends ApplicationContinuation { |
var newObject = |
new ObjectValue(class_, new List<Value>(class_.instanceSize)); |
- var cont = |
- new ObjectInitializationContinuation(constructor, ctrEnv, continuation); |
- |
- return new ContinuationConfiguration(cont, newObject); |
+ return new ObjectInitializationConfiguration( |
+ constructor, |
+ new InstanceEnvironment(newObject, ctrEnv), |
+ new NewInstanceConfiguration(continuation, newObject)); |
Dmitry Stefantsov
2017/05/18 12:56:51
I think this statement would be hard to translate
|
} |
} |
/// Represents the application continuation for redirecting constructor |
/// invocation applied on the list of evaluated arguments. |
class RedirectingConstructorApplication extends ApplicationContinuation { |
- final ObjectValue newObject; |
final Constructor constructor; |
- final ExpressionContinuation continuation; |
+ final Environment environment; |
+ final StatementConfiguration configuration; |
RedirectingConstructorApplication( |
- this.newObject, this.constructor, this.continuation); |
+ this.constructor, this.environment, this.configuration); |
Configuration call(List<InterpreterValue> argValues) { |
+ Value object = environment.thisInstance; |
Environment ctrEnv = ApplicationContinuation.createEnvironment( |
- constructor.function, argValues); |
- var cont = |
- new ObjectInitializationContinuation(constructor, ctrEnv, continuation); |
- return new ContinuationConfiguration(cont, newObject); |
+ constructor.function, |
+ argValues, |
+ new InstanceEnvironment(object, new Environment.empty())); |
+ |
+ return new ObjectInitializationConfiguration( |
+ constructor, ctrEnv, configuration); |
} |
} |
/// Represents the application continuation for super constructor |
/// invocation applied on the list of evaluated arguments. |
class SuperConstructorApplication extends ApplicationContinuation { |
- final ObjectValue newObject; |
final Constructor constructor; |
- // TODO: remember to execute body of previous ctr. |
- final ExpressionContinuation continuation; |
+ final Environment environment; |
+ final StatementConfiguration configuration; |
SuperConstructorApplication( |
- this.newObject, this.constructor, this.continuation); |
+ this.constructor, this.environment, this.configuration); |
Configuration call(List<InterpreterValue> argValues) { |
- Environment ctrEnv = ApplicationContinuation.createEnvironment( |
- constructor.function, argValues); |
- var cont = |
- new ObjectInitializationContinuation(constructor, ctrEnv, continuation); |
- return new ContinuationConfiguration(cont, newObject); |
+ Value object = environment.thisInstance; |
+ |
+ Environment superEnv = ApplicationContinuation.createEnvironment( |
+ constructor.function, |
+ argValues, |
+ new InstanceEnvironment(object, new Environment.empty())); |
+ |
+ return new ObjectInitializationConfiguration( |
+ constructor, superEnv, configuration); |
} |
} |
-class ObjectInitializationContinuation extends ExpressionContinuation { |
+/// Represents the configuration for execution of initializer and |
+/// constructor body statements for initialization of a newly allocated object. |
+class ObjectInitializationConfiguration extends Configuration { |
final Constructor constructor; |
final Environment environment; |
- final ExpressionContinuation continuation; |
+ final StatementConfiguration configuration; |
- ObjectInitializationContinuation( |
- this.constructor, this.environment, this.continuation); |
+ ObjectInitializationConfiguration( |
+ this.constructor, this.environment, this.configuration); |
- Configuration call(Value v) { |
+ Configuration step(StatementExecuter _) { |
if (constructor.initializers.isNotEmpty && |
constructor.initializers.last is RedirectingInitializer) { |
// Constructor is redirecting. |
Initializer initializer = constructor.initializers.first; |
if (initializer is RedirectingInitializer) { |
var app = new RedirectingConstructorApplication( |
- v, initializer.target, continuation); |
+ initializer.target, environment, configuration); |
var args = _createArgumentExpressionList( |
initializer.arguments, initializer.target.function); |
@@ -606,17 +635,26 @@ class ObjectInitializationContinuation extends ExpressionContinuation { |
assert(i is LocalInitializer); |
} |
var class_ = new Class(constructor.enclosingClass.reference); |
+ var initEnv = new Environment(environment); |
var cont = new InitializerContinuation( |
- v, class_, environment, constructor.initializers, continuation); |
+ class_, initEnv, constructor.initializers, configuration); |
return new ExpressionConfiguration( |
(initializer as LocalInitializer).variable.initializer, |
- environment, |
+ initEnv, |
cont); |
} |
+ // Set head of configurations to be executed to configuration for current |
+ // constructor body. |
+ var state = new State.initial() |
+ .withEnvironment(environment) |
+ .withConfiguration(configuration); |
+ var bodyConfig = |
+ new StatementConfiguration(constructor.function.body, state); |
+ |
// Initialize fields in immediately enclosing class. |
- var cont = new InstanceFieldsApplication( |
- v, constructor, environment, continuation); |
+ var cont = |
+ new InstanceFieldsApplication(constructor, environment, bodyConfig); |
var fieldExpressions = _createInstanceInitializers(constructor); |
return new ExpressionListConfiguration( |
@@ -646,44 +684,47 @@ class ObjectInitializationContinuation extends ExpressionContinuation { |
/// Represents the application continuation applied on the list of evaluated |
/// field initializer expressions. |
class InstanceFieldsApplication extends ApplicationContinuation { |
- final ObjectValue newObject; |
final Constructor constructor; |
final Environment environment; |
- final ExpressionContinuation expressionContinuation; |
+ final StatementConfiguration configuration; |
final Class _currentClass; |
+ final ObjectValue _newObject; |
- InstanceFieldsApplication(this.newObject, this.constructor, this.environment, |
- this.expressionContinuation) |
- : _currentClass = new Class(constructor.enclosingClass.reference); |
+ InstanceFieldsApplication( |
+ this.constructor, this.environment, this.configuration) |
+ : _currentClass = new Class(constructor.enclosingClass.reference), |
+ _newObject = environment.thisInstance; |
Configuration call(List<InterpreterValue> fieldValues) { |
for (FieldInitializerValue current in fieldValues.reversed) { |
- _currentClass.setProperty(newObject, current.field, current.value); |
+ _currentClass.setProperty(_newObject, current.field, current.value); |
} |
if (constructor.initializers.isEmpty) { |
- _initializeNullFields(_currentClass, newObject); |
- return new ContinuationConfiguration(expressionContinuation, newObject); |
+ _initializeNullFields(_currentClass, _newObject); |
+ return configuration; |
} |
+ // Produce next configuration. |
if (constructor.initializers.first is SuperInitializer) { |
// SuperInitializer appears last in the initializer list. |
assert(constructor.initializers.length == 1); |
SuperInitializer current = constructor.initializers.first; |
var args = _createArgumentExpressionList( |
current.arguments, current.target.function); |
+ |
var superApp = new SuperConstructorApplication( |
- newObject, current.target, expressionContinuation); |
- _initializeNullFields(_currentClass, newObject); |
+ current.target, environment, configuration); |
+ _initializeNullFields(_currentClass, _newObject); |
return new ExpressionListConfiguration(args, environment, superApp); |
} |
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( |
+ class_, initEnv, constructor.initializers, configuration); |
return new ExpressionConfiguration( |
_getExpression(constructor.initializers.first), initEnv, cont); |
} |
@@ -692,16 +733,16 @@ 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 Class currentClass; |
final Environment initializerEnvironment; |
final List<Initializer> initializers; |
- final ExpressionContinuation continuation; |
+ final StatementConfiguration configuration; |
- InitializerContinuation(this.newObject, this.currentClass, |
- this.initializerEnvironment, this.initializers, this.continuation); |
+ InitializerContinuation(this.currentClass, this.initializerEnvironment, |
+ this.initializers, this.configuration); |
Configuration call(Value v) { |
+ ObjectValue newObject = initializerEnvironment.thisInstance; |
Initializer current = initializers.first; |
if (current is FieldInitializer) { |
currentClass.setProperty(newObject, current.field, v); |
@@ -712,9 +753,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]; |
@@ -722,12 +762,11 @@ class InitializerContinuation extends ExpressionContinuation { |
if (next is RedirectingInitializer) { |
// RedirectingInitializer appears last in the initializer list. |
assert(initializers.length == 2); |
- var cont = new RedirectingConstructorApplication( |
- newObject, next.target, continuation); |
+ var app = new RedirectingConstructorApplication( |
+ next.target, initializerEnvironment, configuration); |
var args = |
_createArgumentExpressionList(next.arguments, next.target.function); |
- return new ExpressionListConfiguration( |
- args, initializerEnvironment, cont); |
+ return new ExpressionListConfiguration(args, initializerEnvironment, app); |
} |
if (next is SuperInitializer) { |
@@ -735,15 +774,15 @@ class InitializerContinuation extends ExpressionContinuation { |
assert(initializers.length == 2); |
var args = |
_createArgumentExpressionList(next.arguments, next.target.function); |
- var superApp = |
- new SuperConstructorApplication(newObject, next.target, continuation); |
+ var superApp = new SuperConstructorApplication( |
+ next.target, initializerEnvironment, 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(currentClass, initializerEnvironment, |
+ initializers.skip(1).toList(), configuration); |
return new ExpressionConfiguration( |
_getExpression(next), initializerEnvironment, cont); |
} |