| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library kernel.interpreter; | 4 library kernel.interpreter; |
| 5 | 5 |
| 6 import '../ast.dart'; | 6 import '../ast.dart'; |
| 7 import '../ast.dart' as ast show Class; | 7 import '../ast.dart' as ast show Class; |
| 8 | 8 |
| 9 import '../log.dart'; | 9 import '../log.dart'; |
| 10 export '../log.dart'; | 10 export '../log.dart'; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 Interpreter(this.program); | 24 Interpreter(this.program); |
| 25 | 25 |
| 26 void run() { | 26 void run() { |
| 27 assert(program.libraries.isEmpty); | 27 assert(program.libraries.isEmpty); |
| 28 Procedure mainMethod = program.mainMethod; | 28 Procedure mainMethod = program.mainMethod; |
| 29 | 29 |
| 30 if (mainMethod == null) return; | 30 if (mainMethod == null) return; |
| 31 | 31 |
| 32 Statement statementBlock = mainMethod.function.body; | 32 Statement statementBlock = mainMethod.function.body; |
| 33 ExecConfiguration configuration = | 33 ExecConfiguration configuration = new ExecConfiguration( |
| 34 new ExecConfiguration(statementBlock, new State.initial()); | 34 statementBlock, new Environment.empty(), const State.initial()); |
| 35 visitor.trampolinedExecution(configuration); | 35 visitor.trampolinedExecution(configuration); |
| 36 } | 36 } |
| 37 } | 37 } |
| 38 | 38 |
| 39 class Location { | 39 class Location { |
| 40 Value value; | 40 Value value; |
| 41 | 41 |
| 42 Location(this.value); | 42 Location(this.value); |
| 43 } | 43 } |
| 44 | 44 |
| 45 class Binding { | 45 class Binding { |
| 46 final VariableDeclaration variable; | 46 final VariableDeclaration variable; |
| 47 final Location location; | 47 final Location location; |
| 48 | 48 |
| 49 Binding(this.variable, this.location); | 49 Binding(this.variable, this.location); |
| 50 } | 50 } |
| 51 | 51 |
| 52 class Environment { | 52 class Environment { |
| 53 final List<Binding> bindings = <Binding>[]; | 53 final List<Binding> bindings = <Binding>[]; |
| 54 final Environment parent; | 54 final Environment parent; |
| 55 | 55 |
| 56 Value get thisInstance => (parent != null) | 56 Value get thisInstance { |
| 57 ? parent.thisInstance | 57 return containsThis() |
| 58 : throw "Invalid reference to 'this' expression"; | 58 ? lookupThis().value |
| 59 : throw "Invalid reference to 'this' expression"; |
| 60 } |
| 59 | 61 |
| 60 Environment.empty() : parent = null; | 62 Environment.empty() : parent = null; |
| 61 Environment(this.parent); | 63 Environment(this.parent); |
| 62 | 64 |
| 63 bool contains(VariableDeclaration variable) { | 65 bool contains(VariableDeclaration variable) { |
| 64 for (Binding b in bindings.reversed) { | 66 for (Binding b in bindings.reversed) { |
| 65 if (identical(b.variable, variable)) return true; | 67 if (identical(b.variable, variable)) return true; |
| 66 } | 68 } |
| 67 return parent?.contains(variable) ?? false; | 69 return parent?.contains(variable) ?? false; |
| 68 } | 70 } |
| 69 | 71 |
| 72 bool containsThis() { |
| 73 for (Binding b in bindings.reversed) { |
| 74 if (identical(b.variable.name, 'this')) return true; |
| 75 } |
| 76 return parent?.containsThis() ?? false; |
| 77 } |
| 78 |
| 70 Binding lookupBinding(VariableDeclaration variable) { | 79 Binding lookupBinding(VariableDeclaration variable) { |
| 71 assert(contains(variable)); | 80 assert(contains(variable)); |
| 72 for (Binding b in bindings) { | 81 for (Binding b in bindings) { |
| 73 if (identical(b.variable, variable)) return b; | 82 if (identical(b.variable, variable)) return b; |
| 74 } | 83 } |
| 75 return parent.lookupBinding(variable); | 84 return parent.lookupBinding(variable); |
| 76 } | 85 } |
| 77 | 86 |
| 87 Location lookupThis() { |
| 88 assert(containsThis()); |
| 89 for (Binding b in bindings) { |
| 90 if (identical(b.variable.name, 'this')) return b.location; |
| 91 } |
| 92 return parent.lookupThis(); |
| 93 } |
| 94 |
| 78 Value lookup(VariableDeclaration variable) { | 95 Value lookup(VariableDeclaration variable) { |
| 79 return lookupBinding(variable).location.value; | 96 return lookupBinding(variable).location.value; |
| 80 } | 97 } |
| 81 | 98 |
| 82 void assign(VariableDeclaration variable, Value value) { | 99 void assign(VariableDeclaration variable, Value value) { |
| 83 assert(contains(variable)); | 100 assert(contains(variable)); |
| 84 lookupBinding(variable).location.value = value; | 101 lookupBinding(variable).location.value = value; |
| 85 } | 102 } |
| 86 | 103 |
| 87 void expand(VariableDeclaration variable, Value value) { | 104 Environment extend(VariableDeclaration variable, Value value) { |
| 88 assert(!contains(variable)); | 105 assert(!contains(variable)); |
| 89 bindings.add(new Binding(variable, new Location(value))); | 106 return new Environment(this) |
| 107 ..bindings.add(new Binding(variable, new Location(value))); |
| 108 } |
| 109 |
| 110 Environment extendWithThis(ObjectValue v) { |
| 111 assert(!containsThis()); |
| 112 return extend(new VariableDeclaration('this'), v); |
| 90 } | 113 } |
| 91 } | 114 } |
| 92 | 115 |
| 93 class InstanceEnvironment extends Environment { | |
| 94 final ObjectValue _thisInstance; | |
| 95 Value get thisInstance => _thisInstance; | |
| 96 | |
| 97 InstanceEnvironment(this._thisInstance, Environment env) : super(env); | |
| 98 } | |
| 99 | |
| 100 /// Evaluate expressions. | 116 /// Evaluate expressions. |
| 101 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { | 117 class Evaluator extends ExpressionVisitor1<Configuration, EvalConfiguration> { |
| 102 Configuration eval(Expression expr, EvalConfiguration config) => | 118 Configuration eval(Expression expr, EvalConfiguration config) => |
| 103 expr.accept1(this, config); | 119 expr.accept1(this, config); |
| 104 | 120 |
| 105 Configuration evalList(List<InterpreterExpression> list, Environment env, | 121 Configuration evalList(List<InterpreterExpression> list, Environment env, |
| 106 ApplicationContinuation cont) { | 122 ApplicationContinuation cont) { |
| 107 if (list.isNotEmpty) { | 123 if (list.isNotEmpty) { |
| 108 return new EvalConfiguration(list.first.expression, env, | 124 return new EvalConfiguration(list.first.expression, env, |
| 109 new ExpressionListContinuation(list.first, list.skip(1), env, cont)); | 125 new ExpressionListEK(list.first, list.skip(1), env, cont)); |
| 110 } | 126 } |
| 111 return new ApplicationConfiguration(cont, <InterpreterValue>[]); | 127 return new ApplicationConfiguration(cont, <InterpreterValue>[]); |
| 112 } | 128 } |
| 113 | 129 |
| 114 Configuration defaultExpression(Expression node, EvalConfiguration config) { | 130 Configuration defaultExpression(Expression node, EvalConfiguration config) { |
| 115 throw new NotImplemented('Evaluation for expressions of type ' | 131 throw new NotImplemented('Evaluation for expressions of type ' |
| 116 '${node.runtimeType} is not implemented.'); | 132 '${node.runtimeType} is not implemented.'); |
| 117 } | 133 } |
| 118 | 134 |
| 119 Configuration visitInvalidExpression1( | 135 Configuration visitInvalidExpression1( |
| 120 InvalidExpression node, EvalConfiguration config) { | 136 InvalidExpression node, EvalConfiguration config) { |
| 121 throw 'Invalid expression at ${node.location.toString()}'; | 137 throw 'Invalid expression at ${node.location.toString()}'; |
| 122 } | 138 } |
| 123 | 139 |
| 124 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { | 140 Configuration visitVariableGet(VariableGet node, EvalConfiguration config) { |
| 125 Value value = config.environment.lookup(node.variable); | 141 Value value = config.environment.lookup(node.variable); |
| 126 return new ValuePassingConfiguration(config.continuation, value); | 142 return new ValuePassingConfiguration(config.continuation, value); |
| 127 } | 143 } |
| 128 | 144 |
| 129 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { | 145 Configuration visitVariableSet(VariableSet node, EvalConfiguration config) { |
| 130 var cont = new VariableSetContinuation( | 146 var cont = new VariableSetEK( |
| 131 node.variable, config.environment, config.continuation); | 147 node.variable, config.environment, config.continuation); |
| 132 return new EvalConfiguration(node.value, config.environment, cont); | 148 return new EvalConfiguration(node.value, config.environment, cont); |
| 133 } | 149 } |
| 134 | 150 |
| 135 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { | 151 Configuration visitPropertyGet(PropertyGet node, EvalConfiguration config) { |
| 136 var cont = new PropertyGetContinuation(node.name, config.continuation); | 152 var cont = new PropertyGetEK(node.name, config.continuation); |
| 137 return new EvalConfiguration(node.receiver, config.environment, cont); | 153 return new EvalConfiguration(node.receiver, config.environment, cont); |
| 138 } | 154 } |
| 139 | 155 |
| 140 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { | 156 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { |
| 141 var cont = new PropertySetContinuation( | 157 var cont = new PropertySetEK( |
| 142 node.value, node.name, config.environment, config.continuation); | 158 node.value, node.name, config.environment, config.continuation); |
| 143 return new EvalConfiguration(node.receiver, config.environment, cont); | 159 return new EvalConfiguration(node.receiver, config.environment, cont); |
| 144 } | 160 } |
| 145 | 161 |
| 146 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => | 162 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => |
| 147 defaultExpression(node, config); | 163 defaultExpression(node, config); |
| 148 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => | 164 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => |
| 149 defaultExpression(node, config); | 165 defaultExpression(node, config); |
| 150 | 166 |
| 151 Configuration visitStaticInvocation( | 167 Configuration visitStaticInvocation( |
| 152 StaticInvocation node, EvalConfiguration config) { | 168 StaticInvocation node, EvalConfiguration config) { |
| 153 if ('print' == node.name.toString()) { | 169 if ('print' == node.name.toString()) { |
| 154 var cont = new PrintContinuation(config.continuation); | 170 var cont = new PrintEK(config.continuation); |
| 155 return new EvalConfiguration( | 171 return new EvalConfiguration( |
| 156 node.arguments.positional.first, config.environment, cont); | 172 node.arguments.positional.first, config.environment, cont); |
| 157 } else { | 173 } else { |
| 158 log.info('static-invocation-${node.target.name.toString()}\n'); | 174 log.info('static-invocation-${node.target.name.toString()}\n'); |
| 159 | 175 |
| 160 List<InterpreterExpression> args = | 176 List<InterpreterExpression> args = |
| 161 _createArgumentExpressionList(node.arguments, node.target.function); | 177 _createArgumentExpressionList(node.arguments, node.target.function); |
| 162 ApplicationContinuation cont = new StaticInvocationApplication( | 178 ApplicationContinuation cont = |
| 163 node.target.function, config.continuation); | 179 new StaticInvocationA(node.target.function, config.continuation); |
| 164 return new EvalListConfiguration(args, config.environment, cont); | 180 return new EvalListConfiguration(args, config.environment, cont); |
| 165 } | 181 } |
| 166 } | 182 } |
| 167 | 183 |
| 168 Configuration visitMethodInvocation( | 184 Configuration visitMethodInvocation( |
| 169 MethodInvocation node, EvalConfiguration config) { | 185 MethodInvocation node, EvalConfiguration config) { |
| 170 // Currently supports only method invocation with <2 arguments and is used | 186 // Currently supports only method invocation with <2 arguments and is used |
| 171 // to evaluate implemented operators for int, double and String values. | 187 // to evaluate implemented operators for int, double and String values. |
| 172 var cont = new MethodInvocationContinuation( | 188 var cont = new MethodInvocationEK( |
| 173 node.arguments, node.name, config.environment, config.continuation); | 189 node.arguments, node.name, config.environment, config.continuation); |
| 174 | 190 |
| 175 return new EvalConfiguration(node.receiver, config.environment, cont); | 191 return new EvalConfiguration(node.receiver, config.environment, cont); |
| 176 } | 192 } |
| 177 | 193 |
| 178 Configuration visitConstructorInvocation( | 194 Configuration visitConstructorInvocation( |
| 179 ConstructorInvocation node, EvalConfiguration config) { | 195 ConstructorInvocation node, EvalConfiguration config) => |
| 180 ApplicationContinuation cont = | 196 defaultExpression(node, config); |
| 181 new ConstructorInvocationApplication(node.target, config.continuation); | |
| 182 var args = | |
| 183 _createArgumentExpressionList(node.arguments, node.target.function); | |
| 184 | |
| 185 return new EvalListConfiguration(args, config.environment, cont); | |
| 186 } | |
| 187 | 197 |
| 188 Configuration visitNot(Not node, EvalConfiguration config) { | 198 Configuration visitNot(Not node, EvalConfiguration config) { |
| 189 return new EvalConfiguration(node.operand, config.environment, | 199 return new EvalConfiguration( |
| 190 new NotContinuation(config.continuation)); | 200 node.operand, config.environment, new NotEK(config.continuation)); |
| 191 } | 201 } |
| 192 | 202 |
| 193 Configuration visitLogicalExpression( | 203 Configuration visitLogicalExpression( |
| 194 LogicalExpression node, EvalConfiguration config) { | 204 LogicalExpression node, EvalConfiguration config) { |
| 195 if ('||' == node.operator) { | 205 if ('||' == node.operator) { |
| 196 var cont = new OrContinuation( | 206 var cont = new OrEK(node.right, config.environment, config.continuation); |
| 197 node.right, config.environment, config.continuation); | |
| 198 return new EvalConfiguration(node.left, config.environment, cont); | 207 return new EvalConfiguration(node.left, config.environment, cont); |
| 199 } else { | 208 } else { |
| 200 assert('&&' == node.operator); | 209 assert('&&' == node.operator); |
| 201 var cont = new AndContinuation( | 210 var cont = new AndEK(node.right, config.environment, config.continuation); |
| 202 node.right, config.environment, config.continuation); | |
| 203 return new EvalConfiguration(node.left, config.environment, cont); | 211 return new EvalConfiguration(node.left, config.environment, cont); |
| 204 } | 212 } |
| 205 } | 213 } |
| 206 | 214 |
| 207 Configuration visitConditionalExpression( | 215 Configuration visitConditionalExpression( |
| 208 ConditionalExpression node, EvalConfiguration config) { | 216 ConditionalExpression node, EvalConfiguration config) { |
| 209 var cont = new ConditionalContinuation( | 217 var cont = new ConditionalEK( |
| 210 node.then, node.otherwise, config.environment, config.continuation); | 218 node.then, node.otherwise, config.environment, config.continuation); |
| 211 return new EvalConfiguration(node.condition, config.environment, cont); | 219 return new EvalConfiguration(node.condition, config.environment, cont); |
| 212 } | 220 } |
| 213 | 221 |
| 214 Configuration visitStringConcatenation( | 222 Configuration visitStringConcatenation( |
| 215 StringConcatenation node, EvalConfiguration config) { | 223 StringConcatenation node, EvalConfiguration config) { |
| 216 var cont = new StringConcatenationContinuation(config.continuation); | 224 var cont = new StringConcatenationA(config.continuation); |
| 217 var expressions = node.expressions | 225 var expressions = node.expressions |
| 218 .map((Expression e) => new PositionalExpression(e)) | 226 .map((Expression e) => new PositionalExpression(e)) |
| 219 .toList(); | 227 .toList(); |
| 220 return new EvalListConfiguration(expressions, config.environment, cont); | 228 return new EvalListConfiguration(expressions, config.environment, cont); |
| 221 } | 229 } |
| 222 | 230 |
| 223 Configuration visitThisExpression( | 231 Configuration visitThisExpression( |
| 224 ThisExpression node, EvalConfiguration config) { | 232 ThisExpression node, EvalConfiguration config) { |
| 225 return new ValuePassingConfiguration( | 233 return new ValuePassingConfiguration( |
| 226 config.continuation, config.environment.thisInstance); | 234 config.continuation, config.environment.thisInstance); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 248 Value value = node.value ? Value.trueInstance : Value.falseInstance; | 256 Value value = node.value ? Value.trueInstance : Value.falseInstance; |
| 249 return new ValuePassingConfiguration(config.continuation, value); | 257 return new ValuePassingConfiguration(config.continuation, value); |
| 250 } | 258 } |
| 251 | 259 |
| 252 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { | 260 Configuration visitNullLiteral(NullLiteral node, EvalConfiguration config) { |
| 253 return new ValuePassingConfiguration( | 261 return new ValuePassingConfiguration( |
| 254 config.continuation, Value.nullInstance); | 262 config.continuation, Value.nullInstance); |
| 255 } | 263 } |
| 256 | 264 |
| 257 Configuration visitLet(Let node, EvalConfiguration config) { | 265 Configuration visitLet(Let node, EvalConfiguration config) { |
| 258 var letCont = new LetContinuation( | 266 var letCont = new LetEK( |
| 259 node.variable, node.body, config.environment, config.continuation); | 267 node.variable, node.body, config.environment, config.continuation); |
| 260 return new EvalConfiguration( | 268 return new EvalConfiguration( |
| 261 node.variable.initializer, config.environment, letCont); | 269 node.variable.initializer, config.environment, letCont); |
| 262 } | 270 } |
| 263 } | 271 } |
| 264 | 272 |
| 265 /// Represents a state for statement execution. | 273 /// Represents a state for statement execution. |
| 266 class State { | 274 class State { |
| 267 final Environment environment; | |
| 268 final Label labels; | 275 final Label labels; |
| 269 final ExecConfiguration statementConfiguration; | 276 // TODO: Add switch labels. |
| 277 // TODO: Add component for exception support |
| 278 final ExpressionContinuation returnContinuation; |
| 279 final StatementContinuation continuation; |
| 270 | 280 |
| 271 final ExpressionContinuation returnContinuation; | 281 State(this.labels, this.returnContinuation, this.continuation); |
| 272 | 282 |
| 273 State(this.environment, this.labels, this.statementConfiguration, | 283 const State.initial() |
| 274 this.returnContinuation); | 284 : labels = null, |
| 285 returnContinuation = null, |
| 286 continuation = null; |
| 275 | 287 |
| 276 State.initial() : this(new Environment.empty(), null, null, null); | 288 State withBreak(Statement stmt, Environment env) { |
| 277 | 289 Label breakLabels = new Label(stmt, env, continuation, labels); |
| 278 State withEnvironment(Environment env) { | 290 return new State(breakLabels, returnContinuation, continuation); |
| 279 return new State(env, labels, statementConfiguration, returnContinuation); | |
| 280 } | 291 } |
| 281 | 292 |
| 282 State withBreak(Statement stmt) { | 293 State withReturnContinuation(ExpressionContinuation returnCont) { |
| 283 Label breakLabels = new Label(stmt, statementConfiguration, labels); | 294 return new State(labels, returnCont, continuation); |
| 284 return new State( | |
| 285 environment, breakLabels, statementConfiguration, returnContinuation); | |
| 286 } | 295 } |
| 287 | 296 |
| 288 State withConfiguration(Configuration config) { | 297 State withContinuation(StatementContinuation cont) { |
| 289 return new State(environment, labels, config, returnContinuation); | 298 return new State(labels, returnContinuation, cont); |
| 290 } | |
| 291 | |
| 292 State withExpressionContinuation(ExpressionContinuation cont) { | |
| 293 return new State(environment, labels, statementConfiguration, cont); | |
| 294 } | 299 } |
| 295 | 300 |
| 296 Label lookupLabel(LabeledStatement s) { | 301 Label lookupLabel(LabeledStatement s) { |
| 297 assert(labels != null); | 302 assert(labels != null); |
| 298 return labels.lookupLabel(s); | 303 return labels.lookupLabel(s); |
| 299 } | 304 } |
| 300 } | 305 } |
| 301 | 306 |
| 302 /// Represents a labeled statement, the corresponding continuation and the | 307 /// Represents a labeled statement, the corresponding continuation and the |
| 303 /// enclosing label. | 308 /// enclosing label. |
| 304 class Label { | 309 class Label { |
| 305 final LabeledStatement statement; | 310 final LabeledStatement statement; |
| 306 final ExecConfiguration configuration; | 311 final Environment environment; |
| 312 final StatementContinuation continuation; |
| 307 final Label enclosingLabel; | 313 final Label enclosingLabel; |
| 308 | 314 |
| 309 Label(this.statement, this.configuration, this.enclosingLabel); | 315 Label( |
| 316 this.statement, this.environment, this.continuation, this.enclosingLabel); |
| 310 | 317 |
| 311 Label lookupLabel(LabeledStatement s) { | 318 Label lookupLabel(LabeledStatement s) { |
| 312 if (identical(s, statement)) return this; | 319 if (identical(s, statement)) return this; |
| 313 assert(enclosingLabel != null); | 320 assert(enclosingLabel != null); |
| 314 return enclosingLabel.lookupLabel(s); | 321 return enclosingLabel.lookupLabel(s); |
| 315 } | 322 } |
| 316 } | 323 } |
| 317 | 324 |
| 325 // ------------------------------------------------------------------------ |
| 326 // Configurations |
| 327 // ------------------------------------------------------------------------ |
| 328 |
| 318 abstract class Configuration { | 329 abstract class Configuration { |
| 319 /// Executes the current and returns the next configuration. | 330 /// Executes the current and returns the next configuration. |
| 320 Configuration step(StatementExecuter executer); | 331 Configuration step(StatementExecuter executer); |
| 321 } | 332 } |
| 322 | 333 |
| 323 /// Represents the configuration for execution of statement. | 334 /// Configuration for evaluating an [Expression]. |
| 335 class EvalConfiguration extends Configuration { |
| 336 final Expression expression; |
| 337 |
| 338 /// Environment in which the expression is evaluated. |
| 339 final Environment environment; |
| 340 |
| 341 /// Next continuation to be applied. |
| 342 final Continuation continuation; |
| 343 |
| 344 EvalConfiguration(this.expression, this.environment, this.continuation); |
| 345 |
| 346 Configuration step(StatementExecuter executer) => |
| 347 executer.eval(expression, this); |
| 348 } |
| 349 |
| 350 /// Configuration for evaluating a [List<InterpreterExpression>]. |
| 351 class EvalListConfiguration extends Configuration { |
| 352 final List<InterpreterExpression> expressions; |
| 353 final Environment environment; |
| 354 final ApplicationContinuation continuation; |
| 355 |
| 356 EvalListConfiguration(this.expressions, this.environment, this.continuation); |
| 357 |
| 358 Configuration step(StatementExecuter executer) => |
| 359 executer.evalList(expressions, environment, continuation); |
| 360 } |
| 361 |
| 362 /// Configuration for execution of a [Statement]. |
| 324 class ExecConfiguration extends Configuration { | 363 class ExecConfiguration extends Configuration { |
| 325 final Statement statement; | 364 final Statement currentStatement; |
| 365 final Environment environment; |
| 326 final State state; | 366 final State state; |
| 327 | 367 |
| 328 ExecConfiguration(this.statement, this.state); | 368 ExecConfiguration(this.currentStatement, this.environment, this.state); |
| 329 | 369 |
| 330 Configuration step(StatementExecuter executer) => | 370 Configuration step(StatementExecuter executer) => |
| 331 executer.exec(statement, state); | 371 executer.exec(currentStatement, this); |
| 332 } | 372 } |
| 333 | 373 |
| 334 class ExitConfiguration extends ExecConfiguration { | 374 /// Configuration for applying a [StatementContinuation] to an [Environment]. |
| 335 final ExpressionContinuation returnContinuation; | 375 class ForwardConfiguration extends Configuration { |
| 376 final StatementContinuation continuation; |
| 377 final Environment environment; |
| 336 | 378 |
| 337 ExitConfiguration(this.returnContinuation) : super(null, null); | 379 ForwardConfiguration(this.continuation, this.environment); |
| 338 | 380 |
| 339 Configuration step(StatementExecuter _) { | 381 Configuration step(StatementExecuter _) => continuation?.call(environment); |
| 340 return returnContinuation(Value.nullInstance); | |
| 341 } | |
| 342 } | 382 } |
| 343 | 383 |
| 344 class NewInstanceConfiguration extends ExecConfiguration { | 384 /// Configuration for applying [ExpressionContinuation] to a [Value]. |
| 345 final ExpressionContinuation continuation; | |
| 346 final ObjectValue newObject; | |
| 347 | |
| 348 NewInstanceConfiguration(this.continuation, this.newObject) | |
| 349 : super(null, new State.initial()); | |
| 350 | |
| 351 Configuration step(StatementExecuter _) { | |
| 352 return continuation(newObject); | |
| 353 } | |
| 354 } | |
| 355 | |
| 356 /// Represents the configuration for applying an [ExpressionContinuation]. | |
| 357 class ValuePassingConfiguration extends Configuration { | 385 class ValuePassingConfiguration extends Configuration { |
| 358 final ExpressionContinuation continuation; | 386 final ExpressionContinuation continuation; |
| 359 final Value value; | 387 final Value value; |
| 360 | 388 |
| 361 ValuePassingConfiguration(this.continuation, this.value); | 389 ValuePassingConfiguration(this.continuation, this.value); |
| 362 | 390 |
| 363 Configuration step(StatementExecuter _) => continuation(value); | 391 Configuration step(StatementExecuter _) => continuation(value); |
| 364 } | 392 } |
| 365 | 393 |
| 366 /// Represents the configuration for applying an [ApplicationContinuation]. | 394 /// Configuration for applying an [ApplicationContinuation] to a |
| 395 /// [List<InterpreterValue>]. |
| 367 class ApplicationConfiguration extends Configuration { | 396 class ApplicationConfiguration extends Configuration { |
| 368 final ApplicationContinuation continuation; | 397 final ApplicationContinuation continuation; |
| 369 final List<InterpreterValue> values; | 398 final List<InterpreterValue> values; |
| 370 | 399 |
| 371 ApplicationConfiguration(this.continuation, this.values); | 400 ApplicationConfiguration(this.continuation, this.values); |
| 372 | 401 |
| 373 Configuration step(StatementExecuter _) => continuation(values); | 402 Configuration step(StatementExecuter _) => continuation(values); |
| 374 } | 403 } |
| 375 | 404 |
| 376 /// Represents the configuration for evaluating an [Expression]. | 405 // ------------------------------------------------------------------------ |
| 377 class EvalConfiguration extends Configuration { | 406 // Interpreter Expressions and Values |
| 378 final Expression expression; | 407 // ------------------------------------------------------------------------ |
| 379 | |
| 380 /// Environment in which the expression is evaluated. | |
| 381 final Environment environment; | |
| 382 | |
| 383 /// Next continuation to be applied. | |
| 384 final Continuation continuation; | |
| 385 | |
| 386 EvalConfiguration(this.expression, this.environment, this.continuation); | |
| 387 | |
| 388 Configuration step(StatementExecuter executer) => | |
| 389 executer.eval(expression, this); | |
| 390 } | |
| 391 | |
| 392 /// Represents the configuration for evaluating a list of expressions. | |
| 393 class EvalListConfiguration extends Configuration { | |
| 394 final List<InterpreterExpression> expressions; | |
| 395 final Environment environment; | |
| 396 final Continuation continuation; | |
| 397 | |
| 398 EvalListConfiguration(this.expressions, this.environment, this.continuation); | |
| 399 | |
| 400 Configuration step(StatementExecuter executer) => | |
| 401 executer.evalList(expressions, environment, continuation); | |
| 402 } | |
| 403 | 408 |
| 404 abstract class InterpreterExpression { | 409 abstract class InterpreterExpression { |
| 405 Expression get expression; | 410 Expression get expression; |
| 406 | 411 |
| 407 InterpreterValue assignValue(Value v); | 412 InterpreterValue assignValue(Value v); |
| 408 } | 413 } |
| 409 | 414 |
| 410 class PositionalExpression extends InterpreterExpression { | 415 class PositionalExpression extends InterpreterExpression { |
| 411 final Expression expression; | 416 final Expression expression; |
| 412 | 417 |
| 413 PositionalExpression(this.expression); | 418 PositionalExpression(this.expression); |
| 414 | 419 |
| 415 InterpreterValue assignValue(Value v) => new PositionalValue(v); | 420 InterpreterValue assignValue(Value v) => new PositionalValue(v); |
| 416 } | 421 } |
| 417 | 422 |
| 418 class NamedExpression extends InterpreterExpression { | 423 class NamedExpression extends InterpreterExpression { |
| 419 final String name; | 424 final String name; |
| 420 final Expression expression; | 425 final Expression expression; |
| 421 | 426 |
| 422 NamedExpression(this.name, this.expression); | 427 NamedExpression(this.name, this.expression); |
| 423 InterpreterValue assignValue(Value v) => new NamedValue(name, v); | 428 InterpreterValue assignValue(Value v) => new NamedValue(name, v); |
| 424 } | 429 } |
| 425 | 430 |
| 426 class LocalInitializerExpression extends InterpreterExpression { | |
| 427 final VariableDeclaration variable; | |
| 428 | |
| 429 Expression get expression => variable.initializer; | |
| 430 | |
| 431 LocalInitializerExpression(this.variable); | |
| 432 | |
| 433 InterpreterValue assignValue(Value v) => | |
| 434 new LocalInitializerValue(variable, v); | |
| 435 } | |
| 436 | |
| 437 class FieldInitializerExpression extends InterpreterExpression { | 431 class FieldInitializerExpression extends InterpreterExpression { |
| 438 final Field field; | 432 final Field field; |
| 439 final Expression expression; | 433 final Expression expression; |
| 440 | 434 |
| 441 FieldInitializerExpression(this.field, this.expression); | 435 FieldInitializerExpression(this.field, this.expression); |
| 442 | 436 |
| 443 InterpreterValue assignValue(Value v) => new FieldInitializerValue(field, v); | 437 InterpreterValue assignValue(Value v) => new FieldInitializerValue(field, v); |
| 444 } | 438 } |
| 445 | 439 |
| 446 abstract class InterpreterValue { | 440 abstract class InterpreterValue { |
| 447 Value get value; | 441 Value get value; |
| 448 } | 442 } |
| 449 | 443 |
| 450 class PositionalValue extends InterpreterValue { | 444 class PositionalValue extends InterpreterValue { |
| 451 final Value value; | 445 final Value value; |
| 452 | 446 |
| 453 PositionalValue(this.value); | 447 PositionalValue(this.value); |
| 454 } | 448 } |
| 455 | 449 |
| 456 class NamedValue extends InterpreterValue { | 450 class NamedValue extends InterpreterValue { |
| 457 final String name; | 451 final String name; |
| 458 final Value value; | 452 final Value value; |
| 459 | 453 |
| 460 NamedValue(this.name, this.value); | 454 NamedValue(this.name, this.value); |
| 461 } | 455 } |
| 462 | 456 |
| 463 class LocalInitializerValue extends InterpreterValue { | |
| 464 final VariableDeclaration variable; | |
| 465 final Value value; | |
| 466 | |
| 467 LocalInitializerValue(this.variable, this.value); | |
| 468 } | |
| 469 | |
| 470 class FieldInitializerValue extends InterpreterValue { | 457 class FieldInitializerValue extends InterpreterValue { |
| 471 final Field field; | 458 final Field field; |
| 472 final Value value; | 459 final Value value; |
| 473 | 460 |
| 474 FieldInitializerValue(this.field, this.value); | 461 FieldInitializerValue(this.field, this.value); |
| 475 } | 462 } |
| 476 | 463 |
| 477 abstract class Continuation {} | 464 abstract class Continuation {} |
| 478 | 465 |
| 466 // ------------------------------------------------------------------------ |
| 467 // Statement Continuations |
| 468 // ------------------------------------------------------------------------ |
| 469 |
| 470 /// Represents a the continuation for the execution of the next statement of |
| 471 /// the program. |
| 472 /// |
| 473 /// There are various kinds of [StatementContinuation]s and their names are |
| 474 /// suffixed with "SK" |
| 475 abstract class StatementContinuation extends Continuation { |
| 476 Configuration call(Environment env); |
| 477 } |
| 478 |
| 479 /// Applies the expression continuation to the provided value. |
| 480 class ExitSK extends StatementContinuation { |
| 481 final ExpressionContinuation continuation; |
| 482 final Value value; |
| 483 |
| 484 ExitSK(this.continuation, this.value); |
| 485 |
| 486 Configuration call(Environment _) => |
| 487 new ValuePassingConfiguration(continuation, value); |
| 488 } |
| 489 |
| 490 /// Executes the next statement from a block with the corresponding environment |
| 491 /// or proceeds with next statement continuation. |
| 492 class BlockSK extends StatementContinuation { |
| 493 final List<Statement> statements; |
| 494 final Environment enclosingEnv; |
| 495 final State state; |
| 496 |
| 497 BlockSK(this.statements, this.enclosingEnv, this.state); |
| 498 |
| 499 BlockSK.fromConfig(this.statements, ExecConfiguration conf) |
| 500 : enclosingEnv = conf.environment, |
| 501 state = conf.state; |
| 502 |
| 503 Configuration call(Environment env) { |
| 504 if (statements.isEmpty) { |
| 505 return new ForwardConfiguration(state.continuation, enclosingEnv); |
| 506 } |
| 507 // Proceed with the execution statement when there are some remaining to |
| 508 // be executed. |
| 509 var cont = new BlockSK(statements.skip(1).toList(), enclosingEnv, state); |
| 510 return new ExecConfiguration( |
| 511 statements.first, env, state.withContinuation(cont)); |
| 512 } |
| 513 } |
| 514 |
| 515 class NewSK extends StatementContinuation { |
| 516 final ExpressionContinuation continuation; |
| 517 final Location location; |
| 518 |
| 519 NewSK(this.continuation, this.location); |
| 520 |
| 521 Configuration call(Environment _) => |
| 522 new ValuePassingConfiguration(continuation, location.value); |
| 523 } |
| 524 |
| 525 class WhileConditionSK extends StatementContinuation { |
| 526 final Expression condition; |
| 527 final Statement body; |
| 528 final Environment enclosingEnv; |
| 529 final State state; |
| 530 |
| 531 WhileConditionSK(this.condition, this.body, this.enclosingEnv, this.state); |
| 532 |
| 533 Configuration call(Environment _) { |
| 534 // Evaluate the condition for the while loop execution. |
| 535 var cont = new WhileConditionEK(condition, body, enclosingEnv, state); |
| 536 return new EvalConfiguration(condition, enclosingEnv, cont); |
| 537 } |
| 538 } |
| 539 |
| 540 // ------------------------------------------------------------------------ |
| 541 // Application Continuations |
| 542 // ------------------------------------------------------------------------ |
| 543 |
| 479 /// Represents the continuation called after the evaluation of argument | 544 /// Represents the continuation called after the evaluation of argument |
| 480 /// expressions. | 545 /// expressions. |
| 546 /// |
| 547 /// There are various kinds of [ApplicationContinuation] and their names are |
| 548 /// suffixed with "A". |
| 481 abstract class ApplicationContinuation extends Continuation { | 549 abstract class ApplicationContinuation extends Continuation { |
| 482 Configuration call(List<InterpreterValue> values); | 550 Configuration call(List<InterpreterValue> values); |
| 483 | 551 |
| 484 /// Binds actual argument values to formal parameters of the function in a | 552 /// Binds actual argument values to formal parameters of the function in a |
| 485 /// new environment or in the provided initial environment. | 553 /// new environment or in the provided initial environment. |
| 486 /// TODO: Add checks for validation of arguments according to spec. | 554 /// TODO: Add checks for validation of arguments according to spec. |
| 487 static Environment createEnvironment( | 555 static Environment createEnvironment( |
| 488 FunctionNode function, List<InterpreterValue> args, | 556 FunctionNode function, List<InterpreterValue> args, |
| 489 [Environment parentEnv]) { | 557 [Environment parentEnv]) { |
| 490 Environment newEnv = new Environment(parentEnv); | 558 Environment newEnv = new Environment(parentEnv ?? new Environment.empty()); |
| 559 |
| 491 List<PositionalValue> positional = args.reversed | 560 List<PositionalValue> positional = args.reversed |
| 492 .where((InterpreterValue av) => av is PositionalValue) | 561 .where((InterpreterValue av) => av is PositionalValue) |
| 493 .toList(); | 562 .toList(); |
| 494 | 563 |
| 495 // Add positional parameters. | 564 // Add positional parameters. |
| 496 for (int i = 0; i < positional.length; ++i) { | 565 for (int i = 0; i < positional.length; ++i) { |
| 497 newEnv.expand(function.positionalParameters[i], positional[i].value); | 566 newEnv = |
| 567 newEnv.extend(function.positionalParameters[i], positional[i].value); |
| 498 } | 568 } |
| 499 | 569 |
| 500 Map<String, Value> named = new Map.fromIterable( | 570 Map<String, Value> named = new Map.fromIterable( |
| 501 args.where((InterpreterValue av) => av is NamedValue), | 571 args.where((InterpreterValue av) => av is NamedValue), |
| 502 key: (NamedValue av) => av.name, | 572 key: (NamedValue av) => av.name, |
| 503 value: (NamedValue av) => av.value); | 573 value: (NamedValue av) => av.value); |
| 504 | 574 |
| 505 // Add named parameters. | 575 // Add named parameters. |
| 506 for (VariableDeclaration v in function.namedParameters) { | 576 for (VariableDeclaration v in function.namedParameters) { |
| 507 newEnv.expand(v, named[v.name.toString()]); | 577 newEnv = newEnv.extend(v, named[v.name.toString()]); |
| 508 } | 578 } |
| 509 | 579 |
| 510 return newEnv; | 580 return newEnv; |
| 511 } | 581 } |
| 512 } | 582 } |
| 513 | 583 |
| 514 /// Represents the application continuation for static invocation. | |
| 515 class StaticInvocationApplication extends ApplicationContinuation { | |
| 516 final FunctionNode function; | |
| 517 final ExpressionContinuation continuation; | |
| 518 | |
| 519 StaticInvocationApplication(this.function, this.continuation); | |
| 520 | |
| 521 Configuration call(List<InterpreterValue> argValues) { | |
| 522 Environment functionEnv = | |
| 523 ApplicationContinuation.createEnvironment(function, argValues); | |
| 524 | |
| 525 State bodyState = new State.initial() | |
| 526 .withExpressionContinuation(continuation) | |
| 527 .withConfiguration(new ExitConfiguration(continuation)) | |
| 528 .withEnvironment(functionEnv); | |
| 529 return new ExecConfiguration(function.body, bodyState); | |
| 530 } | |
| 531 } | |
| 532 | |
| 533 /// Represents the application continuation for constructor invocation applied | |
| 534 /// on the list of evaluated arguments. | |
| 535 class ConstructorInvocationApplication extends ApplicationContinuation { | |
| 536 final Constructor constructor; | |
| 537 final ExpressionContinuation continuation; | |
| 538 | |
| 539 ConstructorInvocationApplication(this.constructor, this.continuation); | |
| 540 | |
| 541 Configuration call(List<InterpreterValue> argValues) { | |
| 542 Environment ctrEnv = ApplicationContinuation.createEnvironment( | |
| 543 constructor.function, argValues); | |
| 544 | |
| 545 var class_ = new Class(constructor.enclosingClass.reference); | |
| 546 var newObject = | |
| 547 new ObjectValue(class_, new List<Value>(class_.instanceSize)); | |
| 548 | |
| 549 return new ObjectInitializationConfiguration( | |
| 550 constructor, | |
| 551 new InstanceEnvironment(newObject, ctrEnv), | |
| 552 new NewInstanceConfiguration(continuation, newObject)); | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 /// Represents the application continuation for redirecting constructor | |
| 557 /// invocation applied on the list of evaluated arguments. | |
| 558 class RedirectingConstructorApplication extends ApplicationContinuation { | |
| 559 final Constructor constructor; | |
| 560 final Environment environment; | |
| 561 final ExecConfiguration configuration; | |
| 562 | |
| 563 RedirectingConstructorApplication( | |
| 564 this.constructor, this.environment, this.configuration); | |
| 565 | |
| 566 Configuration call(List<InterpreterValue> argValues) { | |
| 567 Value object = environment.thisInstance; | |
| 568 Environment ctrEnv = ApplicationContinuation.createEnvironment( | |
| 569 constructor.function, | |
| 570 argValues, | |
| 571 new InstanceEnvironment(object, new Environment.empty())); | |
| 572 | |
| 573 return new ObjectInitializationConfiguration( | |
| 574 constructor, ctrEnv, configuration); | |
| 575 } | |
| 576 } | |
| 577 | |
| 578 /// Represents the application continuation for super constructor | |
| 579 /// invocation applied on the list of evaluated arguments. | |
| 580 class SuperConstructorApplication extends ApplicationContinuation { | |
| 581 final Constructor constructor; | |
| 582 final Environment environment; | |
| 583 final ExecConfiguration configuration; | |
| 584 | |
| 585 SuperConstructorApplication( | |
| 586 this.constructor, this.environment, this.configuration); | |
| 587 | |
| 588 Configuration call(List<InterpreterValue> argValues) { | |
| 589 Value object = environment.thisInstance; | |
| 590 | |
| 591 Environment superEnv = ApplicationContinuation.createEnvironment( | |
| 592 constructor.function, | |
| 593 argValues, | |
| 594 new InstanceEnvironment(object, new Environment.empty())); | |
| 595 | |
| 596 return new ObjectInitializationConfiguration( | |
| 597 constructor, superEnv, configuration); | |
| 598 } | |
| 599 } | |
| 600 | |
| 601 /// Represents the configuration for execution of initializer and | |
| 602 /// constructor body statements for initialization of a newly allocated object. | |
| 603 class ObjectInitializationConfiguration extends Configuration { | |
| 604 final Constructor constructor; | |
| 605 final Environment environment; | |
| 606 final ExecConfiguration configuration; | |
| 607 | |
| 608 ObjectInitializationConfiguration( | |
| 609 this.constructor, this.environment, this.configuration); | |
| 610 | |
| 611 Configuration step(StatementExecuter _) { | |
| 612 if (constructor.initializers.isNotEmpty && | |
| 613 constructor.initializers.last is RedirectingInitializer) { | |
| 614 // Constructor is redirecting. | |
| 615 Initializer initializer = constructor.initializers.first; | |
| 616 if (initializer is RedirectingInitializer) { | |
| 617 var app = new RedirectingConstructorApplication( | |
| 618 initializer.target, environment, configuration); | |
| 619 var args = _createArgumentExpressionList( | |
| 620 initializer.arguments, initializer.target.function); | |
| 621 | |
| 622 return new EvalListConfiguration(args, environment, app); | |
| 623 } | |
| 624 // Redirecting initializer is not the only initializer. | |
| 625 for (Initializer i in constructor.initializers.reversed.skip(1)) { | |
| 626 assert(i is LocalInitializer); | |
| 627 } | |
| 628 var class_ = new Class(constructor.enclosingClass.reference); | |
| 629 var initEnv = new Environment(environment); | |
| 630 var cont = new InitializerContinuation( | |
| 631 class_, initEnv, constructor.initializers, configuration); | |
| 632 return new EvalConfiguration( | |
| 633 (initializer as LocalInitializer).variable.initializer, | |
| 634 initEnv, | |
| 635 cont); | |
| 636 } | |
| 637 | |
| 638 // Set head of configurations to be executed to configuration for current | |
| 639 // constructor body. | |
| 640 var state = new State.initial() | |
| 641 .withEnvironment(environment) | |
| 642 .withConfiguration(configuration); | |
| 643 var bodyConfig = new ExecConfiguration(constructor.function.body, state); | |
| 644 | |
| 645 // Initialize fields in immediately enclosing class. | |
| 646 var cont = | |
| 647 new InstanceFieldsApplication(constructor, environment, bodyConfig); | |
| 648 var fieldExpressions = _createInstanceInitializers(constructor); | |
| 649 | |
| 650 return new EvalListConfiguration( | |
| 651 fieldExpressions, new Environment.empty(), cont); | |
| 652 } | |
| 653 | |
| 654 /// Creates a list of expressions for instance field initializers in | |
| 655 /// immediately enclosing class. | |
| 656 static List<InterpreterExpression> _createInstanceInitializers( | |
| 657 Constructor ctr) { | |
| 658 Class currentClass = new Class(ctr.enclosingClass.reference); | |
| 659 List<InterpreterExpression> es = <InterpreterExpression>[]; | |
| 660 | |
| 661 for (int i = currentClass.superclass?.instanceSize ?? 0; | |
| 662 i < currentClass.instanceSize; | |
| 663 i++) { | |
| 664 Field current = currentClass.instanceFields[i]; | |
| 665 if (current.initializer != null) { | |
| 666 es.add(new FieldInitializerExpression(current, current.initializer)); | |
| 667 } | |
| 668 } | |
| 669 | |
| 670 return es; | |
| 671 } | |
| 672 } | |
| 673 | |
| 674 /// Represents the application continuation applied on the list of evaluated | |
| 675 /// field initializer expressions. | |
| 676 class InstanceFieldsApplication extends ApplicationContinuation { | |
| 677 final Constructor constructor; | |
| 678 final Environment environment; | |
| 679 final ExecConfiguration configuration; | |
| 680 | |
| 681 final Class _currentClass; | |
| 682 final ObjectValue _newObject; | |
| 683 | |
| 684 InstanceFieldsApplication( | |
| 685 this.constructor, this.environment, this.configuration) | |
| 686 : _currentClass = new Class(constructor.enclosingClass.reference), | |
| 687 _newObject = environment.thisInstance; | |
| 688 | |
| 689 Configuration call(List<InterpreterValue> fieldValues) { | |
| 690 for (FieldInitializerValue current in fieldValues.reversed) { | |
| 691 _currentClass.setProperty(_newObject, current.field, current.value); | |
| 692 } | |
| 693 | |
| 694 if (constructor.initializers.isEmpty) { | |
| 695 _initializeNullFields(_currentClass, _newObject); | |
| 696 return configuration; | |
| 697 } | |
| 698 | |
| 699 // Produce next configuration. | |
| 700 if (constructor.initializers.first is SuperInitializer) { | |
| 701 // SuperInitializer appears last in the initializer list. | |
| 702 assert(constructor.initializers.length == 1); | |
| 703 SuperInitializer current = constructor.initializers.first; | |
| 704 var args = _createArgumentExpressionList( | |
| 705 current.arguments, current.target.function); | |
| 706 | |
| 707 var superApp = new SuperConstructorApplication( | |
| 708 current.target, environment, configuration); | |
| 709 _initializeNullFields(_currentClass, _newObject); | |
| 710 return new EvalListConfiguration(args, environment, superApp); | |
| 711 } | |
| 712 | |
| 713 Class class_ = new Class(constructor.enclosingClass.reference); | |
| 714 Environment initEnv = new Environment(environment); | |
| 715 | |
| 716 var cont = new InitializerContinuation( | |
| 717 class_, initEnv, constructor.initializers, configuration); | |
| 718 return new EvalConfiguration( | |
| 719 _getExpression(constructor.initializers.first), initEnv, cont); | |
| 720 } | |
| 721 } | |
| 722 | |
| 723 /// Represents the expression continuation applied on the list of evaluated | |
| 724 /// initializer expressions preceding a super call in the list. | |
| 725 class InitializerContinuation extends ExpressionContinuation { | |
| 726 final Class currentClass; | |
| 727 final Environment initializerEnvironment; | |
| 728 final List<Initializer> initializers; | |
| 729 final ExecConfiguration configuration; | |
| 730 | |
| 731 InitializerContinuation(this.currentClass, this.initializerEnvironment, | |
| 732 this.initializers, this.configuration); | |
| 733 | |
| 734 Configuration call(Value v) { | |
| 735 ObjectValue newObject = initializerEnvironment.thisInstance; | |
| 736 Initializer current = initializers.first; | |
| 737 if (current is FieldInitializer) { | |
| 738 currentClass.setProperty(newObject, current.field, v); | |
| 739 } else if (current is LocalInitializer) { | |
| 740 initializerEnvironment.expand(current.variable, v); | |
| 741 } else { | |
| 742 throw 'Assigning value $v to ${current.runtimeType}'; | |
| 743 } | |
| 744 | |
| 745 if (initializers.length <= 1) { | |
| 746 _initializeNullFields(currentClass, newObject); | |
| 747 return configuration; | |
| 748 } | |
| 749 | |
| 750 Initializer next = initializers[1]; | |
| 751 | |
| 752 if (next is RedirectingInitializer) { | |
| 753 // RedirectingInitializer appears last in the initializer list. | |
| 754 assert(initializers.length == 2); | |
| 755 var app = new RedirectingConstructorApplication( | |
| 756 next.target, initializerEnvironment, configuration); | |
| 757 var args = | |
| 758 _createArgumentExpressionList(next.arguments, next.target.function); | |
| 759 return new EvalListConfiguration(args, initializerEnvironment, app); | |
| 760 } | |
| 761 | |
| 762 if (next is SuperInitializer) { | |
| 763 // SuperInitializer appears last in the initializer list. | |
| 764 assert(initializers.length == 2); | |
| 765 var args = | |
| 766 _createArgumentExpressionList(next.arguments, next.target.function); | |
| 767 var superApp = new SuperConstructorApplication( | |
| 768 next.target, initializerEnvironment, configuration); | |
| 769 _initializeNullFields(currentClass, newObject); | |
| 770 return new EvalListConfiguration(args, initializerEnvironment, superApp); | |
| 771 } | |
| 772 | |
| 773 var cont = new InitializerContinuation(currentClass, initializerEnvironment, | |
| 774 initializers.skip(1).toList(), configuration); | |
| 775 return new EvalConfiguration( | |
| 776 _getExpression(next), initializerEnvironment, cont); | |
| 777 } | |
| 778 } | |
| 779 | |
| 780 /// Represents the application continuation called after the evaluation of all | 584 /// Represents the application continuation called after the evaluation of all |
| 781 /// argument expressions for an invocation. | 585 /// argument expressions for an invocation. |
| 782 class ValueApplication extends ApplicationContinuation { | 586 class ValueA extends ApplicationContinuation { |
| 783 final InterpreterValue value; | 587 final InterpreterValue value; |
| 784 final ApplicationContinuation applicationContinuation; | 588 final ApplicationContinuation applicationContinuation; |
| 785 | 589 |
| 786 ValueApplication(this.value, this.applicationContinuation); | 590 ValueA(this.value, this.applicationContinuation); |
| 787 | 591 |
| 788 Configuration call(List<InterpreterValue> args) { | 592 Configuration call(List<InterpreterValue> args) { |
| 789 args.add(value); | 593 args.add(value); |
| 790 return new ApplicationConfiguration(applicationContinuation, args); | 594 return new ApplicationConfiguration(applicationContinuation, args); |
| 791 } | 595 } |
| 792 } | 596 } |
| 793 | 597 |
| 598 class StringConcatenationA extends ApplicationContinuation { |
| 599 final ExpressionContinuation continuation; |
| 600 |
| 601 StringConcatenationA(this.continuation); |
| 602 |
| 603 Configuration call(List<InterpreterValue> values) { |
| 604 StringBuffer result = new StringBuffer(); |
| 605 for (InterpreterValue v in values.reversed) { |
| 606 result.write(v.value.value); |
| 607 } |
| 608 return new ValuePassingConfiguration( |
| 609 continuation, new StringValue(result.toString())); |
| 610 } |
| 611 } |
| 612 |
| 613 /// Represents the application continuation for static invocation. |
| 614 class StaticInvocationA extends ApplicationContinuation { |
| 615 final FunctionNode function; |
| 616 final ExpressionContinuation continuation; |
| 617 |
| 618 StaticInvocationA(this.function, this.continuation); |
| 619 |
| 620 Configuration call(List<InterpreterValue> argValues) { |
| 621 Environment functionEnv = |
| 622 ApplicationContinuation.createEnvironment(function, argValues); |
| 623 State bodyState = new State( |
| 624 null, continuation, new ExitSK(continuation, Value.nullInstance)); |
| 625 |
| 626 return new ExecConfiguration(function.body, functionEnv, bodyState); |
| 627 } |
| 628 } |
| 629 |
| 630 // ------------------------------------------------------------------------ |
| 631 // Expression Continuations |
| 632 // ------------------------------------------------------------------------ |
| 633 |
| 794 /// Represents an expression continuation. | 634 /// Represents an expression continuation. |
| 635 /// |
| 636 /// There are various kinds of [ExpressionContinuation]s and their names are |
| 637 /// suffixed with "EK". |
| 795 abstract class ExpressionContinuation extends Continuation { | 638 abstract class ExpressionContinuation extends Continuation { |
| 796 Configuration call(Value v); | 639 Configuration call(Value v); |
| 797 } | 640 } |
| 798 | 641 |
| 799 /// Represents a continuation that returns the next [ExecConfiguration] | 642 /// Represents a continuation that returns the next [ExecConfiguration] |
| 800 /// to be executed. | 643 /// to be executed. |
| 801 class ExpressionStatementContinuation extends ExpressionContinuation { | 644 class ExpressionSK extends ExpressionContinuation { |
| 802 final ExecConfiguration configuration; | 645 final StatementContinuation continuation; |
| 646 final Environment environment; |
| 803 | 647 |
| 804 ExpressionStatementContinuation(this.configuration); | 648 ExpressionSK(this.continuation, this.environment); |
| 805 | 649 |
| 806 Configuration call(Value _) { | 650 Configuration call(Value _) { |
| 807 return configuration; | 651 return new ForwardConfiguration(continuation, environment); |
| 808 } | 652 } |
| 809 } | 653 } |
| 810 | 654 |
| 811 class PrintContinuation extends ExpressionContinuation { | 655 class PrintEK extends ExpressionContinuation { |
| 812 final ExpressionContinuation continuation; | 656 final ExpressionContinuation continuation; |
| 813 | 657 |
| 814 PrintContinuation(this.continuation); | 658 PrintEK(this.continuation); |
| 815 | 659 |
| 816 Configuration call(Value v) { | 660 Configuration call(Value v) { |
| 817 log.info('print(${v.value.runtimeType}: ${v.value})\n'); | 661 log.info('print(${v.value.runtimeType}: ${v.value})\n'); |
| 818 print(v.value); | 662 print(v.value); |
| 819 return new ValuePassingConfiguration(continuation, Value.nullInstance); | 663 return new ValuePassingConfiguration(continuation, Value.nullInstance); |
| 820 } | 664 } |
| 821 } | 665 } |
| 822 | 666 |
| 823 class PropertyGetContinuation extends ExpressionContinuation { | 667 class PropertyGetEK extends ExpressionContinuation { |
| 824 final Name name; | 668 final Name name; |
| 825 final ExpressionContinuation continuation; | 669 final ExpressionContinuation continuation; |
| 826 | 670 |
| 827 PropertyGetContinuation(this.name, this.continuation); | 671 PropertyGetEK(this.name, this.continuation); |
| 828 | 672 |
| 829 Configuration call(Value receiver) { | 673 Configuration call(Value receiver) { |
| 830 // TODO: CPS the invocation of the getter. | 674 // TODO: CPS the invocation of the getter. |
| 831 Value propertyValue = receiver.class_.lookupGetter(name)(receiver); | 675 Value propertyValue = receiver.class_.lookupGetter(name)(receiver); |
| 832 return new ValuePassingConfiguration(continuation, propertyValue); | 676 return new ValuePassingConfiguration(continuation, propertyValue); |
| 833 } | 677 } |
| 834 } | 678 } |
| 835 | 679 |
| 836 class PropertySetContinuation extends ExpressionContinuation { | 680 class PropertySetEK extends ExpressionContinuation { |
| 837 final Expression value; | 681 final Expression value; |
| 838 final Name setterName; | 682 final Name setterName; |
| 839 final Environment environment; | 683 final Environment environment; |
| 840 final ExpressionContinuation continuation; | 684 final ExpressionContinuation continuation; |
| 841 | 685 |
| 842 PropertySetContinuation( | 686 PropertySetEK( |
| 843 this.value, this.setterName, this.environment, this.continuation); | 687 this.value, this.setterName, this.environment, this.continuation); |
| 844 | 688 |
| 845 Configuration call(Value receiver) { | 689 Configuration call(Value receiver) { |
| 846 var cont = new SetterContinuation(receiver, setterName, continuation); | 690 var cont = new SetterEK(receiver, setterName, continuation); |
| 847 return new EvalConfiguration(value, environment, cont); | 691 return new EvalConfiguration(value, environment, cont); |
| 848 } | 692 } |
| 849 } | 693 } |
| 850 | 694 |
| 851 class SetterContinuation extends ExpressionContinuation { | 695 class SetterEK extends ExpressionContinuation { |
| 852 final Value receiver; | 696 final Value receiver; |
| 853 final Name name; | 697 final Name name; |
| 854 final ExpressionContinuation continuation; | 698 final ExpressionContinuation continuation; |
| 855 | 699 |
| 856 SetterContinuation(this.receiver, this.name, this.continuation); | 700 SetterEK(this.receiver, this.name, this.continuation); |
| 857 | 701 |
| 858 Configuration call(Value v) { | 702 Configuration call(Value v) { |
| 859 Setter setter = receiver.class_.lookupSetter(name); | 703 Setter setter = receiver.class_.lookupSetter(name); |
| 860 setter(receiver, v); | 704 setter(receiver, v); |
| 861 return new ValuePassingConfiguration(continuation, v); | 705 return new ValuePassingConfiguration(continuation, v); |
| 862 } | 706 } |
| 863 } | 707 } |
| 864 | 708 |
| 865 /// Represents a continuation to be called after the evaluation of an actual | 709 /// Represents a continuation to be called after the evaluation of an actual |
| 866 /// argument for function invocation. | 710 /// argument for function invocation. |
| 867 class ExpressionListContinuation extends ExpressionContinuation { | 711 class ExpressionListEK extends ExpressionContinuation { |
| 868 final InterpreterExpression currentExpression; | 712 final InterpreterExpression currentExpression; |
| 869 final List<InterpreterExpression> expressions; | 713 final List<InterpreterExpression> expressions; |
| 870 final Environment environment; | 714 final Environment environment; |
| 871 final ApplicationContinuation applicationContinuation; | 715 final ApplicationContinuation applicationContinuation; |
| 872 | 716 |
| 873 ExpressionListContinuation(this.currentExpression, this.expressions, | 717 ExpressionListEK(this.currentExpression, this.expressions, this.environment, |
| 874 this.environment, this.applicationContinuation); | 718 this.applicationContinuation); |
| 875 | 719 |
| 876 Configuration call(Value v) { | 720 Configuration call(Value v) { |
| 877 ValueApplication app = new ValueApplication( | 721 ValueA app = |
| 878 currentExpression.assignValue(v), applicationContinuation); | 722 new ValueA(currentExpression.assignValue(v), applicationContinuation); |
| 879 return new EvalListConfiguration(expressions, environment, app); | 723 return new EvalListConfiguration(expressions, environment, app); |
| 880 } | 724 } |
| 881 } | 725 } |
| 882 | 726 |
| 883 class MethodInvocationContinuation extends ExpressionContinuation { | 727 class MethodInvocationEK extends ExpressionContinuation { |
| 884 final Arguments arguments; | 728 final Arguments arguments; |
| 885 final Name methodName; | 729 final Name methodName; |
| 886 final Environment environment; | 730 final Environment environment; |
| 887 final ExpressionContinuation continuation; | 731 final ExpressionContinuation continuation; |
| 888 | 732 |
| 889 MethodInvocationContinuation( | 733 MethodInvocationEK( |
| 890 this.arguments, this.methodName, this.environment, this.continuation); | 734 this.arguments, this.methodName, this.environment, this.continuation); |
| 891 | 735 |
| 892 Configuration call(Value receiver) { | 736 Configuration call(Value receiver) { |
| 893 if (arguments.positional.isEmpty) { | 737 if (arguments.positional.isEmpty) { |
| 894 Value returnValue = receiver.invokeMethod(methodName); | 738 Value returnValue = receiver.invokeMethod(methodName); |
| 895 return new ValuePassingConfiguration(continuation, returnValue); | 739 return new ValuePassingConfiguration(continuation, returnValue); |
| 896 } | 740 } |
| 897 var cont = new ArgumentsContinuation( | 741 var cont = new ArgumentsEK( |
| 898 receiver, methodName, arguments, environment, continuation); | 742 receiver, methodName, arguments, environment, continuation); |
| 899 | 743 |
| 900 return new EvalConfiguration(arguments.positional.first, environment, cont); | 744 return new EvalConfiguration(arguments.positional.first, environment, cont); |
| 901 } | 745 } |
| 902 } | 746 } |
| 903 | 747 |
| 904 class ArgumentsContinuation extends ExpressionContinuation { | 748 class ArgumentsEK extends ExpressionContinuation { |
| 905 final Value receiver; | 749 final Value receiver; |
| 906 final Name methodName; | 750 final Name methodName; |
| 907 final Arguments arguments; | 751 final Arguments arguments; |
| 908 final Environment environment; | 752 final Environment environment; |
| 909 final ExpressionContinuation continuation; | 753 final ExpressionContinuation continuation; |
| 910 | 754 |
| 911 ArgumentsContinuation(this.receiver, this.methodName, this.arguments, | 755 ArgumentsEK(this.receiver, this.methodName, this.arguments, this.environment, |
| 912 this.environment, this.continuation); | 756 this.continuation); |
| 913 | 757 |
| 914 Configuration call(Value value) { | 758 Configuration call(Value value) { |
| 915 // Currently evaluates only one argument, for simple method invocations | 759 // Currently evaluates only one argument, for simple method invocations |
| 916 // with 1 argument. | 760 // with 1 argument. |
| 917 Value returnValue = receiver.invokeMethod(methodName, value); | 761 Value returnValue = receiver.invokeMethod(methodName, value); |
| 918 return new ValuePassingConfiguration(continuation, returnValue); | 762 return new ValuePassingConfiguration(continuation, returnValue); |
| 919 } | 763 } |
| 920 } | 764 } |
| 921 | 765 |
| 922 class VariableSetContinuation extends ExpressionContinuation { | 766 class VariableSetEK extends ExpressionContinuation { |
| 923 final VariableDeclaration variable; | 767 final VariableDeclaration variable; |
| 924 final Environment environment; | 768 final Environment environment; |
| 925 final ExpressionContinuation continuation; | 769 final ExpressionContinuation continuation; |
| 926 | 770 |
| 927 VariableSetContinuation(this.variable, this.environment, this.continuation); | 771 VariableSetEK(this.variable, this.environment, this.continuation); |
| 928 | 772 |
| 929 Configuration call(Value value) { | 773 Configuration call(Value value) { |
| 930 environment.assign(variable, value); | 774 environment.assign(variable, value); |
| 931 return new ValuePassingConfiguration(continuation, value); | 775 return new ValuePassingConfiguration(continuation, value); |
| 932 } | 776 } |
| 933 } | 777 } |
| 934 | 778 |
| 935 class NotContinuation extends ExpressionContinuation { | 779 class NotEK extends ExpressionContinuation { |
| 936 final ExpressionContinuation continuation; | 780 final ExpressionContinuation continuation; |
| 937 | 781 |
| 938 NotContinuation(this.continuation); | 782 NotEK(this.continuation); |
| 939 | 783 |
| 940 Configuration call(Value value) { | 784 Configuration call(Value value) { |
| 941 Value notValue = identical(Value.trueInstance, value) | 785 Value notValue = identical(Value.trueInstance, value) |
| 942 ? Value.falseInstance | 786 ? Value.falseInstance |
| 943 : Value.trueInstance; | 787 : Value.trueInstance; |
| 944 return new ValuePassingConfiguration(continuation, notValue); | 788 return new ValuePassingConfiguration(continuation, notValue); |
| 945 } | 789 } |
| 946 } | 790 } |
| 947 | 791 |
| 948 class OrContinuation extends ExpressionContinuation { | 792 class OrEK extends ExpressionContinuation { |
| 949 final Expression right; | 793 final Expression right; |
| 950 final Environment environment; | 794 final Environment environment; |
| 951 final ExpressionContinuation continuation; | 795 final ExpressionContinuation continuation; |
| 952 | 796 |
| 953 OrContinuation(this.right, this.environment, this.continuation); | 797 OrEK(this.right, this.environment, this.continuation); |
| 954 | 798 |
| 955 Configuration call(Value left) { | 799 Configuration call(Value left) { |
| 956 return identical(Value.trueInstance, left) | 800 return identical(Value.trueInstance, left) |
| 957 ? new ValuePassingConfiguration(continuation, Value.trueInstance) | 801 ? new ValuePassingConfiguration(continuation, Value.trueInstance) |
| 958 : new EvalConfiguration(right, environment, continuation); | 802 : new EvalConfiguration(right, environment, continuation); |
| 959 } | 803 } |
| 960 } | 804 } |
| 961 | 805 |
| 962 class AndContinuation extends ExpressionContinuation { | 806 class AndEK extends ExpressionContinuation { |
| 963 final Expression right; | 807 final Expression right; |
| 964 final Environment environment; | 808 final Environment environment; |
| 965 final ExpressionContinuation continuation; | 809 final ExpressionContinuation continuation; |
| 966 | 810 |
| 967 AndContinuation(this.right, this.environment, this.continuation); | 811 AndEK(this.right, this.environment, this.continuation); |
| 968 | 812 |
| 969 Configuration call(Value left) { | 813 Configuration call(Value left) { |
| 970 return identical(Value.falseInstance, left) | 814 return identical(Value.falseInstance, left) |
| 971 ? new ValuePassingConfiguration(continuation, Value.falseInstance) | 815 ? new ValuePassingConfiguration(continuation, Value.falseInstance) |
| 972 : new EvalConfiguration(right, environment, continuation); | 816 : new EvalConfiguration(right, environment, continuation); |
| 973 } | 817 } |
| 974 } | 818 } |
| 975 | 819 |
| 976 class ConditionalContinuation extends ExpressionContinuation { | 820 class ConditionalEK extends ExpressionContinuation { |
| 977 final Expression then; | 821 final Expression then; |
| 978 final Expression otherwise; | 822 final Expression otherwise; |
| 979 final Environment environment; | 823 final Environment environment; |
| 980 final ExpressionContinuation continuation; | 824 final ExpressionContinuation continuation; |
| 981 | 825 |
| 982 ConditionalContinuation( | 826 ConditionalEK(this.then, this.otherwise, this.environment, this.continuation); |
| 983 this.then, this.otherwise, this.environment, this.continuation); | |
| 984 | 827 |
| 985 Configuration call(Value value) { | 828 Configuration call(Value value) { |
| 986 return identical(Value.trueInstance, value) | 829 return identical(Value.trueInstance, value) |
| 987 ? new EvalConfiguration(then, environment, continuation) | 830 ? new EvalConfiguration(then, environment, continuation) |
| 988 : new EvalConfiguration(otherwise, environment, continuation); | 831 : new EvalConfiguration(otherwise, environment, continuation); |
| 989 } | 832 } |
| 990 } | 833 } |
| 991 | 834 |
| 992 class StringConcatenationContinuation extends ApplicationContinuation { | 835 class LetEK extends ExpressionContinuation { |
| 993 final ExpressionContinuation continuation; | |
| 994 | |
| 995 StringConcatenationContinuation(this.continuation); | |
| 996 | |
| 997 Configuration call(List<InterpreterValue> values) { | |
| 998 StringBuffer result = new StringBuffer(); | |
| 999 for (InterpreterValue v in values.reversed) { | |
| 1000 result.write(v.value.value); | |
| 1001 } | |
| 1002 return new ValuePassingConfiguration( | |
| 1003 continuation, new StringValue(result.toString())); | |
| 1004 } | |
| 1005 } | |
| 1006 | |
| 1007 class LetContinuation extends ExpressionContinuation { | |
| 1008 final VariableDeclaration variable; | 836 final VariableDeclaration variable; |
| 1009 final Expression letBody; | 837 final Expression letBody; |
| 1010 final Environment environment; | 838 final Environment environment; |
| 1011 final ExpressionContinuation continuation; | 839 final ExpressionContinuation continuation; |
| 1012 | 840 |
| 1013 LetContinuation( | 841 LetEK(this.variable, this.letBody, this.environment, this.continuation); |
| 1014 this.variable, this.letBody, this.environment, this.continuation); | |
| 1015 | 842 |
| 1016 Configuration call(Value value) { | 843 Configuration call(Value value) { |
| 1017 var letEnv = new Environment(environment); | 844 var letEnv = new Environment(environment); |
| 1018 letEnv.expand(variable, value); | 845 letEnv.extend(variable, value); |
| 1019 return new EvalConfiguration(letBody, letEnv, continuation); | 846 return new EvalConfiguration(letBody, letEnv, continuation); |
| 1020 } | 847 } |
| 1021 } | 848 } |
| 1022 | 849 |
| 1023 /// Represents the continuation for the condition expression in [WhileStatement]
. | 850 /// Represents the continuation for the condition expression in [WhileStatement]
. |
| 1024 class WhileConditionContinuation extends ExpressionContinuation { | 851 class WhileConditionEK extends ExpressionContinuation { |
| 1025 final WhileStatement node; | 852 final Expression condition; |
| 853 final Statement body; |
| 854 final Environment enclosingEnv; |
| 1026 final State state; | 855 final State state; |
| 1027 | 856 |
| 1028 WhileConditionContinuation(this.node, this.state); | 857 WhileConditionEK(this.condition, this.body, this.enclosingEnv, this.state); |
| 1029 | 858 |
| 1030 ExecConfiguration call(Value v) { | 859 Configuration call(Value v) { |
| 1031 if (identical(v, Value.trueInstance)) { | 860 if (identical(v, Value.falseInstance)) { |
| 1032 // Add configuration for the While statement to the linked list. | 861 return new ForwardConfiguration(state.continuation, enclosingEnv); |
| 1033 ExecConfiguration config = new ExecConfiguration(node, state); | |
| 1034 // Configuration for the body of the loop. | |
| 1035 return new ExecConfiguration(node.body, state.withConfiguration(config)); | |
| 1036 } | 862 } |
| 1037 | 863 var cont = new WhileConditionSK(condition, body, enclosingEnv, state); |
| 1038 return state.statementConfiguration; | 864 return new ExecConfiguration( |
| 865 body, enclosingEnv, state.withContinuation(cont)); |
| 1039 } | 866 } |
| 1040 } | 867 } |
| 1041 | 868 |
| 1042 /// Represents the continuation for the condition expression in [IfStatement]. | 869 /// Represents the continuation for the condition expression in [IfStatement]. |
| 1043 class IfConditionContinuation extends ExpressionContinuation { | 870 class IfConditionEK extends ExpressionContinuation { |
| 1044 final Statement then; | 871 final Statement then; |
| 1045 final Statement otherwise; | 872 final Statement otherwise; |
| 873 final Environment environment; |
| 1046 final State state; | 874 final State state; |
| 1047 | 875 |
| 1048 IfConditionContinuation(this.then, this.otherwise, this.state); | 876 IfConditionEK(this.then, this.otherwise, this.environment, this.state); |
| 1049 | 877 |
| 1050 ExecConfiguration call(Value v) { | 878 Configuration call(Value v) { |
| 1051 if (identical(v, Value.trueInstance)) { | 879 if (identical(v, Value.trueInstance)) { |
| 1052 log.info("if-then\n"); | 880 log.info("if-then\n"); |
| 1053 return new ExecConfiguration(then, state); | 881 return new ExecConfiguration(then, environment, state); |
| 1054 } else if (otherwise != null) { | 882 } else if (otherwise != null) { |
| 1055 log.info("if-otherwise\n"); | 883 log.info("if-otherwise\n"); |
| 1056 return new ExecConfiguration(otherwise, state); | 884 return new ExecConfiguration(otherwise, environment, state); |
| 1057 } | 885 } |
| 1058 return state.statementConfiguration; | 886 return new ForwardConfiguration(state.continuation, environment); |
| 1059 } | 887 } |
| 1060 } | 888 } |
| 1061 | 889 |
| 1062 /// Represents the continuation for the initializer expression in | 890 /// Represents the continuation for the initializer expression in |
| 1063 /// [VariableDeclaration]. | 891 /// [VariableDeclaration]. |
| 1064 class VariableInitializerContinuation extends ExpressionContinuation { | 892 class VariableInitializerEK extends ExpressionContinuation { |
| 1065 final VariableDeclaration variable; | 893 final VariableDeclaration variable; |
| 1066 final Environment environment; | 894 final Environment environment; |
| 1067 final ExecConfiguration nextConfiguration; | 895 final StatementContinuation continuation; |
| 1068 | 896 |
| 1069 VariableInitializerContinuation( | 897 VariableInitializerEK(this.variable, this.environment, this.continuation); |
| 1070 this.variable, this.environment, this.nextConfiguration); | |
| 1071 | 898 |
| 1072 ExecConfiguration call(Value v) { | 899 Configuration call(Value v) { |
| 1073 environment.expand(variable, v); | 900 return new ForwardConfiguration( |
| 1074 return nextConfiguration; | 901 continuation, environment.extend(variable, v)); |
| 1075 } | 902 } |
| 1076 } | 903 } |
| 1077 | 904 |
| 1078 /// Executes statements. | 905 /// Executes statements. |
| 1079 /// | 906 /// |
| 1080 /// Execution of a statement completes in one of the following ways: | 907 /// Execution of a statement completes in one of the following ways: |
| 1081 /// - it completes normally, in which case the execution proceeds to applying | 908 /// - it completes normally, in which case the execution proceeds to applying |
| 1082 /// the next continuation | 909 /// the next continuation |
| 1083 /// - it breaks with a label, in which case the corresponding continuation is | 910 /// - it breaks with a label, in which case the corresponding continuation is |
| 1084 /// returned and applied | 911 /// returned and applied |
| 1085 /// - it returns with or without value, TBD | 912 /// - it returns with or without value, TBD |
| 1086 /// - it throws, TBD | 913 /// - it throws, TBD |
| 1087 class StatementExecuter extends StatementVisitor1<Configuration, State> { | 914 class StatementExecuter |
| 915 extends StatementVisitor1<Configuration, ExecConfiguration> { |
| 1088 Evaluator evaluator = new Evaluator(); | 916 Evaluator evaluator = new Evaluator(); |
| 1089 | 917 |
| 1090 void trampolinedExecution(Configuration configuration) { | 918 void trampolinedExecution(Configuration configuration) { |
| 1091 while (configuration != null) { | 919 while (configuration != null) { |
| 1092 configuration = configuration.step(this); | 920 configuration = configuration.step(this); |
| 1093 } | 921 } |
| 922 ; |
| 1094 } | 923 } |
| 1095 | 924 |
| 1096 Configuration exec(Statement statement, State state) => | 925 Configuration exec(Statement statement, ExecConfiguration conf) => |
| 1097 statement.accept1(this, state); | 926 statement.accept1(this, conf); |
| 1098 Configuration eval(Expression expression, EvalConfiguration config) => | 927 Configuration eval(Expression expression, EvalConfiguration config) => |
| 1099 evaluator.eval(expression, config); | 928 evaluator.eval(expression, config); |
| 1100 Configuration evalList( | 929 Configuration evalList( |
| 1101 List<InterpreterExpression> es, Environment env, Continuation cont) => | 930 List<InterpreterExpression> es, Environment env, Continuation cont) => |
| 1102 evaluator.evalList(es, env, cont); | 931 evaluator.evalList(es, env, cont); |
| 1103 | 932 |
| 1104 Configuration defaultStatement(Statement node, State state) { | 933 Configuration defaultStatement(Statement node, ExecConfiguration conf) { |
| 1105 throw notImplemented( | 934 throw notImplemented( |
| 1106 m: "Execution is not implemented for statement:\n$node "); | 935 m: "Execution is not implemented for statement:\n$node "); |
| 1107 } | 936 } |
| 1108 | 937 |
| 1109 Configuration visitInvalidStatement(InvalidStatement node, State state) { | 938 Configuration visitInvalidStatement( |
| 939 InvalidStatement node, ExecConfiguration conf) { |
| 1110 throw "Invalid statement at ${node.location}"; | 940 throw "Invalid statement at ${node.location}"; |
| 1111 } | 941 } |
| 1112 | 942 |
| 1113 Configuration visitExpressionStatement( | 943 Configuration visitExpressionStatement( |
| 1114 ExpressionStatement node, State state) { | 944 ExpressionStatement node, ExecConfiguration conf) { |
| 1115 var cont = | 945 var cont = new ExpressionSK(conf.state.continuation, conf.environment); |
| 1116 new ExpressionStatementContinuation(state.statementConfiguration); | 946 return new EvalConfiguration(node.expression, conf.environment, cont); |
| 1117 return new EvalConfiguration(node.expression, state.environment, cont); | |
| 1118 } | 947 } |
| 1119 | 948 |
| 1120 Configuration visitBlock(Block node, State state) { | 949 Configuration visitBlock(Block node, ExecConfiguration conf) { |
| 1121 if (node.statements.isEmpty) { | 950 if (node.statements.isEmpty) { |
| 1122 return state.statementConfiguration; | 951 return new ForwardConfiguration( |
| 952 conf.state.continuation, conf.environment); |
| 1123 } | 953 } |
| 1124 State blockState = | 954 |
| 1125 state.withEnvironment(new Environment(state.environment)); | 955 var env = new Environment(conf.environment); |
| 1126 ExecConfiguration configuration = state.statementConfiguration; | 956 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); |
| 1127 for (Statement s in node.statements.reversed) { | 957 return new ExecConfiguration(node.statements.first, env, |
| 1128 configuration = | 958 new State(conf.state.labels, conf.state.returnContinuation, cont)); |
| 1129 new ExecConfiguration(s, blockState.withConfiguration(configuration)); | |
| 1130 } | |
| 1131 return configuration; | |
| 1132 } | 959 } |
| 1133 | 960 |
| 1134 Configuration visitEmptyStatement(EmptyStatement node, State state) { | 961 Configuration visitEmptyStatement( |
| 1135 return state.statementConfiguration; | 962 EmptyStatement node, ExecConfiguration conf) { |
| 963 return new ForwardConfiguration(conf.state.continuation, conf.environment); |
| 1136 } | 964 } |
| 1137 | 965 |
| 1138 Configuration visitIfStatement(IfStatement node, State state) { | 966 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { |
| 1139 var cont = new IfConditionContinuation(node.then, node.otherwise, state); | 967 var cont = new IfConditionEK( |
| 968 node.then, node.otherwise, conf.environment, conf.state); |
| 1140 | 969 |
| 1141 return new EvalConfiguration(node.condition, state.environment, cont); | 970 return new EvalConfiguration(node.condition, conf.environment, cont); |
| 1142 } | 971 } |
| 1143 | 972 |
| 1144 Configuration visitLabeledStatement(LabeledStatement node, State state) { | 973 Configuration visitLabeledStatement( |
| 1145 return new ExecConfiguration(node.body, state.withBreak(node)); | 974 LabeledStatement node, ExecConfiguration conf) { |
| 975 var l = new Label( |
| 976 node, conf.environment, conf.state.continuation, conf.state.labels); |
| 977 return new ExecConfiguration(node.body, conf.environment, |
| 978 new State(l, conf.state.returnContinuation, conf.state.continuation)); |
| 1146 } | 979 } |
| 1147 | 980 |
| 1148 Configuration visitBreakStatement(BreakStatement node, State state) { | 981 Configuration visitBreakStatement( |
| 1149 return state.lookupLabel(node.target).configuration; | 982 BreakStatement node, ExecConfiguration conf) { |
| 983 Label l = conf.state.lookupLabel(node.target); |
| 984 return new ForwardConfiguration(l.continuation, l.environment); |
| 1150 } | 985 } |
| 1151 | 986 |
| 1152 Configuration visitWhileStatement(WhileStatement node, State state) { | 987 Configuration visitWhileStatement( |
| 1153 var cont = new WhileConditionContinuation(node, state); | 988 WhileStatement node, ExecConfiguration conf) { |
| 989 var cont = new WhileConditionEK( |
| 990 node.condition, node.body, conf.environment, conf.state); |
| 1154 | 991 |
| 1155 return new EvalConfiguration(node.condition, state.environment, cont); | 992 return new EvalConfiguration(node.condition, conf.environment, cont); |
| 1156 } | 993 } |
| 1157 | 994 |
| 1158 Configuration visitDoStatement(DoStatement node, State state) { | 995 Configuration visitDoStatement(DoStatement node, ExecConfiguration conf) { |
| 1159 WhileStatement whileStatement = | 996 var cont = new WhileConditionSK( |
| 1160 new WhileStatement(node.condition, node.body); | 997 node.condition, node.body, conf.environment, conf.state); |
| 1161 ExecConfiguration configuration = | |
| 1162 new ExecConfiguration(whileStatement, state); | |
| 1163 | 998 |
| 1164 return new ExecConfiguration( | 999 return new ExecConfiguration(node.body, conf.environment, |
| 1165 node.body, state.withConfiguration(configuration)); | 1000 new State(conf.state.labels, conf.state.returnContinuation, cont)); |
| 1166 } | 1001 } |
| 1167 | 1002 |
| 1168 Configuration visitReturnStatement(ReturnStatement node, State state) { | 1003 Configuration visitReturnStatement( |
| 1169 assert(state.returnContinuation != null); | 1004 ReturnStatement node, ExecConfiguration conf) { |
| 1005 assert(conf.state.returnContinuation != null); |
| 1170 log.info('return\n'); | 1006 log.info('return\n'); |
| 1171 if (node.expression == null) { | 1007 if (node.expression == null) { |
| 1172 return new ValuePassingConfiguration( | 1008 return new ValuePassingConfiguration( |
| 1173 state.returnContinuation, Value.nullInstance); | 1009 conf.state.returnContinuation, Value.nullInstance); |
| 1174 } | 1010 } |
| 1175 | 1011 |
| 1176 return new EvalConfiguration( | 1012 return new EvalConfiguration( |
| 1177 node.expression, state.environment, state.returnContinuation); | 1013 node.expression, conf.environment, conf.state.returnContinuation); |
| 1178 } | 1014 } |
| 1179 | 1015 |
| 1180 Configuration visitVariableDeclaration( | 1016 Configuration visitVariableDeclaration( |
| 1181 VariableDeclaration node, State state) { | 1017 VariableDeclaration node, ExecConfiguration conf) { |
| 1182 if (node.initializer != null) { | 1018 if (node.initializer != null) { |
| 1183 var cont = new VariableInitializerContinuation( | 1019 var cont = new VariableInitializerEK( |
| 1184 node, state.environment, state.statementConfiguration); | 1020 node, conf.environment, conf.state.continuation); |
| 1185 return new EvalConfiguration(node.initializer, state.environment, cont); | 1021 return new EvalConfiguration(node.initializer, conf.environment, cont); |
| 1186 } | 1022 } |
| 1187 state.environment.expand(node, Value.nullInstance); | 1023 return new ForwardConfiguration(conf.state.continuation, |
| 1188 return state.statementConfiguration; | 1024 conf.environment.extend(node, Value.nullInstance)); |
| 1189 } | 1025 } |
| 1190 } | 1026 } |
| 1191 | 1027 |
| 1192 // ------------------------------------------------------------------------ | 1028 // ------------------------------------------------------------------------ |
| 1193 // VALUES | 1029 // VALUES |
| 1194 // ------------------------------------------------------------------------ | 1030 // ------------------------------------------------------------------------ |
| 1195 | 1031 |
| 1196 typedef Value Getter(Value receiver); | 1032 typedef Value Getter(Value receiver); |
| 1197 typedef void Setter(Value receiver, Value value); | 1033 typedef void Setter(Value receiver, Value value); |
| 1198 | 1034 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1476 void _initializeNullFields(Class class_, ObjectValue newObject) { | 1312 void _initializeNullFields(Class class_, ObjectValue newObject) { |
| 1477 int superClassSize = class_.superclass?.instanceSize ?? 0; | 1313 int superClassSize = class_.superclass?.instanceSize ?? 0; |
| 1478 for (int i = superClassSize; i < class_.instanceSize; i++) { | 1314 for (int i = superClassSize; i < class_.instanceSize; i++) { |
| 1479 Field field = class_.instanceFields[i]; | 1315 Field field = class_.instanceFields[i]; |
| 1480 if (class_.getProperty(newObject, field) == null) { | 1316 if (class_.getProperty(newObject, field) == null) { |
| 1481 assert(field.initializer == null); | 1317 assert(field.initializer == null); |
| 1482 class_.setProperty(newObject, field, Value.nullInstance); | 1318 class_.setProperty(newObject, field, Value.nullInstance); |
| 1483 } | 1319 } |
| 1484 } | 1320 } |
| 1485 } | 1321 } |
| OLD | NEW |