| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| /// A library to help move super calls last in the initializer list. |
| library kernel.frontend.super_calls; |
| |
| import '../ast.dart'; |
| |
| /// Mutates the initializer list of [node] so that its super initializer occurs |
| /// last, while its arguments are evaluated at the correct place. |
| /// |
| /// Does nothing if there is no super initializer or if it is already last. |
| void moveSuperInitializerLast(Constructor node) { |
| List<Initializer> initializers = node.initializers; |
| if (initializers.isEmpty) return; |
| if (initializers.last is SuperInitializer) return; |
| int superIndex = -1; |
| for (int i = initializers.length - 1; i >= 0; --i) { |
| Initializer initializer = initializers[i]; |
| if (initializer is SuperInitializer) { |
| superIndex = i; |
| break; |
| } |
| } |
| if (superIndex == -1) return; |
| SuperInitializer superCall = initializers[superIndex]; |
| Arguments arguments = superCall.arguments; |
| int argumentCount = arguments.positional.length + arguments.named.length; |
| |
| // We move all initializers after the super call to the place where the super |
| // call was, but reserve [argumentCount] slots before that for |
| // [LocalInitializer]s. |
| initializers.length += argumentCount; |
| initializers.setRange( |
| superIndex + argumentCount, // destination start (inclusive) |
| initializers.length - 1, // destination end (exclusive) |
| initializers, // source list |
| superIndex + 1); // source start index |
| initializers[initializers.length - 1] = superCall; |
| |
| // Fill in the [argumentCount] reserved slots with the evaluation expressions |
| // of the arguments to the super constructor call. |
| int storeIndex = superIndex; |
| for (int i = 0; i < arguments.positional.length; ++i) { |
| var variable = new VariableDeclaration.forValue(arguments.positional[i]); |
| arguments.positional[i] = new VariableGet(variable)..parent = arguments; |
| initializers[storeIndex++] = new LocalInitializer(variable)..parent = node; |
| } |
| for (int i = 0; i < arguments.named.length; ++i) { |
| NamedExpression argument = arguments.named[i]; |
| var variable = new VariableDeclaration.forValue(argument.value); |
| arguments.named[i].value = new VariableGet(variable)..parent = argument; |
| initializers[storeIndex++] = new LocalInitializer(variable)..parent = node; |
| } |
| } |