Chromium Code Reviews| 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 #import('../../uri/uri.dart'); | 6 #import('../../uri/uri.dart'); |
| 7 #import('leg.dart'); | 7 #import('leg.dart'); |
| 8 #import('elements/elements.dart'); | 8 #import('elements/elements.dart'); |
| 9 #import('scanner/scannerlib.dart'); | 9 #import('scanner/scannerlib.dart'); |
| 10 #import('ssa/ssa.dart'); | 10 #import('ssa/ssa.dart'); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 checkAllowedLibrary(listener, token); | 124 checkAllowedLibrary(listener, token); |
| 125 token = token.next; | 125 token = token.next; |
| 126 if (token.kind !== STRING_TOKEN) { | 126 if (token.kind !== STRING_TOKEN) { |
| 127 listener.unexpected(token); | 127 listener.unexpected(token); |
| 128 } else { | 128 } else { |
| 129 token = token.next; | 129 token = token.next; |
| 130 } | 130 } |
| 131 return token; | 131 return token; |
| 132 } | 132 } |
| 133 | 133 |
| 134 RegExp nativeRedirectionRegExp = const RegExp(@'^[a-zA-Z][a-zA-Z_$0-9]*$'); | |
| 135 | |
| 134 Token handleNativeFunctionBody(ElementListener listener, Token token) { | 136 Token handleNativeFunctionBody(ElementListener listener, Token token) { |
| 135 checkAllowedLibrary(listener, token); | 137 checkAllowedLibrary(listener, token); |
| 136 Token begin = token; | 138 Token begin = token; |
| 137 listener.beginExpressionStatement(token); | 139 listener.beginExpressionStatement(token); |
| 138 listener.handleIdentifier(token); | 140 listener.handleIdentifier(token); |
| 139 token = token.next; | 141 token = token.next; |
| 140 if (token.kind === STRING_TOKEN) { | 142 if (token.kind === STRING_TOKEN) { |
| 141 listener.beginLiteralString(token); | 143 listener.beginLiteralString(token); |
| 142 listener.endLiteralString(0); | 144 listener.endLiteralString(0); |
| 143 listener.pushNode(new NodeList.singleton(listener.popNode())); | 145 LiteralString str = listener.popNode(); |
| 146 listener.pushNode(new NodeList.singleton(str)); | |
| 144 listener.endSend(token); | 147 listener.endSend(token); |
| 145 token = token.next; | 148 token = token.next; |
| 146 listener.endExpressionStatement(token); | 149 // If this native method is just redirecting to another method, |
| 150 // we add a return node to match the SSA builder expactations. | |
|
floitsch
2012/03/30 19:41:26
expectations
| |
| 151 if (nativeRedirectionRegExp.hasMatch(str.dartString.slowToString())) { | |
| 152 listener.endReturnStatement(true, begin, token); | |
| 153 } else { | |
| 154 listener.endExpressionStatement(token); | |
| 155 } | |
| 147 } else { | 156 } else { |
| 148 listener.pushNode(new NodeList.empty()); | 157 listener.pushNode(new NodeList.empty()); |
| 149 listener.endSend(token); | 158 listener.endSend(token); |
| 150 listener.endReturnStatement(true, begin, token); | 159 listener.endReturnStatement(true, begin, token); |
| 151 } | 160 } |
| 152 listener.endFunctionBody(1, begin, token); | 161 listener.endFunctionBody(1, begin, token); |
| 153 // TODO(ngeoffray): expect a ';'. | 162 // TODO(ngeoffray): expect a ';'. |
| 154 return token.next; | 163 return token.next; |
| 155 } | 164 } |
| 156 | 165 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 // 3) foo() native "return 42"; hasBody = true, isRedirecting = false | 225 // 3) foo() native "return 42"; hasBody = true, isRedirecting = false |
| 217 bool hasBody = false; | 226 bool hasBody = false; |
| 218 bool isRedirecting = false; | 227 bool isRedirecting = false; |
| 219 String nativeMethodName = element.name.slowToString(); | 228 String nativeMethodName = element.name.slowToString(); |
| 220 if (!node.arguments.isEmpty()) { | 229 if (!node.arguments.isEmpty()) { |
| 221 if (!node.arguments.tail.isEmpty()) { | 230 if (!node.arguments.tail.isEmpty()) { |
| 222 builder.compiler.cancel('More than one argument to native'); | 231 builder.compiler.cancel('More than one argument to native'); |
| 223 } | 232 } |
| 224 LiteralString jsCode = node.arguments.head; | 233 LiteralString jsCode = node.arguments.head; |
| 225 String str = jsCode.dartString.slowToString(); | 234 String str = jsCode.dartString.slowToString(); |
| 226 if (const RegExp(@'^[a-zA-Z][a-zA-Z_$0-9]*$').hasMatch(str)) { | 235 if (nativeRedirectionRegExp.hasMatch(str)) { |
| 227 nativeMethodName = str; | 236 nativeMethodName = str; |
| 228 isRedirecting = true; | 237 isRedirecting = true; |
| 229 } else { | 238 } else { |
| 230 hasBody = true; | 239 hasBody = true; |
| 231 } | 240 } |
| 232 } | 241 } |
| 233 | 242 |
| 234 FunctionParameters parameters = element.computeParameters(builder.compiler); | 243 FunctionParameters parameters = element.computeParameters(builder.compiler); |
| 235 if (!hasBody) { | 244 if (!hasBody) { |
| 236 List<String> arguments = <String>[]; | 245 List<String> arguments = <String>[]; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 jsCode, const LiteralDartString('Object'), | 334 jsCode, const LiteralDartString('Object'), |
| 326 <HInstruction>[builder.localsHandler.readThis(), constant])); | 335 <HInstruction>[builder.localsHandler.readThis(), constant])); |
| 327 | 336 |
| 328 builder.handleIf(visitThen, visitElse); | 337 builder.handleIf(visitThen, visitElse); |
| 329 | 338 |
| 330 HPhi phi = new HPhi.manyInputs( | 339 HPhi phi = new HPhi.manyInputs( |
| 331 null, <HInstruction>[thenInstruction, elseInstruction]); | 340 null, <HInstruction>[thenInstruction, elseInstruction]); |
| 332 builder.current.addPhi(phi); | 341 builder.current.addPhi(phi); |
| 333 builder.stack.add(phi); | 342 builder.stack.add(phi); |
| 334 } | 343 } |
| 335 if (isRedirecting) { | |
| 336 // The parser creates a return node if there is no string literal | |
| 337 // after the native keyword. In case of a redirecting method, there | |
| 338 // is a string literal, therefore we must emit a return instruction | |
| 339 // in the builder. | |
| 340 builder.push(new HReturn(builder.pop())); | |
| 341 } | |
| 342 } else { | 344 } else { |
| 343 // This is JS code written in a Dart file with the construct | 345 // This is JS code written in a Dart file with the construct |
| 344 // native """ ... """;. It does not work well with mangling, | 346 // native """ ... """;. It does not work well with mangling, |
| 345 // but there should currently be no clash between leg mangling | 347 // but there should currently be no clash between leg mangling |
| 346 // and the library where this construct is being used. This | 348 // and the library where this construct is being used. This |
| 347 // mangling problem will go away once we switch these libraries | 349 // mangling problem will go away once we switch these libraries |
| 348 // to use Leg's 'JS' function. | 350 // to use Leg's 'JS' function. |
| 349 parameters.forEachParameter((Element parameter) { | 351 parameters.forEachParameter((Element parameter) { |
| 350 Type type = parameter.computeType(compiler); | 352 Type type = parameter.computeType(compiler); |
| 351 if (type is FunctionType) { | 353 if (type is FunctionType) { |
| 352 HInstruction jsClosure = convertDartClosure(parameter); | 354 HInstruction jsClosure = convertDartClosure(parameter); |
| 353 // Because the JS code references the argument name directly, | 355 // Because the JS code references the argument name directly, |
| 354 // we must keep the name and assign the JS closure to it. | 356 // we must keep the name and assign the JS closure to it. |
| 355 builder.add(new HForeign( | 357 builder.add(new HForeign( |
| 356 new DartString.literal('${parameter.name.slowToString()} = #'), | 358 new DartString.literal('${parameter.name.slowToString()} = #'), |
| 357 const LiteralDartString('void'), | 359 const LiteralDartString('void'), |
| 358 <HInstruction>[jsClosure])); | 360 <HInstruction>[jsClosure])); |
| 359 } | 361 } |
| 360 }); | 362 }); |
| 361 LiteralString jsCode = node.arguments.head; | 363 LiteralString jsCode = node.arguments.head; |
| 362 builder.push(new HForeign(jsCode.dartString, | 364 builder.push(new HForeign(jsCode.dartString, |
| 363 const LiteralDartString('Object'), | 365 const LiteralDartString('Object'), |
| 364 <HInstruction>[])); | 366 <HInstruction>[])); |
| 365 } | 367 } |
| 366 } | 368 } |
| OLD | NEW |