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 |
360 if (glue.isStringClass(clazz)) { | 372 if (glue.isStringClass(clazz)) { |
361 if (node.isTypeTest) { | 373 if (node.isTypeTest) { |
362 return js.js(r'typeof # === "string"', <js.Expression>[value]); | 374 return js.js(r'typeof # === "string"', <js.Expression>[value]); |
363 } | 375 } |
364 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. | 376 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. |
365 } else if (glue.isBoolClass(clazz)) { | 377 } else if (glue.isBoolClass(clazz)) { |
366 if (node.isTypeTest) { | 378 if (node.isTypeTest) { |
367 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); | 379 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); |
368 } | 380 } |
369 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. | 381 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 js.Expression typeValue = typeArguments.single; | 421 js.Expression typeValue = typeArguments.single; |
410 | 422 |
411 return buildStaticHelperInvocation( | 423 return buildStaticHelperInvocation( |
412 function, | 424 function, |
413 <js.Expression>[value, typeValue]); | 425 <js.Expression>[value, typeValue]); |
414 } | 426 } |
415 return giveup(node, 'type check unimplemented for $type.'); | 427 return giveup(node, 'type check unimplemented for $type.'); |
416 } | 428 } |
417 | 429 |
418 @override | 430 @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 | |
429 js.Expression visitVariableUse(tree_ir.VariableUse node) { | 431 js.Expression visitVariableUse(tree_ir.VariableUse node) { |
430 return buildVariableAccess(node.variable); | 432 return buildVariableAccess(node.variable); |
431 } | 433 } |
432 | 434 |
433 js.Expression buildVariableAccess(tree_ir.Variable variable) { | 435 js.Expression buildVariableAccess(tree_ir.Variable variable) { |
434 return new js.VariableUse(getVariableName(variable)); | 436 return new js.VariableUse(getVariableName(variable)); |
435 } | 437 } |
436 | 438 |
437 @override | 439 @override |
438 js.Expression visitAssign(tree_ir.Assign node) { | 440 js.Expression visitAssign(tree_ir.Assign node) { |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 return buildStaticHelperInvocation( | 812 return buildStaticHelperInvocation( |
811 glue.getTypeArgumentByIndex(), | 813 glue.getTypeArgumentByIndex(), |
812 [visitExpression(node.target), index], | 814 [visitExpression(node.target), index], |
813 sourceInformation: node.sourceInformation); | 815 sourceInformation: node.sourceInformation); |
814 } | 816 } |
815 } | 817 } |
816 | 818 |
817 @override | 819 @override |
818 js.Expression visitTypeExpression(tree_ir.TypeExpression node) { | 820 js.Expression visitTypeExpression(tree_ir.TypeExpression node) { |
819 List<js.Expression> arguments = visitExpressionList(node.arguments); | 821 List<js.Expression> arguments = visitExpressionList(node.arguments); |
820 return glue.generateTypeRepresentation(node.dartType, arguments, registry); | 822 return glue.generateTypeRepresentation(node.dartType, arguments); |
821 } | 823 } |
822 | 824 |
823 js.Node handleForeignCode(tree_ir.ForeignCode node) { | 825 js.Node handleForeignCode(tree_ir.ForeignCode node) { |
824 registry.registerStaticUse(node.dependency); | 826 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); | |
906 } | 896 } |
907 } | 897 } |
908 | 898 |
909 /// The JS name of a built-in method. | 899 /// The JS name of a built-in method. |
910 static final Map<BuiltinMethod, String> builtinMethodName = | 900 static final Map<BuiltinMethod, String> builtinMethodName = |
911 const <BuiltinMethod, String>{ | 901 const <BuiltinMethod, String>{ |
912 BuiltinMethod.Push: 'push', | 902 BuiltinMethod.Push: 'push', |
913 BuiltinMethod.Pop: 'pop', | 903 BuiltinMethod.Pop: 'pop', |
914 }; | 904 }; |
915 | 905 |
916 @override | 906 @override |
917 js.Expression visitApplyBuiltinMethod(tree_ir.ApplyBuiltinMethod node) { | 907 js.Expression visitApplyBuiltinMethod(tree_ir.ApplyBuiltinMethod node) { |
918 String name = builtinMethodName[node.method]; | 908 String name = builtinMethodName[node.method]; |
919 js.Expression receiver = visitExpression(node.receiver); | 909 js.Expression receiver = visitExpression(node.receiver); |
920 List<js.Expression> args = visitExpressionList(node.arguments); | 910 List<js.Expression> args = visitExpressionList(node.arguments); |
921 return js.js('#.#(#)', [receiver, name, args]); | 911 return js.js('#.#(#)', [receiver, name, args]); |
922 } | 912 } |
923 | 913 |
924 @override | 914 @override |
925 js.Expression visitAwait(tree_ir.Await node) { | 915 js.Expression visitAwait(tree_ir.Await node) { |
926 return new js.Await(visitExpression(node.input)); | 916 return new js.Await(visitExpression(node.input)); |
927 } | 917 } |
928 | 918 |
929 visitFunctionExpression(tree_ir.FunctionExpression node) { | 919 visitFunctionExpression(tree_ir.FunctionExpression node) { |
930 // FunctionExpressions are currently unused. | 920 // FunctionExpressions are currently unused. |
931 // We might need them if we want to emit raw JS nested functions. | 921 // We might need them if we want to emit raw JS nested functions. |
932 throw 'FunctionExpressions should not be used'; | 922 throw 'FunctionExpressions should not be used'; |
933 } | 923 } |
934 } | 924 } |
OLD | NEW |