Macro dome_cloomnik::register_modules[][src]

macro_rules! register_modules {
    { $ctx:expr, $($modules:tt)+ } => { ... };
}

Helper macro to register modules in Wren.

NOTE: Do NOT depend on destructors! They run nondeterministically when the GC thinks it's appropriate. Provide your users a close() method or similar mechanism to free resources! Destructors of foreign objects should be used solely for:

  1. Freeing memory owned by this type.
  2. Cleaning resources that has not been cleaned, probably forgotten by the Wren programmer.

Note that Rust's ownership system means that you may hold an object that its destructor will run even when it is already closed, and can even be deeply nested. To solve that, either:

  • Ensure that your objects won't get bad state if dropped twice. This usually mean some sort of guard in their destructor.
  • (Especially good if you do not have control over the element, or even it does not have a close() method at all, for example objects from the standard library:) Hold an Option<Object> instead of plain Object and set it to None in close(). This way, you run the destructor automatically, and the object won't be closed again.

Example

struct MyType;
impl MyType {
    fn new(_vm: &WrenVM) -> Self {
        MyType
    }
    fn foreign_subscript_setter(_vm: &mut WrenVM) {}
}
#[derive(Debug)]
struct MyOtherType(f64);
impl MyOtherType {
    fn construct(vm: &WrenVM) -> Self {
        MyOtherType(vm.get_slot_double(1))
    }
    fn foreign_method(&mut self, _vm: &mut WrenVM) {}
}
impl Drop for MyOtherType {
    fn drop(&mut self) {
        println!("MyOtherType's destructor: {:?}", self);
    }
}
mod non_foreign {
    pub(super) struct SomeOtherClass;
    impl SomeOtherClass {
        pub(super) fn foreign_getter(vm: &mut WrenVM) {}
    }
}
(register_modules! {
    ctx,
    module "my-module" {
        foreign class MyClass = new of MyType {
            "construct new() { }"
            foreign static [a, b]=(value) = foreign_subscript_setter
        }
        foreign class MyOtherClass is "MyClass" = construct of MyOtherType {
            "construct new(shouldBeDouble) { }"
            foreign method() = foreign_method
        }
        class SomeOtherClass = non_foreign::SomeOtherClass {
            r#"
            construct myConstructor(p1, p2) {
                _f1 = p1
                _f2 = p2
            }
            getter { "Wren code here" }
            "#
            foreign foreignGetter = foreign_getter
            "method() {
                System.print([1, 2, 3])
            }"
        }
    }
    module "my-second-module" {}
})?;