/*********************************************************** load a program into a graph, but do not actually consult it. ***********************************************************/ load( D, _OMAP ) :- working_directory(_, D), fail. load( _, _Map ) :- % from libraries outside the current directories assert( node( attributes, woken_att_do/4, 'library/atts.yap', prolog ) ), fail. load( _ , Dirs ) :- dirs( Dirs ), %%% phase 1: find modules nb_setval( current_module, user ), nb_setval( private, false ), nb_setval( file_entry, user:user ), init_loop( Dirs ), maplist( pl_interfs, Dirs ), %%% phase 2: find C-code predicates maplist( c_preds, Dirs ). dirs( Roots ) :- member( Root-_, Roots ), % (Root = 'OPTYap' -> start_low_level_trace ; true ), absolute_file_name( Root, FRoot ), rdir( FRoot ), fail. dirs( _Roots ). rdir( FRoot ) :- absolute_file_name( FRoot, [glob(*), solutions(all), file_errors(fail)], File ), \+ doskip( File ), ( file_property( File, type(directory) ) -> rdir( File ) ; assert_new( dir( FRoot, File )) ), fail. rdir(_). c_preds(Dir - Mod) :- atom( Dir ), absolute_file_name( Dir, [glob(*), solutions(all), file_errors(fail)], File ), ( ( sub_atom(File,_,_,0,'.c') ; sub_atom(File,_,_,0,'.i') ; sub_atom(File,_,_,0,'.C') ; sub_atom(File,_,_,0,'.cpp') ; sub_atom(File,_,_,0,'.icc') ; sub_atom(File,_,_,0,'.h') ) -> \+ doskip( File ), c_file( File , Mod ) ; exists_directory( File ), \+ doskip( File ), c_preds( File - Mod ) ), fail. c_preds(_). c_file(F, _Mod) :- consulted( F, _ ), !. c_file(F, Mod) :- % writeln(F), assert( consulted( F, Mod ) ), nb_setval( current_module, Mod ), open(F, read, S, [alias(c_file)]), repeat, read_line_to_string( S, String ), ( String == end_of_file -> !, close(S) ; sub_string(String, _, _, _, `PL_extension`), %writeln(Fields), c_ext(S, Mod, F), fail ; split_string(String, `,; ()\t\"\'`, Fields), %' %writeln(Fields), line_count(S, Lines), c_line(Fields , Mod, F:Lines), fail ). c_line([`}`], Mod, _) :- !, nb_setval( current_module, Mod ). c_line(Line, _Mod, _) :- append( _, [ `CurrentModule`, `=`, M|_], Line), system_mod(M, _Mod, Mod, _), nb_setval( current_module, Mod ). c_line(Line, Mod, F: LineP) :- break_line( Line, N/A, Fu), assert( node( Mod, N/A, F-LineP, Fu ) ), handle_pred( Mod, N, A, F ). c_ext( S, Mod, F ) :- repeat, read_line_to_string( S, String ), ( sub_string( String, _, _, _, `NULL` ), ! ; split_string(String, `,; (){}\t\"\'`, [`FRG`, NS,AS,FS|_]), %' atom_string(N,NS), atom_string(Fu,FS), number_string(A, AS), stream_property( S, position( Pos ) ), stream_position_data( line_count, Pos, Line ), assert( node( Mod , N/A, F-Line, Fu ) ), handle_pred( Mod, N, A, F ) ; split_string(String, `,; (){}\t\"\'`, [NS,AS,FS|_]), %' atom_string(N,NS), atom_string(Fu,FS), number_string(A, AS), stream_property( S, position( Pos ) ), stream_position_data( line_count, Pos, Line ), Line0 is Line-1, assert( node( Mod, N/A, F-Line0, Fu ) ), handle_pred( Mod, N, A, F ) ). break_line( Line, N/A, c(Fu)) :- take_line( Line, NS, AS, FS ), !, atom_string(N,NS), atom_string(Fu,FS), number_string(A, AS). break_line( Line, N/A, swi(Fu)) :- take_line( Line, NS, AS, FS ), !, atom_string(N,NS), number_string(A, AS), atomic_concat([`pl_`,FS,`_`,A,`_va`], Fu). break_line( Line, N/A, bp(Fu)) :- take_line( Line, NS, AS, FS ), !, atom_string(N,NS), number_string(A, AS), atomic_concat([`pc_`,FS,`_`,A], Fu). break_line( Line, N/A, c(FuE, FuB)) :- take_line( Line, NS, AS, FSE, FSB ), !, atom_string(N,NS), atom_string(FuE,FSE), atom_string(FuB,FSB), number_string(A, AS). take_line( Line, NS, AS, FS ) :- append( _, [ `Yap_InitCPred`, NS, AS, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `Yap_InitAsmPred`, NS, AS, _, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `Yap_InitCmpPred`, NS, AS, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `Yap_InitCmpPred`, NS, AS, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `YAP_UserCPredicate`, NS, FS, AS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `PRED`, NS0, AS, FS|_], Line), !, append( [`pl_`, NS0, AS, `_va`], NS ). take_line( Line, NS, AS, FS ) :- append( _, [ `PRED_IMPL`, NS0, AS, FS|_], Line), !, append( [`pl_`, NS0, AS, `_va`], NS ). take_line( Line, NS, AS, FS ) :- append( _, [ `PL_register_foreign`, NS, AS, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `PRED_DEF`, NS0, AS, FS|_], Line), !, append( [`pl_`, NS0, AS, `_va`], NS ). take_line( Line, NS, AS, FS ) :- append( _, [ `FRG`, NS, AS, FS|_], Line), !. % from odbc take_line( Line, NS, AS, FS ) :- append( _, [ `NDET`, NS, AS, FS|_], Line), !. take_line( Line, NS, AS, FS ) :- append( _, [ `DET`, NS, AS, FS|_], Line), !. take_line( Line, AS, FS ) :- append( _, [ `REGISTER_CPRED`, FS, AS], Line), !. take_line( Line, NS, AS, FSE, FSB ) :- append( _, [ `Yap_InitCPredBack`, NS, AS, _, FSE, FSB|_], Line), !. system_mod(`ATTRIBUTES_MODULE`, _, attributes, user ). system_mod(`HACKS_MODULE`, _, '$hacks' , sys ). system_mod(`USER_MODULE`, _, user, user ). system_mod(`DBLOAD_MODULE`, _, '$db_load', sys ). system_mod(`GLOBALS_MODULE`, _, globals, sys ). system_mod(`ARG_MODULE`, _, arg, sys ). system_mod(`PROLOG_MODULE`, _ , prolog, sys ). system_mod(`RANGE_MODULE`, _, range, user ). system_mod(`SWI_MODULE`, _, swi, sys ). system_mod(`OPERATING_SYSTEM_MODULE`, _, system , sys ). system_mod(`TERMS_MODULE`, _, terms , sys). system_mod(`SYSTEM_MODULE`, _, system, sys ). system_mod(`IDB_MODULE`, _, idb, user ). system_mod(`CHARSIO_MODULE`, _, charsio, sys ). system_mod(`cm`, M, M, user ). call_c_files( File, Mod, _Fun, [CFile] ) :- search_file( CFile, File, c, F ), c_file(F, Mod). call_c_files( File, Mod, _Fun, CFile ) :- CFile \= [_|_], search_file( CFile, File, c, F ), c_file(F, Mod). pl_interfs(Dir - Mod) :- \+ doskip( Dir ), format('% ************* ~a\n', [Dir]), nb_setval( current_module, Mod ), atom( Dir ), directory_files( Dir , Files), member( File, Files ), atom_concat([Dir,'/',File], Path), ( ( sub_atom(File,_,_,0,'.yap') ; sub_atom(File,_,_,0,'.pl') ; sub_atom(File,_,_,0,'.ypp') ) -> ops_restore, absolute_file_name( Path, APath ), pl_interf( APath , Mod ) ; exists_directory( Path ), \+ atom_concat(_, '/.', Path), \+ atom_concat(_, '/..', Path), \+ atom_concat(_, '/.git', Path), absolute_file_name( Path, APath ), \+ doskip( APath ), pl_interfs( APath - Mod ) ), fail. pl_interfs(_). %% % pl_interf( File, Mod) % adds a node to the file graph and marks which files are modules % % main side-effect facts like edge( F0-Mod:File ) % exported( ( FMNATarget :- FMNASource ) ) ou exported(F-M, Op ), % module_on ( M, File ) % pl_interf(F, _Mod) :- module_on( F , _M, _Is), !. pl_interf(F, Mod) :- consulted(F, Mod ), !. pl_interf(F, Mod) :- % ( sub_atom(F,_,_,_,'matrix.yap') -> spy get_interf ; true ), % ( sub_atom( F, _, _, 0, 'gecode.yap' ) -> spy user_deps; true ), assert_new(consulted(F, Mod ) ), nb_getval( private, Default ), nb_setval( private, false ), nb_getval( file_entry, OF:OMod ), nb_setval( file_entry, F:Mod ), preprocess_file( F, PF ), catch( open(PF, read, S, [scripting(true)]) , _, fail ), repeat, nb_getval( current_module, MR ), %( sub_atom(F,_,_,_,'e.yap') -> spy get_interf ; nospyall ), catch( read_term( S, T, [module( MR ),term_position(Pos)] ), Throw, (ypp(F,Throw), fail)), ( T == end_of_file -> !, close(S), ( c_dep( F, Fc), c_file( Fc, MR ), fail ; build_graph( F, MR ), fail % cleanup ; module_on( F , _M, _Is) -> % also, close ops defined in the module M, if M \= Mod nb_setval( current_module, Mod ), nb_setval( private, Default ), nb_setval( file_entry, OF:OMod ) ; true ) ; nb_getval( current_module, MC0 ), stream_position_data( line_count, Pos, Line ), nb_setval( line, Line ), ( Mod == prolog -> MC = prolog ; MC = MC0 ), get_interf( T, F, MC ), fail ). get_interf( T, _F, _M0 ) :- var(T), !. get_interf( T, _F, _M0 ) :- % ( T = (:- op(_,_,_)) -> trace ; true ), var(T), !. get_interf( M:T, F, _M0 ) :- !, get_interf( T, F, M ). get_interf( goal_expansion(G, M, _) , F, _M0 ) :- nonvar( G ), !, ( var( M ) -> M1 = prolog ; M = M1 ), functor( G, N, A ), handle_pred( M1, N, A, F ). get_interf( goal_expansion(G, _) , F, _M0 ) :- nonvar( G ), !, functor( G, N, A ), handle_pred( prolog, N, A, F ). get_interf( ( M:H :- _B), F, _M ) :- !, get_interf( H, F, M ). get_interf( ( goal_expansion(G, M, _) :- _) , F, _M0 ) :- nonvar( G ), !, ( var( M ) -> M1 = prolog ; M = M1 ), functor( G, N, A ), handle_pred( M1, N, A, F ). get_interf( ( goal_expansion(G, _) :- _) , F, _M0 ) :- nonvar( G ), !, functor( G, N, A ), handle_pred( prolog, N, A, F ). get_interf( ( M:H --> _B), F, _ ) :- !, get_interf( ( H --> _B), F, M ). get_interf( ( A, _ --> _B), F, M ) :- get_interf( ( A --> _B), F, M ). get_interf( (H --> _B), F, M ) :- !, functor( H, N, Ar), Ar2 is Ar+2, functor( H2, N, Ar2), get_interf( H2, F, M ). get_interf( (H :- _B), F, M ) :- !, get_interf( H, F, M ). %% switches to new file n get_interf( (:- V ), _F, _M ) :- var( V ), !. get_interf( (:- module( NM, Is ) ), F, _M ) :- !, assert(module_file( F, NM ) ), nb_setval( current_module, NM ), assert( module_on( F , NM, Is) ), maplist( public(F, NM), Is ), nb_setval( private, true ). get_interf( (:- reexport( Loc, Is ) ), F, M ) :- !, % find the file search_file( Loc, F, pl, NF ), include_files( F, M, Is, NF ), % extend the interface.rg retract( module_on( F , M, Is0) ), append( Is0, Is, NIs ), assert( module_on( F , M, NIs) ), maplist( public(F, M), NIs ). get_interf( (:- use_module( Loc, Is ) ), F, M ) :- !, !, include_files( F, M, Is, Loc ). get_interf( (:- use_module( Loc ) ), F, M ) :- !, !, include_files( F, M, Loc ). % nb_getval(current_module,MM), writeln(NM:MM:M). get_interf( (:- use_module( Loc, Is, _ ) ), F, M ) :- !, !, include_files( F, M, Is, Loc ). get_interf( (:- consult( Files ) ), F, M ) :- !, include_files( F, M, Files ). get_interf( (:- reconsult( Files ) ), F, M ) :- !, include_files( F, M, Files ). get_interf( (:- ensure_loaded( Files ) ), F, M ) :- !, include_files( F, M, Files ). get_interf( (:- include( Files ) ), F, M ) :- !, source_files( F, M, Files ). get_interf( (:- load_files( Files , [_|_] ) ), F, M ) :- !, include_files( F, M, Files ). get_interf( ( :- ( G -> _ ; _ ) ) , F, M) :- !, get_interf( (:- G ) , F, M). get_interf( (:- catch( G , _, _ ) ) , F, M) :- !, get_interf( (:- G ) , F, M). get_interf( (:- initialization( G , now ) ) , F, M) :- !, get_interf( (:- G ) , F, M). get_interf( (:- load_files( Files , [_|_] ) ), F, M ) :- !, include_files( F, M, Files ). get_interf( (:- [F1|Fs] ), F, M ) :- !, include_files( F, M, [F1|Fs] ). % don't actually use this one. get_interf( (:- load_foreign_files(Fs, _, Fun) ), F, M ) :- !, call_c_files( F, M, Fun, Fs ). get_interf( (:- load_foreign_library(F) ), F0, M ) :- !, always_strip_module(M:F, M1, F1), call_c_files( F0, M1, '', F1 ). get_interf( (:- load_foreign_library(F,Fun) ), F0, M ) :- !, always_strip_module(M:F, M1, F1), call_c_files( F0, M1, Fun, F1 ). get_interf( (:- use_foreign_library(F) ), F0, M ) :- !, always_strip_module(M:F, M1, F1), call_c_files( F0, M1, '', F1 ). get_interf( (:- system_module( _NM, _Publics, _Hiddens) ), _F, _M ) :- !. get_interf( (:- style_checker( _ ) ), _F, _M ) :- !. get_interf( (:- dynamic T), F, M ) :- !, declare_functors( T, F, M ). get_interf( (:- multifile T), F, M ) :- % public? !, declare_functors( T, F, M ). get_interf( (:- meta_predicate T), F, M ) :-!, declare_terms( T, F, M ), % public? !. get_interf( (:- '$install_meta_predicate'( H, M) ), F, __M ) :- !, declare_functors( H, F, M ). get_interf( (:- thread_local T), F, M ) :- !, declare_functors( T, F, M ). get_interf( (:- op( X, Y, Z) ), F, M ) :- !, always_strip_module(M:Z, M1, Z1), handle_op( F, M1, op( X, Y, Z1) ). get_interf( (:- record( Records ) ), F, M ) :- !, handle_record( Records, F, M). get_interf( (:- set_prolog_flag(dollar_as_lower_case,On) ), _F, _M ) :- !, set_prolog_flag(dollar_as_lower_case,On). get_interf( (:- _ ), _F, _M ) :- !. get_interf( (?- _ ), _F, _M ) :- !. get_interf( V , _F, _M ) :- var( V ), !, error( instantiation_error ). get_interf( G , F, M ) :- functor( G, N, A), handle_pred( M, N, A, F ), !. % support SWI package record handle_record( (Records1, Records2), F, M ) :- !, handle_record( Records1, F, M ), handle_record( Records2, F, M ). handle_record( Record, F, M ) :- Record =.. [Constructor|Fields], atom_concat(Constructor, '_data', Data), handle_pred( M, Data, 3, F), atom_concat(default_, Constructor, New), handle_pred( M, New, 1, F), atom_concat(is_, Constructor, Is), handle_pred( M, Is, 1, F), atom_concat(make_, Constructor, Make), handle_pred( M, Make, 2, F), handle_pred( M, Make, 3, F), atom_concat([set_, Constructor,'_fields'], Sets), handle_pred( M, Sets, 3, F), handle_pred( M, Sets, 4, F), atom_concat([set_, Constructor,'_field'], Set), handle_pred( M, Set, 3, F), maplist( handle_record_field( Constructor, F, M) , Fields ). handle_record_field( Constructor, F, M, Name:_=_ ) :- !, handle_record_field_name( Constructor, F, M, Name). handle_record_field( Constructor, F, M, Name:_ ) :- !, handle_record_field_name( Constructor, F, M, Name). handle_record_field( Constructor, F, M, Name=_ ) :- !, handle_record_field_name( Constructor, F, M, Name). handle_record_field( Constructor, F, M, Name ) :- handle_record_field_name( Constructor, F, M, Name). handle_record_field_name( Constructor, F, M, Name) :- atom_concat([ Constructor,'_', Name], Val), handle_pred( M, Val, 2, F), atom_concat([ set_, Name, '_of_', Constructor ], Set), handle_pred( M, Set, 3, F), handle_pred( M, Set, 2, F), atom_concat([ nb_set_, Name, '_of_', Constructor ], Set), handle_pred( M, Set, 3, F), handle_pred( M, Set, 2, F). handle_pred( M, N, A, F ) :- ( system_mod( _, _, M, sys ) -> ( atom_concat('$',_,N) -> private( F, M, N/A ) ; public( F, M, N/A ) ) ; ( nb_getval( private, false ) -> public( F, M, N/A ) ; private( F, M, N/A ) ) ). handle_op( F, M, Op ) :- ( nb_getval( private, false ) -> public( F, M, Op ) ; private( F, M, Op ) ), Op = op(X, Y, Z ), ( ( M == user ; M == prolog ) -> op( X, Y, prolog:Z ) ; op( X, Y, M:Z ) ). exported( NF, F, NM, M, op(X,Y,Z)) :- !, public( NF , NM:op(X,Y,Z) ), handle_op( F, M , op(X,Y,Z) ). exported( NF, F, NM, M, N/A) :- !, % sink no more retractall( exported(( _ :- F-M:N/A) ) ), assert_new( exported( (F-M:N/A :- NF-NM:N/A )) ). exported( NF, F, NM, M, N/A as NN) :- !, % sink no more retractall( exported(( _ :- F-M:N/A) ) ), assert_new( exported( ( F-M:NN/A :- NF-NM:N/A ) ) ). exported( NF, F, NM, M, N//A) :- !, A2 is A+2, % sink no more retractall( exported(( _ :- F-M:N/A2) ) ), assert_new( exported( (F-M:N/A2 :- NF-NM:N/A2) ) ). exported( NF, F, NM, M, N//A as NN) :- !, A2 is A+2, % sink no more retractall( exported(( _ :- F-M:N/A2) ) ), assert_new( exported( ( F-M:NN/A2 :- NF-NM:N/A2 )) ). import_publics( F, ProducerMod, ConsumerMod ) :- public(F, ProducerMod:op(X,Y,Z) ), handle_op( F, ConsumerMod, op(X,Y,Z) ), fail. import_publics( _F, _ProducerMod, _ConsumerMod ). all_imported( ProducerFile, ConsumerFile, ProducerMod, ConsumerMod ) :- public(ProducerFile, ProducerMod:op(X,Y,Z) ), handle_op( ConsumerFile, ConsumerMod, op(X,Y,Z) ), fail. all_imported( ProducerFile, ConsumerFile, ProducerMod, ConsumerMod ) :- public(ProducerFile, ProducerMod:N/A ), exported( ProducerFile, ConsumerFile, ProducerMod, ConsumerMod, N/A ), fail. all_imported( _ProducerFile, _ConsumerFile, _ProducerMod, _ConsumerMod ). include_files( F, M, Files ) :- include_files( F, M, _Is, Files ). include_files( F, M, Is, Files ) :- maplist( include_files( F, M, Is ), Files ), !. include_files( F, M, Is, -Files ) :- !, include_files( F, M, Is, Files). include_files( F, M, Is, Files ) :- !, always_strip_module(M:Files, M1, NFiles), include_file( F, M1, Is, NFiles ). include_files( F, M, Is, Loc ) :- include_file( F, M, Is, Loc ). include_file( F, M, Is, Loc ) :- is_list( Loc ), !, maplist( include_file( F, M, Is), Loc ). include_file( F, M, Is0, Loc ) :- nb_getval( private, Private ), % find the file once( search_file( Loc, F, pl, NF ) ), % depth visit pl_interf(NF, M), % should verify Is in _Is % link b ( module_on(NF, NM, Is) -> ( var(Is0) -> Is = Is0 ; true ), maplist( exported( NF, F, NM, M) , Is0 ) ; all_imported( NF, F, NM, M) ), nb_setval( private, Private ). source_files( F, M, Files ) :- maplist( source_files( F, M ), Files ), !. source_files( F, M, Loc ) :- source_file( F, M, Loc ). source_file( F, M, Loc ) :- once( search_file( Loc, F, pl, NF ) ), % depth visit pl_source(NF, F, M). % should verify Is in _Is pl_source(F, F0, Mod) :- % writeln( -F ), preprocess_file( F, PF ), catch( open(PF, read, S, []) , _, fail ), repeat, nb_getval( current_module, MR ), %( sub_atom(F,_,_,_,'examples/matrix.yap') -> spy get_interf ; nospyall ), catch( read_term( S, T, [module( MR ),term_position(Pos)] ), Throw, (writeln(F:MR:Throw), break, fail)), ( T == end_of_file -> !, close(S) ; nb_getval( current_module, MC0 ), stream_position_data( line_count, Pos, Line ), nb_setval( line, Line ), ( Mod == prolog -> MC = prolog ; MC = MC0 ), get_interf( T, F0, MC ), fail ). declare_functors( T, _F, _M1) :- var(T), !, error( unbound_variable ). declare_functors( M:T, F, _M1) :- !, declare_functors( T, F, M). declare_functors( (T1,T2), F, M1) :- !, declare_functors( T1, F, M1), declare_functors( T2, F, M1). declare_functors( Ts, F, M1) :- maplist( declare_functor( F, M1), Ts ), !. declare_functors( T, F, M1) :- declare_functor( F, M1, T). declare_functor(File, M, N/A) :- handle_pred( M, N, A, File ). declare_terms( T, _F, _M1) :- var(T), !, error( unbound_variable ). declare_terms( M:T, F, _M1) :- !, declare_functors( T, F, M). declare_terms( (N1,N2), F, M) :- number(N1), number(N2), !, declare_term( F, M, (N1,N2)). declare_terms( (T1,T2), F, M1) :- !, declare_terms( T1, F, M1), declare_terms( T2, F, M1). declare_terms( Ts, F, M1) :- maplist( declare_term( F, M1), Ts ), !. declare_terms( T, F, M1) :- declare_term( F, M1, T). declare_term(F, M, S) :- functor(S, N, A), handle_pred( M, N, A, F ).