blob: ab150cfbd6568b05333bfb5b2b94e3a2cdfd7671 [file] [log] [blame]
// Copyright (c) 2019, 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 fasta.transform_set_literals;
import 'dart:core' hide MapEntry;
import 'package:kernel/ast.dart'
show
Arguments,
Expression,
InterfaceType,
Let,
MethodInvocation,
Name,
Procedure,
SetLiteral,
StaticInvocation,
TreeNode,
VariableDeclaration,
VariableGet;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/visitor.dart' show Transformer;
import '../source/source_loader.dart' show SourceLoader;
import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
// TODO(askesc): Delete this class when all backends support set literals.
class SetLiteralTransformer extends Transformer {
final CoreTypes coreTypes;
final Procedure setFactory;
final Procedure addMethod;
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
RedirectingFactoryBody body = factory?.function?.body;
return body?.target;
}
static Procedure _findAddMethod(CoreTypes coreTypes) {
return coreTypes.index.getMember('dart:core', 'Set', 'add');
}
SetLiteralTransformer(SourceLoader loader)
: coreTypes = loader.coreTypes,
setFactory = _findSetFactory(loader.coreTypes),
addMethod = _findAddMethod(loader.coreTypes);
TreeNode visitSetLiteral(SetLiteral node) {
if (node.isConst) return node;
// Outermost declaration of let chain: Set<E> setVar = new Set<E>();
VariableDeclaration setVar = new VariableDeclaration.forValue(
new StaticInvocation(
setFactory, new Arguments([], types: [node.typeArgument])),
type: new InterfaceType(coreTypes.setClass, [node.typeArgument]));
// Innermost body of let chain: setVar
Expression setExp = new VariableGet(setVar);
for (int i = node.expressions.length - 1; i >= 0; i--) {
// let _ = setVar.add(expression) in rest
Expression entry = node.expressions[i].accept<TreeNode>(this);
setExp = new Let(
new VariableDeclaration.forValue(new MethodInvocation(
new VariableGet(setVar),
new Name("add"),
new Arguments([entry]),
addMethod)),
setExp);
}
return new Let(setVar, setExp);
}
}