1use crate::{
2 complex::NumStr::Num,
3 math::do_math,
4 options::set_commands,
5 parse::input_var,
6 units::{Colors, Number, Options, Variable},
7};
8use rug::{Float, float::Constant::Pi};
9pub fn get_file_vars(
10 options: Options,
11 vars: &mut Vec<Variable>,
12 lines: Vec<String>,
13 r: &str,
14 blacklist: &mut Vec<String>,
15)
16{
17 if r.chars().all(|c| !c.is_alphabetic())
18 {
19 return;
20 }
21 get_preset_vars(options, r, vars, blacklist);
22 'lower: for i in lines.clone()
23 {
24 let mut split = i.splitn(2, '=');
25 if split.clone().count() == 2
26 {
27 let l = split.next().unwrap().to_string();
28 let left = if l.contains('(')
29 {
30 l.split('(').next().unwrap().to_owned()
31 }
32 else
33 {
34 l.clone()
35 };
36 if !blacklist.contains(&l) && {
37 let mut word = String::new();
38 let mut b = false;
39 for c in r.chars()
40 {
41 if c.is_alphanumeric() || matches!(c, '\'' | '`' | '_')
42 {
43 word.push(c)
44 }
45 else
46 {
47 if l.contains('(')
48 {
49 b = word.trim_end_matches('\'').trim_end_matches('`') == left
50 && matches!(c, '(' | '{' | '[' | '|');
51 }
52 else
53 {
54 b = word == left;
55 }
56 if b
57 {
58 break;
59 }
60 word.clear()
61 }
62 }
63 b
64 }
65 {
66 if let Some(r) = split.next()
67 {
68 let le = l.chars().collect::<Vec<char>>();
69 blacklist.push(l.clone());
70 get_file_vars(options, vars, lines.clone(), r, blacklist);
71 for (i, j) in vars.iter().enumerate()
72 {
73 if j.name.len() <= le.len()
74 {
75 if let Err(s) = add_var(le, r, i, vars, options, false, false, false)
76 {
77 println!("{s}")
78 }
79 continue 'lower;
80 }
81 }
82 if let Err(s) = add_var(le, r, 0, vars, options, false, false, false)
83 {
84 println!("{s}")
85 }
86 }
87 }
88 }
89 }
90}
91fn get_preset_vars(
92 options: Options,
93 args: &str,
94 vars: &mut Vec<Variable>,
95 blacklist: &mut Vec<String>,
96)
97{
98 {
99 let phi1 = args.contains("phi") && !blacklist.contains(&"phi".to_string());
100 let phi2 = args.contains('φ') && !blacklist.contains(&"φ".to_string());
101 if phi1 || phi2
102 {
103 let phi: Float = (1 + Float::with_val(options.prec, 5).sqrt()) / 2;
104 if phi1
105 {
106 blacklist.push("phi".to_string());
107 vars.insert(
108 0,
109 Variable {
110 name: vec!['p', 'h', 'i'],
111 parsed: vec![Num(Number::from(phi.clone().into(), None))],
112 unparsed: String::new(),
113 funcvars: Vec::new(),
114 },
115 );
116 }
117 if phi2
118 {
119 blacklist.push("φ".to_string());
120 vars.push(Variable {
121 name: vec!['φ'],
122 parsed: vec![Num(Number::from(phi.into(), None))],
123 unparsed: String::new(),
124 funcvars: Vec::new(),
125 });
126 }
127 }
128 }
129 {
130 let pi1 = args.contains("pi") && !blacklist.contains(&"pi".to_string());
131 let pi2 = args.contains('π') && !blacklist.contains(&"π".to_string());
132 let tau1 = args.contains("tau") && !blacklist.contains(&"tau".to_string());
133 let tau2 = args.contains('τ') && !blacklist.contains(&"τ".to_string());
134 if pi1 || pi2 || tau1 || tau2
135 {
136 let pi = Float::with_val(options.prec, Pi);
137 if pi1
138 {
139 blacklist.push("pi".to_string());
140 vars.insert(
141 vars.iter().position(|c| c.name.len() != 3).unwrap_or(0),
142 Variable {
143 name: vec!['p', 'i'],
144 parsed: vec![Num(Number::from(pi.clone().into(), None))],
145 unparsed: String::new(),
146 funcvars: Vec::new(),
147 },
148 );
149 }
150 if pi2
151 {
152 blacklist.push("π".to_string());
153 vars.push(Variable {
154 name: vec!['π'],
155 parsed: vec![Num(Number::from(pi.clone().into(), None))],
156 unparsed: String::new(),
157 funcvars: Vec::new(),
158 });
159 }
160 if tau1 || tau2
161 {
162 let tau: Float = pi.clone() * 2;
163 if tau1
164 {
165 blacklist.push("tau".to_string());
166 vars.insert(
167 0,
168 Variable {
169 name: vec!['t', 'a', 'u'],
170 parsed: vec![Num(Number::from(tau.clone().into(), None))],
171 unparsed: String::new(),
172 funcvars: Vec::new(),
173 },
174 );
175 }
176 if tau2
177 {
178 blacklist.push("τ".to_string());
179 vars.push(Variable {
180 name: vec!['τ'],
181 parsed: vec![Num(Number::from(tau.into(), None))],
182 unparsed: String::new(),
183 funcvars: Vec::new(),
184 });
185 }
186 }
187 }
188 }
189 if args.contains('e') && !blacklist.contains(&"e".to_string())
190 {
191 blacklist.push("e".to_string());
192 let e = Float::with_val(options.prec, 1).exp();
193 vars.push(Variable {
194 name: vec!['e'],
195 parsed: vec![Num(Number::from(e.into(), None))],
196 unparsed: String::new(),
197 funcvars: Vec::new(),
198 });
199 }
200}
201pub fn get_cli_vars(options: Options, args: String, vars: &mut Vec<Variable>)
202{
203 if args.chars().all(|c| !c.is_alphabetic())
204 {
205 return;
206 }
207 {
208 let phi1 = args.contains("phi");
209 let phi2 = args.contains('φ');
210 if phi1 || phi2
211 {
212 let phi: Float = (1 + Float::with_val(options.prec, 5).sqrt()) / 2;
213 if phi1
214 {
215 vars.insert(
216 0,
217 Variable {
218 name: vec!['p', 'h', 'i'],
219 parsed: vec![Num(Number::from(phi.clone().into(), None))],
220 unparsed: String::new(),
221 funcvars: Vec::new(),
222 },
223 );
224 }
225 if phi2
226 {
227 vars.push(Variable {
228 name: vec!['φ'],
229 parsed: vec![Num(Number::from(phi.into(), None))],
230 unparsed: String::new(),
231 funcvars: Vec::new(),
232 });
233 }
234 }
235 }
236 {
237 let pi1 = args.contains("pi");
238 let pi2 = args.contains('π');
239 let tau1 = args.contains("tau");
240 let tau2 = args.contains('τ');
241 if pi1 || pi2 || tau1 || tau2
242 {
243 let pi = Float::with_val(options.prec, Pi);
244 if pi1
245 {
246 vars.insert(
247 vars.iter().position(|c| c.name.len() != 3).unwrap_or(0),
248 Variable {
249 name: vec!['p', 'i'],
250 parsed: vec![Num(Number::from(pi.clone().into(), None))],
251 unparsed: String::new(),
252 funcvars: Vec::new(),
253 },
254 );
255 }
256 if pi2
257 {
258 vars.push(Variable {
259 name: vec!['π'],
260 parsed: vec![Num(Number::from(pi.clone().into(), None))],
261 unparsed: String::new(),
262 funcvars: Vec::new(),
263 });
264 }
265 if tau1 || tau2
266 {
267 let tau: Float = pi.clone() * 2;
268 if tau1
269 {
270 vars.insert(
271 0,
272 Variable {
273 name: vec!['t', 'a', 'u'],
274 parsed: vec![Num(Number::from(tau.clone().into(), None))],
275 unparsed: String::new(),
276 funcvars: Vec::new(),
277 },
278 );
279 }
280 if tau2
281 {
282 vars.push(Variable {
283 name: vec!['τ'],
284 parsed: vec![Num(Number::from(tau.into(), None))],
285 unparsed: String::new(),
286 funcvars: Vec::new(),
287 });
288 }
289 }
290 }
291 }
292 if args.contains('e')
293 {
294 let e = Float::with_val(options.prec, 1).exp();
295 vars.push(Variable {
296 name: vec!['e'],
297 parsed: vec![Num(Number::from(e.into(), None))],
298 unparsed: String::new(),
299 funcvars: Vec::new(),
300 });
301 }
302}
303pub fn get_vars(options: Options) -> Vec<Variable>
304{
305 let pi = Float::with_val(options.prec, Pi);
306 let tau: Float = pi.clone() * 2;
307 let phi: Float = (1 + Float::with_val(options.prec, 5).sqrt()) / 2;
308 let e = Float::with_val(options.prec, 1).exp();
309 vec![
310 Variable {
311 name: vec!['p', 'h', 'i'],
312 parsed: vec![Num(Number::from(phi.clone().into(), None))],
313 unparsed: String::new(),
314 funcvars: Vec::new(),
315 },
316 Variable {
317 name: vec!['t', 'a', 'u'],
318 parsed: vec![Num(Number::from(tau.clone().into(), None))],
319 unparsed: String::new(),
320 funcvars: Vec::new(),
321 },
322 Variable {
323 name: vec!['p', 'i'],
324 parsed: vec![Num(Number::from(pi.clone().into(), None))],
325 unparsed: String::new(),
326 funcvars: Vec::new(),
327 },
328 Variable {
329 name: vec!['e'],
330 parsed: vec![Num(Number::from(e.into(), None))],
331 unparsed: String::new(),
332 funcvars: Vec::new(),
333 },
334 Variable {
335 name: vec!['φ'],
336 parsed: vec![Num(Number::from(phi.into(), None))],
337 unparsed: String::new(),
338 funcvars: Vec::new(),
339 },
340 Variable {
341 name: vec!['π'],
342 parsed: vec![Num(Number::from(pi.into(), None))],
343 unparsed: String::new(),
344 funcvars: Vec::new(),
345 },
346 Variable {
347 name: vec!['τ'],
348 parsed: vec![Num(Number::from(tau.into(), None))],
349 unparsed: String::new(),
350 funcvars: Vec::new(),
351 },
352 ]
353}
354#[allow(clippy::too_many_arguments)]
355pub fn add_var(
356 l: Vec<char>,
357 mut r: &str,
358 i: usize,
359 vars: &mut Vec<Variable>,
360 options: Options,
361 redef: bool,
362 replace: bool,
363 null: bool,
364) -> Result<(), &'static str>
365{
366 if null
367 {
368 vars.remove(i);
369 }
370 else
371 {
372 let orig = r;
373 let mut func_vars: Vec<(isize, String)> = Vec::new();
374 if l.contains(&'(')
375 {
376 let mut l = l.clone();
377 l.pop();
378 let st = l
379 .drain(0..=l.iter().position(|c| c == &'(').unwrap_or(0))
380 .collect::<String>();
381 if st.contains(',') || st.len() == 1
382 {
383 return Err("bad var name");
384 }
385 for i in l.split(|c| c == &',')
386 {
387 func_vars.push((-1, i.iter().collect()));
388 }
389 }
390 else if l.contains(&',') || l.is_empty()
391 {
392 return Err("bad var name");
393 }
394 let mut fvs = Vec::new();
395 let mut parsed = if r.contains("pw") || r.contains("piecewise")
396 {
397 let mut k = 0;
398 for (j, v) in vars.iter().enumerate()
399 {
400 if v.name.len() <= l.len()
401 {
402 k = j;
403 break;
404 }
405 }
406 let mut tempvars = vars.clone();
407 tempvars.insert(
408 k,
409 Variable {
410 name: l.clone(),
411 parsed: Vec::new(),
412 unparsed: String::new(),
413 funcvars: Vec::new(),
414 },
415 );
416 if r.contains(':')
417 {
418 let mut split = r.split(':').collect::<Vec<&str>>();
419 r = split.pop().unwrap();
420 for i in split
421 {
422 if i.contains('=')
423 {
424 let mut split = i.splitn(2, '=');
425 let s = split.next().unwrap().to_string();
426 let parsed = input_var(
427 split.next().unwrap(),
428 &tempvars,
429 &mut func_vars,
430 &mut 0,
431 options,
432 false,
433 0,
434 s.chars().collect::<Vec<char>>(),
435 false,
436 &mut Vec::new(),
437 None,
438 )?;
439 func_vars.push((-1, s.clone()));
440 fvs.push((s, parsed.0));
441 fvs.extend(parsed.1)
442 }
443 }
444 }
445 input_var(
446 r,
447 &tempvars,
448 &mut func_vars,
449 &mut 0,
450 options,
451 false,
452 0,
453 l.clone(),
454 false,
455 &mut Vec::new(),
456 None,
457 )?
458 }
459 else
460 {
461 if r.contains(':')
462 {
463 let mut split = r.split(':').collect::<Vec<&str>>();
464 r = split.pop().unwrap();
465 for i in split
466 {
467 if i.contains('=')
468 {
469 let mut split = i.splitn(2, '=');
470 let s = split.next().unwrap().to_string();
471 let parsed = input_var(
472 split.next().unwrap(),
473 vars,
474 &mut func_vars,
475 &mut 0,
476 options,
477 false,
478 0,
479 s.chars().collect::<Vec<char>>(),
480 false,
481 &mut Vec::new(),
482 None,
483 )?;
484 func_vars.push((-1, s.clone()));
485 fvs.push((s, parsed.0));
486 fvs.extend(parsed.1)
487 }
488 }
489 }
490 input_var(
491 r,
492 vars,
493 &mut func_vars,
494 &mut 0,
495 options,
496 false,
497 0,
498 l.clone(),
499 false,
500 &mut Vec::new(),
501 None,
502 )?
503 };
504 parsed.1.extend(fvs);
505 if l.contains(&'(')
506 && r.contains(l.split(|c| c == &'(').next().unwrap())
507 && (r.contains("piecewise") || r.contains("pw"))
508 {
509 parsed
510 .1
511 .push((l.iter().collect::<String>(), parsed.0.clone()))
512 }
513 if parsed.0.is_empty()
514 {
515 return Err("bad input");
516 }
517 else if replace
518 {
519 vars[i] = Variable {
520 name: l.clone(),
521 parsed: if l.contains(&'(')
522 {
523 parsed.0
524 }
525 else
526 {
527 vec![do_math(parsed.0, options, parsed.1.clone())?]
528 },
529 unparsed: orig.to_string(),
530 funcvars: parsed.1,
531 };
532 }
533 else
534 {
535 vars.insert(
536 i,
537 Variable {
538 name: l.clone(),
539 parsed: if l.contains(&'(')
540 {
541 parsed.0
542 }
543 else
544 {
545 vec![do_math(parsed.0, options, parsed.1.clone())?]
546 },
547 unparsed: orig.to_string(),
548 funcvars: parsed.1,
549 },
550 )
551 }
552 }
553 if redef
554 {
555 let mut redef = vec![(l.clone(), Vec::new())];
556 let mut k = 0;
557 while k < redef.len()
558 {
559 let mut j = 0;
560 while j < vars.len()
561 {
562 let v = &vars[j];
563 let check = &redef[k].0[0..=redef[k]
564 .0
565 .iter()
566 .position(|a| a == &'(')
567 .unwrap_or(redef[k].0.len().saturating_sub(1))]
568 .iter()
569 .collect::<String>();
570 if !redef.iter().any(|a| a.0 == v.name && a.1 == redef[k].0)
571 && v.unparsed.contains(check)
572 {
573 let mut func_vars: Vec<(isize, String)> = Vec::new();
574 if v.name.contains(&'(')
575 {
576 let mut l = v.name.clone();
577 l.drain(0..=l.iter().position(|c| c == &'(').unwrap());
578 l.pop();
579 for i in l.split(|c| c == &',')
580 {
581 func_vars.push((-1, i.iter().collect::<String>()));
582 }
583 }
584 let mut fvs = Vec::new();
585 let mut unparsed = v.unparsed.clone();
586 if unparsed.contains(':')
587 {
588 let un = unparsed;
589 let mut split = un.split(':').collect::<Vec<&str>>();
590 unparsed = split.pop().unwrap().to_string();
591 for i in split
592 {
593 if i.contains('=')
594 {
595 let mut split = i.splitn(2, '=');
596 let s = split.next().unwrap().to_string();
597 let parsed = input_var(
598 split.next().unwrap(),
599 vars,
600 &mut func_vars,
601 &mut 0,
602 options,
603 false,
604 0,
605 s.chars().collect::<Vec<char>>(),
606 false,
607 &mut Vec::new(),
608 None,
609 )?;
610 func_vars.push((-1, s.clone()));
611 fvs.push((s, parsed.0));
612 fvs.extend(parsed.1)
613 }
614 }
615 }
616 let mut parsed = input_var(
617 &unparsed,
618 vars,
619 &mut func_vars,
620 &mut 0,
621 options,
622 false,
623 0,
624 v.name.clone(),
625 false,
626 &mut Vec::new(),
627 None,
628 )?;
629 parsed.1.extend(fvs);
630 if v.name.contains(&'(')
631 && v.unparsed
632 .contains(v.name.split(|c| c == &'(').next().unwrap())
633 && (v.unparsed.contains("piecewise") || v.unparsed.contains("pw"))
634 {
635 parsed
636 .1
637 .push((v.name.iter().collect::<String>(), parsed.0.clone()));
638 }
639 if v.name.contains(&'(')
640 {
641 if v.parsed != parsed.0 || v.funcvars != parsed.1
642 {
643 redef.push((v.name.clone(), redef[k].0.clone()));
644 vars[j].parsed = parsed.0;
645 vars[j].funcvars = parsed.1;
646 }
647 }
648 else if let Ok(n) = do_math(parsed.0.clone(), options, parsed.1.clone())
649 {
650 if n != v.parsed[0]
651 {
652 redef.push((v.name.clone(), redef[k].0.clone()));
653 vars[j].parsed = vec![n];
654 }
655 }
656 }
657 j += 1;
658 }
659 k += 1;
660 }
661 }
662 Ok(())
663}
664pub fn set_commands_or_vars(
665 colors: &mut Colors,
666 options: &mut Options,
667 vars: &mut Vec<Variable>,
668 input: &[char],
669) -> Result<(), &'static str>
670{
671 let n = input.iter().collect::<String>();
672 let mut split = n.splitn(2, '=');
673 let s = split.next().unwrap().replace(' ', "");
674 let l = s;
675 let r = split.next().unwrap();
676 if l.is_empty()
677 || l.chars()
678 .any(|c| !c.is_alphanumeric() && !matches!(c, '(' | ')' | ',' | '\'' | '`' | '_'))
679 {
680 return Ok(());
681 }
682 else if let Err(s) = set_commands(options, colors, vars, &l, r)
683 {
684 if s.is_empty()
685 {
686 return Ok(());
687 }
688 return Err(s);
689 }
690 let l = l.chars().collect::<Vec<char>>();
691 for (i, v) in vars.iter().enumerate()
692 {
693 if v.name.split(|c| c == &'(').next() == l.split(|c| c == &'(').next()
694 && v.name.contains(&'(') == l.contains(&'(')
695 && v.name.iter().filter(|c| c == &&',').count()
696 == l.iter().filter(|c| c == &&',').count()
697 {
698 if r == "null"
699 {
700 add_var(l, r, i, vars, *options, true, true, true)?
701 }
702 else
703 {
704 add_var(l, r, i, vars, *options, true, true, false)?
705 }
706 return Ok(());
707 }
708 }
709 for (i, j) in vars.iter().enumerate()
710 {
711 if j.name.len() <= l.len()
712 {
713 add_var(l, r, i, vars, *options, true, false, false)?;
714 return Ok(());
715 }
716 }
717 add_var(l, r, vars.len(), vars, *options, true, false, false)?;
718 Ok(())
719}