1use crate::func_man::FuncManager;
2use crate::scope::Scope;
3use crate::tdata::*;
4use crate::temp_man::TempManager;
5use crate::tparam::*;
6use err_tools::*;
7use std::ops::Deref;
8
9#[derive(Clone, Debug, PartialEq)]
10pub enum VarPart {
11 Num(usize),
12 Id(String),
13}
14impl VarPart {
15 pub fn as_str(&self) -> Option<&str> {
16 match self {
17 VarPart::Num(_) => None,
18 VarPart::Id(s) => Some(s),
19 }
20 }
21}
22
23#[derive(Clone, Debug, PartialEq)]
24pub enum Expr {
25 Lit(TData),
26 Var(Vec<VarPart>),
27 Command(String, Vec<Expr>),
28 List(Vec<Expr>),
29 Map(Vec<(String, Expr)>),
30}
31
32pub fn run_values<'a, TM: TempManager, FM: FuncManager>(
33 cname: &str,
34 args: &[TCow<'a>],
35 tm: &mut TM,
36 fm: &FM,
37) -> anyhow::Result<TCow<'a>> {
38 if let Some(in_f) = fm.get_func(&cname) {
39 return Ok(in_f(&args)?);
40 }
41 match tm.get_t(cname).map(|t| t.clone()) {
42 Ok(in_tp) => {
43 let mut v2: Vec<&dyn TParam> = Vec::new();
44 for a in args {
45 v2.push(a);
46 }
47 let (s, mut mp) = in_tp.run_exp(&v2, tm, fm)?;
48 if let Some(v) = mp.remove("return") {
49 return Ok(TCow::Owned(v));
50 }
51 Ok(TCow::Owned(TData::String(s)))
52 }
53 Err(e) => e_string(format!("Getting template {}, {}", cname, e)),
54 }
55}
56
57pub fn run_command<'a, TM: TempManager, FM: FuncManager>(
58 cname: &str,
59 args: &'a [Expr],
60 scope: &'a Scope,
61 tm: &mut TM,
62 fm: &FM,
63) -> anyhow::Result<TCow<'a>> {
64 if cname == "run" {
65 let mut tds = Vec::new();
66 for p in args {
67 tds.push(p.run(scope, tm, fm)?);
68 }
69 let mut v: Vec<&dyn TParam> = Vec::new();
71 for p in &tds[1..] {
72 v.push(p);
73 }
74 if let Some(tp) = tds.get(0) {
75 if let TData::Template(t) = tp.deref() {
76 let (s, mut mp) = t.run_exp(&v, tm, fm)?;
77 if let Some(v) = mp.remove("return") {
78 return Ok(TCow::Owned(v));
79 }
80 return Ok(TCow::Owned(TData::String(s)));
81 }
82 }
83 }
84 if cname == "first" {
85 for p in args {
86 if let Ok(res) = p.run(scope, tm, fm) {
87 if *res.deref() != TData::Null {
88 return Ok(res);
89 }
90 }
91 }
92 return Ok(TCow::Owned(TData::Null));
93 }
94 if cname == "select" {
95 if args.len() < 3 {
96 return e_str("'select' requires at least 1 test and 2 possible values");
97 }
98 let bval = args[0].run(scope, tm, fm)?;
99 let bval = if let Some(n) = bval.as_usize() {
100 n + 1
101 } else if let Some(b) = bval.as_bool() {
102 2 - (b as usize)
103 } else {
104 return e_string(format!("As Bool failed on {}", bval.deref()));
105 };
106
107 if bval > args.len() {
108 return e_str("'select' first param must choose return a value less than the length of the rest of the args");
109 }
110
111 return args[bval].run(scope, tm, fm);
112 }
113 let mut v = Vec::new();
114 for p in args {
115 let pval = p.run(scope, tm, fm)?;
116 v.push(pval);
117 }
118 run_values(cname, &v, tm, fm)
119}
120
121impl Expr {
122 pub fn run<'a, TM: TempManager, FM: FuncManager>(
123 &'a self,
124 scope: &'a Scope,
125 tm: &mut TM,
126 fm: &FM,
127 ) -> anyhow::Result<TCow<'a>> {
128 match self {
129 Expr::Lit(v) => Ok(TCow::Borrowed(v)),
130 Expr::Var(v) => scope.get(v).e_string(format!("No Var by the name {:?}", v)),
131 Expr::Command(c, pars) => run_command(c, pars, scope, tm, fm),
132 Expr::List(v) => {
133 let mut res: Vec<TData> = Vec::new();
134 for c in v {
135 let r = c.run(scope, tm, fm)?;
136 res.push(r.into_owned());
137 }
138 Ok(TCow::Owned(TData::List(res)))
139 }
140 Expr::Map(m) => {
141 let mut res = std::collections::HashMap::new();
142 for (k, v) in m {
143 let r = v.run(scope, tm, fm)?;
144 res.insert(k.clone(), r.into_owned());
145 }
146 Ok(TCow::Owned(TData::Map(res)))
147 }
148 }
149 }
150}