| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 native; | 5 library native; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 import 'dart2jslib.dart'; | 8 import 'dart2jslib.dart'; |
| 9 import 'dart_types.dart'; | 9 import 'dart_types.dart'; |
| 10 import 'elements/elements.dart'; | 10 import 'elements/elements.dart'; |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 * `null` may be returned. | 760 * `null` may be returned. |
| 761 */ | 761 */ |
| 762 class NativeBehavior { | 762 class NativeBehavior { |
| 763 | 763 |
| 764 /// [DartType]s or [SpecialType]s returned or yielded by the native element. | 764 /// [DartType]s or [SpecialType]s returned or yielded by the native element. |
| 765 final List typesReturned = []; | 765 final List typesReturned = []; |
| 766 | 766 |
| 767 /// [DartType]s or [SpecialType]s instantiated by the native element. | 767 /// [DartType]s or [SpecialType]s instantiated by the native element. |
| 768 final List typesInstantiated = []; | 768 final List typesInstantiated = []; |
| 769 | 769 |
| 770 // If this behavior is for a JS expression, [codeAst] contains the | 770 // If this behavior is for a JS expression, [codeTemplate] contains the |
| 771 // parsed tree. | 771 // parsed tree. |
| 772 js.Expression codeAst; | 772 js.Template codeTemplate; |
| 773 | 773 |
| 774 final SideEffects sideEffects = new SideEffects.empty(); | 774 final SideEffects sideEffects = new SideEffects.empty(); |
| 775 | 775 |
| 776 static NativeBehavior NONE = new NativeBehavior(); | 776 static NativeBehavior NONE = new NativeBehavior(); |
| 777 | 777 |
| 778 static NativeBehavior ofJsCall(Send jsCall, Compiler compiler, resolver) { | 778 static NativeBehavior ofJsCall(Send jsCall, Compiler compiler, resolver) { |
| 779 // The first argument of a JS-call is a string encoding various attributes | 779 // The first argument of a JS-call is a string encoding various attributes |
| 780 // of the code. | 780 // of the code. |
| 781 // | 781 // |
| 782 // 'Type1|Type2'. A union type. | 782 // 'Type1|Type2'. A union type. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 793 } | 793 } |
| 794 | 794 |
| 795 LiteralString specLiteral = argNodes.head.asLiteralString(); | 795 LiteralString specLiteral = argNodes.head.asLiteralString(); |
| 796 if (specLiteral == null) { | 796 if (specLiteral == null) { |
| 797 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It | 797 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It |
| 798 // is not very satisfactory because it does not work for void, dynamic. | 798 // is not very satisfactory because it does not work for void, dynamic. |
| 799 compiler.internalError(argNodes.head, "Unexpected JS first argument."); | 799 compiler.internalError(argNodes.head, "Unexpected JS first argument."); |
| 800 } | 800 } |
| 801 | 801 |
| 802 var behavior = new NativeBehavior(); | 802 var behavior = new NativeBehavior(); |
| 803 behavior.codeAst = js.js.parseForeignJS(code.dartString.slowToString()); | 803 behavior.codeTemplate = js.js.parseForeignJS(code.dartString.slowToString())
; |
| 804 new SideEffectsVisitor(behavior.sideEffects).visit(behavior.codeAst); | 804 new SideEffectsVisitor(behavior.sideEffects).visit(behavior.codeTemplate.ast
); |
| 805 | 805 |
| 806 String specString = specLiteral.dartString.slowToString(); | 806 String specString = specLiteral.dartString.slowToString(); |
| 807 // Various things that are not in fact types. | 807 // Various things that are not in fact types. |
| 808 if (specString == 'void') return behavior; | 808 if (specString == 'void') return behavior; |
| 809 if (specString == '' || specString == 'var') { | 809 if (specString == '' || specString == 'var') { |
| 810 behavior.typesReturned.add(compiler.objectClass.computeType(compiler)); | 810 behavior.typesReturned.add(compiler.objectClass.computeType(compiler)); |
| 811 behavior.typesReturned.add(compiler.nullClass.computeType(compiler)); | 811 behavior.typesReturned.add(compiler.nullClass.computeType(compiler)); |
| 812 return behavior; | 812 return behavior; |
| 813 } | 813 } |
| 814 for (final typeString in specString.split('|')) { | 814 for (final typeString in specString.split('|')) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; | 1155 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; |
| 1156 } else if (element.kind == ElementKind.GETTER) { | 1156 } else if (element.kind == ElementKind.GETTER) { |
| 1157 nativeMethodCall = '$receiver$nativeMethodName'; | 1157 nativeMethodCall = '$receiver$nativeMethodName'; |
| 1158 } else if (element.kind == ElementKind.SETTER) { | 1158 } else if (element.kind == ElementKind.SETTER) { |
| 1159 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; | 1159 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; |
| 1160 } else { | 1160 } else { |
| 1161 builder.compiler.internalError(element, | 1161 builder.compiler.internalError(element, |
| 1162 'Unexpected kind: "${element.kind}".'); | 1162 'Unexpected kind: "${element.kind}".'); |
| 1163 } | 1163 } |
| 1164 | 1164 |
| 1165 builder.push(new HForeign(js.js(nativeMethodCall), backend.dynamicType, | 1165 builder.push( |
| 1166 inputs, effects: new SideEffects())); | 1166 new HForeign( |
| 1167 // TODO(sra): This could be cached. The number of templates should |
| 1168 // be proportional to the number of native methods, which is bounded |
| 1169 // by the dart: libraries. |
| 1170 js.js.uncachedExpressionTemplate(nativeMethodCall), |
| 1171 backend.dynamicType, |
| 1172 inputs, effects: new SideEffects())); |
| 1167 builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit); | 1173 builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit); |
| 1168 } else { | 1174 } else { |
| 1169 if (parameters.parameterCount != 0) { | 1175 if (parameters.parameterCount != 0) { |
| 1170 compiler.internalError(nativeBody, | 1176 compiler.internalError(nativeBody, |
| 1171 'native "..." syntax is restricted to ' | 1177 'native "..." syntax is restricted to ' |
| 1172 'functions with zero parameters.'); | 1178 'functions with zero parameters.'); |
| 1173 } | 1179 } |
| 1174 LiteralString jsCode = nativeBody.asLiteralString(); | 1180 LiteralString jsCode = nativeBody.asLiteralString(); |
| 1175 builder.push(new HForeign.statement( | 1181 builder.push(new HForeign.statement( |
| 1176 new js.LiteralStatement(jsCode.dartString.slowToString()), | 1182 js.js.statementTemplateYielding( |
| 1183 new js.LiteralStatement(jsCode.dartString.slowToString())), |
| 1177 <HInstruction>[], | 1184 <HInstruction>[], |
| 1178 new SideEffects(), | 1185 new SideEffects(), |
| 1179 null, | 1186 null, |
| 1180 backend.dynamicType)); | 1187 backend.dynamicType)); |
| 1181 } | 1188 } |
| 1182 } | 1189 } |
| OLD | NEW |