| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, 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 package com.google.dart.compiler.backend.isolate; | |
| 6 | |
| 7 import java.io.FileNotFoundException; | |
| 8 import java.io.IOException; | |
| 9 import java.io.PrintStream; | |
| 10 import java.util.Collection; | |
| 11 import java.util.List; | |
| 12 import java.util.Set; | |
| 13 | |
| 14 import com.google.dart.compiler.Backend; | |
| 15 import com.google.dart.compiler.DartCompilerContext; | |
| 16 import com.google.dart.compiler.DartSource; | |
| 17 import com.google.dart.compiler.LibrarySource; | |
| 18 import com.google.dart.compiler.ast.DartClass; | |
| 19 import com.google.dart.compiler.ast.DartContext; | |
| 20 import com.google.dart.compiler.ast.DartExpression; | |
| 21 import com.google.dart.compiler.ast.DartFunction; | |
| 22 import com.google.dart.compiler.ast.DartIdentifier; | |
| 23 import com.google.dart.compiler.ast.DartMethodDefinition; | |
| 24 import com.google.dart.compiler.ast.DartNode; | |
| 25 import com.google.dart.compiler.ast.DartParameter; | |
| 26 import com.google.dart.compiler.ast.DartTypeNode; | |
| 27 import com.google.dart.compiler.ast.DartUnit; | |
| 28 import com.google.dart.compiler.ast.DartVisitor; | |
| 29 import com.google.dart.compiler.ast.LibraryUnit; | |
| 30 import com.google.dart.compiler.resolver.CoreTypeProvider; | |
| 31 | |
| 32 /** | |
| 33 * Generate code for proxies and dispatchers for cross-isolate calls. | |
| 34 */ | |
| 35 public class DartIsolateStubGenerator implements Backend { | |
| 36 private final Set<String> stubInterfaces; | |
| 37 private PrintStream outStream; | |
| 38 | |
| 39 public DartIsolateStubGenerator(final Set<String> classes, String out) | |
| 40 throws FileNotFoundException { | |
| 41 outStream = new PrintStream(out); | |
| 42 stubInterfaces = classes; | |
| 43 } | |
| 44 | |
| 45 private void autoGenerate(DartUnit unit) { | |
| 46 if (stubInterfaces.isEmpty()) { | |
| 47 return; | |
| 48 } | |
| 49 | |
| 50 DartVisitor visitor = new DartVisitor() { | |
| 51 private boolean first = true; | |
| 52 | |
| 53 @Override | |
| 54 public boolean visit(DartClass clazz, DartContext ctx) { | |
| 55 if (clazz.isInterface() && stubInterfaces.contains(clazz.getClassName())
) { | |
| 56 if (!first) | |
| 57 nl(); | |
| 58 first = false; | |
| 59 p("/* class = " + clazz.getClassName() + " (" | |
| 60 + clazz.getSource().getName() + ": " + clazz.getSourceLine() + ") */
"); | |
| 61 nl(); | |
| 62 nl(); | |
| 63 generateProxyClass(clazz); | |
| 64 nl(); | |
| 65 generateDispatchClass(clazz); | |
| 66 nl(); | |
| 67 generateIsolateClass(clazz); | |
| 68 } | |
| 69 return false; | |
| 70 } | |
| 71 | |
| 72 }; | |
| 73 visitor.accept(unit); | |
| 74 outStream.flush(); | |
| 75 } | |
| 76 | |
| 77 private static boolean isConstructor(DartMethodDefinition x) { | |
| 78 return x.getSymbol().isConstructor(); | |
| 79 } | |
| 80 | |
| 81 // Simple types can be passed directly, non-simple types need proxying. Promis
es count as a | |
| 82 // simple type because the marshaling handles them internally. | |
| 83 private static boolean isSimpleType(DartTypeNode x) { | |
| 84 if (!(x.getIdentifier() instanceof DartIdentifier)) | |
| 85 return false; | |
| 86 String name = ((DartIdentifier)x.getIdentifier()).getTargetName(); | |
| 87 if (name.equals("Promise")) | |
| 88 return true; | |
| 89 if (!x.getTypeArguments().isEmpty()) | |
| 90 return false; | |
| 91 if (name.equals("int") || name.equals("void")) | |
| 92 return true; | |
| 93 return false; | |
| 94 } | |
| 95 | |
| 96 private static boolean isPromise(DartTypeNode x) { | |
| 97 if (!(x.getIdentifier() instanceof DartIdentifier)) | |
| 98 return false; | |
| 99 String name = ((DartIdentifier)x.getIdentifier()).getTargetName(); | |
| 100 return name.equals("Promise"); | |
| 101 } | |
| 102 | |
| 103 private String getPromiseType(DartTypeNode x) { | |
| 104 assert isPromise(x); | |
| 105 List<DartTypeNode> types = x.getTypeArguments(); | |
| 106 assert types.size() == 1; | |
| 107 return ((DartIdentifier)types.get(0).getIdentifier()).getTargetName(); | |
| 108 } | |
| 109 | |
| 110 private static boolean isPromiseForProxy(DartTypeNode x) { | |
| 111 if (!isPromise(x)) | |
| 112 return false; | |
| 113 List<DartTypeNode> types = x.getTypeArguments(); | |
| 114 if (types.size() != 1) | |
| 115 return false; | |
| 116 String name = ((DartIdentifier)types.get(0).getIdentifier()).getTargetName()
; | |
| 117 return name.endsWith("$Proxy"); | |
| 118 } | |
| 119 | |
| 120 private static boolean isVoid(DartTypeNode x) { | |
| 121 if (!isSimpleType(x)) | |
| 122 return false; | |
| 123 return ((DartIdentifier)x.getIdentifier()).getTargetName().equals("void"); | |
| 124 } | |
| 125 | |
| 126 private static boolean isProxyType(DartTypeNode x) { | |
| 127 if (!(x.getIdentifier() instanceof DartIdentifier)) | |
| 128 return false; | |
| 129 String name = ((DartIdentifier)x.getIdentifier()).getTargetName(); | |
| 130 if (name.equals("Promise")) | |
| 131 return true; | |
| 132 if (!x.getTypeArguments().isEmpty()) | |
| 133 return false; | |
| 134 return name.endsWith("$Proxy"); | |
| 135 } | |
| 136 | |
| 137 private void p(String str) { | |
| 138 outStream.print(str); | |
| 139 } | |
| 140 | |
| 141 private void nl() { | |
| 142 outStream.println(); | |
| 143 } | |
| 144 | |
| 145 class ProxifyingVisitor extends DartVisitor { | |
| 146 @Override | |
| 147 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 148 accept(x.getIdentifier()); | |
| 149 printTypeArguments(x); | |
| 150 if (!isSimpleType(x)) | |
| 151 p("$Proxy"); | |
| 152 return false; | |
| 153 } | |
| 154 | |
| 155 @Override | |
| 156 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 157 p(x.getTargetName()); | |
| 158 return false; | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 private void printTypeArguments(DartTypeNode x) { | |
| 163 List<DartTypeNode> arguments = x.getTypeArguments(); | |
| 164 if (arguments != null && !arguments.isEmpty()) { | |
| 165 p("<"); | |
| 166 printParams(arguments); | |
| 167 p(">"); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 private void printParams(List<? extends DartNode> nodes) { | |
| 172 boolean first = true; | |
| 173 for (DartNode node : nodes) { | |
| 174 if (!first) { | |
| 175 p(", "); | |
| 176 } | |
| 177 DartVisitor param = new DartVisitor() { | |
| 178 @Override | |
| 179 public boolean visit(DartParameter x, DartContext ctx) { | |
| 180 if (x.getModifiers().isFinal()) { | |
| 181 p("final "); | |
| 182 } | |
| 183 if (x.getTypeNode() != null) { | |
| 184 accept(x.getTypeNode()); | |
| 185 p(" "); | |
| 186 } | |
| 187 accept(x.getName()); | |
| 188 if (x.getFunctionParameters() != null) { | |
| 189 p("("); | |
| 190 printParams(x.getFunctionParameters()); | |
| 191 p(")"); | |
| 192 } | |
| 193 if (x.getDefaultExpr() != null) { | |
| 194 p(" = "); | |
| 195 accept(x.getDefaultExpr()); | |
| 196 } | |
| 197 return false; | |
| 198 } | |
| 199 @Override | |
| 200 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 201 accept(x.getIdentifier()); | |
| 202 printTypeArguments(x); | |
| 203 return false; | |
| 204 } | |
| 205 @Override | |
| 206 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 207 p(x.getTargetName()); | |
| 208 return false; | |
| 209 } | |
| 210 }; | |
| 211 param.accept(node); | |
| 212 first = false; | |
| 213 } | |
| 214 } | |
| 215 | |
| 216 private void printProxyInterfaceFunctions(DartClass clazz) { | |
| 217 DartVisitor visitor = new DartVisitor() { | |
| 218 @Override | |
| 219 public boolean visit(DartMethodDefinition x, DartContext ctx) { | |
| 220 if (!printFunctionDeclaration(this, x)) { | |
| 221 return false; | |
| 222 } | |
| 223 p(";"); | |
| 224 nl(); | |
| 225 | |
| 226 return false; | |
| 227 } | |
| 228 | |
| 229 @Override | |
| 230 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 231 accept(x.getIdentifier()); | |
| 232 printTypeArguments(x); | |
| 233 return false; | |
| 234 } | |
| 235 | |
| 236 @Override | |
| 237 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 238 p(x.getTargetName()); | |
| 239 return false; | |
| 240 } | |
| 241 | |
| 242 }; | |
| 243 visitor.acceptList(clazz.getMembers()); | |
| 244 } | |
| 245 | |
| 246 /** | |
| 247 * Produce something looking like: | |
| 248 * | |
| 249 * | |
| 250 * interface Purse$Proxy { | |
| 251 * void init(Mint$Proxy mint, int balance); | |
| 252 * | |
| 253 * Promise<int> queryBalance(); | |
| 254 * | |
| 255 * Purse$Proxy sproutPurse(); | |
| 256 * | |
| 257 * void deposit(int amount, Purse$Proxy source); | |
| 258 * } | |
| 259 * | |
| 260 * class Purse$ProxyImpl extends Proxy implements Purse$Proxy { | |
| 261 * Purse$ProxyImpl(Promise<SendPort> port) : super.forReply(port) { } | |
| 262 * Purse$ProxyImpl.forIsolate(Proxy isolate) : super.forReply(isolate.call([
null])) { } | |
| 263 * factory Purse$ProxyImpl.createIsolate() { | |
| 264 * Proxy isolate = new Proxy.forIsolate(new Purse$Dispatcher$Isolate()); | |
| 265 * return new Purse$ProxyImpl.forIsolate(isolate); | |
| 266 * } | |
| 267 * factory Purse$ProxyImpl.localProxy(Purse obj) { | |
| 268 * return new Purse$ProxyImpl(new Promise<SendPort>.fromValue(Dispatcher.s
erve( | |
| 269 * new Purse$Dispatcher(obj)))); | |
| 270 * } | |
| 271 * | |
| 272 * void init(Mint$Proxy mint, int balance) { | |
| 273 * this.send(["init", mint, balance]); | |
| 274 * } | |
| 275 * | |
| 276 * Promise<int> queryBalance() { | |
| 277 * return this.call(["queryBalance"]); | |
| 278 * } | |
| 279 * | |
| 280 * Purse$Proxy sproutPurse() { | |
| 281 * return new Purse$ProxyImpl(this.call(["sproutPurse"])); | |
| 282 * } | |
| 283 * | |
| 284 * void deposit(int amount, Purse$Proxy source) { | |
| 285 * this.send(["deposit", amount, source]); | |
| 286 * } | |
| 287 * } | |
| 288 */ | |
| 289 private void generateProxyClass(DartClass clazz) { | |
| 290 String name = clazz.getClassName(); | |
| 291 p("interface " + name + "$Proxy extends Proxy {"); | |
| 292 printProxyInterfaceFunctions(clazz); | |
| 293 p("}"); | |
| 294 nl(); | |
| 295 nl(); | |
| 296 | |
| 297 p("class " + name + "$ProxyImpl extends ProxyImpl implements " + name + "$Pr
oxy {"); | |
| 298 nl(); | |
| 299 p(" " + name + "$ProxyImpl(Promise<SendPort> port) : super.forReply(port) {
}"); | |
| 300 nl(); | |
| 301 p(" " + name | |
| 302 + "$ProxyImpl.forIsolate(Proxy isolate) : super.forReply(isolate.call([nul
l])) { }"); | |
| 303 nl(); | |
| 304 | |
| 305 p(" factory " + name + "$ProxyImpl.createIsolate() {"); | |
| 306 nl(); | |
| 307 p(" Proxy isolate = new Proxy.forIsolate(new " + name + "$Dispatcher$Isol
ate());"); | |
| 308 nl(); | |
| 309 p(" return new " + name + "$ProxyImpl.forIsolate(isolate);"); | |
| 310 nl(); | |
| 311 p(" }"); | |
| 312 nl(); | |
| 313 | |
| 314 // FIXME(benl, kasperl): We should be able to get hold of our existing dispa
tcher, not have to | |
| 315 // create a new one... | |
| 316 p(" factory " + name + "$ProxyImpl.localProxy(" + name + " obj) {"); | |
| 317 nl(); | |
| 318 p(" return new " + name + "$ProxyImpl(new Promise<SendPort>.fromValue(Dis
patcher.serve(new " | |
| 319 + name + "$Dispatcher(obj))));"); | |
| 320 nl(); | |
| 321 p(" }"); | |
| 322 nl(); | |
| 323 | |
| 324 DartVisitor visitor = new DartVisitor() { | |
| 325 @Override | |
| 326 public boolean visit(DartMethodDefinition x, DartContext ctx) { | |
| 327 if (!printFunctionDeclaration(this, x)) | |
| 328 return false; | |
| 329 p(" {"); | |
| 330 nl(); | |
| 331 p(" "); | |
| 332 final DartFunction func = x.getFunction(); | |
| 333 final DartTypeNode returnTypeNode = func.getReturnTypeNode(); | |
| 334 final boolean isVoid = isVoid(returnTypeNode); | |
| 335 final boolean isSimple = isSimpleType(returnTypeNode); | |
| 336 final boolean isProxy = isProxyType(returnTypeNode); | |
| 337 final boolean isPromise = isPromise(returnTypeNode); | |
| 338 final boolean isPromiseForProxy = isPromiseForProxy(returnTypeNode); | |
| 339 if (isPromiseForProxy) { | |
| 340 String type = getPromiseType(returnTypeNode); | |
| 341 // This horrific unpacking is because a Proxy is, in effect, a Promise
, but not quite, so | |
| 342 // a Promise<Proxy> ends up begin wrapped in two layers of SendPorts. | |
| 343 // FIXME(benl): unifying Promise and Proxy under Completable might wel
l reduce the | |
| 344 // complexity here. | |
| 345 p("return new Promise<" + type + ">.fromValue(new " + type | |
| 346 + "Impl(new PromiseProxy<SendPort>(new PromiseProxy<SendPort>("); | |
| 347 } else { | |
| 348 if (!isVoid) { | |
| 349 p("return "); | |
| 350 if (!isSimple) { | |
| 351 p("new "); | |
| 352 accept(returnTypeNode); | |
| 353 if (!isProxy) { | |
| 354 p("$Proxy"); | |
| 355 } | |
| 356 p("Impl("); | |
| 357 } | |
| 358 } | |
| 359 if (isProxy) { | |
| 360 // Note that Promises are Proxies. | |
| 361 p("new PromiseProxy"); | |
| 362 if (isPromise) { | |
| 363 printTypeArguments(returnTypeNode); | |
| 364 } else { | |
| 365 p("<SendPort>"); | |
| 366 } | |
| 367 p("("); | |
| 368 } | |
| 369 } | |
| 370 p("this."); | |
| 371 if (isVoid) { | |
| 372 p("send"); | |
| 373 } else { | |
| 374 p("call"); | |
| 375 } | |
| 376 p("([\""); | |
| 377 accept(x.getName()); | |
| 378 p("\""); | |
| 379 DartVisitor params = new DartVisitor() { | |
| 380 @Override | |
| 381 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 382 p(", "); | |
| 383 p(x.getTargetName()); | |
| 384 return false; | |
| 385 } | |
| 386 | |
| 387 @Override | |
| 388 public boolean visit(DartParameter x, DartContext ctx) { | |
| 389 accept(x.getName()); | |
| 390 return false; | |
| 391 } | |
| 392 }; | |
| 393 params.acceptList(func.getParams()); | |
| 394 p("])"); | |
| 395 if (isPromiseForProxy) { | |
| 396 p("))))"); | |
| 397 } else { | |
| 398 if (isProxy) { | |
| 399 p(")"); | |
| 400 } | |
| 401 if (!isSimple) { | |
| 402 p(")"); | |
| 403 } | |
| 404 } | |
| 405 p(";"); | |
| 406 nl(); | |
| 407 | |
| 408 p(" }"); | |
| 409 nl(); | |
| 410 | |
| 411 return false; | |
| 412 } | |
| 413 | |
| 414 @Override | |
| 415 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 416 accept(x.getIdentifier()); | |
| 417 printTypeArguments(x); | |
| 418 return false; | |
| 419 } | |
| 420 | |
| 421 @Override | |
| 422 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 423 p(x.getTargetName()); | |
| 424 return false; | |
| 425 } | |
| 426 | |
| 427 }; | |
| 428 visitor.acceptList(clazz.getMembers()); | |
| 429 p("}"); | |
| 430 nl(); | |
| 431 } | |
| 432 | |
| 433 private void printSelector(List<DartNode> members, String dispatcherName) { | |
| 434 boolean first = true; | |
| 435 for (DartNode member : members) { | |
| 436 if (first) { | |
| 437 p(" "); | |
| 438 } else { | |
| 439 p(" else "); | |
| 440 } | |
| 441 p("if (command == \""); | |
| 442 printFunctionName(member); | |
| 443 p("\") {"); | |
| 444 nl(); | |
| 445 int proxies = unpackParams(member); | |
| 446 if (proxies != 0) { | |
| 447 // FIXME(benl): we don't need to gather them anymore, could just pass th
em directly. Too | |
| 448 // lazy right now. | |
| 449 gatherProxies(member); | |
| 450 } | |
| 451 callTarget((DartMethodDefinition)member, ""); | |
| 452 p(" }"); | |
| 453 first = false; | |
| 454 } | |
| 455 p(" else {"); | |
| 456 nl(); | |
| 457 p(" // TODO(kasperl,benl): Somehow throw an exception instead."); | |
| 458 nl(); | |
| 459 p(" reply(\"Exception: command '\" + command + \"' not understood by "
+ dispatcherName + ".\");"); | |
| 460 nl(); | |
| 461 p(" }"); | |
| 462 nl(); | |
| 463 } | |
| 464 | |
| 465 private void callTarget(DartMethodDefinition member, String extra) { | |
| 466 if (isConstructor(member)) { | |
| 467 return; | |
| 468 } | |
| 469 p(extra + " "); | |
| 470 boolean isVoid = isVoid(member.getFunction().getReturnTypeNode()); | |
| 471 if (!isVoid) { | |
| 472 printReturnType(member); | |
| 473 p(" "); | |
| 474 printFunctionName(member); | |
| 475 p(" = "); | |
| 476 } | |
| 477 p("target."); | |
| 478 printFunctionName(member); | |
| 479 p("("); | |
| 480 printParamNames(member); | |
| 481 p(");"); | |
| 482 nl(); | |
| 483 String returnType = stringReturnType(member); | |
| 484 if (stubInterfaces.contains(returnType)) { | |
| 485 p(extra + " SendPort port = Dispatcher.serve(new " + returnType + "$D
ispatcher("); | |
| 486 printFunctionName(member); | |
| 487 p("));"); | |
| 488 nl(); | |
| 489 p(extra + " reply(port);"); | |
| 490 nl(); | |
| 491 } else if (!isVoid) { | |
| 492 p(extra + " reply("); | |
| 493 printFunctionName(member); | |
| 494 p(");"); | |
| 495 nl(); | |
| 496 } | |
| 497 } | |
| 498 | |
| 499 private static String stringReturnType(DartMethodDefinition member) { | |
| 500 return stringType(member.getFunction().getReturnTypeNode()); | |
| 501 } | |
| 502 | |
| 503 private void printParamNames(DartMethodDefinition member) { | |
| 504 boolean first = true; | |
| 505 for(DartParameter param : member.getFunction().getParams()) { | |
| 506 if (!first) { | |
| 507 p(", "); | |
| 508 } | |
| 509 printName(param.getName()); | |
| 510 first = false; | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 private void printName(DartExpression name) { | |
| 515 DartVisitor visitor = new DartVisitor() { | |
| 516 @Override | |
| 517 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 518 p(x.getTargetName()); | |
| 519 return false; | |
| 520 } | |
| 521 }; | |
| 522 visitor.accept(name); | |
| 523 } | |
| 524 | |
| 525 private void printReturnType(DartMethodDefinition member) { | |
| 526 printType(member.getFunction().getReturnTypeNode()); | |
| 527 } | |
| 528 | |
| 529 private void printType(DartTypeNode type) { | |
| 530 DartVisitor visitor = new DartVisitor() { | |
| 531 @Override | |
| 532 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 533 p(x.getTargetName()); | |
| 534 return false; | |
| 535 } | |
| 536 | |
| 537 @Override | |
| 538 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 539 accept(x.getIdentifier()); | |
| 540 printTypeArguments(x); | |
| 541 return false; | |
| 542 } | |
| 543 }; | |
| 544 visitor.accept(type); | |
| 545 } | |
| 546 | |
| 547 private static String stringType(DartTypeNode type) { | |
| 548 final StringBuilder strType = new StringBuilder(); | |
| 549 DartVisitor visitor = new DartVisitor() { | |
| 550 @Override | |
| 551 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 552 strType.append(x.getTargetName()); | |
| 553 return false; | |
| 554 } | |
| 555 | |
| 556 @Override | |
| 557 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 558 accept(x.getIdentifier()); | |
| 559 List<DartTypeNode> arguments = x.getTypeArguments(); | |
| 560 if (arguments != null && !arguments.isEmpty()) { | |
| 561 strType.append("<"); | |
| 562 // Really we should do | |
| 563 // strType.append(stringParams(arguments)); | |
| 564 // but for now, this will suffice | |
| 565 strType.append("..."); | |
| 566 strType.append(">"); | |
| 567 } | |
| 568 return false; | |
| 569 } | |
| 570 }; | |
| 571 visitor.accept(type); | |
| 572 return strType.toString(); | |
| 573 } | |
| 574 | |
| 575 private int unpackParams(DartNode member) { | |
| 576 class UnpackVisitor extends DartVisitor { | |
| 577 private int pos; | |
| 578 int proxies; | |
| 579 | |
| 580 @Override | |
| 581 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 582 accept(x.getIdentifier()); | |
| 583 printTypeArguments(x); | |
| 584 return false; | |
| 585 } | |
| 586 | |
| 587 @Override | |
| 588 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 589 p(x.getTargetName()); | |
| 590 return false; | |
| 591 } | |
| 592 | |
| 593 @Override | |
| 594 public boolean visit(DartMethodDefinition x, DartContext ctx) { | |
| 595 pos = 1; | |
| 596 proxies = 0; | |
| 597 for (DartParameter param : x.getFunction().getParams()) { | |
| 598 p(" "); | |
| 599 accept(param); | |
| 600 nl(); | |
| 601 ++pos; | |
| 602 } | |
| 603 return false; | |
| 604 } | |
| 605 | |
| 606 @Override | |
| 607 public boolean visit(DartParameter x, DartContext ctx) { | |
| 608 boolean isSimpleType = isSimpleType(x.getTypeNode()); | |
| 609 | |
| 610 if (isSimpleType) { | |
| 611 accept(x.getTypeNode()); | |
| 612 p(" "); | |
| 613 accept(x.getName()); | |
| 614 p(" = "); | |
| 615 } else { | |
| 616 if (proxies == 0) { | |
| 617 p("List<Promise<SendPort>> promises = new List<Promise<SendPort>>()
;"); | |
| 618 nl(); | |
| 619 p(" "); | |
| 620 } | |
| 621 p("promises.add(new PromiseProxy<SendPort>(new Promise<SendPort>.fromV
alue("); | |
| 622 ++proxies; | |
| 623 //p("new "); | |
| 624 //accept(x.getTypeNode()); | |
| 625 //p("Impl(new Promise<SendPort>.fromValue("); | |
| 626 } | |
| 627 p("message[" + pos + "]"); | |
| 628 if (!isSimpleType) { | |
| 629 p(")))"); | |
| 630 } | |
| 631 p(";"); | |
| 632 return false; | |
| 633 } | |
| 634 }; | |
| 635 | |
| 636 UnpackVisitor visitor = new UnpackVisitor(); | |
| 637 | |
| 638 visitor.accept(member); | |
| 639 return visitor.proxies; | |
| 640 } | |
| 641 | |
| 642 private void gatherProxies(DartNode member) { | |
| 643 class GatherVisitor extends DartVisitor { | |
| 644 private int proxies; | |
| 645 | |
| 646 @Override | |
| 647 public boolean visit(DartTypeNode x, DartContext ctx) { | |
| 648 accept(x.getIdentifier()); | |
| 649 printTypeArguments(x); | |
| 650 return false; | |
| 651 } | |
| 652 | |
| 653 @Override | |
| 654 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 655 p(x.getTargetName()); | |
| 656 return false; | |
| 657 } | |
| 658 | |
| 659 @Override | |
| 660 public boolean visit(DartMethodDefinition x, DartContext ctx) { | |
| 661 proxies = 0; | |
| 662 for (DartParameter param : x.getFunction().getParams()) { | |
| 663 accept(param); | |
| 664 } | |
| 665 return false; | |
| 666 } | |
| 667 | |
| 668 @Override | |
| 669 public boolean visit(DartParameter x, DartContext ctx) { | |
| 670 boolean isSimpleType = isSimpleType(x.getTypeNode()); | |
| 671 | |
| 672 if (!isSimpleType) { | |
| 673 p(" "); | |
| 674 accept(x.getTypeNode()); | |
| 675 p(" "); | |
| 676 accept(x.getName()); | |
| 677 p(" = new "); | |
| 678 accept(x.getTypeNode()); | |
| 679 p("Impl(promises[" + proxies + "]);"); | |
| 680 ++proxies; | |
| 681 nl(); | |
| 682 } | |
| 683 return false; | |
| 684 } | |
| 685 }; | |
| 686 | |
| 687 GatherVisitor visitor = new GatherVisitor(); | |
| 688 | |
| 689 visitor.accept(member); | |
| 690 } | |
| 691 | |
| 692 private void printFunctionName(DartNode member) { | |
| 693 DartVisitor functionName = new DartVisitor() { | |
| 694 @Override | |
| 695 public boolean visit(DartMethodDefinition x, DartContext ctx) { | |
| 696 accept(x.getName()); | |
| 697 return false; | |
| 698 } | |
| 699 | |
| 700 @Override | |
| 701 public boolean visit(DartIdentifier x, DartContext ctx) { | |
| 702 p(x.getTargetName()); | |
| 703 return false; | |
| 704 } | |
| 705 }; | |
| 706 functionName.accept(member); | |
| 707 } | |
| 708 | |
| 709 /** | |
| 710 * Generate a dispatcher, looking like: | |
| 711 * | |
| 712 * class Purse$Dispatcher extends Dispatcher<Purse> { | |
| 713 * Purse$Dispatcher(Purse thing) : super(thing) { } | |
| 714 * | |
| 715 * void process(var message, void reply(var response)) { | |
| 716 * String command = message[0]; | |
| 717 * if (command == "queryBalance") { | |
| 718 * int queryBalance = target.queryBalance(); | |
| 719 * reply(queryBalance); | |
| 720 * } else if (command == "sproutPurse") { | |
| 721 * Purse sproutPurse = target.sproutPurse(); | |
| 722 * SendPort port = Dispatcher.serve(new Purse$Dispatcher(sproutPurse)); | |
| 723 * reply(port); | |
| 724 * } else if (command == "deposit") { | |
| 725 * int amount = message[1]; | |
| 726 * Promise<SendPort> port = | |
| 727 * new PromiseProxy<SendPort>(new Promise<SendPort>.fromValue(messag
e[2])); | |
| 728 * port.addCompletionHandler((_) { | |
| 729 * Purse$Proxy source = new Purse$ProxyImpl(port); | |
| 730 * target.deposit(amount, source); | |
| 731 * }); | |
| 732 * //Proxy<Purse> source = new Proxy<Purse>.forPort(message[2]); | |
| 733 * //target.deposit(amount, source); | |
| 734 * } else { | |
| 735 * // TODO(kasperl,benl): Somehow throw an exception instead. | |
| 736 * reply("Exception: command not understood."); | |
| 737 * } | |
| 738 * } | |
| 739 * } | |
| 740 */ | |
| 741 private void generateDispatchClass(DartClass clazz) { | |
| 742 String name = clazz.getClassName(); | |
| 743 p("class " + name + "$Dispatcher extends Dispatcher<" + name + "> {"); | |
| 744 nl(); | |
| 745 p(" " + name + "$Dispatcher(" + name + " thing) : super(thing) { }"); | |
| 746 nl(); | |
| 747 nl(); | |
| 748 p(" void process(var message, void reply(var response)) {"); | |
| 749 nl(); | |
| 750 p(" String command = message[0];"); | |
| 751 nl(); | |
| 752 printSelector(clazz.getMembers(), name); | |
| 753 p(" }"); | |
| 754 nl(); | |
| 755 p("}"); | |
| 756 nl(); | |
| 757 } | |
| 758 | |
| 759 /** | |
| 760 * Generate a dispatcher isolate, looking like: | |
| 761 * | |
| 762 * class Purse$Dispatcher extends Dispatcher<Purse> { | |
| 763 * Purse$Dispatcher(Purse thing) : super(thing) { } | |
| 764 * | |
| 765 * void process(var message, void reply(var response)) { | |
| 766 * String command = message[0]; | |
| 767 * if (command == "Purse") { | |
| 768 * } else if (command == "init") { | |
| 769 * Mint$Proxy mint = new Mint$ProxyImpl(new Promise<SendPort>.fromValue(
message[1])); | |
| 770 * int balance = message[2]; | |
| 771 * target.init(mint, balance); | |
| 772 * } else if (command == "queryBalance") { | |
| 773 * int queryBalance = target.queryBalance(); | |
| 774 * reply(queryBalance); | |
| 775 * } else if (command == "sproutPurse") { | |
| 776 * Purse sproutPurse = target.sproutPurse(); | |
| 777 * SendPort port = Dispatcher.serve(new Purse$Dispatcher(sproutPurse)); | |
| 778 * reply(port); | |
| 779 * } else if (command == "deposit") { | |
| 780 * int amount = message[1]; | |
| 781 * Purse$Proxy source = new Purse$ProxyImpl(new Promise<SendPort>.fromVa
lue(message[2])); | |
| 782 * target.deposit(amount, source); | |
| 783 * } else { | |
| 784 * // TODO(kasperl,benl): Somehow throw an exception instead. | |
| 785 * reply("Exception: command not understood."); | |
| 786 * } | |
| 787 * } | |
| 788 * } | |
| 789 */ | |
| 790 private void generateIsolateClass(DartClass clazz) { | |
| 791 String name = clazz.getClassName(); | |
| 792 p("class " + name + "$Dispatcher$Isolate extends Isolate {"); | |
| 793 nl(); | |
| 794 p(" " + name + "$Dispatcher$Isolate() : super() { }"); | |
| 795 nl(); | |
| 796 nl(); | |
| 797 p(" void main() {"); | |
| 798 nl(); | |
| 799 p(" this.port.receive(void _(var message, SendPort replyTo) {"); | |
| 800 nl(); | |
| 801 p(" " + name + " thing = new " + name + "();"); | |
| 802 nl(); | |
| 803 p(" SendPort port = Dispatcher.serve(new " + name + "$Dispatcher(thing)
);"); | |
| 804 nl(); | |
| 805 p(" Proxy proxy = new Proxy.forPort(replyTo);"); | |
| 806 nl(); | |
| 807 p(" proxy.send([port]);"); | |
| 808 nl(); | |
| 809 p(" });"); | |
| 810 nl(); | |
| 811 p(" }"); | |
| 812 nl(); | |
| 813 p("}"); | |
| 814 nl(); | |
| 815 } | |
| 816 | |
| 817 @Override | |
| 818 public boolean isOutOfDate(DartSource src, DartCompilerContext context) { | |
| 819 return true; | |
| 820 } | |
| 821 | |
| 822 @Override | |
| 823 public void compileUnit(DartUnit unit, DartSource src, DartCompilerContext con
text, | |
| 824 CoreTypeProvider typeProvider) throws IOException { | |
| 825 autoGenerate(unit); | |
| 826 } | |
| 827 | |
| 828 @Override | |
| 829 public void packageApp(LibrarySource app, Collection<LibraryUnit> libraries, | |
| 830 DartCompilerContext context, CoreTypeProvider typeProvi
der) | |
| 831 throws IOException { | |
| 832 // TODO Auto-generated method stub | |
| 833 } | |
| 834 | |
| 835 @Override | |
| 836 public String getAppExtension() { | |
| 837 // TODO Auto-generated method stub | |
| 838 return null; | |
| 839 } | |
| 840 | |
| 841 private boolean printFunctionDeclaration(DartVisitor visitor, DartMethodDefini
tion x) { | |
| 842 if (isConstructor(x)) { | |
| 843 return false; | |
| 844 } | |
| 845 nl(); | |
| 846 final DartFunction func = x.getFunction(); | |
| 847 final DartTypeNode returnTypeNode = func.getReturnTypeNode(); | |
| 848 final boolean isVoid = isVoid(returnTypeNode); | |
| 849 final boolean isSimple = isSimpleType(returnTypeNode); | |
| 850 final boolean isProxy = isProxyType(returnTypeNode); | |
| 851 final boolean isPromise = isPromise(returnTypeNode); | |
| 852 p(" "); | |
| 853 if (!isVoid && isSimple && !isPromise) { | |
| 854 p("Promise<"); | |
| 855 } | |
| 856 visitor.accept(returnTypeNode); | |
| 857 if (!isVoid) { | |
| 858 if (isSimple && !isPromise) { | |
| 859 p(">"); | |
| 860 } else if (!isProxy) { | |
| 861 p("$Proxy"); | |
| 862 } | |
| 863 } | |
| 864 p(" "); | |
| 865 visitor.accept(x.getName()); | |
| 866 p("("); | |
| 867 printParams(func.getParams()); | |
| 868 p(")"); | |
| 869 | |
| 870 return true; | |
| 871 } | |
| 872 } | |
| OLD | NEW |