1use crate::ast::statements::TypeAnnotation;
25use crate::interpreter::evaluator::Evaluator;
26use crate::interpreter::values::Value;
27use crate::utils::errors::{Error, Reason};
28use crate::utils::span::Span;
29use std::collections::HashMap;
30use std::sync::Arc;
31
32pub type NativeFn =
34 Arc<dyn Fn(&mut Evaluator, Vec<Value>, Span) -> Result<Value, Error> + Send + Sync>;
35
36pub struct Module {
38 pub name: String,
40 pub functions: HashMap<String, NativeFn>,
42 pub submodules: HashMap<String, Module>,
44}
45
46impl Module {
47 pub fn new(name: impl Into<String>) -> Self {
48 Self {
49 name: name.into(),
50 functions: HashMap::new(),
51 submodules: HashMap::new(),
52 }
53 }
54
55 pub fn with_function<F, A>(mut self, name: impl Into<String>, f: F) -> Self
57 where
58 F: IntoNativeFn<A>,
59 {
60 self.functions.insert(name.into(), f.into_native());
61 self
62 }
63
64 pub fn with_raw_function<F>(mut self, name: impl Into<String>, f: F) -> Self
67 where
68 F: Fn(&mut Evaluator, Vec<Value>, Span) -> Result<Value, Error> + Send + Sync + 'static,
69 {
70 self.functions.insert(name.into(), Arc::new(f));
71 self
72 }
73
74 pub fn with_module(mut self, m: Module) -> Self {
76 self.submodules.insert(m.name.clone(), m);
77 self
78 }
79
80 pub fn resolve(&self, path: &[String]) -> Option<&NativeFn> {
83 if path.is_empty() {
84 return None;
85 }
86 let mut module = self;
87 for seg in &path[..path.len() - 1] {
88 module = module.submodules.get(seg)?;
89 }
90 module.functions.get(&path[path.len() - 1])
91 }
92}
93
94pub trait ValueType {
97 fn type_annotation() -> TypeAnnotation;
98}
99
100impl ValueType for i64 {
101 fn type_annotation() -> TypeAnnotation {
102 TypeAnnotation::Int
103 }
104}
105
106impl ValueType for f64 {
107 fn type_annotation() -> TypeAnnotation {
108 TypeAnnotation::Float
109 }
110}
111
112impl ValueType for String {
113 fn type_annotation() -> TypeAnnotation {
114 TypeAnnotation::String
115 }
116}
117
118impl ValueType for bool {
119 fn type_annotation() -> TypeAnnotation {
120 TypeAnnotation::Bool
121 }
122}
123
124impl ValueType for char {
125 fn type_annotation() -> TypeAnnotation {
126 TypeAnnotation::Char
127 }
128}
129
130impl<T: ValueType> ValueType for Vec<T> {
131 fn type_annotation() -> TypeAnnotation {
132 TypeAnnotation::Array(Box::new(T::type_annotation()))
133 }
134}
135
136pub trait FromValue: Sized {
139 fn from_value(v: Value, span: Span) -> Result<Self, Error>;
140}
141
142impl FromValue for Value {
143 fn from_value(v: Value, _span: Span) -> Result<Self, Error> {
144 Ok(v)
145 }
146}
147
148impl FromValue for i64 {
149 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
150 match v {
151 Value::Integer(i) => Ok(i),
152 Value::Byte(b) => Ok(b as i64),
153 other => Err(Error::at(
154 Reason::Runtime,
155 format!("expected integer, got {}", other.type_name()),
156 span,
157 )),
158 }
159 }
160}
161
162impl FromValue for f64 {
163 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
164 match v {
165 Value::Float(f) => Ok(f),
166 other => Err(Error::at(
167 Reason::Runtime,
168 format!("expected float, got {}", other.type_name()),
169 span,
170 )),
171 }
172 }
173}
174
175impl FromValue for String {
176 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
177 match v {
178 Value::String(s) => Ok(s),
179 other => Err(Error::at(
180 Reason::Runtime,
181 format!("expected string, got {}", other.type_name()),
182 span,
183 )),
184 }
185 }
186}
187
188impl FromValue for bool {
189 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
190 match v {
191 Value::Bool(b) => Ok(b),
192 other => Err(Error::at(
193 Reason::Runtime,
194 format!("expected bool, got {}", other.type_name()),
195 span,
196 )),
197 }
198 }
199}
200
201impl FromValue for char {
202 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
203 match v {
204 Value::Char(c) => Ok(c),
205 other => Err(Error::at(
206 Reason::Runtime,
207 format!("expected char, got {}", other.type_name()),
208 span,
209 )),
210 }
211 }
212}
213
214impl<T: FromValue> FromValue for Vec<T> {
215 fn from_value(v: Value, span: Span) -> Result<Self, Error> {
216 match v {
217 Value::Values { items, .. } => items
218 .into_iter()
219 .map(|item| T::from_value(item, span))
220 .collect(),
221 other => Err(Error::at(
222 Reason::Runtime,
223 format!("expected array, got {}", other.type_name()),
224 span,
225 )),
226 }
227 }
228}
229
230pub trait IntoValue {
233 fn into_value(self) -> Value;
234}
235
236impl IntoValue for Value {
237 fn into_value(self) -> Value {
238 self
239 }
240}
241
242impl IntoValue for () {
243 fn into_value(self) -> Value {
244 Value::Null
245 }
246}
247
248impl IntoValue for i64 {
249 fn into_value(self) -> Value {
250 Value::Integer(self)
251 }
252}
253
254impl IntoValue for f64 {
255 fn into_value(self) -> Value {
256 Value::Float(self)
257 }
258}
259
260impl IntoValue for String {
261 fn into_value(self) -> Value {
262 Value::String(self)
263 }
264}
265
266impl IntoValue for bool {
267 fn into_value(self) -> Value {
268 Value::Bool(self)
269 }
270}
271
272impl IntoValue for char {
273 fn into_value(self) -> Value {
274 Value::Char(self)
275 }
276}
277
278impl<T: IntoValue + ValueType> IntoValue for Vec<T> {
279 fn into_value(self) -> Value {
280 Value::Values {
281 items_type: T::type_annotation(),
282 items: self.into_iter().map(T::into_value).collect(),
283 }
284 }
285}
286
287pub trait IntoNativeFn<Args> {
290 fn into_native(self) -> NativeFn;
291}
292
293impl<F, R> IntoNativeFn<()> for F
294where
295 F: Fn(&mut Evaluator) -> R + Send + Sync + 'static,
296 R: IntoValue,
297{
298 fn into_native(self) -> NativeFn {
299 Arc::new(
300 move |rt: &mut Evaluator, args: Vec<Value>, span: Span| -> Result<Value, Error> {
301 if !args.is_empty() {
302 return Err(Error::at(
303 Reason::Runtime,
304 format!("expected 0 argument(s), got {}", args.len()),
305 span,
306 ));
307 }
308 Ok(self(rt).into_value())
309 },
310 )
311 }
312}
313
314pub struct Fallible<T>(std::marker::PhantomData<T>);
316
317macro_rules! impl_into_native_fn {
318 ($count:literal, $(($ty:ident, $var:ident)),+) => {
319 impl<F, R, $($ty),+> IntoNativeFn<($($ty,)+)> for F
320 where
321 F: Fn(&mut Evaluator, $($ty),+) -> R + Send + Sync + 'static,
322 R: IntoValue,
323 $($ty: FromValue),+
324 {
325 fn into_native(self) -> NativeFn {
326 Arc::new(move |rt: &mut Evaluator, args: Vec<Value>, span: Span| -> Result<Value, Error> {
327 if args.len() != $count {
328 return Err(Error::at(
329 Reason::Runtime,
330 format!("expected {} argument(s), got {}", $count, args.len()),
331 span, ));
332 }
333 let mut iter = args.into_iter();
334 $(let $var = <$ty>::from_value(iter.next().unwrap(), span)?;)+
335 Ok(self(rt, $($var),+).into_value())
336 })
337 }
338 }
339
340 impl<F, R, $($ty),+> IntoNativeFn<(Fallible<($($ty,)+)>,)> for F
341 where
342 F: Fn(&mut Evaluator, $($ty),+) -> Result<R, Error> + Send + Sync + 'static,
343 R: IntoValue,
344 $($ty: FromValue),+
345 {
346 fn into_native(self) -> NativeFn {
347 Arc::new(move |rt: &mut Evaluator, args: Vec<Value>, span: Span| -> Result<Value, Error> {
348 if args.len() != $count {
349 return Err(Error::at(
350 Reason::Runtime,
351 format!("expected {} argument(s), got {}", $count, args.len()),
352 span, ));
353 }
354 let mut iter = args.into_iter();
355 $(let $var = <$ty>::from_value(iter.next().unwrap(), span)?;)+
356 Ok(self(rt, $($var),+)?.into_value())
357 })
358 }
359 }
360 };
361}
362impl_into_native_fn!(1, (A1, a1));
363impl_into_native_fn!(2, (A1, a1), (A2, a2));
364impl_into_native_fn!(3, (A1, a1), (A2, a2), (A3, a3));
365impl_into_native_fn!(4, (A1, a1), (A2, a2), (A3, a3), (A4, a4));
366impl_into_native_fn!(5, (A1, a1), (A2, a2), (A3, a3), (A4, a4), (A5, a5));
367impl_into_native_fn!(
368 6,
369 (A1, a1),
370 (A2, a2),
371 (A3, a3),
372 (A4, a4),
373 (A5, a5),
374 (A6, a6)
375);
376impl_into_native_fn!(
377 7,
378 (A1, a1),
379 (A2, a2),
380 (A3, a3),
381 (A4, a4),
382 (A5, a5),
383 (A6, a6),
384 (A7, a7)
385);
386impl_into_native_fn!(
387 8,
388 (A1, a1),
389 (A2, a2),
390 (A3, a3),
391 (A4, a4),
392 (A5, a5),
393 (A6, a6),
394 (A7, a7),
395 (A8, a8)
396);
397impl_into_native_fn!(
398 9,
399 (A1, a1),
400 (A2, a2),
401 (A3, a3),
402 (A4, a4),
403 (A5, a5),
404 (A6, a6),
405 (A7, a7),
406 (A8, a8),
407 (A9, a9)
408);
409impl_into_native_fn!(
410 10,
411 (A1, a1),
412 (A2, a2),
413 (A3, a3),
414 (A4, a4),
415 (A5, a5),
416 (A6, a6),
417 (A7, a7),
418 (A8, a8),
419 (A9, a9),
420 (A10, a10)
421);
422
423pub struct Spanned<T>(std::marker::PhantomData<T>);
425
426macro_rules! impl_into_native_fn_spanned {
427 ($count:literal, $(($ty:ident, $var:ident)),+) => {
428 impl<F, R, $($ty),+> IntoNativeFn<(Spanned<($($ty,)+)>,)> for F
429 where
430 F: Fn(&mut Evaluator, $($ty),+, Span) -> Result<R, Error> + Send + Sync + 'static,
431 R: IntoValue,
432 $($ty: FromValue),+
433 {
434 fn into_native(self) -> NativeFn {
435 Arc::new(move |rt: &mut Evaluator, args: Vec<Value>, span: Span| -> Result<Value, Error> {
436 if args.len() != $count {
437 return Err(rt.err(
438 format!("expected {} argument(s), got {}", $count, args.len()),
439 span,
440 ));
441 }
442 let mut iter = args.into_iter();
443 $(let $var = <$ty>::from_value(iter.next().unwrap(), span)?;)+
444 Ok(self(rt, $($var),+, span)?.into_value())
445 })
446 }
447 }
448 };
449}
450
451impl_into_native_fn_spanned!(1, (A1, a1));
452impl_into_native_fn_spanned!(2, (A1, a1), (A2, a2));
453impl_into_native_fn_spanned!(3, (A1, a1), (A2, a2), (A3, a3));
454impl_into_native_fn_spanned!(4, (A1, a1), (A2, a2), (A3, a3), (A4, a4));
455impl_into_native_fn_spanned!(5, (A1, a1), (A2, a2), (A3, a3), (A4, a4), (A5, a5));
456impl_into_native_fn_spanned!(
457 6,
458 (A1, a1),
459 (A2, a2),
460 (A3, a3),
461 (A4, a4),
462 (A5, a5),
463 (A6, a6)
464);
465impl_into_native_fn_spanned!(
466 7,
467 (A1, a1),
468 (A2, a2),
469 (A3, a3),
470 (A4, a4),
471 (A5, a5),
472 (A6, a6),
473 (A7, a7)
474);
475impl_into_native_fn_spanned!(
476 8,
477 (A1, a1),
478 (A2, a2),
479 (A3, a3),
480 (A4, a4),
481 (A5, a5),
482 (A6, a6),
483 (A7, a7),
484 (A8, a8)
485);
486impl_into_native_fn_spanned!(
487 9,
488 (A1, a1),
489 (A2, a2),
490 (A3, a3),
491 (A4, a4),
492 (A5, a5),
493 (A6, a6),
494 (A7, a7),
495 (A8, a8),
496 (A9, a9)
497);
498impl_into_native_fn_spanned!(
499 10,
500 (A1, a1),
501 (A2, a2),
502 (A3, a3),
503 (A4, a4),
504 (A5, a5),
505 (A6, a6),
506 (A7, a7),
507 (A8, a8),
508 (A9, a9),
509 (A10, a10)
510);