OLD | NEW |
---|---|
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 library fletchc.codegen_visitor; | 5 library fletchc.codegen_visitor; |
6 | 6 |
7 import 'package:compiler/src/resolution/semantic_visitor.dart'; | 7 import 'package:compiler/src/resolution/semantic_visitor.dart'; |
8 | 8 |
9 import 'package:compiler/src/resolution/operators.dart' show | 9 import 'package:compiler/src/resolution/operators.dart' show |
10 AssignmentOperator, | 10 AssignmentOperator, |
11 BinaryOperator, | 11 BinaryOperator, |
12 IncDecOperator, | 12 IncDecOperator, |
13 UnaryOperator; | 13 UnaryOperator; |
14 | 14 |
15 import 'package:compiler/src/constants/expressions.dart' show | 15 import 'package:compiler/src/constants/expressions.dart' show |
16 BoolFromEnvironmentConstantExpression, | 16 BoolFromEnvironmentConstantExpression, |
17 IntFromEnvironmentConstantExpression, | 17 IntFromEnvironmentConstantExpression, |
18 StringFromEnvironmentConstantExpression, | 18 StringFromEnvironmentConstantExpression, |
19 ConstantExpression, | 19 ConstantExpression, |
20 ConstructedConstantExpression, | 20 ConstructedConstantExpression, |
21 TypeConstantExpression; | 21 TypeConstantExpression; |
22 | 22 |
23 import 'package:compiler/src/dart2jslib.dart' show | 23 import 'package:compiler/src/resolution/tree_elements.dart' show |
24 MessageKind, | 24 TreeElements; |
25 Registry; | |
26 | 25 |
27 import 'package:compiler/src/util/util.dart' show | 26 import 'package:compiler/src/util/util.dart' show |
28 Link; | 27 Link; |
29 | 28 |
29 import 'package:compiler/src/common/names.dart' show | |
30 Names, | |
31 Selectors; | |
32 | |
33 import 'package:compiler/src/universe/use.dart' show DynamicUse, StaticUse; | |
34 | |
30 import 'package:compiler/src/elements/elements.dart'; | 35 import 'package:compiler/src/elements/elements.dart'; |
31 import 'package:compiler/src/resolution/resolution.dart'; | |
32 import 'package:compiler/src/tree/tree.dart'; | 36 import 'package:compiler/src/tree/tree.dart'; |
33 import 'package:compiler/src/universe/universe.dart'; | 37 import 'package:compiler/src/universe/call_structure.dart' show |
34 import 'package:compiler/src/util/util.dart' show Spannable; | 38 CallStructure; |
39 import 'package:compiler/src/universe/selector.dart' show | |
40 Selector; | |
41 import 'package:compiler/src/diagnostics/spannable.dart' show | |
42 Spannable; | |
35 import 'package:compiler/src/dart_types.dart'; | 43 import 'package:compiler/src/dart_types.dart'; |
36 | 44 |
37 import 'fletch_context.dart'; | 45 import 'fletch_context.dart'; |
38 | 46 |
39 import 'fletch_backend.dart'; | 47 import 'fletch_backend.dart'; |
40 | 48 |
41 import 'fletch_constants.dart' show | 49 import 'fletch_constants.dart' show |
42 FletchFunctionBuilderConstant, | |
43 FletchClassConstant, | 50 FletchClassConstant, |
44 FletchClassInstanceConstant; | 51 FletchClassInstanceConstant; |
45 | 52 |
46 import 'fletch_function_builder.dart' show | 53 import 'fletch_function_builder.dart' show |
47 FletchFunctionBuilder; | 54 FletchFunctionBuilder; |
48 | 55 |
49 import 'fletch_class_builder.dart' show | 56 import 'fletch_class_builder.dart' show |
50 FletchClassBuilder; | 57 FletchClassBuilder; |
51 | 58 |
52 import 'fletch_selector.dart'; | 59 import 'fletch_selector.dart'; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
203 BinaryBulkMixin, | 210 BinaryBulkMixin, |
204 PrefixBulkMixin, | 211 PrefixBulkMixin, |
205 PostfixBulkMixin, | 212 PostfixBulkMixin, |
206 NewBulkMixin, | 213 NewBulkMixin, |
207 VariableBulkMixin, | 214 VariableBulkMixin, |
208 ParameterBulkMixin, | 215 ParameterBulkMixin, |
209 FunctionBulkMixin, | 216 FunctionBulkMixin, |
210 ConstructorBulkMixin, | 217 ConstructorBulkMixin, |
211 InitializerBulkMixin, | 218 InitializerBulkMixin, |
212 BaseImplementationOfStaticsMixin, | 219 BaseImplementationOfStaticsMixin, |
213 BaseImplementationOfLocalsMixin | 220 BaseImplementationOfLocalsMixin, |
221 SetIfNullBulkMixin | |
214 implements SemanticSendVisitor, SemanticDeclarationVisitor { | 222 implements SemanticSendVisitor, SemanticDeclarationVisitor { |
215 // A literal int can have up to 31 bits of information (32 minus sign). | 223 // A literal int can have up to 31 bits of information (32 minus sign). |
216 static const int LITERAL_INT_MAX = 0x3FFFFFFF; | 224 static const int LITERAL_INT_MAX = 0x3FFFFFFF; |
217 static const int MAX_INT64 = (1 << 63) - 1; | 225 static const int MAX_INT64 = (1 << 63) - 1; |
218 static const int MIN_INT64 = -(1 << 63); | 226 static const int MIN_INT64 = -(1 << 63); |
219 | 227 |
220 final FletchContext context; | 228 final FletchContext context; |
221 | 229 |
222 final ClosureEnvironment closureEnvironment; | 230 final ClosureEnvironment closureEnvironment; |
223 | 231 |
224 final ExecutableElement element; | 232 final ExecutableElement element; |
225 | 233 |
226 final MemberElement member; | |
227 | |
228 final FletchFunctionBuilder functionBuilder; | 234 final FletchFunctionBuilder functionBuilder; |
229 | 235 |
230 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; | 236 final Map<Element, LocalValue> scope = <Element, LocalValue>{}; |
231 | 237 |
232 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; | 238 final Map<Node, JumpInfo> jumpInfo = <Node, JumpInfo>{}; |
233 | 239 |
234 // Stack of try blocks (inner-most first), in the lexical scope. | 240 // Stack of try blocks (inner-most first), in the lexical scope. |
235 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); | 241 Link<TryBlock> tryBlockStack = const Link<TryBlock>(); |
236 | 242 |
237 VisitState visitState; | 243 VisitState visitState; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 } | 366 } |
361 | 367 |
362 void pushVariableDeclaration(LocalValue value) { | 368 void pushVariableDeclaration(LocalValue value) { |
363 scope[value.element] = value; | 369 scope[value.element] = value; |
364 } | 370 } |
365 | 371 |
366 void popVariableDeclaration(Element local) { | 372 void popVariableDeclaration(Element local) { |
367 scope.remove(local); | 373 scope.remove(local); |
368 } | 374 } |
369 | 375 |
370 void registerDynamicInvocation(Selector selector); | 376 void registerDynamicUse(Selector selector); |
371 | 377 |
372 void registerDynamicGetter(Selector selector); | 378 void registerStaticUse(StaticUse use); |
ahe
2015/12/01 10:12:12
StaticUse (like DynamicUse) is problematic to use
sigurdm
2015/12/03 14:48:09
Done.
| |
373 | |
374 void registerDynamicSetter(Selector selector); | |
375 | |
376 void registerStaticInvocation(FunctionElement function); | |
377 | 379 |
378 void registerInstantiatedClass(ClassElement klass); | 380 void registerInstantiatedClass(ClassElement klass); |
379 | 381 |
380 void registerIsCheck(DartType type); | 382 void registerIsCheck(DartType type); |
381 | 383 |
382 void registerLocalInvoke(LocalElement element, Selector selector); | 384 void registerLocalInvoke(LocalElement element, Selector selector); |
383 | 385 |
384 /// Register that [element] is a closure. This can happen for a tear-off, or | 386 /// Register that [element] is a closure. This can happen for a tear-off, or |
385 /// for local functions. See [ClosureKind] for more information about the | 387 /// for local functions. See [ClosureKind] for more information about the |
386 /// various kinds of implicit or explicit closurizations that can occur. | 388 /// various kinds of implicit or explicit closurizations that can occur. |
387 void registerClosurization(FunctionElement element, ClosureKind kind); | 389 void registerClosurization(FunctionElement element, ClosureKind kind); |
388 | 390 |
389 int compileLazyFieldInitializer(FieldElement field); | 391 int compileLazyFieldInitializer(FieldElement field); |
390 | 392 |
391 void invokeMethod(Node node, Selector selector) { | 393 void invokeMethod(Node node, Selector selector) { |
392 registerDynamicInvocation(selector); | 394 registerDynamicUse(selector); |
393 String symbol = context.getSymbolFromSelector(selector); | 395 String symbol = context.getSymbolFromSelector(selector); |
394 int id = context.getSymbolId(symbol); | 396 int id = context.getSymbolId(symbol); |
395 int arity = selector.argumentCount; | 397 int arity = selector.argumentCount; |
396 int fletchSelector = FletchSelector.encodeMethod(id, arity); | 398 int fletchSelector = FletchSelector.encodeMethod(id, arity); |
397 assembler.invokeMethod(fletchSelector, arity, selector.name); | 399 assembler.invokeMethod(fletchSelector, arity, selector.name); |
398 } | 400 } |
399 | 401 |
400 void invokeGetter(Node node, Selector selector) { | 402 void invokeGetter(Node node, Name name) { |
401 registerDynamicGetter(selector); | 403 registerDynamicUse(new Selector.getter(name)); |
ahe
2015/12/01 10:12:12
This shouldn't create new objects.
sigurdm
2015/12/03 14:48:09
Done.
| |
402 String symbol = context.getSymbolFromSelector(selector); | 404 String symbol = context.mangleName(name); |
403 int id = context.getSymbolId(symbol); | 405 int id = context.getSymbolId(symbol); |
404 int fletchSelector = FletchSelector.encodeGetter(id); | 406 int fletchSelector = FletchSelector.encodeGetter(id); |
405 assembler.invokeMethod(fletchSelector, 0); | 407 assembler.invokeMethod(fletchSelector, 0); |
406 } | 408 } |
407 | 409 |
408 void invokeSetter(Node node, Selector selector) { | 410 void invokeSetter(Node node, Name name) { |
409 registerDynamicSetter(selector); | 411 registerDynamicUse(new Selector.setter(name)); |
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
410 String symbol = context.getSymbolFromSelector(selector); | 412 String symbol = context.mangleName(name); |
411 int id = context.getSymbolId(symbol); | 413 int id = context.getSymbolId(symbol); |
412 int fletchSelector = FletchSelector.encodeSetter(id); | 414 int fletchSelector = FletchSelector.encodeSetter(id); |
413 assembler.invokeMethod(fletchSelector, 1); | 415 assembler.invokeMethod(fletchSelector, 1); |
414 } | 416 } |
415 | 417 |
416 void invokeFactory(Node node, int constId, int arity) { | 418 void invokeFactory(Node node, int constId, int arity) { |
417 assembler.invokeFactory(constId, arity); | 419 assembler.invokeFactory(constId, arity); |
418 } | 420 } |
419 | 421 |
420 void invokeStatic(Node node, int constId, int arity) { | 422 void invokeStatic(Node node, int constId, int arity) { |
(...skipping 21 matching lines...) Expand all Loading... | |
442 int constId = allocateConstantFromNode(caseMatch.expression); | 444 int constId = allocateConstantFromNode(caseMatch.expression); |
443 assembler.loadConst(constId); | 445 assembler.loadConst(constId); |
444 // For debugging, ignore the equality checks in connection | 446 // For debugging, ignore the equality checks in connection |
445 // with case matches by not associating the calls with | 447 // with case matches by not associating the calls with |
446 // any node. | 448 // any node. |
447 invokeMethod(null, new Selector.binaryOperator('==')); | 449 invokeMethod(null, new Selector.binaryOperator('==')); |
448 assembler.branchIfTrue(ifTrue); | 450 assembler.branchIfTrue(ifTrue); |
449 } | 451 } |
450 | 452 |
451 FletchFunctionBase requireFunction(FunctionElement element) { | 453 FletchFunctionBase requireFunction(FunctionElement element) { |
452 registerStaticInvocation(element); | 454 // TODO(johnniwinther): More precise use. |
455 registerStaticUse(new StaticUse.foreignUse(element)); | |
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
453 return context.backend.getFunctionForElement(element); | 456 return context.backend.getFunctionForElement(element); |
454 } | 457 } |
455 | 458 |
456 FletchFunctionBase requireConstructorInitializer( | 459 FletchFunctionBase requireConstructorInitializer( |
457 ConstructorElement constructor) { | 460 ConstructorElement constructor) { |
458 assert(constructor.isGenerativeConstructor); | 461 assert(constructor.isGenerativeConstructor); |
459 registerInstantiatedClass(constructor.enclosingClass); | 462 registerInstantiatedClass(constructor.enclosingClass); |
460 registerStaticInvocation(constructor); | 463 registerStaticUse(new StaticUse.foreignUse(constructor)); |
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
461 return context.backend.getConstructorInitializerFunction(constructor); | 464 return context.backend.getConstructorInitializerFunction(constructor); |
462 } | 465 } |
463 | 466 |
464 void doStaticFunctionInvoke( | 467 void doStaticFunctionInvoke( |
465 Node node, | 468 Node node, |
466 FletchFunctionBase function, | 469 FletchFunctionBase function, |
467 NodeList arguments, | 470 NodeList arguments, |
468 CallStructure callStructure, | 471 CallStructure callStructure, |
469 {bool factoryInvoke: false}) { | 472 {bool factoryInvoke: false}) { |
470 if (function.isInstanceMember) loadThis(); | 473 if (function.isInstanceMember) loadThis(); |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
902 assembler.loadLiteralTrue(); | 905 assembler.loadLiteralTrue(); |
903 return; | 906 return; |
904 } | 907 } |
905 | 908 |
906 if (type.isTypedef) { | 909 if (type.isTypedef) { |
907 // TODO(ajohnsen): This only matches with the number of arguments, not | 910 // TODO(ajohnsen): This only matches with the number of arguments, not |
908 // the actual argument types. | 911 // the actual argument types. |
909 TypedefType typedefType = type; | 912 TypedefType typedefType = type; |
910 int arity = typedefType.element.functionSignature.parameterCount; | 913 int arity = typedefType.element.functionSignature.parameterCount; |
911 int fletchSelector = context.toFletchIsSelector( | 914 int fletchSelector = context.toFletchIsSelector( |
912 context.backend.compiler.functionClass, arity); | 915 context.backend.compiler.coreClasses.functionClass, arity); |
913 assembler.invokeTest(fletchSelector, 0); | 916 assembler.invokeTest(fletchSelector, 0); |
914 return; | 917 return; |
915 } | 918 } |
916 | 919 |
917 if (!type.isInterfaceType) { | 920 if (!type.isInterfaceType) { |
918 assembler.pop(); | 921 assembler.pop(); |
919 generateUnimplementedError( | 922 generateUnimplementedError( |
920 diagnosticLocation, "Unhandled type test for $type."); | 923 diagnosticLocation, "Unhandled type test for $type."); |
921 return; | 924 return; |
922 } | 925 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
994 FletchClassBuilder classBuilder = | 997 FletchClassBuilder classBuilder = |
995 context.backend.createTearoffClass(target); | 998 context.backend.createTearoffClass(target); |
996 assert(classBuilder.fields == 0); | 999 assert(classBuilder.fields == 0); |
997 int constId = allocateConstantClassInstance(classBuilder.classId); | 1000 int constId = allocateConstantClassInstance(classBuilder.classId); |
998 assembler.loadConst(constId); | 1001 assembler.loadConst(constId); |
999 applyVisitState(); | 1002 applyVisitState(); |
1000 } | 1003 } |
1001 | 1004 |
1002 void doMainCall(Send node, NodeList arguments) { | 1005 void doMainCall(Send node, NodeList arguments) { |
1003 FunctionElement function = context.compiler.mainFunction; | 1006 FunctionElement function = context.compiler.mainFunction; |
1004 if (function.isErroneous) { | 1007 if (function.isMalformed) { |
1005 doCompileError(); | 1008 doCompileError(); |
1006 return; | 1009 return; |
1007 } | 1010 } |
1008 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; | 1011 if (context.compiler.libraryLoader.libraries.any(checkCompileError)) return; |
1009 | 1012 |
1010 // Load up to 'parameterCount' arguments, padding with nulls. | 1013 // Load up to 'parameterCount' arguments, padding with nulls. |
1011 int parameterCount = function.functionSignature.parameterCount; | 1014 int parameterCount = function.functionSignature.parameterCount; |
1012 int argumentCount = 0; | 1015 int argumentCount = 0; |
1013 for (Node argument in arguments) { | 1016 for (Node argument in arguments) { |
1014 if (argumentCount == parameterCount) break; | 1017 if (argumentCount == parameterCount) break; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1068 Send node, | 1071 Send node, |
1069 MethodElement element, | 1072 MethodElement element, |
1070 NodeList arguments, | 1073 NodeList arguments, |
1071 CallStructure callStructure, | 1074 CallStructure callStructure, |
1072 _) { | 1075 _) { |
1073 doStaticallyBoundInvoke(node, element, arguments, callStructure); | 1076 doStaticallyBoundInvoke(node, element, arguments, callStructure); |
1074 applyVisitState(); | 1077 applyVisitState(); |
1075 } | 1078 } |
1076 | 1079 |
1077 void doSuperCall(Node node, FunctionElement function) { | 1080 void doSuperCall(Node node, FunctionElement function) { |
1078 registerStaticInvocation(function); | 1081 registerStaticUse(new StaticUse.foreignUse(function)); |
ahe
2015/12/01 10:12:12
Ditto.
sigurdm
2015/12/03 14:48:09
Done.
| |
1079 int arity = function.functionSignature.parameterCount + 1; | 1082 int arity = function.functionSignature.parameterCount + 1; |
1080 FletchFunctionBase base = requireFunction(function); | 1083 FletchFunctionBase base = requireFunction(function); |
1081 int constId = functionBuilder.allocateConstantFromFunction(base.functionId); | 1084 int constId = functionBuilder.allocateConstantFromFunction(base.functionId); |
1082 invokeStatic(node, constId, arity); | 1085 invokeStatic(node, constId, arity); |
1083 } | 1086 } |
1084 | 1087 |
1085 void visitSuperGetterGet( | 1088 void visitSuperGetterGet( |
1086 Send node, | 1089 Send node, |
1087 FunctionElement getter, | 1090 FunctionElement getter, |
1088 _) { | 1091 _) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1285 invokeMethod(node, callStructure.callSelector); | 1288 invokeMethod(node, callStructure.callSelector); |
1286 applyVisitState(); | 1289 applyVisitState(); |
1287 } | 1290 } |
1288 | 1291 |
1289 void visitDynamicPropertyInvoke( | 1292 void visitDynamicPropertyInvoke( |
1290 Send node, | 1293 Send node, |
1291 Node receiver, | 1294 Node receiver, |
1292 NodeList arguments, | 1295 NodeList arguments, |
1293 Selector selector, | 1296 Selector selector, |
1294 _) { | 1297 _) { |
1295 if (selector == null) { | |
1296 // TODO(ajohnsen): Remove hack - dart2js has a problem with generating | |
1297 // selectors in initializer bodies. | |
1298 selector = new Selector.call( | |
1299 node.selector.asIdentifier().source, | |
1300 element.library, | |
1301 arguments.slowLength()); | |
1302 } | |
1303 visitForValue(receiver); | 1298 visitForValue(receiver); |
1304 for (Node argument in arguments) { | 1299 for (Node argument in arguments) { |
1305 visitForValue(argument); | 1300 visitForValue(argument); |
1306 } | 1301 } |
1307 invokeMethod(node, selector); | 1302 invokeMethod(node, selector); |
1308 applyVisitState(); | 1303 applyVisitState(); |
1309 } | 1304 } |
1310 | 1305 |
1306 void visitIfNull( | |
1307 Send node, | |
1308 Node left, | |
1309 Node right, | |
1310 _) { | |
1311 BytecodeLabel end = new BytecodeLabel(); | |
1312 visitForValue(left); | |
1313 assembler.dup(); | |
1314 assembler.loadLiteralNull(); | |
1315 assembler.identicalNonNumeric(); | |
1316 assembler.branchIfFalse(end); | |
1317 assembler.pop(); | |
1318 visitForValue(right); | |
1319 assembler.bind(end); | |
1320 applyVisitState(); | |
1321 } | |
1322 | |
1311 void doIfNotNull(Node receiver, void ifNotNull()) { | 1323 void doIfNotNull(Node receiver, void ifNotNull()) { |
1312 BytecodeLabel end = new BytecodeLabel(); | 1324 BytecodeLabel end = new BytecodeLabel(); |
1313 visitForValue(receiver); | 1325 visitForValue(receiver); |
1314 assembler.dup(); | 1326 assembler.dup(); |
1315 assembler.loadLiteralNull(); | 1327 assembler.loadLiteralNull(); |
1316 assembler.identicalNonNumeric(); | 1328 assembler.identicalNonNumeric(); |
1317 assembler.branchIfTrue(end); | 1329 assembler.branchIfTrue(end); |
1318 ifNotNull(); | 1330 ifNotNull(); |
1319 assembler.bind(end); | 1331 assembler.bind(end); |
1320 } | 1332 } |
(...skipping 10 matching lines...) Expand all Loading... | |
1331 } | 1343 } |
1332 invokeMethod(node, selector); | 1344 invokeMethod(node, selector); |
1333 }); | 1345 }); |
1334 applyVisitState(); | 1346 applyVisitState(); |
1335 } | 1347 } |
1336 | 1348 |
1337 void visitExpressionInvoke( | 1349 void visitExpressionInvoke( |
1338 Send node, | 1350 Send node, |
1339 Expression receiver, | 1351 Expression receiver, |
1340 NodeList arguments, | 1352 NodeList arguments, |
1341 Selector selector, | 1353 CallStructure callStructure, |
1342 _) { | 1354 _) { |
1343 visitForValue(receiver); | 1355 visitForValue(receiver); |
1344 for (Node argument in arguments) { | 1356 for (Node argument in arguments) { |
1345 visitForValue(argument); | 1357 visitForValue(argument); |
1346 } | 1358 } |
1347 invokeMethod(node, selector); | 1359 invokeMethod(node, new Selector.call(Names.call, callStructure)); |
1348 applyVisitState(); | 1360 applyVisitState(); |
1349 } | 1361 } |
1350 | 1362 |
1351 void visitThisPropertyInvoke( | 1363 void visitThisPropertyInvoke( |
1352 Send node, | 1364 Send node, |
1353 NodeList arguments, | 1365 NodeList arguments, |
1354 Selector selector, | 1366 Selector selector, |
1355 _) { | 1367 _) { |
1356 loadThis(); | 1368 loadThis(); |
1357 | 1369 |
1358 // If the property is statically known to be a field, instead invoke the | 1370 // If the property is statically known to be a field, instead invoke the |
1359 // getter and then invoke 'call(...)' on the value. | 1371 // getter and then invoke 'call(...)' on the value. |
1360 // TODO(ajohnsen): This is a fix that only works when the field is | 1372 // TODO(ajohnsen): This is a fix that only works when the field is |
1361 // statically known - that is not always the case. Implement VM support? | 1373 // statically known - that is not always the case. Implement VM support? |
1362 Element target = elements[node]; | 1374 Element target = elements[node]; |
1363 if (target != null && target.isField) { | 1375 if (target != null && target.isField) { |
1364 invokeGetter(node, new Selector.getter(target.name, element.library)); | 1376 invokeGetter(node, new Name(target.name, element.library)); |
1365 selector = new Selector.callClosureFrom(selector); | 1377 selector = new Selector.callClosureFrom(selector); |
1366 } | 1378 } |
1367 for (Node argument in arguments) { | 1379 for (Node argument in arguments) { |
1368 visitForValue(argument); | 1380 visitForValue(argument); |
1369 } | 1381 } |
1370 invokeMethod(node, selector); | 1382 invokeMethod(node, selector); |
1371 applyVisitState(); | 1383 applyVisitState(); |
1372 } | 1384 } |
1373 | 1385 |
1374 void visitThisInvoke( | 1386 void visitThisInvoke( |
(...skipping 14 matching lines...) Expand all Loading... | |
1389 ConstantExpression constant, | 1401 ConstantExpression constant, |
1390 _) { | 1402 _) { |
1391 generateUnimplementedError( | 1403 generateUnimplementedError( |
1392 node, "[visitClassTypeLiteralGet] isn't implemented."); | 1404 node, "[visitClassTypeLiteralGet] isn't implemented."); |
1393 applyVisitState(); | 1405 applyVisitState(); |
1394 } | 1406 } |
1395 | 1407 |
1396 void visitDynamicPropertyGet( | 1408 void visitDynamicPropertyGet( |
1397 Send node, | 1409 Send node, |
1398 Node receiver, | 1410 Node receiver, |
1399 Selector selector, | 1411 Name name, |
1400 _) { | 1412 _) { |
1401 if (selector == null) { | 1413 if (name.text == "runtimeType") { |
1402 // TODO(ajohnsen): Remove hack - dart2js has a problem with generating | |
1403 // selectors in initializer bodies. | |
1404 selector = new Selector.getter( | |
1405 node.selector.asIdentifier().source, | |
1406 element.library); | |
1407 } | |
1408 if (selector.name == "runtimeType") { | |
1409 // TODO(ahe): Implement runtimeType. | 1414 // TODO(ahe): Implement runtimeType. |
1410 generateUnimplementedError( | 1415 generateUnimplementedError( |
1411 node, | 1416 node, |
1412 "'runtimeType' isn't supported in Fletch. See https://goo.gl/ELH6Zc"); | 1417 "'runtimeType' isn't supported in Fletch. See https://goo.gl/ELH6Zc"); |
1413 applyVisitState(); | 1418 applyVisitState(); |
1414 return; | 1419 return; |
1415 } | 1420 } |
1416 visitForValue(receiver); | 1421 visitForValue(receiver); |
1417 invokeGetter(node, selector); | 1422 invokeGetter(node, name); |
1418 applyVisitState(); | 1423 applyVisitState(); |
1419 } | 1424 } |
1420 | 1425 |
1421 void visitIfNotNullDynamicPropertyGet( | 1426 void visitIfNotNullDynamicPropertyGet( |
1422 Send node, | 1427 Send node, |
1423 Node receiver, | 1428 Node receiver, |
1424 Selector selector, | 1429 Name name, |
1425 _) { | 1430 _) { |
1426 doIfNotNull(receiver, () { | 1431 doIfNotNull(receiver, () { |
1427 invokeGetter(node, selector); | 1432 invokeGetter(node, name); |
1428 }); | 1433 }); |
1429 applyVisitState(); | 1434 applyVisitState(); |
1430 } | 1435 } |
1431 | 1436 |
1432 void visitThisPropertyGet( | 1437 void visitThisPropertyGet( |
1433 Send node, | 1438 Send node, |
1434 Selector selector, | 1439 Name name, |
1435 _) { | 1440 _) { |
1436 loadThis(); | 1441 loadThis(); |
1437 invokeGetter(node, selector); | 1442 invokeGetter(node, name); |
1438 applyVisitState(); | 1443 applyVisitState(); |
1439 } | 1444 } |
1440 | 1445 |
1441 void visitThisPropertySet( | 1446 void visitThisPropertySet( |
1442 Send node, | 1447 Send node, |
1443 Selector selector, | 1448 Name name, |
1444 Node rhs, | 1449 Node rhs, |
1445 _) { | 1450 _) { |
1446 loadThis(); | 1451 loadThis(); |
1447 visitForValue(rhs); | 1452 visitForValue(rhs); |
1448 invokeSetter(node, selector); | 1453 invokeSetter(node, name); |
1449 applyVisitState(); | 1454 applyVisitState(); |
1450 } | 1455 } |
1451 | 1456 |
1452 void doStaticFieldGet(FieldElement field) { | 1457 void doStaticFieldGet(FieldElement field) { |
1453 if (checkCompileError(field)) return; | 1458 if (checkCompileError(field)) return; |
1454 if (field.isConst) { | 1459 if (field.isConst) { |
1455 int constId = allocateConstantFromNode( | 1460 int constId = allocateConstantFromNode( |
1456 field.initializer, | 1461 field.initializer, |
1457 elements: field.resolvedAst.elements); | 1462 elements: field.resolvedAst.elements); |
1458 assembler.loadConst(constId); | 1463 assembler.loadConst(constId); |
1459 } else { | 1464 } else { |
1460 int index = compileLazyFieldInitializer(field); | 1465 int index = compileLazyFieldInitializer(field); |
1461 if (field.initializer != null) { | 1466 if (field.initializer != null) { |
1462 assembler.loadStaticInit(index); | 1467 assembler.loadStaticInit(index); |
1463 } else { | 1468 } else { |
1464 assembler.loadStatic(index); | 1469 assembler.loadStatic(index); |
1465 } | 1470 } |
1466 } | 1471 } |
1467 } | 1472 } |
1468 | 1473 |
1469 void handleStaticFieldGet( | 1474 void handleStaticFieldGet( |
1470 Send node, | 1475 Send node, |
1471 FieldElement field, | 1476 FieldElement field, |
1472 _) { | 1477 _) { |
1473 doStaticFieldGet(field); | 1478 doStaticFieldGet(field); |
1474 applyVisitState(); | 1479 applyVisitState(); |
1475 } | 1480 } |
1476 | 1481 |
1477 void visitAssert(Send node, Node expression, _) { | 1482 void visitAssert(Assert node) { |
1478 // TODO(ajohnsen): Emit assert in checked mode. | 1483 // TODO(ajohnsen): Emit assert in checked mode. |
1479 } | 1484 } |
1480 | 1485 |
1481 void visitDynamicPropertySet( | 1486 void visitDynamicPropertySet( |
1482 Send node, | 1487 Send node, |
1483 Node receiver, | 1488 Node receiver, |
1484 Selector selector, | 1489 Name name, |
1485 Node rhs, | 1490 Node rhs, |
1486 _) { | 1491 _) { |
1487 visitForValue(receiver); | 1492 visitForValue(receiver); |
1488 visitForValue(rhs); | 1493 visitForValue(rhs); |
1489 invokeSetter(node, selector); | 1494 invokeSetter(node, name); |
1490 applyVisitState(); | 1495 applyVisitState(); |
1491 } | 1496 } |
1492 | 1497 |
1493 void visitIfNotNullDynamicPropertySet( | 1498 void visitIfNotNullDynamicPropertySet( |
1494 SendSet node, | 1499 SendSet node, |
1495 Node receiver, | 1500 Node receiver, |
1496 Selector selector, | 1501 Name name, |
1497 Node rhs, | 1502 Node rhs, |
1498 _) { | 1503 _) { |
1499 doIfNotNull(receiver, () { | 1504 doIfNotNull(receiver, () { |
1500 visitForValue(rhs); | 1505 visitForValue(rhs); |
1501 invokeSetter(node, selector); | 1506 invokeSetter(node, name); |
1502 }); | 1507 }); |
1503 applyVisitState(); | 1508 applyVisitState(); |
1504 } | 1509 } |
1505 | 1510 |
1506 void doStaticFieldSet(FieldElement field) { | 1511 void doStaticFieldSet( |
ahe
2015/12/01 10:12:12
Why this change?
sigurdm
2015/12/03 14:48:09
Not sure - reverted.
| |
1512 FieldElement field) { | |
1507 int index = context.getStaticFieldIndex(field, element); | 1513 int index = context.getStaticFieldIndex(field, element); |
1508 assembler.storeStatic(index); | 1514 assembler.storeStatic(index); |
1509 } | 1515 } |
1510 | 1516 |
1511 void handleStaticFieldSet( | 1517 void handleStaticFieldSet( |
1512 SendSet node, | 1518 SendSet node, |
1513 FieldElement field, | 1519 FieldElement field, |
1514 Node rhs, | 1520 Node rhs, |
1515 _) { | 1521 _) { |
1516 visitForValue(rhs); | 1522 visitForValue(rhs); |
1517 doStaticFieldSet(field); | 1523 doStaticFieldSet(field); |
1518 applyVisitState(); | 1524 applyVisitState(); |
1519 } | 1525 } |
1520 | 1526 |
1521 void visitStringJuxtaposition(StringJuxtaposition node) { | 1527 void visitStringJuxtaposition(StringJuxtaposition node) { |
1522 // TODO(ajohnsen): This could probably be optimized to string constants in | 1528 // TODO(ajohnsen): This could probably be optimized to string constants in |
1523 // some cases. | 1529 // some cases. |
1524 visitForValue(node.first); | 1530 visitForValue(node.first); |
1525 visitForValue(node.second); | 1531 visitForValue(node.second); |
1526 // TODO(ajohnsen): Cache these in context/backend. | 1532 // TODO(ajohnsen): Cache these in context/backend. |
1527 Selector concat = new Selector.binaryOperator('+'); | 1533 Selector concat = new Selector.binaryOperator('+'); |
1528 invokeMethod(node, concat); | 1534 invokeMethod(node, concat); |
1529 applyVisitState(); | 1535 applyVisitState(); |
1530 } | 1536 } |
1531 | 1537 |
1532 void visitStringInterpolation(StringInterpolation node) { | 1538 void visitStringInterpolation(StringInterpolation node) { |
1533 // TODO(ajohnsen): Cache these in context/backend. | 1539 // TODO(ajohnsen): Cache this in context/backend. |
1534 Selector toString = new Selector.call('toString', null, 0); | |
1535 Selector concat = new Selector.binaryOperator('+'); | 1540 Selector concat = new Selector.binaryOperator('+'); |
1536 visitForValueNoDebugInfo(node.string); | 1541 visitForValueNoDebugInfo(node.string); |
1537 for (StringInterpolationPart part in node.parts) { | 1542 for (StringInterpolationPart part in node.parts) { |
1538 visitForValue(part.expression); | 1543 visitForValue(part.expression); |
1539 invokeMethod(part.expression, toString); | 1544 invokeMethod(part.expression, Selectors.toString_); |
1540 LiteralString string = part.string; | 1545 LiteralString string = part.string; |
1541 if (string.dartString.isNotEmpty) { | 1546 if (string.dartString.isNotEmpty) { |
1542 visitForValueNoDebugInfo(string); | 1547 visitForValueNoDebugInfo(string); |
1543 invokeMethod(null, concat); | 1548 invokeMethod(null, concat); |
1544 } | 1549 } |
1545 invokeMethod(null, concat); | 1550 invokeMethod(null, concat); |
1546 } | 1551 } |
1547 applyVisitState(); | 1552 applyVisitState(); |
1548 } | 1553 } |
1549 | 1554 |
1550 void visitLiteralNull(LiteralNull node) { | 1555 void visitLiteralNull(LiteralNull node) { |
1551 if (visitState == VisitState.Value) { | 1556 if (visitState == VisitState.Value) { |
1552 assembler.loadLiteralNull(); | 1557 assembler.loadLiteralNull(); |
1553 } else if (visitState == VisitState.Test) { | 1558 } else if (visitState == VisitState.Test) { |
1554 assembler.branch(falseLabel); | 1559 if (falseLabel != null) assembler.branch(falseLabel); |
1555 } | 1560 } |
1556 } | 1561 } |
1557 | 1562 |
1558 void visitLiteralSymbol(LiteralSymbol node) { | 1563 void visitLiteralSymbol(LiteralSymbol node) { |
1559 int constId = allocateConstantFromNode(node); | 1564 int constId = allocateConstantFromNode(node); |
1560 assembler.loadConst(constId); | 1565 assembler.loadConst(constId); |
1561 applyVisitState(); | 1566 applyVisitState(); |
1562 } | 1567 } |
1563 | 1568 |
1564 void visitLiteralBool(LiteralBool node) { | 1569 void visitLiteralBool(LiteralBool node) { |
(...skipping 26 matching lines...) Expand all Loading... | |
1591 node, | 1596 node, |
1592 'Program compiled without support for big integers'); | 1597 'Program compiled without support for big integers'); |
1593 } else { | 1598 } else { |
1594 int constId = allocateConstantFromNode(node); | 1599 int constId = allocateConstantFromNode(node); |
1595 assembler.loadConst(constId); | 1600 assembler.loadConst(constId); |
1596 } | 1601 } |
1597 } else { | 1602 } else { |
1598 assembler.loadLiteral(value); | 1603 assembler.loadLiteral(value); |
1599 } | 1604 } |
1600 } else if (visitState == VisitState.Test) { | 1605 } else if (visitState == VisitState.Test) { |
1601 assembler.branch(falseLabel); | 1606 if (falseLabel != null) assembler.branch(falseLabel); |
1602 } | 1607 } |
1603 } | 1608 } |
1604 | 1609 |
1605 void visitLiteral(Literal node) { | 1610 void visitLiteral(Literal node) { |
1606 if (visitState == VisitState.Value) { | 1611 if (visitState == VisitState.Value) { |
1607 assembler.loadConst(allocateConstantFromNode(node)); | 1612 assembler.loadConst(allocateConstantFromNode(node)); |
1608 } else if (visitState == VisitState.Test) { | 1613 } else if (visitState == VisitState.Test) { |
1609 assembler.branch(falseLabel); | 1614 if (falseLabel != null) assembler.branch(falseLabel); |
1610 } | 1615 } |
1611 } | 1616 } |
1612 | 1617 |
1613 void visitLiteralList(LiteralList node) { | 1618 void visitLiteralList(LiteralList node) { |
1614 if (node.isConst) { | 1619 if (node.isConst) { |
1615 int constId = allocateConstantFromNode(node); | 1620 int constId = allocateConstantFromNode(node); |
1616 assembler.loadConst(constId); | 1621 assembler.loadConst(constId); |
1617 applyVisitState(); | 1622 applyVisitState(); |
1618 return; | 1623 return; |
1619 } | 1624 } |
1620 ClassElement literalClass = context.backend.growableListClass; | 1625 ClassElement literalClass = context.backend.growableListClass; |
1621 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); | 1626 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); |
1622 if (constructor == null) { | 1627 if (constructor == null) { |
1623 internalError(node, "Failed to lookup default list constructor"); | 1628 internalError(node, "Failed to lookup default list constructor"); |
1624 } | 1629 } |
1625 // Call with empty arguments, as we call the default constructor. | 1630 // Call with empty arguments, as we call the default constructor. |
1626 callConstructor( | 1631 callConstructor( |
1627 node, constructor, new NodeList.empty(), CallStructure.NO_ARGS); | 1632 node, constructor, new NodeList.empty(), CallStructure.NO_ARGS); |
1628 Selector add = new Selector.call('add', null, 1); | 1633 Selector add = new Selector.call(new Name('add', null), |
1634 CallStructure.ONE_ARG); | |
1629 for (Node element in node.elements) { | 1635 for (Node element in node.elements) { |
1630 assembler.dup(); | 1636 assembler.dup(); |
1631 visitForValue(element); | 1637 visitForValue(element); |
1632 invokeMethod(node, add); | 1638 invokeMethod(node, add); |
1633 assembler.pop(); | 1639 assembler.pop(); |
1634 } | 1640 } |
1635 applyVisitState(); | 1641 applyVisitState(); |
1636 } | 1642 } |
1637 | 1643 |
1638 void visitLiteralMap(LiteralMap node) { | 1644 void visitLiteralMap(LiteralMap node) { |
1639 if (node.isConst) { | 1645 if (node.isConst) { |
1640 int constId = allocateConstantFromNode(node); | 1646 int constId = allocateConstantFromNode(node); |
1641 assembler.loadConst(constId); | 1647 assembler.loadConst(constId); |
1642 applyVisitState(); | 1648 applyVisitState(); |
1643 return; | 1649 return; |
1644 } | 1650 } |
1645 ClassElement literalClass = context.backend.mapImplementation; | 1651 ClassElement literalClass = |
1646 ConstructorElement constructor = literalClass.lookupDefaultConstructor(); | 1652 context.backend.mapImplementation.implementation; |
1653 ConstructorElement constructor = literalClass.lookupConstructor(""); | |
1647 if (constructor == null) { | 1654 if (constructor == null) { |
1648 internalError(literalClass, "Failed to lookup default map constructor"); | 1655 internalError(literalClass, "Failed to lookup default map constructor"); |
1649 return; | 1656 return; |
1650 } | 1657 } |
1651 // The default constructor is a redirecting factory constructor. Follow it. | 1658 // The default constructor is a redirecting factory constructor. Follow it. |
1652 constructor = constructor.effectiveTarget; | 1659 constructor = constructor.effectiveTarget; |
1653 FletchFunctionBase function = requireFunction(constructor.declaration); | 1660 FletchFunctionBase function = requireFunction(constructor.declaration); |
1654 doStaticFunctionInvoke( | 1661 doStaticFunctionInvoke( |
1655 node, | 1662 node, |
1656 function, | 1663 function, |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1881 Send node, | 1888 Send node, |
1882 FieldElement field, | 1889 FieldElement field, |
1883 IncDecOperator operator, | 1890 IncDecOperator operator, |
1884 _) { | 1891 _) { |
1885 doStaticFieldPrefix(node, field, operator); | 1892 doStaticFieldPrefix(node, field, operator); |
1886 applyVisitState(); | 1893 applyVisitState(); |
1887 } | 1894 } |
1888 | 1895 |
1889 void doDynamicPropertyCompound( | 1896 void doDynamicPropertyCompound( |
1890 Node node, | 1897 Node node, |
1898 Name name, | |
1891 AssignmentOperator operator, | 1899 AssignmentOperator operator, |
1892 Node rhs, | 1900 Node rhs) { |
1893 Selector getterSelector, | |
1894 Selector setterSelector) { | |
1895 // Dup receiver for setter. | 1901 // Dup receiver for setter. |
1896 assembler.dup(); | 1902 assembler.dup(); |
1897 invokeGetter(node, getterSelector); | 1903 invokeGetter(node, name); |
1898 visitForValue(rhs); | 1904 visitForValue(rhs); |
1899 invokeMethod(node, getAssignmentSelector(operator)); | 1905 invokeMethod(node, getAssignmentSelector(operator)); |
1900 invokeSetter(node, setterSelector); | 1906 invokeSetter(node, name); |
1901 } | 1907 } |
1902 | 1908 |
1903 void visitDynamicPropertyCompound( | 1909 void visitDynamicPropertyCompound( |
1904 Send node, | 1910 Send node, |
1905 Node receiver, | 1911 Node receiver, |
1912 Name name, | |
1906 AssignmentOperator operator, | 1913 AssignmentOperator operator, |
1907 Node rhs, | 1914 Node rhs, |
1908 Selector getterSelector, | |
1909 Selector setterSelector, | |
1910 _) { | 1915 _) { |
1911 visitForValue(receiver); | 1916 visitForValue(receiver); |
1912 doDynamicPropertyCompound( | 1917 doDynamicPropertyCompound( |
1913 node, | 1918 node, |
1919 name, | |
1914 operator, | 1920 operator, |
1915 rhs, | 1921 rhs); |
1916 getterSelector, | |
1917 setterSelector); | |
1918 applyVisitState(); | 1922 applyVisitState(); |
1919 } | 1923 } |
1920 | 1924 |
1921 void visitIfNotNullDynamicPropertyCompound( | 1925 void visitIfNotNullDynamicPropertyCompound( |
1922 Send node, | 1926 Send node, |
1923 Node receiver, | 1927 Node receiver, |
1928 Name name, | |
1924 AssignmentOperator operator, | 1929 AssignmentOperator operator, |
1925 Node rhs, | 1930 Node rhs, |
1926 Selector getterSelector, | |
1927 Selector setterSelector, | |
1928 _) { | 1931 _) { |
1929 doIfNotNull(receiver, () { | 1932 doIfNotNull(receiver, () { |
1930 doDynamicPropertyCompound( | 1933 doDynamicPropertyCompound( |
1931 node, | 1934 node, |
1935 name, | |
1932 operator, | 1936 operator, |
1933 rhs, | 1937 rhs); |
1934 getterSelector, | |
1935 setterSelector); | |
1936 }); | 1938 }); |
1937 applyVisitState(); | 1939 applyVisitState(); |
1938 } | 1940 } |
1939 | 1941 |
1940 void visitThisPropertyCompound( | 1942 void visitThisPropertyCompound( |
1941 Send node, | 1943 Send node, |
1944 Name name, | |
1942 AssignmentOperator operator, | 1945 AssignmentOperator operator, |
1943 Node rhs, | 1946 Node rhs, |
1944 Selector getterSelector, | |
1945 Selector setterSelector, | |
1946 _) { | 1947 _) { |
1947 loadThis(); | 1948 loadThis(); |
1948 doDynamicPropertyCompound( | 1949 doDynamicPropertyCompound( |
1949 node, | 1950 node, |
1951 name, | |
1950 operator, | 1952 operator, |
1951 rhs, | 1953 rhs); |
1952 getterSelector, | |
1953 setterSelector); | |
1954 applyVisitState(); | 1954 applyVisitState(); |
1955 } | 1955 } |
1956 | 1956 |
1957 void doDynamicPrefix( | 1957 void doDynamicPrefix( |
1958 Node node, | 1958 Node node, |
1959 IncDecOperator operator, | 1959 Name name, |
1960 Selector getterSelector, | 1960 IncDecOperator operator) { |
1961 Selector setterSelector) { | |
1962 assembler.dup(); | 1961 assembler.dup(); |
1963 invokeGetter(node, getterSelector); | 1962 invokeGetter(node, name); |
1964 assembler.loadLiteral(1); | 1963 assembler.loadLiteral(1); |
1965 invokeMethod(node, getIncDecSelector(operator)); | 1964 invokeMethod(node, getIncDecSelector(operator)); |
1966 invokeSetter(node, setterSelector); | 1965 invokeSetter(node, name); |
1967 } | 1966 } |
1968 | 1967 |
1969 void doIndexPrefix( | 1968 void doIndexPrefix( |
1970 SendSet node, | 1969 SendSet node, |
1971 Node receiver, | 1970 Node receiver, |
1972 Node index, | 1971 Node index, |
1973 IncDecOperator operator) { | 1972 IncDecOperator operator) { |
1974 visitForValue(receiver); | 1973 visitForValue(receiver); |
1975 visitForValue(index); | 1974 visitForValue(index); |
1976 // Load already evaluated receiver and index for '[]' call. | 1975 // Load already evaluated receiver and index for '[]' call. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2037 invokeMethod(node, new Selector.index()); | 2036 invokeMethod(node, new Selector.index()); |
2038 visitForValue(rhs); | 2037 visitForValue(rhs); |
2039 invokeMethod(node, getAssignmentSelector(operator)); | 2038 invokeMethod(node, getAssignmentSelector(operator)); |
2040 // Use existing evaluated receiver and index for '[]=' call. | 2039 // Use existing evaluated receiver and index for '[]=' call. |
2041 invokeMethod(node, new Selector.indexSet()); | 2040 invokeMethod(node, new Selector.indexSet()); |
2042 applyVisitState(); | 2041 applyVisitState(); |
2043 } | 2042 } |
2044 | 2043 |
2045 void visitThisPropertyPrefix( | 2044 void visitThisPropertyPrefix( |
2046 Send node, | 2045 Send node, |
2046 Name name, | |
2047 IncDecOperator operator, | 2047 IncDecOperator operator, |
2048 Selector getterSelector, | |
2049 Selector setterSelector, | |
2050 _) { | 2048 _) { |
2051 loadThis(); | 2049 loadThis(); |
2052 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2050 doDynamicPrefix(node, name, operator); |
2053 applyVisitState(); | 2051 applyVisitState(); |
2054 } | 2052 } |
2055 | 2053 |
2056 void visitThisPropertyPostfix( | 2054 void visitThisPropertyPostfix( |
2057 Send node, | 2055 Send node, |
2056 Name name, | |
2058 IncDecOperator operator, | 2057 IncDecOperator operator, |
2059 Selector getterSelector, | |
2060 Selector setterSelector, | |
2061 _) { | 2058 _) { |
2062 // If visitState is for effect, we can ignore the return value, thus always | 2059 // If visitState is for effect, we can ignore the return value, thus always |
2063 // generate code for the simpler 'prefix' case. | 2060 // generate code for the simpler 'prefix' case. |
2064 if (visitState == VisitState.Effect) { | 2061 if (visitState == VisitState.Effect) { |
2065 loadThis(); | 2062 loadThis(); |
2066 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2063 doDynamicPrefix(node, name, operator); |
2067 applyVisitState(); | 2064 applyVisitState(); |
2068 return; | 2065 return; |
2069 } | 2066 } |
2070 | 2067 |
2071 loadThis(); | 2068 loadThis(); |
2072 invokeGetter(node, getterSelector); | 2069 invokeGetter(node, name); |
2073 // For postfix, keep local, unmodified version, to 'return' after store. | 2070 // For postfix, keep local, unmodified version, to 'return' after store. |
2074 assembler.dup(); | 2071 assembler.dup(); |
2075 assembler.loadLiteral(1); | 2072 assembler.loadLiteral(1); |
2076 invokeMethod(node, getIncDecSelector(operator)); | 2073 invokeMethod(node, getIncDecSelector(operator)); |
2077 loadThis(); | 2074 loadThis(); |
2078 assembler.loadLocal(1); | 2075 assembler.loadLocal(1); |
2079 invokeSetter(node, setterSelector); | 2076 invokeSetter(node, name); |
2080 assembler.popMany(2); | 2077 assembler.popMany(2); |
2081 applyVisitState(); | 2078 applyVisitState(); |
2082 } | 2079 } |
2083 | 2080 |
2084 void visitDynamicPropertyPrefix( | 2081 void visitDynamicPropertyPrefix( |
2085 Send node, | 2082 Send node, |
2086 Node receiver, | 2083 Node receiver, |
2084 Name name, | |
2087 IncDecOperator operator, | 2085 IncDecOperator operator, |
2088 Selector getterSelector, | |
2089 Selector setterSelector, | |
2090 _) { | 2086 _) { |
2091 visitForValue(receiver); | 2087 visitForValue(receiver); |
2092 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2088 doDynamicPrefix(node, name, operator); |
2093 applyVisitState(); | 2089 applyVisitState(); |
2094 } | 2090 } |
2095 | 2091 |
2096 void visitIfNotNullDynamicPropertyPrefix( | 2092 void visitIfNotNullDynamicPropertyPrefix( |
2097 Send node, | 2093 Send node, |
2098 Node receiver, | 2094 Node receiver, |
2095 Name name, | |
2099 IncDecOperator operator, | 2096 IncDecOperator operator, |
2100 Selector getterSelector, | |
2101 Selector setterSelector, | |
2102 _) { | 2097 _) { |
2103 doIfNotNull(receiver, () { | 2098 doIfNotNull(receiver, () { |
2104 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2099 doDynamicPrefix(node, name, operator); |
2105 }); | 2100 }); |
2106 applyVisitState(); | 2101 applyVisitState(); |
2107 } | 2102 } |
2108 | 2103 |
2109 void doDynamicPostfix( | 2104 void doDynamicPostfix( |
2110 Send node, | 2105 Send node, |
2111 Node receiver, | 2106 Node receiver, |
2112 IncDecOperator operator, | 2107 Name name, |
2113 Selector getterSelector, | 2108 IncDecOperator operator) { |
2114 Selector setterSelector) { | |
2115 int receiverSlot = assembler.stackSize - 1; | 2109 int receiverSlot = assembler.stackSize - 1; |
2116 assembler.loadSlot(receiverSlot); | 2110 assembler.loadSlot(receiverSlot); |
2117 invokeGetter(node, getterSelector); | 2111 invokeGetter(node, name); |
2118 // For postfix, keep local, unmodified version, to 'return' after store. | 2112 // For postfix, keep local, unmodified version, to 'return' after store. |
2119 assembler.dup(); | 2113 assembler.dup(); |
2120 assembler.loadLiteral(1); | 2114 assembler.loadLiteral(1); |
2121 invokeMethod(node, getIncDecSelector(operator)); | 2115 invokeMethod(node, getIncDecSelector(operator)); |
2122 assembler.loadSlot(receiverSlot); | 2116 assembler.loadSlot(receiverSlot); |
2123 assembler.loadLocal(1); | 2117 assembler.loadLocal(1); |
2124 invokeSetter(node, setterSelector); | 2118 invokeSetter(node, name); |
2125 assembler.popMany(2); | 2119 assembler.popMany(2); |
2126 assembler.storeLocal(1); | 2120 assembler.storeLocal(1); |
2127 // Pop receiver. | 2121 // Pop receiver. |
2128 assembler.pop(); | 2122 assembler.pop(); |
2129 } | 2123 } |
2130 | 2124 |
2131 void visitDynamicPropertyPostfix( | 2125 void visitDynamicPropertyPostfix( |
2132 Send node, | 2126 Send node, |
2133 Node receiver, | 2127 Node receiver, |
2128 Name name, | |
2134 IncDecOperator operator, | 2129 IncDecOperator operator, |
2135 Selector getterSelector, | |
2136 Selector setterSelector, | |
2137 _) { | 2130 _) { |
2138 // If visitState is for effect, we can ignore the return value, thus always | 2131 // If visitState is for effect, we can ignore the return value, thus always |
2139 // generate code for the simpler 'prefix' case. | 2132 // generate code for the simpler 'prefix' case. |
2140 if (visitState == VisitState.Effect) { | 2133 if (visitState == VisitState.Effect) { |
2141 visitForValue(receiver); | 2134 visitForValue(receiver); |
2142 doDynamicPrefix(node, operator, getterSelector, setterSelector); | 2135 doDynamicPrefix(node, name, operator); |
2143 applyVisitState(); | 2136 applyVisitState(); |
2144 return; | 2137 return; |
2145 } | 2138 } |
2146 | 2139 |
2147 visitForValue(receiver); | 2140 visitForValue(receiver); |
2148 doDynamicPostfix(node, receiver, operator, getterSelector, setterSelector); | 2141 doDynamicPostfix(node, receiver, name, operator); |
2149 applyVisitState(); | 2142 applyVisitState(); |
2150 } | 2143 } |
2151 | 2144 |
2152 void visitIfNotNullDynamicPropertyPostfix( | 2145 void visitIfNotNullDynamicPropertyPostfix( |
2153 Send node, | 2146 Send node, |
2154 Node receiver, | 2147 Node receiver, |
2148 Name name, | |
2155 IncDecOperator operator, | 2149 IncDecOperator operator, |
2156 Selector getterSelector, | |
2157 Selector setterSelector, | |
2158 _) { | 2150 _) { |
2159 doIfNotNull(receiver, () { | 2151 doIfNotNull(receiver, () { |
2160 doDynamicPostfix( | 2152 doDynamicPostfix( |
2161 node,receiver, operator, getterSelector, setterSelector); | 2153 node, receiver, name, operator); |
2162 }); | 2154 }); |
2163 applyVisitState(); | 2155 applyVisitState(); |
2164 } | 2156 } |
2165 | 2157 |
2166 void visitThrow(Throw node) { | 2158 void visitThrow(Throw node) { |
2167 visitForValue(node.expression); | 2159 visitForValue(node.expression); |
2168 assembler.emitThrow(); | 2160 assembler.emitThrow(); |
2169 // TODO(ahe): It seems suboptimal that each throw is followed by a pop. | 2161 // TODO(ahe): It seems suboptimal that each throw is followed by a pop. |
2170 applyVisitState(); | 2162 applyVisitState(); |
2171 } | 2163 } |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2747 void visitSyncForIn(SyncForIn node) { | 2739 void visitSyncForIn(SyncForIn node) { |
2748 visitForIn(node); | 2740 visitForIn(node); |
2749 } | 2741 } |
2750 | 2742 |
2751 void visitForIn(ForIn node) { | 2743 void visitForIn(ForIn node) { |
2752 BytecodeLabel start = new BytecodeLabel(); | 2744 BytecodeLabel start = new BytecodeLabel(); |
2753 BytecodeLabel end = new BytecodeLabel(); | 2745 BytecodeLabel end = new BytecodeLabel(); |
2754 | 2746 |
2755 // Evalutate expression and iterator. | 2747 // Evalutate expression and iterator. |
2756 visitForValue(node.expression); | 2748 visitForValue(node.expression); |
2757 invokeGetter(node.expression, new Selector.getter('iterator', null)); | 2749 invokeGetter(node.expression, Names.iterator); |
2758 | 2750 |
2759 jumpInfo[node] = new JumpInfo(assembler.stackSize, start, end); | 2751 jumpInfo[node] = new JumpInfo(assembler.stackSize, start, end); |
2760 | 2752 |
2761 assembler.bind(start); | 2753 assembler.bind(start); |
2762 | 2754 |
2763 assembler.dup(); | 2755 assembler.dup(); |
2764 invokeMethod(node, new Selector.call('moveNext', null, 0)); | 2756 invokeMethod(node, Selectors.moveNext); |
2765 assembler.branchIfFalse(end); | 2757 assembler.branchIfFalse(end); |
2766 | 2758 |
2767 bool isVariableDeclaration = node.declaredIdentifier.asSend() == null; | 2759 bool isVariableDeclaration = node.declaredIdentifier.asSend() == null; |
2768 Element element = elements[node]; | 2760 Element element = elements[node]; |
2769 if (isVariableDeclaration) { | 2761 if (isVariableDeclaration) { |
2770 // Create local value and load the current element to it. | 2762 // Create local value and load the current element to it. |
2771 LocalValue value = createLocalValueFor(element); | 2763 LocalValue value = createLocalValueFor(element); |
2772 assembler.dup(); | 2764 assembler.dup(); |
2773 invokeGetter(node, new Selector.getter('current', null)); | 2765 invokeGetter(node, Names.current); |
2774 value.initialize(assembler); | 2766 value.initialize(assembler); |
2775 pushVariableDeclaration(value); | 2767 pushVariableDeclaration(value); |
2776 } else { | 2768 } else { |
2777 if (element == null || element.isInstanceMember) { | 2769 if (element == null || element.isInstanceMember) { |
2778 loadThis(); | 2770 loadThis(); |
2779 assembler.loadLocal(1); | 2771 assembler.loadLocal(1); |
2780 invokeGetter(node, new Selector.getter('current', null)); | 2772 invokeGetter(node, Names.current); |
2781 Selector selector = elements.getSelector(node.declaredIdentifier); | 2773 Selector selector = elements.getSelector(node.declaredIdentifier); |
2782 invokeSetter(node, selector); | 2774 invokeSetter(node, selector.memberName); |
2783 } else { | 2775 } else { |
2784 assembler.dup(); | 2776 assembler.dup(); |
2785 invokeGetter(node, new Selector.getter('current', null)); | 2777 invokeGetter(node, Names.current); |
2786 if (element.isLocal) { | 2778 if (element.isLocal) { |
2787 scope[element].store(assembler); | 2779 scope[element].store(assembler); |
2788 } else if (element.isField) { | 2780 } else if (element.isField) { |
2789 doStaticFieldSet(element); | 2781 doStaticFieldSet(element); |
2790 } else if (element.isErroneous) { | 2782 } else if (element.isMalformed) { |
2791 doUnresolved(element.name); | 2783 doUnresolved(element.name); |
2792 assembler.pop(); | 2784 assembler.pop(); |
2793 } else { | 2785 } else { |
2794 internalError(node, "Unhandled store in for-in"); | 2786 internalError(node, "Unhandled store in for-in"); |
2795 } | 2787 } |
2796 } | 2788 } |
2797 assembler.pop(); | 2789 assembler.pop(); |
2798 } | 2790 } |
2799 | 2791 |
2800 doScopedStatement(node.body); | 2792 doScopedStatement(node.body); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3092 NodeList arguments, | 3084 NodeList arguments, |
3093 CallStructure callStructure, | 3085 CallStructure callStructure, |
3094 _) { | 3086 _) { |
3095 if (!checkCompileError(function)) { | 3087 if (!checkCompileError(function)) { |
3096 doUnresolved(function.name); | 3088 doUnresolved(function.name); |
3097 } | 3089 } |
3098 applyVisitState(); | 3090 applyVisitState(); |
3099 } | 3091 } |
3100 | 3092 |
3101 void internalError(Spannable spannable, String reason) { | 3093 void internalError(Spannable spannable, String reason) { |
3102 context.compiler.internalError(spannable, reason); | 3094 context.compiler.reporter.internalError(spannable, reason); |
3103 } | 3095 } |
3104 | 3096 |
3105 void generateUnimplementedError(Spannable spannable, String reason) { | 3097 void generateUnimplementedError(Spannable spannable, String reason) { |
3106 context.backend.generateUnimplementedError( | 3098 context.backend.generateUnimplementedError( |
3107 spannable, | 3099 spannable, |
3108 reason, | 3100 reason, |
3109 functionBuilder); | 3101 functionBuilder); |
3110 } | 3102 } |
3111 | 3103 |
3112 String toString() => "FunctionCompiler(${element.name})"; | 3104 String toString() => "FunctionCompiler(${element.name})"; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3164 void handleStaticFunctionSet( | 3156 void handleStaticFunctionSet( |
3165 SendSet node, | 3157 SendSet node, |
3166 MethodElement function, | 3158 MethodElement function, |
3167 Node rhs, | 3159 Node rhs, |
3168 _) { | 3160 _) { |
3169 generateUnimplementedError( | 3161 generateUnimplementedError( |
3170 node, "[handleStaticFunctionSet] isn't implemented."); | 3162 node, "[handleStaticFunctionSet] isn't implemented."); |
3171 applyVisitState(); | 3163 applyVisitState(); |
3172 } | 3164 } |
3173 | 3165 |
3166 @override | |
3167 void bulkHandleSetIfNull(Node node, _) { | |
3168 generateUnimplementedError( | |
3169 node, "[bulkHandleSetIfNull] isn't implemented."); | |
3170 applyVisitState(); | |
3171 } | |
3172 | |
3174 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { | 3173 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { |
3175 // We don't support deferred access, so nothing to do for now. | 3174 // We don't support deferred access, so nothing to do for now. |
3176 } | 3175 } |
3177 | 3176 |
3178 void bulkHandleNode(Node node, String msg, _) { | 3177 void bulkHandleNode(Node node, String msg, _) { |
3179 generateUnimplementedError(node, msg.replaceAll('#', node.toString())); | 3178 generateUnimplementedError(node, msg.replaceAll('#', node.toString())); |
3180 applyVisitState(); | 3179 applyVisitState(); |
3181 } | 3180 } |
3182 | 3181 |
3183 void visitNode(Node node) { | 3182 void visitNode(Node node) { |
(...skipping 10 matching lines...) Expand all Loading... | |
3194 | 3193 |
3195 void applyParameters(NodeList parameters, _) { | 3194 void applyParameters(NodeList parameters, _) { |
3196 internalError(parameters, "[applyParameters] isn't implemented."); | 3195 internalError(parameters, "[applyParameters] isn't implemented."); |
3197 } | 3196 } |
3198 } | 3197 } |
3199 | 3198 |
3200 abstract class FletchRegistryMixin { | 3199 abstract class FletchRegistryMixin { |
3201 FletchRegistry get registry; | 3200 FletchRegistry get registry; |
3202 FletchContext get context; | 3201 FletchContext get context; |
3203 | 3202 |
3204 void registerDynamicInvocation(Selector selector) { | 3203 void registerDynamicUse(Selector selector) { |
3205 registry.registerDynamicInvocation(new UniverseSelector(selector, null)); | 3204 registry.registerDynamicUse(selector); |
3206 } | 3205 } |
3207 | 3206 |
3208 void registerDynamicGetter(Selector selector) { | 3207 void registerStaticUse(StaticUse staticUse) { |
3209 registry.registerDynamicGetter(new UniverseSelector(selector, null)); | 3208 registry.registerStaticUse(staticUse); |
3210 } | |
3211 | |
3212 void registerDynamicSetter(Selector selector) { | |
3213 registry.registerDynamicSetter(new UniverseSelector(selector, null)); | |
3214 } | |
3215 | |
3216 void registerStaticInvocation(FunctionElement function) { | |
3217 registry.registerStaticInvocation(function); | |
3218 } | 3209 } |
3219 | 3210 |
3220 void registerInstantiatedClass(ClassElement klass) { | 3211 void registerInstantiatedClass(ClassElement klass) { |
3221 registry.registerInstantiatedClass(klass); | 3212 registry.registerInstantiatedClass(klass); |
3222 } | 3213 } |
3223 | 3214 |
3224 void registerIsCheck(DartType type) { | 3215 void registerIsCheck(DartType type) { |
3225 registry.registerIsCheck(type); | 3216 registry.registerIsCheck(type); |
3226 } | 3217 } |
3227 | 3218 |
3228 void registerLocalInvoke(LocalElement element, Selector selector) { | 3219 void registerLocalInvoke(LocalElement element, Selector selector) { |
3229 registry.registerLocalInvoke(element, selector); | 3220 registry.registerLocalInvoke(element, selector); |
3230 } | 3221 } |
3231 | 3222 |
3232 void registerClosurization(FunctionElement element, ClosureKind kind) { | 3223 void registerClosurization(FunctionElement element, ClosureKind kind) { |
3233 if (kind == ClosureKind.localFunction) { | 3224 if (kind == ClosureKind.localFunction) { |
3234 // TODO(ahe): Get rid of the call to [registerStaticInvocation]. It is | 3225 // TODO(ahe): Get rid of the call to [registerStaticUse]. It is |
3235 // currently needed to ensure that local function expression closures are | 3226 // currently needed to ensure that local function expression closures are |
3236 // compiled correctly. For example, `[() {}].last()`, notice that `last` | 3227 // compiled correctly. For example, `[() {}].last()`, notice that `last` |
3237 // is a getter. This happens for both named and unnamed. | 3228 // is a getter. This happens for both named and unnamed. |
3238 registerStaticInvocation(element); | 3229 registerStaticUse(new StaticUse.foreignUse(element)); |
3239 } | 3230 } |
3240 registry.registerClosurization(element, kind); | 3231 registry.registerClosurization(element, kind); |
3241 } | 3232 } |
3242 | 3233 |
3243 int compileLazyFieldInitializer(FieldElement field) { | 3234 int compileLazyFieldInitializer(FieldElement field) { |
3244 return context.backend.compileLazyFieldInitializer(field, registry); | 3235 return context.backend.compileLazyFieldInitializer(field, registry); |
3245 } | 3236 } |
3246 } | 3237 } |
OLD | NEW |