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'; |
11 | 11 |
12 class NotImplemented { | 12 class NotImplemented { |
13 String message; | 13 String message; |
14 | 14 |
15 NotImplemented(this.message); | 15 NotImplemented(this.message); |
16 | 16 |
17 String toString() => message; | 17 String toString() => message; |
18 } | 18 } |
19 | 19 |
20 class Interpreter { | 20 class Interpreter { |
21 Program program; | 21 Program program; |
22 StatementExecuter visitor = new StatementExecuter(); | 22 StatementExecuter visitor = new StatementExecuter(); |
23 | 23 |
| 24 // The execution of the program starts with empty main environment. |
| 25 static MainEnvironment mainEnvironment = |
| 26 new MainEnvironment(<Member, Location>{}); |
| 27 |
24 Interpreter(this.program); | 28 Interpreter(this.program); |
25 | 29 |
26 void run() { | 30 void run() { |
27 assert(program.libraries.isEmpty); | 31 assert(program.libraries.isEmpty); |
28 Procedure mainMethod = program.mainMethod; | 32 Procedure mainMethod = program.mainMethod; |
29 | 33 |
30 if (mainMethod == null) return; | 34 if (mainMethod == null) return; |
31 | 35 |
32 Statement statementBlock = mainMethod.function.body; | 36 Statement statementBlock = mainMethod.function.body; |
33 ExecConfiguration configuration = new ExecConfiguration( | 37 ExecConfiguration configuration = new ExecConfiguration( |
34 statementBlock, new Environment.empty(), new State.initial()); | 38 statementBlock, new Environment.empty(), new State.initial()); |
35 visitor.trampolinedExecution(configuration); | 39 visitor.trampolinedExecution(configuration); |
36 } | 40 } |
37 } | 41 } |
38 | 42 |
39 class Location { | 43 class Location { |
40 Value value; | 44 Value value; |
41 | 45 |
42 Location.empty(); | 46 Location.empty(); |
43 Location(this.value); | 47 Location(this.value); |
44 } | 48 } |
45 | 49 |
46 class Binding { | 50 class Binding { |
47 final VariableDeclaration variable; | 51 final VariableDeclaration variable; |
48 final Location location; | 52 final Location location; |
49 | 53 |
50 Binding(this.variable, this.location); | 54 Binding(this.variable, this.location); |
51 } | 55 } |
52 | 56 |
| 57 /// Represents the top level environment that binds previously accessed or set |
| 58 /// static fields to the location that stores their value. |
| 59 class MainEnvironment { |
| 60 final Map<Member, Location> _staticFields; |
| 61 |
| 62 MainEnvironment(this._staticFields); |
| 63 |
| 64 bool contains(Member member) => _staticFields[member] != null; |
| 65 |
| 66 Value lookup(Member member) { |
| 67 assert(contains(member)); |
| 68 return _staticFields[member].value; |
| 69 } |
| 70 |
| 71 void updateStore(Member member, Value value) { |
| 72 assert(contains(member)); |
| 73 _staticFields[member].value = value; |
| 74 } |
| 75 |
| 76 MainEnvironment extend(Member member, Value value) { |
| 77 var newMap = new Map<Member, Location>.from(_staticFields); |
| 78 newMap[member] = new Location(value); |
| 79 return new MainEnvironment(newMap); |
| 80 } |
| 81 } |
| 82 |
53 class Environment { | 83 class Environment { |
54 final List<Binding> bindings = <Binding>[]; | 84 final List<Binding> bindings = <Binding>[]; |
55 final Environment parent; | 85 final Environment parent; |
56 | 86 |
57 Value get thisInstance { | 87 Value get thisInstance { |
58 return containsThis() | 88 return containsThis() |
59 ? lookupThis().value | 89 ? lookupThis().value |
60 : throw "Invalid reference to 'this' expression"; | 90 : throw "Invalid reference to 'this' expression"; |
61 } | 91 } |
62 | 92 |
(...skipping 27 matching lines...) Expand all Loading... |
90 for (Binding b in bindings) { | 120 for (Binding b in bindings) { |
91 if (identical(b.variable.name, 'this')) return b.location; | 121 if (identical(b.variable.name, 'this')) return b.location; |
92 } | 122 } |
93 return parent.lookupThis(); | 123 return parent.lookupThis(); |
94 } | 124 } |
95 | 125 |
96 Value lookup(VariableDeclaration variable) { | 126 Value lookup(VariableDeclaration variable) { |
97 return lookupBinding(variable).location.value; | 127 return lookupBinding(variable).location.value; |
98 } | 128 } |
99 | 129 |
100 void assign(VariableDeclaration variable, Value value) { | 130 void updateStore(VariableDeclaration variable, Value value) { |
101 assert(contains(variable)); | 131 assert(contains(variable)); |
102 lookupBinding(variable).location.value = value; | 132 lookupBinding(variable).location.value = value; |
103 } | 133 } |
104 | 134 |
105 Environment extend(VariableDeclaration variable, Value value) { | 135 Environment extend(VariableDeclaration variable, Value value) { |
106 assert(!contains(variable)); | 136 assert(!contains(variable)); |
107 return new Environment(this) | 137 return new Environment(this) |
108 ..bindings.add(new Binding(variable, new Location(value))); | 138 ..bindings.add(new Binding(variable, new Location(value))); |
109 } | 139 } |
110 | 140 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 node.receiver, config.environment, config.exceptionComponents, cont); | 190 node.receiver, config.environment, config.exceptionComponents, cont); |
161 } | 191 } |
162 | 192 |
163 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { | 193 Configuration visitPropertySet(PropertySet node, EvalConfiguration config) { |
164 var cont = new PropertySetEK(node.value, node.name, config.environment, | 194 var cont = new PropertySetEK(node.value, node.name, config.environment, |
165 config.exceptionComponents, config.continuation); | 195 config.exceptionComponents, config.continuation); |
166 return new EvalConfiguration( | 196 return new EvalConfiguration( |
167 node.receiver, config.environment, config.exceptionComponents, cont); | 197 node.receiver, config.environment, config.exceptionComponents, cont); |
168 } | 198 } |
169 | 199 |
170 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) => | 200 Configuration visitStaticGet(StaticGet node, EvalConfiguration config) { |
171 defaultExpression(node, config); | 201 Member member = node.target; |
172 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) => | 202 |
173 defaultExpression(node, config); | 203 if (member is Procedure && !member.isAccessor) { |
| 204 // Create a closure for the method tear off. |
| 205 var v = new FunctionValue(member.function, new Environment.empty()); |
| 206 return new ValuePassingConfiguration(config.continuation, v); |
| 207 } |
| 208 |
| 209 if (member is Procedure && member.isGetter) { |
| 210 // Execute the body of the getter. |
| 211 var state = new State.initial() |
| 212 .withReturnContinuation(config.continuation) |
| 213 .withContinuation(new ExitSK(config.continuation, Value.nullInstance)) |
| 214 .withException(config.exceptionComponents); |
| 215 return new ExecConfiguration( |
| 216 member.function.body, new Environment.empty(), state); |
| 217 } |
| 218 |
| 219 assert(member is Field); |
| 220 if (Interpreter.mainEnvironment.contains(member)) { |
| 221 // Read the value for the member in the main environment. |
| 222 return new ValuePassingConfiguration( |
| 223 config.continuation, Interpreter.mainEnvironment.lookup(member)); |
| 224 } |
| 225 |
| 226 // Otherwise, the static field is accessed for the first time. |
| 227 // We extend the main environment with a new binding. |
| 228 Interpreter.mainEnvironment = |
| 229 Interpreter.mainEnvironment.extend(member, Value.nullInstance); |
| 230 |
| 231 if ((member as Field).initializer == null) { |
| 232 return new ValuePassingConfiguration( |
| 233 config.continuation, Value.nullInstance); |
| 234 } |
| 235 |
| 236 // The initializer expression is evaluated otherwise. |
| 237 var cont = new StaticSetEK(member, config.continuation); |
| 238 return new EvalConfiguration((member as Field).initializer, |
| 239 new Environment.empty(), config.exceptionComponents, cont); |
| 240 } |
| 241 |
| 242 Configuration visitStaticSet(StaticSet node, EvalConfiguration config) { |
| 243 Member member = node.target; |
| 244 ExpressionContinuation cont; |
| 245 |
| 246 if (member is Procedure) { |
| 247 assert(member.isSetter); |
| 248 cont = new StaticSetterEK( |
| 249 member.function, config.exceptionComponents, config.continuation); |
| 250 } else { |
| 251 assert(member is Field); |
| 252 cont = new StaticSetEK(member, config.continuation); |
| 253 } |
| 254 |
| 255 return new EvalConfiguration( |
| 256 node.value, config.environment, config.exceptionComponents, cont); |
| 257 } |
174 | 258 |
175 Configuration visitStaticInvocation( | 259 Configuration visitStaticInvocation( |
176 StaticInvocation node, EvalConfiguration config) { | 260 StaticInvocation node, EvalConfiguration config) { |
177 if ('print' == node.name.toString()) { | 261 if ('print' == node.name.toString()) { |
178 var cont = new PrintEK(config.continuation); | 262 var cont = new PrintEK(config.continuation); |
179 return new EvalConfiguration(node.arguments.positional.first, | 263 return new EvalConfiguration(node.arguments.positional.first, |
180 config.environment, config.exceptionComponents, cont); | 264 config.environment, config.exceptionComponents, cont); |
181 } else { | 265 } else { |
182 log.info('static-invocation-${node.target.name.toString()}\n'); | 266 log.info('static-invocation-${node.target.name.toString()}\n'); |
183 | 267 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 config.continuation, config.environment.thisInstance); | 340 config.continuation, config.environment.thisInstance); |
257 } | 341 } |
258 | 342 |
259 Configuration visitThrow(Throw node, EvalConfiguration config) { | 343 Configuration visitThrow(Throw node, EvalConfiguration config) { |
260 var cont = new ThrowEK(config.exceptionComponents); | 344 var cont = new ThrowEK(config.exceptionComponents); |
261 | 345 |
262 return new EvalConfiguration( | 346 return new EvalConfiguration( |
263 node.expression, config.environment, config.exceptionComponents, cont); | 347 node.expression, config.environment, config.exceptionComponents, cont); |
264 } | 348 } |
265 | 349 |
| 350 Configuration visitFunctionExpression( |
| 351 FunctionExpression node, EvalConfiguration config) { |
| 352 var val = new FunctionValue(node.function, config.environment); |
| 353 return new ValuePassingConfiguration(config.continuation, val); |
| 354 } |
| 355 |
266 // Evaluation of BasicLiterals. | 356 // Evaluation of BasicLiterals. |
267 Configuration visitStringLiteral( | 357 Configuration visitStringLiteral( |
268 StringLiteral node, EvalConfiguration config) { | 358 StringLiteral node, EvalConfiguration config) { |
269 return new ValuePassingConfiguration( | 359 return new ValuePassingConfiguration( |
270 config.continuation, new StringValue(node.value)); | 360 config.continuation, new StringValue(node.value)); |
271 } | 361 } |
272 | 362 |
273 Configuration visitIntLiteral(IntLiteral node, EvalConfiguration config) { | 363 Configuration visitIntLiteral(IntLiteral node, EvalConfiguration config) { |
274 return new ValuePassingConfiguration( | 364 return new ValuePassingConfiguration( |
275 config.continuation, new IntValue(node.value)); | 365 config.continuation, new IntValue(node.value)); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 } | 498 } |
409 | 499 |
410 /// Configuration for execution of a [Statement]. | 500 /// Configuration for execution of a [Statement]. |
411 class ExecConfiguration extends Configuration { | 501 class ExecConfiguration extends Configuration { |
412 final Statement currentStatement; | 502 final Statement currentStatement; |
413 final Environment environment; | 503 final Environment environment; |
414 final State state; | 504 final State state; |
415 | 505 |
416 ExecConfiguration(this.currentStatement, this.environment, this.state); | 506 ExecConfiguration(this.currentStatement, this.environment, this.state); |
417 | 507 |
418 Configuration step(StatementExecuter executer) => | 508 Configuration step(StatementExecuter executer) { |
419 executer.exec(currentStatement, this); | 509 return executer.exec(currentStatement, this); |
| 510 } |
420 } | 511 } |
421 | 512 |
422 /// Configuration for applying a [StatementContinuation] to an [Environment]. | 513 /// Configuration for applying a [StatementContinuation] to an [Environment]. |
423 class ForwardConfiguration extends Configuration { | 514 class ForwardConfiguration extends Configuration { |
424 final StatementContinuation continuation; | 515 final StatementContinuation continuation; |
425 final Environment environment; | 516 final Environment environment; |
426 | 517 |
427 ForwardConfiguration(this.continuation, this.environment); | 518 ForwardConfiguration(this.continuation, this.environment); |
428 | 519 |
429 Configuration step(StatementExecuter _) => continuation?.call(environment); | 520 Configuration step(StatementExecuter _) => continuation?.call(environment); |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 ? initializer.value | 976 ? initializer.value |
886 : (initializer as LocalInitializer).variable.initializer; | 977 : (initializer as LocalInitializer).variable.initializer; |
887 | 978 |
888 // We start with index = 0 since we are evaluating the expression for the | 979 // We start with index = 0 since we are evaluating the expression for the |
889 // first initializer in the initializer list. | 980 // first initializer in the initializer list. |
890 var cont = new InitializerListEK(constructor, 0, location, environment, | 981 var cont = new InitializerListEK(constructor, 0, location, environment, |
891 exceptionComponents, continuation); | 982 exceptionComponents, continuation); |
892 return new EvalConfiguration(expr, environment, exceptionComponents, cont); | 983 return new EvalConfiguration(expr, environment, exceptionComponents, cont); |
893 } | 984 } |
894 } | 985 } |
| 986 |
| 987 class FunctionValueA extends ApplicationContinuation { |
| 988 final FunctionValue receiver; |
| 989 final ExceptionComponents exceptionComponents; |
| 990 final ExpressionContinuation returnContinuation; |
| 991 |
| 992 FunctionValueA( |
| 993 this.receiver, this.exceptionComponents, this.returnContinuation); |
| 994 |
| 995 Configuration call(List<InterpreterValue> vs) { |
| 996 Environment env = ApplicationContinuation.createEnvironment( |
| 997 receiver.function, vs, receiver.environment); |
| 998 var scont = new ExitSK(returnContinuation, Value.nullInstance); |
| 999 var state = new State(null, exceptionComponents, returnContinuation, scont); |
| 1000 return new ExecConfiguration(receiver.function.body, env, state); |
| 1001 } |
| 1002 } |
| 1003 |
895 // ------------------------------------------------------------------------ | 1004 // ------------------------------------------------------------------------ |
896 // Expression Continuations | 1005 // Expression Continuations |
897 // ------------------------------------------------------------------------ | 1006 // ------------------------------------------------------------------------ |
898 | 1007 |
899 /// Represents an expression continuation. | 1008 /// Represents an expression continuation. |
900 /// | 1009 /// |
901 /// There are various kinds of [ExpressionContinuation]s and their names are | 1010 /// There are various kinds of [ExpressionContinuation]s and their names are |
902 /// suffixed with "EK". | 1011 /// suffixed with "EK". |
903 abstract class ExpressionContinuation extends Continuation { | 1012 abstract class ExpressionContinuation extends Continuation { |
904 Configuration call(Value v); | 1013 Configuration call(Value v); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 | 1073 |
965 SetterEK(this.receiver, this.name, this.continuation); | 1074 SetterEK(this.receiver, this.name, this.continuation); |
966 | 1075 |
967 Configuration call(Value v) { | 1076 Configuration call(Value v) { |
968 Setter setter = receiver.class_.lookupImplicitSetter(name); | 1077 Setter setter = receiver.class_.lookupImplicitSetter(name); |
969 setter(receiver, v); | 1078 setter(receiver, v); |
970 return new ValuePassingConfiguration(continuation, v); | 1079 return new ValuePassingConfiguration(continuation, v); |
971 } | 1080 } |
972 } | 1081 } |
973 | 1082 |
| 1083 class StaticSetEK extends ExpressionContinuation { |
| 1084 final Member member; |
| 1085 final ExpressionContinuation continuation; |
| 1086 |
| 1087 StaticSetEK(this.member, this.continuation); |
| 1088 |
| 1089 Configuration call(Value v) { |
| 1090 if (Interpreter.mainEnvironment.contains(member)) { |
| 1091 Interpreter.mainEnvironment.updateStore(member, v); |
| 1092 } else { |
| 1093 Interpreter.mainEnvironment = |
| 1094 Interpreter.mainEnvironment.extend(member, v); |
| 1095 } |
| 1096 return new ValuePassingConfiguration(continuation, v); |
| 1097 } |
| 1098 } |
| 1099 |
| 1100 class StaticSetterEK extends ExpressionContinuation { |
| 1101 final FunctionNode setter; |
| 1102 final ExceptionComponents exceptionComponents; |
| 1103 final ExpressionContinuation expressionContinuation; |
| 1104 |
| 1105 StaticSetterEK( |
| 1106 this.setter, this.exceptionComponents, this.expressionContinuation); |
| 1107 |
| 1108 Configuration call(Value v) { |
| 1109 VariableDeclaration arg = setter.positionalParameters.first; |
| 1110 var env = new Environment.empty().extend(arg, v); |
| 1111 var state = new State.initial() |
| 1112 .withException(exceptionComponents) |
| 1113 .withReturnContinuation(expressionContinuation) |
| 1114 .withContinuation( |
| 1115 new ExitSK(expressionContinuation, Value.nullInstance)); |
| 1116 |
| 1117 return new ExecConfiguration(setter.body, env, state); |
| 1118 } |
| 1119 } |
| 1120 |
974 /// Represents a continuation to be called after the evaluation of an actual | 1121 /// Represents a continuation to be called after the evaluation of an actual |
975 /// argument for function invocation. | 1122 /// argument for function invocation. |
976 class ExpressionListEK extends ExpressionContinuation { | 1123 class ExpressionListEK extends ExpressionContinuation { |
977 final InterpreterExpression currentExpression; | 1124 final InterpreterExpression currentExpression; |
978 final List<InterpreterExpression> expressions; | 1125 final List<InterpreterExpression> expressions; |
979 final Environment environment; | 1126 final Environment environment; |
980 final ExceptionComponents exceptionComponents; | 1127 final ExceptionComponents exceptionComponents; |
981 final ApplicationContinuation applicationContinuation; | 1128 final ApplicationContinuation applicationContinuation; |
982 | 1129 |
983 ExpressionListEK(this.currentExpression, this.expressions, this.environment, | 1130 ExpressionListEK(this.currentExpression, this.expressions, this.environment, |
(...skipping 11 matching lines...) Expand all Loading... |
995 final Arguments arguments; | 1142 final Arguments arguments; |
996 final Name methodName; | 1143 final Name methodName; |
997 final Environment environment; | 1144 final Environment environment; |
998 final ExceptionComponents exceptionComponents; | 1145 final ExceptionComponents exceptionComponents; |
999 final ExpressionContinuation continuation; | 1146 final ExpressionContinuation continuation; |
1000 | 1147 |
1001 MethodInvocationEK(this.arguments, this.methodName, this.environment, | 1148 MethodInvocationEK(this.arguments, this.methodName, this.environment, |
1002 this.exceptionComponents, this.continuation); | 1149 this.exceptionComponents, this.continuation); |
1003 | 1150 |
1004 Configuration call(Value receiver) { | 1151 Configuration call(Value receiver) { |
| 1152 if (receiver is FunctionValue) { |
| 1153 // TODO(zhivkag): use method lookup instead. |
| 1154 assert(methodName.toString() == 'call'); |
| 1155 var args = _getArgumentExpressions(arguments, receiver.function); |
| 1156 var acont = |
| 1157 new FunctionValueA(receiver, exceptionComponents, continuation); |
| 1158 return new EvalListConfiguration( |
| 1159 args, environment, exceptionComponents, acont); |
| 1160 } |
| 1161 |
1005 if (arguments.positional.isEmpty) { | 1162 if (arguments.positional.isEmpty) { |
1006 Value returnValue = receiver.invokeMethod(methodName); | 1163 Value returnValue = receiver.invokeMethod(methodName); |
1007 return new ValuePassingConfiguration(continuation, returnValue); | 1164 return new ValuePassingConfiguration(continuation, returnValue); |
1008 } | 1165 } |
1009 var cont = new ArgumentsEK( | 1166 var cont = new ArgumentsEK( |
1010 receiver, methodName, arguments, environment, continuation); | 1167 receiver, methodName, arguments, environment, continuation); |
1011 | 1168 |
1012 return new EvalConfiguration( | 1169 return new EvalConfiguration( |
1013 arguments.positional.first, environment, exceptionComponents, cont); | 1170 arguments.positional.first, environment, exceptionComponents, cont); |
1014 } | 1171 } |
(...skipping 18 matching lines...) Expand all Loading... |
1033 } | 1190 } |
1034 | 1191 |
1035 class VariableSetEK extends ExpressionContinuation { | 1192 class VariableSetEK extends ExpressionContinuation { |
1036 final VariableDeclaration variable; | 1193 final VariableDeclaration variable; |
1037 final Environment environment; | 1194 final Environment environment; |
1038 final ExpressionContinuation continuation; | 1195 final ExpressionContinuation continuation; |
1039 | 1196 |
1040 VariableSetEK(this.variable, this.environment, this.continuation); | 1197 VariableSetEK(this.variable, this.environment, this.continuation); |
1041 | 1198 |
1042 Configuration call(Value value) { | 1199 Configuration call(Value value) { |
1043 environment.assign(variable, value); | 1200 environment.updateStore(variable, value); |
1044 return new ValuePassingConfiguration(continuation, value); | 1201 return new ValuePassingConfiguration(continuation, value); |
1045 } | 1202 } |
1046 } | 1203 } |
1047 | 1204 |
1048 class NotEK extends ExpressionContinuation { | 1205 class NotEK extends ExpressionContinuation { |
1049 final ExpressionContinuation continuation; | 1206 final ExpressionContinuation continuation; |
1050 | 1207 |
1051 NotEK(this.continuation); | 1208 NotEK(this.continuation); |
1052 | 1209 |
1053 Configuration call(Value value) { | 1210 Configuration call(Value value) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 final VariableDeclaration variable; | 1272 final VariableDeclaration variable; |
1116 final Expression letBody; | 1273 final Expression letBody; |
1117 final Environment environment; | 1274 final Environment environment; |
1118 final ExceptionComponents exceptionComponents; | 1275 final ExceptionComponents exceptionComponents; |
1119 final ExpressionContinuation continuation; | 1276 final ExpressionContinuation continuation; |
1120 | 1277 |
1121 LetEK(this.variable, this.letBody, this.environment, this.exceptionComponents, | 1278 LetEK(this.variable, this.letBody, this.environment, this.exceptionComponents, |
1122 this.continuation); | 1279 this.continuation); |
1123 | 1280 |
1124 Configuration call(Value value) { | 1281 Configuration call(Value value) { |
1125 var letEnv = new Environment(environment); | 1282 var letEnv = environment.extend(variable, value); |
1126 letEnv.extend(variable, value); | |
1127 return new EvalConfiguration( | 1283 return new EvalConfiguration( |
1128 letBody, letEnv, exceptionComponents, continuation); | 1284 letBody, letEnv, exceptionComponents, continuation); |
1129 } | 1285 } |
1130 } | 1286 } |
1131 | 1287 |
1132 /// Represents the continuation for the condition expression in [WhileStatement]
. | 1288 /// Represents the continuation for the condition expression in [WhileStatement]
. |
1133 class WhileConditionEK extends ExpressionContinuation { | 1289 class WhileConditionEK extends ExpressionContinuation { |
1134 final Expression condition; | 1290 final Expression condition; |
1135 final Statement body; | 1291 final Statement body; |
1136 final Environment enclosingEnv; | 1292 final Environment enclosingEnv; |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1493 return new EvalConfiguration(node.expression, conf.environment, | 1649 return new EvalConfiguration(node.expression, conf.environment, |
1494 conf.state.exceptionComponents, cont); | 1650 conf.state.exceptionComponents, cont); |
1495 } | 1651 } |
1496 | 1652 |
1497 Configuration visitBlock(Block node, ExecConfiguration conf) { | 1653 Configuration visitBlock(Block node, ExecConfiguration conf) { |
1498 if (node.statements.isEmpty) { | 1654 if (node.statements.isEmpty) { |
1499 return new ForwardConfiguration( | 1655 return new ForwardConfiguration( |
1500 conf.state.continuation, conf.environment); | 1656 conf.state.continuation, conf.environment); |
1501 } | 1657 } |
1502 | 1658 |
1503 var env = new Environment(conf.environment); | |
1504 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); | 1659 var cont = new BlockSK.fromConfig(node.statements.skip(1).toList(), conf); |
1505 return new ExecConfiguration( | 1660 return new ExecConfiguration(node.statements.first, conf.environment, |
1506 node.statements.first, env, conf.state.withContinuation(cont)); | 1661 conf.state.withContinuation(cont)); |
1507 } | 1662 } |
1508 | 1663 |
1509 Configuration visitEmptyStatement( | 1664 Configuration visitEmptyStatement( |
1510 EmptyStatement node, ExecConfiguration conf) { | 1665 EmptyStatement node, ExecConfiguration conf) { |
1511 return new ForwardConfiguration(conf.state.continuation, conf.environment); | 1666 return new ForwardConfiguration(conf.state.continuation, conf.environment); |
1512 } | 1667 } |
1513 | 1668 |
1514 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { | 1669 Configuration visitIfStatement(IfStatement node, ExecConfiguration conf) { |
1515 var cont = new IfConditionEK( | 1670 var cont = new IfConditionEK( |
1516 node.then, node.otherwise, conf.environment, conf.state); | 1671 node.then, node.otherwise, conf.environment, conf.state); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 VariableDeclaration node, ExecConfiguration conf) { | 1747 VariableDeclaration node, ExecConfiguration conf) { |
1593 if (node.initializer != null) { | 1748 if (node.initializer != null) { |
1594 var cont = new VariableInitializerEK( | 1749 var cont = new VariableInitializerEK( |
1595 node, conf.environment, conf.state.continuation); | 1750 node, conf.environment, conf.state.continuation); |
1596 return new EvalConfiguration(node.initializer, conf.environment, | 1751 return new EvalConfiguration(node.initializer, conf.environment, |
1597 conf.state.exceptionComponents, cont); | 1752 conf.state.exceptionComponents, cont); |
1598 } | 1753 } |
1599 return new ForwardConfiguration(conf.state.continuation, | 1754 return new ForwardConfiguration(conf.state.continuation, |
1600 conf.environment.extend(node, Value.nullInstance)); | 1755 conf.environment.extend(node, Value.nullInstance)); |
1601 } | 1756 } |
| 1757 |
| 1758 Configuration visitFunctionDeclaration( |
| 1759 FunctionDeclaration node, ExecConfiguration conf) { |
| 1760 var newEnv = conf.environment.extend(node.variable, Value.nullInstance); |
| 1761 var fun = new FunctionValue(node.function, newEnv); |
| 1762 newEnv.updateStore(node.variable, fun); |
| 1763 return new ForwardConfiguration(conf.state.continuation, newEnv); |
| 1764 } |
1602 } | 1765 } |
1603 | 1766 |
1604 // ------------------------------------------------------------------------ | 1767 // ------------------------------------------------------------------------ |
1605 // VALUES | 1768 // VALUES |
1606 // ------------------------------------------------------------------------ | 1769 // ------------------------------------------------------------------------ |
1607 | 1770 |
1608 typedef Value Getter(Value receiver); | 1771 typedef Value Getter(Value receiver); |
1609 typedef void Setter(Value receiver, Value value); | 1772 typedef void Setter(Value receiver, Value value); |
1610 | 1773 |
1611 class Class { | 1774 class Class { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1727 Object get value => this; | 1890 Object get value => this; |
1728 | 1891 |
1729 ObjectValue(this.class_) : fields = new List<Location>(class_.instanceSize) { | 1892 ObjectValue(this.class_) : fields = new List<Location>(class_.instanceSize) { |
1730 for (int i = 0; i < fields.length; i++) { | 1893 for (int i = 0; i < fields.length; i++) { |
1731 // Create fresh locations for each field. | 1894 // Create fresh locations for each field. |
1732 fields[i] = new Location.empty(); | 1895 fields[i] = new Location.empty(); |
1733 } | 1896 } |
1734 } | 1897 } |
1735 } | 1898 } |
1736 | 1899 |
| 1900 class FunctionValue extends Value { |
| 1901 Class get class_ => throw 'Class for FunctionValue is not defined'; |
| 1902 List<Location> get fields => throw 'FunctionValue has no fields.'; |
| 1903 |
| 1904 FunctionValue get value => this; |
| 1905 |
| 1906 final FunctionNode function; |
| 1907 final Environment environment; |
| 1908 |
| 1909 FunctionValue(this.function, this.environment); |
| 1910 } |
| 1911 |
1737 abstract class LiteralValue extends Value { | 1912 abstract class LiteralValue extends Value { |
1738 Class get class_ => | 1913 Class get class_ => |
1739 notImplemented(m: "Loading class for literal is not implemented."); | 1914 notImplemented(m: "Loading class for literal is not implemented."); |
1740 List<Location> get fields => | 1915 List<Location> get fields => |
1741 notImplemented(m: "Literal value does not have fields"); | 1916 notImplemented(m: "Literal value does not have fields"); |
1742 | 1917 |
1743 const LiteralValue(); | 1918 const LiteralValue(); |
1744 } | 1919 } |
1745 | 1920 |
1746 class StringValue extends LiteralValue { | 1921 class StringValue extends LiteralValue { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1893 /// Initializes all non initialized fields from the provided class to | 2068 /// Initializes all non initialized fields from the provided class to |
1894 /// `Value.nullInstance` in the provided value. | 2069 /// `Value.nullInstance` in the provided value. |
1895 void _initializeNullFields(Class class_, Value value) { | 2070 void _initializeNullFields(Class class_, Value value) { |
1896 int startIndex = class_.superclass?.instanceSize ?? 0; | 2071 int startIndex = class_.superclass?.instanceSize ?? 0; |
1897 for (int i = startIndex; i < class_.instanceSize; i++) { | 2072 for (int i = startIndex; i < class_.instanceSize; i++) { |
1898 if (value.fields[i].value == null) { | 2073 if (value.fields[i].value == null) { |
1899 value.fields[i].value = Value.nullInstance; | 2074 value.fields[i].value = Value.nullInstance; |
1900 } | 2075 } |
1901 } | 2076 } |
1902 } | 2077 } |
OLD | NEW |