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 31442017fb54cd4f6ad5f2eded0f1db6f6ccefea..b3787a671c6e2e213a633ce2ee010e808ccde172 100644 |
| --- a/pkg/kernel/lib/interpreter/interpreter.dart |
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart |
| @@ -30,8 +30,8 @@ class Interpreter { |
| if (mainMethod == null) return; |
| Statement statementBlock = mainMethod.function.body; |
| - ExecConfiguration configuration = |
| - new ExecConfiguration(statementBlock, new State.initial()); |
| + ExecConfiguration configuration = new ExecConfiguration( |
| + statementBlock, new Environment.empty(), const State.initial()); |
| visitor.trampolinedExecution(configuration); |
| } |
| } |
| @@ -53,10 +53,6 @@ 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); |
| @@ -84,19 +80,13 @@ class Environment { |
| lookupBinding(variable).location.value = value; |
| } |
| - void expand(VariableDeclaration variable, Value value) { |
| + Environment extend(VariableDeclaration variable, Value value) { |
| assert(!contains(variable)); |
| - bindings.add(new Binding(variable, new Location(value))); |
| + return new Environment(this) |
| + ..bindings.add(new Binding(variable, new Location(value))); |
| } |
| } |
| -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, EvalConfiguration> { |
| Configuration eval(Expression expr, EvalConfiguration config) => |
| @@ -152,7 +142,6 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| StaticInvocation node, EvalConfiguration config) { |
| if ('print' == node.name.toString()) { |
| var cont = new PrintEK(config.continuation); |
| - |
| return new EvalConfiguration( |
| node.arguments.positional.first, config.environment, cont); |
| } else { |
| @@ -162,7 +151,6 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| _createArgumentExpressionList(node.arguments, node.target.function); |
| ApplicationContinuation cont = |
| new StaticInvocationA(node.target.function, config.continuation); |
| - |
| return new EvalListConfiguration(args, config.environment, cont); |
| } |
| } |
| @@ -178,14 +166,8 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| } |
| Configuration visitConstructorInvocation( |
| - ConstructorInvocation node, EvalConfiguration config) { |
| - ApplicationContinuation cont = |
| - new ConstructorInvocationA(node.target, config.continuation); |
| - var args = |
| - _createArgumentExpressionList(node.arguments, node.target.function); |
| - |
| - return new EvalListConfiguration(args, config.environment, cont); |
| - } |
| + ConstructorInvocation node, EvalConfiguration config) => |
| + defaultExpression(node, config); |
| Configuration visitNot(Not node, EvalConfiguration config) { |
| return new EvalConfiguration( |
| @@ -221,10 +203,8 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| } |
| Configuration visitThisExpression( |
| - ThisExpression node, EvalConfiguration config) { |
| - return new ValuePassingConfiguration( |
| - config.continuation, config.environment.thisInstance); |
| - } |
| + ThisExpression node, EvalConfiguration config) => |
| + defaultExpression(node, config); |
| // Evaluation of BasicLiterals. |
| Configuration visitStringLiteral( |
| @@ -264,33 +244,30 @@ class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| /// Represents a state for statement execution. |
| class State { |
| - final Environment environment; |
| final Label labels; |
| - final ExecConfiguration statementConfiguration; |
| - |
| + // TODO: Add switch labels. |
| + // TODO: Add component for exception support |
|
Dmitry Stefantsov
2017/07/18 10:39:52
Probably, the above comment should end with a full
zhivkag
2017/07/18 11:01:10
Done.
|
| final ExpressionContinuation returnContinuation; |
| + final StatementContinuation continuation; |
| - State(this.environment, this.labels, this.statementConfiguration, |
| - this.returnContinuation); |
| - |
| - State.initial() : this(new Environment.empty(), null, null, null); |
| + State(this.labels, this.returnContinuation, this.continuation); |
| - State withEnvironment(Environment env) { |
| - return new State(env, labels, statementConfiguration, returnContinuation); |
| - } |
| + const State.initial() |
| + : labels = null, |
| + returnContinuation = null, |
| + continuation = null; |
| - State withBreak(Statement stmt) { |
| - Label breakLabels = new Label(stmt, statementConfiguration, labels); |
| - return new State( |
| - environment, breakLabels, statementConfiguration, returnContinuation); |
| + State withBreak(Statement stmt, Environment env) { |
| + Label breakLabels = new Label(stmt, env, continuation, labels); |
| + return new State(breakLabels, returnContinuation, continuation); |
| } |
| - State withConfiguration(Configuration config) { |
| - return new State(environment, labels, config, returnContinuation); |
| + State withReturnContinuation(ExpressionContinuation returnCont) { |
| + return new State(labels, returnCont, continuation); |
| } |
| - State withExpressionContinuation(ExpressionContinuation cont) { |
| - return new State(environment, labels, statementConfiguration, cont); |
| + State withContinuation(StatementContinuation cont) { |
| + return new State(labels, returnContinuation, cont); |
| } |
| Label lookupLabel(LabeledStatement s) { |
| @@ -303,10 +280,12 @@ class State { |
| /// enclosing label. |
| class Label { |
| final LabeledStatement statement; |
| - final ExecConfiguration configuration; |
| + final Environment environment; |
| + final StatementContinuation continuation; |
| final Label enclosingLabel; |
| - Label(this.statement, this.configuration, this.enclosingLabel); |
| + Label( |
| + this.statement, this.environment, this.continuation, this.enclosingLabel); |
| Label lookupLabel(LabeledStatement s) { |
| if (identical(s, statement)) return this; |
| @@ -324,7 +303,7 @@ abstract class Configuration { |
| Configuration step(StatementExecuter executer); |
| } |
| -/// Represents the configuration for evaluating an [Expression]. |
| +/// Configuration for evaluating an [Expression]. |
| class EvalConfiguration extends Configuration { |
| final Expression expression; |
| @@ -340,11 +319,11 @@ class EvalConfiguration extends Configuration { |
| executer.eval(expression, this); |
| } |
| -/// Represents the configuration for evaluating a list of expressions. |
| +/// Configuration for evaluating a [List<InterpreterExpression>]. |
|
Dmitry Stefantsov
2017/07/18 10:39:52
I think that square brackets only work on identifi
zhivkag
2017/07/18 11:01:10
Done.
|
| class EvalListConfiguration extends Configuration { |
| final List<InterpreterExpression> expressions; |
| final Environment environment; |
| - final Continuation continuation; |
| + final ApplicationContinuation continuation; |
| EvalListConfiguration(this.expressions, this.environment, this.continuation); |
| @@ -352,40 +331,29 @@ class EvalListConfiguration extends Configuration { |
| executer.evalList(expressions, environment, continuation); |
| } |
| -/// Represents the configuration for execution of statement. |
| +/// Configuration for execution of a [Statement]. |
| class ExecConfiguration extends Configuration { |
| - final Statement statement; |
| + final Statement currentStatement; |
| + final Environment environment; |
| final State state; |
| - ExecConfiguration(this.statement, this.state); |
| + ExecConfiguration(this.currentStatement, this.environment, this.state); |
| Configuration step(StatementExecuter executer) => |
| - executer.exec(statement, state); |
| + executer.exec(currentStatement, this); |
| } |
| -class ExitConfiguration extends ExecConfiguration { |
| - final ExpressionContinuation returnContinuation; |
| - |
| - ExitConfiguration(this.returnContinuation) : super(null, null); |
| - |
| - Configuration step(StatementExecuter _) { |
| - return returnContinuation(Value.nullInstance); |
| - } |
| -} |
| - |
| -class NewInstanceConfiguration extends ExecConfiguration { |
| - final ExpressionContinuation continuation; |
| - final ObjectValue newObject; |
| +/// Configuration for applying a [StatementContinuation] to an [Environment]. |
| +class ForwardConfiguration extends Configuration { |
| + final StatementContinuation continuation; |
| + final Environment environment; |
| - NewInstanceConfiguration(this.continuation, this.newObject) |
| - : super(null, new State.initial()); |
| + ForwardConfiguration(this.continuation, this.environment); |
| - Configuration step(StatementExecuter _) { |
| - return continuation(newObject); |
| - } |
| + Configuration step(StatementExecuter _) => continuation?.call(environment); |
| } |
| -/// Represents the configuration for applying an [ExpressionContinuation]. |
| +/// Configuration for applying [ExpressionContinuation] to a [Value]. |
| class ValuePassingConfiguration extends Configuration { |
| final ExpressionContinuation continuation; |
| final Value value; |
| @@ -395,7 +363,8 @@ class ValuePassingConfiguration extends Configuration { |
| Configuration step(StatementExecuter _) => continuation(value); |
| } |
| -/// Represents the configuration for applying an [ApplicationContinuation]. |
| +/// Configuration for applying an [ApplicationContinuation] to a |
| +/// [List<InterpreterValue>]. |
|
Dmitry Stefantsov
2017/07/18 10:39:52
Same as above. Square brackets should probably be
zhivkag
2017/07/18 11:01:10
Done.
|
| class ApplicationConfiguration extends Configuration { |
| final ApplicationContinuation continuation; |
| final List<InterpreterValue> values; |
| @@ -408,6 +377,7 @@ class ApplicationConfiguration extends Configuration { |
| // ------------------------------------------------------------------------ |
| // Interpreter Expressions and Values |
| // ------------------------------------------------------------------------ |
| + |
| abstract class InterpreterExpression { |
| Expression get expression; |
| @@ -430,17 +400,6 @@ class NamedExpression extends InterpreterExpression { |
| InterpreterValue assignValue(Value v) => new NamedValue(name, v); |
| } |
| -class LocalInitializerExpression extends InterpreterExpression { |
| - final VariableDeclaration variable; |
| - |
| - Expression get expression => variable.initializer; |
| - |
| - LocalInitializerExpression(this.variable); |
| - |
| - InterpreterValue assignValue(Value v) => |
| - new LocalInitializerValue(variable, v); |
| -} |
| - |
| class FieldInitializerExpression extends InterpreterExpression { |
| final Field field; |
| final Expression expression; |
| @@ -467,13 +426,6 @@ class NamedValue extends InterpreterValue { |
| NamedValue(this.name, this.value); |
| } |
| -class LocalInitializerValue extends InterpreterValue { |
| - final VariableDeclaration variable; |
| - final Value value; |
| - |
| - LocalInitializerValue(this.variable, this.value); |
| -} |
| - |
| class FieldInitializerValue extends InterpreterValue { |
| final Field field; |
| final Value value; |
| @@ -483,6 +435,84 @@ class FieldInitializerValue extends InterpreterValue { |
| abstract class Continuation {} |
| +// ------------------------------------------------------------------------ |
| +// Statement Continuations |
| +// ------------------------------------------------------------------------ |
| + |
| +/// Represents a the continuation for the execution of the next statement of |
| +/// the program. |
| +/// |
| +/// There are various kinds of [StatementContinuation]s and their names are |
| +/// suffixed with "SK" |
|
Dmitry Stefantsov
2017/07/18 10:39:52
Probably, there should be a full-stop at the end.
zhivkag
2017/07/18 11:01:10
Done.
|
| +abstract class StatementContinuation extends Continuation { |
| + Configuration call(Environment env); |
| +} |
| + |
| +/// Applies the expression continuation to the provided value. |
| +class ExitSK extends StatementContinuation { |
| + final ExpressionContinuation continuation; |
| + final Value value; |
| + |
| + ExitSK(this.continuation, this.value); |
| + |
| + Configuration call(Environment _) => |
| + new ValuePassingConfiguration(continuation, value); |
| +} |
| + |
| +/// Executes the next statement from a block with the corresponding environment |
| +/// or proceeds with next statement continuation. |
| +class BlockSK extends StatementContinuation { |
| + final List<Statement> statements; |
| + final Environment enclosingEnv; |
| + final State state; |
| + |
| + BlockSK(this.statements, this.enclosingEnv, this.state); |
| + |
| + BlockSK.fromConfig(this.statements, ExecConfiguration conf) |
| + : enclosingEnv = conf.environment, |
| + state = conf.state; |
| + |
| + Configuration call(Environment env) { |
| + if (statements.isEmpty) { |
| + return new ForwardConfiguration(state.continuation, enclosingEnv); |
| + } |
| + // Proceed with the execution statement when there are some remaining to |
| + // be executed. |
| + var cont = new BlockSK(statements.skip(1).toList(), enclosingEnv, state); |
| + return new ExecConfiguration( |
| + statements.first, env, state.withContinuation(cont)); |
| + } |
| +} |
| + |
| +class NewSK extends StatementContinuation { |
| + final ExpressionContinuation continuation; |
| + final Location location; |
| + |
| + NewSK(this.continuation, this.location); |
| + |
| + Configuration call(Environment _) => |
| + new ValuePassingConfiguration(continuation, location.value); |
| +} |
| + |
| +class WhileConditionSK extends StatementContinuation { |
| + final Expression condition; |
| + final Statement body; |
| + final Environment enclosingEnv; |
| + final State state; |
| + |
| + WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state); |
| + |
| + Configuration call(Environment _) { |
| + // Evaluate the condition for the while loop execution. |
| + var cont = new WhileConditionEK(condition, body, enclosingEnv, state); |
| + return new EvalConfiguration(condition, enclosingEnv, cont); |
| + } |
| +} |
| + |
| +// ------------------------------------------------------------------------ |
| +// Application Continuations |
| +// ------------------------------------------------------------------------ |
| + |
| /// Represents the continuation called after the evaluation of argument |
| /// expressions. |
| /// |
| @@ -497,14 +527,16 @@ abstract class ApplicationContinuation extends Continuation { |
| static Environment createEnvironment( |
| FunctionNode function, List<InterpreterValue> args, |
| [Environment parentEnv]) { |
| - Environment newEnv = new Environment(parentEnv); |
| + Environment newEnv = new Environment(parentEnv ?? new Environment.empty()); |
| + |
| List<PositionalValue> positional = args.reversed |
| .where((InterpreterValue av) => av is PositionalValue) |
| .toList(); |
| // Add positional parameters. |
| for (int i = 0; i < positional.length; ++i) { |
| - newEnv.expand(function.positionalParameters[i], positional[i].value); |
| + newEnv = |
| + newEnv.extend(function.positionalParameters[i], positional[i].value); |
| } |
| Map<String, Value> named = new Map.fromIterable( |
| @@ -514,13 +546,27 @@ abstract class ApplicationContinuation extends Continuation { |
| // Add named parameters. |
| for (VariableDeclaration v in function.namedParameters) { |
| - newEnv.expand(v, named[v.name.toString()]); |
| + newEnv = newEnv.extend(v, named[v.name.toString()]); |
| } |
| return newEnv; |
| } |
| } |
| +/// Represents the application continuation called after the evaluation of all |
| +/// argument expressions for an invocation. |
| +class ValueA extends ApplicationContinuation { |
| + final InterpreterValue value; |
| + final ApplicationContinuation applicationContinuation; |
| + |
| + ValueA(this.value, this.applicationContinuation); |
| + |
| + Configuration call(List<InterpreterValue> args) { |
| + args.add(value); |
| + return new ApplicationConfiguration(applicationContinuation, args); |
| + } |
| +} |
| + |
| class StringConcatenationA extends ApplicationContinuation { |
| final ExpressionContinuation continuation; |
| @@ -546,276 +592,17 @@ class StaticInvocationA extends ApplicationContinuation { |
| Configuration call(List<InterpreterValue> argValues) { |
| Environment functionEnv = |
| ApplicationContinuation.createEnvironment(function, argValues); |
| + State bodyState = new State( |
| + null, continuation, new ExitSK(continuation, Value.nullInstance)); |
| - State bodyState = new State.initial() |
| - .withExpressionContinuation(continuation) |
| - .withConfiguration(new ExitConfiguration(continuation)) |
| - .withEnvironment(functionEnv); |
| - return new ExecConfiguration(function.body, bodyState); |
| - } |
| -} |
| - |
| -/// Represents the application continuation for constructor invocation applied |
| -/// on the list of evaluated arguments. |
| -class ConstructorInvocationA extends ApplicationContinuation { |
| - final Constructor constructor; |
| - final ExpressionContinuation continuation; |
| - |
| - ConstructorInvocationA(this.constructor, this.continuation); |
| - |
| - Configuration call(List<InterpreterValue> argValues) { |
| - Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| - constructor.function, argValues); |
| - |
| - var class_ = new Class(constructor.enclosingClass.reference); |
| - var newObject = |
| - new ObjectValue(class_, new List<Value>(class_.instanceSize)); |
| - |
| - return new ObjectInitializationConfiguration( |
| - constructor, |
| - new InstanceEnvironment(newObject, ctrEnv), |
| - new NewInstanceConfiguration(continuation, newObject)); |
| - } |
| -} |
| - |
| -/// Represents the application continuation for redirecting constructor |
| -/// invocation applied on the list of evaluated arguments. |
| -class RedirectingConstructorA extends ApplicationContinuation { |
| - final Constructor constructor; |
| - final Environment environment; |
| - final ExecConfiguration configuration; |
| - |
| - RedirectingConstructorA( |
| - this.constructor, this.environment, this.configuration); |
| - |
| - Configuration call(List<InterpreterValue> argValues) { |
| - Value object = environment.thisInstance; |
| - Environment ctrEnv = ApplicationContinuation.createEnvironment( |
| - 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 SuperConstructorA extends ApplicationContinuation { |
| - final Constructor constructor; |
| - final Environment environment; |
| - final ExecConfiguration configuration; |
| - |
| - SuperConstructorA(this.constructor, this.environment, this.configuration); |
| - |
| - Configuration call(List<InterpreterValue> argValues) { |
| - Value object = environment.thisInstance; |
| - |
| - Environment superEnv = ApplicationContinuation.createEnvironment( |
| - constructor.function, |
| - argValues, |
| - new InstanceEnvironment(object, new Environment.empty())); |
| - |
| - return new ObjectInitializationConfiguration( |
| - constructor, superEnv, configuration); |
| - } |
| -} |
| - |
| -/// 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 ExecConfiguration configuration; |
| - |
| - ObjectInitializationConfiguration( |
| - this.constructor, this.environment, this.configuration); |
| - |
| - 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 RedirectingConstructorA( |
| - initializer.target, environment, configuration); |
| - var args = _createArgumentExpressionList( |
| - initializer.arguments, initializer.target.function); |
| - |
| - return new EvalListConfiguration(args, environment, app); |
| - } |
| - // Redirecting initializer is not the only initializer. |
| - for (Initializer i in constructor.initializers.reversed.skip(1)) { |
| - assert(i is LocalInitializer); |
| - } |
| - var class_ = new Class(constructor.enclosingClass.reference); |
| - var initEnv = new Environment(environment); |
| - var cont = new InitializerEK( |
| - class_, initEnv, constructor.initializers, configuration); |
| - return new EvalConfiguration( |
| - (initializer as LocalInitializer).variable.initializer, |
| - 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 ExecConfiguration(constructor.function.body, state); |
| - |
| - // Initialize fields in immediately enclosing class. |
| - var cont = new InstanceFieldsA(constructor, environment, bodyConfig); |
| - var fieldExpressions = _createInstanceInitializers(constructor); |
| - |
| - return new EvalListConfiguration( |
| - fieldExpressions, new Environment.empty(), cont); |
| - } |
| - |
| - /// Creates a list of expressions for instance field initializers in |
| - /// immediately enclosing class. |
| - static List<InterpreterExpression> _createInstanceInitializers( |
| - Constructor ctr) { |
| - Class currentClass = new Class(ctr.enclosingClass.reference); |
| - List<InterpreterExpression> es = <InterpreterExpression>[]; |
| - |
| - for (int i = currentClass.superclass?.instanceSize ?? 0; |
| - i < currentClass.instanceSize; |
| - i++) { |
| - Field current = currentClass.instanceFields[i]; |
| - if (current.initializer != null) { |
| - es.add(new FieldInitializerExpression(current, current.initializer)); |
| - } |
| - } |
| - |
| - return es; |
| - } |
| -} |
| - |
| -/// Represents the application continuation applied on the list of evaluated |
| -/// field initializer expressions. |
| -class InstanceFieldsA extends ApplicationContinuation { |
| - final Constructor constructor; |
| - final Environment environment; |
| - final ExecConfiguration configuration; |
| - |
| - final Class _currentClass; |
| - final ObjectValue _newObject; |
| - |
| - InstanceFieldsA(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); |
| - } |
| - |
| - if (constructor.initializers.isEmpty) { |
| - _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 SuperConstructorA(current.target, environment, configuration); |
| - _initializeNullFields(_currentClass, _newObject); |
| - return new EvalListConfiguration(args, environment, superApp); |
| - } |
| - |
| - Class class_ = new Class(constructor.enclosingClass.reference); |
| - Environment initEnv = new Environment(environment); |
| - |
| - var cont = new InitializerEK( |
| - class_, initEnv, constructor.initializers, configuration); |
| - return new EvalConfiguration( |
| - _getExpression(constructor.initializers.first), initEnv, cont); |
| - } |
| -} |
| - |
| -/// Represents the expression continuation applied on the list of evaluated |
| -/// initializer expressions preceding a super call in the list. |
| -class InitializerEK extends ExpressionContinuation { |
| - final Class currentClass; |
| - final Environment initializerEnvironment; |
| - final List<Initializer> initializers; |
| - final ExecConfiguration configuration; |
| - |
| - InitializerEK(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); |
| - } else if (current is LocalInitializer) { |
| - initializerEnvironment.expand(current.variable, v); |
| - } else { |
| - throw 'Assigning value $v to ${current.runtimeType}'; |
| - } |
| - |
| - if (initializers.length <= 1) { |
| - _initializeNullFields(currentClass, newObject); |
| - return configuration; |
| - } |
| - |
| - Initializer next = initializers[1]; |
| - |
| - if (next is RedirectingInitializer) { |
| - // RedirectingInitializer appears last in the initializer list. |
| - assert(initializers.length == 2); |
| - var app = new RedirectingConstructorA( |
| - next.target, initializerEnvironment, configuration); |
| - var args = |
| - _createArgumentExpressionList(next.arguments, next.target.function); |
| - return new EvalListConfiguration(args, initializerEnvironment, app); |
| - } |
| - |
| - if (next is SuperInitializer) { |
| - // SuperInitializer appears last in the initializer list. |
| - assert(initializers.length == 2); |
| - var args = |
| - _createArgumentExpressionList(next.arguments, next.target.function); |
| - var superApp = new SuperConstructorA( |
| - next.target, initializerEnvironment, configuration); |
| - _initializeNullFields(currentClass, newObject); |
| - return new EvalListConfiguration(args, initializerEnvironment, superApp); |
| - } |
| - |
| - var cont = new InitializerEK(currentClass, initializerEnvironment, |
| - initializers.skip(1).toList(), configuration); |
| - return new EvalConfiguration( |
| - _getExpression(next), initializerEnvironment, cont); |
| - } |
| -} |
| - |
| -/// Represents the application continuation called after the evaluation of all |
| -/// argument expressions for an invocation. |
| -class ValueA extends ApplicationContinuation { |
| - final InterpreterValue value; |
| - final ApplicationContinuation applicationContinuation; |
| - |
| - ValueA(this.value, this.applicationContinuation); |
| - |
| - Configuration call(List<InterpreterValue> args) { |
| - args.add(value); |
| - return new ApplicationConfiguration(applicationContinuation, args); |
| + return new ExecConfiguration(function.body, functionEnv, bodyState); |
| } |
| } |
| // ------------------------------------------------------------------------ |
| // Expression Continuations |
| // ------------------------------------------------------------------------ |
| + |
| /// Represents an expression continuation. |
| /// |
| /// There are various kinds of [ExpressionContinuation]s and their names are |
| @@ -826,13 +613,14 @@ abstract class ExpressionContinuation extends Continuation { |
| /// Represents a continuation that returns the next [ExecConfiguration] |
| /// to be executed. |
| -class ExpressionEK extends ExpressionContinuation { |
| - final ExecConfiguration configuration; |
| +class ExpressionSK extends ExpressionContinuation { |
|
Dmitry Stefantsov
2017/07/18 10:39:52
Why is it marked "SK" now instead of "EK"?
zhivkag
2017/07/18 11:01:10
Indeed, this should be marked with "EK". Done.
|
| + final StatementContinuation continuation; |
| + final Environment environment; |
| - ExpressionEK(this.configuration); |
| + ExpressionSK(this.continuation, this.environment); |
| Configuration call(Value _) { |
| - return configuration; |
| + return new ForwardConfiguration(continuation, environment); |
| } |
| } |
| @@ -1026,27 +814,27 @@ class LetEK extends ExpressionContinuation { |
| Configuration call(Value value) { |
| var letEnv = new Environment(environment); |
| - letEnv.expand(variable, value); |
| + letEnv.extend(variable, value); |
| return new EvalConfiguration(letBody, letEnv, continuation); |
| } |
| } |
| /// Represents the continuation for the condition expression in [WhileStatement]. |
| class WhileConditionEK extends ExpressionContinuation { |
| - final WhileStatement node; |
| + final Expression condition; |
| + final Statement body; |
| + final Environment enclosingEnv; |
| final State state; |
| - WhileConditionEK(this.node, this.state); |
| + WhileConditionEK(this.condition, this.body, this.enclosingEnv, this.state); |
| - ExecConfiguration call(Value v) { |
| - if (identical(v, Value.trueInstance)) { |
| - // Add configuration for the While statement to the linked list. |
| - ExecConfiguration config = new ExecConfiguration(node, state); |
| - // Configuration for the body of the loop. |
| - return new ExecConfiguration(node.body, state.withConfiguration(config)); |
| + Configuration call(Value v) { |
| + if (identical(v, Value.falseInstance)) { |
| + return new ForwardConfiguration(state.continuation, enclosingEnv); |
| } |
| - |
| - return state.statementConfiguration; |
| + var cont = new WhileConditionSK(condition, body, enclosingEnv, state); |
| + return new ExecConfiguration( |
| + body, enclosingEnv, state.withContinuation(cont)); |
| } |
| } |
| @@ -1054,19 +842,20 @@ class WhileConditionEK extends ExpressionContinuation { |
| class IfConditionEK extends ExpressionContinuation { |
| final Statement then; |
| final Statement otherwise; |
| + final Environment environment; |
| final State state; |
| - IfConditionEK(this.then, this.otherwise, this.state); |
| + IfConditionEK(this.then, this.otherwise, this.environment, this.state); |
| - ExecConfiguration call(Value v) { |
| + Configuration call(Value v) { |
| if (identical(v, Value.trueInstance)) { |
| log.info("if-then\n"); |
| - return new ExecConfiguration(then, state); |
| + return new ExecConfiguration(then, environment, state); |
| } else if (otherwise != null) { |
| log.info("if-otherwise\n"); |
| - return new ExecConfiguration(otherwise, state); |
| + return new ExecConfiguration(otherwise, environment, state); |
| } |
| - return state.statementConfiguration; |
| + return new ForwardConfiguration(state.continuation, environment); |
| } |
| } |
| @@ -1075,14 +864,13 @@ class IfConditionEK extends ExpressionContinuation { |
| class VariableInitializerEK extends ExpressionContinuation { |
| final VariableDeclaration variable; |
| final Environment environment; |
| - final ExecConfiguration nextConfiguration; |
| + final StatementContinuation continuation; |
| - VariableInitializerEK( |
| - this.variable, this.environment, this.nextConfiguration); |
| + VariableInitializerEK(this.variable, this.environment, this.continuation); |
| - ExecConfiguration call(Value v) { |
| - environment.expand(variable, v); |
| - return nextConfiguration; |
| + Configuration call(Value v) { |
| + return new ForwardConfiguration( |
| + continuation, environment.extend(variable, v)); |
| } |
| } |
| @@ -1095,107 +883,115 @@ class VariableInitializerEK extends ExpressionContinuation { |
| /// returned and applied |
| /// - it returns with or without value, TBD |
| /// - it throws, TBD |
| -class StatementExecuter extends StatementVisitor1<Configuration, State> { |
| +class StatementExecuter |
| + extends StatementVisitor1<Configuration, ExecConfiguration> { |
| Evaluator evaluator = new Evaluator(); |
| void trampolinedExecution(Configuration configuration) { |
| while (configuration != null) { |
| configuration = configuration.step(this); |
| } |
| + ; |
|
Dmitry Stefantsov
2017/07/18 10:39:52
Why do we need this semicolon?
zhivkag
2017/07/18 11:01:10
Done.
|
| } |
| - Configuration exec(Statement statement, State state) => |
| - statement.accept1(this, state); |
| + Configuration exec(Statement statement, ExecConfiguration conf) => |
| + statement.accept1(this, conf); |
| Configuration eval(Expression expression, EvalConfiguration config) => |
| evaluator.eval(expression, config); |
| Configuration evalList( |
| List<InterpreterExpression> es, Environment env, Continuation cont) => |
| evaluator.evalList(es, env, cont); |
| - Configuration defaultStatement(Statement node, State state) { |
| + Configuration defaultStatement(Statement node, ExecConfiguration conf) { |
| throw notImplemented( |
| m: "Execution is not implemented for statement:\n$node "); |
| } |
| - Configuration visitInvalidStatement(InvalidStatement node, State state) { |
| + Configuration visitInvalidStatement( |
| + InvalidStatement node, ExecConfiguration conf) { |
| throw "Invalid statement at ${node.location}"; |
| } |
| Configuration visitExpressionStatement( |
| - ExpressionStatement node, State state) { |
| - var cont = new ExpressionEK(state.statementConfiguration); |
| - return new EvalConfiguration(node.expression, state.environment, cont); |
| + ExpressionStatement node, ExecConfiguration conf) { |
| + var cont = new ExpressionSK(conf.state.continuation, conf.environment); |
| + return new EvalConfiguration(node.expression, conf.environment, cont); |
| } |
| - Configuration visitBlock(Block node, State state) { |
| + Configuration visitBlock(Block node, ExecConfiguration conf) { |
| if (node.statements.isEmpty) { |
| - return state.statementConfiguration; |
| - } |
| - State blockState = |
| - state.withEnvironment(new Environment(state.environment)); |
| - ExecConfiguration configuration = state.statementConfiguration; |
| - for (Statement s in node.statements.reversed) { |
| - configuration = |
| - new ExecConfiguration(s, blockState.withConfiguration(configuration)); |
| + return new ForwardConfiguration( |
| + conf.state.continuation, conf.environment); |
| } |
| - return configuration; |
| + |
| + 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)); |
| } |
| - Configuration visitEmptyStatement(EmptyStatement node, State state) { |
| - return state.statementConfiguration; |
| + Configuration visitEmptyStatement( |
| + EmptyStatement node, ExecConfiguration conf) { |
| + return new ForwardConfiguration(conf.state.continuation, conf.environment); |
| } |
| - Configuration visitIfStatement(IfStatement node, State state) { |
| - var cont = new IfConditionEK(node.then, node.otherwise, state); |
| + Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { |
| + var cont = new IfConditionEK( |
| + node.then, node.otherwise, conf.environment, conf.state); |
| - return new EvalConfiguration(node.condition, state.environment, cont); |
| + return new EvalConfiguration(node.condition, conf.environment, cont); |
| } |
| - Configuration visitLabeledStatement(LabeledStatement node, State state) { |
| - return new ExecConfiguration(node.body, state.withBreak(node)); |
| + Configuration visitLabeledStatement( |
| + LabeledStatement node, ExecConfiguration conf) { |
| + return new ExecConfiguration(node.body, conf.environment, |
| + conf.state.withBreak(node, conf.environment)); |
| } |
| - Configuration visitBreakStatement(BreakStatement node, State state) { |
| - return state.lookupLabel(node.target).configuration; |
| + Configuration visitBreakStatement( |
| + BreakStatement node, ExecConfiguration conf) { |
| + Label l = conf.state.lookupLabel(node.target); |
| + return new ForwardConfiguration(l.continuation, l.environment); |
| } |
| - Configuration visitWhileStatement(WhileStatement node, State state) { |
| - var cont = new WhileConditionEK(node, state); |
| + Configuration visitWhileStatement( |
| + WhileStatement node, ExecConfiguration conf) { |
| + var cont = new WhileConditionEK( |
| + node.condition, node.body, conf.environment, conf.state); |
| - return new EvalConfiguration(node.condition, state.environment, cont); |
| + return new EvalConfiguration(node.condition, conf.environment, cont); |
| } |
| - Configuration visitDoStatement(DoStatement node, State state) { |
| - WhileStatement whileStatement = |
| - new WhileStatement(node.condition, node.body); |
| - ExecConfiguration configuration = |
| - new ExecConfiguration(whileStatement, state); |
| + Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) { |
| + var cont = new WhileConditionSK( |
| + node.condition, node.body, conf.environment, conf.state); |
| return new ExecConfiguration( |
| - node.body, state.withConfiguration(configuration)); |
| + node.body, conf.environment, conf.state.withContinuation(cont)); |
| } |
| - Configuration visitReturnStatement(ReturnStatement node, State state) { |
| - assert(state.returnContinuation != null); |
| + Configuration visitReturnStatement( |
| + ReturnStatement node, ExecConfiguration conf) { |
| + assert(conf.state.returnContinuation != null); |
| log.info('return\n'); |
| if (node.expression == null) { |
| return new ValuePassingConfiguration( |
| - state.returnContinuation, Value.nullInstance); |
| + conf.state.returnContinuation, Value.nullInstance); |
| } |
| return new EvalConfiguration( |
| - node.expression, state.environment, state.returnContinuation); |
| + node.expression, conf.environment, conf.state.returnContinuation); |
| } |
| Configuration visitVariableDeclaration( |
| - VariableDeclaration node, State state) { |
| + VariableDeclaration node, ExecConfiguration conf) { |
| if (node.initializer != null) { |
| var cont = new VariableInitializerEK( |
| - node, state.environment, state.statementConfiguration); |
| - return new EvalConfiguration(node.initializer, state.environment, cont); |
| + node, conf.environment, conf.state.continuation); |
| + return new EvalConfiguration(node.initializer, conf.environment, cont); |
| } |
| - state.environment.expand(node, Value.nullInstance); |
| - return state.statementConfiguration; |
| + return new ForwardConfiguration(conf.state.continuation, |
| + conf.environment.extend(node, Value.nullInstance)); |
| } |
| } |