36
37:- module(prolog_source,
38 [ prolog_read_source_term/4, 39 read_source_term_at_location/3, 40 prolog_open_source/2, 41 prolog_close_source/1, 42 prolog_canonical_source/2, 43
44 load_quasi_quotation_syntax/2, 45
46 file_name_on_path/2, 47 file_alias_path/2, 48 path_segments_atom/2, 49 directory_source_files/3, 50 valid_term_position/2 51 ]). 52:- use_module(library(debug), [debug/3, assertion/1]). 53:- autoload(library(apply), [maplist/2, maplist/3, foldl/4]). 54:- autoload(library(error), [domain_error/2, is_of_type/2]). 55:- autoload(library(lists), [member/2, last/2, select/3, append/3, selectchk/3]). 56:- autoload(library(operators), [push_op/3, push_operators/1, pop_operators/0]). 57:- autoload(library(option), [select_option/4, option/3, option/2]). 58
59
82
83:- thread_local
84 open_source/2, 85 mode/2. 86
87:- multifile
88 requires_library/2,
89 prolog:xref_source_identifier/2, 90 prolog:xref_source_time/2, 91 prolog:xref_open_source/2, 92 prolog:xref_close_source/2, 93 prolog:alternate_syntax/4, 94 prolog:xref_update_syntax/2, 95 prolog:quasi_quotation_syntax/2. 96
97
98:- predicate_options(prolog_read_source_term/4, 4,
99 [ pass_to(system:read_clause/3, 3)
100 ]). 101:- predicate_options(read_source_term_at_location/3, 3,
102 [ line(integer),
103 offset(integer),
104 module(atom),
105 operators(list),
106 error(-any),
107 pass_to(system:read_term/3, 3)
108 ]). 109:- predicate_options(directory_source_files/3, 3,
110 [ recursive(boolean),
111 if(oneof([true,loaded])),
112 pass_to(system:absolute_file_name/3,3)
113 ]). 114
115
116 119
133
134prolog_read_source_term(In, Term, Expanded, Options) :-
135 maplist(read_clause_option, Options),
136 !,
137 select_option(subterm_positions(TermPos), Options,
138 RestOptions, TermPos),
139 read_clause(In, Term,
140 [ subterm_positions(TermPos)
141 | RestOptions
142 ]),
143 expand(Term, TermPos, In, Expanded),
144 '$current_source_module'(M),
145 update_state(Term, Expanded, M).
146prolog_read_source_term(In, Term, Expanded, Options) :-
147 '$current_source_module'(M),
148 select_option(syntax_errors(SE), Options, RestOptions0, dec10),
149 select_option(subterm_positions(TermPos), RestOptions0,
150 RestOptions, TermPos),
151 ( style_check(?(singleton))
152 -> FinalOptions = [ singletons(warning) | RestOptions ]
153 ; FinalOptions = RestOptions
154 ),
155 read_term(In, Term,
156 [ module(M),
157 syntax_errors(SE),
158 subterm_positions(TermPos)
159 | FinalOptions
160 ]),
161 expand(Term, TermPos, In, Expanded),
162 update_state(Term, Expanded, M).
163
164read_clause_option(syntax_errors(_)).
165read_clause_option(term_position(_)).
166read_clause_option(process_comment(_)).
167read_clause_option(comments(_)).
168
169:- public
170 expand/3. 171
172expand(Term, In, Exp) :-
173 expand(Term, _, In, Exp).
174
175expand(Var, _, _, Var) :-
176 var(Var),
177 !.
178expand(Term, _, _, Term) :-
179 no_expand(Term),
180 !.
181expand(Term, _, _, _) :-
182 requires_library(Term, Lib),
183 ensure_loaded(user:Lib),
184 fail.
185expand(Term, _, In, Term) :-
186 chr_expandable(Term, In),
187 !.
188expand(Term, Pos, _, Expanded) :-
189 expand_term(Term, Pos, Expanded, _).
190
191no_expand((:- if(_))).
192no_expand((:- elif(_))).
193no_expand((:- else)).
194no_expand((:- endif)).
195no_expand((:- require(_))).
196
197chr_expandable((:- chr_constraint(_)), In) :-
198 add_mode(In, chr).
199chr_expandable((handler(_)), In) :-
200 mode(In, chr).
201chr_expandable((rules(_)), In) :-
202 mode(In, chr).
203chr_expandable(<=>(_, _), In) :-
204 mode(In, chr).
205chr_expandable(@(_, _), In) :-
206 mode(In, chr).
207chr_expandable(==>(_, _), In) :-
208 mode(In, chr).
209chr_expandable(pragma(_, _), In) :-
210 mode(In, chr).
211chr_expandable(option(_, _), In) :-
212 mode(In, chr).
213
214add_mode(Stream, Mode) :-
215 mode(Stream, Mode),
216 !.
217add_mode(Stream, Mode) :-
218 asserta(mode(Stream, Mode)).
219
223
224requires_library((:- emacs_begin_mode(_,_,_,_,_)), library(emacs_extend)).
225requires_library((:- draw_begin_shape(_,_,_,_)), library(pcedraw)).
226requires_library((:- use_module(library(pce))), library(pce)).
227requires_library((:- pce_begin_class(_,_)), library(pce)).
228requires_library((:- pce_begin_class(_,_,_)), library(pce)).
229
233
234:- multifile
235 pce_expansion:push_compile_operators/1,
236 pce_expansion:pop_compile_operators/0. 237
238update_state(Raw, _, _) :-
239 Raw == (:- pce_end_class),
240 !,
241 ignore(pce_expansion:pop_compile_operators).
242update_state(Raw, _, SM) :-
243 subsumes_term((:- pce_extend_class(_)), Raw),
244 !,
245 pce_expansion:push_compile_operators(SM).
246update_state(_Raw, Expanded, M) :-
247 update_state(Expanded, M).
248
249update_state(Var, _) :-
250 var(Var),
251 !.
252update_state([], _) :-
253 !.
254update_state([H|T], M) :-
255 !,
256 update_state(H, M),
257 update_state(T, M).
258update_state((:- Directive), M) :-
259 nonvar(Directive),
260 !,
261 catch(update_directive(Directive, M), _, true).
262update_state((?- Directive), M) :-
263 !,
264 update_state((:- Directive), M).
265update_state(_, _).
266
267update_directive(Directive, Module) :-
268 prolog:xref_update_syntax(Directive, Module),
269 !.
270update_directive(module(Module, Public), _) :-
271 atom(Module),
272 is_list(Public),
273 !,
274 '$set_source_module'(Module),
275 maplist(import_syntax(_,Module, _), Public).
276update_directive(M:op(P,T,N), SM) :-
277 atom(M),
278 ground(op(P,T,N)),
279 !,
280 update_directive(op(P,T,N), SM).
281update_directive(op(P,T,N), SM) :-
282 ground(op(P,T,N)),
283 !,
284 strip_module(SM:N, M, PN),
285 push_op(P,T,M:PN).
286update_directive(style_check(Style), _) :-
287 ground(Style),
288 style_check(Style),
289 !.
290update_directive(use_module(Spec), SM) :-
291 ground(Spec),
292 catch(module_decl(Spec, Path, Public), _, fail),
293 is_list(Public),
294 !,
295 maplist(import_syntax(Path, SM, _), Public).
296update_directive(use_module(Spec, Imports), SM) :-
297 ground(Spec),
298 is_list(Imports),
299 catch(module_decl(Spec, Path, Public), _, fail),
300 is_list(Public),
301 !,
302 maplist(import_syntax(Path, SM, Imports), Public).
303update_directive(pce_begin_class_definition(_,_,_,_), SM) :-
304 pce_expansion:push_compile_operators(SM),
305 !.
306update_directive(_, _).
307
312
313import_syntax(_, _, _, Var) :-
314 var(Var),
315 !.
316import_syntax(_, M, Imports, Op) :-
317 Op = op(_,_,_),
318 \+ \+ member(Op, Imports),
319 !,
320 update_directive(Op, M).
321import_syntax(Path, SM, Imports, Syntax/4) :-
322 \+ \+ member(Syntax/4, Imports),
323 load_quasi_quotation_syntax(SM:Path, Syntax),
324 !.
325import_syntax(_,_,_, _).
326
327
341
342load_quasi_quotation_syntax(SM:Path, Syntax) :-
343 atom(Path), atom(Syntax),
344 source_file_property(Path, module(M)),
345 functor(ST, Syntax, 4),
346 predicate_property(M:ST, quasi_quotation_syntax),
347 !,
348 use_module(SM:Path, [Syntax/4]).
349load_quasi_quotation_syntax(SM:Path, Syntax) :-
350 atom(Path), atom(Syntax),
351 prolog:quasi_quotation_syntax(Syntax, Spec),
352 absolute_file_name(Spec, Path2,
353 [ file_type(prolog),
354 file_errors(fail),
355 access(read)
356 ]),
357 Path == Path2,
358 !,
359 use_module(SM:Path, [Syntax/4]).
360
366
367module_decl(Spec, Path, Decl) :-
368 absolute_file_name(Spec, Path,
369 [ file_type(prolog),
370 file_errors(fail),
371 access(read)
372 ]),
373 setup_call_cleanup(
374 prolog_open_source(Path, In),
375 read_module_decl(In, Decl),
376 prolog_close_source(In)).
377
378read_module_decl(In, Decl) :-
379 read(In, Term0),
380 read_module_decl(Term0, In, Decl).
381
382read_module_decl((:- module(_, DeclIn)), _In, Decl) =>
383 Decl = DeclIn.
384read_module_decl((:- encoding(Enc)), In, Decl) =>
385 set_stream(In, encoding(Enc)),
386 read(In, Term2),
387 read_module_decl(Term2, In, Decl).
388read_module_decl(_, _, _) =>
389 fail.
390
391
432
433:- thread_local
434 last_syntax_error/2. 435
436read_source_term_at_location(Stream, Term, Options) :-
437 retractall(last_syntax_error(_,_)),
438 seek_to_start(Stream, Options),
439 stream_property(Stream, position(Here)),
440 '$current_source_module'(DefModule),
441 option(module(Module), Options, DefModule),
442 option(operators(Ops), Options, []),
443 alternate_syntax(Syntax, Module, Setup, Restore),
444 set_stream_position(Stream, Here),
445 debug(read, 'Trying with syntax ~w', [Syntax]),
446 push_operators(Module:Ops),
447 call(Setup),
448 Error = error(Formal,_), 449 setup_call_cleanup(
450 asserta(user:thread_message_hook(_,_,_), Ref), 451 catch(qq_read_term(Stream, Term0,
452 [ module(Module)
453 | Options
454 ]),
455 Error,
456 true),
457 erase(Ref)),
458 call(Restore),
459 pop_operators,
460 ( var(Formal)
461 -> !, Term = Term0
462 ; assert_error(Error, Options),
463 fail
464 ).
465read_source_term_at_location(_, _, Options) :-
466 option(error(Error), Options),
467 !,
468 setof(CharNo:Msg, retract(last_syntax_error(CharNo, Msg)), Pairs),
469 last(Pairs, Error).
470
471assert_error(Error, Options) :-
472 option(error(_), Options),
473 !,
474 ( ( Error = error(syntax_error(Id),
475 stream(_S1, _Line1, _LinePos1, CharNo))
476 ; Error = error(syntax_error(Id),
477 file(_S2, _Line2, _LinePos2, CharNo))
478 )
479 -> message_to_string(error(syntax_error(Id), _), Msg),
480 assertz(last_syntax_error(CharNo, Msg))
481 ; debug(read, 'Error: ~q', [Error]),
482 throw(Error)
483 ).
484assert_error(_, _).
485
486
499
500alternate_syntax(prolog, _, true, true).
501alternate_syntax(Syntax, M, Setup, Restore) :-
502 prolog:alternate_syntax(Syntax, M, Setup, Restore).
503
504
508
509seek_to_start(Stream, Options) :-
510 option(line(Line), Options),
511 !,
512 seek(Stream, 0, bof, _),
513 seek_to_line(Stream, Line).
514seek_to_start(Stream, Options) :-
515 option(offset(Start), Options),
516 !,
517 seek(Stream, Start, bof, _).
518seek_to_start(_, _).
519
523
524seek_to_line(Fd, N) :-
525 N > 1,
526 !,
527 skip(Fd, 10),
528 NN is N - 1,
529 seek_to_line(Fd, NN).
530seek_to_line(_, _).
531
532
533 536
542
543qq_read_term(Stream, Term, Options) :-
544 select(syntax_errors(ErrorMode), Options, Options1),
545 ErrorMode \== error,
546 !,
547 ( ErrorMode == dec10
548 -> repeat,
549 qq_read_syntax_ex(Stream, Term, Options1, Error),
550 ( var(Error)
551 -> !
552 ; print_message(error, Error),
553 fail
554 )
555 ; qq_read_syntax_ex(Stream, Term, Options1, Error),
556 ( ErrorMode == fail
557 -> print_message(error, Error),
558 fail
559 ; ErrorMode == quiet
560 -> fail
561 ; domain_error(syntax_errors, ErrorMode)
562 )
563 ).
564qq_read_term(Stream, Term, Options) :-
565 qq_read_term_ex(Stream, Term, Options).
566
567qq_read_syntax_ex(Stream, Term, Options, Error) :-
568 catch(qq_read_term_ex(Stream, Term, Options),
569 error(syntax_error(Syntax), Context),
570 Error = error(Syntax, Context)).
571
572qq_read_term_ex(Stream, Term, Options) :-
573 stream_property(Stream, position(Here)),
574 catch(read_term(Stream, Term, Options),
575 error(syntax_error(unknown_quasi_quotation_syntax(Syntax, Module)), Context),
576 load_qq_and_retry(Here, Syntax, Module, Context, Stream, Term, Options)).
577
578load_qq_and_retry(Here, Syntax, Module, _, Stream, Term, Options) :-
579 set_stream_position(Stream, Here),
580 prolog:quasi_quotation_syntax(Syntax, Library),
581 !,
582 use_module(Module:Library, [Syntax/4]),
583 read_term(Stream, Term, Options).
584load_qq_and_retry(_Pos, Syntax, Module, Context, _Stream, _Term, _Options) :-
585 print_message(warning, quasi_quotation(undeclared, Syntax)),
586 throw(error(syntax_error(unknown_quasi_quotation_syntax(Syntax, Module)), Context)).
587
596
597prolog:quasi_quotation_syntax(html, library(http/html_write)).
598prolog:quasi_quotation_syntax(javascript, library(http/js_write)).
599
600
601 604
619
620prolog_open_source(Src, Fd) :-
621 '$push_input_context'(source),
622 catch(( prolog:xref_open_source(Src, Fd)
623 -> Hooked = true
624 ; open(Src, read, Fd),
625 Hooked = false
626 ), E,
627 ( '$pop_input_context',
628 throw(E)
629 )),
630 skip_hashbang(Fd),
631 push_operators([]),
632 '$current_source_module'(SM),
633 '$save_lex_state'(LexState, []),
634 asserta(open_source(Fd, state(Hooked, Src, LexState, SM))).
635
636skip_hashbang(Fd) :-
637 catch(( peek_char(Fd, #) 638 -> skip(Fd, 10)
639 ; true
640 ), E,
641 ( close(Fd, [force(true)]),
642 '$pop_input_context',
643 throw(E)
644 )).
645
653
654
661
662prolog_close_source(In) :-
663 call_cleanup(
664 restore_source_context(In, Hooked, Src),
665 close_source(Hooked, Src, In)).
666
667close_source(true, Src, In) :-
668 catch(prolog:xref_close_source(Src, In), _, false),
669 !,
670 '$pop_input_context'.
671close_source(_, _Src, In) :-
672 close(In, [force(true)]),
673 '$pop_input_context'.
674
675restore_source_context(In, Hooked, Src) :-
676 ( at_end_of_stream(In)
677 -> true
678 ; ignore(catch(expand(end_of_file, _, In, _), _, true))
679 ),
680 pop_operators,
681 retractall(mode(In, _)),
682 ( retract(open_source(In, state(Hooked, Src, LexState, SM)))
683 -> '$restore_lex_state'(LexState),
684 '$set_source_module'(SM)
685 ; assertion(fail)
686 ).
687
693
700
701prolog_canonical_source(Source, Src) :-
702 var(Source),
703 !,
704 Src = Source.
705prolog_canonical_source(User, user) :-
706 User == user,
707 !.
708prolog_canonical_source(Src, Id) :- 709 prolog:xref_source_identifier(Src, Id),
710 !.
711prolog_canonical_source(Source, Src) :-
712 source_file(Source),
713 !,
714 Src = Source.
715prolog_canonical_source(Source, Src) :-
716 absolute_file_name(Source, Src,
717 [ file_type(prolog),
718 access(read),
719 file_errors(fail)
720 ]),
721 !.
722
723
728
729file_name_on_path(Path, ShortId) :-
730 ( file_alias_path(Alias, Dir),
731 atom_concat(Dir, Local, Path)
732 -> ( Alias == '.'
733 -> ShortId = Local
734 ; file_name_extension(Base, pl, Local)
735 -> ShortId =.. [Alias, Base]
736 ; ShortId =.. [Alias, Local]
737 )
738 ; ShortId = Path
739 ).
740
741
746
747:- dynamic
748 alias_cache/2. 749
750file_alias_path(Alias, Dir) :-
751 ( alias_cache(_, _)
752 -> true
753 ; build_alias_cache
754 ),
755 ( nonvar(Dir)
756 -> ensure_slash(Dir, DirSlash),
757 alias_cache(Alias, DirSlash)
758 ; alias_cache(Alias, Dir)
759 ).
760
761build_alias_cache :-
762 findall(t(DirLen, AliasLen, Alias, Dir),
763 search_path(Alias, Dir, AliasLen, DirLen), Ts),
764 sort(0, >, Ts, List),
765 forall(member(t(_, _, Alias, Dir), List),
766 assert(alias_cache(Alias, Dir))).
767
768search_path('.', Here, 999, DirLen) :-
769 working_directory(Here0, Here0),
770 ensure_slash(Here0, Here),
771 atom_length(Here, DirLen).
772search_path(Alias, Dir, AliasLen, DirLen) :-
773 user:file_search_path(Alias, _),
774 Alias \== autoload, 775 Alias \== noautoload,
776 Spec =.. [Alias,'.'],
777 atom_length(Alias, AliasLen0),
778 AliasLen is 1000 - AliasLen0, 779 absolute_file_name(Spec, Dir0,
780 [ file_type(directory),
781 access(read),
782 solutions(all),
783 file_errors(fail)
784 ]),
785 ensure_slash(Dir0, Dir),
786 atom_length(Dir, DirLen).
787
788ensure_slash(Dir, Dir) :-
789 sub_atom(Dir, _, _, 0, /),
790 !.
791ensure_slash(Dir0, Dir) :-
792 atom_concat(Dir0, /, Dir).
793
794
812
813path_segments_atom(Segments, Atom) :-
814 var(Atom),
815 !,
816 ( atomic(Segments)
817 -> Atom = Segments
818 ; segments_to_list(Segments, List, [])
819 -> atomic_list_concat(List, /, Atom)
820 ; throw(error(type_error(file_path, Segments), _))
821 ).
822path_segments_atom(Segments, Atom) :-
823 atomic_list_concat(List, /, Atom),
824 parts_to_path(List, Segments).
825
826segments_to_list(Var, _, _) :-
827 var(Var), !, fail.
828segments_to_list(A/B, H, T) :-
829 segments_to_list(A, H, T0),
830 segments_to_list(B, T0, T).
831segments_to_list(A, [A|T], T) :-
832 atomic(A).
833
834parts_to_path([One], One) :- !.
835parts_to_path(List, More/T) :-
836 ( append(H, [T], List)
837 -> parts_to_path(H, More)
838 ).
839
852
853directory_source_files(Dir, SrcFiles, Options) :-
854 option(if(loaded), Options, loaded),
855 !,
856 absolute_file_name(Dir, AbsDir, [file_type(directory), access(read)]),
857 ( option(recursive(true), Options)
858 -> ensure_slash(AbsDir, Prefix),
859 findall(F, ( source_file(F),
860 sub_atom(F, 0, _, _, Prefix)
861 ),
862 SrcFiles)
863 ; findall(F, ( source_file(F),
864 file_directory_name(F, AbsDir)
865 ),
866 SrcFiles)
867 ).
868directory_source_files(Dir, SrcFiles, Options) :-
869 absolute_file_name(Dir, AbsDir, [file_type(directory), access(read)]),
870 directory_files(AbsDir, Files),
871 phrase(src_files(Files, AbsDir, Options), SrcFiles).
872
873src_files([], _, _) -->
874 [].
875src_files([H|T], Dir, Options) -->
876 { file_name_extension(_, Ext, H),
877 user:prolog_file_type(Ext, prolog),
878 \+ user:prolog_file_type(Ext, qlf),
879 dir_file_path(Dir, H, File0),
880 absolute_file_name(File0, File,
881 [ file_errors(fail)
882 | Options
883 ])
884 },
885 !,
886 [File],
887 src_files(T, Dir, Options).
888src_files([H|T], Dir, Options) -->
889 { \+ special(H),
890 option(recursive(true), Options),
891 dir_file_path(Dir, H, SubDir),
892 exists_directory(SubDir),
893 !,
894 catch(directory_files(SubDir, Files), _, fail)
895 },
896 !,
897 src_files(Files, SubDir, Options),
898 src_files(T, Dir, Options).
899src_files([_|T], Dir, Options) -->
900 src_files(T, Dir, Options).
901
902special(.).
903special(..).
904
907dir_file_path(Dir, File, Path) :-
908 ( sub_atom(Dir, _, _, 0, /)
909 -> atom_concat(Dir, File, Path)
910 ; atom_concat(Dir, /, TheDir),
911 atom_concat(TheDir, File, Path)
912 ).
913
914
944
945valid_term_position(Term, TermPos) :-
946 valid_term_position(0, 0x7fffffffffffffff, Term, TermPos).
947
948valid_term_position(OuterFrom, OuterTo, _Term, TermPos),
949 var(TermPos),
950 OuterFrom =< OuterTo => true.
951valid_term_position(OuterFrom, OuterTo, Var, From-To),
952 var(Var),
953 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
954valid_term_position(OuterFrom, OuterTo, Atom, From-To),
955 atom(Atom),
956 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
957valid_term_position(OuterFrom, OuterTo, Number, From-To),
958 number(Number),
959 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
960valid_term_position(OuterFrom, OuterTo, [], From-To),
961 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
962valid_term_position(OuterFrom, OuterTo, String, string_position(From,To)),
963 ( string(String)
964 -> true
965 ; is_of_type(codes, String)
966 -> true
967 ; is_of_type(chars, String)
968 -> true
969 ; atom(String)
970 ),
971 valid_term_position_from_to(OuterFrom, OuterTo, From, To) => true.
972valid_term_position(OuterFrom, OuterTo, {Arg},
973 brace_term_position(From,To,ArgPos)),
974 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
975 valid_term_position(From, To, Arg, ArgPos).
976valid_term_position(OuterFrom, OuterTo, [Hd|Tl],
977 list_position(From,To,ElemsPos,none)),
978 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
979 term_position_list_tail([Hd|Tl], _HdPart, []),
980 maplist(valid_term_position, [Hd|Tl], ElemsPos).
981valid_term_position(OuterFrom, OuterTo, [Hd|Tl],
982 list_position(From, To, ElemsPos, TailPos)),
983 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
984 term_position_list_tail([Hd|Tl], HdPart, Tail),
985 maplist(valid_term_position(From,To), HdPart, ElemsPos),
986 valid_term_position(Tail, TailPos).
987valid_term_position(OuterFrom, OuterTo, Term,
988 term_position(From,To, FFrom,FTo,SubPos)),
989 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
990 compound_name_arguments(Term, Name, Arguments),
991 valid_term_position(Name, FFrom-FTo),
992 maplist(valid_term_position(From,To), Arguments, SubPos).
993valid_term_position(OuterFrom, OuterTo, Dict,
994 dict_position(From,To,TagFrom,TagTo,KeyValuePosList)),
995 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
996 dict_pairs(Dict, Tag, Pairs),
997 valid_term_position(Tag, TagFrom-TagTo),
998 foldl(valid_term_position_dict(From,To), Pairs, KeyValuePosList, []).
1001valid_term_position(OuterFrom, OuterTo, Term,
1002 parentheses_term_position(From,To,ContentPos)),
1003 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1004 valid_term_position(From, To, Term, ContentPos).
1005valid_term_position(OuterFrom, OuterTo, _Term,
1006 quasi_quotation_position(From,To,
1007 SyntaxTerm,SyntaxPos,_ContentPos)),
1008 valid_term_position_from_to(OuterFrom, OuterTo, From, To) =>
1009 valid_term_position(From, To, SyntaxTerm, SyntaxPos).
1010
1011valid_term_position_from_to(OuterFrom, OuterTo, From, To) :-
1012 integer(OuterFrom),
1013 integer(OuterTo),
1014 integer(From),
1015 integer(To),
1016 OuterFrom =< OuterTo,
1017 From =< To,
1018 OuterFrom =< From,
1019 To =< OuterTo.
1020
1021:- det(valid_term_position_dict/5). 1022valid_term_position_dict(OuterFrom, OuterTo, Key-Value,
1023 KeyValuePosList0, KeyValuePosList1) :-
1024 selectchk(key_value_position(From,To,SepFrom,SepTo,Key,KeyPos,ValuePos),
1025 KeyValuePosList0, KeyValuePosList1),
1026 valid_term_position_from_to(OuterFrom, OuterTo, From, To),
1027 valid_term_position_from_to(OuterFrom, OuterTo, SepFrom, SepTo),
1028 SepFrom >= OuterFrom,
1029 valid_term_position(From, SepFrom, Key, KeyPos),
1030 valid_term_position(SepTo, To, Value, ValuePos).
1031
1046
1047:- det(term_position_list_tail/3). 1048term_position_list_tail([X|Xs], HdPart, Tail) =>
1049 HdPart = [X|HdPart2],
1050 term_position_list_tail(Xs, HdPart2, Tail).
1051term_position_list_tail(Tail0, HdPart, Tail) =>
1052 HdPart = [],
1053 Tail0 = Tail.
1054
1055
1056 1059
1060:- multifile
1061 prolog:message//1. 1062
1063prolog:message(quasi_quotation(undeclared, Syntax)) -->
1064 [ 'Undeclared quasi quotation syntax: ~w'-[Syntax], nl,
1065 'Autoloading can be defined using prolog:quasi_quotation_syntax/2'
1066 ]