| 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 |