| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 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 | 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 /** | 5 /** |
| 6 * Generates the code for all used classes in the program. Static fields (even | 6 * Generates the code for all used classes in the program. Static fields (even |
| 7 * in classes) are ignored, since they can be treated as non-class elements. | 7 * in classes) are ignored, since they can be treated as non-class elements. |
| 8 * | 8 * |
| 9 * The code for the containing (used) methods must exist in the [:universe:]. | 9 * The code for the containing (used) methods must exist in the [:universe:]. |
| 10 */ | 10 */ |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 if (addedInheritFunction) return; | 33 if (addedInheritFunction) return; |
| 34 addedInheritFunction = true; | 34 addedInheritFunction = true; |
| 35 buffer.add('$inheritsName = '); | 35 buffer.add('$inheritsName = '); |
| 36 buffer.add(INHERIT_FUNCTION); | 36 buffer.add(INHERIT_FUNCTION); |
| 37 buffer.add(';\n'); | 37 buffer.add(';\n'); |
| 38 } | 38 } |
| 39 | 39 |
| 40 void addParameterStub(FunctionElement member, | 40 void addParameterStub(FunctionElement member, |
| 41 String prototype, | 41 String prototype, |
| 42 StringBuffer buffer, | 42 StringBuffer buffer, |
| 43 Invocation invocation) { | 43 Selector selector) { |
| 44 // TODO(ngeoffray): also support invocation with names. | 44 FunctionParameters parameters = member.computeParameters(compiler); |
| 45 int positionalArgumentCount = selector.positionalArgumentCount; |
| 46 if (positionalArgumentCount == parameters.parameterCount) { |
| 47 assert(selector.namedArgumentCount == 0); |
| 48 return; |
| 49 } |
| 50 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 51 |
| 45 String invocationName = | 52 String invocationName = |
| 46 namer.instanceMethodName(member.name, invocation.argumentCount); | 53 namer.instanceMethodInvocationName(member.name, selector); |
| 47 int allParameters = member.parameterCount(compiler); | |
| 48 int missingParameters = allParameters - invocation.argumentCount; | |
| 49 if (missingParameters == 0) return; | |
| 50 assert(missingParameters > 0); | |
| 51 buffer.add('$prototype.$invocationName = function('); | 54 buffer.add('$prototype.$invocationName = function('); |
| 52 StringBuffer parameters = new StringBuffer(); | 55 |
| 53 for (int i = 0; i < invocation.argumentCount; i++) { | 56 // The parameters that this stub takes. |
| 54 if (i != 0) parameters.add(', '); | 57 List<String> parametersBuffer = new List<String>(selector.argumentCount); |
| 55 parameters.add('param$i'); | 58 // The arguments that will be passed to the real method. |
| 56 } | 59 List<String> argumentsBuffer = new List<String>(parameters.parameterCount); |
| 57 buffer.add('$parameters) {\n'); | 60 |
| 58 buffer.add(' this.${namer.getName(member)}($parameters'); | 61 // We fill the lists depending on the selector. For example, |
| 59 for (int i = 0; i < missingParameters; i++) { | 62 // take method foo: |
| 60 if (i != 0 || invocation.argumentCount != 0) buffer.add(', '); | 63 // foo(a, b, [c, d]); |
| 61 buffer.add('(void 0)'); | 64 // |
| 62 } | 65 // We may have multiple ways of calling foo: |
| 63 buffer.add(')\n}\n'); | 66 // (1) foo(1, 2, 3, 4) |
| 67 // (2) foo(1, 2); |
| 68 // (3) foo(1, 2, 3); |
| 69 // (4) foo(1, 2, c: 3); |
| 70 // (5) foo(1, 2, d: 4); |
| 71 // (6) foo(1, 2, c: 3, d: 4); |
| 72 // (7) foo(1, 2, d: 4, c: 3); |
| 73 // |
| 74 // What we generate at the call sites are: |
| 75 // (1) foo$4(1, 2, 3, 4) |
| 76 // (2) foo$2(1, 2); |
| 77 // (3) foo$3(1, 2, 3); |
| 78 // (4) foo$3$c(1, 2, 3); |
| 79 // (5) foo$3$d(1, 2, 4); |
| 80 // (6) foo$4$c$d(1, 2, 3, 4); |
| 81 // (7) foo$4$c$d(1, 2, 3, 4); |
| 82 // |
| 83 // The stubs we generate are (expressed in Dart): |
| 84 // (1) No stub generated, call is direct. |
| 85 // (2) foo$2(a, b) => foo$4(a, b, null, null) |
| 86 // (3) foo$3(a, b, c) => foo$4(a, b, c, null) |
| 87 // (4) foo$3$c(a, b, c) => foo$4(a, b, c, null); |
| 88 // (5) foo$3$d(a, b, d) => foo$4(a, b, null, d); |
| 89 // (6) foo$4$c$d(a, b, c, d) => foo$4(a, b, c, d); |
| 90 // (7) Same as (5). |
| 91 // |
| 92 // We need to generate a stub for (5) because the order of the |
| 93 // stub arguments and the real method may be different. |
| 94 |
| 95 int count = 0; |
| 96 parameters.forEachParameter((Element element) { |
| 97 String jsName = JsNames.getValid('${element.name}'); |
| 98 if (count < positionalArgumentCount) { |
| 99 parametersBuffer[count] = jsName; |
| 100 argumentsBuffer[count] = jsName; |
| 101 } else { |
| 102 int index = names.indexOf(element.name); |
| 103 if (index != -1) { |
| 104 // The order of the named arguments is not the same as the |
| 105 // one in the real method (which is in Dart source order). |
| 106 argumentsBuffer[count] = jsName; |
| 107 parametersBuffer[selector.positionalArgumentCount + index] = jsName; |
| 108 } else { |
| 109 // TODO(ngeoffray): Get the default value. |
| 110 argumentsBuffer[count] = '(void 0)'; |
| 111 } |
| 112 } |
| 113 count++; |
| 114 }); |
| 115 |
| 116 buffer.add('${Strings.join(parametersBuffer, ",")}) {\n'); |
| 117 buffer.add(' return this.${namer.getName(member)}'); |
| 118 buffer.add('(${Strings.join(argumentsBuffer, ",")})\n}\n'); |
| 64 } | 119 } |
| 65 | 120 |
| 66 void addParameterStubs(FunctionElement member, | 121 void addParameterStubs(FunctionElement member, |
| 67 String prototype, | 122 String prototype, |
| 68 StringBuffer buffer) { | 123 StringBuffer buffer) { |
| 69 Set<Invocation> invocations = compiler.universe.invokedNames[member.name]; | 124 Set<Selector> selectors = compiler.universe.invokedNames[member.name]; |
| 70 if (invocations == null) return; | 125 if (selectors == null) return; |
| 71 for (Invocation invocation in invocations) { | 126 for (Selector selector in selectors) { |
| 72 if (!invocation.applies(compiler, member)) continue; | 127 if (!selector.applies(compiler, member)) continue; |
| 73 addParameterStub(member, prototype, buffer, invocation); | 128 addParameterStub(member, prototype, buffer, selector); |
| 74 } | 129 } |
| 75 } | 130 } |
| 76 | 131 |
| 77 void addInstanceMember(Element member, | 132 void addInstanceMember(Element member, |
| 78 String prototype, | 133 String prototype, |
| 79 StringBuffer buffer) { | 134 StringBuffer buffer) { |
| 80 assert(member.isInstanceMember()); | 135 assert(member.isInstanceMember()); |
| 81 if (member.kind === ElementKind.FUNCTION | 136 if (member.kind === ElementKind.FUNCTION |
| 82 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY | 137 || member.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY |
| 83 || member.kind === ElementKind.GETTER | 138 || member.kind === ElementKind.GETTER |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 emitStaticFunctions(buffer); | 343 emitStaticFunctions(buffer); |
| 289 emitStaticFinalFieldInitializations(buffer); | 344 emitStaticFinalFieldInitializations(buffer); |
| 290 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); | 345 buffer.add('var ${namer.CURRENT_ISOLATE} = new ${namer.ISOLATE}();\n'); |
| 291 Element main = compiler.universe.find(Compiler.MAIN); | 346 Element main = compiler.universe.find(Compiler.MAIN); |
| 292 buffer.add('${namer.isolateAccess(main)}();\n'); | 347 buffer.add('${namer.isolateAccess(main)}();\n'); |
| 293 compiler.assembledCode = buffer.toString(); | 348 compiler.assembledCode = buffer.toString(); |
| 294 }); | 349 }); |
| 295 return compiler.assembledCode; | 350 return compiler.assembledCode; |
| 296 } | 351 } |
| 297 } | 352 } |
| OLD | NEW |