;;; Library LOCAL_CALL                                  Chris Mellish, Feb 85

;;; "Fix" for some problems with Prolog modules.
;;; This provides a predicate "local_call" which behaves like "call"
;;; except that predicates are ALWAYS looked for in the module where
;;; the "local_call" is textually placed, rather than in the module which is
;;; active when the call takes place.

;;; Load this before anything else

:- prolog_language("pop11").

vars prolog_old_chartype;
    item_chartype(`\\`) -> prolog_old_chartype;
12 -> item_chartype(`\\`);

;;; Prolog predicate to call a goal in a given module
;;; (represented by the actual POPLOG section)

define prolog_call_in_section\/2(goal,sect);
lvars goal x y;
   prolog_deref(goal) -> goal;
   for y from 1 to goal.prolog_nargs do prolog_arg(y,goal) endfor;
   cons_with consword {% goal.prolog_predword.explode, `/`,
        goal.prolog_nargs.dest_characters %} -> x;
   word_identifier(x,sect,true) -> x;
   if x.not or
      x.identprops == undef or
      x.valof.isundef then
      mishap('Undefined procedure',[^goal])
   endif;
   chain(valof(x))
enddefine;

sysGLOBAL("prolog_call_in_section\/2");

:- prolog_language("prolog").

;;; Predicate to define 'local_call' for the current module
;;; This should be called at the start of any module that might
;;; want to make "local calls"

enable_local_calls :-
   X is apply(valof(current_section)),
   assert(local_call(Goal):- prolog_call_in_section(Goal,X)).

:- library(modules).

:- global(enable_local_calls/0).

;;; An example of this in use:
;;;
;;; :- module m.
;;;
;;; :- export a/2.
;;; :- export b/1.
;;; :- enable_local_calls.                   
;;;
;;; a(X,Y) :-
;;;    T =.. [X|Y],
;;;    local_call(Y).
;;;
;;; b(X) :- foo(X).
;;; foo(1).
;;; foo(2).
;;; baz(3).
;;; baz(4).
;;;
;;; :- endmodule.
;;;
;;; ?- a(foo,[X]).
