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