blob: 94bf00d83ea1c2054aaf6c40cc32fdfa5fc2a1a7 [file] [log] [blame]
// Copyright (c) 2020, 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.scanner;
import '../ast.dart';
abstract class Scanner<X extends TreeNode?, Y extends TreeNode?> {
final Scanner<Y, TreeNode?>? next;
Scanner(this.next);
bool predicate(X x);
ScanResult<X, Y> scan(TreeNode node);
}
class ScanResult<X extends TreeNode?, Y extends TreeNode?> {
Map<X, ScanResult<Y, TreeNode?>?> targets = new Map();
Map<X, ScanError>? errors;
@override
String toString() => 'ScanResult<$X,$Y>';
}
class ScanError {}
abstract class ClassScanner<Y extends TreeNode?> implements Scanner<Class, Y> {
@override
final Scanner<Y, TreeNode?>? next;
ClassScanner(this.next);
@override
bool predicate(Class node);
@override
ScanResult<Class, Y> scan(TreeNode node) {
ScanResult<Class, Y> result = new ScanResult<Class, Y>();
if (node is Class) {
if (predicate(node)) {
result.targets[node] = next?.scan(node);
// TODO(cstefantsova): set result.errors when specification is landed,
// same with all other places where targets is set
}
} else if (node is Library) {
_scanLibrary(node, result);
} else if (node is Component) {
_scanComponent(node, result);
}
return result;
}
void _scanLibrary(Library library, ScanResult<Class, Y> result) {
for (Class cls in library.classes) {
if (predicate(cls)) {
result.targets[cls] = next?.scan(cls);
}
}
}
void _scanComponent(Component component, ScanResult<Class, Y> result) {
for (Library library in component.libraries) {
_scanLibrary(library, result);
}
}
}
abstract class FieldScanner<Y extends TreeNode> implements Scanner<Field, Y> {
@override
final Scanner<Y, TreeNode>? next;
FieldScanner(this.next);
@override
bool predicate(Field node);
@override
ScanResult<Field, Y> scan(TreeNode node) {
ScanResult<Field, Y> result = new ScanResult<Field, Y>();
if (node is Field) {
_scanField(node, result);
} else if (node is Class) {
_scanClass(node, result);
} else if (node is Library) {
_scanLibrary(node, result);
} else if (node is Component) {
_scanComponent(node, result);
}
return result;
}
void _scanField(Field field, ScanResult<Field, Y> result) {
if (predicate(field)) {
result.targets[field] = next?.scan(field);
}
}
void _scanClass(Class cls, ScanResult<Field, Y> result) {
for (Field field in cls.fields) {
_scanField(field, result);
}
}
void _scanLibrary(Library library, ScanResult<Field, Y> result) {
for (Class cls in library.classes) {
_scanClass(cls, result);
}
for (Field field in library.fields) {
_scanField(field, result);
}
}
void _scanComponent(Component component, ScanResult<Field, Y> result) {
for (Library library in component.libraries) {
_scanLibrary(library, result);
}
}
}
abstract class MemberScanner<Y extends TreeNode> implements Scanner<Member, Y> {
@override
final Scanner<Y, TreeNode?>? next;
MemberScanner(this.next);
@override
bool predicate(Member node);
@override
ScanResult<Member, Y> scan(TreeNode node) {
ScanResult<Member, Y> result = new ScanResult<Member, Y>();
if (node is Member) {
_scanMember(node, result);
} else if (node is Class) {
_scanClass(node, result);
} else if (node is Library) {
_scanLibrary(node, result);
} else if (node is Component) {
_scanComponent(node, result);
}
return result;
}
void _scanMember(Member member, ScanResult<Member, Y> result) {
if (predicate(member)) {
result.targets[member] = next?.scan(member);
}
}
void _scanClass(Class cls, ScanResult<Member, Y> result) {
for (Member member in cls.members) {
_scanMember(member, result);
}
}
void _scanLibrary(Library library, ScanResult<Member, Y> result) {
for (Class cls in library.classes) {
_scanClass(cls, result);
}
for (Member member in library.members) {
_scanMember(member, result);
}
}
void _scanComponent(Component component, ScanResult<Member, Y> result) {
for (Library library in component.libraries) {
_scanLibrary(library, result);
}
}
}
abstract class ProcedureScanner<Y extends TreeNode?>
implements Scanner<Procedure, Y> {
@override
final Scanner<Y, TreeNode>? next;
ProcedureScanner(this.next);
@override
bool predicate(Procedure node);
@override
ScanResult<Procedure, Y> scan(TreeNode node) {
ScanResult<Procedure, Y> result = new ScanResult<Procedure, Y>();
if (node is Procedure) {
_scanProcedure(node, result);
} else if (node is Class) {
_scanClass(node, result);
} else if (node is Library) {
_scanLibrary(node, result);
} else if (node is Component) {
_scanComponent(node, result);
}
return result;
}
void _scanProcedure(Procedure procedure, ScanResult<Procedure, Y> result) {
if (predicate(procedure)) {
result.targets[procedure] = next?.scan(procedure);
}
}
void _scanClass(Class cls, ScanResult<Procedure, Y> result) {
for (Procedure procedure in cls.procedures) {
_scanProcedure(procedure, result);
}
}
void _scanLibrary(Library library, ScanResult<Procedure, Y> result) {
for (Class cls in library.classes) {
_scanClass(cls, result);
}
for (Procedure procedure in library.procedures) {
_scanProcedure(procedure, result);
}
}
void _scanComponent(Component component, ScanResult<Procedure, Y> result) {
for (Library library in component.libraries) {
_scanLibrary(library, result);
}
}
}
abstract class ExpressionScanner<Y extends TreeNode>
extends RecursiveResultVisitor<void> implements Scanner<Expression, Y> {
@override
final Scanner<Y, TreeNode>? next;
ScanResult<Expression, Y>? _result;
ExpressionScanner(this.next);
@override
bool predicate(Expression node);
@override
ScanResult<Expression, Y> scan(TreeNode node) {
ScanResult<Expression, Y> result =
_result = new ScanResult<Expression, Y>();
node.accept(this);
_result = null;
return result;
}
void visitExpression(Expression node) {
if (predicate(node)) {
_result!.targets[node] = next?.scan(node);
// TODO: Update result.errors.
}
}
}
abstract class MethodInvocationScanner<Y extends TreeNode?>
extends RecursiveVisitor
implements Scanner<InstanceInvocationExpression, Y> {
@override
final Scanner<Y, TreeNode>? next;
ScanResult<InstanceInvocationExpression, Y>? _result;
MethodInvocationScanner(this.next);
@override
bool predicate(InstanceInvocationExpression node);
@override
ScanResult<InstanceInvocationExpression, Y> scan(TreeNode node) {
ScanResult<InstanceInvocationExpression, Y> result =
_result = new ScanResult<InstanceInvocationExpression, Y>();
node.accept(this);
_result = null;
return result;
}
@override
void visitInstanceInvocation(InstanceInvocation node) {
if (predicate(node)) {
_result!.targets[node] = next?.scan(node);
// TODO: Update result.errors.
}
}
}