1use std::collections::{HashMap, HashSet};
2
3#[derive(Debug, Clone, Default)]
6pub struct SymbolTable {
7 globals: HashSet<String>,
9 global_fields: HashMap<String, HashSet<String>>,
11 class_fields: HashMap<String, HashSet<String>>,
13}
14
15impl SymbolTable {
16 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn add_global(&mut self, name: &str) {
22 self.globals.insert(name.to_string());
23 }
24
25 pub fn add_global_field(&mut self, table: &str, field: &str) {
27 self.global_fields
28 .entry(table.to_string())
29 .or_default()
30 .insert(field.to_string());
31 }
32
33 pub fn has_global(&self, name: &str) -> bool {
35 self.globals.contains(name)
36 }
37
38 pub fn has_global_field(&self, table: &str, field: &str) -> bool {
40 self.global_fields
41 .get(table)
42 .is_some_and(|fields| fields.contains(field))
43 }
44
45 pub fn global_fields_for(&self, table: &str) -> Option<&HashSet<String>> {
48 self.global_fields.get(table)
49 }
50
51 pub fn add_class(&mut self, class_name: &str) {
53 self.class_fields.entry(class_name.to_string()).or_default();
54 }
55
56 pub fn add_class_field(&mut self, class_name: &str, field: &str) {
58 self.class_fields
59 .entry(class_name.to_string())
60 .or_default()
61 .insert(field.to_string());
62 }
63
64 pub fn has_class(&self, class_name: &str) -> bool {
66 self.class_fields.contains_key(class_name)
67 }
68
69 pub fn has_class_field(&self, class_name: &str, field: &str) -> bool {
71 self.class_fields
72 .get(class_name)
73 .is_some_and(|fields| fields.contains(field))
74 }
75
76 pub fn class_fields_for(&self, class_name: &str) -> Option<&HashSet<String>> {
78 self.class_fields.get(class_name)
79 }
80
81 pub fn with_lua54_stdlib(mut self) -> Self {
83 let stdlib_globals = [
84 "assert",
85 "collectgarbage",
86 "dofile",
87 "error",
88 "getmetatable",
89 "ipairs",
90 "load",
91 "loadfile",
92 "next",
93 "pairs",
94 "pcall",
95 "print",
96 "rawequal",
97 "rawget",
98 "rawlen",
99 "rawset",
100 "require",
101 "select",
102 "setmetatable",
103 "tonumber",
104 "tostring",
105 "type",
106 "warn",
107 "xpcall",
108 "coroutine",
110 "debug",
111 "io",
112 "math",
113 "os",
114 "package",
115 "string",
116 "table",
117 "utf8",
118 "_G",
120 "_VERSION",
121 ];
122 for name in &stdlib_globals {
123 self.globals.insert((*name).to_string());
124 }
125 self
126 }
127}