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