fix module resolution in dcgs, call/N (#1539)
This commit is contained in:
101
src/lib/dcgs.pl
101
src/lib/dcgs.pl
@@ -12,16 +12,6 @@
|
||||
:- use_module(library(lists), [append/3, member/2]).
|
||||
:- use_module(library(loader), [strip_module/3]).
|
||||
|
||||
load_context(GRBody, Module, GRBody0) :-
|
||||
strip_module(GRBody, Module, GRBody0),
|
||||
( nonvar(Module) ->
|
||||
true
|
||||
; prolog_load_context(module, Module) ->
|
||||
true
|
||||
; Module = user
|
||||
).
|
||||
|
||||
|
||||
:- meta_predicate phrase(2, ?).
|
||||
|
||||
:- meta_predicate phrase(2, ?, ?).
|
||||
@@ -30,12 +20,12 @@ phrase(GRBody, S0) :-
|
||||
phrase(GRBody, S0, []).
|
||||
|
||||
phrase(GRBody, S0, S) :-
|
||||
load_context(GRBody, Module, GRBody0),
|
||||
( var(GRBody0) ->
|
||||
( var(GRBody) ->
|
||||
instantiation_error(phrase/3)
|
||||
; dcg_body(GRBody0, S0, S, GRBody1, Module) ->
|
||||
call(Module:GRBody1)
|
||||
; type_error(callable, GRBody0, phrase/3)
|
||||
; dcg_constr(GRBody),
|
||||
dcg_body(GRBody, S0, S, GRBody1) ->
|
||||
call(GRBody1)
|
||||
; call(GRBody, S0, S)
|
||||
).
|
||||
|
||||
|
||||
@@ -48,25 +38,25 @@ module_call_qualified(M, Call, Call1) :-
|
||||
% The same version of the below two dcg_rule clauses, but with module scoping.
|
||||
dcg_rule(( M:NonTerminal, Terminals --> GRBody ), ( M:Head :- Body )) :-
|
||||
dcg_non_terminal(NonTerminal, S0, S, Head),
|
||||
dcg_body(GRBody, S0, S1, Goal1, _),
|
||||
dcg_body(GRBody, S0, S1, Goal1),
|
||||
dcg_terminals(Terminals, S, S1, Goal2),
|
||||
Body = ( Goal1, Goal2 ).
|
||||
dcg_rule(( M:NonTerminal --> GRBody ), ( M:Head :- Body )) :-
|
||||
NonTerminal \= ( _, _ ),
|
||||
dcg_non_terminal(NonTerminal, S0, S, Head),
|
||||
dcg_body(GRBody, S0, S, Body, _).
|
||||
dcg_body(GRBody, S0, S, Body).
|
||||
|
||||
% This program uses append/3 as defined in the Prolog prologue.
|
||||
% Expands a DCG rule into a Prolog rule, when no error condition applies.
|
||||
dcg_rule(( NonTerminal, Terminals --> GRBody ), ( Head :- Body )) :-
|
||||
dcg_non_terminal(NonTerminal, S0, S, Head),
|
||||
dcg_body(GRBody, S0, S1, Goal1, _),
|
||||
dcg_body(GRBody, S0, S1, Goal1),
|
||||
dcg_terminals(Terminals, S, S1, Goal2),
|
||||
Body = ( Goal1, Goal2 ).
|
||||
dcg_rule(( NonTerminal --> GRBody ), ( Head :- Body )) :-
|
||||
NonTerminal \= ( _, _ ),
|
||||
dcg_non_terminal(NonTerminal, S0, S, Head),
|
||||
dcg_body(GRBody, S0, S, Body, _).
|
||||
dcg_body(GRBody, S0, S, Body).
|
||||
|
||||
dcg_non_terminal(NonTerminal, S0, S, Goal) :-
|
||||
NonTerminal =.. NonTerminalUniv,
|
||||
@@ -76,21 +66,21 @@ dcg_non_terminal(NonTerminal, S0, S, Goal) :-
|
||||
dcg_terminals(Terminals, S0, S, S0 = List) :-
|
||||
append(Terminals, S, List).
|
||||
|
||||
dcg_body(Var, S0, S, Body, M) :-
|
||||
dcg_body(Var, S0, S, Body) :-
|
||||
var(Var),
|
||||
module_call_qualified(M, Var, Var1),
|
||||
Body = phrase(Var1, S0, S).
|
||||
dcg_body(GRBody, S0, S, Body, M) :-
|
||||
Body = phrase(Var, S0, S).
|
||||
dcg_body(GRBody, S0, S, Body) :-
|
||||
nonvar(GRBody),
|
||||
dcg_constr(GRBody),
|
||||
dcg_cbody(GRBody, S0, S, Body, M).
|
||||
dcg_body(NonTerminal, S0, S, Goal1, M) :-
|
||||
dcg_cbody(GRBody, S0, S, Body).
|
||||
dcg_body(NonTerminal, S0, S, Goal1) :-
|
||||
nonvar(NonTerminal),
|
||||
\+ dcg_constr(NonTerminal),
|
||||
NonTerminal \= ( _ -> _ ),
|
||||
NonTerminal \= ( \+ _ ),
|
||||
module_call_qualified(M, Goal, Goal1),
|
||||
dcg_non_terminal(NonTerminal, S0, S, Goal).
|
||||
loader:strip_module(NonTerminal, M, NonTerminal0),
|
||||
dcg_non_terminal(NonTerminal0, S0, S, Goal0),
|
||||
module_call_qualified(M, Goal0, Goal1).
|
||||
|
||||
% The following constructs in a grammar rule body
|
||||
% are defined in the corresponding subclauses.
|
||||
@@ -108,36 +98,32 @@ dcg_constr((_->_)). % 7.14.12 - if-then (existence implementation dep.)
|
||||
|
||||
% The principal functor of the first argument indicates
|
||||
% the construct to be expanded.
|
||||
dcg_cbody([], S0, S, S0 = S, _M).
|
||||
dcg_cbody([T|Ts], S0, S, Goal, _M) :-
|
||||
dcg_cbody([], S0, S, S0 = S).
|
||||
dcg_cbody([T|Ts], S0, S, Goal) :-
|
||||
must_be(list, [T|Ts]),
|
||||
dcg_terminals([T|Ts], S0, S, Goal).
|
||||
dcg_cbody(( GRFirst, GRSecond ), S0, S, ( First, Second ), M) :-
|
||||
dcg_body(GRFirst, S0, S1, First, M),
|
||||
dcg_body(GRSecond, S1, S, Second, M).
|
||||
dcg_cbody(( GREither ; GROr ), S0, S, ( Either ; Or ), M) :-
|
||||
dcg_cbody(( GRFirst, GRSecond ), S0, S, ( First, Second )) :-
|
||||
dcg_body(GRFirst, S0, S1, First),
|
||||
dcg_body(GRSecond, S1, S, Second).
|
||||
dcg_cbody(( GREither ; GROr ), S0, S, ( Either ; Or )) :-
|
||||
\+ subsumes_term(( _ -> _ ), GREither),
|
||||
dcg_body(GREither, S0, S, Either, M),
|
||||
dcg_body(GROr, S0, S, Or, M).
|
||||
dcg_cbody(( GRCond ; GRElse ), S0, S, ( Cond ; Else ), M) :-
|
||||
dcg_body(GREither, S0, S, Either),
|
||||
dcg_body(GROr, S0, S, Or).
|
||||
dcg_cbody(( GRCond ; GRElse ), S0, S, ( Cond ; Else )) :-
|
||||
subsumes_term(( _GRIf -> _GRThen ), GRCond),
|
||||
dcg_cbody(GRCond, S0, S, Cond, M),
|
||||
dcg_body(GRElse, S0, S, Else, M).
|
||||
dcg_cbody(( GREither '|' GROr ), S0, S, ( Either ; Or ), M) :-
|
||||
dcg_body(GREither, S0, S, Either, M),
|
||||
dcg_body(GROr, S0, S, Or, M).
|
||||
dcg_cbody({Goal}, S0, S, ( Goal1, S0 = S ), M) :-
|
||||
module_call_qualified(M, Goal, Goal1).
|
||||
dcg_cbody(call(Cont), S0, S, call(Cont1, S0, S), M) :-
|
||||
module_call_qualified(M, Cont, Cont1).
|
||||
dcg_cbody(phrase(Body), S0, S, phrase(Body1, S0, S), M) :-
|
||||
module_call_qualified(M, Body, Body1).
|
||||
dcg_cbody(!, S0, S, ( !, S0 = S ), _M).
|
||||
dcg_cbody(\+ GRBody, S0, S, ( \+ phrase(GRBody1,S0,_), S0 = S ), M) :-
|
||||
module_call_qualified(M, GRBody, GRBody1).
|
||||
dcg_cbody(( GRIf -> GRThen ), S0, S, ( If -> Then ), M) :-
|
||||
dcg_body(GRIf, S0, S1, If, M),
|
||||
dcg_body(GRThen, S1, S, Then, M).
|
||||
dcg_cbody(GRCond, S0, S, Cond),
|
||||
dcg_body(GRElse, S0, S, Else).
|
||||
dcg_cbody(( GREither '|' GROr ), S0, S, ( Either ; Or )) :-
|
||||
dcg_body(GREither, S0, S, Either),
|
||||
dcg_body(GROr, S0, S, Or).
|
||||
dcg_cbody({Goal}, S0, S, ( Goal, S0 = S )).
|
||||
dcg_cbody(call(Cont), S0, S, call(Cont, S0, S)).
|
||||
dcg_cbody(phrase(Body), S0, S, phrase(Body, S0, S)).
|
||||
dcg_cbody(!, S0, S, ( !, S0 = S )).
|
||||
dcg_cbody(\+ GRBody, S0, S, ( \+ phrase(GRBody,S0,_), S0 = S )).
|
||||
dcg_cbody(( GRIf -> GRThen ), S0, S, ( If -> Then )) :-
|
||||
dcg_body(GRIf, S0, S1, If),
|
||||
dcg_body(GRThen, S1, S, Then).
|
||||
|
||||
user:term_expansion(Term0, Term) :-
|
||||
nonvar(Term0),
|
||||
@@ -159,12 +145,13 @@ error_goal(error(E, must_be/2), error(E, must_be/2)).
|
||||
error_goal(error(E, (=..)/2), error(E, (=..)/2)).
|
||||
error_goal(E, _) :- throw(E).
|
||||
|
||||
user:goal_expansion(phrase(GRBody, S, S0), GRBody1) :-
|
||||
load_context(GRBody, M, GRBody0),
|
||||
user:goal_expansion(phrase(GRBody, S, S0), GRBody2) :-
|
||||
loader:strip_module(GRBody, M, GRBody0),
|
||||
nonvar(GRBody0),
|
||||
catch(dcgs:dcg_body(GRBody0, S, S0, GRBody1, M),
|
||||
catch(dcgs:dcg_body(GRBody0, S, S0, GRBody1),
|
||||
E,
|
||||
dcgs:error_goal(E, GRBody1)
|
||||
).
|
||||
),
|
||||
module_call_qualified(M, GRBody1, GRBody2).
|
||||
|
||||
user:goal_expansion(phrase(GRBody, S), phrase(GRBody, S, [])).
|
||||
|
||||
Reference in New Issue
Block a user