/ compiler / passes / src / name_validation / program.rs
program.rs
 1  // Copyright (C) 2019-2025 ADnet Contributors
 2  // This file is part of the ADL library.
 3  
 4  // The ADL library is free software: you can redistribute it and/or modify
 5  // it under the terms of the GNU General Public License as published by
 6  // the Free Software Foundation, either version 3 of the License, or
 7  // (at your option) any later version.
 8  
 9  // The ADL library is distributed in the hope that it will be useful,
10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  // GNU General Public License for more details.
13  
14  // You should have received a copy of the GNU General Public License
15  // along with the ADL library. If not, see <https://www.gnu.org/licenses/>.
16  
17  use super::NameValidationVisitor;
18  
19  use adl_ast::*;
20  
21  impl ProgramVisitor for NameValidationVisitor<'_> {
22      fn visit_program(&mut self, input: &Program) {
23          input.stubs.iter().for_each(|(_symbol, stub)| self.visit_stub(stub));
24          input.modules.values().for_each(|module| self.visit_module(module));
25          input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
26      }
27  
28      fn visit_program_scope(&mut self, input: &ProgramScope) {
29          let program_name = input.program_id.name;
30          self.does_not_contain_reserved(program_name, "program");
31          self.is_not_keyword(program_name, "program", &[]);
32  
33          input.composites.iter().for_each(|(_, function)| self.visit_composite(function));
34          input.functions.iter().for_each(|(_, function)| self.visit_function(function));
35      }
36  
37      fn visit_module(&mut self, input: &Module) {
38          input.composites.iter().for_each(|(_, function)| self.visit_composite(function));
39          input.functions.iter().for_each(|(_, function)| self.visit_function(function));
40      }
41  
42      fn visit_stub(&mut self, input: &Stub) {
43          input.composites.iter().for_each(|(_, function)| self.visit_composite_stub(function));
44          input.functions.iter().for_each(|(_, function)| self.visit_function_stub(function));
45      }
46  
47      fn visit_composite(&mut self, input: &Composite) {
48          let composite_name = input.identifier;
49          let item_type = if input.is_record { "record" } else { "struct" };
50          self.is_not_keyword(composite_name, item_type, &[]);
51          if input.is_record {
52              self.does_not_contain_reserved(composite_name, item_type);
53          }
54  
55          for Member { identifier: member_name, .. } in &input.members {
56              if input.is_record {
57                  self.is_not_keyword(*member_name, "record member", &["owner"]);
58                  self.does_not_contain_reserved(*member_name, "record member");
59              } else {
60                  self.is_not_keyword(*member_name, "struct member", &[]);
61              }
62          }
63      }
64  
65      fn visit_function(&mut self, function: &Function) {
66          use Variant::*;
67          match function.variant {
68              Transition | AsyncTransition => self.is_not_keyword(function.identifier, "transition", &[]),
69              Function => self.is_not_keyword(function.identifier, "function", &[]),
70              Inline | AsyncFunction | Script => {}
71          }
72      }
73  
74      fn visit_function_stub(&mut self, input: &FunctionStub) {
75          use Variant::*;
76          match input.variant {
77              Transition | AsyncTransition => self.is_not_keyword(input.identifier, "transition", &[]),
78              Function => self.is_not_keyword(input.identifier, "function", &[]),
79              Inline | AsyncFunction | Script => {}
80          }
81      }
82  
83      fn visit_composite_stub(&mut self, input: &Composite) {
84          self.visit_composite(input);
85      }
86  }