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