1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
#[macro_export] macro_rules! dyon_macro_items { ($($x:item)+) => ($($x)+) } #[macro_export] macro_rules! dyon_fn_pop { ($rt:ident $arg:ident : $t:ty) => { let $arg: $t = try!($rt.pop()); }; ($rt:ident $arg:ident : $t:ty, $($args:tt : $ts:ty),+) => { dyon_fn_pop!($rt $($args: $ts),+); let $arg: $t = try!($rt.pop()); }; } #[macro_export] macro_rules! dyon_fn { (fn $name:ident () -> $rt:ty $b:block) => { #[allow(non_snake_case)] pub fn $name(rt: &mut $crate::Runtime) -> Result<(), String> { fn inner() -> $rt { $b } rt.push(inner()); Ok(()) } }; (fn $name:ident ($($arg:tt : $t:ty),+) -> $rt:ty $b:block) => { dyon_macro_items!{ #[allow(non_snake_case)] pub fn $name(rt: &mut $crate::Runtime) -> Result<(), String> { fn inner($($arg: $t),+) -> $rt { $b } dyon_fn_pop!(rt $($arg: $t),+); rt.push(inner($($arg),+)); Ok(()) } } }; (fn $name:ident () $b:block) => { #[allow(non_snake_case)] pub fn $name(_: &mut $crate::Runtime) -> Result<(), String> { fn inner() { $b } inner(); Ok(()) } }; (fn $name:ident ($($arg:tt : $t:ty),+) $b:block) => { dyon_macro_items!{ #[allow(non_snake_case)] pub fn $name(rt: &mut $crate::Runtime) -> Result<(), String> { fn inner($($arg: $t),+) { $b } dyon_fn_pop!(rt $($arg: $t),+); inner($($arg),+); Ok(()) } } }; } #[macro_export] macro_rules! dyon_obj { ($t:tt { $($f:tt),* }) => { dyon_macro_items!{ impl $crate::embed::PopVariable for $t { fn pop_var(rt: &$crate::Runtime, var: &$crate::Variable) -> Result<Self, String> { use dyon::embed::obj_field; let var = rt.resolve(var); if let &$crate::Variable::Object(ref obj) = var { Ok($t { $( $f: try!(obj_field(rt, obj, stringify!($f))) ),* }) } else { Err(rt.expected(var, stringify!($t))) } } } impl $crate::embed::PushVariable for $t { fn push_var(&self) -> $crate::Variable { use std::sync::Arc; use std::collections::HashMap; let mut obj: HashMap<_, $crate::Variable> = HashMap::new(); $( obj.insert(Arc::new(stringify!($f).into()), self.$f.push_var()) ;)* $crate::Variable::Object(Arc::new(obj)) } } } } }