OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 | 4 |
5 library code_generator; | 5 library code_generator; |
6 | 6 |
7 import 'glue.dart'; | 7 import 'glue.dart'; |
8 | 8 |
9 import '../../closure.dart' show ClosureClassElement; | 9 import '../../closure.dart' show ClosureClassElement; |
10 import '../../common/codegen.dart' show CodegenRegistry; | 10 import '../../common/codegen.dart' show CodegenRegistry; |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 350 |
351 @override | 351 @override |
352 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { | 352 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { |
353 js.Expression value = visitExpression(node.value); | 353 js.Expression value = visitExpression(node.value); |
354 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments); | 354 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments); |
355 DartType type = node.type; | 355 DartType type = node.type; |
356 if (type is InterfaceType) { | 356 if (type is InterfaceType) { |
357 glue.registerIsCheck(type, registry); | 357 glue.registerIsCheck(type, registry); |
358 ClassElement clazz = type.element; | 358 ClassElement clazz = type.element; |
359 | 359 |
360 // Handle some special checks against classes that exist only in | |
361 // the compile-time class hierarchy, not at runtime. | |
362 // TODO(sra): Is this correct? The field tests are only valid with the | |
363 // precondition that [value] is an Array. They will crash on `null`. | |
364 if (clazz == glue.jsExtendableArrayClass) { | |
365 assert(node.isTypeTest); | |
366 return js.js(r'!#.fixed$length', <js.Expression>[value]); | |
367 } else if (clazz == glue.jsMutableArrayClass) { | |
368 assert(node.isTypeTest); | |
369 return js.js(r'!#.immutable$list', <js.Expression>[value]); | |
370 } | |
371 | |
372 if (glue.isStringClass(clazz)) { | 360 if (glue.isStringClass(clazz)) { |
373 if (node.isTypeTest) { | 361 if (node.isTypeTest) { |
374 return js.js(r'typeof # === "string"', <js.Expression>[value]); | 362 return js.js(r'typeof # === "string"', <js.Expression>[value]); |
375 } | 363 } |
376 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. | 364 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. |
377 } else if (glue.isBoolClass(clazz)) { | 365 } else if (glue.isBoolClass(clazz)) { |
378 if (node.isTypeTest) { | 366 if (node.isTypeTest) { |
379 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); | 367 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); |
380 } | 368 } |
381 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. | 369 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 js.Expression typeValue = typeArguments.single; | 409 js.Expression typeValue = typeArguments.single; |
422 | 410 |
423 return buildStaticHelperInvocation( | 411 return buildStaticHelperInvocation( |
424 function, | 412 function, |
425 <js.Expression>[value, typeValue]); | 413 <js.Expression>[value, typeValue]); |
426 } | 414 } |
427 return giveup(node, 'type check unimplemented for $type.'); | 415 return giveup(node, 'type check unimplemented for $type.'); |
428 } | 416 } |
429 | 417 |
430 @override | 418 @override |
| 419 js.Expression visitGetTypeTestProperty(tree_ir.GetTypeTestProperty node) { |
| 420 js.Expression object = visitExpression(node.object); |
| 421 DartType dartType = node.dartType; |
| 422 assert(dartType.isInterfaceType); |
| 423 glue.registerIsCheck(dartType, registry); |
| 424 js.Expression property = glue.getTypeTestTag(dartType); |
| 425 return js.js(r'#.#', [object, property]); |
| 426 } |
| 427 |
| 428 @override |
431 js.Expression visitVariableUse(tree_ir.VariableUse node) { | 429 js.Expression visitVariableUse(tree_ir.VariableUse node) { |
432 return buildVariableAccess(node.variable); | 430 return buildVariableAccess(node.variable); |
433 } | 431 } |
434 | 432 |
435 js.Expression buildVariableAccess(tree_ir.Variable variable) { | 433 js.Expression buildVariableAccess(tree_ir.Variable variable) { |
436 return new js.VariableUse(getVariableName(variable)); | 434 return new js.VariableUse(getVariableName(variable)); |
437 } | 435 } |
438 | 436 |
439 @override | 437 @override |
440 js.Expression visitAssign(tree_ir.Assign node) { | 438 js.Expression visitAssign(tree_ir.Assign node) { |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 return buildStaticHelperInvocation( | 810 return buildStaticHelperInvocation( |
813 glue.getTypeArgumentByIndex(), | 811 glue.getTypeArgumentByIndex(), |
814 [visitExpression(node.target), index], | 812 [visitExpression(node.target), index], |
815 sourceInformation: node.sourceInformation); | 813 sourceInformation: node.sourceInformation); |
816 } | 814 } |
817 } | 815 } |
818 | 816 |
819 @override | 817 @override |
820 js.Expression visitTypeExpression(tree_ir.TypeExpression node) { | 818 js.Expression visitTypeExpression(tree_ir.TypeExpression node) { |
821 List<js.Expression> arguments = visitExpressionList(node.arguments); | 819 List<js.Expression> arguments = visitExpressionList(node.arguments); |
822 return glue.generateTypeRepresentation(node.dartType, arguments); | 820 return glue.generateTypeRepresentation(node.dartType, arguments, registry); |
823 } | 821 } |
824 | 822 |
825 js.Node handleForeignCode(tree_ir.ForeignCode node) { | 823 js.Node handleForeignCode(tree_ir.ForeignCode node) { |
826 registry.registerStaticUse(node.dependency); | 824 registry.registerStaticUse(node.dependency); |
| 825 // TODO(sra): Should this be in CodegenRegistry? |
| 826 glue.registerNativeBehavior(node.nativeBehavior, node); |
827 return node.codeTemplate.instantiate(visitExpressionList(node.arguments)); | 827 return node.codeTemplate.instantiate(visitExpressionList(node.arguments)); |
828 } | 828 } |
829 | 829 |
830 @override | 830 @override |
831 js.Expression visitForeignExpression(tree_ir.ForeignExpression node) { | 831 js.Expression visitForeignExpression(tree_ir.ForeignExpression node) { |
832 return handleForeignCode(node); | 832 return handleForeignCode(node); |
833 } | 833 } |
834 | 834 |
835 @override | 835 @override |
836 void visitForeignStatement(tree_ir.ForeignStatement node) { | 836 void visitForeignStatement(tree_ir.ForeignStatement node) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
886 case BuiltinOperator.IsFalsy: | 886 case BuiltinOperator.IsFalsy: |
887 return new js.Prefix('!', args[0]); | 887 return new js.Prefix('!', args[0]); |
888 case BuiltinOperator.IsNumber: | 888 case BuiltinOperator.IsNumber: |
889 return js.js('typeof # === "number"', args); | 889 return js.js('typeof # === "number"', args); |
890 case BuiltinOperator.IsNotNumber: | 890 case BuiltinOperator.IsNotNumber: |
891 return js.js('typeof # !== "number"', args); | 891 return js.js('typeof # !== "number"', args); |
892 case BuiltinOperator.IsFloor: | 892 case BuiltinOperator.IsFloor: |
893 return js.js('Math.floor(#) === #', args); | 893 return js.js('Math.floor(#) === #', args); |
894 case BuiltinOperator.IsNumberAndFloor: | 894 case BuiltinOperator.IsNumberAndFloor: |
895 return js.js('typeof # === "number" && Math.floor(#) === #', args); | 895 return js.js('typeof # === "number" && Math.floor(#) === #', args); |
| 896 case BuiltinOperator.IsFixedLengthJSArray: |
| 897 // TODO(sra): Remove boolify (i.e. !!). |
| 898 return js.js(r'!!#.fixed$length', args); |
| 899 case BuiltinOperator.IsExtendableJSArray: |
| 900 return js.js(r'!#.fixed$length', args); |
| 901 case BuiltinOperator.IsModifiableJSArray: |
| 902 return js.js(r'!#.immutable$list', args); |
| 903 case BuiltinOperator.IsUnmodifiableJSArray: |
| 904 // TODO(sra): Remove boolify (i.e. !!). |
| 905 return js.js(r'!!#.immutable$list', args); |
896 } | 906 } |
897 } | 907 } |
898 | 908 |
899 /// The JS name of a built-in method. | 909 /// The JS name of a built-in method. |
900 static final Map<BuiltinMethod, String> builtinMethodName = | 910 static final Map<BuiltinMethod, String> builtinMethodName = |
901 const <BuiltinMethod, String>{ | 911 const <BuiltinMethod, String>{ |
902 BuiltinMethod.Push: 'push', | 912 BuiltinMethod.Push: 'push', |
903 BuiltinMethod.Pop: 'pop', | 913 BuiltinMethod.Pop: 'pop', |
904 }; | 914 }; |
905 | 915 |
906 @override | 916 @override |
907 js.Expression visitApplyBuiltinMethod(tree_ir.ApplyBuiltinMethod node) { | 917 js.Expression visitApplyBuiltinMethod(tree_ir.ApplyBuiltinMethod node) { |
908 String name = builtinMethodName[node.method]; | 918 String name = builtinMethodName[node.method]; |
909 js.Expression receiver = visitExpression(node.receiver); | 919 js.Expression receiver = visitExpression(node.receiver); |
910 List<js.Expression> args = visitExpressionList(node.arguments); | 920 List<js.Expression> args = visitExpressionList(node.arguments); |
911 return js.js('#.#(#)', [receiver, name, args]); | 921 return js.js('#.#(#)', [receiver, name, args]); |
912 } | 922 } |
913 | 923 |
914 @override | 924 @override |
915 js.Expression visitAwait(tree_ir.Await node) { | 925 js.Expression visitAwait(tree_ir.Await node) { |
916 return new js.Await(visitExpression(node.input)); | 926 return new js.Await(visitExpression(node.input)); |
917 } | 927 } |
918 | 928 |
919 visitFunctionExpression(tree_ir.FunctionExpression node) { | 929 visitFunctionExpression(tree_ir.FunctionExpression node) { |
920 // FunctionExpressions are currently unused. | 930 // FunctionExpressions are currently unused. |
921 // We might need them if we want to emit raw JS nested functions. | 931 // We might need them if we want to emit raw JS nested functions. |
922 throw 'FunctionExpressions should not be used'; | 932 throw 'FunctionExpressions should not be used'; |
923 } | 933 } |
924 } | 934 } |
OLD | NEW |