33
34:- module(scasp_input,
35 [ load_source_files/1, 36 sasp_read/2, 37 scasp_load_terms/2 38 ]). 39:- use_module(library(apply)). 40:- use_module(library(lists)). 41:- use_module(library(option)). 42:- use_module(library(prolog_code)). 43
44:- use_module(common). 45:- use_module(program). 46:- use_module(source_ref). 47
52
56
57:- op(700, xfx, [#= , #<>, #< , #> , #=<, #>= ]). 58:- op(900, fy, not). 59:- op(1200, fx, #). 60:- op(950, xfx, ::). 61:- op(350, fx, [include, compute, abducible]). 62:- op(1150, fx, [table, show, pred]). 63
64 67
75
76load_source_files(Fs) :-
77 maplist(sasp_read, Fs, StmtsList),
78 append(StmtsList, Statements),
79 assert_program(Statements).
80
85
86scasp_load_terms(Terms, Options) :-
87 term_statements(Terms, Statements, Options),
88 assert_program(Statements).
89
90term_statements([], [], _).
91term_statements([H|T], Statements, Options) :-
92 sasp_statement(H, [], New, _Pos, Options),
93 add_statements(New, Tail, Statements),
94 term_statements(T, Tail, Options).
95
96
97 100
101
107
108sasp_read(File, Statements) :-
109 sasp_read(File, Statements, []).
110
111sasp_read(File, Statements, Options) :-
112 absolute_file_name(File, Path,
113 [ access(read),
114 extensions([asp,pl,''])
115 ]),
116 setup_call_cleanup(
117 open(Path, read, In),
118 sasp_read_stream_raw(Path, In, Statements,
119 [ base(Path),
120 stream(In)
121 | Options
122 ]),
123 close(In)).
124
125sasp_read_stream_raw(Path, In, Statements, Options) :-
126 setup_call_cleanup(
127 prep_read(Undo),
128 sasp_read_stream(Path, In, Statements, Options),
129 call(Undo)).
130
136
137prep_read(Undo) :-
138 convlist(update_flag,
139 [ allow_variable_name_as_functor-true
140 ], UndoList),
141 ( UndoList == []
142 -> Undo = true
143 ; comma_list(Undo, UndoList)
144 ).
145
146update_flag(Flag-Value, true) :-
147 current_prolog_flag(Flag, Value).
148update_flag(Flag-Value, set_prolog_flag(Flag, Old)) :-
149 current_prolog_flag(Flag, Old),
150 set_prolog_flag(Flag, Value).
151
155
156sasp_read_stream(Path, In, Statements, Options) :-
157 context_module(M),
158 read_term(In, Term,
159 [ module(M),
160 variable_names(VarNames),
161 subterm_positions(Pos),
162 term_position(Start)
163 ]),
164 b_setval('$term_position', Start),
165 ( Term == end_of_file
166 -> Statements = []
167 ; Term = (:- use_module(library(File))),
168 nonvar(File)
169 -> sasp_read_stream(Path, In, Statements, Options)
170 ; sasp_statement(source(Path-Start, Term), VarNames, New, Pos, Options),
171 add_statements(New, Tail, Statements),
172 sasp_read_stream(Path, In, Tail, Options)
173 ).
174
175add_statements(source(_, New), Tail, Statements) :-
176 is_list(New),
177 !,
178 append(New, Tail, Statements).
179add_statements(New, Tail, [New|Tail]).
180
194
195:- det(sasp_statement/5). 196
197sasp_statement(source(Ref, Term), VarNames, SSASP, Pos, Options),
198 blob(Ref, clause) =>
199 SSASP = source(Ref, SASP),
200 sasp_statement_(Term, VarNames, SASP, Pos, [source(Ref)|Options]).
201sasp_statement(source(Path-Start, Term), VarNames, SSASP, Pos, Options) =>
202 SSASP = source(Ref, SASP),
203 assert_scasp_source_reference(Path, Start, Ref),
204 sasp_statement_(Term, VarNames, SASP, Pos, [source(Ref)|Options]).
205sasp_statement(Term, VarNames, SSASP, Pos, Options) =>
206 SSASP = source(Ref, SASP),
207 assert_scasp_source_reference(-, 0, Ref),
208 sasp_statement_(Term, VarNames, SASP, Pos, [source(Ref)|Options]).
209
210sasp_statement_(Term, VarNames, SASP, Pos, Options) :-
211 maplist(bind_var,VarNames),
212 term_variables(Term, Vars),
213 bind_anon(Vars, 0),
214 sasp_statement(Term, SASP, Pos, Options).
215
216bind_var(Name=Var) :-
217 Var = $Name.
218
219bind_anon([], _).
220bind_anon([$Name|T], I) :-
221 atom_concat('_V', I, Name),
222 I2 is I+1,
223 bind_anon(T, I2).
224
228
229sasp_statement(Head :- Body, SASP, Pos, Options) =>
230 tpos(Pos, HP, BP),
231 sasp_predicate(Head, SASPHead, HP, Options),
232 comma_list(Body, BP, BodyList, BodyPos),
233 maplist(sasp_predicate_m(Options), BodyList, SASPBody, BodyPos),
234 SASP = (SASPHead-SASPBody).
235sasp_statement(?-(Query), SASP, Pos, Options) =>
236 tpos(Pos, QP),
237 comma_list(Query, QP, BodyList, BodyPos),
238 maplist(sasp_predicate_m(Options), BodyList, SASPBody, BodyPos),
239 SASP = c(1, SASPBody).
240sasp_statement(:-(Constraint), SASP, Pos, Options) =>
241 tpos(Pos, QP),
242 comma_list(Constraint, QP, BodyList, BodyPos),
243 maplist(sasp_predicate_m(Options), BodyList, SASPBody, BodyPos),
244 SASP = '_false_0'-SASPBody.
245sasp_statement(#Directive, SASP, Pos, Options) =>
246 tpos(Pos, DP),
247 directive(Directive, SASP, DP, Options).
248sasp_statement(Head, SASP, Pos, Options), callable(Head) =>
249 sasp_predicate(Head, SASPHead, Pos, Options),
250 SASP = (SASPHead-[]).
251
252tpos(parentheses_term_position(_,_,Pos), HP, BP) :-
253 nonvar(Pos),
254 !,
255 tpos(Pos, HP, BP).
256tpos(term_position(_,_,_,_,[HP,BP]), HP, BP).
257
258tpos(parentheses_term_position(_,_,Pos), P) :-
259 nonvar(Pos),
260 !,
261 tpos(Pos, P).
262tpos(term_position(_,_,_,_,[P]), P).
263
264
270
271sasp_predicate_m(Options, Term, ASPTerm, Pos) :-
272 sasp_predicate(Term, ASPTerm, Pos, Options).
273
274sasp_predicate(Pred, ASPPred, PPos, Options) :-
275 nonvar(PPos),
276 PPos = parentheses_term_position(_,_,Pos),
277 !,
278 sasp_predicate(Pred, ASPPred, Pos, Options).
279sasp_predicate(not(Pred), not(ASPPred),
280 term_position(_,_,_,_,[Pos]), Options) :-
281 !,
282 sasp_predicate(Pred, ASPPred, Pos, Options).
283sasp_predicate(-(Pred), ASPPred,
284 term_position(_,_,_,_,[_Pos]), _Options) :-
285 !,
286 Pred =.. [Name|Args0],
287 functor(Pred, Name, Arity),
288 asp_prefix(Name, Arity, ASPName),
289 atom_concat(c_, ASPName, ASPNameNeg),
290 maplist(asp_term, Args0, Args),
291 ASPPred =.. [ASPNameNeg|Args].
292sasp_predicate(Pred, error, Pos, Options) :-
293 illegal_pred(Pred),
294 !,
295 sasp_syntax_error(invalid_predicate(Pred), Pos, Options).
296sasp_predicate(Pred, SASPPred, _, _Options) :-
297 Pred =.. [Name|Args0],
298 functor(Pred, Name, Arity),
299 maplist(asp_term, Args0, Args),
300 ( atom_concat(-, PName, Name) 301 -> asp_prefix(PName, Arity, ASPName),
302 atom_concat(c_, ASPName, ASPNameNeg),
303 SASPPred =.. [ASPNameNeg|Args]
304 ; asp_prefix(Name, Arity, ASPName),
305 SASPPred =.. [ASPName|Args]
306 ).
307
308asp_term(Term, Term).
309
310asp_prefix(Name, 2, ASPName) :-
311 operator(Name, _, _),
312 !,
313 ASPName = Name.
314asp_prefix(Name, Arity, ASPName) :-
315 builtin(Name/Arity),
316 !,
317 ASPName = Name.
318asp_prefix(Name, Arity, ASPName) :-
319 handle_prefixes(Name, ASPName0),
320 join_functor(ASPName, ASPName0, Arity).
321
327
328handle_prefixes(Fi, Fo) :-
329 needs_dummy_prefix(Fi),
330 !,
331 atom_concat(d_, Fi, Fo).
332handle_prefixes(F, F).
333
334needs_dummy_prefix(F) :-
335 has_prefix(F, _),
336 !.
337needs_dummy_prefix(F) :-
338 reserved_prefix(F),
339 !.
340needs_dummy_prefix(F) :-
341 sub_atom(F, 0, _, _, '_').
342
346
347builtin(write/1).
348builtin(writef/2).
349builtin(nl/0).
350
351illegal_pred($_).
352illegal_pred(_;_).
353
357
358directive(include(File), Statements, _, Options) =>
359 option(base(Base), Options),
360 absolute_file_name(File, Path,
361 [ access(read),
362 extensions([asp,pl,'']),
363 relative_to(Base)
364 ]),
365 sasp_read(Path, Statements).
366directive(table(Pred), Statements, _, _) =>
367 Statements = (:- table(Pred)).
368directive(show(Pred), Statements, _, _) =>
369 Statements = (:- show(Pred)).
370directive(pred(Pred::Template), Statements, Pos, Options) =>
371 tpos(Pos, Pos1),
372 tpos(Pos1, PPos, _),
373 sasp_predicate(Pred, SASPPred, PPos, Options),
374 Statements = (:- pred(SASPPred::Template)).
375directive(abducible(Pred), Rules, Pos, Options) =>
376 sasp_predicate(Pred, ASPPred, Pos, Options),
377 abducible_rules(ASPPred, Rules, Options).
378directive(Directive, Statements, Pos, Options) =>
379 sasp_syntax_error(invalid_directive(Directive), Pos, Options),
380 Statements = [].
381
382abducible_rules(Head,
383 [ source(Ref, Head - [ not AHead, abducible_1(Head) ]),
384 source(Ref, AHead - [ not Head ]),
385 source(Ref, abducible_1(Head) - [ not '_abducible_1'(Head) ]),
386 source(Ref, '_abducible_1'(Head) - [ not abducible_1(Head) ])
387 ], Options) :-
388 option(source(Ref), Options, no_path-no_position),
389 Head =.. [F|Args],
390 atom_concat('_', F, AF),
391 AHead =.. [AF|Args].
392
396
397sasp_syntax_error(Error, Pos, Options) :-
398 error_position(Pos, EPos, Options),
399 print_message(error, sasp_error(Error, EPos)).
400
401error_position(Pos, pos(File, Line, Col), Options) :-
402 option(base(File), Options),
403 option(stream(In), Options),
404 prolog_load_context(term_position, Start),
405 arg(1, Pos, StartChar),
406 stream_property(In, position(Here)),
407 setup_call_cleanup(
408 set_stream_position(In, Start),
409 ( read_string(In, StartChar, _),
410 stream_property(In, position(AtError))
411 ),
412 set_stream_position(In, Here)),
413 stream_position_data(line_count, AtError, Line),
414 stream_position_data(line_position, AtError, Col).
415
416
421
422comma_list(Body, Pos, BodyList, PosList) :-
423 comma_list(Body, Pos, BodyList, [], PosList, []).
424
425comma_list(Term, PPos, TL0, TL, PL0, PL) :-
426 nonvar(PPos),
427 PPos = parentheses_term_position(_,_,Pos),
428 !,
429 comma_list(Term, Pos, TL0, TL, PL0, PL).
430comma_list((A,B), term_position(_,_,_,_,[AP, BP]), TL0, TL, PL0, PL) :-
431 !,
432 comma_list(A, AP, TL0, TL1, PL0, PL1),
433 comma_list(B, BP, TL1, TL, PL1, PL).
434comma_list(One, Pos, [One|TL], TL, [Pos|PL], PL).
435
436 439
440:- multifile
441 prolog:message//1. 442
443prolog:message(sasp_error(Error, EPos)) -->
444 position(EPos),
445 error(Error).
446
447position(pos(File, Line, Col)) -->
448 !,
449 [ '~w:~w:~w: '-[File, Line, Col] ].
450position(_) -->
451 [].
452
453error(invalid_directive(Directive)) -->
454 [ 'sCASP: invalid directive ~p'-[Directive] ]