diff --git a/pkg/kernel/bin/transform.dart b/pkg/kernel/bin/transform.dart index 28425bac100..3f11e2d53f9 100755 --- a/pkg/kernel/bin/transform.dart +++ b/pkg/kernel/bin/transform.dart @@ -12,7 +12,6 @@ import 'package:kernel/checks.dart' as checks; import 'package:kernel/transformations/continuation.dart' as cont; import 'package:kernel/transformations/infer_values.dart' as infer_values; import 'package:kernel/transformations/mixin_full_resolution.dart' as mix; -import 'package:kernel/transformations/closure_conversion.dart' as closures; import 'package:kernel/transformations/treeshaker.dart' as treeshaker; import 'batch_util.dart'; @@ -23,10 +22,7 @@ ArgParser parser = new ArgParser() allowed: ['text', 'bin'], defaultsTo: 'bin', help: 'Output format.') - ..addOption('out', - abbr: 'o', - help: 'Output file.', - defaultsTo: null) + ..addOption('out', abbr: 'o', help: 'Output file.', defaultsTo: null) ..addFlag('verbose', abbr: 'v', negatable: false, @@ -76,13 +72,11 @@ Future runTransformation(List arguments) async { case 'resolve-mixins': program = mix.transformProgram(program); break; - case 'closures': - program = closures.transformProgram(program); - break; case 'treeshake': program = treeshaker.transformProgram(program); break; - default: throw 'Unknown transformation'; + default: + throw 'Unknown transformation'; } program.accept(new checks.CheckParentPointers()); diff --git a/pkg/kernel/lib/transformations/closure_conversion.dart b/pkg/kernel/lib/transformations/closure_conversion.dart deleted file mode 100644 index 18da0669c04..00000000000 --- a/pkg/kernel/lib/transformations/closure_conversion.dart +++ /dev/null @@ -1,440 +0,0 @@ -// 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. - -library kernel.transformations.closure_conversion; - -import '../ast.dart'; -import '../core_types.dart'; -import '../visitor.dart'; - -Program transformProgram(Program program) { - var captured = new CapturedVariables(); - captured.visitProgram(program); - - var convert = - new ClosureConverter(new CoreTypes(program), captured.variables); - return convert.visitProgram(program); -} - -class CapturedVariables extends RecursiveVisitor { - FunctionNode _currentFunction; - final Map _function = - {}; - - final Set variables = new Set(); - - visitFunctionNode(FunctionNode node) { - var saved = _currentFunction; - _currentFunction = node; - node.visitChildren(this); - _currentFunction = saved; - } - - visitVariableDeclaration(VariableDeclaration node) { - _function[node] = _currentFunction; - node.visitChildren(this); - } - - visitVariableGet(VariableGet node) { - if (_function[node.variable] != _currentFunction) { - variables.add(node.variable); - } - node.visitChildren(this); - } - - visitVariableSet(VariableSet node) { - if (_function[node.variable] != _currentFunction) { - variables.add(node.variable); - } - node.visitChildren(this); - } -} - -abstract class Context { - Expression get expression; - - void extend(VariableDeclaration variable, Expression value); - - Expression lookup(VariableDeclaration variable); - Expression assign(VariableDeclaration variable, Expression value); - - Context toClosureContext(VariableDeclaration parameter); -} - -class NoContext extends Context { - final ClosureConverter converter; - - NoContext(this.converter); - - Expression get expression => new NullLiteral(); - - void extend(VariableDeclaration variable, Expression value) { - converter.context = - new LocalContext(converter, this)..extend(variable, value); - } - - - Expression lookup(VariableDeclaration variable) { - throw 'Unbound NoContext.lookup($variable)'; - } - - Expression assign(VariableDeclaration variable, Expression value) { - throw 'Unbound NoContext.assign($variable, ...)'; - } - - Context toClosureContext(VariableDeclaration parameter) { - return new ClosureContext(converter, parameter, - >[]); - } -} - - -class LocalContext extends Context { - final ClosureConverter converter; - final Context parent; - final VariableDeclaration self; - final IntLiteral size; - final List variables = []; - - LocalContext._internal(this.converter, this.parent, this.self, this.size); - - factory LocalContext(ClosureConverter converter, Context parent) { - Class contextClass = converter.internalContextClass; - assert(contextClass.constructors.length == 1); - IntLiteral zero = new IntLiteral(0); - VariableDeclaration declaration = - new VariableDeclaration.forValue( - new ConstructorInvocation(contextClass.constructors.first, - new Arguments([zero])), - type: new InterfaceType(contextClass)); - converter.insert(declaration); - converter.insert(new ExpressionStatement( - new PropertySet(new VariableGet(declaration), - new Name('parent'), - parent.expression))); - - return new LocalContext._internal(converter, parent, declaration, zero); - } - - Expression get expression => new VariableGet(self); - - void extend(VariableDeclaration variable, Expression value) { - converter.insert( - new ExpressionStatement( - new MethodInvocation( - expression, - new Name('[]='), - new Arguments( - [new IntLiteral(variables.length), value])))); - ++size.value; - variables.add(variable); - } - - Expression lookup(VariableDeclaration variable) { - var index = variables.indexOf(variable); - return index == -1 - ? parent.lookup(variable) - : new MethodInvocation( - expression, - new Name('[]'), - new Arguments([new IntLiteral(index)])); - } - - Expression assign(VariableDeclaration variable, Expression value) { - var index = variables.indexOf(variable); - return index == -1 - ? parent.assign(variable, value) - : new MethodInvocation( - expression, - new Name('[]='), - new Arguments([new IntLiteral(index), value])); - } - - Context toClosureContext(VariableDeclaration parameter) { - List> variabless = >[]; - var current = this; - while (current != null && current is! NoContext) { - if (current is LocalContext) { - variabless.add(current.variables); - current = current.parent; - } else if (current is ClosureContext) { - variabless.addAll(current.variabless); - current = null; - } else if (current is LoopContext) { - // TODO. - current = current.parent; - } - } - return new ClosureContext(converter, parameter, variabless); - } -} - -class LoopContext { - final ClosureConverter converter; - final Context parent; - - LoopContext(this.converter, this.parent); - - void extend(VariableDeclaration variable, Expression value) { - converter.context = - new LocalContext(converter, parent)..extend(variable, value); - } -} - -class ClosureContext extends Context { - final ClosureConverter converter; - final VariableDeclaration self; - final List> variabless; - - ClosureContext(this.converter, this.self, this.variabless); - - Expression get expression => new VariableGet(self); - - void extend(VariableDeclaration variable, Expression value) { - converter.context = - new LocalContext(converter, this)..extend(variable, value); - } - - Expression lookup(VariableDeclaration variable) { - var context = expression; - for (var variables in variabless) { - var index = variables.indexOf(variable); - if (index != -1) { - return new MethodInvocation( - context, - new Name('[]'), - new Arguments([new IntLiteral(index)])); - } - context = new PropertyGet(context, new Name('parent')); - } - throw 'Unbound ClosureContext.lookup($variable)'; - } - - Expression assign(VariableDeclaration variable, Expression value) { - var context = expression; - for (var variables in variabless) { - var index = variables.indexOf(variable); - if (index != -1) { - return new MethodInvocation( - context, - new Name('[]='), - new Arguments([new IntLiteral(index), value])); - } - context = new PropertyGet(context, new Name('parent')); - } - throw 'Unbound ClosureContext.lookup($variable)'; - } - - Context toClosureContext(VariableDeclaration parameter) { - return new ClosureContext(converter, parameter, variabless); - } -} - -class ClosureConverter extends Transformer { - final CoreTypes coreTypes; - Class internalContextClass; - final Set captured; - - Block _currentBlock; - int _insertionIndex = 0; - - Context context; - - ClosureConverter(this.coreTypes, this.captured) { - internalContextClass = coreTypes.getCoreClass('dart:_internal', 'Context'); - } - - void insert(Statement statement) { - _currentBlock.statements.insert(_insertionIndex++, statement); - statement.parent = _currentBlock; - } - - TreeNode visitConstructor(Constructor node) { - return node; - } - - TreeNode visitFunctionDeclaration(FunctionDeclaration node) { - if (captured.contains(node.variable)) { - context.extend(node.variable, - new FunctionExpression(node.function)); - } - - Block savedBlock = _currentBlock; - int savedIndex = _insertionIndex; - Context savedContext = context; - - Statement body = node.function.body; - assert(body != null); - - if (body is Block) { - _currentBlock = body; - } else { - _currentBlock = new Block([body]); - node.function.body = body.parent = _currentBlock; - } - _insertionIndex = 0; - - // TODO: This is really the closure, not the context. - VariableDeclaration parameter = - new VariableDeclaration(null, - type: internalContextClass.rawType, - isFinal: true); - node.function.positionalParameters.insert(0, parameter); - parameter.parent = node.function; - ++node.function.requiredParameterCount; - context = context.toClosureContext(parameter); - - // Don't visit the children, because that included a variable declaration. - node.function = node.function.accept(this); - - _currentBlock = savedBlock; - _insertionIndex = savedIndex; - context = savedContext; - - return captured.contains(node.variable) ? null : node; - } - - TreeNode visitFunctionExpression(FunctionExpression node) { - Block savedBlock = _currentBlock; - int savedIndex = _insertionIndex; - Context savedContext = context; - - Statement body = node.function.body; - assert(body != null); - - if (body is Block) { - _currentBlock = body; - } else { - _currentBlock = new Block([body]); - node.function.body = body.parent = _currentBlock; - } - _insertionIndex = 0; - - // TODO: This is really the closure, not the context. - VariableDeclaration parameter = - new VariableDeclaration(null, - type: internalContextClass.rawType, - isFinal: true); - node.function.positionalParameters.insert(0, parameter); - parameter.parent = node.function; - ++node.function.requiredParameterCount; - context = context.toClosureContext(parameter); - - node.transformChildren(this); - - _currentBlock = savedBlock; - _insertionIndex = savedIndex; - context = savedContext; - - return node; - } - - TreeNode visitProcedure(Procedure node) { - assert(_currentBlock == null); - assert(_insertionIndex == 0); - assert(context == null); - - Statement body = node.function.body; - if (body == null) return node; - - // Ensure that the body is a block which becomes the current block. - if (body is Block) { - _currentBlock = body; - } else { - _currentBlock = new Block([body]); - node.function.body = body.parent = _currentBlock; - } - _insertionIndex = 0; - - // Start with no context. This happens after setting up _currentBlock - // so statements can be emitted into _currentBlock if necessary. - context = new NoContext(this); - - node.transformChildren(this); - - _currentBlock = null; - _insertionIndex = 0; - context = null; - return node; - } - - TreeNode visitLocalInitializer(LocalInitializer node) { - assert(!captured.contains(node.variable)); - node.transformChildren(this); - return node; - } - - TreeNode visitFunctionNode(FunctionNode node) { - transformList(node.typeParameters, this, node); - - void extend(VariableDeclaration parameter) { - context.extend(parameter, new VariableGet(parameter)); - } - // TODO: Can parameters contain initializers (e.g., for optional ones) that - // need to be closure converted? - node.positionalParameters.where(captured.contains).forEach(extend); - node.namedParameters.where(captured.contains).forEach(extend); - - assert(node.body != null); - node.body = node.body.accept(this); - node.body.parent = node; - return node; - } - - TreeNode visitBlock(Block node) { - Block savedBlock; - int savedIndex; - if (_currentBlock != node) { - savedBlock = _currentBlock; - savedIndex = _insertionIndex; - _currentBlock = node; - _insertionIndex = 0; - } - - while (_insertionIndex < _currentBlock.statements.length) { - assert(_currentBlock == node); - - var original = _currentBlock.statements[_insertionIndex]; - var transformed = original.accept(this); - assert(_currentBlock.statements[_insertionIndex] == original); - if (transformed == null) { - _currentBlock.statements.removeAt(_insertionIndex); - } else { - _currentBlock.statements[_insertionIndex++] = transformed; - transformed.parent = _currentBlock; - } - } - - if (savedBlock != null) { - _currentBlock = savedBlock; - _insertionIndex = savedIndex; - } - return node; - } - - TreeNode visitVariableDeclaration(VariableDeclaration node) { - node.transformChildren(this); - - if (!captured.contains(node)) return node; - context.extend(node, node.initializer ?? new NullLiteral()); - - // TODO(ahe): Return null here when the parent has been correctly - // rewritten. So far, only for-in is known to use this return value. - return new VariableDeclaration(null, initializer: new InvalidExpression()); - } - - TreeNode visitVariableGet(VariableGet node) { - return captured.contains(node.variable) - ? context.lookup(node.variable) - : node; - } - - TreeNode visitVariableSet(VariableSet node) { - node.transformChildren(this); - - return captured.contains(node.variable) - ? context.assign(node.variable, node.value) - : node; - } -}