1mod ast;
2mod parser;
3use std::fs::read_to_string;
4
5use ast::Tree;
6use parser::yolol_parser;
7use yolol_devices::devices::chip::CodeRunner;
8use yolol_devices::field::Field;
9use yolol_devices::value::ValueTrait;
10use yolol_devices::value::YololInt;
11use yolol_devices::value::YololValue;
12
13#[derive(Debug, Default)]
14pub struct YololRunner {
15 lines: Vec<String>,
16 globals: Vec<Field>,
17 locals: Vec<Field>,
18 pc: usize,
19 path: String,
20}
21
22impl YololRunner {
23 pub fn globals(&self) -> &[Field] {
25 self.globals.as_slice()
26 }
27
28 pub fn locals(&self) -> &[Field] {
30 self.locals.as_slice()
31 }
32
33 fn get_local(&mut self, k: String) -> &mut Field {
34 if self
35 .locals
36 .iter()
37 .any(|f| f.name().to_lowercase() == k.to_lowercase())
38 {
39 for f in &mut self.locals {
40 if f.name() == k {
41 return f;
42 }
43 }
44 unreachable!();
45 } else {
46 let mut field = Field::default();
47 field.set_name(k.clone());
48 self.locals.push(field);
49 self.get_local(k)
50 }
51 }
52
53 fn get_global(&mut self, k: String) -> &mut Field {
54 if self
55 .globals
56 .iter()
57 .any(|f| f.name().to_lowercase() == k.to_lowercase())
58 {
59 for f in &mut self.globals {
60 if f.name() == k {
61 return f;
62 }
63 }
64 unreachable!();
65 } else {
66 let mut field = Field::default();
67 field.set_name(k.clone());
68 self.globals.push(field);
69 self.get_global(k)
70 }
71 }
72
73 fn process(&mut self, token: &Tree) -> Option<()> {
74 match token {
75 Tree::Error => None,
76 Tree::Comment(_) => Some(()),
77 Tree::Assign(r, l) => self.process_assing(r, l),
78 Tree::IfThen(p, s) => {
79 let v = &self.process_expr(p)?;
80 if v.into() {
81 for stmt in s {
82 self.process(stmt)?;
83 }
84 }
85 Some(())
86 }
87 Tree::Goto(t) => {
88 if let YololValue::Int(v) = &self.process_expr(t)? {
89 let pc: i64 = v.into();
90 self.pc = (pc - 2).clamp(0, 20) as usize;
91 }
92 None
93 }
94 Tree::Empty => Some(()),
95 t => self.process_expr(t).map(|_| ()),
96 }
97 }
98
99 fn process_assing(&mut self, r: &Tree, l: &Tree) -> Option<()> {
100 let value = self.process_expr(l)?;
101
102 let field = match r {
103 Tree::LocalVariable(v) => self.get_local(v.clone()),
104 Tree::GlobalVariable(v) => self.get_global(v.clone()),
105 t => unreachable!("process_assing : {:?}", t),
106 };
107 **field = value;
108 Some(())
109 }
110 fn process_expr(&mut self, token: &Tree) -> Option<YololValue> {
111 match token {
112 Tree::LocalVariable(v) => Some((**self.get_local(v.clone())).clone()),
113 Tree::GlobalVariable(v) => Some((**self.get_global(v.clone())).clone()),
114 Tree::Numerical(v) => Some(YololInt::new_raw(*v).into()),
115 Tree::String(v) => Some(v.as_str().into()),
116 Tree::Or(r, l) => Some(self.process_expr(r)?.or(&self.process_expr(l)?)),
117 Tree::And(r, l) => Some(self.process_expr(r)?.and(&self.process_expr(l)?)),
118 Tree::Eq(r, l) => Some((self.process_expr(r)? == self.process_expr(l)?).into()),
119 Tree::Ne(r, l) => Some((self.process_expr(r)? != self.process_expr(l)?).into()),
120 Tree::Gt(r, l) => Some((self.process_expr(r)? > self.process_expr(l)?).into()),
121 Tree::Lt(r, l) => Some((self.process_expr(r)? < self.process_expr(l)?).into()),
122 Tree::Gte(r, l) => Some((self.process_expr(r)? >= self.process_expr(l)?).into()),
123 Tree::Lte(r, l) => Some((self.process_expr(r)? <= self.process_expr(l)?).into()),
124 Tree::Add(r, l) => Some(&self.process_expr(r)? + &self.process_expr(l)?),
125 Tree::Sub(r, l) => &self.process_expr(r)? - &self.process_expr(l)?,
126 Tree::Mul(r, l) => &self.process_expr(r)? * &self.process_expr(l)?,
127 Tree::Div(r, l) => &self.process_expr(r)? / &self.process_expr(l)?,
128 Tree::Mod(r, l) => &self.process_expr(r)? % &self.process_expr(l)?,
129 Tree::Neg(l) => &YololValue::default() - &self.process_expr(l)?,
130 Tree::Fac(r) => Some(self.process_expr(r)?.fac()?),
131 Tree::Abs(r) => Some(self.process_expr(r)?.abs()?),
132 Tree::Sqrt(r) => Some(self.process_expr(r)?.sqrt()?),
133 Tree::Sin(r) => Some(self.process_expr(r)?.sin()?),
134 Tree::Asin(r) => Some(self.process_expr(r)?.asin()?),
135 Tree::Cos(r) => Some(self.process_expr(r)?.cos()?),
136 Tree::Acos(r) => Some(self.process_expr(r)?.acos()?),
137 Tree::Tan(r) => Some(self.process_expr(r)?.tan()?),
138 Tree::Atan(r) => Some(self.process_expr(r)?.atan()?),
139 Tree::Not(r) => Some((self.process_expr(r)? == false.into()).into()),
140 Tree::Exp(r, l) => Some(self.process_expr(r)?.pow(&self.process_expr(l)?)?),
141
142 Tree::AssignAdd(r, l) => {
143 let v = self.process_expr(l)?;
144 let field = match &**r {
145 Tree::LocalVariable(v) => self.get_local(v.to_string()),
146 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
147 _ => unreachable!(),
148 };
149 **field = &**field + &v;
150 Some(YololValue::default())
151 }
152
153 Tree::AssignSub(r, l) => {
154 let v = self.process_expr(l)?;
155 let field = match &**r {
156 Tree::LocalVariable(v) => self.get_local(v.to_string()),
157 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
158 _ => unreachable!(),
159 };
160 **field = (&**field - &v)?;
161 Some(YololValue::default())
162 }
163
164 Tree::AssignMul(r, l) => {
165 let v = self.process_expr(l)?;
166 let field = match &**r {
167 Tree::LocalVariable(v) => self.get_local(v.to_string()),
168 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
169 _ => unreachable!(),
170 };
171 **field = (&**field * &v)?;
172 Some(YololValue::default())
173 }
174
175 Tree::AssignDiv(r, l) => {
176 let v = self.process_expr(l)?;
177 let field = match &**r {
178 Tree::LocalVariable(v) => self.get_local(v.to_string()),
179 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
180 _ => unreachable!(),
181 };
182 **field = (&**field / &v)?;
183 Some(YololValue::default())
184 }
185
186 Tree::AssignMod(r, l) => {
187 let v = self.process_expr(l)?;
188 let field = match &**r {
189 Tree::LocalVariable(v) => self.get_local(v.to_string()),
190 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
191 _ => unreachable!(),
192 };
193 **field = (&**field % &v)?;
194 Some(YololValue::default())
195 }
196
197 Tree::AssignExp(r, l) => {
198 let v = self.process_expr(l)?;
199 let field = match &**r {
200 Tree::LocalVariable(v) => self.get_local(v.to_string()),
201 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
202 _ => unreachable!(),
203 };
204 let v = field.pow(&v);
205 **field = v?;
206 Some(YololValue::default())
207 }
208
209 Tree::PostInc(r) => {
210 let field = match &**r {
211 Tree::LocalVariable(v) => self.get_local(v.to_string()),
212 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
213 _ => unreachable!(),
214 };
215 Some(field.post_inc())
216 }
217 Tree::PostDec(r) => {
218 let field = match &**r {
219 Tree::LocalVariable(v) => self.get_local(v.to_string()),
220 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
221 _ => unreachable!(),
222 };
223 Some(field.post_dec()?)
224 }
225 Tree::PreDec(r) => {
226 let field = match &**r {
227 Tree::LocalVariable(v) => self.get_local(v.to_string()),
228 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
229 _ => unreachable!(),
230 };
231 Some(field.pre_dec()?)
232 }
233 Tree::PreInc(r) => {
234 let field = match &**r {
235 Tree::LocalVariable(v) => self.get_local(v.to_string()),
236 Tree::GlobalVariable(v) => self.get_global(v.to_string()),
237 _ => unreachable!(),
238 };
239 Some(field.pre_inc())
240 }
241 t => unreachable!("process_expr : {:?}", t),
242 }
243 }
244}
245
246impl CodeRunner for YololRunner {
247 fn parse(&mut self, path: &str) -> Option<()> {
248 self.path = path.to_string();
249 if let Ok(file) = read_to_string(path) {
250 self.lines = file
251 .replace("\r\n", "\n")
252 .split('\n')
253 .map(|s| s.to_string())
254 .collect(); return Some(());
256 }
257 None
258 }
259
260 fn step(&mut self) {
261 if self.lines.len() <= self.pc {
262 self.pc = 0;
263 }
264 let stmts = yolol_parser::line(&self.lines[self.pc]);
265 if let Ok(stmts) = stmts {
266 for stmt in stmts {
267 if self.process(&stmt).is_none() {
268 break;
269 }
270 }
271 } else if let Err(err) = stmts {
272 println!("error {} line {}\n{}", self.path, self.pc + 1, err);
273 }
274 self.pc += 1;
275 }
276
277 fn update_globals(&mut self, globals: Vec<Field>) {
278 self.globals = globals;
279 }
280
281 fn get_global(&self) -> Vec<Field> {
282 self.globals.clone()
283 }
284}