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

Side by Side 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, 7 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 library kernel.checks; 4 library kernel.checks;
5 5
6 import 'ast.dart'; 6 import 'ast.dart';
7 import 'transformations/flags.dart'; 7 import 'transformations/flags.dart';
8 8
9 void verifyProgram(Program program) { 9 void verifyProgram(Program program) {
10 VerifyingVisitor.check(program); 10 VerifyingVisitor.check(program);
(...skipping 20 matching lines...) Expand all
31 return "$file:${location.line}:${location.column}: Verification error:" 31 return "$file:${location.line}:${location.column}: Verification error:"
32 " $details"; 32 " $details";
33 } else { 33 } else {
34 return "Verification error: $details\n" 34 return "Verification error: $details\n"
35 "Context: '$context'.\n" 35 "Context: '$context'.\n"
36 "Node: '$node'."; 36 "Node: '$node'.";
37 } 37 }
38 } 38 }
39 } 39 }
40 40
41 enum TypedefState { Done, BeingChecked }
42
41 /// Checks that a kernel program is well-formed. 43 /// Checks that a kernel program is well-formed.
42 /// 44 ///
43 /// This does not include any kind of type checking. 45 /// This does not include any kind of type checking.
44 class VerifyingVisitor extends RecursiveVisitor { 46 class VerifyingVisitor extends RecursiveVisitor {
45 final Set<Class> classes = new Set<Class>(); 47 final Set<Class> classes = new Set<Class>();
46 final Set<TypeParameter> typeParameters = new Set<TypeParameter>(); 48 final Set<Typedef> typedefs = new Set<Typedef>();
49 Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
47 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; 50 final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
51 final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
48 bool classTypeParametersAreInScope = false; 52 bool classTypeParametersAreInScope = false;
49 53
50 /// If true, relax certain checks for *outline* mode. For example, don't 54 /// If true, relax certain checks for *outline* mode. For example, don't
51 /// attempt to validate constructor initializers. 55 /// attempt to validate constructor initializers.
52 bool isOutline = false; 56 bool isOutline = false;
53 57
54 bool inCatchBlock = false; 58 bool inCatchBlock = false;
55 59
56 Member currentMember; 60 Member currentMember;
57 Class currentClass; 61 Class currentClass;
58 TreeNode currentParent; 62 TreeNode currentParent;
59 63
60 TreeNode get context => currentMember ?? currentClass; 64 TreeNode get context => currentMember ?? currentClass;
61 65
62 static void check(Program program) { 66 static void check(Program program) {
63 program.accept(new VerifyingVisitor()); 67 program.accept(new VerifyingVisitor());
64 } 68 }
65 69
66 defaultTreeNode(TreeNode node) { 70 defaultTreeNode(TreeNode node) {
67 visitChildren(node); 71 visitChildren(node);
68 } 72 }
69 73
70 problem(TreeNode node, String details) { 74 problem(TreeNode node, String details, {TreeNode context}) {
75 context ??= this.context;
71 throw new VerificationError(context, node, details); 76 throw new VerificationError(context, node, details);
72 } 77 }
73 78
74 TreeNode enterParent(TreeNode node) { 79 TreeNode enterParent(TreeNode node) {
75 if (!identical(node.parent, currentParent)) { 80 if (!identical(node.parent, currentParent)) {
76 problem( 81 problem(
77 node, 82 node,
78 "Incorrect parent pointer: expected '${node.parent.runtimeType}'," 83 "Incorrect parent pointer on ${node.runtimeType}:"
84 " expected '${node.parent.runtimeType}',"
79 " but found: '${currentParent.runtimeType}'."); 85 " but found: '${currentParent.runtimeType}'.");
80 } 86 }
81 var oldParent = currentParent; 87 var oldParent = currentParent;
82 currentParent = node; 88 currentParent = node;
83 return oldParent; 89 return oldParent;
84 } 90 }
85 91
86 void exitParent(TreeNode oldParent) { 92 void exitParent(TreeNode oldParent) {
87 currentParent = oldParent; 93 currentParent = oldParent;
88 } 94 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 variableStack.add(variable); 134 variableStack.add(variable);
129 } 135 }
130 136
131 void undeclareVariable(VariableDeclaration variable) { 137 void undeclareVariable(VariableDeclaration variable) {
132 variable.flags &= ~VariableDeclaration.FlagInScope; 138 variable.flags &= ~VariableDeclaration.FlagInScope;
133 } 139 }
134 140
135 void declareTypeParameters(List<TypeParameter> parameters) { 141 void declareTypeParameters(List<TypeParameter> parameters) {
136 for (int i = 0; i < parameters.length; ++i) { 142 for (int i = 0; i < parameters.length; ++i) {
137 var parameter = parameters[i]; 143 var parameter = parameters[i];
138 if (!typeParameters.add(parameter)) { 144 if (!typeParametersInScope.add(parameter)) {
139 problem(parameter, "Type parameter '$parameter' redeclared."); 145 problem(parameter, "Type parameter '$parameter' redeclared.");
140 } 146 }
141 } 147 }
142 } 148 }
143 149
144 void undeclareTypeParameters(List<TypeParameter> parameters) { 150 void undeclareTypeParameters(List<TypeParameter> parameters) {
145 typeParameters.removeAll(parameters); 151 typeParametersInScope.removeAll(parameters);
146 } 152 }
147 153
148 void checkVariableInScope(VariableDeclaration variable, TreeNode where) { 154 void checkVariableInScope(VariableDeclaration variable, TreeNode where) {
149 if (variable.flags & VariableDeclaration.FlagInScope == 0) { 155 if (variable.flags & VariableDeclaration.FlagInScope == 0) {
150 problem(where, "Variable '$variable' used out of scope."); 156 problem(where, "Variable '$variable' used out of scope.");
151 } 157 }
152 } 158 }
153 159
154 visitProgram(Program program) { 160 visitProgram(Program program) {
155 try { 161 try {
156 for (var library in program.libraries) { 162 for (var library in program.libraries) {
157 for (var class_ in library.classes) { 163 for (var class_ in library.classes) {
158 if (!classes.add(class_)) { 164 if (!classes.add(class_)) {
159 problem(class_, "Class '$class_' declared more than once."); 165 problem(class_, "Class '$class_' declared more than once.");
160 } 166 }
161 } 167 }
168 for (var typedef_ in library.typedefs) {
169 if (!typedefs.add(typedef_)) {
170 problem(typedef_, "Typedef '$typedef_' declared more than once.");
171 }
172 }
162 library.members.forEach(declareMember); 173 library.members.forEach(declareMember);
163 for (var class_ in library.classes) { 174 for (var class_ in library.classes) {
164 class_.members.forEach(declareMember); 175 class_.members.forEach(declareMember);
165 } 176 }
166 } 177 }
167 visitChildren(program); 178 visitChildren(program);
168 } finally { 179 } finally {
169 for (var library in program.libraries) { 180 for (var library in program.libraries) {
170 library.members.forEach(undeclareMember); 181 library.members.forEach(undeclareMember);
171 for (var class_ in library.classes) { 182 for (var class_ in library.classes) {
172 class_.members.forEach(undeclareMember); 183 class_.members.forEach(undeclareMember);
173 } 184 }
174 } 185 }
175 variableStack.forEach(undeclareVariable); 186 variableStack.forEach(undeclareVariable);
176 } 187 }
177 } 188 }
178 189
190 void checkTypedef(Typedef node) {
191 var state = typedefState[node];
192 if (state == TypedefState.Done) return;
193 if (state == TypedefState.BeingChecked) {
194 problem(node, "The typedef '$node' refers to itself", context: node);
195 }
196 assert(state == null);
197 typedefState[node] = TypedefState.BeingChecked;
198 var savedTypeParameters = typeParametersInScope;
199 typeParametersInScope = node.typeParameters.toSet();
200 var savedParent = currentParent;
201 currentParent = node;
202 // Visit children without checking the parent pointer on the typedef itself
203 // since this can be called from a context other than its true parent.
204 node.visitChildren(this);
205 currentParent = savedParent;
206 typeParametersInScope = savedTypeParameters;
207 typedefState[node] = TypedefState.Done;
208 }
209
210 visitTypedef(Typedef node) {
211 checkTypedef(node);
212 // Enter and exit the node to check the parent pointer on the typedef node.
213 exitParent(enterParent(node));
214 }
215
179 visitField(Field node) { 216 visitField(Field node) {
180 currentMember = node; 217 currentMember = node;
181 var oldParent = enterParent(node); 218 var oldParent = enterParent(node);
182 classTypeParametersAreInScope = !node.isStatic; 219 classTypeParametersAreInScope = !node.isStatic;
183 node.initializer?.accept(this); 220 node.initializer?.accept(this);
184 classTypeParametersAreInScope = false; 221 classTypeParametersAreInScope = false;
185 visitList(node.annotations, this); 222 visitList(node.annotations, this);
186 exitParent(oldParent); 223 exitParent(oldParent);
224 node.type.accept(this);
187 currentMember = null; 225 currentMember = null;
188 } 226 }
189 227
190 visitProcedure(Procedure node) { 228 visitProcedure(Procedure node) {
191 currentMember = node; 229 currentMember = node;
192 var oldParent = enterParent(node); 230 var oldParent = enterParent(node);
193 classTypeParametersAreInScope = !node.isStatic; 231 classTypeParametersAreInScope = !node.isStatic;
194 node.function.accept(this); 232 node.function.accept(this);
195 classTypeParametersAreInScope = false; 233 classTypeParametersAreInScope = false;
196 visitList(node.annotations, this); 234 visitList(node.annotations, this);
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 523
486 @override 524 @override
487 visitClassReference(Class node) { 525 visitClassReference(Class node) {
488 if (!classes.contains(node)) { 526 if (!classes.contains(node)) {
489 problem( 527 problem(
490 node, "Dangling reference to '$node', parent is: '${node.parent}'."); 528 node, "Dangling reference to '$node', parent is: '${node.parent}'.");
491 } 529 }
492 } 530 }
493 531
494 @override 532 @override
533 visitTypedefReference(Typedef node) {
534 if (!typedefs.contains(node)) {
535 problem(
536 node, "Dangling reference to '$node', parent is: '${node.parent}'");
537 }
538 }
539
540 @override
495 visitTypeParameterType(TypeParameterType node) { 541 visitTypeParameterType(TypeParameterType node) {
496 var parameter = node.parameter; 542 var parameter = node.parameter;
497 if (!typeParameters.contains(parameter)) { 543 if (!typeParametersInScope.contains(parameter)) {
498 problem( 544 problem(
499 currentParent, 545 currentParent,
500 "Type parameter '$parameter' referenced out of" 546 "Type parameter '$parameter' referenced out of"
501 " scope, parent is: '${parameter.parent}'."); 547 " scope, parent is: '${parameter.parent}'.");
502 } 548 }
503 if (parameter.parent is Class && !classTypeParametersAreInScope) { 549 if (parameter.parent is Class && !classTypeParametersAreInScope) {
504 problem( 550 problem(
505 currentParent, 551 currentParent,
506 "Type parameter '$parameter' referenced from" 552 "Type parameter '$parameter' referenced from"
507 " static context, parent is '${parameter.parent}'."); 553 " static context, parent is '${parameter.parent}'.");
508 } 554 }
509 } 555 }
510 556
511 @override 557 @override
512 visitInterfaceType(InterfaceType node) { 558 visitInterfaceType(InterfaceType node) {
513 node.visitChildren(this); 559 node.visitChildren(this);
514 if (node.typeArguments.length != node.classNode.typeParameters.length) { 560 if (node.typeArguments.length != node.classNode.typeParameters.length) {
515 problem( 561 problem(
516 currentParent, 562 currentParent,
517 "Type $node provides ${node.typeArguments.length}" 563 "Type $node provides ${node.typeArguments.length}"
518 " type arguments but the class declares" 564 " type arguments but the class declares"
519 " ${node.classNode.typeParameters.length} parameters."); 565 " ${node.classNode.typeParameters.length} parameters.");
520 } 566 }
521 } 567 }
568
569 @override
570 visitTypedefType(TypedefType node) {
571 checkTypedef(node.typedefNode);
572 node.visitChildren(this);
573 if (node.typeArguments.length != node.typedefNode.typeParameters.length) {
574 problem(
575 currentParent,
576 "The typedef type $node provides ${node.typeArguments.length}"
577 " type arguments but the typedef declares"
578 " ${node.typedefNode.typeParameters.length} parameters.");
579 }
580 }
522 } 581 }
523 582
524 class CheckParentPointers extends Visitor { 583 class CheckParentPointers extends Visitor {
525 static void check(TreeNode node) { 584 static void check(TreeNode node) {
526 node.accept(new CheckParentPointers(node.parent)); 585 node.accept(new CheckParentPointers(node.parent));
527 } 586 }
528 587
529 TreeNode parent; 588 TreeNode parent;
530 589
531 CheckParentPointers([this.parent]); 590 CheckParentPointers([this.parent]);
(...skipping 10 matching lines...) Expand all
542 var oldParent = parent; 601 var oldParent = parent;
543 parent = node; 602 parent = node;
544 node.visitChildren(this); 603 node.visitChildren(this);
545 parent = oldParent; 604 parent = oldParent;
546 } 605 }
547 } 606 }
548 607
549 void checkInitializers(Constructor constructor) { 608 void checkInitializers(Constructor constructor) {
550 // TODO(ahe): I'll add more here in other CLs. 609 // TODO(ahe): I'll add more here in other CLs.
551 } 610 }
OLDNEW
« 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