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 Feb 8, 2024
2 parents 89520f6 + a96439c commit 5840eeb
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 16 deletions.
22 changes: 21 additions & 1 deletion lib/src/metta/runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ impl Metta {
metta
}

// Loads stdlib into a separate space and returns it
fn stdlib_space(&self) -> DynSpace {
self.load_module_space(PathBuf::from("stdlib")).unwrap()
}

/// Returns a new MeTTa interpreter intended for use loading MeTTa modules during import
fn new_loading_runner(metta: &Metta, path: &Path) -> Self {
let space = DynSpace::new(GroundingSpace::new());
Expand Down Expand Up @@ -182,16 +187,31 @@ impl Metta {

// Load the module to the new space
let runner = Metta::new_loading_runner(self, &path);
let mut loading_stdlib = false;
let program = match path.to_str() {
Some("stdlib") => METTA_CODE.to_string(),
Some("stdlib") => {
loading_stdlib = true;
METTA_CODE.to_string()
},
_ => std::fs::read_to_string(&path).map_err(
|err| format!("Could not read file, path: {}, error: {}", path.display(), err))?,
};

let stdlib_space = if !loading_stdlib {
let stdlib_space = Atom::gnd(runner.stdlib_space());
runner.space().borrow_mut().add(stdlib_space.clone());
Some(stdlib_space)
} else {
None
};
// Make the imported module be immediately available to itself
// to mitigate circular imports
self.0.modules.borrow_mut().insert(path.clone(), runner.space().clone());
runner.run(SExprParser::new(program.as_str()))
.map_err(|err| format!("Cannot import module, path: {}, error: {}", path.display(), err))?;
if let Some(stdlib_space) = stdlib_space {
runner.space().borrow_mut().remove(&stdlib_space);
}

Ok(runner.space().clone())
}
Expand Down
4 changes: 3 additions & 1 deletion lib/src/metta/runner/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,9 @@ impl Grounded for GetAtomsOp {
let arg_error = || ExecError::from("get-atoms expects one argument: space");
let space = args.get(0).ok_or_else(arg_error)?;
let space = Atom::as_gnd::<DynSpace>(space).ok_or("get-atoms expects a space as its argument")?;
space.borrow().as_space().atom_iter().map(|iter| iter.cloned().collect()).ok_or(ExecError::Runtime("Unsupported Operation. Can't traverse atoms in this space".to_string()))
space.borrow().as_space().atom_iter()
.map(|iter| iter.cloned().map(|a| make_variables_unique(a)).collect())
.ok_or(ExecError::Runtime("Unsupported Operation. Can't traverse atoms in this space".to_string()))
}

fn match_(&self, other: &Atom) -> MatchResultIter {
Expand Down
2 changes: 2 additions & 0 deletions lib/src/metta/runner/stdlib2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ pub fn register_runner_tokens(metta: &Metta) {
tref.register_token(regex(r"bind!"), move |_| { bind_op.clone() });
let trace_op = Atom::gnd(stdlib::TraceOp{});
tref.register_token(regex(r"trace!"), move |_| { trace_op.clone() });
let println_op = Atom::gnd(stdlib::PrintlnOp{});
tref.register_token(regex(r"println!"), move |_| { println_op.clone() });
// &self should be updated
// TODO: adding &self might be done not by stdlib, but by MeTTa itself.
// TODO: adding &self introduces self referencing and thus prevents space
Expand Down
38 changes: 24 additions & 14 deletions python/tests/scripts/f1_imports.metta
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,23 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!(import! &m f1_moduleA.metta)

; Check whether passed expression contains atom for which condition is True
(: contains (-> Expression (-> Atom Bool) Bool))
(= (contains $list $condition)
(if (== $list ()) False
(let $head (car-atom $list)
(if ($condition $head) True
(let $tail (cdr-atom $list) (contains $tail $condition)) ))))

; Check whether atom is space comparing its type with type of the &self atom
(: is-space (-> Atom Bool))
(= (is-space $atom)
(let* (($type (get-type $atom)) ($space (get-type &self))) (== $type $space)))

; It's first atom is a space
!(assertEqual
(let* (($x (collapse (get-atoms &m)))
($y (car-atom $x)))
(get-type $y))
(get-type &self))
(let $x (collapse (get-atoms &m)) (contains $x is-space))
True)

; FIXME? Now, it is moduleC space.
; Should it be `stdlib` atom for a separately imported space
Expand Down Expand Up @@ -55,25 +66,24 @@
!(assertEqual (g 2) 102)
!(assertEqual (f 2) 103)

; Check whether atom is &m
(: is-m (-> Atom Bool))
(= (is-m $atom) (== $atom &m))

; `&self` contains 3 atoms-spaces now:
; - stdlib
; - moduleC imported by moduleA and removed from A after its import to &self
; - moduleA itself, which is the same as &m
!(assertEqual &m
(let* (($a (collapse (get-atoms &self)))
($x (cdr-atom $a))
($y (cdr-atom $x)))
(car-atom $y)))
!(assertEqual
(let $a (collapse (get-atoms &self)) (contains $a is-m))
True)

; NOTE: now the first atom, which was a space, is removed from `&m`,
; because we load modules only once, and we collect atoms-spaces to
; prevent duplication
!(assertEqual
(== (let* (($x (collapse (get-atoms &m)))
($y (car-atom $x)))
(get-type $y))
(get-type &self))
False)
(let $x (collapse (get-atoms &m)) (contains $x is-space))
False)

; Let's check that `if` from stdlib is not duplicated and gives only one result
!(assertEqual
Expand Down

0 comments on commit 5840eeb

Please sign in to comment.