Strange warning message from compile or listing

I’m using: SWI-Prolog version 8.3.21

I get a weird warning message when compiling or when listing a clause. Similar clauses produce no message. And I can make the message go away by removing a meta_predicate directive.
And, as far as I can tell the message is bogus (the resulting term expansion appears to be correct).

I can trace the code to bool/expand.pl predicate call_goal_expansion/5, where there’s a call to either M:goal_expansion(G0,P0,G,P) or M:goal_expansion(G0,G) … but when I single-step, all I get is the weird error message. (Question to @jan - how to trace such low-level predicates?)

This is the message from compiling (and a similar message from calling listing/1):

Warning: /home/peter/Downloads/extended_pos_msg_bug.pl:28:
Warning:    Unknown message: extended_pos(list_position(1376,1400,[term_position(1378,1398,1396,1397,[term_position(1378,1396,1386,1387,[1378-1386,1387-1396]),1397-1398])],none),7)
Warning: /home/peter/Downloads/extended_pos_msg_bug.pl:28:
Warning:    Unknown message: extended_pos(list_position(1376,1400,[term_position(1378,1398,1396,1397,[term_position(1378,1396,1386,1387,[1378-1386,1387-1396]),1397-1398])],none),7)

I can make the message go away by removing the meta_predicate directive on line 16.

The code can be downloaded from extended_pos_msg_bug.pl (1.6 KB)

To duplicate the bug, simply download the file and run:
swipl extended_pos_msg_bug.pl
The best spy point I could find was ci_expand.

1 Like

You may try using the normal debugger. As the term expansion code is used by the source level debugger it most likely gets a mess. What can also help is a couple of well placed trace/1 calls, e.g., starting with

?- trace('$expand':extended_pos/3).

Another option is to add some print/debug/… statements to the code :slight_smile:

I don’t know really what is happening why, but the message suggests it tries to add 7 arguments to a list, i.e., turn a term '[|]'(Head,Tail) into '[|]'(Head,Tail, A1, ... A7). I doubt that is a good idea. If this is what really should happen than extended_pos/3 should be extended to turn the list_position term into a term_position term, reusing as much as possible of the info.

P.s. while ?- directive. is still accepted I think it should be considered deprecated. I think it got there because C-Prolog had this. Any other Prolog system?

The problem seems to occur in some internal post-processing of the clause (hence the extended_pos stuff, which doesn’t occur in my term_expansion code; and also it shows up when I use listing/1 on the predicate). It’s clearly related to adding arguments in a call/7 context (the problem goes away when I remove the meta_predicate maplist_kyfact_symrej(7, +, -, +, -, +, -, +) directive), but I can’t figure out where the message is produced … when I try tracing, I get to call_goal_expansion/5, and then the debugger jumps to outputting the message – I need a way to turn on turn on a global generate_debug_info. Alternatively, I’d add some print/debug statements but how do I do that for code that’s defined as part of the system? (Add the print/debug statements and rebuild?)

Anyway, I discovered set_prolog_flag(debug_term_position, true), and that produced a bunch of warnings of the following form, but I’m not sure how to interpret them, nor do I understand why listing/1 would be calling term expansion.

Layout data: expected f1, found: [term_position(2351,2472,2351,2353,[term_position(2354,2472,2354,2371,[term_position(2372,2386,2384,2385,[2372-2384,2385-2386]),2388-2389,list_position(2412,2471,[term_position(2414,2448,2414,2421,[term_position(2422,2444,2428,2429,[2422-2428,term_position(2429,2444,2442,2443,[2429-2442,2443-2444])]),2446-2447])],none)])]),term_position(2351,2472,2351,2353,[term_position(2354,2472,2354,2371,[term_position(2372,2386,2384,2385,[2372-2384,2385-2386]),2388-2389,list_position(2412,2471,[term_position(2414,2448,2414,2421,[term_position(2422,2444,2428,2429,[2422-2428,term_position(2429,2444,2442,2443,[2429-2442,2443-2444])]),2446-2447])],none)])]),term_position(2351,2472,2351,2353,[term_position(2354,2472,2354,2371,[term_position(2372,2386,2384,2385,[2372-2384,2385-2386]),2388-2389,list_position(2412,2471,[term_position(2414,2448,2414,2421,[term_position(2422,2444,2428,2429,[2422-2428,term_position(2429,2444,2442,2443,[2429-2442,2443-2444])]),2446-2447])],none)])])]

I used that in the posted code to ensure that if someone tries to reproduce the bug, they have the correct SWI-Prolog and EDCG versions. Is there a better way of doing this than adding a ?- that throws an error?

Mostly. If you build from source, the quickest way to get going again is edit the source and run

 ninja core

Now you can run src/swipl to run the new version. No need to install. The position management is really hard. I tried to write a new approach to this, but it never materialized and I’m too busy now.

edit to some extend you can trace the stuff (using the commandline tracer) after setting the flag below. YMMV though, It is easy enough to cause the debugger eating its own tail :slight_smile:

?- set_prolog_flag(access_level, system).

AFAIK the ISO standard dictates :- Directive, were directives are things defined by the language and :- initialization(Goal) can be used to run initialization tasks. SWI-Prolog has no special “directive” class. All directives are goals and :- dynamic p/1. thus simply executes dynamic/1. The only implication of initialization is that, conform ISO, the goal is executed after loading the file has completed rather than immediately. ?- Goal. is, AFAIK, something from the old days.

I’ve sent a patch to @jan , but I’m not convinced it’s a correct solution. It appears that term expansion is being applied to a read-in-term, but it’s become confused about where it is.

Specifically, when compiling (or listing this code:

eval_assign_dot_op_binds_single(RightEval, astn(Start,End,AttrName), _BindsLeft, function_type(FunctionName,Params, Return)) ==>>
    eval_union_type(Return, _),
    maplist_kyfact_symrej(eval_union_type, Params, _),
    { join_fqn([FunctionName, AttrName], BindsFqn) },
    [ BindsFqn-RightEval-_ ]:symrej,
    kyanchor_binding(Start,End, AttrName, BindsFqn, FunctionName, 'eval_assign_dot_op_binds_single/function_type').

goal expansion seems to be working on eval_union_type(Return, _) but extended_pos/3 is trying to handle [ BindsFqn-RightEval-_ ]:symrej. (For listing/1, there’s
a call to prolog_clause:clause_info/5,
which calls prolog_clause:unify_clause/5,
which calls proloog_clause:ci_expand/5,
which calls expand_term/3,
which fails; but it produces a spurious warning message from extended_pos/3 along the way.

(The presence of a meta-predicate declaration changes some of the term expansion behavior, which appears to be why removing it makes the error message go away … but this seems to be yet another variation of how term expansion is confused about its position in the term.)

@jan has rejected my patch – correctly so (it was solving the wrong problem).

The solution seems to be in modifying EDCG term expansion. In the meantime, I have silenced the message by:

:- multifile user:message_hook/3.
:- dynamic   user:message_hook/3.

user:message_hook(extended_pos(_Pos, _N), warning, Lines) :-
    Lines = ['Unknown message: ~p'-_],
    % user:message_hook(extended_pos(_Pos, _N), informational, _Lines).
    true. % suppress this message.

For future reference, here’s Jan’s reply to me:

For me, the marginal value of improving this is very low – I seldom use the source-level tracing, and it’s “good enough” for me without the fancier term expansion that figures out variable names. But it’s probably worth modifying EDCG to use term_expansion/4 and return a “I don’t know” value.

I’ve updated EDCG pack, following Jan’s suggestion. (And now I understand the var/1 tests in expand.pl).

Hey,
FYI I’ve hit this issue with SWI-Prolog version 8.3.27 as well.
It can be reproduced with the following module:

$ cat term_expansion_warning.pl
:- module(term_expansion_warning, [op(1200, xfx, <^>)]).

user:term_expansion((L <^> R0), (L --> R)) :-
    lift(R0, R).

lift(L, l(L)) :- is_list(L), !.
lift(','(H0, T0), ','(H, T)) :- lift(H0, H), lift(T0, T), !.
lift(R, R).

foo <^> [1].

When compiling or listing/1 foo there’s a warning although the term expansion seems to work fine:

$ swipl term_expansion_warning.pl
Warning: /tmp/term_expansion_warning.pl:10:
Warning:    Unknown message: extended_pos(list_position(236,239,[237-238],none),2)
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.27)
...

?- listing(term_expansion_warning:foo).
Warning: Unknown message: extended_pos(list_position(236,239,[237-238],none),2)
foo(A, B) :-
    l([1], A, B).

true.

To get rid of the warning I used the same solution suggested above, and replaced

user:term_expansion((L <^> R0), (L --> R)) :- lift(R0, R).

with

user:term_expansion((L <^> R0), _Layout0, (L --> R), _Layout) :- lift(R0, R).

Cheers :slight_smile:

The problem is that foo <^> [1] becomes foo --> l([1]), while the position information for the right hand is not updated. Now, DCG expansion adds two arguments to l/1, but the position information is that for a list and adding arguments to a list position term is not defined. If you want this to work, the trick is to use term_expansion/4 and wrap the list position term into one that you create for the l/1 term. What you do works as well, as it effectively destroys the position information. As a result the source level debugger doesn’t work for this clause.