go_types/check/
initorder.rs1#![allow(dead_code)]
13use crate::SourceRead;
14
15use super::super::objects::{DeclInfoKey, ObjKey, TCObjects};
16use super::check::{Checker, Initializer};
17use super::resolver::DeclInfo;
18use go_parser::Map;
19use std::cell::RefCell;
20use std::collections::HashSet;
21use std::rc::Rc;
22
23#[derive(Debug)]
24struct GraphEdges {
25 pred: Rc<RefCell<HashSet<ObjKey>>>,
26 succ: Rc<RefCell<HashSet<ObjKey>>>,
27}
28
29struct GraphNode {
30 obj: ObjKey,
31 ndeps: usize,
32 pos: usize,
33}
34
35impl GraphEdges {
36 fn new(succ: Rc<RefCell<HashSet<ObjKey>>>) -> GraphEdges {
37 GraphEdges {
38 pred: Rc::new(RefCell::new(HashSet::new())),
39 succ: succ,
40 }
41 }
42}
43
44impl<'a, S: SourceRead> Checker<'a, S> {
45 pub fn init_order(&mut self) {
46 let (mut nodes, edges) = self.dependency_graph();
47 nodes.sort_by(|a, b| a.ndeps.cmp(&b.ndeps)); let len = nodes.len();
49 let mut nodes = &mut nodes[0..len];
50 let mut order: Vec<ObjKey> = vec![];
51 let mut emitted: HashSet<DeclInfoKey> = HashSet::new();
52
53 loop {
54 if nodes.len() == 0 {
55 break;
56 }
57 let mut first_dependant = nodes
58 .iter()
59 .enumerate()
60 .find(|(_, n)| n.ndeps > 0)
61 .map_or(nodes.len(), |(i, _)| i);
62 if first_dependant == 0 {
63 let visited = &mut HashSet::new();
65 let obj = nodes[0].obj;
66 if let Some(cycle) = find_path(&self.obj_map, obj, obj, visited, self.tc_objs) {
75 self.report_cycle(&cycle);
76 }
77 first_dependant = 1;
82 }
83
84 let mut indep: Vec<ObjKey> = nodes[0..first_dependant].iter().map(|n| n.obj).collect();
85 indep.sort_by(|a, b| self.lobj(*a).order().cmp(&self.lobj(*b).order()));
86 order.append(&mut indep);
87
88 let to_sub: Map<ObjKey, usize> =
90 nodes[0..first_dependant]
91 .iter()
92 .fold(Map::new(), |mut init, x| {
93 for p in edges[&x.obj].pred.borrow().iter() {
94 *init.entry(*p).or_insert(0) += 1;
95 }
96 init
97 });
98 nodes = &mut nodes[first_dependant..];
100 for n in nodes.iter_mut() {
101 n.ndeps -= *to_sub.get(&n.obj).unwrap_or(&0);
102 }
103 nodes.sort_by(|a, b| a.ndeps.cmp(&b.ndeps));
105 }
106
107 let init_order = order
109 .into_iter()
110 .filter_map(|x| {
111 let decl_key = self.obj_map[&x];
112 match &self.tc_objs.decls[decl_key] {
113 DeclInfo::Var(var) => {
114 if var.init.is_none() {
115 return None;
116 }
117 if emitted.contains(&decl_key) {
122 return None;
123 }
124 emitted.insert(decl_key);
125 let lhs = var.lhs.clone().unwrap_or(vec![x]);
126 Some(Initializer {
127 lhs: lhs,
128 rhs: var.init.clone().unwrap(),
129 })
130 }
131 _ => None,
132 }
133 })
134 .collect();
135 self.result.record_init_order(init_order);
136 }
137
138 fn dependency_graph(&self) -> (Vec<GraphNode>, Map<ObjKey, GraphEdges>) {
142 let map: Map<ObjKey, GraphEdges> = self.obj_map.iter().fold(
144 Map::new(),
145 |mut init: Map<ObjKey, GraphEdges>, (&x, &decl_key)| {
146 if self.lobj(x).entity_type().is_dependency() {
147 let decl = &self.tc_objs.decls[decl_key];
148 let deps: HashSet<ObjKey> = decl.deps().iter().map(|z| *z).collect();
149 init.insert(x, GraphEdges::new(Rc::new(RefCell::new(deps))));
150 }
151 init
152 },
153 );
154
155 for (o, node) in map.iter() {
157 for s in node.succ.borrow().iter() {
158 map[s].pred.borrow_mut().insert(*o);
159 }
160 }
161
162 let mut nodes: Vec<GraphNode> = map
168 .iter()
169 .filter_map(|(o, node)| {
170 if self.lobj(*o).entity_type().is_func() {
171 for p in node.pred.borrow().iter() {
172 if p != o {
173 for s in node.succ.borrow().iter() {
174 if s != o {
175 map[p].succ.borrow_mut().insert(*s);
176 map[s].pred.borrow_mut().insert(*p);
177 map[s].pred.borrow_mut().remove(o);
178 }
179 }
180 map[p].succ.borrow_mut().remove(o);
181 }
182 }
183 None
184 } else {
185 Some(GraphNode {
186 obj: *o,
187 ndeps: node.succ.borrow().len(),
188 pos: self.lobj(*o).pos(),
189 })
190 }
191 })
192 .collect();
193
194 nodes.sort_by(|a, b| a.pos.cmp(&b.pos)); (nodes, map)
196 }
197
198 fn report_cycle(&self, cycle: &Vec<ObjKey>) {
199 let o = self.lobj(cycle[0]);
200 self.error(o.pos(), format!("initialization cycle for {}", o.name()));
201 self.error(o.pos(), format!("\t{} refers to", o.name()));
202 for okey in cycle[1..].iter().rev() {
203 let o = self.lobj(*okey);
204 self.error(o.pos(), format!("\t{} refers to", o.name()));
205 }
206 let o = self.lobj(cycle[0]);
207 self.error(o.pos(), format!("\t{}", o.name()));
208 }
209}
210
211fn find_path(
215 map: &Map<ObjKey, DeclInfoKey>,
216 from: ObjKey,
217 to: ObjKey,
218 visited: &mut HashSet<ObjKey>,
219 tc_objs: &TCObjects,
220) -> Option<Vec<ObjKey>> {
221 if visited.contains(&from) {
222 return None;
223 }
224 visited.insert(from);
225
226 let decl = &tc_objs.decls[map[&from]];
227 for &d in decl.deps().iter() {
228 if d == to {
229 return Some(vec![d]);
230 }
231 if let Some(mut p) = find_path(map, d, to, visited, tc_objs) {
232 p.push(d);
233 return Some(p);
234 }
235 }
236 None
237}