Chromium Code Reviews| OLD | NEW |
|---|---|
| 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); |
| 11 } | 11 } |
| 12 | 12 |
| 13 /// Checks that a kernel program is well-formed. | 13 /// Checks that a kernel program is well-formed. |
| 14 /// | 14 /// |
| 15 /// This does not include any kind of type checking. | 15 /// This does not include any kind of type checking. |
| 16 class VerifyingVisitor extends RecursiveVisitor { | 16 class VerifyingVisitor extends RecursiveVisitor { |
| 17 final Set<Class> classes = new Set<Class>(); | 17 final Set<Class> classes = new Set<Class>(); |
| 18 final Set<TypeParameter> typeParameters = new Set<TypeParameter>(); | 18 final Set<TypeParameter> typeParameters = new Set<TypeParameter>(); |
| 19 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; | 19 final List<VariableDeclaration> variableStack = <VariableDeclaration>[]; |
| 20 bool classTypeParametersAreInScope = false; | 20 bool classTypeParametersAreInScope = false; |
| 21 bool isOutline = false; | |
|
asgerf
2017/01/06 15:56:26
Please add a short comment.
ahe
2017/01/11 11:39:28
Done.
| |
| 21 | 22 |
| 22 Member currentMember; | 23 Member currentMember; |
| 23 Class currentClass; | 24 Class currentClass; |
| 24 TreeNode currentParent; | 25 TreeNode currentParent; |
| 25 | 26 |
| 26 TreeNode get context => currentMember ?? currentClass; | 27 TreeNode get context => currentMember ?? currentClass; |
| 27 | 28 |
| 28 static void check(Program program) { | 29 static void check(Program program) { |
| 29 program.accept(new VerifyingVisitor()); | 30 program.accept(new VerifyingVisitor()); |
| 30 } | 31 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 } | 107 } |
| 107 | 108 |
| 108 void checkVariableInScope(VariableDeclaration variable, TreeNode where) { | 109 void checkVariableInScope(VariableDeclaration variable, TreeNode where) { |
| 109 if (variable.flags & VariableDeclaration.FlagInScope == 0) { | 110 if (variable.flags & VariableDeclaration.FlagInScope == 0) { |
| 110 throw 'Variable $variable used out of scope in $context ' | 111 throw 'Variable $variable used out of scope in $context ' |
| 111 '(${where.location})'; | 112 '(${where.location})'; |
| 112 } | 113 } |
| 113 } | 114 } |
| 114 | 115 |
| 115 visitProgram(Program program) { | 116 visitProgram(Program program) { |
| 116 for (var library in program.libraries) { | 117 try { |
| 117 for (var class_ in library.classes) { | 118 for (var library in program.libraries) { |
| 118 if (!classes.add(class_)) { | 119 for (var class_ in library.classes) { |
| 119 throw 'Class $class_ declared more than once'; | 120 if (!classes.add(class_)) { |
| 121 throw 'Class $class_ declared more than once.'; | |
| 122 } | |
| 123 } | |
| 124 library.members.forEach(declareMember); | |
| 125 for (var class_ in library.classes) { | |
| 126 class_.members.forEach(declareMember); | |
| 120 } | 127 } |
| 121 } | 128 } |
| 122 library.members.forEach(declareMember); | 129 visitChildren(program); |
| 123 for (var class_ in library.classes) { | 130 } finally { |
| 124 class_.members.forEach(declareMember); | 131 for (var library in program.libraries) { |
| 132 library.members.forEach(undeclareMember); | |
| 133 for (var class_ in library.classes) { | |
| 134 class_.members.forEach(undeclareMember); | |
| 135 } | |
| 125 } | 136 } |
| 126 } | 137 variableStack.forEach(undeclareVariable); |
| 127 visitChildren(program); | |
| 128 for (var library in program.libraries) { | |
| 129 library.members.forEach(undeclareMember); | |
| 130 for (var class_ in library.classes) { | |
| 131 class_.members.forEach(undeclareMember); | |
| 132 } | |
| 133 } | 138 } |
| 134 } | 139 } |
| 135 | 140 |
| 136 visitField(Field node) { | 141 visitField(Field node) { |
| 137 currentMember = node; | 142 currentMember = node; |
| 138 var oldParent = enterParent(node); | 143 var oldParent = enterParent(node); |
| 139 classTypeParametersAreInScope = !node.isStatic; | 144 classTypeParametersAreInScope = !node.isStatic; |
| 140 node.initializer?.accept(this); | 145 node.initializer?.accept(this); |
| 141 classTypeParametersAreInScope = false; | 146 classTypeParametersAreInScope = false; |
| 142 visitList(node.annotations, this); | 147 visitList(node.annotations, this); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 157 | 162 |
| 158 visitConstructor(Constructor node) { | 163 visitConstructor(Constructor node) { |
| 159 currentMember = node; | 164 currentMember = node; |
| 160 classTypeParametersAreInScope = true; | 165 classTypeParametersAreInScope = true; |
| 161 // The constructor member needs special treatment due to parameters being | 166 // The constructor member needs special treatment due to parameters being |
| 162 // in scope in the initializer list. | 167 // in scope in the initializer list. |
| 163 var oldParent = enterParent(node); | 168 var oldParent = enterParent(node); |
| 164 int stackHeight = enterLocalScope(); | 169 int stackHeight = enterLocalScope(); |
| 165 visitChildren(node.function); | 170 visitChildren(node.function); |
| 166 visitList(node.initializers, this); | 171 visitList(node.initializers, this); |
| 172 if (!isOutline) { | |
| 173 checkInitializers(node); | |
| 174 } | |
| 167 exitLocalScope(stackHeight); | 175 exitLocalScope(stackHeight); |
| 168 classTypeParametersAreInScope = false; | 176 classTypeParametersAreInScope = false; |
| 169 visitList(node.annotations, this); | 177 visitList(node.annotations, this); |
| 170 exitParent(oldParent); | 178 exitParent(oldParent); |
| 171 classTypeParametersAreInScope = false; | 179 classTypeParametersAreInScope = false; |
| 172 currentMember = null; | 180 currentMember = null; |
| 173 } | 181 } |
| 174 | 182 |
| 175 visitClass(Class node) { | 183 visitClass(Class node) { |
| 176 currentClass = node; | 184 currentClass = node; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 441 throw 'Parent pointer on ${node.runtimeType} ' | 449 throw 'Parent pointer on ${node.runtimeType} ' |
| 442 'is ${node.parent.runtimeType} ' | 450 'is ${node.parent.runtimeType} ' |
| 443 'but should be ${parent.runtimeType}'; | 451 'but should be ${parent.runtimeType}'; |
| 444 } | 452 } |
| 445 var oldParent = parent; | 453 var oldParent = parent; |
| 446 parent = node; | 454 parent = node; |
| 447 node.visitChildren(this); | 455 node.visitChildren(this); |
| 448 parent = oldParent; | 456 parent = oldParent; |
| 449 } | 457 } |
| 450 } | 458 } |
| 459 | |
| 460 void checkInitializers(Constructor constructor) { | |
| 461 // TODO(ahe): I'll add more here in other CLs. | |
| 462 } | |
| OLD | NEW |