# :-multifile and DCG rules being stubborn, predicate fails immediately

**URL:** <https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796>\
**Category:** General\
**Created:** [April 5, 2021, 1:50pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796 "2021-04-05T13:50:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 1:50pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/1 "2021-04-05T13:50:49Z")

</div>

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:

```prolog
| 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:

```prolog
:- 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:

```prolog
:- 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:

```prolog
:- 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:

```prolog
:- 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:

```prolog
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:

```prolog
:- 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.

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 2:39pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/2 "2021-04-05T14:39:01Z")

</div>

OK, After posting, you always remember -something- you read somewhere… for me it was remembering the extended module:predicate calling format so for now, I have modified my code to look like this, using the functor name as the module name, which isn’t such a hardship and would actually enforce the rule of one module per reserved word handler which is fine. Heck, maybe this -is- the answer I was looking for ?

```prolog
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)])
    },
    RealFn:inst(Term, Out). % call individual handler! eg defun:inst()

```

This means at least that I can continue to break the code out into separate file in lieu of a more pertinent answer.

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 3:03pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/3 "2021-04-05T15:03:24Z")

</div>

OK, well, I’ve stopped doing that pattern as the number of warnings is growing with each one I farm out:

```prolog
| 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 assign
Warning: /Users/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.pl:38:
Warning: Local definition of ast:inst/4 overrides weak import from defun
Warning: /Users/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.pl:39:
Warning: Local definition of ast:inst/4 overrides weak import from defvar
Warning: /Users/sean/Documents/code/prolog/the-f-word-project/src/ast/ast.pl:40:
Warning: Local definition of ast:inst/4 overrides weak import from emit

```

So what -is- the best way to break out a large file into smaller ones ?

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 3:23pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/4 "2021-04-05T15:23:09Z")

</div>

Thanks again to @pmoura and he doesn’t even know it yet!  
🙂

I dived in and found this article:  
[http://swi-prolog.996271.n3.nabble.com/About-quot-multifile-quot-td6839.html](http://swi-prolog.996271.n3.nabble.com/About-quot-multifile-quot-td6839.html)

The nugget of hope was shown and I now have a fully working solution, no warnings or other flies in the ointment and I can now happily break up my code. Here is my solution thanks due to that article:

in may MAIN ast file:

```prolog
:- multifile ast:inst//2.
:- use_module(myapp(assign)).
:- use_module(myapp(defun)).
:- use_module(myapp(defvar)).
:- use_module(myapp(emit)).

```

and then in my other files, a few packed in here…

```prolog
:- module(defun, [ast:inst//2]).
:- multifile ast:inst//2.

ast:inst(defun(Pos), defun(Pos, pub(Name), Args, Body)) -->
    defun_(defun_function_name, Pos, Name, Args, Body).

:- module(emit, [ast:inst//2]).
:- multifile ast:inst//2.

ast:inst(emit(Pos), emit(Pos, Terms)) -->
    all_single_or_sexp(Terms).
:
: etc.
:

```

As those great scholars Bill and Ted would say, “Excelleeeennnnt!”  
As with APL, it does what you expect, you just have to know what to expect!

Thanks Paulo!

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [April 5, 2021, 3:36pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/5 "2021-04-05T15:36:31Z")

</div>

Paulo got too annoyed once and he left this list ☹

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 3:37pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/6 "2021-04-05T15:37:38Z")

</div>

Noooooooo! Really?

---

<div class="post-metadata">

**Author:** ![PaulBrownMagic](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/paulbrownmagic/32/211_2.png) [@PaulBrownMagic](https://swi-prolog.discourse.group/u/PaulBrownMagic)\
**Post date:** [April 5, 2021, 3:58pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/7 "2021-04-05T15:58:05Z")

</div>

Glad you got your across module predicates sorted. Regarding doing this in a cleaner way:

```
:- 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)).

```

You could do this instead:

```
:- prolog_load_context(directory, Dir),
    asserta(user:file_search_path(myapp, Dir)),
    asserta(user:file_search_path(src, myapp(src))),
    asserta(user:file_search_path(ast, src(ast))),
    asserta(user:file_search_path(inst, ast(inst))),
    asserta(user:file_search_path(tokeniser, src(tokeniser))),
    asserta(user:file_search_path(coder, src(coder))).

```

Using this means you’ll need to be more explicit with your imports:

```
:- multifile ast:inst//2.
:- use_module(myapp(assign)). % I can't see where this actually is
:- use_module(inst(defun)).
:- use_module(inst(defvar)).
:- use_module(myapp(emit)). % I can't see where this actually is

```

This has the advantage that your code tells you about where the file is, so when you’re looking for it somewhere in `myapp`, you at least know what directory it’s in and you’re only a query away from getting the whole path to it, rather than searching.

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 4:00pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/8 "2021-04-05T16:00:06Z")

</div>

Thanks Paul, I’ll study that and decide if I go with it ot now…it does look a lot cleaner though at the cost of being clearer about imports as you say.

Thanks.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [April 5, 2021, 4:38pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/9 "2021-04-05T16:38:09Z")

</div>

Better. Note that you only have to assert the one that you compute dynamically from prolog\_load\_context/2. The others can just be facts in the file. You can also dynamically add (say) `myapp_root` as dynamically computed alias and then do

```prolog
user:file_search_path(myapp, myapp_root(src)).
user:file_search_path(myapp, myapp_root(src/ast)).
...

```

Does it make much sense to use a directory structure and then smash these directories to the same alias in Prolog, creating a flat namespace?

I also have my doubt that multifile is a nice solution. If you can avoid it, that is typically a good idea.

---

<div class="post-metadata">

**Author:** ![emacstheviking](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/emacstheviking/32/228_2.png) [@emacstheviking](https://swi-prolog.discourse.group/u/emacstheviking)\
**Post date:** [April 5, 2021, 7:23pm UTC](https://swi-prolog.discourse.group/t/multifile-and-dcg-rules-being-stubborn-predicate-fails-immediately/3796/10 "2021-04-05T19:23:13Z")

</div>

I don’t like `multifile/2` either it feels somehow kludgy but I can’t think of another way, being something of a newcomer to the environment.

Is there some glaringly obvious feature I have missed?

I’ve spent a (comparatively) long time for me learning Prolog thus far but I have not really picked up too much about the SWI environment. I had a heck of a time when trying some of the http server stuff for instance.

I will study your comment in depth regarding expressing the search path as facts, for whatever reason I sometimes find the official docs either confusing or unclear to my beginner and it puts me at odds with what I am trying to do until I finally get it, usually after much gnashing of teeth etc.

Thanks.
