aplang_lib/standard_library/
std_macros.rs

1#[macro_export]
2macro_rules! std_function {
3    ($location:expr => fn $name:ident ($($arg:ident:  Value $(:: $arg_type:ident)? $(<$ot:ty>)?),*) {$($body:tt)*}) => {
4        $location.insert(
5            String::from(stringify!($name)),
6            (std::rc::Rc::new($crate::interpreter::NativeProcedure {
7                name: String::from(stringify!($name)),
8                arity: $crate::arity!($($arg)*),
9                callable: |_interpreter: &mut $crate::interpreter::Interpreter,  args: &[$crate::interpreter::Value], args_toks: &[miette::SourceSpan], _source: std::sync::Arc<str>| {
10                    #[allow(unused_mut, unused_variables)]
11                    let mut iter = args.into_iter();
12                    #[allow(unused_mut)]
13                    let mut __iter_toks = iter.zip(args_toks.into_iter());
14
15                    $(
16                        let $arg = __iter_toks.next().unwrap();
17                        $crate::unwrap_arg_type!($arg => Value $(::$arg_type)? $(<$ot>)?, _interpreter, _source);
18                    )*
19
20                    $($body)*
21                }
22            }), None)
23        )
24    };
25}
26
27#[macro_export]
28macro_rules! arity {
29    ($arg:ident $($tail:tt)*) => {
30        1u8 + $crate::arity!($($tail)*)
31    };
32    () => {
33        0u8
34    };
35}
36
37#[macro_export]
38macro_rules! unwrap_arg_type {
39    ($value:ident => Value::Null, $interpreter:ident, $source:ident) => {
40        #[allow(unused_mut)]
41        let mut $value = match $value.0 {
42            $crate::interpreter::value::Value::Null => $crate::interpreter::Value::Null,
43            _ => return Err(
44                $crate::interpreter::errors::RuntimeError {
45                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
46                    span: *$value.1,
47                    message: "Invalid Argument Cast".to_string(),
48                    help: format!("Argument Value ({}) is not of type NULL", stringify!($value)),
49                    label: "This argument cannot be cast into null".to_string(),
50                }
51            )
52        }
53    };
54    ($value:ident => Value::Number, $interpreter:ident, $source:ident) => {
55        #[allow(unused_mut)]
56        let $crate::interpreter::Value::Number(mut $value) = $value.0.clone() else {
57            return Err(
58                $crate::interpreter::errors::RuntimeError {
59                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
60                    span: *$value.1,
61                    message: "Invalid Argument Cast".to_string(),
62                    help: format!("Argument Value ({}) is not of type NUMBER", stringify!($value)),
63                    label: "This argument cannot be cast into NUMBER".to_string(),
64                }
65            );
66       };
67    };
68    ($value:ident => Value::String, $interpreter:ident, $source:ident) => {
69        #[allow(unused_mut)]
70        let $crate::interpreter::Value::String(mut $value) = $value.0.clone() else {
71            return Err(
72                $crate::interpreter::errors::RuntimeError {
73                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
74                    span: *$value.1,
75                    message: "Invalid Argument Cast".to_string(),
76                    help: format!("Argument Value ({}) is not of type STRING", stringify!($value)),
77                    label: "This argument cannot be cast into STRING".to_string(),
78                }
79            );
80        };
81    };
82    ($value:ident => Value::Bool, $interpreter:ident, $source:ident) => {
83        #[allow(unused_mut)]
84        let $crate::interpreter::value::Value::Bool(mut $value) = $value.0.clone() else {
85            return Err(
86                $crate::interpreter::errors::RuntimeError {
87                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
88                    span: *$value.1,
89                    message: "Invalid Argument Cast".to_string(),
90                    help: format!("Argument Value ({}) is not of type BOOL", stringify!($value)),
91                    label: "This argument cannot be cast into BOOL".to_string(),
92                }
93            );
94        };
95    };
96    ($value:ident => Value::List, $interpreter:ident, $source:ident) => {
97        #[allow(unused_mut)]
98        let $crate::interpreter::Value::List(mut $value) = $value.0.clone() else {
99            return Err(
100                $crate::interpreter::errors::RuntimeError {
101                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
102                    span: *$value.1,
103                    message: "Invalid Argument Cast".to_string(),
104                    help: format!("Argument Value ({}) is not of type LIST<Value>", stringify!($value)),
105                    label: "This argument cannot be cast into LIST".to_string(),
106                }
107            );
108        };
109    };
110    ($value:ident => Value::NativeObject<$ot:ty>, $interpreter:ident, $source:ident) => {
111        
112        let __span = *$value.1;
113        #[allow(unused_mut)]
114        let $crate::interpreter::Value::NativeObject(mut $value) = $value.0.clone() else {
115            return Err(
116                $crate::interpreter::errors::RuntimeError {
117                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
118                    span: __span,
119                    message: "Invalid Argument Cast".to_string(),
120                    help: format!("Argument Value ({}) is not of type NATIVE_OBJECT<A>", stringify!($value)),
121                    label: "This argument cannot be cast into NATIVE_OBJECT".to_string(),
122                }
123            );
124        };
125        
126        /* we check to make sure it is the right struct instance */
127        if $value.as_ref().borrow().downcast_ref::<$ot>().is_none() {
128            return Err(
129                $crate::interpreter::errors::RuntimeError {
130                    named_source: miette::NamedSource::new($interpreter.get_file_path(), $source),
131                    span: __span,
132                    message: "Invalid NATIVE_OBJECT variety for function".to_string(),
133                    help: format!("THe function cannot accept this type"),
134                    label: "This argument is a NATIVE_OBJECT but not the correct variety".to_string(),
135                }
136            )
137        }
138    };
139    ($value:ident => Value, $interpreter:ident, $source:ident) => {
140        #[allow(unused_mut)]
141        let mut $value = $value.0;
142    };
143}
144
145#[macro_export]
146macro_rules! downcast {
147    ($any:ident => $ty:ty) => {
148        #[allow(clippy::mutable_key_type)]
149        let mut __any_ref = $any.as_ref().borrow_mut();
150        let $any =  __any_ref.downcast_mut::<$ty>().unwrap();
151    };
152}