main.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. use std::ffi::{CString,CStr};
  2. use std::mem::MaybeUninit;
  3. mod wren;
  4. pub struct Config {
  5. config: wren::WrenConfiguration,
  6. }
  7. pub struct VM {
  8. vm: *mut wren::WrenVM,
  9. }
  10. impl Config {
  11. fn init() -> Config {
  12. extern "C" fn write_fn(_vm: *mut wren::WrenVM, text: *const i8) {
  13. let s = unsafe { CStr::from_ptr(text) };
  14. print!("{}", s.to_str().unwrap());
  15. }
  16. unsafe {
  17. let mut config = MaybeUninit::uninit();
  18. wren::wrenInitConfiguration(config.as_mut_ptr());
  19. let mut config = config.assume_init();
  20. config.writeFn = Some(write_fn);
  21. Config { config: config }
  22. }
  23. }
  24. fn mk_vm(&mut self) -> VM {
  25. let vm = unsafe { wren::wrenNewVM(&mut self.config as *mut _) };
  26. VM { vm }
  27. }
  28. }
  29. impl VM {
  30. fn interpret(&self, module: &str, code: &str) -> bool {
  31. let mod_str = CString::new(module).unwrap();
  32. let code_str = CString::new(code).unwrap();
  33. let result = unsafe { wren::wrenInterpret(self.vm, mod_str.as_ptr(), code_str.as_ptr()) };
  34. result == 0
  35. }
  36. fn ensure_slots(&self, n: i32) {
  37. unsafe { wren::wrenEnsureSlots(self.vm, n) }
  38. }
  39. fn call_handle(&self, sig: &str) -> Option<Handle> {
  40. unsafe {
  41. let sig_str = CString::new(sig).unwrap();
  42. let handle = wren::wrenMakeCallHandle(self.vm, sig_str.as_ptr());
  43. if handle.is_null() {
  44. None
  45. } else {
  46. Some(Handle { handle, vm: self })
  47. }
  48. }
  49. }
  50. }
  51. impl Drop for VM {
  52. fn drop(&mut self) {
  53. unsafe { wren::wrenFreeVM(self.vm) }
  54. }
  55. }
  56. struct Handle<'a> {
  57. vm: &'a VM,
  58. handle: *mut wren::WrenHandle,
  59. }
  60. impl<'t> Handle<'t> {
  61. fn call(&self, args: &[&dyn WrenValue]) {
  62. self.vm.ensure_slots(args.len() as i32);
  63. for (i, v) in args.iter().enumerate() {
  64. v.set_slot(&self.vm, i as i32);
  65. }
  66. unsafe {
  67. wren::wrenCall(self.vm.vm, self.handle);
  68. }
  69. }
  70. }
  71. impl<'t> Drop for Handle<'t> {
  72. fn drop(&mut self) {
  73. unsafe { wren::wrenReleaseHandle(self.vm.vm, self.handle) }
  74. }
  75. }
  76. fn c_str(s: &str) -> CString {
  77. CString::new(s).unwrap()
  78. }
  79. trait WrenValue {
  80. // fn get_slot(vm: &VM, slot: i32) -> Self;
  81. fn set_slot(&self, vm: &VM, slot: i32);
  82. }
  83. impl WrenValue for String {
  84. fn set_slot(&self, vm: &VM, slot: i32) {
  85. unsafe {
  86. wren::wrenSetSlotString(vm.vm, slot, c_str(self).as_ptr())
  87. }
  88. }
  89. }
  90. struct Var {
  91. module: &'static str,
  92. name: &'static str,
  93. }
  94. impl WrenValue for Var {
  95. fn set_slot(&self, vm: &VM, slot: i32) {
  96. unsafe {
  97. wren::wrenGetVariable(vm.vm, c_str(self.module).as_ptr(), c_str(self.name).as_ptr(), slot);
  98. }
  99. }
  100. }
  101. fn main() {
  102. let vm = Config::init().mk_vm();
  103. vm.interpret("main", "class Foo { static hello(name) { System.print(\"what's up, %(name)\") } }");
  104. let hello = vm.call_handle("hello(_)").unwrap();
  105. hello.call(&[
  106. &Var { module: "main", name: "Foo" },
  107. &format!("my dog"),
  108. ]);
  109. }