1use std::collections::HashMap;
18use crate::{lang::SError, IntoNodeRef, SData, SDataRef, SDoc, SField, SFunc, SNodeRef, SType, SVal};
19
20
21#[derive(Clone, Debug)]
24pub struct StofEnv {
25 pub main: SNodeRef,
27
28 pub pid: String,
30
31 pub relative_import_path: String,
33
34 pub assign_type_stack: Vec<HashMap<String, SType>>,
36
37 pub init_funcs: Vec<(SDataRef, Vec<SVal>)>,
39
40 node_field_collisions: HashMap<String, HashMap<String, SDataRef>>,
44}
45impl StofEnv {
46 pub fn new(pid: &str, doc: &mut SDoc) -> Self {
48 let main;
49 if doc.graph.roots.len() < 1 {
50 main = doc.graph.insert_root("root");
51 } else {
52 main = doc.graph.main_root().unwrap();
53 }
54 Self {
55 main,
56 pid: pid.to_owned(),
57 assign_type_stack: vec![Default::default()],
58 init_funcs: Default::default(),
59 node_field_collisions: Default::default(),
60 relative_import_path: String::default(),
61 }
62 }
63
64 pub fn new_at_node(pid: &str, doc: &mut SDoc, node: impl IntoNodeRef) -> Option<Self> {
66 let nref = node.node_ref();
67 if nref.exists(&doc.graph) {
68 return Some(Self {
69 main: nref,
70 pid: pid.to_owned(),
71 init_funcs: Default::default(),
72 assign_type_stack: vec![Default::default()],
73 node_field_collisions: Default::default(),
74 relative_import_path: String::default(),
75 });
76 }
77 None
78 }
79
80 pub(crate) fn insert_field(&mut self, doc: &mut SDoc, node: impl IntoNodeRef, field: SField) -> Result<(), SError> {
83 let node_ref = node.node_ref();
84 if !self.node_field_collisions.contains_key(&node_ref.id) {
85 let mut map = HashMap::new();
86 for existing_ref in SField::field_refs(&doc.graph, &node_ref) {
87 if let Some(field) = SData::get::<SField>(&doc.graph, &existing_ref) {
88 map.insert(field.name.clone(), existing_ref);
89 }
90 }
91 self.node_field_collisions.insert(node_ref.id.clone(), map);
92 }
93 if let Some(existing) = self.node_field_collisions.get_mut(&node_ref.id) {
94 if existing.contains_key(&field.name) {
95 if let Some(existing_field) = SData::get_mut::<SField>(&mut doc.graph, existing.get(&field.name).unwrap()) {
98 existing_field.merge(&field)?;
99 }
100 } else {
101 let name = field.name.clone();
103 if let Some(dref) = SData::insert_new(&mut doc.graph, &node_ref, Box::new(field)) {
104 existing.insert(name, dref);
105 }
106 }
107 }
108 Ok(())
109 }
110
111 pub fn before_parse(&mut self, doc: &mut SDoc) {
113 doc.push_self(&self.pid, self.main.clone());
114 }
115
116 pub fn after_parse(&mut self, doc: &mut SDoc) {
118 self.call_init_functions(doc);
119 doc.clean(&self.pid);
120 }
121
122 pub fn compiled_path(&self, path: &str, doc: &SDoc) -> bool {
124 doc.env_compiled_paths.contains(path)
125 }
126
127 pub fn add_compiled_path(&mut self, path: &str, doc: &mut SDoc) {
129 doc.env_compiled_paths.insert(path.to_owned());
130 }
131
132 pub fn scope(&self, doc: &SDoc) -> SNodeRef {
134 if let Some(nref) = doc.self_ptr(&self.pid) {
135 nref
136 } else {
137 self.main.clone()
138 }
139 }
140
141 pub fn push_scope(&mut self, doc: &mut SDoc, path: &str, sep: char, fields: bool) -> SNodeRef {
144 let nref = doc.graph.ensure_nodes(path, sep, fields, None);
145 self.push_scope_ref(doc, nref.clone());
146 nref
147 }
148
149 pub fn push_scope_ref(&mut self, doc: &mut SDoc, nref: SNodeRef) {
151 doc.push_self(&self.pid, nref);
152 self.assign_type_stack.push(HashMap::default());
153 }
154
155 pub fn pop_scope(&mut self, doc: &mut SDoc) {
157 doc.pop_self(&self.pid);
158 self.assign_type_stack.pop();
159 }
160
161 pub fn call_init_functions(&self, doc: &mut SDoc) {
163 for (dref, params) in &self.init_funcs {
164 SFunc::call(dref, &self.pid, doc, params.clone(), true).expect(&format!("Failed to call init function: {:?}", SData::get::<SFunc>(&doc.graph, dref)));
165 }
166 }
167}