resynth 0.4.0

A packet synthesis language
Documentation
extern crate concat_with;

#[macro_export]
macro_rules! func {
    (@as_expr $e:expr) => {$e};
    (@replace $_t:tt $sub:expr) => {$sub};
    (@len $($tt:tt)*) => {{<[()]>::len(&[$(func!(@replace $tt ())),*])}};

    (
        @pdecl $type:ident
    ) => {
        ArgDecl::Positional(ValType::$type)
    };

    (
        @odecl $type:ident $init:expr
    ) => {
        ArgDecl::Optional(func!(@as_expr ValDef::$type($init)))
    };

    (
        @pos $name:ident $type:ident
    ) => {
        ArgDesc {
            name: stringify!($name),
            typ: func!(@pdecl $type),
        }
    };

    (
        @opt $name:ident $type:ident $init:expr
    ) => {
        ArgDesc {
            name: stringify!($name),
            typ: func!(@odecl $type $init),
        }
    };

    (
        $(#[doc = $doc:literal])+
        resynth fn $name:ident
        (
            $($arg_name:ident : $arg_type:ident),* $(,)*
            =>
            $($dfl_name:ident : $dfl_type:ident = $dfl_init:expr),* $(,)*
            =>
            $collect_type:ident
        ) -> $return_type:ident
        $exec:expr
    ) => {
        {
            #[allow(unused)]
            use $crate::libapi::{FuncDef, ArgDesc, ArgDecl};
            #[allow(unused)]
            use $crate::val::ValType;

            #[allow(non_camel_case_types,unused)]
            enum ArgName {
               $($arg_name,)*
               $($dfl_name,)*
            }

            fn arg_pos(name: &str) -> Option<usize> {
                match name {
                    $(stringify!($arg_name) => Some(ArgName::$arg_name as usize),)*
                    $(stringify!($dfl_name) => Some(ArgName::$dfl_name as usize),)*
                    _ => None,
                }
            }

            FuncDef {
                name: stringify!($name),
                return_type: ValType::$return_type,
                args: &[
                    $(func!(@pos $arg_name $arg_type),)*
                    $(func!(@opt $dfl_name $dfl_type $dfl_init),)*
                ],
                arg_pos,
                min_args: func!(@len $($arg_name)*),
                collect_type: ValType::$collect_type,
                exec: $exec,
                doc: concat_with::concat_line!($($doc),+),
            }
        }
    };
}

#[macro_export]
macro_rules! module {
    (
        @sym $name:ident $sym:expr
    ) => {
        SymDesc {
            name: stringify!($name),
            sym: $sym,
        }
    };

    (
        $(#[doc = $doc:literal])+
        resynth mod $modname:ident {$(
            $name:ident => $sym:expr,
        )*}
    ) => {
        {
            #[allow(unused)]
            use $crate::libapi::{Module, SymDesc};

            #[allow(non_camel_case_types,unused)]
            enum SymName {
               $($name,)*
            }

            fn lookup(name: &str) -> Option<usize> {
                match name {
                    $(stringify!($name) => Some(SymName::$name as usize),)*
                    _ => None,
                }
            }

            Module {
                name: stringify!($modname),
                symtab: &[
                    $(module!(@sym $name $sym),)*
                ],
                lookup,
                doc: concat_with::concat_line!($($doc),+),
            }
        }
    };
}

#[macro_export]
macro_rules! class {
    (
        @sym $name:ident $sym:expr
    ) => {
        SymDesc {
            name: stringify!($name),
            sym: $sym,
        }
    };

    (
        $(#[doc = $doc:literal])+
        resynth class $modname:ident {$(
            $name:ident => $sym:expr,
        )*}
    ) => {
        {
            #[allow(unused)]
            use $crate::libapi::{ClassDef, SymDesc};

            #[allow(non_camel_case_types,unused)]
            enum MethodName {
               $($name,)*
            }

            fn lookup(name: &str) -> Option<usize> {
                match name {
                    $(stringify!($name) => Some(MethodName::$name as usize),)*
                    _ => None,
                }
            }

            ClassDef {
                name: stringify!($modname),
                symtab: &[
                    $(class!(@sym $name $sym),)*
                ],
                lookup,
                doc: concat_with::concat_line!($($doc),+),
            }
        }
    };
}

#[macro_export]
macro_rules! ok {
    ($st:expr, $fmt:expr $(, $($arg:expr),*)*) => {{
        $st.set_color(ColorSpec::new()
            .set_fg(Some(Color::Green))
            .set_bold(true)
            .set_intense(true)
        ).unwrap();
        let ret = print!($fmt, $($arg),*);
        $st.set_color(&ColorSpec::default()).unwrap();
        ret
    }
}}

#[macro_export]
macro_rules! warn {
    ($st:expr, $fmt:expr $(, $($arg:expr),*)*) => {{
        $st.set_color(ColorSpec::new()
            .set_fg(Some(Color::Yellow))
            .set_bold(true)
            .set_intense(true)
        ).unwrap();
        let ret = print!($fmt, $($arg),*);
        $st.set_color(&ColorSpec::default()).unwrap();
        ret
    }
}}

#[macro_export]
macro_rules! error {
    ($st:expr, $fmt:expr $(, $($arg:expr),*)*) => {{
        $st.set_color(ColorSpec::new()
            .set_fg(Some(Color::Red))
            .set_bold(true)
            .set_intense(true)
        ).unwrap();
        let ret = print!($fmt, $($arg),*);
        $st.set_color(&ColorSpec::default()).unwrap();
        ret
    }
}}

#[macro_export]
macro_rules! notice {
    ($st:expr, $fmt:expr $(, $($arg:expr),*)*) => {{
        $st.set_color(ColorSpec::new()
            .set_bold(true)
            .set_intense(true)
        ).unwrap();
        let ret = print!($fmt, $($arg),*);
        $st.set_color(&ColorSpec::default()).unwrap();
        ret
    }}
}