123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- use std::ffi::{CString,CStr};
- use std::mem::MaybeUninit;
- mod wren;
- pub struct Config {
- config: wren::WrenConfiguration,
- }
- pub struct VM {
- vm: *mut wren::WrenVM,
- }
- impl Config {
- fn init() -> Config {
- extern "C" fn write_fn(_vm: *mut wren::WrenVM, text: *const i8) {
- let s = unsafe { CStr::from_ptr(text) };
- print!("{}", s.to_str().unwrap());
- }
- unsafe {
- let mut config = MaybeUninit::uninit();
- wren::wrenInitConfiguration(config.as_mut_ptr());
- let mut config = config.assume_init();
- config.writeFn = Some(write_fn);
- Config { config: config }
- }
- }
- fn mk_vm(&mut self) -> VM {
- let vm = unsafe { wren::wrenNewVM(&mut self.config as *mut _) };
- VM { vm }
- }
- }
- impl VM {
- fn interpret(&self, module: &str, code: &str) -> bool {
- let mod_str = CString::new(module).unwrap();
- let code_str = CString::new(code).unwrap();
- let result = unsafe { wren::wrenInterpret(self.vm, mod_str.as_ptr(), code_str.as_ptr()) };
- result == 0
- }
- fn ensure_slots(&self, n: i32) {
- unsafe { wren::wrenEnsureSlots(self.vm, n) }
- }
- fn call_handle(&self, sig: &str) -> Option<Handle> {
- unsafe {
- let sig_str = CString::new(sig).unwrap();
- let handle = wren::wrenMakeCallHandle(self.vm, sig_str.as_ptr());
- if handle.is_null() {
- None
- } else {
- Some(Handle { handle, vm: self })
- }
- }
- }
- }
- impl Drop for VM {
- fn drop(&mut self) {
- unsafe { wren::wrenFreeVM(self.vm) }
- }
- }
- struct Handle<'a> {
- vm: &'a VM,
- handle: *mut wren::WrenHandle,
- }
- impl<'t> Handle<'t> {
- fn call(&self, args: &[&dyn WrenValue]) {
- self.vm.ensure_slots(args.len() as i32);
- for (i, v) in args.iter().enumerate() {
- v.set_slot(&self.vm, i as i32);
- }
- unsafe {
- wren::wrenCall(self.vm.vm, self.handle);
- }
- }
- }
- impl<'t> Drop for Handle<'t> {
- fn drop(&mut self) {
- unsafe { wren::wrenReleaseHandle(self.vm.vm, self.handle) }
- }
- }
- fn c_str(s: &str) -> CString {
- CString::new(s).unwrap()
- }
- trait WrenValue {
- // fn get_slot(vm: &VM, slot: i32) -> Self;
- fn set_slot(&self, vm: &VM, slot: i32);
- }
- impl WrenValue for String {
- fn set_slot(&self, vm: &VM, slot: i32) {
- unsafe {
- wren::wrenSetSlotString(vm.vm, slot, c_str(self).as_ptr())
- }
- }
- }
- struct Var {
- module: &'static str,
- name: &'static str,
- }
- impl WrenValue for Var {
- fn set_slot(&self, vm: &VM, slot: i32) {
- unsafe {
- wren::wrenGetVariable(vm.vm, c_str(self.module).as_ptr(), c_str(self.name).as_ptr(), slot);
- }
- }
- }
- fn main() {
- let vm = Config::init().mk_vm();
- vm.interpret("main", "class Foo { static hello(name) { System.print(\"what's up, %(name)\") } }");
- let hello = vm.call_handle("hello(_)").unwrap();
- hello.call(&[
- &Var { module: "main", name: "Foo" },
- &format!("my dog"),
- ]);
- }
|