36
37:- module(prolog_source,
38 [ prolog_read_source_term/4, 39 read_source_term_at_location/3, 40 prolog_file_directives/3, 41 prolog_open_source/2, 42 prolog_close_source/1, 43 prolog_canonical_source/2, 44
45 load_quasi_quotation_syntax/2, 46
47 file_name_on_path/2, 48 file_alias_path/2, 49 path_segments_atom/2, 50 directory_source_files/3, 51 valid_term_position/2 52 ]). 53:- use_module(library(debug), [debug/3, assertion/1]). 54:- autoload(library(apply), [maplist/2, maplist/3, foldl/4]). 55:- autoload(library(error), [domain_error/2, is_of_type/2]). 56:- autoload(library(lists), [member/2, last/2, select/3, append/3, selectchk/3]). 57:- autoload(library(operators), [push_op/3, push_operators/1, pop_operators/0]). 58:- autoload(library(option), [select_option/4, option/3, option/2]). 59:- autoload(library(modules),[in_temporary_module/3]). 60
61
84
85:- thread_local
86 open_source/2, 87 mode/2. 88
89:- multifile
90 requires_library/2,
91 prolog:xref_source_identifier/2, 92 prolog:xref_source_time/2, 93 prolog:xref_open_source/2, 94 prolog:xref_close_source/2, 95 prolog:alternate_syntax/4, 96 prolog:xref_update_syntax/2, 97 prolog:quasi_quotation_syntax/2. 98
99
100:- predicate_options(prolog_read_source_term/4, 4,
101 [ pass_to(system:read_clause/3, 3)
102 ]). 103:- predicate_options(read_source_term_at_location/3, 3,
104 [ line(integer),
105 offset(integer),
106 module(atom),
107 operators(list),
108 error(-any),
109 pass_to(system:read_term/3, 3)
110 ]). 111:- predicate_options(directory_source_files/3, 3,
112 [ recursive(boolean),
113 if(oneof([true,loaded])),
114 pass_to(system:absolute_file_name/3,3)
115 ]). 116
117
118 121
135
136prolog_read_source_term(In, Term, Expanded, Options) :-
137 maplist(read_clause_option, Options),
138 !,
139 select_option(subterm_positions(TermPos), Options,
140 RestOptions, TermPos),
141 read_clause(In, Term,
142 [ subterm_positions(TermPos)
143 | RestOptions
144 ]),
145 expand(Term, TermPos, In, Expanded),
146 '$current_source_module'(M),
147 update_state(Term, Expanded, M, In).
148prolog_read_source_term(In, Term, Expanded, Options) :-
149 '$current_source_module'(M),
150 select_option(syntax_errors(SE), Options, RestOptions0, dec10),
151 select_option(subterm_positions(TermPos), RestOptions0,
152 RestOptions, TermPos),
153 ( style_check(?(singleton))
154 -> FinalOptions = [ singletons(warning) | RestOptions ]
155 ; FinalOptions = RestOptions
156 ),
157 read_term(In, Term,
158 [ module(M),
159 syntax_errors(SE),
160 subterm_positions(TermPos)
161 | FinalOptions
162 ]),
163 expand(Term, TermPos, In, Expanded),
164 update_state(Term, Expanded, M, In).
165
166read_clause_option(syntax_errors(_)).
167read_clause_option(term_position(_)).
168read_clause_option(process_comment(_)).
169read_clause_option(comments(_)).
170
171:- public
172 expand/3. 173
174expand(Term, In, Exp) :-
175 expand(Term, _, In, Exp).
176
177expand(Var, _, _, Var) :-
178 var(Var),
179 !.
180expand(Term, _, _, Term) :-
181 no_expand(Term),
182 !.
183expand(Term, _, _, _) :-
184 requires_library(Term, Lib),
185 ensure_loaded(user:Lib),
186 fail.
187expand(Term, _, In, Term) :-
188 chr_expandable(Term, In),
189 !.
190expand(Term, Pos, _, Expanded) :-
191 expand_term(Term, Pos, Expanded, _).
192
193no_expand((:- if(_))).
194no_expand((:- elif(_))).
195no_expand((:- else)).
196no_expand((:- endif)).
197no_expand((:- require(_))).
198
199chr_expandable((:- chr_constraint(_)), In) :-
200 add_mode(In, chr).
201chr_expandable((handler(_)), In) :-
202 mode(In, chr).
203chr_expandable((rules(_)), In) :-
204 mode(In, chr).
205chr_expandable(<=>(_, _), In) :-
206 mode(In, chr).
207chr_expandable(@(_, _), In) :-
208 mode(In, chr).
209chr_expandable(==>(_, _), In) :-
210 mode(In, chr).
211chr_expandable(pragma(_, _), In) :-
212 mode(In, chr).
213chr_expandable(option(_, _), In) :-
214 mode(In, chr).
215
216add_mode(Stream, Mode) :-
217 mode(Stream, Mode),
218 !.
219add_mode(Stream, Mode) :-
220 asserta(mode(Stream, Mode)).
221
225
226requires_library((:- emacs_begin_mode(_,_,_,_,_)), library(emacs_extend)).
227requires_library((:- draw_begin_shape(_,_,_,_)), library(pcedraw)).
228requires_library((:- use_module(library(pce))), library(pce)).
229requires_library((:- pce_begin_class(_,_)), library(pce)).
230requires_library((:- pce_begin_class(_,_,_)), library(pce)).
231requires_library((:- html_meta(_)), library(http/html_decl)).
232
236
237:- multifile
238 pce_expansion:push_compile_operators/1,
239 pce_expansion:pop_compile_operators/0. 240
241update_state((:- pce_end_class), _, _, _) =>
242 ignore(pce_expansion:pop_compile_operators).
243update_state((:- pce_extend_class(_)), _, SM, _) =>
244 pce_expansion:push_compile_operators(SM).
245update_state(Raw, _, Module, _),
246 catch(prolog:xref_update_syntax(Raw, Module),
247 error(_,_),
248 fail) =>
249 true.
250update_state(_Raw, Expanded, M, In) =>
251 update_state(Expanded, M, In).
252
253update_state(Var, _, _) :-
254 var(Var),
255 !.
256update_state([], _, _) :-
257 !.
258update_state([H|T], M, In) :-
259 !,
260 update_state(H, M, In),
261 update_state(T, M, In).
262update_state((:- Directive), M, In) :-
263 nonvar(Directive),
264 !,
265 catch(update_directive(Directive, M, In), _, true).
266update_state((?- Directive), M, In) :-
267 !,
268 update_state((:- Directive), M, In).
269update_state(MetaDecl, _M, _) :-
270 MetaDecl = html_write:html_meta_head(_Head,_Module,_Meta),
271 ( clause(MetaDecl, true)
272 -> true
273 ; assertz(MetaDecl)
274 ).
275update_state(_, _, _).
276
278
279update_directive(Directive, Module, _) :-
280 prolog:xref_update_syntax((:- Directive), Module),
281 !.
282update_directive(encoding(Enc), _, In) :-
283 !,
284 set_stream(In, encoding(Enc)).
285update_directive(module(Module, Public), _, _) :-
286 atom(Module),
287 is_list(Public),
288 !,
289 '$set_source_module'(Module),
290 maplist(import_syntax(_,Module, _), Public).
291update_directive(M:op(P,T,N), SM, In) :-
292 atom(M),
293 ground(op(P,T,N)),
294 !,
295 update_directive(op(P,T,N), SM, In).
296update_directive(op(P,T,N), SM, _) :-
297 ground(op(P,T,N)),
298 !,
299 strip_module(SM:N, M, PN),
300 push_op(P,T,M:PN).
301update_directive(style_check(Style), _, _) :-
302 ground(Style),
303 style_check(Style),
304 !.
305update_directive(use_module(Spec), SM, _) :-
306 ground(Spec),
307 catch(module_decl(Spec, Path, Public), _, fail),
308 is_list(Public),
309 !,
310 maplist(import_syntax(Path, SM, _), Public).
311update_directive(use_module(Spec, Imports), SM, _) :-
312 ground(Spec),
313 is_list(Imports),
314 catch(module_decl(Spec, Path, Public), _, fail),
315 is_list(Public),
316 !,
317 maplist(import_syntax(Path, SM, Imports), Public).
318update_directive(pce_begin_class_definition(_,_,_,_), SM, _) :-
319 pce_expansion:push_compile_operators(SM),
320 !.
321update_directive(_, _, _).
322
327
328import_syntax(_, _, _, Var) :-
329 var(Var),
330 !.
331import_syntax(_, M, Imports, Op) :-
332 Op = op(_,_,_),
333 \+ \+ member(Op, Imports),
334 !,
335 update_directive(Op, M, _).
336import_syntax(Path, SM, Imports, Syntax/4) :-
337 \+ \+ member(Syntax/4, Imports),
338 load_quasi_quotation_syntax(SM:Path, Syntax),
339 !.
340import_syntax(_,_,_, _).
341
342
356
357load_quasi_quotation_syntax(SM:Path, Syntax) :-
358 atom(Path), atom(Syntax),
359 source_file_property(Path, module(M)),
360 functor(ST, Syntax, 4),
361 predicate_property(M:ST, quasi_quotation_syntax),
362 !,
363 use_module(SM:Path, [Syntax/4]).
364load_quasi_quotation_syntax(SM:Path, Syntax) :-
365 atom(Path), atom(Syntax),
366 prolog:quasi_quotation_syntax(Syntax, Spec),
367 absolute_file_name(Spec, Path2,
368 [ file_type(prolog),
369 file_errors(fail),
370 access(read)
371 ]),
372 Path == Path2,
373 !,
374 use_module(SM:Path, [Syntax/4]).
375
381
382module_decl(Spec, Source, Exports) :-
383 absolute_file_name(Spec, Path,
384 [ file_type(prolog),
385 file_errors(fail),
386 access(read)
387 ]),
388 module_decl_(Path, Source, Exports).
389
390module_decl_(Path, Source, Exports) :-
391 file_name_extension(_, qlf, Path),
392 !,
393 '$qlf_module'(Path, Info),
394 _{file:Source, exports:Exports} :< Info.
395module_decl_(Path, Path, Exports) :-
396 setup_call_cleanup(
397 prolog_open_source(Path, In),
398 read_module_decl(In, Exports),
399 prolog_close_source(In)).
400
401read_module_decl(In, Decl) :-
402 read(In, Term0),
403 read_module_decl(Term0, In, Decl).
404
405read_module_decl((:- module(_, DeclIn)), _In, Decl) =>
406 Decl = DeclIn.
407read_module_decl((:- encoding(Enc)), In, Decl) =>
408 set_stream(In, encoding(Enc)),
409 read(In, Term2),
410 read_module_decl(Term2, In, Decl).
411read_module_decl(_, _, _) =>
412 fail.
413
414
455
456:- thread_local
457 last_syntax_error/2. 458
459read_source_term_at_location(Stream, Term, Options) :-
460 retractall(last_syntax_error(_,_)),
461 seek_to_start(Stream, Options),
462 stream_property(Stream, position(Here)),
463 '$current_source_module'(DefModule),
464 option(module(Module), Options, DefModule),
465 option(operators(Ops), Options, []),
466 alternate_syntax(Syntax, Module, Setup, Restore),
467 set_stream_position(Stream, Here),
468 debug(read, 'Trying with syntax ~w', [Syntax]),
469 push_operators(Module:Ops),
470 call(Setup),
471 Error = error(Formal,_), 472 setup_call_cleanup(
473 asserta(user:thread_message_hook(_,_,_), Ref), 474 catch(qq_read_term(Stream, Term0,
475 [ module(Module)
476 | Options
477 ]),
478 Error,
479 true),
480 erase(Ref)),
481 call(Restore),
482 pop_operators,
483 ( var(Formal)
484 -> !, Term = Term0
485 ; assert_error(Error, Options),
486 fail
487 ).
488read_source_term_at_location(_, _, Options) :-
489 option(error(Error), Options),
490 !,
491 setof(CharNo:Msg, retract(last_syntax_error(CharNo, Msg)), Pairs),
492 last(Pairs, Error).
493
494assert_error(Error, Options) :-
495 option(error(_), Options),
496 !,
497 ( ( Error = error(syntax_error(Id),
498 stream(_S1, _Line1, _LinePos1, CharNo))
499 ; Error = error(syntax_error(Id),
500 file(_S2, _Line2, _LinePos2, CharNo))
501 )
502 -> message_to_string(error(syntax_error(Id), _), Msg),
503 assertz(last_syntax_error(CharNo, Msg))
504 ; debug(read, 'Error: ~q', [Error]),
505 throw(Error)
506 ).
507assert_error(_, _).
508
509
522
523alternate_syntax(prolog, _, true, true).
524alternate_syntax(Syntax, M, Setup, Restore) :-
525 prolog:alternate_syntax(Syntax, M, Setup, Restore).
526
527
531
532seek_to_start(Stream, Options) :-
533 option(line(Line), Options),
534 !,
535 seek(Stream, 0, bof, _),
536 seek_to_line(Stream, Line).
537seek_to_start(Stream, Options) :-
538 option(offset(Start), Options),
539 !,
540 seek(Stream, Start, bof, _).
541seek_to_start(_, _).
542
546
547seek_to_line(Fd, N) :-
548 N > 1,
549 !,
550 skip(Fd, 10),
551 NN is N - 1,
552 seek_to_line(Fd, NN).
553seek_to_line(_, _).
554
555
556 559
565
566qq_read_term(Stream, Term, Options) :-
567 select(syntax_errors(ErrorMode), Options, Options1),
568 ErrorMode \== error,
569 !,
570 ( ErrorMode == dec10
571 -> repeat,
572 qq_read_syntax_ex(Stream, Term, Options1, Error),
573 ( var(Error)
574 -> !
575 ; print_message(error, Error),
576 fail
577 )
578 ; qq_read_syntax_ex(Stream, Term, Options1, Error),
579 ( ErrorMode == fail
580 -> print_message(error, Error),
581 fail
582 ; ErrorMode == quiet
583 -> fail
584 ; domain_error(syntax_errors, ErrorMode)
585 )
586 ).
587qq_read_term(Stream, Term, Options) :-
588 qq_read_term_ex(Stream, Term, Options).
589
590qq_read_syntax_ex(Stream, Term, Options, Error) :-
591 catch(qq_read_term_ex(Stream, Term, Options),
592 error(syntax_error(Syntax), Context),
593 Error = error(Syntax, Context)).
594
595qq_read_term_ex(Stream, Term, Options) :-
596 stream_property(Stream, position(Here)),
597 catch(read_term(Stream, Term, Options),
598 error(syntax_error(unknown_quasi_quotation_syntax(Syntax, Module)), Context),
599 load_qq_and_retry(Here, Syntax, Module, Context, Stream, Term, Options)).
600
601load_qq_and_retry(Here, Syntax, Module, _, Stream, Term, Options) :-
602 set_stream_position(Stream, Here),
603 prolog:quasi_quotation_syntax(Syntax, Library),
604 !,
605 use_module(Module:Library, [Syntax/4]),
606 read_term(Stream, Term, Options).
607load_qq_and_retry(_Pos, Syntax, Module, Context, _Stream, _Term, _Options) :-
608 print_message(warning, quasi_quotation(undeclared, Syntax)),
609 throw(error(syntax_error(unknown_quasi_quotation_syntax(Syntax, Module)), Context)).
610
619
620prolog:quasi_quotation_syntax(html, library(http/html_write)).
621prolog:quasi_quotation_syntax(javascript, library(http/js_write)).
622
623
637
638prolog_file_directives(File, Directives, Options) :-
639 option(canonical_source(Path), Options, _),
640 prolog_canonical_source(File, Path),
641 in_temporary_module(
642 TempModule,
643 true,
644 read_directives(TempModule, Path, Directives, Options)).
645
646read_directives(TempModule, Path, Directives, Options) :-
647 setup_call_cleanup(
648 read_directives_setup(TempModule, Path, In, State),
649 phrase(read_directives(In, Options, [true]), Directives),
650 read_directives_cleanup(In, State)).
651
652read_directives_setup(TempModule, Path, In, state(OldM, OldXref)) :-
653 prolog_open_source(Path, In),
654 '$set_source_module'(OldM, TempModule),
655 current_prolog_flag(xref, OldXref),
656 set_prolog_flag(xref, true).
657
658read_directives_cleanup(In, state(OldM, OldXref)) :-
659 '$set_source_module'(OldM),
660 set_prolog_flag(xref, OldXref),
661 prolog_close_source(In).
662
663read_directives(In, Options, State) -->
664 { E = error(_,_),
665 repeat,
666 catch(prolog_read_source_term(In, Term, Expanded,
667 [ process_comment(true),
668 syntax_errors(error)
669 ]),
670 E, report_syntax_error(E, Options))
671 -> nonvar(Term),
672 Term = (:-_)
673 },
674 !,
675 terms(Expanded, State, State1),
676 read_directives(In, Options, State1).
677read_directives(_, _, _) --> [].
678
679report_syntax_error(_, Options) :-
680 option(silent(true), Options),
681 !,
682 fail.
683report_syntax_error(E, _Options) :-
684 print_message(warning, E),
685 fail.
686
687terms(Var, State, State) --> { var(Var) }, !.
688terms([H|T], State0, State) -->
689 !,
690 terms(H, State0, State1),
691 terms(T, State1, State).
692terms((:-if(Cond)), State0, [True|State0]) -->
693 !,
694 { eval_cond(Cond, True) }.
695terms((:-elif(Cond)), [True0|State], [True|State]) -->
696 !,
697 { eval_cond(Cond, True1),
698 elif(True0, True1, True)
699 }.
700terms((:-else), [True0|State], [True|State]) -->
701 !,
702 { negate(True0, True) }.
703terms((:-endif), [_|State], State) --> !.
704terms(H, State, State) -->
705 ( {State = [true|_]}
706 -> [H]
707 ; []
708 ).
709
710eval_cond(Cond, true) :-
711 catch(Cond, error(_,_), fail),
712 !.
713eval_cond(_, false).
714
715elif(true, _, else_false) :- !.
716elif(false, true, true) :- !.
717elif(True, _, True).
718
719negate(true, false).
720negate(false, true).
721negate(else_false, else_false).
722
723 726
741
742prolog_open_source(Src, Fd) :-
743 '$push_input_context'(source),
744 catch(( prolog:xref_open_source(Src, Fd)
745 -> Hooked = true
746 ; open(Src, read, Fd),
747 Hooked = false
748 ), E,
749 ( '$pop_input_context',
750 throw(E)
751 )),
752 skip_hashbang(Fd),
753 push_operators([]),
754 '$current_source_module'(SM),
755 '$save_lex_state'(LexState, []),
756 asserta(open_source(Fd, state(Hooked, Src, LexState, SM))).
757
758skip_hashbang(Fd) :-
759 catch(( peek_char(Fd, #) 760 -> skip(Fd, 10)
761 ; true
762 ), E,
763 ( close(Fd, [force(true)]),
764 '$pop_input_context',
765 throw(E)
766 )).
767
775
776
783
784prolog_close_source(In) :-
785 call_cleanup(
786 restore_source_context(In, Hooked, Src),
787 close_source(Hooked, Src, In)).
788
789close_source(true, Src, In) :-
790 catch(prolog:xref_close_source(Src, In), _, false),
791 !,
792 '$pop_input_context'.
793close_source(_, _Src, In) :-
794 close(In, [force(true)]),
795 '$pop_input_context'.
796
797restore_source_context(In, Hooked, Src) :-
798 ( at_end_of_stream(In)
799 -> true
800 ; ignore(catch(expand(end_of_file, _, In, _), _, true))
801 ),
802 pop_operators,
803 retractall(mode(In, _)),
804 ( retract(open_source(In, state(Hooked, Src, LexState, SM)))
805 -> '$restore_lex_state'(LexState),
806 '$set_source_module'(SM)
807 ; assertion(fail)
808 ).
809
815
822
823prolog_canonical_source(Source, Src) :-
824 var(Source),
825 !,
826 Src = Source.
827prolog_canonical_source(User, user) :-
828 User == user,
829 !.
830prolog_canonical_source(Src, Id) :- 831 prolog:xref_source_identifier(Src, Id),
832 !.
833prolog_canonical_source(Source, Src) :-
834 source_file(Source),
835 !,
836 Src = Source.
837prolog_canonical_source(Source, Src) :-
838 absolute_file_name(Source, Src,
839 [ file_type(prolog),
840 access(read),
841 file_errors(fail)
842 ]),
843 !.
844
845
850
851file_name_on_path(Path, ShortId) :-
852 ( file_alias_path(Alias, Dir),
853 atom_concat(Dir, Local, Path)
854 -> ( Alias == '.'
855 -> ShortId = Local
856 ; file_name_extension(Base, pl, Local)
857 -> ShortId =.. [Alias, Base]
858 ; ShortId =.. [Alias, Local]
859 )
860 ; ShortId = Path
861 ).
862
863
868
869:- dynamic
870 alias_cache/2. 871
872file_alias_path(Alias, Dir) :-
873 ( alias_cache(_, _)
874 -> true
875 ; build_alias_cache
876 ),
877 ( nonvar(Dir)
878 -> ensure_slash(Dir, DirSlash),
879 alias_cache(Alias, DirSlash)
880 ; alias_cache(Alias, Dir)
881 ).
882
883build_alias_cache :-
884 findall(t(DirLen, AliasLen, Alias, Dir),
885 search_path(Alias, Dir, AliasLen, DirLen), Ts),
886 sort(0, >, Ts, List),
887 forall(member(t(_, _, Alias, Dir), List),
888 assert(alias_cache(Alias, Dir))).
889
890search_path('.', Here, 999, DirLen) :-
891 working_directory(Here0, Here0),
892 ensure_slash(Here0, Here),
893 atom_length(Here, DirLen).
894search_path(Alias, Dir, AliasLen, DirLen) :-
895 user:file_search_path(Alias, _),
896 Alias \== autoload, 897 Alias \== noautoload,
898 Spec =.. [Alias,'.'],
899 atom_length(Alias, AliasLen0),
900 AliasLen is 1000 - AliasLen0, 901 absolute_file_name(Spec, Dir0,
902 [ file_type(directory),
903 access(read),
904 solutions(all),
905 file_errors(fail)
906 ]),
907 ensure_slash(Dir0, Dir),
908 atom_length(Dir, DirLen).
909
910ensure_slash(Dir, Dir) :-
911 sub_atom(Dir, _, _, 0, /),
912 !.
913ensure_slash(Dir0, Dir) :-
914 atom_concat(Dir0, /, Dir).
915
916
934
935path_segments_atom(Segments, Atom) :-
936 var(Atom),
937 !,
938 ( atomic(Segments)
939 -> Atom = Segments
940 ; segments_to_list(Segments, List, [])
941 -> atomic_list_concat(List, /, Atom)
942 ; throw(error(type_error(file_path, Segments), _))
943 ).
944path_segments_atom(Segments, Atom) :-
945 atomic_list_concat(List, /, Atom),
946 parts_to_path(List, Segments).
947
948segments_to_list(Var, _, _) :-
949 var(Var), !, fail.
950segments_to_list(A/B, H, T) :-
951 segments_to_list(A, H, T0),
952 segments_to_list(B, T0, T).
953segments_to_list(A, [A|T], T) :-
954 atomic(A).
955
956parts_to_path([One], One) :- !.
957parts_to_path(List, More/T) :-
958 ( append(H, [T], List)
959 -> parts_to_path(H, More)
960 ).
961
974
975directory_source_files(Dir, SrcFiles, Options) :-
976 option(if(loaded), Options, loaded),
977 !,
978 absolute_file_name(Dir, AbsDir, [file_type(directory), access(read)]),
979 ( option(recursive(true), Options)
980 -> ensure_slash(AbsDir, Prefix),
981 findall(F, ( source_file(F),
982 sub_atom(F, 0, _, _, Prefix)
983 ),
984 SrcFiles)
985 ; findall(F, ( source_file(F),
986 file_directory_name(F, AbsDir)
987 ),
988 SrcFiles)
989 ).
990directory_source_files(Dir, SrcFiles, Options) :-
991 absolute_file_name(Dir, AbsDir, [file_type(directory), access(read)]),
992 directory_files(AbsDir, Files),
993 phrase(src_files(Files, AbsDir, Options), SrcFiles).
994
995src_files([], _, _) -->
996 [].
997src_files([H|T], Dir, Options) -->
998 { file_name_extension(_, Ext, H),
999 user:prolog_file_type(Ext, prolog),
1000 \+ user:prolog_file_type(Ext, qlf),
1001 dir_file_path(Dir, H, File0),
1002 absolute_file_name(File0, File,
1003 [ file_errors(fail)
1004 | Options
1005 ])
1006 },
1007 !,
1008 [File],
1009 src_files(T, Dir, Options).
1010src_files([H|T], Dir, Options) -->
1011 { \+ special(H),
1012 option(recursive(true), Options),
1013 dir_file_path(Dir, H, SubDir),
1014 exists_directory(SubDir),
1015 !,
1016 catch(directory_files(SubDir, Files), _, fail)
1017 },
1018 !,
1019 src_files(Files, SubDir, Options),
1020 src_files(T, Dir, Options).
1021src_files([_|T], Dir, Options) -->
1022 src_files(T, Dir, Options).
1023
1024special(.).
1025special(..).
1026
1029dir_file_path(Dir, File, Path) :-
1030 ( sub_atom(Dir, _, _, 0, /)
1031 -> atom_concat(Dir, File, Path)
1032 ; atom_concat(Dir, /, TheDir),
1033 atom_concat(TheDir, File, Path)
1034 ).
1035
1036
1066
1067valid_term_position(Term, TermPos) :-
1068 valid_term_position(0, 0x7fffffffffffffff, Term, TermPos).
1069
1070valid_term_position(OuterFrom, OuterTo, _Term, TermPos),
1071 var(TermPos),
1072 OuterFrom =< OuterTo => true.
1073valid_term_position(OuterFrom, OuterTo, Var, From-To),
1074 var(Var),
1075 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
1076valid_term_position(OuterFrom, OuterTo, Atom, From-To),
1077 atom(Atom),
1078 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
1079valid_term_position(OuterFrom, OuterTo, Number, From-To),
1080 number(Number),
1081 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
1082valid_term_position(OuterFrom, OuterTo, [], From-To),
1083 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
1084valid_term_position(OuterFrom, OuterTo, String, string_position(From,To)),
1085 ( string(String)
1086 -> true
1087 ; is_of_type(codes, String)
1088 -> true
1089 ; is_of_type(chars, String)
1090 -> true
1091 ; atom(String)
1092 ),
1093 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
1094valid_term_position(OuterFrom, OuterTo, {Arg},
1095 brace_term_position(From,To,ArgPos)),
1096 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1097 valid_term_position(From, To, Arg, ArgPos).
1098valid_term_position(OuterFrom, OuterTo, [Hd|Tl],
1099 list_position(From,To,ElemsPos,none)),
1100 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1101 term_position_list_tail([Hd|Tl], _HdPart, []),
1102 maplist(valid_term_position, [Hd|Tl], ElemsPos).
1103valid_term_position(OuterFrom, OuterTo, [Hd|Tl],
1104 list_position(From, To, ElemsPos, TailPos)),
1105 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1106 term_position_list_tail([Hd|Tl], HdPart, Tail),
1107 maplist(valid_term_position(From,To), HdPart, ElemsPos),
1108 valid_term_position(Tail, TailPos).
1109valid_term_position(OuterFrom, OuterTo, Term,
1110 term_position(From,To, FFrom,FTo,SubPos)),
1111 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1112 compound_name_arguments(Term, Name, Arguments),
1113 valid_term_position(Name, FFrom-FTo),
1114 maplist(valid_term_position(From,To), Arguments, SubPos).
1115valid_term_position(OuterFrom, OuterTo, Dict,
1116 dict_position(From,To,TagFrom,TagTo,KeyValuePosList)),
1117 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1118 dict_pairs(Dict, Tag, Pairs),
1119 valid_term_position(Tag, TagFrom-TagTo),
1120 foldl(valid_term_position_dict(From,To), Pairs, KeyValuePosList, []).
1123valid_term_position(OuterFrom, OuterTo, Term,
1124 parentheses_term_position(From,To,ContentPos)),
1125 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1126 valid_term_position(From, To, Term, ContentPos).
1127valid_term_position(OuterFrom, OuterTo, _Term,
1128 quasi_quotation_position(From,To,
1129 SyntaxTerm,SyntaxPos,_ContentPos)),
1130 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1131 valid_term_position(From, To, SyntaxTerm, SyntaxPos).
1132
1133valid_term_position_from_to(OuterFrom, OuterTo, From, To) :-
1134 integer(OuterFrom),
1135 integer(OuterTo),
1136 integer(From),
1137 integer(To),
1138 OuterFrom =< OuterTo,
1139 From =< To,
1140 OuterFrom =< From,
1141 To =< OuterTo.
1142
1143:- det(valid_term_position_dict/5). 1144valid_term_position_dict(OuterFrom, OuterTo, Key-Value,
1145 KeyValuePosList0, KeyValuePosList1) :-
1146 selectchk(key_value_position(From,To,SepFrom,SepTo,Key,KeyPos,ValuePos),
1147 KeyValuePosList0, KeyValuePosList1),
1148 valid_term_position_from_to(OuterFrom, OuterTo, From, To),
1149 valid_term_position_from_to(OuterFrom, OuterTo, SepFrom, SepTo),
1150 SepFrom >= OuterFrom,
1151 valid_term_position(From, SepFrom, Key, KeyPos),
1152 valid_term_position(SepTo, To, Value, ValuePos).
1153
1168
1169:- det(term_position_list_tail/3). 1170term_position_list_tail([X|Xs], HdPart, Tail) =>
1171 HdPart = [X|HdPart2],
1172 term_position_list_tail(Xs, HdPart2, Tail).
1173term_position_list_tail(Tail0, HdPart, Tail) =>
1174 HdPart = [],
1175 Tail0 = Tail.
1176
1177
1178 1181
1182:- multifile
1183 prolog:message//1. 1184
1185prolog:message(quasi_quotation(undeclared, Syntax)) -->
1186 [ 'Undeclared quasi quotation syntax: ~w'-[Syntax], nl,
1187 'Autoloading can be defined using prolog:quasi_quotation_syntax/2'
1188 ]