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..7fd29341987282a983252dda249ade90241775a4 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. |
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>`. |
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>`. |
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". |
+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 |
@@ -827,12 +614,13 @@ abstract class ExpressionContinuation extends Continuation { |
/// Represents a continuation that returns the next [ExecConfiguration] |
/// to be executed. |
class ExpressionEK extends ExpressionContinuation { |
- final ExecConfiguration configuration; |
+ final StatementContinuation continuation; |
+ final Environment environment; |
- ExpressionEK(this.configuration); |
+ ExpressionEK(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,27 +864,28 @@ 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)); |
} |
} |
/// Executes statements. |
/// |
/// Execution of a statement completes in one of the following ways: |
-/// - it completes normally, in which case the execution proceeds to applying |
-/// the next continuation |
-/// - it breaks with a label, in which case the corresponding continuation is |
-/// returned and applied |
-/// - it returns with or without value, TBD |
-/// - it throws, TBD |
-class StatementExecuter extends StatementVisitor1<Configuration, State> { |
+/// - It completes normally, in which case the execution proceeds to applying |
+/// the next continuation. |
+/// - It breaks with a label, in which case the corresponding continuation is |
+/// returned and applied. |
+/// - It returns with or without value, in which case the return continuation is |
+/// returned and applied accordingly. |
+/// - It throws, in which case the handler is returned and applied accordingly. |
+class StatementExecuter |
+ extends StatementVisitor1<Configuration, ExecConfiguration> { |
Evaluator evaluator = new Evaluator(); |
void trampolinedExecution(Configuration configuration) { |
@@ -1104,98 +894,104 @@ class StatementExecuter extends StatementVisitor1<Configuration, State> { |
} |
} |
- 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 ExpressionEK(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)); |
} |
} |