#![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);
}
}
}