1use internment::Intern;
2
3use crate::builtin::*;
5use crate::compiler::BUILTIN_STORAGE;
6use crate::compiler::NULL_STORAGE;
7use crate::compiler_info::CodeArea;
8use crate::context::BreakType;
9use crate::context::FullContext;
10use crate::levelstring::GdObj;
11
12use crate::compiler_types::*;
13use crate::value::*;
14
15use crate::compiler_info::CompilerInfo;
17use crate::value_storage::*;
18use std::collections::HashMap;
19
20use std::path::PathBuf;
21
22use crate::compiler::RuntimeError;
23
24#[allow(non_snake_case)]
25pub struct Globals {
26 pub closed_groups: u16,
28 pub closed_colors: u16,
29 pub closed_blocks: u16,
30 pub closed_items: u16,
31
32 pub path: Intern<PathBuf>,
33
34 pub lowest_y: HashMap<u32, u16>,
35 pub stored_values: ValStorage,
36 pub val_id: StoredValue,
37
38 pub type_ids: HashMap<String, (u16, CodeArea)>,
39 pub type_id_count: u16,
40
41 pub func_ids: Vec<FunctionId>,
42 pub objects: Vec<GdObj>,
43
44 pub prev_imports: HashMap<ImportType, (StoredValue, Implementations)>,
45
46 pub trigger_order: usize,
47
48 pub uid_counter: usize,
49 pub implementations: Implementations,
50
51 pub sync_groups: Vec<SyncGroup>,
52 pub includes: Vec<PathBuf>,
53
54 pub TYPE_MEMBER_NAME: Intern<String>,
55 pub SELF_MEMBER_NAME: Intern<String>,
56 pub OR_BUILTIN: Intern<String>,
57 pub AND_BUILTIN: Intern<String>,
58 pub ASSIGN_BUILTIN: Intern<String>,
59 pub OBJ_KEY_ID: Intern<String>,
60 pub OBJ_KEY_PATTERN: Intern<String>,
61}
62
63impl Globals {
64 pub fn get_val_fn_context(
65 &self,
66 p: StoredValue,
67 info: CompilerInfo,
68 ) -> Result<Group, RuntimeError> {
69 match self.stored_values.map.get(&p) {
70 Some(val) => Ok(val.fn_context),
71 None => Err(RuntimeError::CustomError(crate::compiler::create_error(
72 info,
73 "Pointer points to no data! (this is probably a bug, please contact a developer)",
74 &[],
75 None,
76 ))),
77 }
78 }
79 pub fn is_mutable(&self, p: StoredValue) -> bool {
80 match self.stored_values.map.get(&p) {
81 Some(val) => val.mutable,
82 None => unreachable!("{}", p),
83 }
84 }
85
86 pub fn can_mutate(&self, p: StoredValue) -> bool {
87 self.is_mutable(p)
88 }
89
90 pub fn get_area(&self, p: StoredValue) -> CodeArea {
105 match self.stored_values.map.get(&p) {
106 Some(val) => val.def_area,
107 None => unreachable!(),
108 }
109 }
110
111 pub fn get_type_str(&self, p: StoredValue) -> String {
112 let val = &self.stored_values[p];
113 let typ = match val {
114 Value::Dict(d) => {
115 if let Some(s) = d.get(&self.TYPE_MEMBER_NAME) {
116 match self.stored_values[*s] {
117 Value::TypeIndicator(t) => t,
118 _ => unreachable!(),
119 }
120 } else {
121 val.to_num(self)
122 }
123 }
124 _ => val.to_num(self),
125 };
126 find_key_for_value(&self.type_ids, typ).unwrap().clone()
127 }
128
129 pub fn new(path: PathBuf) -> Self {
130 let storage = ValStorage::new();
131 let mut globals = Globals {
132 closed_groups: 0,
133 closed_colors: 0,
134 closed_blocks: 0,
135 closed_items: 0,
136 path: Intern::new(path),
137
138 lowest_y: HashMap::new(),
139
140 type_ids: HashMap::new(),
141
142 prev_imports: HashMap::new(),
143 type_id_count: 0,
144 trigger_order: 0,
145 uid_counter: 0,
146
147 val_id: storage.map.len() as StoredValue,
148 stored_values: storage,
149 func_ids: vec![FunctionId {
150 parent: None,
151 width: None,
152 obj_list: Vec::new(),
153 }],
154 objects: Vec::new(),
155 implementations: HashMap::new(),
156 sync_groups: vec![SyncGroup {
157 parts: vec![0],
158 groups_used: Vec::new(),
159 }],
160 includes: Vec::new(),
161 TYPE_MEMBER_NAME: Intern::new(String::from("type")),
162 SELF_MEMBER_NAME: Intern::new(String::from("self")),
163 OR_BUILTIN: Intern::new(String::from("_or_")),
164 AND_BUILTIN: Intern::new(String::from("_and_")),
165 ASSIGN_BUILTIN: Intern::new(String::from("_assign_")),
166 OBJ_KEY_ID: Intern::new(String::from("id")),
167 OBJ_KEY_PATTERN: Intern::new(String::from("pattern")),
168 };
169
170 let mut add_type = |name: &str, id: u16| {
171 globals
172 .type_ids
173 .insert(String::from(name), (id, CodeArea::new()))
174 };
175
176 add_type("group", 0);
177 add_type("color", 1);
178 add_type("block", 2);
179 add_type("item", 3);
180 add_type("number", 4);
181 add_type("bool", 5);
182 add_type("trigger_function", 6);
183 add_type("dictionary", 7);
184 add_type("macro", 8);
185 add_type("string", 9);
186 add_type("array", 10);
187 add_type("object", 11);
188 add_type("spwn", 12);
189 add_type("builtin", 13);
190 add_type("type_indicator", 14);
191 add_type("NULL", 15);
192 add_type("trigger", 16);
193 add_type("range", 17);
194 add_type("pattern", 18);
195 add_type("object_key", 19);
196 add_type("epsilon", 20);
197
198 globals.type_id_count = globals.type_ids.len() as u16;
199
200 globals
201 }
202
203 pub fn push_new_preserved(&mut self) {
243 self.stored_values.preserved_stack.push(Vec::new());
244 }
245
246 pub fn pop_preserved(&mut self) {
247 self.stored_values.preserved_stack.pop();
248 }
249
250 pub fn push_preserved_val(&mut self, val: StoredValue) {
251 self.stored_values
252 .preserved_stack
253 .last_mut()
254 .unwrap()
255 .push(val);
256 }
257
258 pub fn collect_garbage(&mut self, contexts: &mut FullContext) {
259 self.stored_values.mark(NULL_STORAGE);
263 self.stored_values.mark(BUILTIN_STORAGE);
264
265 unsafe {
266 let root_context = contexts
267 .with_breaks()
268 .next()
269 .unwrap()
270 .inner()
271 .root_context_ptr
272 .as_mut()
273 .unwrap();
274
275 for c in root_context.with_breaks() {
276 for stack in c.inner().get_variables().values() {
277 for (v, _) in stack.iter() {
278 self.stored_values.mark(*v);
279 }
280 }
281
282 match c.inner().broken {
283 Some((BreakType::Macro(Some(v), _), _)) | Some((BreakType::Switch(v), _)) => {
284 self.stored_values.mark(v);
285 }
286 _ => (),
287 }
288
289 self.stored_values.mark(c.inner().return_value);
291 self.stored_values.mark(c.inner().return_value2);
292 }
293 for s in self.stored_values.preserved_stack.clone() {
294 for v in s {
295 self.stored_values.mark(v);
296 }
297 }
298 for imp in self.implementations.values() {
299 for (v, _) in imp.values() {
300 self.stored_values.mark(*v);
301 }
302 }
303 }
304
305 for (v, imp) in self.prev_imports.values() {
306 for imp in imp.values() {
307 for (v, _) in imp.values() {
308 self.stored_values.mark(*v);
309 }
310 }
311
312 self.stored_values.mark(*v);
313 }
314 self.stored_values.sweep();
318
319 self.stored_values.prev_value_count = self.stored_values.map.len() as u32;
320 }
321}