Files
sdk/pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart
T
Dmitry Stefantsov d5e2fcb430 Merge the work on Generic Types Reification from 'dart-lang/reify' repo
This CL adds the work done at https://github.com/dart-lang/reify to SDK.
The commit that is used for the merge is
a2066a68374d49de92ff75f5e1ffc36335fd9451 (Nov 23, 2016). The code is
adjusted to respect the changes of the kernel package in SDK since that
commit.

The reify transformation is run by specifying 'vmreify' target to
'dartk'. The transformation requires its runtime library to present in
the program being transformed. The library is found in its default
location in SDK checkout if 'dartk' is run from its default location in
SDK checkout. To preserve the library in the output, TreeShaker is
disabled in 'vmreify' target.

The "golden" set of tests is also copied from 'dart-lang/reify'
repository, and the appropriate test suite is defined for it.

The bash script 'bin/reified_dart' from 'dart-lang/reify' is rewritten
as Dart script 'pkg/kernel/bin/reified_dart.dart'. It requires path to
'dartk' and path to SDK. Those are taken from their default locations in
SDK if 'reified_dart.dart' is run from its default location in SDK.

The added files were formatted using 'dartfmt' with default settings.
Additionally, the files were checked with 'dartanalyzer --strong'. The
necessary changes were made to fix the error messages. There are some
'hint' and 'error' messages left for some .dart files from the added
test cases, but they reflect intentional errors or conventions in those
files.

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

Review-Url: https://codereview.chromium.org/2697873007 .
2017-02-17 14:19:29 +01:00

107 lines
3.0 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.transformation.reify.analysis.program_analysis;
import '../asts.dart';
import 'package:kernel/ast.dart';
// TODO(karlklose): keep all predicates and derived information here and move
// the actual data to a builder class.
class ProgramKnowledge {
Map<Member, Set<TypeParameter>> _usedTypeVariables =
<Member, Set<TypeParameter>>{};
Map<Member, Set<DartType>> isTests = <Member, Set<DartType>>{};
Set<Class> _classTests;
/// Contains all classes that are used as the declaration of a type expression
/// in a type test.
Set<Class> get classTests {
if (_classTests == null) {
_classTests = isTests.values
.expand((set) => set)
.where((DartType type) => type is InterfaceType)
.map((DartType type) => (type as InterfaceType).classNode)
.toSet();
}
return _classTests;
}
recordTypeVariableUse(Expression expression, TypeParameter parameter) {
// TODO(karlklose): also record expression.
add(_usedTypeVariables, getEnclosingMember(expression), parameter);
}
Set<TypeParameter> usedParameters(Member member) {
return _usedTypeVariables[member] ?? new Set<TypeParameter>();
}
void recordIsTest(IsExpression node, DartType type) {
add(isTests, getEnclosingMember(node), type);
}
add(Map<dynamic, Set> map, key, value) {
map.putIfAbsent(key, () => new Set()).add(value);
}
}
typedef bool LibraryFilter(Library library);
class ProgramAnalysis extends Visitor {
final ProgramKnowledge knowledge;
final LibraryFilter analyzeLibrary;
ProgramAnalysis(this.knowledge, this.analyzeLibrary);
defaultTreeNode(TreeNode node) => node.visitChildren(this);
visitLibrary(Library library) {
if (!analyzeLibrary(library)) {
return;
}
super.visitLibrary(library);
}
handleTypeReference(TreeNode node, DartType type) {
typeVariables(type).forEach((TypeParameter parameter) {
knowledge.recordTypeVariableUse(node, parameter);
});
}
handleInstantiation(InvocationExpression node) {
node.arguments.types.forEach((DartType type) {
handleTypeReference(node, type);
});
}
visitIsExpression(IsExpression node) {
knowledge.recordIsTest(node, node.type);
handleTypeReference(node, node.type);
node.visitChildren(this);
}
visitConstructorInvocation(ConstructorInvocation node) {
handleInstantiation(node);
node.visitChildren(this);
}
visitStaticInvocation(StaticInvocation node) {
if (node.target.kind == ProcedureKind.Factory) {
handleInstantiation(node);
}
node.visitChildren(this);
}
}
bool _analyzeAll(Library library) => true;
ProgramKnowledge analyze(Program program,
{LibraryFilter analyzeLibrary: _analyzeAll}) {
ProgramKnowledge knowledge = new ProgramKnowledge();
program.accept(new ProgramAnalysis(knowledge, analyzeLibrary));
return knowledge;
}