Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
CICS-Oleg committed Feb 6, 2024
2 parents b42c1e0 + 7b73a4f commit a031c02
Show file tree
Hide file tree
Showing 18 changed files with 276 additions and 116 deletions.
17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[workspace]
members = [
"lib",
"c",
"repl",
]
resolver = "2"

[workspace.package]
version = "0.1.6"
edition = "2021"

[workspace.dependencies]
hyperon = { path = "./lib", version = "0.1.6" }
regex = "1.5.4"
log = "0.4.0"
env_logger = "0.8.4"
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,10 @@ python3 -m pip install pip==23.1.2

# Build and run

## Hyperon library
## Rust library and REPL

Build and test the library:
Build and test the Rust binaries:
```
cd ./lib
cargo build
cargo test
```

Expand All @@ -90,6 +88,12 @@ Run examples:
cargo run --example sorted_list
```

Run REPL:
```
cargo run --bin metta
```
You can also find executable at `./target/debug/metta`.

To enable logging during running tests or examples export `RUST_LOG`
environment variable:
```
Expand All @@ -103,10 +107,9 @@ cargo +nightly bench

Generate docs:
```
cd ./lib
cargo doc --no-deps
```
Docs can be found at `./lib/target/doc/hyperon/index.html`.
Docs can be found at `./target/doc/hyperon/index.html`.

## C and Python API

Expand Down
13 changes: 6 additions & 7 deletions c/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
[package]
name = "hyperonc"
version = "0.1.6"
authors = ["Vitaly Bogdanov <vsbogd@gmail.com>"]
edition = "2018"
version.workspace = true
edition.workspace = true

[dependencies]
hyperon = { path = "../lib/" }
regex = "1.5.4"
log = "0.4.0"
env_logger = "0.8.4"
hyperon = { workspace = true }
regex = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }

[lib]
name = "hyperonc"
Expand Down
22 changes: 20 additions & 2 deletions c/src/metta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ pub extern "C" fn tokenizer_register_token(tokenizer: *mut tokenizer_t,
let regex = Regex::new(cstr_as_str(regex)).unwrap();
let c_token = CToken{ context, api };
tokenizer.register_token(regex, move |token| {
let c_token = &c_token; //Be explicit we're capturing c_token, and not the pointers it contains
let constr = unsafe{ (&*c_token.api).construct_atom };
let atom = constr(str_as_cstr(token).as_ptr(), c_token.context);
atom.into_inner()
Expand Down Expand Up @@ -557,16 +558,33 @@ pub extern "C" fn atom_error_message(atom: *const atom_ref_t, buf: *mut c_char,
///
#[no_mangle] pub extern "C" fn ATOM_TYPE_GROUNDED_SPACE() -> atom_t { rust_type_atom::<DynSpace>().into() }

/// @brief Creates an atom used to indicate that an atom's type is a unit type.
/// @ingroup metta_language_group
/// @return The `atom_t` representing the atom
/// @note The returned `atom_t` must be freed with `atom_free()`
///
#[no_mangle] pub extern "C" fn ATOM_TYPE_UNIT() -> atom_t { hyperon::metta::UNIT_TYPE().into() }

/// @brief Creates a Symbol atom for the special MeTTa symbol used to indicate empty results
/// returned by function.
/// @ingroup metta_language_group
/// @return The `atom_t` representing the Void atom
/// @return The `atom_t` representing the Empty atom
/// @note The returned `atom_t` must be freed with `atom_free()`
///
#[no_mangle] pub extern "C" fn EMPTY_SYMBOL() -> atom_t {
#[no_mangle] pub extern "C" fn EMPTY_ATOM() -> atom_t {
hyperon::metta::EMPTY_SYMBOL.into()
}

/// @brief Creates an atom used to return from functions which are not
/// supposed to return results (print for example).
/// @ingroup metta_language_group
/// @return The `atom_t` representing the Unit atom
/// @note The returned `atom_t` must be freed with `atom_free()`
///
#[no_mangle] pub extern "C" fn UNIT_ATOM() -> atom_t {
hyperon::metta::UNIT_ATOM().into()
}

/// @brief Checks whether Atom `atom` has Type `typ` in context of `space`
/// @ingroup metta_language_group
/// @param[in] space A pointer to the `space_t` representing the space context in which to perform the check
Expand Down
11 changes: 5 additions & 6 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
[package]
name = "hyperon"
version = "0.1.6"
authors = ["Vitaly Bogdanov <vsbogd@gmail.com>"]
edition = "2021"
version.workspace = true
edition.workspace = true

[dependencies]
mopa = "0.2.2"
regex = "1.5.4"
log = "0.4.0"
env_logger = "0.8.4"
regex = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }
directories = "5.0.1" # For Environment to find platform-specific config location
smallvec = "1.10.0"
im = "15.1.0"
Expand Down
43 changes: 39 additions & 4 deletions lib/src/atom/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl Bindings {
self.bindings.remove(binding_id).atom
} else {
if binding.var == *var {
self.rename_binding(binding_id, var);
let _ = self.rename_binding(binding_id);
}
None
}
Expand All @@ -190,14 +190,15 @@ impl Bindings {
}
}

fn rename_binding(&mut self, binding_id: usize, old_var: &VariableAtom) {
fn rename_binding(&mut self, binding_id: usize) -> Result<(), ()> {
let binding = &mut self.bindings[binding_id];
let var = self.binding_by_var.iter()
.filter(|(v, i)| **i == binding.id && *v != old_var)
.filter(|(v, i)| **i == binding.id && **v != binding.var)
.map(|(v, _i)| v)
.next()
.expect("Unexpected state");
.ok_or(())?;
binding.var = var.clone();
Ok(())
}

fn move_binding_to_binding(&mut self, from_binding_id: usize, to_binding_id: usize) {
Expand Down Expand Up @@ -694,6 +695,11 @@ impl Bindings {
BindingsIter { bindings: self, delegate: self.binding_by_var.iter() }
}

/// An iterator visiting all variables in arbitrary order.
pub fn vars(&self) -> impl Iterator<Item=&VariableAtom> {
self.binding_by_var.keys()
}

fn into_vec_of_pairs(mut self) -> Vec<(VariableAtom, Atom)> {
let mut result = Vec::new();

Expand Down Expand Up @@ -1712,6 +1718,35 @@ mod test {
Ok(())
}

#[test]
fn bindings_retain_all() -> Result<(), &'static str> {
let mut bindings = Bindings::new()
.add_var_equality(&VariableAtom::new("a"), &VariableAtom::new("b"))?;
bindings.retain(|_| false);
assert!(bindings.is_empty());
Ok(())
}

#[test]
fn bindings_rename_binding() -> Result<(), &'static str> {
let a = &VariableAtom::new("a");
let b = &VariableAtom::new("b");
let mut bindings = Bindings::new().add_var_equality(a, b)?;
let binding_id = bindings.get_binding(a).unwrap().id;
assert_eq!(bindings.resolve(a), Some(Atom::Variable(a.clone())));
assert_eq!(bindings.resolve(b), Some(Atom::Variable(a.clone())));

assert_eq!(bindings.rename_binding(binding_id), Ok(()));
assert_eq!(bindings.resolve(a), Some(Atom::Variable(b.clone())));
assert_eq!(bindings.resolve(b), Some(Atom::Variable(b.clone())));

let mut bindings = Bindings::new().with_var_no_value(a);
let binding_id = bindings.get_binding(a).unwrap().id;
assert_eq!(bindings.rename_binding(binding_id), Err(()));
assert_eq!(bindings.resolve(a), Some(Atom::Variable(a.clone())));
Ok(())
}

#[ignore = "Unstable because HashMap doesn't guarantee the order of entries"]
#[test]
fn bindings_into_entries() -> Result<(), &'static str> {
Expand Down
Loading

0 comments on commit a031c02

Please sign in to comment.