Skip to content

Commit

Permalink
Merge pull request #501 from vsbogd/remove-resolve-and-remove
Browse files Browse the repository at this point in the history
Remove Bindings::resolve_and_remove method
  • Loading branch information
vsbogd authored Nov 15, 2023
2 parents 0946b3f + 45e94a2 commit 6f13bb0
Show file tree
Hide file tree
Showing 8 changed files with 17 additions and 67 deletions.
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

0 comments on commit 6f13bb0

Please sign in to comment.