Skip to content
Open
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
7 changes: 7 additions & 0 deletions examples/file_a.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
!(import! &self file_b)

(= (add_10 $x)
(+ $x 10))

(= (square $x)
(* $x $x))
4 changes: 4 additions & 0 deletions examples/file_b.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
!(import! &self file_a)

(= (mul_2 $x)
(* (add_10 $x) 2))
7 changes: 7 additions & 0 deletions examples/test_cyclic_imports.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
!(import! &self file_a)

;; direct
!(test (add_10 10) 20)

;; cross-module
!(test (mul_2 5) 30)
6 changes: 6 additions & 0 deletions examples/test_import_order.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
!(import! &self file_b)
!(import! &self file_a)

!(test (add_10 5) 15)
!(test (mul_2 10) 40)
!(test (square 3) 9)
4 changes: 4 additions & 0 deletions examples/test_nested_imports.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
!(import! &self file_b)

!(test (add_10 5) 15)
!(test (mul_2 10) 40)
54 changes: 54 additions & 0 deletions src/filereader.pl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
% Track imported files for cycle detection and order-independence
:- dynamic imported_file/1.
:- use_module(library(readutil)). % read_file_to_string/3
:- use_module(library(pcre)). % re_replace/4
:- current_prolog_flag(argv, Args), ( (memberchk(silent, Args) ; memberchk('--silent', Args) ; memberchk('-s', Args))
Expand All @@ -14,9 +16,43 @@
strip(Cs, 0, Codes),
phrase(top_forms(Forms, 1), Codes),
maplist(parse_form, Forms, ParsedForms),
pre_register_imports(ParsedForms),
maplist(process_form(Space), ParsedForms, ResultsList), !,
append(ResultsList, Results).

% Pre-register all imports before compilation (order-independence)
pre_register_imports([]).
pre_register_imports([parsed(runnable, _, ['import!', _, File])|Rest]) :- !,
catch(pre_register_from_file(File), _, true),
pre_register_imports(Rest).
pre_register_imports([_|Rest]) :- pre_register_imports(Rest).

% Parse an imported file to register its function names and arities, with cycle detection
pre_register_from_file(File) :-
atom(File),
atom_string(File, SFile),
working_dir(Base),
\+ file_name_extension(_, 'py', SFile),
( Path = SFile ; atomic_list_concat([Base, '/', SFile], Path) ),
ensure_metta_ext(Path, PathWithExt),
exists_file(PathWithExt),
( imported_file(PathWithExt) -> true
; assertz(imported_file(PathWithExt)),
read_file_to_string(PathWithExt, S, []),
string_codes(S, Cs),
strip(Cs, 0, Codes),
phrase(top_forms(Forms, 1), Codes),
maplist(parse_form, Forms, ParsedForms),
pre_register_imports(ParsedForms),
forall(member(parsed(function, _, Term), ParsedForms),
( add_sexp('&self', Term),
translate_clause(Term, Clause),
assertz(Clause, Ref),
assertz(translated_from(Ref, Term))
)
)
).

%First pass to convert MeTTa to Prolog Terms and register functions:
parse_form(form(S), parsed(T, S, Term)) :- sread(S, Term),
( Term = [=, [F|W], _], atom(F) -> register_fun(F), length(W, N), Arity is N + 1, assertz(arity(F,Arity)), T=function
Expand All @@ -28,6 +64,24 @@
( silent(true) -> true ; swrite(Term,STerm),
format("\e[33m--> metta sexpr -->~n\e[36m~w~n", [STerm]),
format("\e[33m^^^^^^^^^^^^^^^^^^^~n\e[0m") ).
% Add runtime cycle detection for import!
process_form(_, parsed(runnable, FormStr, ['import!', _, File]), Result) :-
atom(File),
atom_string(File, SFile),
working_dir(Base),
\+ file_name_extension(_, 'py', SFile),
( Path = SFile ; atomic_list_concat([Base, '/', SFile], Path) ),
ensure_metta_ext(Path, PathWithExt),
exists_file(PathWithExt),
( imported_file(PathWithExt) -> Result = []
; assertz(imported_file(PathWithExt)),
translate_expr([collapse, ['import!', _, File]], Goals, Result),
( silent(true) -> true ; format("\e[33m--> metta runnable -->~n\e[36m!~w~n\e[33m--> prolog goal -->\e[35m ~n", [FormStr]),
forall(member(G, Goals), portray_clause((:- G))),
format("\e[33m^^^^^^^^^^^^^^^^^^^^^^^~n\e[0m") ),
call_goals(Goals)
).
% Fallback for other runnables
process_form(_, parsed(runnable, FormStr, Term), Result) :- translate_expr([collapse, Term], Goals, Result),
( silent(true) -> true ; format("\e[33m--> metta runnable -->~n\e[36m!~w~n\e[33m--> prolog goal -->\e[35m ~n", [FormStr]),
forall(member(G, Goals), portray_clause((:- G))),
Expand Down
Loading