Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Bindings::resolve_and_remove method #501

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions c/src/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,21 +1155,6 @@ pub extern "C" fn bindings_resolve(bindings: *const bindings_t, var_name: *const
bindings.resolve(&var).into()
}

/// @brief Returns the atom bound to the supplied variable name in the `bindings_t`, and removes it from the `bindings_t`
/// @ingroup matching_group
/// @param[in] bindings A pointer to the `bindings_t` to inspect
/// @param[in] var_name A NULL-terminated C-style string containing the name of the variable
/// @return The `atom_t` representing the atom that corresponds to the specified variable, or a NULL `atom_ref_t` if the variable is not present.
/// @note The caller must take ownership responsibility for the returned `atom_t`, if it is not NULL
///
#[no_mangle]
pub extern "C" fn bindings_resolve_and_remove(bindings: *mut bindings_t, var_name: *const c_char) -> atom_t {
let bindings = unsafe{ &mut*bindings }.borrow_mut();
let var = VariableAtom::new(cstr_into_string(var_name));

bindings.resolve_and_remove(&var).into()
}

/// @brief Merges two `bindings_t` Bindings frames together into a Bindings Set
/// @ingroup matching_group
/// @param[in] _self The first `bindings_t` to merge. Ownership of this argument is taken by this function
Expand Down
19 changes: 0 additions & 19 deletions lib/src/atom/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,25 +429,6 @@ impl Bindings {
var_by_id
}

/// Resolve variable, remove it from [Bindings] and return result.
///
/// # Examples
///
/// ```
/// use hyperon::*;
///
/// let mut bindings = bind!{ x: expr!(y), y: expr!("A" z), z: expr!("B") };
///
/// assert_eq!(bindings.resolve_and_remove(&VariableAtom::new("x")), Some(expr!("A" "B")));
/// assert_eq!(bindings.resolve(&VariableAtom::new("x")), None);
/// assert_eq!(bindings.resolve(&VariableAtom::new("y")), Some(expr!("A" "B")));
/// ```
pub fn resolve_and_remove(&mut self, var: &VariableAtom) -> Option<Atom> {
let result = self.resolve(&var);
self.remove(&var);
result
}

fn remove(&mut self, var: &VariableAtom) -> Option<Atom> {
match self.id_by_var.remove(var) {
None => None,
Expand Down
5 changes: 2 additions & 3 deletions lib/src/metta/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,9 +624,8 @@ fn match_op<'a, T: SpaceRef<'a>>(context: InterpreterContextRef<'a, T>, input: I
let mut query_bindings = context.space.query(&query);
let results: Vec<InterpretedAtom> = query_bindings
.drain(0..)
.map(|mut query_binding| {
let result = query_binding.resolve_and_remove(&var_x).unwrap();
let result = apply_bindings_to_atom(&result, &query_binding);
.map(|query_binding| {
let result = apply_bindings_to_atom(&Atom::Variable(var_x.clone()), &query_binding);
// TODO: sometimes we apply bindings twice: first time here,
// second time when inserting matched argument into nesting
// expression. It should be enough doing it only once.
Expand Down
7 changes: 3 additions & 4 deletions lib/src/metta/interpreter2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,13 @@ fn query<'a, T: SpaceRef<'a>>(space: T, atom: Atom, bindings: Bindings) -> Vec<I
let var = VariableAtom::new("X").make_unique();
let query = Atom::expr([EQUAL_SYMBOL, atom, Atom::Variable(var.clone())]);
let results = space.query(&query);
let atom = Atom::Variable(var);
if results.is_empty() {
vec![InterpretedAtom(return_not_reducible(), bindings)]
} else {
results.into_iter()
.flat_map(|mut b| {
let atom = b.resolve_and_remove(&var).unwrap();
let bindings = b.merge_v2(&bindings);
bindings.into_iter().map(move |b| {
.flat_map(|b| {
b.merge_v2(&bindings).into_iter().map(|b| {
let atom = apply_bindings_to_atom(&atom, &b);
InterpretedAtom(atom, b)
})
Expand Down
13 changes: 11 additions & 2 deletions lib/src/metta/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ fn query_super_types(space: &dyn Space, sub_type: &Atom) -> Vec<Atom> {
// TODO: query should check that sub type is a type and not another typed symbol
let var_x = VariableAtom::new("X").make_unique();
let mut super_types = space.query(&isa_query(&sub_type, &Atom::Variable(var_x.clone())));
super_types.drain(0..).map(|mut bindings| { bindings.resolve_and_remove(&var_x).unwrap() }).collect()
let atom_x = Atom::Variable(var_x);
super_types.drain(0..).map(|bindings| { apply_bindings_to_atom(&atom_x, &bindings) }).collect()
}

fn add_super_types(space: &dyn Space, sub_types: &mut Vec<Atom>, from: usize) {
Expand Down Expand Up @@ -107,7 +108,15 @@ pub fn is_func(typ: &Atom) -> bool {
fn query_types(space: &dyn Space, atom: &Atom) -> Vec<Atom> {
let var_x = VariableAtom::new("X").make_unique();
let mut types = query_has_type(space, atom, &Atom::Variable(var_x.clone()));
let mut types = types.drain(0..).filter_map(|mut bindings| { bindings.resolve_and_remove(&var_x) }).collect();
let atom_x = Atom::Variable(var_x);
let mut types = types.drain(0..).filter_map(|bindings| {
let atom = apply_bindings_to_atom(&atom_x, &bindings);
if atom_x == atom {
None
} else {
Some(atom)
}
}).collect();
add_super_types(space, &mut types, 0);
types
}
Expand Down
5 changes: 0 additions & 5 deletions python/hyperon/atoms.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,6 @@ def resolve(self, var_name: str) -> Union[Atom, None]:
raw_atom = hp.bindings_resolve(self.cbindings, var_name)
return None if raw_atom is None else Atom._from_catom(raw_atom)

def resolve_and_remove(self, var_name: str) -> Union[Atom, None]:
"""Finds and removes the atom for a given variable name"""
raw_atom = hp.bindings_resolve_and_remove(self.cbindings, var_name)
return None if raw_atom is None else Atom._from_catom(raw_atom)

def iterator(self):
"""Returns an iterator over the variable-atom pairs in the bindings"""
res = hp.bindings_list(self.cbindings)
Expand Down
5 changes: 0 additions & 5 deletions python/hyperonpy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,6 @@ PYBIND11_MODULE(hyperonpy, m) {
return atom_is_null(&res) ? nonstd::nullopt : nonstd::optional<CAtom>(CAtom(res));
}, "Resolve" );

m.def("bindings_resolve_and_remove", [](CBindings bindings, char const* varName) -> nonstd::optional<CAtom> {
auto const res = bindings_resolve_and_remove(bindings.ptr(), varName);
return atom_is_null(&res) ? nonstd::nullopt : nonstd::optional<CAtom>(CAtom(res));
}, "Resolve and remove" );

m.def("bindings_to_str", [](CBindings bindings) {
return func_to_string((write_to_buf_func_t)&bindings_to_str, bindings.ptr());
}, "Convert bindings to human readable string");
Expand Down
15 changes: 1 addition & 14 deletions python/tests/test_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,6 @@ def test_bindings_resolve(self):
atom_resolved = self.bindings.resolve("a")
self.assertEqual(atom_expected, atom_resolved)

def test_bindings_resolve_and_remove(self):
self.assertIsNone(self.emptyBindings.resolve_and_remove("a"))
self.assertIsNone(self.bindings.resolve_and_remove("XYXY"))

atom_expected_first = S("b")
atom_expected_second = S("y")
atom_resolved_first = self.bindings.resolve_and_remove("a")
atom_resolved_second = self.bindings.resolve_and_remove("x")

self.assertTrue(self.bindings.is_empty())
self.assertEqual(atom_expected_first, atom_resolved_first)
self.assertEqual(atom_expected_second, atom_resolved_second)

def test_bindings_iterator(self):
pass
# uncomment below as sort in bindings become stable.
Expand Down Expand Up @@ -120,7 +107,7 @@ def test_bindings_set(self):
set.add_var_binding(V("a"), S("A"))
self.assertFalse(set.is_single())
self.assertFalse(set.is_empty())
self.assertEqual(set, no_longer_empty_set);
self.assertEqual(set, no_longer_empty_set);

new_bindings = Bindings()
new_bindings.add_var_binding(V("a"), S("A"))
Expand Down