Skip to main content

mech_interpreter/
literals.rs

1use crate::*;
2#[cfg(feature = "convert")]
3use crate::stdlib::convert::ConvertKind;
4
5// Literals
6// ----------------------------------------------------------------------------
7
8pub fn literal(ltrl: &Literal, p: &Interpreter) -> MResult<Value> {
9  match &ltrl {
10    Literal::Empty(_) => Ok(empty()),
11    #[cfg(feature = "bool")]
12    Literal::Boolean(bln) => Ok(boolean(bln)),
13    Literal::Number(num) => number(num, p),
14    #[cfg(feature = "string")]
15    Literal::String(strng) => Ok(string(strng)),
16    #[cfg(feature = "atom")]
17    Literal::Atom(atm) => Ok(atom(atm, p)),
18    #[cfg(feature = "kind_annotation")]
19    Literal::Kind(knd) => kind_value(knd, p),
20    #[cfg(feature = "convert")]
21    Literal::TypedLiteral((ltrl,kind)) => typed_literal(ltrl,kind,p),
22    _ => Err(MechError::new(
23      FeatureNotEnabledError, None
24      ).with_compiler_loc())
25  }
26}
27
28#[cfg(feature = "kind_annotation")]
29pub fn kind_value(knd: &NodeKind, p: &Interpreter) -> MResult<Value> {
30  let kind = kind_annotation(knd, p)?;
31  Ok(Value::Kind(kind.to_value_kind(&p.state.borrow().kinds)?))
32}
33
34pub fn kind_annotation(knd: &NodeKind, p: &Interpreter) -> MResult<Kind> {
35  match knd {
36    NodeKind::Kind(knd) => {
37      let knda = kind_annotation(knd, p)?;
38      Ok(Kind::Kind(Box::new(knda)))
39    }
40    NodeKind::Any => Ok(Kind::Any),
41    NodeKind::Atom(atm_identifier) => {
42      let id = atm_identifier.hash();
43      let name = atm_identifier.to_string();
44      Ok(Kind::Atom(id, name))
45    }
46    NodeKind::Empty => Ok(Kind::Empty),
47    NodeKind::Record(elements) => {
48      let mut knds = vec![];
49      for (id, knd) in elements {
50        let knda = kind_annotation(knd, p)?;
51        knds.push((id.to_string().clone(), knda));
52      }
53      Ok(Kind::Record(knds))
54    }
55    NodeKind::Tuple(elements) => {
56      let mut knds = vec![];
57      for knd in elements {
58        let knda = kind_annotation(knd, p)?;
59        knds.push(knda);
60      }
61      Ok(Kind::Tuple(knds))
62    }
63    NodeKind::Map(keys, vals) => {
64      let key_knd = kind_annotation(keys, p)?;
65      let val_knd = kind_annotation(vals, p)?;
66      Ok(Kind::Map(Box::new(key_knd), Box::new(val_knd)))
67    }
68    NodeKind::Scalar(id) => {
69      let kind_id = id.hash();
70      Ok(Kind::Scalar(kind_id))
71    }
72    NodeKind::Matrix((knd, size)) => {
73      let knda = kind_annotation(knd, p)?;
74      let mut dims = vec![];
75      for dim in size {
76        let dim_val = literal(dim, p)?;
77        match dim_val {
78          Value::Empty => { dims.push(0); }
79          _ => {
80            match dim_val.as_usize() {
81              Ok(size_val) => dims.push(size_val.clone()),
82              Err(_) => { return Err(MechError::new(
83                ExpectedNumericForKindSizeError, None
84                ).with_compiler_loc())
85              }
86            } 
87          }
88        }
89      }
90      Ok(Kind::Matrix(Box::new(knda.clone()),dims))
91    }
92    NodeKind::Option(knd) => {
93      let knda = kind_annotation(knd, p)?;
94      Ok(Kind::Option(Box::new(knda)))
95    }
96    NodeKind::Table((elements, size)) => {
97      let mut knds = vec![];
98      for (id, knd) in elements {
99        let knda = kind_annotation(knd, p)?;
100        knds.push((id.to_string().clone(), knda));
101      }
102      let size_val = literal(size, p)?;
103      let size_val = match size_val {
104        Value::Empty => 0,
105        _ => {
106          match size_val.as_usize() {
107            Ok(size_val) => size_val,
108            Err(_) => { return Err(MechError::new(
109              ExpectedNumericForKindSizeError, None
110              ).with_compiler_loc())
111            }
112          }
113        }
114      };
115      Ok(Kind::Table(knds, size_val))
116    }
117    NodeKind::Set(knd, size) => {
118      let knda = kind_annotation(knd, p)?;
119      let size_val = match size {
120        Some(size) => literal(size, p)?,
121        None => Value::Empty,
122      };
123      match size_val.as_usize() {
124        Ok(size_val) => Ok(Kind::Set(Box::new(knda.clone()), Some(size_val))),
125        Err(_) => Ok(Kind::Set(Box::new(knda.clone()), None)),
126      }
127    }
128  }
129}
130
131#[cfg(feature = "convert")]
132pub fn typed_literal(ltrl: &Literal, knd_attn: &KindAnnotation, p: &Interpreter) -> MResult<Value> {
133  let value = literal(ltrl,p)?;
134  let kind = kind_annotation(&knd_attn.kind, p)?;
135  let args = vec![value, kind.to_value(&p.state.borrow().kinds)?];
136  let convert_fxn = ConvertKind{}.compile(&args)?;
137  convert_fxn.solve();
138  let converted_result = convert_fxn.out();
139  p.state.borrow_mut().add_plan_step(convert_fxn);
140  Ok(converted_result)
141}
142
143#[cfg(feature = "atom")]
144pub fn atom(atm: &Atom, p: &Interpreter) -> Value {
145  let id = atm.name.hash();
146  let state = p.state.borrow();
147  let dictionary = state.dictionary.clone();
148  {
149    let mut dictionary_brrw = dictionary.borrow_mut();
150    dictionary_brrw.insert(id, atm.name.to_string());
151  }
152  Value::Atom(Ref::new(MechAtom((id, dictionary))))
153}
154
155pub fn number(num: &Number, p: &Interpreter) -> MResult<Value> {
156  match num {
157    Number::Real(num) => real(num, p),
158    #[cfg(feature = "complex")]
159    Number::Complex(num) => complex(num, p),
160    _ => panic!("Number type not supported."),
161  }
162}
163
164#[cfg(feature = "complex")]
165fn complex(num: &C64Node, p: &Interpreter) -> MResult<Value> {
166  let im: f64 = match real(&num.imaginary.number, p)?.as_f64() {
167    Ok(val) => *val.borrow(),
168    Err(_) => 0.0,
169  };
170  let result = match &num.real {
171    Some(real_val) => {
172      let re: f64 = match real(&real_val, p)?.as_f64() {
173        Ok(val) => *val.borrow(),
174        Err(_) => 0.0,
175      };      
176      Value::C64(Ref::new(C64::new(re, im)))
177    },
178    None => Value::C64(Ref::new(C64::new(0.0, im))),
179  };
180  Ok(result)
181}
182
183pub fn real(rl: &RealNumber, p: &Interpreter) -> MResult<Value> {
184  let result = match rl {
185    #[cfg(feature = "math_neg")]
186    RealNumber::Negated(num) => negated(num, p)?,
187    #[cfg(feature = "f64")]
188    RealNumber::Integer(num) => integer(num),
189    #[cfg(feature = "floats")]
190    RealNumber::Float(num) => float(num),
191    #[cfg(feature = "i64")]
192    RealNumber::Decimal(num) => dec(num),
193    #[cfg(feature = "i64")]
194    RealNumber::Hexadecimal(num) => hex(num),
195    #[cfg(feature = "i64")]
196    RealNumber::Octal(num) => oct(num),
197    #[cfg(feature = "i64")]
198    RealNumber::Binary(num) => binary(num),
199    #[cfg(feature = "floats")]
200    RealNumber::Scientific(num) => scientific(num),
201    #[cfg(feature = "rational")]
202    RealNumber::Rational(num) => rational(num),
203    #[cfg(feature = "convert")]
204    RealNumber::TypedInteger((num_tkn, kind)) => {
205      let num: Literal = Literal::Number(Number::Real(RealNumber::Integer(num_tkn.clone())));
206      typed_literal(&num, kind, p)?
207    },
208    _ => panic!("Number type not supported."),
209  };
210  Ok(result)
211}
212
213#[cfg(feature = "math_neg")]
214pub fn negated(num: &RealNumber, p: &Interpreter) -> MResult<Value> {
215  let num_val = real(&num, p)?;
216  let result = match num_val {
217    #[cfg(feature = "i8")]
218    Value::I8(val) => Value::I8(Ref::new(-*val.borrow())),
219    #[cfg(feature = "i16")]
220    Value::I16(val) => Value::I16(Ref::new(-*val.borrow())),
221    #[cfg(feature = "i32")]
222    Value::I32(val) => Value::I32(Ref::new(-*val.borrow())),
223    #[cfg(feature = "i64")]
224    Value::I64(val) => Value::I64(Ref::new(-*val.borrow())),
225    #[cfg(feature = "i128")]
226    Value::I128(val) => Value::I128(Ref::new(-*val.borrow())),
227    #[cfg(feature = "f64")]
228    Value::F64(val) => Value::F64(Ref::new(-(*val.borrow()))),
229    #[cfg(feature = "f32")]
230    Value::F32(val) => Value::F32(Ref::new(-(*val.borrow()))),
231    x => panic!("Negation is only supported for integer and float types, got {:?}", x),
232  };
233  Ok(result)
234}
235
236#[cfg(feature = "rational")]
237pub fn rational(rat: &(Token,Token)) -> Value {
238  let (num, denom) = rat;
239  let num = num.chars.iter().collect::<String>().parse::<i64>().unwrap();
240  let denom = denom.chars.iter().collect::<String>().parse::<i64>().unwrap();
241  if denom == 0 {
242    panic!("Denominator cannot be zero in a rational number");
243  }
244  let rat_num = R64::new(num, denom);
245  Value::R64(Ref::new(rat_num))
246}
247
248#[cfg(feature = "i64")]
249pub fn dec(bnry: &Token) -> Value {
250  let binary_str: String = bnry.chars.iter().collect();
251  let num = i64::from_str_radix(&binary_str, 10).unwrap();
252  Value::I64(Ref::new(num))
253}
254
255#[cfg(feature = "i64")]
256pub fn binary(bnry: &Token) -> Value {
257  let binary_str: String = bnry.chars.iter().collect();
258  let num = i64::from_str_radix(&binary_str, 2).unwrap();
259  Value::I64(Ref::new(num))
260}
261
262#[cfg(feature = "i64")]
263pub fn oct(octl: &Token) -> Value {
264  let hex_str: String = octl.chars.iter().collect();
265  let num = i64::from_str_radix(&hex_str, 8).unwrap();
266  Value::I64(Ref::new(num))
267}
268
269#[cfg(feature = "i64")]
270pub fn hex(hxdcml: &Token) -> Value {
271  let hex_str: String = hxdcml.chars.iter().collect();
272  let num = i64::from_str_radix(&hex_str, 16).unwrap();
273  Value::I64(Ref::new(num))
274}
275
276#[cfg(feature = "f64")]
277pub fn scientific(sci: &(Base,Exponent)) -> Value {
278  let (base,exp): &(Base,Exponent) = sci;
279  let (whole,part): &(Whole,Part) = base;
280  let (sign,exp_whole, exp_part): &(Sign, Whole, Part) = exp;
281
282  let a = whole.chars.iter().collect::<String>();
283  let b = part.chars.iter().collect::<String>();
284  let c = exp_whole.chars.iter().collect::<String>();
285  let d = exp_part.chars.iter().collect::<String>();
286  let num_f64: f64 = format!("{}.{}",a,b).parse::<f64>().unwrap();
287  let mut exp_f64: f64 = format!("{}.{}",c,d).parse::<f64>().unwrap();
288  if *sign {
289    exp_f64 = -exp_f64;
290  }
291  let num = num_f64 * 10f64.powf(exp_f64);
292  Value::F64(Ref::new(num))
293}
294
295#[cfg(feature = "floats")]
296pub fn float(flt: &(Token,Token)) -> Value {
297  let a = flt.0.chars.iter().collect::<String>();
298  let b = flt.1.chars.iter().collect::<String>();
299  let num: f64 = format!("{}.{}",a,b).parse::<f64>().unwrap();
300  Value::F64(Ref::new(num))
301}
302
303#[cfg(feature = "f64")]
304pub fn integer(int: &Token) -> Value {
305  let num: f64 = int.chars.iter().collect::<String>().parse::<f64>().unwrap();
306  Value::F64(Ref::new(num))
307}
308
309#[cfg(feature = "string")]
310pub fn string(tkn: &MechString) -> Value {
311  let strng: String = tkn.text.chars.iter().collect::<String>();
312  Value::String(Ref::new(strng))
313}
314
315pub fn empty() -> Value {
316  Value::Empty
317}
318
319#[cfg(feature = "bool")]
320pub fn boolean(tkn: &Token) -> Value {
321  let val = match tkn.kind {
322    TokenKind::True => true,
323    TokenKind::False => false,
324    _ => unreachable!(),
325  };
326  Value::Bool(Ref::new(val))
327}
328
329#[derive(Debug, Clone)]
330pub struct ExpectedNumericForKindSizeError;
331impl MechErrorKind for ExpectedNumericForKindSizeError {
332  fn name(&self) -> &str {
333    "ExpectedNumericForKindSize"
334  }
335  fn message(&self) -> String {
336    "Expected a numeric value for kind size, but received a non-numeric value.".to_string()
337  }
338}