microsoft/qdk
Publicmirrored fromhttps://github.com/microsoft/qdkAvailable
compiler/qsc_ast/src/validate.rs
114lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | use crate::{ |
| 5 | ast::{ |
| 6 | Attr, Block, CallableDecl, Expr, FunctorExpr, Ident, Item, Namespace, NodeId, Package, Pat, |
| 7 | Path, QubitInit, SpecDecl, Stmt, Ty, TyDef, Visibility, |
| 8 | }, |
| 9 | visit::{self, Visitor}, |
| 10 | }; |
| 11 | use qsc_data_structures::index_map::IndexMap; |
| 12 | use std::fmt::Display; |
| 13 | |
| 14 | #[derive(Default)] |
| 15 | pub struct Validator { |
| 16 | ids: IndexMap<NodeId, ()>, |
| 17 | } |
| 18 | |
| 19 | impl Validator { |
| 20 | fn check(&mut self, id: NodeId, node: impl Display) { |
| 21 | if id.is_default() { |
| 22 | panic!("default node ID should be replaced: {node}") |
| 23 | } else if self.ids.contains_key(id) { |
| 24 | panic!("duplicate node ID: {node}"); |
| 25 | } else { |
| 26 | self.ids.insert(id, ()); |
| 27 | } |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | impl Visitor<'_> for Validator { |
| 32 | fn visit_package(&mut self, package: &Package) { |
| 33 | self.check(package.id, package); |
| 34 | visit::walk_package(self, package); |
| 35 | } |
| 36 | |
| 37 | fn visit_namespace(&mut self, namespace: &Namespace) { |
| 38 | self.check(namespace.id, namespace); |
| 39 | visit::walk_namespace(self, namespace); |
| 40 | } |
| 41 | |
| 42 | fn visit_item(&mut self, item: &Item) { |
| 43 | self.check(item.id, item); |
| 44 | visit::walk_item(self, item); |
| 45 | } |
| 46 | |
| 47 | fn visit_attr(&mut self, attr: &Attr) { |
| 48 | self.check(attr.id, attr); |
| 49 | visit::walk_attr(self, attr); |
| 50 | } |
| 51 | |
| 52 | fn visit_visibility(&mut self, visibility: &Visibility) { |
| 53 | self.check(visibility.id, visibility); |
| 54 | } |
| 55 | |
| 56 | fn visit_ty_def(&mut self, def: &TyDef) { |
| 57 | self.check(def.id, def); |
| 58 | visit::walk_ty_def(self, def); |
| 59 | } |
| 60 | |
| 61 | fn visit_callable_decl(&mut self, decl: &CallableDecl) { |
| 62 | self.check(decl.id, decl); |
| 63 | visit::walk_callable_decl(self, decl); |
| 64 | } |
| 65 | |
| 66 | fn visit_spec_decl(&mut self, decl: &SpecDecl) { |
| 67 | self.check(decl.id, decl); |
| 68 | visit::walk_spec_decl(self, decl); |
| 69 | } |
| 70 | |
| 71 | fn visit_functor_expr(&mut self, expr: &FunctorExpr) { |
| 72 | self.check(expr.id, expr); |
| 73 | visit::walk_functor_expr(self, expr); |
| 74 | } |
| 75 | |
| 76 | fn visit_ty(&mut self, ty: &Ty) { |
| 77 | self.check(ty.id, ty); |
| 78 | visit::walk_ty(self, ty); |
| 79 | } |
| 80 | |
| 81 | fn visit_block(&mut self, block: &Block) { |
| 82 | self.check(block.id, block); |
| 83 | visit::walk_block(self, block); |
| 84 | } |
| 85 | |
| 86 | fn visit_stmt(&mut self, stmt: &Stmt) { |
| 87 | self.check(stmt.id, stmt); |
| 88 | visit::walk_stmt(self, stmt); |
| 89 | } |
| 90 | |
| 91 | fn visit_expr(&mut self, expr: &Expr) { |
| 92 | self.check(expr.id, expr); |
| 93 | visit::walk_expr(self, expr); |
| 94 | } |
| 95 | |
| 96 | fn visit_pat(&mut self, pat: &Pat) { |
| 97 | self.check(pat.id, pat); |
| 98 | visit::walk_pat(self, pat); |
| 99 | } |
| 100 | |
| 101 | fn visit_qubit_init(&mut self, init: &QubitInit) { |
| 102 | self.check(init.id, init); |
| 103 | visit::walk_qubit_init(self, init); |
| 104 | } |
| 105 | |
| 106 | fn visit_path(&mut self, path: &Path) { |
| 107 | self.check(path.id, path); |
| 108 | visit::walk_path(self, path); |
| 109 | } |
| 110 | |
| 111 | fn visit_ident(&mut self, ident: &Ident) { |
| 112 | self.check(ident.id, ident); |
| 113 | } |
| 114 | } |
| 115 | |