34
35:- module(term_info,
36 [ get_term_info/6,
37 with_source_file/3,
38 fetch_term_info/4
39 ]). 40
41:- use_module(library(apply)). 42:- use_module(library(lists)). 43:- use_module(library(option)). 44:- use_module(library(prolog_source)). 45:- use_module(library(clambda)). 46:- use_module(library(module_files)). 47:- use_module(library(transpose)). 48:- init_expansors. 49
50:- meta_predicate
51 with_source_file(+, -, 0),
52 get_term_info(+, ?, ?, 1, -, +),
53 transverse_apply_2(1, +, ?, ?, ?). 54
55get_term_info(M, Pattern, Term, AllChk, File, Options) :-
56 module_files(M, Files),
57 member(File, Files),
58 call(AllChk, File),
59 get_term_info_file(Pattern, Term, File, Options).
60
61ti_open_source(Path, In) :-
62 b_setval(ti_open_source, yes),
63 prolog_open_source(Path, In),
64 b_setval(ti_open_source, no).
65
66with_source_file(File, In, Goal) :-
67 prolog_canonical_source(File, Path),
68 print_message(informational, format("Reading ~w", Path)),
69 setup_call_cleanup(ti_open_source(Path, In),
70 Goal,
71 prolog_close_source(In)).
72
73fetch_term_info(Pattern, Term, Options, In) :-
74 ( ( option(line(Line), Options),
75 nonvar(Line)
76 ->seek(In, 0, bof, _),
77 prolog_source:seek_to_line(In, Line),
78 once(get_term_info_fd(In, Pattern, Term, Options))
79 ; get_term_info_fd(In, Pattern, Term, Options)
80 )
81 ; fail 82 ).
83
84get_term_info_file(Pattern, Term, File, Options) :-
85 with_source_file(File, In, fetch_term_info(Pattern, Term, Options, In)).
86
87get_term_info_fd(In, PatternL, TermL, Options1) :-
88 is_list(PatternL),
89 !,
90 foldl(\ (H-D)^O1^O^select_option(H, O1, O, D),
91 [subterm_positions(TermPos)-TermPos,
92 term_position(Pos)-Pos,
93 comments(Comments)-Comments,
94 variable_names(VN)-VN,
95 module(M)-M
96 ], Options1, OptionT),
97 PatternL = [_|PatternT],
98 length(PatternT, TN),
99 length(TSPVCMLL, TN),
100 maplist(get_term_info_each(In, OptionT), TSPVCMLL),
101 transpose(TSPVCMLL, TSPVCMLT),
102 maplist(append, TSPVCMLT, TSPVCMT, TSPVCMH),
103 transverse_apply_2(get_term_info_each(In, OptionT), TSPVCMH, TSPVCMT,
104 [TermL, TermPosL, [Pos|_], VNL, CommentsL, ModuleL],
105 [_, TermPosE, _, _, _, _]),
106 maplist(subsumes_term, PatternL, TermL),
107 append(CommentsL, Comments),
108 append(VNL, VN),
109 TermPosL = [TermPosI|_],
110 arg(2, TermPosE, To),
111 findall(From, ( Comments = [StreamPos-_|_],
112 stream_position_data(char_count, StreamPos, From)
113 ; arg(1, TermPosI, From)
114 ),
115 FromL),
116 min_list(FromL, From),
117 [M|_] = ModuleL, 118 TermPos = list_position(From, To, TermPosL, none).
119get_term_info_fd(In, Pattern, Term, Options1) :-
120 should_set_line(SetLine, Options1),
121 select_option(module(M), Options1, Options, M),
122 repeat,
123 '$current_source_module'(OM),
124 read_term(In, Term, [module(OM)|Options]),
125 ( Term == end_of_file
126 ->!,
127 fail
128 ; true
129 ),
130 set_line(SetLine),
131 ( member(ModDecl, [(:- module(M, ExL)), (:- module(M, ExL, _))]),
132 subsumes_term(ModDecl, Term),
133 Term = ModDecl
134 ->'$set_source_module'(_, M),
135 forall(member(op(A, B, C), ExL), op(A, B, OM:C))
136 ; member(ModDecl, [(:- op(A, B, C))]),
137 subsumes_term(ModDecl, Term),
138 Term = ModDecl
139 ->op(A, B, OM:C)
140 ; true
141 ),
142 subsumes_term(Pattern, Term).
143
144should_set_line(posline(Pos, Line), Options) :-
145 option(term_position(Pos), Options),
146 option(line(Line), Options),
147 !.
148should_set_line(no, _).
149
150set_line(no).
151set_line(posline(Pos, Line)) :-
152 stream_position_data(line_count, Pos, Line).
153
154transverse_apply(_, ListL, ListT, ListL, EL, EL) :- maplist(=([]), ListT).
155transverse_apply(Apply, ListH1, ListT, ListL, _, EL) :-
156 maplist(\ [_|L]^L^true, ListH1, ListH),
157 transverse_apply_2(Apply, ListH, ListT, ListL, EL).
158
159transverse_apply_2(Apply, ListH, ListT1, ListL, EL) :-
160 call(Apply, EL1),
161 maplist(\ E^[E|L]^L^true, EL1, ListT1, ListT),
162 transverse_apply(Apply, ListH, ListT, ListL, EL1, EL).
163
164get_term_info_each(In, Options, [T, S, P, V, C, M]) :-
165 '$current_source_module'(OM),
166 read_term(In, T, [subterm_positions(S), term_position(P), variable_names(V),
167 comments(C), module(OM)|Options]),
168 T \== end_of_file,
169 ( member(ModDecl, [(:- module(M, _)), (:- module(M, _, _))]),
170 subsumes_term(ModDecl, T),
171 T = ModDecl
172 ->'$set_source_module'(_, M)
173 ; M = OM
174 ).
175
176:- public read_terms/3. 177
178read_terms(In, TermOptsL, Options) :-
179 read_terms_opts(TermOptsL, In, Options, TermOptsL1, TermOptsT),
180 read_terms_opts_rec(In, Options, TermOptsL1, TermOptsT, TermOptsL).
181
182read_terms_opts([], _, _, TermOptsT, TermOptsT).
183read_terms_opts([_|T], In, Options1, [TermOpts|TermOptsL], TermOptsT) :-
184 read_term_opts(In, Options1, TermOpts),
185 read_terms_opts(T, In, Options1, TermOptsL, TermOptsT).
186
187read_term_opts(In, Options1, Term-Options) :-
188 copy_term(Options1, Options),
189 read_term(In, Term, Options).
190
191read_terms_opts_rec(_, _, TermOptsL, [], TermOptsL).
192read_terms_opts_rec(In, Options1, [_|TermOptsL1 ], [TermOpts|TermOptsT], TermOptsL) :-
193 read_term_opts(In, Options1, TermOpts),
194 read_terms_opts_rec(In, Options1, TermOptsL1, TermOptsT, TermOptsL)