Skip to content

Commit

Permalink
Merge branch 'main' of github.com:trueagi-io/hyperon-experimental int…
Browse files Browse the repository at this point in the history
…o edit_listening_agent
  • Loading branch information
sveta committed Dec 9, 2024
2 parents 53e56bb + 49c4ab0 commit 41159d0
Show file tree
Hide file tree
Showing 38 changed files with 4,563 additions and 3,377 deletions.
2 changes: 1 addition & 1 deletion c/src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ pub unsafe extern "C" fn atom_get_space(atom: *const atom_ref_t) -> space_t {
}

/// Private convenience function to call an `c_atom_vec_callback_t` callback with each atom in a vec
pub(crate) fn return_atoms(atoms: &Vec<Atom>, callback: c_atom_vec_callback_t, context: *mut c_void) {
pub(crate) fn return_atoms(atoms: &[Atom], callback: c_atom_vec_callback_t, context: *mut c_void) {
callback(&(&atoms[..]).into(), context);
}

Expand Down
4 changes: 2 additions & 2 deletions c/src/metta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ pub extern "C" fn atom_error_message(atom: *const atom_ref_t, buf: *mut c_char,
/// @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() }
#[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.
Expand All @@ -636,7 +636,7 @@ pub extern "C" fn atom_error_message(atom: *const atom_ref_t, buf: *mut c_char,
/// @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()
hyperon::metta::UNIT_ATOM.into()
}

/// @brief Creates a Symbol atom for the special MeTTa symbol used to indicate
Expand Down
2 changes: 0 additions & 2 deletions docs/minimal-metta.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,6 @@ Evaluate atom in a loop until result is calculated:
(eval (reduce $res $var $templ)) )))))
```

[Link](../lib/src/metta/runner/stdlib_minimal.rs) to the full code of the interpreter in MeTTa.

# Properties

## Turing completeness
Expand Down
4 changes: 2 additions & 2 deletions lib/benches/interpreter_minimal.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![feature(test)]
mod interpreter_minimal_bench {
mod interpreter_bench {

extern crate test;

Expand All @@ -8,7 +8,7 @@ use test::Bencher;
use hyperon::*;
use hyperon::space::grounding::*;
use hyperon::metta::*;
use hyperon::metta::interpreter_minimal::*;
use hyperon::metta::interpreter::*;

fn chain_atom(size: isize) -> Atom {
let mut atom = Atom::expr([CHAIN_SYMBOL, Atom::sym("A"), Atom::var("x"), Atom::var("x")]);
Expand Down
58 changes: 32 additions & 26 deletions lib/src/atom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,16 @@ macro_rules! expr {
use $crate::*;
(&&$crate::Wrap($x)).to_atom()
}};
(($($x:tt)*)) => { $crate::Atom::expr(vec![ $( expr!($x) , )* ]) };
($($x:tt)*) => { $crate::Atom::expr(vec![ $( expr!($x) , )* ]) };
(($($x:tt)*)) => { $crate::Atom::expr([ $( expr!($x) , )* ]) };
($($x:tt)*) => { $crate::Atom::expr([ $( expr!($x) , )* ]) };
}

#[macro_export]
macro_rules! constexpr {
() => { $crate::Atom::Expression($crate::ExpressionAtom::new($crate::common::collections::CowArray::Literal(&[]))) };
($x:literal) => { $crate::Atom::Symbol($crate::SymbolAtom::new($crate::common::collections::ImmutableString::Literal($x))) };
(($($x:tt)*)) => { $crate::Atom::Expression($crate::ExpressionAtom::new($crate::common::collections::CowArray::Literal(const { &[ $( constexpr!($x) , )* ] }))) };
($($x:tt)*) => { $crate::Atom::Expression($crate::ExpressionAtom::new($crate::common::collections::CowArray::Literal(const { &[ $( constexpr!($x) , )* ] }))) };
}

/// Constructs new symbol atom. Can be used to construct `const` instances.
Expand Down Expand Up @@ -117,7 +125,7 @@ use std::any::Any;
use std::fmt::{Display, Debug};
use std::convert::TryFrom;

use crate::common::collections::ImmutableString;
use crate::common::collections::{ImmutableString, CowArray};

// Symbol atom

Expand All @@ -130,7 +138,6 @@ pub struct SymbolAtom {
impl SymbolAtom {
/// Constructs new symbol from `name`. Not intended to be used directly,
/// use [sym!] or [Atom::sym] instead.
#[doc(hidden)]
pub const fn new(name: ImmutableString) -> Self {
Self{ name }
}
Expand All @@ -152,14 +159,13 @@ impl Display for SymbolAtom {
/// An expression atom structure.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExpressionAtom {
children: Vec<Atom>,
children: CowArray<Atom>,
}

impl ExpressionAtom {
/// Constructs new expression from vector of sub-atoms. Not intended to be
/// used directly, use [Atom::expr] instead.
#[doc(hidden)]
pub(crate) fn new(children: Vec<Atom>) -> Self {
/// used directly, use [expr!], [constexpr!] or [Atom::expr] instead.
pub const fn new(children: CowArray<Atom>) -> Self {
Self{ children }
}

Expand All @@ -169,18 +175,18 @@ impl ExpressionAtom {
}

/// Returns a reference to a vector of sub-atoms.
pub fn children(&self) -> &Vec<Atom> {
&self.children
pub fn children(&self) -> &[Atom] {
self.children.as_slice()
}

/// Returns a mutable reference to a vector of sub-atoms.
pub fn children_mut(&mut self) -> &mut Vec<Atom> {
&mut self.children
pub fn children_mut(&mut self) -> &mut [Atom] {
self.children.as_slice_mut()
}

/// Converts into a vector of sub-atoms.
pub fn into_children(self) -> Vec<Atom> {
self.children
self.children.into()
}
}

Expand Down Expand Up @@ -837,7 +843,7 @@ impl Atom {
/// assert_eq!(expr, same_expr);
/// assert_ne!(expr, other_expr);
/// ```
pub fn expr<T: Into<Vec<Atom>>>(children: T) -> Self {
pub fn expr<T: Into<CowArray<Atom>>>(children: T) -> Self {
Self::Expression(ExpressionAtom::new(children.into()))
}

Expand Down Expand Up @@ -1013,7 +1019,7 @@ impl<'a> TryFrom<&'a Atom> for &'a [Atom] {
type Error = &'static str;
fn try_from(atom: &Atom) -> Result<&[Atom], &'static str> {
match atom {
Atom::Expression(expr) => Ok(expr.children().as_slice()),
Atom::Expression(expr) => Ok(expr.children()),
_ => Err("Atom is not an ExpressionAtom")
}
}
Expand All @@ -1023,7 +1029,7 @@ impl<'a> TryFrom<&'a mut Atom> for &'a mut [Atom] {
type Error = &'static str;
fn try_from(atom: &mut Atom) -> Result<&mut [Atom], &'static str> {
match atom {
Atom::Expression(expr) => Ok(expr.children_mut().as_mut_slice()),
Atom::Expression(expr) => Ok(expr.children_mut()),
_ => Err("Atom is not an ExpressionAtom")
}
}
Expand Down Expand Up @@ -1093,8 +1099,8 @@ mod test {
}

#[inline]
fn expression(children: Vec<Atom>) -> Atom {
Atom::Expression(ExpressionAtom{ children })
fn expression<const N: usize>(children: [Atom; N]) -> Atom {
Atom::Expression(ExpressionAtom::new(CowArray::Allocated(Box::new(children))))
}

#[inline]
Expand Down Expand Up @@ -1175,15 +1181,15 @@ mod test {
#[test]
fn test_expr_expression() {
assert_eq!(expr!("=" ("fact" n) ("*" n ("-" n "1"))),
expression(vec![symbol("="), expression(vec![symbol("fact"), variable("n")]),
expression(vec![symbol("*"), variable("n"),
expression(vec![symbol("-"), variable("n"), symbol("1") ]) ]) ]));
expression([symbol("="), expression([symbol("fact"), variable("n")]),
expression([symbol("*"), variable("n"),
expression([symbol("-"), variable("n"), symbol("1") ]) ]) ]));
assert_eq!(expr!("=" n {[1, 2, 3]}),
expression(vec![symbol("="), variable("n"), value([1, 2, 3])]));
expression([symbol("="), variable("n"), value([1, 2, 3])]));
assert_eq!(expr!("=" {6} ("fact" n)),
expression(vec![symbol("="), value(6), expression(vec![symbol("fact"), variable("n")])]));
expression([symbol("="), value(6), expression([symbol("fact"), variable("n")])]));
assert_eq!(expr!({TestMulX(3)} {TestInteger(6)}),
expression(vec![grounded(TestMulX(3)), grounded(TestInteger(6))]));
expression([grounded(TestMulX(3)), grounded(TestInteger(6))]));
}

#[test]
Expand Down Expand Up @@ -1239,8 +1245,8 @@ mod test {
assert_eq!(Atom::gnd(TestMulX(3)).clone(), grounded(TestMulX(3)));
assert_eq!(Atom::expr([Atom::sym("="), Atom::value(6),
Atom::expr([Atom::sym("fact"), Atom::var("n")])]).clone(),
expression(vec![symbol("="), value(6),
expression(vec![symbol("fact"), variable("n")])]));
expression([symbol("="), value(6),
expression([symbol("fact"), variable("n")])]));
}

#[test]
Expand Down
22 changes: 21 additions & 1 deletion lib/src/atom/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,35 @@ pub trait Serializer {
}

/// Serialization error code
#[derive(Debug)]
pub enum Error {
/// Serialization of the type is not supported by serializer.
NotSupported,
}

/// Serializer which converts serialized atom into native Rust type T.
pub trait ConvertingSerializer<T>: Serializer {
fn as_mut(&mut self) -> &mut dyn Serializer;
fn into_type(self) -> Option<T>;

/// Converts atom into Rust value using `Self::default`
fn convert(atom: &super::Atom) -> Option<T>
where
T: 'static + Clone,
Self: Default {
std::convert::TryInto::<&dyn super::GroundedAtom>::try_into(atom)
.ok()
.map(|gnd| {
gnd.as_any_ref()
.downcast_ref::<T>()
.cloned()
.or_else(|| {
let mut serializer = Self::default();
gnd.serialize(&mut serializer).expect("ConvertingSerializer is not expected returning error");
serializer.into_type()
})
})
.flatten()
}
}

/// Serialization result type
Expand Down
91 changes: 91 additions & 0 deletions lib/src/common/collections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,97 @@ impl From<String> for ImmutableString {
}
}

#[derive(Debug, Clone)]
pub enum CowArray<T: 'static> {
Allocated(Box<[T]>),
Literal(&'static [T]),
}

impl<T: 'static> CowArray<T> {

pub fn new() -> Self {
Self::Literal(&[])
}

pub fn as_slice(&self) -> &[T] {
match self {
Self::Allocated(array) => &*array,
Self::Literal(array) => array,
}
}

pub fn as_slice_mut(&mut self) -> &mut [T] where T: Clone {
match self {
Self::Allocated(array) => &mut *array,
Self::Literal(array) => {
*self = Self::Allocated((*array).into());
self.as_slice_mut()
}
}
}

pub fn len(&self) -> usize {
self.as_slice().len()
}

pub fn iter(&self) -> impl Iterator<Item=&T> {
self.as_slice().iter()
}
}

impl<T: PartialEq> PartialEq for CowArray<T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}

impl<T: Eq> Eq for CowArray<T> {}

impl<T: Display> Display for CowArray<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[")
.and_then(|_| self.as_slice().iter().take(1).fold(Ok(()),
|res, atom| res.and_then(|_| write!(f, "{}", atom))))
.and_then(|_| self.as_slice().iter().skip(1).fold(Ok(()),
|res, atom| res.and_then(|_| write!(f, " {}", atom))))
.and_then(|_| write!(f, "]"))
}
}

impl<T: 'static> From<&'static [T]> for CowArray<T> {
fn from(a: &'static [T]) -> Self {
CowArray::Literal(a)
}
}

impl<T, const N: usize> From<[T; N]> for CowArray<T> {
fn from(a: [T; N]) -> Self {
CowArray::Allocated(Box::new(a))
}
}

impl<T> From<Vec<T>> for CowArray<T> {
fn from(v: Vec<T>) -> Self {
CowArray::Allocated(v.into_boxed_slice())
}
}

impl<T: Clone> Into<Vec<T>> for CowArray<T> {
fn into(self) -> Vec<T> {
match self {
Self::Allocated(array) => array.into(),
Self::Literal(array) => array.into(),
}
}
}

impl<'a, T> Into<&'a [T]> for &'a CowArray<T> {
fn into(self) -> &'a [T] {
self.as_slice()
}
}


#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading

0 comments on commit 41159d0

Please sign in to comment.