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