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