diff --git a/examples/add_atom_fun_space.metta b/examples/add_atom_fun_space.metta new file mode 100644 index 00000000..c3e267f3 --- /dev/null +++ b/examples/add_atom_fun_space.metta @@ -0,0 +1,6 @@ + + +(= (space) my_space_name) + +!(add-atom (space) (my test atom)) +!(test (match (space) $a $a) (my test atom)) diff --git a/python/tests/test_petta.py b/python/tests/test_petta.py index 68f77e9a..f80d9699 100644 --- a/python/tests/test_petta.py +++ b/python/tests/test_petta.py @@ -27,3 +27,20 @@ def test_var_out(petta_instance): assert ( var == '$b' or (var.startswith('$_') and var[2:].isdigit()) ), f"Unexpected variable name '{var}' in result '{result}'" + +def test_nested_relative_imports_use_importer_directory(petta_instance, tmp_path): + main_dir = tmp_path / "main" + libs_dir = tmp_path / "libs" + main_dir.mkdir() + libs_dir.mkdir() + + root_file = main_dir / "root.metta" + parent_file = libs_dir / "parent.metta" + sibling_file = libs_dir / "sibling.metta" + + root_file.write_text("!(import! &self ../libs/parent)\n!(from-sibling)\n") + parent_file.write_text("!(import! &self sibling)\n") + sibling_file.write_text("(= (from-sibling) 42)\n") + + results = petta_instance.load_metta_file(str(root_file)) + assert any(result == "42" for result in results), f"Expected sibling import to resolve; got {results}" diff --git a/src/filereader.pl b/src/filereader.pl index 2305a856..fcfc891c 100644 --- a/src/filereader.pl +++ b/src/filereader.pl @@ -2,11 +2,23 @@ :- use_module(library(pcre)). % re_replace/4 :- current_prolog_flag(argv, Args), ( (memberchk(silent, Args) ; memberchk('--silent', Args) ; memberchk('-s', Args)) -> assertz(silent(true)) ; assertz(silent(false)) ). +:- dynamic working_dir/1. + +push_working_dir(Filename) :- file_directory_name(Filename, Dir0), + ( absolute_file_name(Dir0, Dir, [file_type(directory), file_errors(fail)]) + -> true + ; Dir = Dir0 ), + asserta(working_dir(Dir)). + +pop_working_dir :- retract(working_dir(_)), !. +pop_working_dir. %Read Filename into string S and process it (S holds MeTTa code): load_metta_file(Filename, Results) :- load_metta_file(Filename, Results, '&self'). -load_metta_file(Filename, Results, Space) :- read_file_to_string(Filename, S, []), - process_metta_string(S, Results, Space). +load_metta_file(Filename, Results, Space) :- setup_call_cleanup(push_working_dir(Filename), + ( read_file_to_string(Filename, S, []), + process_metta_string(S, Results, Space) ), + pop_working_dir). %Extract function definitions, call invocations, and S-expressions part of &self space: process_metta_string(S, Results) :- process_metta_string(S, Results, '&self'). diff --git a/src/translator.pl b/src/translator.pl index 4e1985f9..47ad4f14 100644 --- a/src/translator.pl +++ b/src/translator.pl @@ -246,9 +246,10 @@ ( FreeVars == [] -> Out = F ; Out = partial(F, FreeVars) ) %--- Spaces ---: - ; ( HV == 'add-atom' ; HV == 'remove-atom' ), T = [_,_] -> append(T, [Out], RawArgs), - Goal =.. [HV|RawArgs], - append(GsH, [Goal], Goals) + ; ( HV == 'add-atom' ; HV == 'remove-atom' ), T = [Space,Atom] -> + translate_expr(Space, G1, S), + Goal =.. [HV,S,Atom,Out], + append([GsH,G1,[Goal]], Goals) ; HV == match, T = [Space, Pattern, Body] -> translate_expr(Space, G1, S), translate_expr(Body, GsB, Out), append(G1, [match(S, Pattern, Out, Out)], G2),