Files
sdk/pkg/kernel/lib/transformations/closure/rewriter.dart
T
Dmitry Stefantsov 9ab86da19c Add Vector type to Kernel
There are four operations that work on Vectors: Vector creation, looking
up an item in a Vector, assigning a value to an item in a Vector, and
copying a Vector. The first three operations are allowed to only use
integer literals as number operands (length for Vector creation, index
for item lookup and assignment). Corresponding AST nodes are created for
these operations.

Vectors are used to represent contexts in Closure Conversion. The parent
context is stored as item 0 in its children contexts. The "golden" tests
for this transformation are adjusted accordingly.

The support for Vectors is added to ast-to-text, ast-to-binary, and
binary-to-ast transformations.

R=asgerf@google.com, kmillikin@google.com

Review-Url: https://codereview.chromium.org/2767773004 .
2017-03-27 15:52:32 +02:00

121 lines
4.1 KiB
Dart

// Copyright (c) 2017, 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.rewriter;
import '../../ast.dart';
import 'converter.dart' show ClosureConverter;
/// Used by the [Context] to initialize and update the context variable
/// used to capture the variables closed over by functions.
abstract class AstRewriter {
/// The declared variable that holds the context.
VariableDeclaration contextDeclaration;
/// Expression that is used to initialize the vector representing the context.
/// It's [length] field is modified by the [extend] operation
VectorCreation vectorCreation;
/// Creates a new [AstRewriter] for a (nested) [Block].
BlockRewriter forNestedBlock(Block block);
/// Inserts an allocation of a context and initializes [contextDeclaration]
/// and [vectorCreation].
void insertContextDeclaration(Expression accessParent);
/// Inserts an expression or statement that extends the context.
void insertExtendContext(VectorSet extender);
void _createDeclaration() {
assert(contextDeclaration == null && vectorCreation == null);
// Context size is set to 1 initially, because the 0-th element of it works
// as a link to the parent context.
vectorCreation = new VectorCreation(1);
contextDeclaration = new VariableDeclaration.forValue(vectorCreation,
type: new VectorType());
contextDeclaration.name = "#context";
}
}
/// Adds a local variable for the context and adds update [Statement]s to the
/// current block.
class BlockRewriter extends AstRewriter {
Block _currentBlock;
int _insertionIndex;
BlockRewriter(this._currentBlock) : _insertionIndex = 0;
BlockRewriter forNestedBlock(Block block) {
return _currentBlock != block ? new BlockRewriter(block) : this;
}
void transformStatements(Block block, ClosureConverter converter) {
while (_insertionIndex < _currentBlock.statements.length) {
var original = _currentBlock.statements[_insertionIndex];
var transformed = original.accept(converter);
assert(_currentBlock.statements[_insertionIndex] == original);
if (transformed == null) {
_currentBlock.statements.removeAt(_insertionIndex);
} else {
_currentBlock.statements[_insertionIndex++] = transformed;
transformed.parent = _currentBlock;
}
}
}
void _insertStatement(Statement statement) {
_currentBlock.statements.insert(_insertionIndex++, statement);
statement.parent = _currentBlock;
}
void insertContextDeclaration(Expression accessParent) {
_createDeclaration();
_insertStatement(contextDeclaration);
if (accessParent is! NullLiteral) {
// Index 0 of a context always points to the parent.
_insertStatement(new ExpressionStatement(
new VectorSet(new VariableGet(contextDeclaration), 0, accessParent)));
}
}
void insertExtendContext(VectorSet extender) {
_insertStatement(new ExpressionStatement(extender));
}
}
/// Creates and updates the context as [Let] bindings around the initializer
/// expression.
class InitializerRewriter extends AstRewriter {
final Expression initializingExpression;
InitializerRewriter(this.initializingExpression) {
assert(initializingExpression.parent is FieldInitializer);
}
@override
BlockRewriter forNestedBlock(Block block) {
return new BlockRewriter(block);
}
@override
void insertContextDeclaration(Expression accessParent) {
_createDeclaration();
FieldInitializer parent = initializingExpression.parent;
Let binding = new Let(contextDeclaration, initializingExpression);
initializingExpression.parent = binding;
parent.value = binding;
binding.parent = parent;
}
@override
void insertExtendContext(VectorSet extender) {
Let parent = initializingExpression.parent;
Let binding = new Let(new VariableDeclaration(null, initializer: extender),
initializingExpression);
parent.body = binding;
binding.parent = parent;
}
}