Skip to content

Commit

Permalink
Update: this fixes the most pressing issues (as mentioned in issue #18)…
Browse files Browse the repository at this point in the history
… regarding calling non-deterministic compiled code from the MeTTa interpreter
  • Loading branch information
patham9 committed Nov 14, 2023
1 parent f21765f commit 474ce00
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 20 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,6 @@ The file name of tests which led to different outputs with MeTTa and Chicken Sch

- Partial evaluation, e.g. leaving variables as variables when calling a function is not supported.

- For non-deterministic execution, backtracking cannot continue across the MeTTa-MeTTamorph boundary, a collapse before returning is necessary in such cases.

- Mettamorph has its own &self space, but as shown in the examples, interop is supported with wrapper functions.

These limitations are relatively minor, a substantial part of MeTTa is supported. Most importantly, the toolset allows to ensure compatibility with the MeTTa interpreter is incrementally preserved during development and the compiled code can easily be called with the MeTTa interpreter. Compared to the MeTTa interpreter the code executes by a factor of 10x+ faster with the Chicken Scheme interpreter, and usually 200x+ faster with the compiler (please see the timing folder for objective quantification).
Expand Down
5 changes: 4 additions & 1 deletion extend/cinterface.scm
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
(import (chicken platform) (chicken foreign) (chicken string))

(define-external (mattamorph_init) void
(eval '(import amb amb-extras)))

(define-external (mettamorph (c-string arg1)) c-string
(let ((result (eval (read (open-input-string arg1)))))
(let ((result (eval (list 'amb-collect (read (open-input-string arg1))))))
(if (symbol? result)
(string-append "'" (->string result))
(if (boolean? result)
Expand Down
6 changes: 3 additions & 3 deletions extend/example4.metta
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
!(compile! "
!(bind! &schemespace (new-space))
(= (add-atom-scheme $x) (add-atom &schemespace $x))
(= (get-atoms-scheme) (collapse (get-atoms &schemespace)))
(= (get-atoms-scheme) (get-atoms &schemespace))
")
!(bind! &mettaspace (new-space))
(= (add-atom-metta $x) (add-atom &mettaspace $x))
(= (get-atoms-metta) (collapse (get-atoms &mettaspace)))
(= (get-atoms-metta) (get-atoms &mettaspace))

!(add-atom-metta 42)
!(add-atom-metta 43)
!(add-atom-scheme 44)
!(add-atom-scheme 45)
!(let $T (TupleConcat (get-atoms-metta) (get-atoms-scheme)) (superpose $T))
!(superpose ((get-atoms-metta) (get-atoms-scheme)))


12 changes: 3 additions & 9 deletions extend/example5.metta
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
!(extend-py! mettamorph)
!(compile! "
;supported as in no case does this function return 2 values
;it just uses non-determinism machinery to execute, but always yields just 1 value
;as the cases are exclusive, such functions can directly be called by Mettamorph
;as they are deterministic:
(= (Add $x Z) $x)
(= (Add $x (S $y)) (Add (S $x) $y))

;This non-determinism however would need to backtrack into MeTTa
;to yield all options, which does not work,
;but with collapse it can be flattened:
(= (Sub) 2)
(= (Sub) 3)
(= (SubWrap) (collapse (Sub)))
(= (Mul) (superpose (4 5)))
")

!(Add (S (S (S Z))) (S (S (S Z))))
!(let $T (SubWrap) (superpose $T))
!(Sub)
!(Mul)
12 changes: 9 additions & 3 deletions extend/mettamorph.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ def quoteSymbol(index, x):
def call_mettamorph(*a):
tokenizer = globalmetta.tokenizer()
EXPRESSION = "(" + (" ".join([quoteSymbol(i, str(x)).replace("'(","(") for i,x in enumerate(a)])) + ")"
parser = SExprParser(str(func_mettamorph(EXPRESSION)))
parser = SExprParser("(superpose " + str(func_mettamorph(EXPRESSION) + ")"))
return parser.parse(tokenizer)

wrapperfunctions = set([])
def inject_calltypewrapper(content):
global wrapperfunctions
wrappers = ""
for line in content.split("\n"):
if line.startswith("(= ("):
Expand All @@ -58,7 +60,10 @@ def inject_calltypewrapper(content):
if counter == 0:
break
i += 1
wrappers += "(= " + args + " (mettamorph " + name + " " + " ".join(args.split(" ")[1:]) + ")\n"
wrapperfunction = "(= " + args + " (mettamorph " + name + " " + " ".join(args.split(" ")[1:]) + ")\n"
if wrapperfunction not in wrapperfunctions:
wrapperfunctions.add(wrapperfunction)
wrappers += "(= " + args + " (mettamorph " + name + " " + " ".join(args.split(" ")[1:]) + ")\n"
if line.startswith("(: "): #TODO multiline typedefs (rare but should work nevertheless)
wrappers += line + "\n"
globalmetta.run(wrappers)
Expand Down Expand Up @@ -104,7 +109,8 @@ def call_compilefile(*a):
file.write(json.dumps(compilations))
# Load the DLL
mettamorphlib = ctypes.CDLL(f"{TEMPfiles}.so")
result = mettamorphlib.CHICKEN_INIT()
mettamorphlib.CHICKEN_INIT()
mettamorphlib.mattamorph_init()
# Define the argument and return types for the mettamorph function
mettamorphlib.mettamorph.argtypes = [ctypes.c_char_p]
mettamorphlib.mettamorph.restype = ctypes.c_char_p
Expand Down
3 changes: 1 addition & 2 deletions mettamorph.scm
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
(define-syntax collapse
(syntax-rules ()
((_ args)
(filter (lambda (x) (not (== x (if #f 42))))
(amb-collect (handle-exceptions exn ((amb-failure-continuation)) (auto-list1 args)))))))
(amb-collect (auto-list1 args)))))

;superpose-helper enforces nested superpose compatibility
;by flatting out the nested superpose calls before passing it to amb
Expand Down

0 comments on commit 474ce00

Please sign in to comment.