diff --git a/python/hyperon/atoms.py b/python/hyperon/atoms.py index 2941b8b3f..4eef04b41 100644 --- a/python/hyperon/atoms.py +++ b/python/hyperon/atoms.py @@ -590,10 +590,7 @@ def resolve(self, var_name: str) -> Union[Atom, None]: def iterator(self): """Returns an iterator over the variable-atom pairs in the bindings""" res = hp.bindings_list(self.cbindings) - result = [] - for r in res: - result.append((r[0], Atom._from_catom(r[1]))) - + result = [(r[0], Atom._from_catom(r[1])) for r in res] return iter(result) class BindingsSet: @@ -698,17 +695,15 @@ def merge_into(self, input: Union['BindingsSet', Bindings]): """Merges the contents of another BindingsSet or Bindings frame.""" self.shadow_list = None if isinstance(input, BindingsSet): - hp.bindings_set_merge_into(self.c_set, input.c_set); + hp.bindings_set_merge_into(self.c_set, input.c_set) else: - new_set = BindingsSet(input); - hp.bindings_set_merge_into(self.c_set, new_set.c_set); + new_set = BindingsSet(input) + hp.bindings_set_merge_into(self.c_set, new_set.c_set) def iterator(self): """Returns an iterator over all Bindings frames""" res = hp.bindings_set_list(self.c_set) - result = [] - for r in res: - result.append(Bindings(r)) + result = [Bindings(r) for r in res] return iter(result) def get_string_value(value) -> str: diff --git a/python/sandbox/jetta/compile.py b/python/sandbox/jetta/compile.py new file mode 100644 index 000000000..2d175dba4 --- /dev/null +++ b/python/sandbox/jetta/compile.py @@ -0,0 +1,75 @@ +from hyperon import MeTTa, OperationAtom, E, S, V +from hyperon.ext import register_atoms +import requests +import json + +''' +This is the very preliminary wrapper to the Kotlin-based +MeTTa compiler, Jetta. For this gate to work, Jetta +should be installed via clonning https://github.com/trueagi-io/jetta +and running Application.kt of `server` subproject. +''' + +default_url_base = 'http://0.0.0.0:9090/contexts' + +def jetta(metta, j_space, code, url=default_url_base): + r = requests.post(url + "/" + j_space, data=code) + if r.status_code != 200: + return None + r = json.loads(r.content.decode()) + if not r['isSuccess']: + return r['messages'] + # metta.parse_single(r['result']) + if r['type'] == 'java.lang.Integer': + r['result'] = int(r['result']) + return r['result'] + +def compile(metta: MeTTa, j_space, func, arity=None): + typ = metta.space().query( + E(S(':'), S(func), V('t')) + ) + typ = list(typ) + assert len(typ) < 2, "Non-deterministic types are not supported yet" + # TODO: different arities can be tried + if len(typ) == 0: + typ = "" + if arity is None: + raise RuntimeError("If type is not defined, arity should be provided") + else: + typ = typ[0]['t'] + arity = len(typ.get_children()) - 2 + typ = f"(: {func} {repr(typ)})" + + f_args = E(S(func), *[V(f'x{i}') for i in range(arity)]) + res = metta.space().query( + E(S('='), f_args, V('__r')) + ) + res = list(res) + assert len(res) == 1, "Functions with one equality are allowed for now" + code = "(= " + repr(f_args) + "\n " +\ + repr(res[0]['__r']) + ")" + code = typ + "\n" + code + jetta(metta, j_space, code) + funcAtom = OperationAtom(func, + lambda *args: jetta(metta, j_space, + f"({func} " + " ".join([repr(a) for a in args]) + ")")) + metta.register_atom(func+'-gnd', funcAtom) + return None + +def jetta_space(url=default_url_base): + r = requests.post(url) + assert r.status_code == 200, "Failed to create jetta space" + return r.content.decode() + +@register_atoms(pass_metta=True) +def jettaspace_atoms(metta: MeTTa): + newJSpaceAtom = OperationAtom('new-jetta-space', jetta_space) + jettaAtom = OperationAtom('jetta', + lambda *args: jetta(metta, *args)) + compileAtom = OperationAtom('compile', + lambda *args: compile(metta, *args)) + return { + r"new-jetta-space": newJSpaceAtom, + r"jetta": jettaAtom, + r"compile": compileAtom + } diff --git a/python/sandbox/jetta/test_jetta.metta b/python/sandbox/jetta/test_jetta.metta new file mode 100644 index 000000000..549312618 --- /dev/null +++ b/python/sandbox/jetta/test_jetta.metta @@ -0,0 +1,34 @@ +!(import! &self compile) + +!(jetta (new-jetta-space) "(+ 1 2)") ; 3 + +!(bind! &jspace (new-jetta-space)) + +; passing code text directly +! (jetta &jspace "(: foo (-> Int Int Int)) + (= (foo $x $y) (+ $x $y 1))") +! (jetta &jspace "(foo 11 2)") ; 14 +! (jetta &jspace "(foo 11 3)") ; 15 + +; works with type inference +! (jetta &jspace ; (: fact (-> Int Int)) + "(= (fact $n) + (if (== $n 0) 1 (* $n (fact (- $n 1)))))") +! (jetta &jspace "(fact 10)") ; 3628800 + +(: boo (-> Int Int)) +(= (boo $x) (* $x 2)) +!(compile &jspace "boo") +!(jetta &jspace "(boo 3)") ; 6 +!(boo-gnd 4) ; 8 + +; Can type definitions be loaded separately? +; ! (jetta &jspace "(: foo (-> Int Int Int))") +; ! (jetta &jspace "(= (foo $x $y) (+ $x $y 1))") +; Doesn't work +;! (jetta &jspace "(: foo (-> Int Int Int)) +; (= (foo 0 0) 0) +; (foo 0 0) +; ") + +