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.expressionTemplateYielding( |
| 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 |