roan_engine/natives/
mod.rs1use crate::{
2 module::StoredFunction,
3 natives::{
4 debug::{__eprint, __format, __print},
5 process::{__abort, __exit, __pid},
6 },
7 value::Value,
8 vm::native_fn::{NativeFunction, NativeFunctionParam},
9};
10use std::{panic, panic::panic_any};
11
12pub mod debug;
13mod process;
14
15#[macro_export]
16macro_rules! native_function {
17 (fn $name:ident($($arg:ident),* $(, ...$rest:ident)?) {$($body:tt)*}) => {
18 #[allow(unused_mut, unused_variables)]
19 pub fn $name() -> NativeFunction {
20 NativeFunction {
21 name: stringify!($name).to_string(),
22 func: |args| {
23 let mut args_iter = args.into_iter();
24 $(
25 let $arg = match args_iter.next() {
26 Some(value) => value,
27 None => panic!("Expected argument but got None"),
28 };
29 )*
30
31 $(
32 let $rest = args_iter.collect::<Vec<Value>>();
33 )?
34
35 $($body)*
36 },
37 params: vec![
38 $(
39 NativeFunctionParam {
40 name: stringify!($arg).to_string(),
41 ty: "Value".to_string(),
42 is_rest: false,
43 },
44 )*
45 $(
46 NativeFunctionParam {
47 name: stringify!($rest).to_string(),
48 ty: "Vec<Value>".to_string(),
49 is_rest: true,
50 },
51 )?
52 ],
53 }
54 }
55 };
56}
57
58#[macro_export]
59macro_rules! as_cast {
60 ($val:expr, $ty:ident) => {
61 match $val {
62 Value::$ty(val) => val,
63 _ => panic!("Expected {} but got {:?}", stringify!($ty), $val),
65 }
66 };
67}
68
69native_function!(
70 fn type_of(value) {
71 Value::String(value.type_name())
72 }
73);
74
75native_function!(
76 fn __panic(msg) {
77 let msg = as_cast!(msg, String);
78
79 let old_hook = std::panic::take_hook();
81
82 panic::set_hook(Box::new(|panic_info| {
83 let payload = panic_info.payload().downcast_ref::<String>().unwrap();
84 eprintln!("program panicked");
85 eprintln!("{}", payload);
86 }));
87
88 panic_any(msg);
89
90 panic::set_hook(old_hook);
92
93 Value::Void
94 }
95);
96
97pub fn get_stored_function() -> Vec<StoredFunction> {
98 vec![
99 __print(),
100 __format(),
101 __eprint(),
102 __exit(),
103 __abort(),
104 __pid(),
105 type_of(),
106 __panic(),
107 ]
108 .into_iter()
109 .map(|f| StoredFunction::Native(f))
110 .collect()
111}