Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Unified Diff: pkg/kernel/lib/verifier.dart

Issue 2825053002: Add typedef AST node boilerplate. (Closed)
Patch Set: Update FastaVerifyingVisitor to work with the changes in VerifyingVisitor Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/kernel/lib/type_environment.dart ('k') | pkg/kernel/lib/visitor.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/verifier.dart
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index c518a6566f3f562eeb19d198f6e568c89256dc47..18b93c320b958c61207f85c805d3a741a2582b03 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -38,13 +38,17 @@ class VerificationError {
}
}
+enum TypedefState { Done, BeingChecked }
+
/// Checks that a kernel program is well-formed.
///
/// This does not include any kind of type checking.
class VerifyingVisitor extends RecursiveVisitor {
final Set<Class> classes = new Set<Class>();
- final Set<TypeParameter> typeParameters = new Set<TypeParameter>();
+ final Set<Typedef> typedefs = new Set<Typedef>();
+ Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
+ final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
bool classTypeParametersAreInScope = false;
/// If true, relax certain checks for *outline* mode. For example, don't
@@ -67,7 +71,8 @@ class VerifyingVisitor extends RecursiveVisitor {
visitChildren(node);
}
- problem(TreeNode node, String details) {
+ problem(TreeNode node, String details, {TreeNode context}) {
+ context ??= this.context;
throw new VerificationError(context, node, details);
}
@@ -75,7 +80,8 @@ class VerifyingVisitor extends RecursiveVisitor {
if (!identical(node.parent, currentParent)) {
problem(
node,
- "Incorrect parent pointer: expected '${node.parent.runtimeType}',"
+ "Incorrect parent pointer on ${node.runtimeType}:"
+ " expected '${node.parent.runtimeType}',"
" but found: '${currentParent.runtimeType}'.");
}
var oldParent = currentParent;
@@ -135,14 +141,14 @@ class VerifyingVisitor extends RecursiveVisitor {
void declareTypeParameters(List<TypeParameter> parameters) {
for (int i = 0; i < parameters.length; ++i) {
var parameter = parameters[i];
- if (!typeParameters.add(parameter)) {
+ if (!typeParametersInScope.add(parameter)) {
problem(parameter, "Type parameter '$parameter' redeclared.");
}
}
}
void undeclareTypeParameters(List<TypeParameter> parameters) {
- typeParameters.removeAll(parameters);
+ typeParametersInScope.removeAll(parameters);
}
void checkVariableInScope(VariableDeclaration variable, TreeNode where) {
@@ -159,6 +165,11 @@ class VerifyingVisitor extends RecursiveVisitor {
problem(class_, "Class '$class_' declared more than once.");
}
}
+ for (var typedef_ in library.typedefs) {
+ if (!typedefs.add(typedef_)) {
+ problem(typedef_, "Typedef '$typedef_' declared more than once.");
+ }
+ }
library.members.forEach(declareMember);
for (var class_ in library.classes) {
class_.members.forEach(declareMember);
@@ -176,6 +187,32 @@ class VerifyingVisitor extends RecursiveVisitor {
}
}
+ void checkTypedef(Typedef node) {
+ var state = typedefState[node];
+ if (state == TypedefState.Done) return;
+ if (state == TypedefState.BeingChecked) {
+ problem(node, "The typedef '$node' refers to itself", context: node);
+ }
+ assert(state == null);
+ typedefState[node] = TypedefState.BeingChecked;
+ var savedTypeParameters = typeParametersInScope;
+ typeParametersInScope = node.typeParameters.toSet();
+ var savedParent = currentParent;
+ currentParent = node;
+ // Visit children without checking the parent pointer on the typedef itself
+ // since this can be called from a context other than its true parent.
+ node.visitChildren(this);
+ currentParent = savedParent;
+ typeParametersInScope = savedTypeParameters;
+ typedefState[node] = TypedefState.Done;
+ }
+
+ visitTypedef(Typedef node) {
+ checkTypedef(node);
+ // Enter and exit the node to check the parent pointer on the typedef node.
+ exitParent(enterParent(node));
+ }
+
visitField(Field node) {
currentMember = node;
var oldParent = enterParent(node);
@@ -184,6 +221,7 @@ class VerifyingVisitor extends RecursiveVisitor {
classTypeParametersAreInScope = false;
visitList(node.annotations, this);
exitParent(oldParent);
+ node.type.accept(this);
currentMember = null;
}
@@ -492,9 +530,17 @@ class VerifyingVisitor extends RecursiveVisitor {
}
@override
+ visitTypedefReference(Typedef node) {
+ if (!typedefs.contains(node)) {
+ problem(
+ node, "Dangling reference to '$node', parent is: '${node.parent}'");
+ }
+ }
+
+ @override
visitTypeParameterType(TypeParameterType node) {
var parameter = node.parameter;
- if (!typeParameters.contains(parameter)) {
+ if (!typeParametersInScope.contains(parameter)) {
problem(
currentParent,
"Type parameter '$parameter' referenced out of"
@@ -519,6 +565,19 @@ class VerifyingVisitor extends RecursiveVisitor {
" ${node.classNode.typeParameters.length} parameters.");
}
}
+
+ @override
+ visitTypedefType(TypedefType node) {
+ checkTypedef(node.typedefNode);
+ node.visitChildren(this);
+ if (node.typeArguments.length != node.typedefNode.typeParameters.length) {
+ problem(
+ currentParent,
+ "The typedef type $node provides ${node.typeArguments.length}"
+ " type arguments but the typedef declares"
+ " ${node.typedefNode.typeParameters.length} parameters.");
+ }
+ }
}
class CheckParentPointers extends Visitor {
« no previous file with comments | « pkg/kernel/lib/type_environment.dart ('k') | pkg/kernel/lib/visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698