Files
sdk/pkg/kernel/lib/transformations/closure/mock.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

209 lines
6.8 KiB
Dart

// 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.mock;
import '../../ast.dart'
show
Arguments,
Block,
Class,
Constructor,
ConstructorInvocation,
DartType,
DynamicType,
EmptyStatement,
Expression,
ExpressionStatement,
Field,
FieldInitializer,
FunctionNode,
Initializer,
IntLiteral,
Library,
MethodInvocation,
Name,
NullLiteral,
Procedure,
ProcedureKind,
Program,
PropertyGet,
ReturnStatement,
Source,
Statement,
StaticInvocation,
Supertype,
TreeNode,
VariableDeclaration,
VariableGet;
import '../../core_types.dart' show CoreTypes;
import '../../frontend/accessors.dart'
show
Accessor,
IndexAccessor,
PropertyAccessor,
ThisPropertyAccessor,
VariableAccessor;
/// TODO(dmitryas): make the "[]=" operator return the value.
/// Extend the program with this mock:
///
/// class Context {
/// final List list;
/// var parent;
/// Context(int i) : list = new List(i);
/// operator[] (int i) => list[i];
/// operator[]= (int i, value) {
/// list[i] = value;
/// }
/// Context copy() {
/// Context c = new Context(list.length);
/// c.parent = parent;
/// c.list.setRange(0, list.length, list);
/// return c;
/// }
/// }
///
/// Returns the mock.
Class mockUpContext(CoreTypes coreTypes, Program program) {
String fileUri = "dart:mock";
/// final List list;
Field listField = new Field(new Name("list"),
type: coreTypes.listClass.rawType, isFinal: true, fileUri: fileUri);
Accessor listFieldAccessor = new ThisPropertyAccessor(
listField.name, listField, null, TreeNode.noOffset);
/// var parent;
Field parentField = new Field(new Name("parent"), fileUri: fileUri);
Accessor parentFieldAccessor = new ThisPropertyAccessor(
parentField.name, parentField, parentField, TreeNode.noOffset);
List<Field> fields = <Field>[listField, parentField];
/// Context(int i) : list = new List(i);
VariableDeclaration iParameter = new VariableDeclaration("i",
type: coreTypes.intClass.rawType, isFinal: true);
// TODO(karlklose): use the default factory when it is exposed again.
Procedure listConstructor = coreTypes.listClass.procedures
.firstWhere((Procedure p) => p.name.name == 'filled');
Constructor constructor = new Constructor(
new FunctionNode(new EmptyStatement(),
positionalParameters: <VariableDeclaration>[iParameter]),
name: new Name(""),
initializers: <Initializer>[
new FieldInitializer(
listField,
new StaticInvocation(
listConstructor,
new Arguments(<Expression>[
new VariableAccessor(iParameter, null, TreeNode.noOffset)
.buildSimpleRead(),
new NullLiteral(),
], types: <DartType>[
const DynamicType()
])))
]);
/// operator[] (int i) => list[i];
iParameter = new VariableDeclaration("i",
type: coreTypes.intClass.rawType, isFinal: true);
Accessor accessor = IndexAccessor.make(
listFieldAccessor.buildSimpleRead(),
new VariableAccessor(iParameter, null, TreeNode.noOffset)
.buildSimpleRead(),
null,
null);
Procedure indexGet = new Procedure(
new Name("[]"),
ProcedureKind.Operator,
new FunctionNode(new ReturnStatement(accessor.buildSimpleRead()),
positionalParameters: <VariableDeclaration>[iParameter]),
fileUri: fileUri);
/// operator[]= (int i, value) {
/// list[i] = value;
/// }
iParameter = new VariableDeclaration("i",
type: coreTypes.intClass.rawType, isFinal: true);
VariableDeclaration valueParameter =
new VariableDeclaration("value", isFinal: true);
accessor = IndexAccessor.make(
listFieldAccessor.buildSimpleRead(),
new VariableAccessor(iParameter, null, TreeNode.noOffset)
.buildSimpleRead(),
null,
null);
Expression expression = accessor.buildAssignment(
new VariableAccessor(valueParameter, null, TreeNode.noOffset)
.buildSimpleRead(),
voidContext: true);
Procedure indexSet = new Procedure(
new Name("[]="),
ProcedureKind.Operator,
new FunctionNode(new ExpressionStatement(expression),
positionalParameters: <VariableDeclaration>[
iParameter,
valueParameter
]),
fileUri: fileUri);
/// Context copy() {
/// Context c = new Context(list.length);
/// c.parent = parent;
/// c.list.setRange(0, list.length, list);
/// return c;
/// }
VariableDeclaration c = new VariableDeclaration("c",
initializer: new ConstructorInvocation(
constructor,
new Arguments(<Expression>[
new PropertyGet(
listFieldAccessor.buildSimpleRead(), new Name("length"))
])));
Accessor accessCParent = PropertyAccessor.make(
new VariableGet(c), parentField.name, parentField, parentField);
Accessor accessCList = PropertyAccessor.make(
new VariableGet(c), listField.name, listField, null);
List<Statement> statements = <Statement>[
c,
new ExpressionStatement(accessCParent.buildAssignment(
parentFieldAccessor.buildSimpleRead(),
voidContext: true)),
new ExpressionStatement(new MethodInvocation(
accessCList.buildSimpleRead(),
new Name("setRange"),
new Arguments(<Expression>[
new IntLiteral(0),
new PropertyGet(
listFieldAccessor.buildSimpleRead(), new Name("length")),
listFieldAccessor.buildSimpleRead()
]))),
new ReturnStatement(new VariableGet(c))
];
Procedure copy = new Procedure(new Name("copy"), ProcedureKind.Method,
new FunctionNode(new Block(statements)),
fileUri: fileUri);
List<Procedure> procedures = <Procedure>[indexGet, indexSet, copy];
Class contextClass = new Class(
name: "Context",
supertype: new Supertype(coreTypes.objectClass, const <DartType>[]),
constructors: [constructor],
fields: fields,
procedures: procedures,
fileUri: fileUri);
Library mock = new Library(Uri.parse(fileUri),
name: "mock", classes: [contextClass])..fileUri = fileUri;
program.libraries.add(mock);
mock.parent = program;
program.uriToSource[mock.fileUri] = new Source(<int>[0], const <int>[]);
return contextClass;
}