Skip to content

Commit

Permalink
Merge branch 'main' of github.com:CICS-Oleg/hyperon-experimental into…
Browse files Browse the repository at this point in the history
… main
  • Loading branch information
CICS-Oleg committed Jan 29, 2024
2 parents 60d2ecd + 169da1d commit f650527
Show file tree
Hide file tree
Showing 22 changed files with 891 additions and 451 deletions.
17 changes: 17 additions & 0 deletions c/src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,23 @@ pub unsafe extern "C" fn atom_get_object(atom: *const atom_ref_t) -> *mut gnd_t
}
}

/// @brief Check if the atom refers to CGrounded object
/// @ingroup atom_group
/// @param[in] atom A pointer to an `atom_t` or an `atom_ref_t` to access
/// @return True if the atom_get_object can be used on this atom without panic
///
#[no_mangle]
pub unsafe extern "C" fn atom_is_cgrounded(atom: *const atom_ref_t) -> bool {
if let Atom::Grounded(ref g) = (&*atom).borrow() {
match (*g).as_any_ref().downcast_ref::<CGrounded>() {
Some(_g) => true,
None => false,
}
} else {
false
}
}

/// @brief Access the space wrapped inside a Grounded atom
/// @ingroup atom_group
/// @see atom_gnd_for_space
Expand Down
78 changes: 78 additions & 0 deletions c/src/metta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use hyperon::metta::interpreter;
use hyperon::metta::interpreter::InterpreterState;
use hyperon::metta::runner::{Metta, RunnerState, Environment, EnvBuilder};
use hyperon::rust_type_atom;
use hyperon::atom::*;
use hyperon::metta::runner::arithmetics::*;

use crate::util::*;
use crate::atom::*;
Expand Down Expand Up @@ -1393,3 +1395,79 @@ pub extern "C" fn env_builder_add_include_path(builder: *mut env_builder_t, path
*builder_arg_ref = builder.into();
}

/// @brief Access the value of a grounded i64 atom
/// @ingroup metta_language_group
/// @param[in] n A pointer to an `atom_t` or an `atom_ref_t` to access
/// @param[out] res A pointer to the variable into which to write the result
/// @return True if the atom was a grounded i64 atom, and the result was successfully written
#[no_mangle]
pub extern "C" fn grounded_number_get_longlong(n: *const atom_ref_t, res: *mut c_longlong) -> bool {
let atom = unsafe { (*n).borrow() };
match atom {
Atom::Grounded(gnd) => {
match gnd.as_any_ref().downcast_ref::<Number>() {
Some(Number::Integer(number)) => {
unsafe { *res = *number };
true
}
_ => false,
}
},
_ => false,
}
}

/// @brief Access the value of a grounded bool atom
/// @ingroup metta_language_group
/// @param[in] n A pointer to an `atom_t` or an `atom_ref_t` to access
/// @param[out] res A pointer to the variable into which to write the result
/// @return True if the atom was a grounded bool atom, and the result was successfully written
#[no_mangle]
pub extern "C" fn grounded_bool_get_bool(n: *const atom_ref_t, res: *mut bool) -> bool {
// NOTE: there is no c_bool, so we have to choose particular int type
let atom = unsafe { (*n).borrow() };
match atom {
Atom::Grounded(gnd) => {
match gnd.as_any_ref().downcast_ref::<Bool>() {
Some(Bool(b)) => {
unsafe { *res = *b };
true
}
_ => false,
}
},
_ => false,
}
}

/// @brief Access the value of a grounded f64 atom
/// @ingroup metta_language_group
/// @param[in] n A pointer to an `atom_t` or an `atom_ref_t` to access
/// @param[out] res A pointer to the variable into which to write the result
/// @return True if the atom was a grounded f64 atom, and the result was successfully written
#[no_mangle]
pub extern "C" fn grounded_number_get_double(n: *const atom_ref_t, res: *mut c_double) -> bool {
let atom = unsafe { (*n).borrow() };
match atom {
Atom::Grounded(gnd) => {
match gnd.as_any_ref().downcast_ref::<Number>() {
Some(Number::Float(number)) => {
unsafe { *res = *number };
true
},
_ => false,
}
},
_ => false,
}
}

#[no_mangle]
pub extern "C" fn longlong_into_grounded_number(n: c_longlong) -> atom_t {
Atom::gnd(Number::Integer(n)).into()
}

#[no_mangle]
pub extern "C" fn double_into_grounded_number(d: c_double) -> atom_t {
Atom::gnd(Number::Float(d)).into()
}
4 changes: 4 additions & 0 deletions c/src/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,9 @@ impl Space for CSpace {
fn as_any(&self) -> Option<&dyn std::any::Any> {
Some(self)
}
fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> {
Some(self)
}
}

impl std::fmt::Display for CSpace {
Expand All @@ -801,6 +804,7 @@ impl Space for DefaultSpace<'_> {
fn common(&self) -> FlexRef<SpaceCommon> { self.0.common() }
fn query(&self, query: &Atom) -> BindingsSet { self.0.query(query) }
fn as_any(&self) -> Option<&dyn std::any::Any> { Some(self.0) }
fn as_any_mut(&mut self) -> Option<&mut dyn std::any::Any> { None }
}
impl std::fmt::Display for DefaultSpace<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down
22 changes: 11 additions & 11 deletions docs/minimal-metta.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ matches `<atom>` with a `<pattern>`. If match is successful then it returns
variable bindings. If matching is not successful then it returns the `<else>`
branch with the original variable bindings.

## cons/decons
## cons-atom/decons-atom

`cons` and `decons` allows constructing and deconstructing the expression atom
from/to pair of the head and tail. `(decons <expr>)` expects non-empty
expression as an argument and returns a pair `(<head> <tail>)`. `(cons <head>
`cons-atom` and `decons-atom` allows constructing and deconstructing the expression atom
from/to pair of the head and tail. `(decons-atom <expr>)` expects non-empty
expression as an argument and returns a pair `(<head> <tail>)`. `(cons-atom <head>
<tail>)` returns an expression where the first sub-atom is `<head>` and others
are copied from `<tail>`.

Expand Down Expand Up @@ -180,7 +180,7 @@ Recursive switch implementation:
```metta
(= (switch $atom $cases)
(function
(chain (decons $cases) $list
(chain (decons-atom $cases) $list
(chain (eval (switch-internal $atom $list)) $res
(unify $res NotReducible (return Empty) (return $res)) ))))
Expand Down Expand Up @@ -238,14 +238,14 @@ instruction set (the full code of the example can be found
(= (move ($head $hole $tail) $char N) ($head $char $tail))
(= (move ($head $hole $tail) $char L) (function
(chain (cons $char $head) $next-head
(chain (decons $tail) $list
(chain (cons-atom $char $head) $next-head
(chain (decons-atom $tail) $list
(unify $list ($next-hole $next-tail)
(return ($next-head $next-hole $next-tail))
(return ($next-head 0 ())) )))))
(= (move ($head $hole $tail) $char R) (function
(chain (cons $char $tail) $next-tail
(chain (decons $head) $list
(chain (cons-atom $char $tail) $next-tail
(chain (decons-atom $head) $list
(unify $list ($next-hole $next-head)
(return ($next-head $next-hole $next-tail))
(return (() 0 $next-tail)) )))))
Expand All @@ -257,7 +257,7 @@ One difference from MOPS [1] is that the minimal instruction set allows
relatively easy write deterministic programs and non-determinism is injected
only via matching and evaluation. `Query` and `Chain` from MOPS are very
similar to `eval`. `Transform` is very similar to `unify`. `chain` has no
analogue in MOPS. `cons`/`decons` to some extent are analogues of
analogue in MOPS. `cons-atom`/`decons-atom` to some extent are analogues of
`AtomAdd`/`AtomRemove` in a sense that they can be used to change the state.

## Partial and complete functions
Expand Down Expand Up @@ -374,7 +374,7 @@ equality. For instance `(unify <atom> (:= Empty) then else)` should match

We could have a specific syntax which would allow matching part of the
expressions. For example such syntax could be used to match head and tail of
the expression without using `cons`/`decons`. Another example is matching part
the expression without using `cons-atom`/`decons-atom`. Another example is matching part
of the expression with some gap, i.e. `(A ... D ...)` could match `(A B C D E)`
atom.

Expand Down
2 changes: 2 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ env_logger = "0.8.4"
directories = "5.0.1" # For Environment to find platform-specific config location
smallvec = "1.10.0"
im = "15.1.0"
rand = "0.8.5"
bitset = "0.1.2"

[lib]
name = "hyperon"
Expand Down
3 changes: 2 additions & 1 deletion lib/examples/custom_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fn main() {
let mut dict = TestDict::new();
dict.put(expr!("x"), expr!({2} {5}));
dict.put(expr!("y"), expr!({5}));
let dict = expr!({dict});
let dict = expr!({dict});

let mut query = TestDict::new();
query.put(expr!(b), expr!(y));
Expand All @@ -69,5 +69,6 @@ fn main() {

let result: Vec<Bindings> = match_atoms(&dict, &query).collect();
assert_eq!(result, vec![bind!{y: expr!({5}), b: expr!("y"), a: expr!("x")}]);
println!("Querying dict: {}, using query: {}, returned result: {:?}", dict, query, result);
}

Loading

0 comments on commit f650527

Please sign in to comment.