umka-sys 0.1.0

low level FFI bindings for umka
Documentation
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(clippy::pub_underscore_fields)]
#![allow(clippy::unreadable_literal)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));

#[cfg(test)]
mod tests {
    use std::{
        ffi::CStr,
        mem::zeroed,
        ptr::{null, null_mut},
    };

    use super::*;

    fn error_msg(umka: *mut tagUmka) -> String {
        unsafe {
            let err = *umkaGetError(umka);
            if err.msg.is_null() {
                return "(no umka error)".to_string();
            }
            let fname = CStr::from_ptr(err.fileName).to_string_lossy();
            let msg = CStr::from_ptr(err.msg).to_string_lossy();
            format!("{}:{} {}", fname, err.line, msg)
        }
    }

    #[test]
    fn compile_and_run() {
        unsafe {
            let umka = umkaAlloc();
            let ok = umkaInit(
                umka,
                c"compile_and_run.um".as_ptr(),
                c"fn main() { printf(\"hello world!\") }".as_ptr(),
                4096,
                null_mut(),
                0,
                null_mut(),
                false,
                false,
                None,
            );
            assert!(ok, "umkaInit failed: {}", error_msg(umka));

            let ok = umkaCompile(umka);
            assert!(ok, "umkaCompile failed: {}", error_msg(umka));

            let code = umkaRun(umka);
            assert_eq!(
                code,
                0,
                "umkaRun exited with code {code}: {}",
                error_msg(umka)
            );

            umkaFree(umka);
        }
    }

    #[test]
    fn compile_and_call_function() {
        let src = c"
            fn add(a: int, b: int): int {
                return a + b
            }
        ";
        unsafe {
            let umka = umkaAlloc();
            let ok = umkaInit(
                umka,
                c"compile_and_call_function.um".as_ptr(),
                src.as_ptr(),
                4096,
                null_mut(),
                0,
                null_mut(),
                false,
                false,
                None,
            );
            assert!(ok, "umkaInit failed: {}", error_msg(umka));

            let ok = umkaCompile(umka);
            assert!(ok, "umkaCompile failed: {}", error_msg(umka));

            let mut add_fn: UmkaFuncContext = zeroed();
            let ok = umkaGetFunc(umka, null(), c"add".as_ptr(), &mut add_fn);
            assert!(ok, "umkaGetFunc(add) failed: {}", error_msg(umka));

            (*umkaGetParam(add_fn.params, 0)).intVal = 3;
            (*umkaGetParam(add_fn.params, 1)).intVal = 7;
            let ok = umkaCall(umka, &mut add_fn);
            assert_eq!(ok, 0, "umkaCall failed: {}", error_msg(umka));
            let ret = (*add_fn.result).intVal;
            assert_eq!(ret, 10, "add(3, 7)");

            umkaFree(umka);
        }
    }
}