c3_lang_linearization/
c3.rs1use std::collections::HashMap;
2
3use crate::{id::Id, split_coma};
4
5use super::{C3Error, Sets};
6
7pub type Class = Id;
8pub type Fn = Id;
9pub type Var = Id;
10
11#[derive(Debug, PartialEq, Eq, Clone)]
12pub struct C3 {
13 classes: HashMap<Class, Vec<Class>>,
15 functions: HashMap<Class, Vec<Fn>>,
16 variables: HashMap<Class, Vec<Var>>,
17}
18
19impl C3 {
20 pub fn new() -> Self {
22 Self {
23 classes: HashMap::new(),
24 functions: HashMap::new(),
25 variables: HashMap::new(),
26 }
27 }
28
29 pub fn add(&mut self, base: Class, path: Vec<Class>) {
31 self.classes.insert(base, path);
32 }
33
34 pub fn add_class_str(&mut self, base: &str, parents: &str) {
36 let input: Vec<Class> = split_coma(parents).into_iter().map(Class::from).collect();
37 self.add(Class::from(base), input);
38 }
39
40 pub fn remove(&mut self, base: &Class) -> Result<(), C3Error> {
42 match self.classes.remove(base) {
43 Some(_) => Ok(()),
44 None => Err(C3Error::BaseClassDoesNotExists(base.clone().into())),
45 }
46 }
47
48 pub fn all_classes(&self) -> Vec<Class> {
50 let mut keys: Vec<Class> = self.classes.keys().cloned().collect();
51 keys.sort();
52 keys
53 }
54
55 pub fn all_classes_str(&self) -> Vec<String> {
57 self.all_classes()
58 .into_iter()
59 .map(|class| class.into())
60 .collect()
61 }
62
63 pub fn is_empty(&self) -> bool {
65 self.classes.is_empty()
66 }
67
68 pub fn path(&self, base: &Class) -> Result<Vec<Class>, C3Error> {
70 match self.classes.get(base) {
71 Some(path) => Ok(path.clone()),
72 None => Err(C3Error::BaseClassDoesNotExists(base.clone().into())),
73 }
74 }
75
76 pub fn sets_for(&self, bases: Vec<Class>) -> Result<Sets<Class>, C3Error> {
78 let mut sets = Sets::new();
79 for base in &bases {
80 let path = self.path(base)?;
81 if !path.is_empty() {
82 sets.push(path.clone())?;
83 }
84 }
85 if !bases.is_empty() {
86 sets.push(bases)?;
87 }
88 Ok(sets)
89 }
90
91 pub fn register_fn(&mut self, class: Class, fun: Fn) {
92 self.functions.entry(class).or_insert(vec![]).push(fun);
93 }
94
95 pub fn register_fns(&mut self, class: Class, funs: Vec<Fn>) {
96 for fun in funs {
97 self.register_fn(class.clone(), fun);
98 }
99 }
100
101 pub fn register_fn_str(&mut self, class: &str, function: &str) {
102 self.register_fn(Class::from(class), Fn::from(function))
103 }
104
105 pub fn functions(&self, class: &Class) -> Vec<Fn> {
106 let path: Vec<Class> = self.path(class).unwrap();
107 let mut functions: Vec<Fn> = vec![];
108 for class in path {
109 let mut list: Vec<Fn> = self.functions.get(&class).cloned().unwrap_or_default();
110 functions.append(&mut list);
111 }
112 functions.sort();
113 functions.dedup();
114 functions
115 }
116
117 pub fn functions_str(&self, class: &str) -> Vec<String> {
118 self.functions(&Class::from(class))
119 .into_iter()
120 .map(|x| x.to_string())
121 .collect()
122 }
123
124 pub fn register_var(&mut self, class: Class, var: Var) {
125 self.variables.entry(class).or_insert(vec![]).push(var);
126 }
127
128 pub fn register_vars(&mut self, class: Class, vars: Vec<Var>) {
129 for var in vars {
130 self.register_var(class.clone(), var);
131 }
132 }
133
134 pub fn register_var_str(&mut self, class: &str, variable: &str) {
135 self.register_var(Class::from(class), Var::from(variable))
136 }
137
138 pub fn variables(&self, class: &Class) -> Vec<Var> {
139 let path: Vec<Class> = self.path(class).unwrap();
140 let mut varialbes: Vec<Var> = vec![];
141 for class in path {
142 let mut list: Vec<Var> = self.variables.get(&class).cloned().unwrap_or_default();
143 varialbes.append(&mut list);
144 }
145 varialbes.sort();
146 varialbes.dedup();
147 varialbes
148 }
149
150 pub fn varialbes_str(&self, class: &str) -> Vec<String> {
151 self.variables(&Class::from(class))
152 .into_iter()
153 .map(|x| x.to_string())
154 .collect()
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use super::C3;
161
162 #[test]
163 fn test_c3() {
164 let mut c3 = C3::new();
165 c3.add_class_str("A", "A");
166 c3.add_class_str("B", "B, A");
167 c3.add_class_str("K1", "K1, K2, A");
168
169 assert_eq!(c3.all_classes_str(), vec!["A", "B", "K1"]);
170
171 c3.register_fn_str("A", "foo");
172 c3.register_fn_str("A", "bar");
173 c3.register_fn_str("B", "bar");
174 assert_eq!(c3.functions_str("A"), vec!["bar", "foo"]);
175 assert_eq!(c3.functions_str("B"), vec!["bar", "foo"]);
176
177 c3.register_var_str("A", "x");
178 c3.register_var_str("B", "y");
179 assert_eq!(c3.varialbes_str("A"), vec!["x"]);
180 assert_eq!(c3.varialbes_str("B"), vec!["x", "y"]);
181 }
182
183 }