1:- module(dialect, 2 [ 3 exists_source/1, 4 source_exports/2 5 ]). 6 7 8prolog:'$expects_dialect'(yap) :- !, 9 eraseall('$dialect'), 10 recorda('$dialect',yap,_). 11prolog:'$expects_dialect'(Dialect) :- 12 check_dialect(Dialect), 13 eraseall('$dialect'), 14 load_files(library(dialect/Dialect),[silent(true),if(not_loaded)]), 15 ( current_predicate(Dialect:setup_dialect/0) 16 -> Dialect:setup_dialect 17 ; true 18 ), 19 recorda('$dialect',Dialect,_). 20 21check_dialect(Dialect) :- 22 var(Dialect),!, 23 '$do_error'(instantiation_error,(:- dialect(Dialect))). 24check_dialect(Dialect) :- 25 \+ atom(Dialect),!, 26 '$do_error'(type_error(Dialect),(:- dialect(Dialect))). 27check_dialect(Dialect) :- 28 exists_source(library(dialect/Dialect)), !. 29check_dialect(Dialect) :- 30 '$do_error'(domain_error(dialect,Dialect),(:- dialect(Dialect))). 31 32%% exists_source(+Source) is semidet. 33% 34% True if Source (a term valid for load_files/2) exists. Fails 35% without error if this is not the case. The predicate is intended 36% to be used with :- if, as in the example below. See also 37% source_exports/2. 38% 39% == 40% :- if(exists_source(library(error))). 41% :- use_module_library(error). 42% :- endif. 43% == 44 45exists_source(Source) :- 46 exists_source(Source, _Path). 47 48exists_source(Source, Path) :- 49 absolute_file_name(Source, Path, 50 [ file_type(prolog), 51 access(read), 52 file_errors(fail) 53 ]). 54 55%% source_exports(+Source, +Export) is semidet. 56%% source_exports(+Source, -Export) is nondet. 57% 58% True if Source exports Export. Fails without error if this is 59% not the case. See also exists_source/1. 60% 61% @tbd Should we also allow for source_exports(-Source, +Export)? 62 63source_exports(Source, Export) :- 64 open_source(Source, In), 65 catch(call_cleanup(exports(In, Exports), close(In)), _, fail), 66 ( ground(Export) 67 -> memberchk(Export, Exports) 68 ; member(Export, Exports) 69 ). 70 71%% open_source(+Source, -In:stream) is semidet. 72% 73% Open a source location. 74 75open_source(File, In) :- 76 exists_source(File, Path), 77 open(Path, read, In), 78 ( peek_char(In, #) 79 -> skip(In, 10) 80 ; true 81 ). 82 83exports(In, Exports) :- 84 read(In, Term), 85 Term = (:- module(_Name, Exports)). 86 87