Chromium Code Reviews| Index: frog/leg/emitter.dart |
| =================================================================== |
| --- frog/leg/emitter.dart (revision 3781) |
| +++ frog/leg/emitter.dart (working copy) |
| @@ -41,26 +41,91 @@ |
| String prototype, |
| StringBuffer buffer, |
| Invocation invocation) { |
| - // TODO(ngeoffray): also support invocation with names. |
| + FunctionParameters parameters = member.computeParameters(compiler); |
| + int positionalArgumentCount = invocation.positionalArgumentCount; |
| + if (positionalArgumentCount == parameters.parameterCount) return; |
|
floitsch
2012/02/01 12:19:17
assert that invocation.namedArgumentCount == 0 bef
ngeoffray
2012/02/01 13:02:40
Done.
|
| + List<SourceString> names = invocation.orderedNamedArguments; |
| + assert(names.length == invocation.namedArguments.length); |
| + |
| String invocationName = |
| - namer.instanceMethodName(member.name, invocation.argumentCount); |
| - int allParameters = member.parameterCount(compiler); |
| - int missingParameters = allParameters - invocation.argumentCount; |
| - if (missingParameters == 0) return; |
| - assert(missingParameters > 0); |
| + namer.instanceMethodInvocationName(member.name, invocation); |
| buffer.add('$prototype.$invocationName = function('); |
| - StringBuffer parameters = new StringBuffer(); |
| - for (int i = 0; i < invocation.argumentCount; i++) { |
| - if (i != 0) parameters.add(', '); |
| - parameters.add('param$i'); |
| + |
| + // The parameters that this stub takes. |
| + StringBuffer parametersBuffer = new StringBuffer(); |
| + // The missing and named arguments that will be passed to the real |
| + // method. |
| + StringBuffer missingAndNamedArgumentsBuffer = new StringBuffer(); |
| + // The positional arguments that will be passed to the real |
| + // method. |
| + StringBuffer positionalArgumentsBuffer = new StringBuffer(); |
| + |
| + // We fullfil the string buffers depending on the selector. For |
|
floitsch
2012/02/01 12:19:17
s/fullfil/fill?
ngeoffray
2012/02/01 13:02:40
Done.
|
| + // example, take method foo: |
| + // foo(a, b, [c, d]); |
| + // |
| + // We may have multiple ways of calling foo: |
| + // (1) foo(1, 2, 3, 4) |
| + // (2) foo(1, 2); |
| + // (3) foo(1, 2, c: 3); |
| + // (4) foo(1, 2, d: 4); |
| + // (5) foo(1, 2, c: 3, d: 4); |
| + // (6) foo(1, 2, d: 4, c: 3); |
| + // |
| + // What we generate at the call sites are: |
| + // (1) foo$4(1, 2, 3, 4) |
| + // (2) foo$2(1, 2); |
| + // (3) foo$3$c(1, 2, c: 3); |
|
floitsch
2012/02/01 12:19:17
remove c:
ngeoffray
2012/02/01 13:02:40
Done.
|
| + // (4) foo$3$d(1, 2, d: 4); |
| + // (5) foo$4$c$d(1, 2, c: 3, d: 4); |
| + // (6) foo$4$c$d(1, 2, d: 4, c: 3); |
|
floitsch
2012/02/01 12:19:17
remove d: and c: and reorder 4 and 3.
ngeoffray
2012/02/01 13:02:40
Done.
|
| + // |
| + // The stubs we generate are (expressed in Dart): |
| + // (1) No stub generated, call is direct. |
| + // (2) foo$2(a, b) => foo$4(a, b, null, null) |
| + // (3) foo$3$c(a, b, c) => foo$4(a, b, c, null); |
| + // (4) foo$3$d(a, b, d) => foo$4(a, b, null, d); |
| + // (5) foo$4$c$d(a, b, c, d) => foo$4(a, b, c, d); |
| + // (6) Same as (5). |
| + // |
| + // We need to generate a stub for (5) because the order of the |
| + // stub arguments and the real method may be different. |
| + |
| + int count = 0; |
| + parameters.forEachParameter((Element element) { |
| + if (count < positionalArgumentCount) { |
| + if (count != 0) parametersBuffer.add(', '); |
|
floitsch
2012/02/01 12:19:17
Given these annoyances with the string-buffer, may
ngeoffray
2012/02/01 13:02:40
Done.
|
| + parametersBuffer.add('${element.name}'); |
|
floitsch
2012/02/01 12:19:17
parameter names might need to be mangled (eg. 'wit
ngeoffray
2012/02/01 13:02:40
Done.
|
| + positionalArgumentsBuffer.add('${element.name}'); |
| + } else { |
| + if (count != positionalArgumentCount || positionalArgumentCount != 0) { |
| + missingAndNamedArgumentsBuffer.add(', '); |
| + } |
| + int index = names.indexOf(element.name); |
| + if (index != -1) { |
| + // The order of the named arguments is not the same as the |
| + // one in the real method (which is in Dart source order). |
| + // Therefore, we don't add the argument to the |
| + // [parametersBuffer] just yet. |
| + missingAndNamedArgumentsBuffer.add('${element.name}'); |
| + } else { |
| + // TODO(ngeoffray): Get the default value. |
| + missingAndNamedArgumentsBuffer.add('(void 0)'); |
| + } |
| + } |
| + count++; |
| + }); |
| + |
| + // Add the named arguments to the parametersBuffer. |
| + for (SourceString name in names) { |
| + if (positionalArgumentCount != 0) parametersBuffer.add(', '); |
|
floitsch
2012/02/01 12:19:17
Only the first name in names should not have a ','
ngeoffray
2012/02/01 13:02:40
Gone with Strings.join.
|
| + parametersBuffer.add(name); |
| } |
| - buffer.add('$parameters) {\n'); |
| - buffer.add(' this.${namer.getName(member)}($parameters'); |
| - for (int i = 0; i < missingParameters; i++) { |
| - if (i != 0 || invocation.argumentCount != 0) buffer.add(', '); |
| - buffer.add('(void 0)'); |
| - } |
| - buffer.add(')\n}\n'); |
| + |
| + buffer.add('$parametersBuffer) {\n'); |
| + buffer.add(' return this.${namer.getName(member)}'); |
| + buffer.add('($positionalArgumentsBuffer$missingAndNamedArgumentsBuffer)'); |
| + buffer.add('\n}\n'); |
| } |
| void addParameterStubs(FunctionElement member, |