I decided to split my growing DCG rules (ast.pl) across one file per handler, I added the module search path but things are not working and I also have the error:
| Warning: /Users/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.pl:37:
Warning: Local definition of ast:inst/4 overrides weak import from defun
I understand what causes this message but right now I am not sure what to do about it and feeling a little confused about just how to break out my big sprawling ast file into smaller more manageable files.
Ideally I want a single file for each syntax form, so one for defun, defvar, emit, blah blah. I currently have the following folder structure from the project root
src/
ast/
ast.pl
inst/
defun.pl, .plt
defvar.pl, .plt
tokeniser
coder
I have this code in my load.pl
which sets up the module paths (IIUIC) so that I can then import my modules and they get found:
:- multifile user:file_search_path/2.
:- prolog_load_context(directory, Dir),
asserta(user:file_search_path(myapp, Dir)),
format(atom(Src), '~s/src', [Dir]),
asserta(user:file_search_path(myapp, Src)),
format(atom(Ast), '~s/src/ast', [Dir]),
asserta(user:file_search_path(myapp, Ast)),
format(atom(Inst), '~s/src/ast/inst', [Dir]),
asserta(user:file_search_path(myapp, Inst)),
format(atom(Tok), '~s/src/tokeniser', [Dir]),
asserta(user:file_search_path(myapp, Tok)),
format(atom(Coder), '~s/src/coder', [Dir]),
asserta(user:file_search_path(myapp, Coder)).
If there’s a shorter cleaner way I’d love to know by the way! In my main ast.pl file I have included the module that contains the extracted code, now under a common predicate name of
inst//2
for -instruction- as that’s what they are processing. My main ast file:
:- multifile inst//2.
:- use_module(myapp(defun)).
and in my defun.pl file which lives in src/ast/inst/defun.pl
I have this at the top of the file:
:- module(myapp(defun)).
:- multifile inst//2.
inst( ..... ) --> ....code.,....
When I step through the code, at the point of calling it, it immediately fails, it doesn’t even seem to try calling into the imported module. When I execute listing(inst)
I can see that the code in both files present:
:- multifile ast:inst/4.
:- multifile defun:inst/4.
defun:inst(defun(Pos),
:
defun:inst('defun+'(Pos),
:
defun:inst('defun#'(Pos),
:
: etc.
The call site is:
built_in_func(Out) -->
[Term], {
Term =.. [Fn, _Pos],
reserved_word(Fn),
bifmap(Fn, RealFn),
debug(ast, "built_in_func: calling as: ~w", [inst(Term,Out)])
},
inst(Term, Out). % <-- fails immediately
% call(RealFn, Start, Out).
and the code I expected to be called is:
:- module(defun, [inst//2]).
:- multifile inst//2.
inst(defun(Pos), defun(Pos, pub(Name), Args, Body)) -->
defun_(defun_function_name, Pos, Name, Args, Body).
:
: much more code...
This is the first time I have tried to split my code out like this but it means I can write tests in the same file now they are going to be small little units of brilliantly logically beautiful code…
So, what have I done wrong / not done in order to break out a large file into smaller files and use the module system?
Thank you in advance,
Sean.