use internment::Intern;
use crate::builtin::*;
use crate::compiler::BUILTIN_STORAGE;
use crate::compiler::NULL_STORAGE;
use crate::compiler_info::CodeArea;
use crate::context::BreakType;
use crate::context::FullContext;
use crate::levelstring::GdObj;
use crate::compiler_types::*;
use crate::value::*;
use crate::compiler_info::CompilerInfo;
use crate::value_storage::*;
use std::collections::HashMap;
use std::path::PathBuf;
use crate::compiler::RuntimeError;
#[allow(non_snake_case)]
pub struct Globals {
pub closed_groups: u16,
pub closed_colors: u16,
pub closed_blocks: u16,
pub closed_items: u16,
pub path: Intern<PathBuf>,
pub lowest_y: HashMap<u32, u16>,
pub stored_values: ValStorage,
pub val_id: StoredValue,
pub type_ids: HashMap<String, (u16, CodeArea)>,
pub type_id_count: u16,
pub func_ids: Vec<FunctionId>,
pub objects: Vec<GdObj>,
pub prev_imports: HashMap<ImportType, (StoredValue, Implementations)>,
pub trigger_order: usize,
pub uid_counter: usize,
pub implementations: Implementations,
pub sync_groups: Vec<SyncGroup>,
pub includes: Vec<PathBuf>,
pub TYPE_MEMBER_NAME: Intern<String>,
pub SELF_MEMBER_NAME: Intern<String>,
pub OR_BUILTIN: Intern<String>,
pub AND_BUILTIN: Intern<String>,
pub ASSIGN_BUILTIN: Intern<String>,
pub OBJ_KEY_ID: Intern<String>,
pub OBJ_KEY_PATTERN: Intern<String>,
}
impl Globals {
pub fn get_val_fn_context(
&self,
p: StoredValue,
info: CompilerInfo,
) -> Result<Group, RuntimeError> {
match self.stored_values.map.get(&p) {
Some(val) => Ok(val.fn_context),
None => Err(RuntimeError::CustomError(crate::compiler::create_error(
info,
"Pointer points to no data! (this is probably a bug, please contact a developer)",
&[],
None,
))),
}
}
pub fn is_mutable(&self, p: StoredValue) -> bool {
match self.stored_values.map.get(&p) {
Some(val) => val.mutable,
None => unreachable!("{}", p),
}
}
pub fn can_mutate(&self, p: StoredValue) -> bool {
self.is_mutable(p)
}
pub fn get_area(&self, p: StoredValue) -> CodeArea {
match self.stored_values.map.get(&p) {
Some(val) => val.def_area,
None => unreachable!(),
}
}
pub fn get_type_str(&self, p: StoredValue) -> String {
let val = &self.stored_values[p];
let typ = match val {
Value::Dict(d) => {
if let Some(s) = d.get(&self.TYPE_MEMBER_NAME) {
match self.stored_values[*s] {
Value::TypeIndicator(t) => t,
_ => unreachable!(),
}
} else {
val.to_num(self)
}
}
_ => val.to_num(self),
};
find_key_for_value(&self.type_ids, typ).unwrap().clone()
}
pub fn new(path: PathBuf) -> Self {
let storage = ValStorage::new();
let mut globals = Globals {
closed_groups: 0,
closed_colors: 0,
closed_blocks: 0,
closed_items: 0,
path: Intern::new(path),
lowest_y: HashMap::new(),
type_ids: HashMap::new(),
prev_imports: HashMap::new(),
type_id_count: 0,
trigger_order: 0,
uid_counter: 0,
val_id: storage.map.len() as StoredValue,
stored_values: storage,
func_ids: vec![FunctionId {
parent: None,
width: None,
obj_list: Vec::new(),
}],
objects: Vec::new(),
implementations: HashMap::new(),
sync_groups: vec![SyncGroup {
parts: vec![0],
groups_used: Vec::new(),
}],
includes: Vec::new(),
TYPE_MEMBER_NAME: Intern::new(String::from("type")),
SELF_MEMBER_NAME: Intern::new(String::from("self")),
OR_BUILTIN: Intern::new(String::from("_or_")),
AND_BUILTIN: Intern::new(String::from("_and_")),
ASSIGN_BUILTIN: Intern::new(String::from("_assign_")),
OBJ_KEY_ID: Intern::new(String::from("id")),
OBJ_KEY_PATTERN: Intern::new(String::from("pattern")),
};
let mut add_type = |name: &str, id: u16| {
globals
.type_ids
.insert(String::from(name), (id, CodeArea::new()))
};
add_type("group", 0);
add_type("color", 1);
add_type("block", 2);
add_type("item", 3);
add_type("number", 4);
add_type("bool", 5);
add_type("trigger_function", 6);
add_type("dictionary", 7);
add_type("macro", 8);
add_type("string", 9);
add_type("array", 10);
add_type("object", 11);
add_type("spwn", 12);
add_type("builtin", 13);
add_type("type_indicator", 14);
add_type("NULL", 15);
add_type("trigger", 16);
add_type("range", 17);
add_type("pattern", 18);
add_type("object_key", 19);
add_type("epsilon", 20);
globals.type_id_count = globals.type_ids.len() as u16;
globals
}
pub fn push_new_preserved(&mut self) {
self.stored_values.preserved_stack.push(Vec::new());
}
pub fn pop_preserved(&mut self) {
self.stored_values.preserved_stack.pop();
}
pub fn push_preserved_val(&mut self, val: StoredValue) {
self.stored_values
.preserved_stack
.last_mut()
.unwrap()
.push(val);
}
pub fn collect_garbage(&mut self, contexts: &mut FullContext) {
self.stored_values.mark(NULL_STORAGE);
self.stored_values.mark(BUILTIN_STORAGE);
unsafe {
let root_context = contexts
.with_breaks()
.next()
.unwrap()
.inner()
.root_context_ptr
.as_mut()
.unwrap();
for c in root_context.with_breaks() {
for stack in c.inner().get_variables().values() {
for (v, _) in stack.iter() {
self.stored_values.mark(*v);
}
}
match c.inner().broken {
Some((BreakType::Macro(Some(v), _), _)) | Some((BreakType::Switch(v), _)) => {
self.stored_values.mark(v);
}
_ => (),
}
self.stored_values.mark(c.inner().return_value);
self.stored_values.mark(c.inner().return_value2);
}
for s in self.stored_values.preserved_stack.clone() {
for v in s {
self.stored_values.mark(v);
}
}
for imp in self.implementations.values() {
for (v, _) in imp.values() {
self.stored_values.mark(*v);
}
}
}
for (v, imp) in self.prev_imports.values() {
for imp in imp.values() {
for (v, _) in imp.values() {
self.stored_values.mark(*v);
}
}
self.stored_values.mark(*v);
}
self.stored_values.sweep();
self.stored_values.prev_value_count = self.stored_values.map.len() as u32;
}
}