Skip to content

Commit

Permalink
Reworking metta_t for API consistency
Browse files Browse the repository at this point in the history
  • Loading branch information
luketpeterson committed Aug 13, 2023
1 parent 2380440 commit 6b45567
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 62 deletions.
3 changes: 2 additions & 1 deletion c/hyperonc.doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,8 @@ EXCLUDE_SYMBOLS = tag \
RustSpaceCommonData \
RustTokenizer \
RustSExprParser \
RustStepResult
RustStepResult \
RustMettaInterpreter

# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
Expand Down
59 changes: 46 additions & 13 deletions c/src/metta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,42 +447,75 @@ pub extern "C" fn step_get_result(step: step_result_t,
}
}

pub type metta_t = SharedApi<Metta>;
/// @brief A handle to a top-level MeTTa Interpreter
/// @ingroup interpreter_group
/// @note A `metta_t` must be freed with `metta_free()`
/// @see metta_new
/// @see metta_free
///
#[repr(C)]
pub struct metta_t {
/// Internal. Should not be accessed directly
metta: *const RustMettaInterpreter,
}

struct RustMettaInterpreter(std::cell::RefCell<Metta>);

impl From<Shared<Metta>> for metta_t {
fn from(metta: Shared<Metta>) -> Self {
Self{ metta: std::rc::Rc::into_raw(metta.0).cast() }
}
}

impl metta_t {
fn borrow_inner(&self) -> &mut Metta {
let cell = unsafe{ &mut *(&(&*self.metta).0 as *const std::cell::RefCell<Metta>).cast_mut() };
cell.get_mut()
}
fn clone_handle(&self) -> Shared<Metta> {
unsafe{ std::rc::Rc::increment_strong_count(self.metta); }
unsafe{ Shared(std::rc::Rc::from_raw(self.metta.cast())) }
}
fn into_handle(self) -> Shared<Metta> {
unsafe{ Shared(std::rc::Rc::from_raw(self.metta.cast())) }
}
}

#[no_mangle]
pub extern "C" fn metta_new(space: *mut space_t, tokenizer: *mut tokenizer_t, cwd: *const c_char) -> *mut metta_t {
pub extern "C" fn metta_new(space: *mut space_t, tokenizer: *mut tokenizer_t, cwd: *const c_char) -> metta_t {
let dyn_space = unsafe{ &*space }.borrow();
let tokenizer = unsafe{ &*tokenizer }.clone_handle();
metta_t::new(Metta::from_space_cwd(dyn_space.clone(), tokenizer, PathBuf::from(cstr_as_str(cwd))))
let metta = Metta::from_space_cwd(dyn_space.clone(), tokenizer, PathBuf::from(cstr_as_str(cwd)));
Shared::new(metta).into()
}

#[no_mangle]
pub extern "C" fn metta_clone(metta: *mut metta_t) -> *mut metta_t {
let metta = unsafe{ &(*metta) };
metta_t::from_shared(metta.shared())
pub extern "C" fn metta_clone_handle(metta: *const metta_t) -> metta_t {
unsafe{ &*metta }.clone_handle().into()
}

#[no_mangle]
pub extern "C" fn metta_free(metta: *mut metta_t) {
metta_t::drop(metta);
pub extern "C" fn metta_free(metta: metta_t) {
let metta = metta.into_handle();
drop(metta);
}

#[no_mangle]
pub extern "C" fn metta_space(metta: *mut metta_t) -> space_t {
let space = unsafe{ &*metta }.borrow().space();
let space = unsafe{ &*metta }.borrow_inner().space();
space.into()
}

#[no_mangle]
pub extern "C" fn metta_tokenizer(metta: *mut metta_t) -> tokenizer_t {
let tokenizer = unsafe{ &*metta }.borrow().tokenizer();
let tokenizer = unsafe{ &*metta }.borrow_inner().tokenizer();
tokenizer.into()
}

#[no_mangle]
pub extern "C" fn metta_run(metta: *mut metta_t, parser: *mut sexpr_parser_t,
output: c_atom_vec_callback_t, out_context: *mut c_void) {
let metta = unsafe{ &*metta }.borrow();
let metta = unsafe{ &*metta }.borrow_inner();
let mut parser = unsafe{ &*parser }.borrow_inner();
let results = metta.run(&mut parser);
// TODO: return erorrs properly after step_get_result() is changed to return errors.
Expand All @@ -494,7 +527,7 @@ pub extern "C" fn metta_run(metta: *mut metta_t, parser: *mut sexpr_parser_t,
#[no_mangle]
pub extern "C" fn metta_evaluate_atom(metta: *mut metta_t, atom: atom_t,
output: c_atom_vec_callback_t, out_context: *mut c_void) {
let metta = unsafe{ &*metta }.borrow();
let metta = unsafe{ &*metta }.borrow_inner();
let atom = atom.into_inner();
let result = metta.evaluate_atom(atom)
.expect("Returning errors from C API is not implemented yet");
Expand All @@ -503,7 +536,7 @@ pub extern "C" fn metta_evaluate_atom(metta: *mut metta_t, atom: atom_t,

#[no_mangle]
pub extern "C" fn metta_load_module(metta: *mut metta_t, name: *const c_char) {
let metta = unsafe{ &*metta }.borrow();
let metta = unsafe{ &*metta }.borrow_inner();
// TODO: return erorrs properly
metta.load_module(PathBuf::from(cstr_as_str(name)))
.expect("Returning errors from C API is not implemented yet");
Expand Down
2 changes: 1 addition & 1 deletion c/src/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub extern "C" fn space_free(space: space_t) {
/// @note The caller must take ownership responsibility for the returned `space_t`, and free it with `space_free()`
///
#[no_mangle]
pub extern "C" fn space_clone_ref(space: *const space_t) -> *mut space_t {
pub extern "C" fn space_clone_handle(space: *const space_t) -> *mut space_t {
let space = unsafe { &(*space).space };
Box::into_raw(Box::new(space_t{ space: space.clone() }))
}
Expand Down
39 changes: 0 additions & 39 deletions c/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ use std::io::{Cursor, Write};
use std::ffi::CString;
use std::os::raw::c_char;
use std::ffi::CStr;
use hyperon::common::shared::Shared;
use std::ops::{Deref, DerefMut};

pub fn cstr_as_str<'a>(s: *const c_char) -> &'a str {
unsafe{ CStr::from_ptr(s) }.to_str().expect("Incorrect UTF-8 sequence")
Expand Down Expand Up @@ -72,40 +70,3 @@ pub(crate) fn write_debug_into_buf<T: std::fmt::Debug>(obj: T, buf: *mut c_char,
}
write_into_buf(DisplayDebug(obj), buf, buf_len)
}

// We cannot use imported Shared in C API because it is not correctly
// converted int C header and header cannot be compiled. This wrapper just
// solves the issue by shadowing original type.
pub struct SharedApi<T>(pub(crate) Shared<T>);

impl<T> SharedApi<T> {
pub fn new(value: T) -> *mut Self {
Box::into_raw(Box::new(Self(Shared::new(value))))
}

pub fn from_shared(shared: Shared<T>) -> *mut Self {
Box::into_raw(Box::new(Self(shared)))
}

pub fn drop(ptr: *mut Self) {
unsafe { drop(Box::from_raw(ptr)) }
}

pub fn borrow(&self) -> Box<dyn Deref<Target=T> + '_> {
self.0.borrow()
}

pub fn borrow_mut(&mut self) -> Box<dyn DerefMut<Target=T> + '_> {
self.0.borrow_mut()
}

pub fn shared(&self) -> Shared<T> {
self.0.clone()
}
}

impl<T> PartialEq for SharedApi<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
16 changes: 8 additions & 8 deletions python/hyperonpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ using CBindingsSet = CStruct<bindings_set_t>;
using CSpace = CStruct<space_t>;
using CTokenizer = CStruct<tokenizer_t>;
using CStepResult = CStruct<step_result_t>;
using CMetta = CPtr<metta_t>;
using CMetta = CStruct<metta_t>;

// Returns a string, created by executing a function that writes string data into a buffer
typedef size_t (*write_to_buf_func_t)(void*, char*, size_t);
Expand Down Expand Up @@ -680,23 +680,23 @@ PYBIND11_MODULE(hyperonpy, m) {
m.def("metta_new", [](CSpace space, CTokenizer tokenizer, char const* cwd) {
return CMetta(metta_new(space.ptr(), tokenizer.ptr(), cwd));
}, "New MeTTa interpreter instance");
m.def("metta_free", [](CMetta metta) { metta_free(metta.ptr); }, "Free MeTTa interpreter");
m.def("metta_clone", [](CMetta metta) { metta_clone(metta.ptr); }, "Clone MeTTa interpreter");
m.def("metta_space", [](CMetta metta) { return CSpace(metta_space(metta.ptr)); }, "Get space of MeTTa interpreter");
m.def("metta_tokenizer", [](CMetta metta) { return CTokenizer(metta_tokenizer(metta.ptr)); }, "Get tokenizer of MeTTa interpreter");
m.def("metta_free", [](CMetta metta) { metta_free(metta.obj); }, "Free MeTTa interpreter");
m.def("metta_clone", [](CMetta metta) { metta_clone_handle(metta.ptr()); }, "Clone MeTTa interpreter");
m.def("metta_space", [](CMetta metta) { return CSpace(metta_space(metta.ptr())); }, "Get space of MeTTa interpreter");
m.def("metta_tokenizer", [](CMetta metta) { return CTokenizer(metta_tokenizer(metta.ptr())); }, "Get tokenizer of MeTTa interpreter");
m.def("metta_run", [](CMetta metta, CSExprParser& parser) {
py::list lists_of_atom;
metta_run(metta.ptr, &parser.parser, copy_lists_of_atom, &lists_of_atom);
metta_run(metta.ptr(), &parser.parser, copy_lists_of_atom, &lists_of_atom);
return lists_of_atom;
}, "Run MeTTa interpreter on an input");
m.def("metta_evaluate_atom", [](CMetta metta, CAtom atom) {
py::list atoms;
metta_evaluate_atom(metta.ptr, atom_clone(atom.ptr()), copy_atoms, &atoms);
metta_evaluate_atom(metta.ptr(), atom_clone(atom.ptr()), copy_atoms, &atoms);
return atoms;
}, "Run MeTTa interpreter on an atom");

m.def("metta_load_module", [](CMetta metta, std::string text) {
metta_load_module(metta.ptr, text.c_str());
metta_load_module(metta.ptr(), text.c_str());
}, "Load MeTTa module");

}
Expand Down

0 comments on commit 6b45567

Please sign in to comment.