OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of native; | |
6 | |
7 final RegExp nativeRedirectionRegExp = new RegExp(r'^[a-zA-Z][a-zA-Z_$0-9]*$'); | |
8 | |
9 void handleSsaNative(SsaBuilder builder, Expression nativeBody) { | |
10 Compiler compiler = builder.compiler; | |
11 FunctionElement element = builder.work.element; | |
12 NativeEmitter nativeEmitter = builder.nativeEmitter; | |
13 JavaScriptBackend backend = builder.backend; | |
14 | |
15 HInstruction convertDartClosure(ParameterElement parameter, | |
16 FunctionType type) { | |
17 HInstruction local = builder.localsHandler.readLocal(parameter); | |
18 ConstantValue arityConstant = | |
19 builder.constantSystem.createInt(type.computeArity()); | |
20 HInstruction arity = builder.graph.addConstant(arityConstant, compiler); | |
21 // TODO(ngeoffray): For static methods, we could pass a method with a | |
22 // defined arity. | |
23 Element helper = backend.getClosureConverter(); | |
24 builder.pushInvokeStatic(nativeBody, helper, [local, arity]); | |
25 HInstruction closure = builder.pop(); | |
26 return closure; | |
27 } | |
28 | |
29 // Check which pattern this native method follows: | |
30 // 1) foo() native; | |
31 // hasBody = false | |
32 // 2) foo() native "bar"; | |
33 // No longer supported, this is now done with @JSName('foo') and case 1. | |
34 // 3) foo() native "return 42"; | |
35 // hasBody = true | |
36 bool hasBody = false; | |
37 assert(element.isNative); | |
38 String nativeMethodName = element.fixedBackendName; | |
39 if (nativeBody != null) { | |
40 LiteralString jsCode = nativeBody.asLiteralString(); | |
41 String str = jsCode.dartString.slowToString(); | |
42 if (nativeRedirectionRegExp.hasMatch(str)) { | |
43 compiler.internalError( | |
44 nativeBody, "Deprecated syntax, use @JSName('name') instead."); | |
45 } | |
46 hasBody = true; | |
47 } | |
48 | |
49 if (!hasBody) { | |
50 nativeEmitter.nativeMethods.add(element); | |
51 } | |
52 | |
53 FunctionSignature parameters = element.functionSignature; | |
54 if (!hasBody) { | |
55 List<String> arguments = <String>[]; | |
56 List<HInstruction> inputs = <HInstruction>[]; | |
57 String receiver = ''; | |
58 if (element.isInstanceMember) { | |
59 receiver = '#.'; | |
60 inputs.add(builder.localsHandler.readThis()); | |
61 } | |
62 parameters.forEachParameter((ParameterElement parameter) { | |
63 DartType type = parameter.type.unalias(compiler); | |
64 HInstruction input = builder.localsHandler.readLocal(parameter); | |
65 if (type is FunctionType) { | |
66 // The parameter type is a function type either directly or through | |
67 // typedef(s). | |
68 input = convertDartClosure(parameter, type); | |
69 } | |
70 inputs.add(input); | |
71 arguments.add('#'); | |
72 }); | |
73 | |
74 String foreignParameters = arguments.join(','); | |
75 String nativeMethodCall; | |
76 if (element.kind == ElementKind.FUNCTION) { | |
77 nativeMethodCall = '$receiver$nativeMethodName($foreignParameters)'; | |
78 } else if (element.kind == ElementKind.GETTER) { | |
79 nativeMethodCall = '$receiver$nativeMethodName'; | |
80 } else if (element.kind == ElementKind.SETTER) { | |
81 nativeMethodCall = '$receiver$nativeMethodName = $foreignParameters'; | |
82 } else { | |
83 builder.compiler.internalError(element, | |
84 'Unexpected kind: "${element.kind}".'); | |
85 } | |
86 | |
87 builder.push( | |
88 new HForeign( | |
89 // TODO(sra): This could be cached. The number of templates should | |
90 // be proportional to the number of native methods, which is bounded | |
91 // by the dart: libraries. | |
92 js.js.uncachedExpressionTemplate(nativeMethodCall), | |
93 backend.dynamicType, | |
94 inputs, effects: new SideEffects())); | |
95 builder.close(new HReturn(builder.pop())).addSuccessor(builder.graph.exit); | |
96 } else { | |
97 if (parameters.parameterCount != 0) { | |
98 compiler.internalError(nativeBody, | |
99 'native "..." syntax is restricted to ' | |
100 'functions with zero parameters.'); | |
101 } | |
102 LiteralString jsCode = nativeBody.asLiteralString(); | |
103 builder.push(new HForeign.statement( | |
104 js.js.statementTemplateYielding( | |
105 new js.LiteralStatement(jsCode.dartString.slowToString())), | |
106 <HInstruction>[], | |
107 new SideEffects(), | |
108 null, | |
109 backend.dynamicType)); | |
110 } | |
111 } | |
OLD | NEW |