1:- module(scasp_json,
2 [ scasp_results_json/2 3 ]). 4:- use_module(output). 5:- use_module(options). 6:- use_module(clp/disequality). 7:- use_module(clp/clpq). 8:- use_module(source_ref).
38:- det(scasp_results_json/2). 39scasp_results_json(Result, Dict) :-
40 _{ query: Query,
41 answers: Answers
42 } :< Result,
43 Dict0 = scasp_result{ solver: Version,
44 query: JQuery,
45 answers: JAnswers
46 },
47 scasp_version(Version),
48 query_json(Query, JQuery),
49 maplist(answer_json, Answers, JAnswers),
50 copy_dict_slots([cpu-time, inputs], Dict0, Dict).
51
52copy_dict_slots(Slots, Dict0, Dict) :-
53 foldl(copy_dict_slot, Slots, Dict0, Dict).
54
55copy_dict_slot(Name, Dict0, Dict), atom(Name) =>
56 ( Value = Dict0.get(Name)
57 -> Dict = Dict0.put(Name, Value)
58 ; Dict0 = Dict
59 ).
60copy_dict_slot(Name-To, Dict0, Dict) =>
61 ( Value = Dict0.get(Name)
62 -> Dict = Dict0.put(To, Value)
63 ; Dict0 = Dict
64 ).
65
66
67:- meta_predicate query_json(:, -). 68:- det(query_json/2). 69query_json(_:Query, JQuery), is_list(Query) =>
70 delete(Query, o_nmr_check, Query1),
71 delete(Query1, true, Query2),
72 plain_term_json(Query2, JQuery).
73query_json(_:Query, JQuery) =>
74 comma_list(Query, List),
75 plain_term_json(List, JQuery).
79:- det(answer_json/2). 80answer_json(Answer, Dict),
81 _{ answer:Counter,
82 bindings:Bindings,
83 model:Model,
84 tree:_:Tree,
85 time:Time
86 } :< Answer =>
87 Dict = scasp_answer{answer: Counter,
88 time: Time.cpu,
89 bindings: JBindings,
90 model: JModel,
91 tree: JTree,
92 constraints: Constraints},
93 maplist(binding_json, Bindings, Pairs),
94 dict_create(JBindings, #, Pairs),
95 maplist(model_term_json, Model, JModel),
96 tree_json(Tree, JTree),
97 constraints_json(t(Bindings,Model,JTree), Constraints).
98answer_json(Answer, Dict),
99 _{ answer:Counter,
100 bindings:Bindings,
101 model:Model,
102 time:Time
103 } :< Answer =>
104 Dict = scasp_answer{answer: Counter,
105 time: Time.cpu,
106 bindings: JBindings,
107 model: JModel,
108 constraints: Constraints},
109 maplist(binding_json, Bindings, Pairs),
110 dict_create(JBindings, #, Pairs),
111 maplist(model_term_json, Model, JModel),
112 constraints_json(t(Bindings,Model), Constraints).
113
114binding_json(Name=Value, Name-JValue) :-
115 model_term_json(Value, JValue).
116
117tree_json(Root-Children, Dict) =>
118 Dict = #{ node: JRoot,
119 children: JChildren },
120 node_json(Root, JRoot),
121 maplist(tree_json, Children, JChildren).
122
123node_json(chs(Node), Dict) =>
124 model_term_json(Node, Dict0),
125 Dict = Dict0.put(chs, true).
126node_json(assume(Node), Dict) =>
127 model_term_json(Node, Dict0),
128 Dict = Dict0.put(assume, true).
129node_json(proved(Node), Dict) =>
130 model_term_json(Node, Dict0),
131 Dict = Dict0.put(proved, true).
132node_json(abduced(Node), Dict) =>
133 model_term_json(Node, Dict0),
134 Dict = Dict0.put(abduced, true).
135node_json(goal_origin(Node, Origin), Dict) =>
136 scasp_source_reference_file_line(Origin, File, Line),
137 node_json(Node, Dict0),
138 Dict1 = Dict0.put(source_file, File),
139 Dict = Dict1.put(source_line, Line).
140node_json(Node, Dict) =>
141 model_term_json(Node, Dict).
146:- det(model_term_json/2). 147model_term_json(not(-Term), Dict) =>
148 Dict = scasp_model_term{truth: likely, value: TermJSON},
149 module_term_json(Term, TermJSON).
150model_term_json(-Term, Dict) =>
151 Dict = scasp_model_term{truth: false, value: TermJSON},
152 module_term_json(Term, TermJSON).
153model_term_json(not(Term), Dict) =>
154 Dict = scasp_model_term{truth: unlikely, value: TermJSON},
155 module_term_json(Term, TermJSON).
156model_term_json(Term, Dict) =>
157 Dict = scasp_model_term{truth: true, value: TermJSON},
158 module_term_json(Term, TermJSON).
159
160module_term_json(M:Term, Dict) =>
161 plain_term_json(Term, Dict0),
162 Dict = Dict0.put(module, M).
163module_term_json(Term, Dict) =>
164 plain_term_json(Term, Dict).
168:- det(plain_term_json/2). 169plain_term_json(Var, Dict), var(Var) =>
170 ( ovar_var_name(Var, Name)
171 -> Dict = prolog{type: var,
172 name: Name}
173 ; ovar_is_singleton(Var)
174 -> Dict = prolog{type: var}
175 ).
176plain_term_json(Var, Dict), var_number(Var, Num) =>
177 ( Num == '_'
178 -> Dict = prolog{type: var}
179 ; format(string(S), '~p', [Var]),
180 Dict = prolog{type: var,
181 name: S}
182 ).
183plain_term_json(Atom, Dict), atom(Atom) =>
184 Dict = atom{type:atom, value:Atom}.
185plain_term_json(Num, Dict), rational(Num, N, D) =>
186 ( current_prolog_flag(scasp_real, Decimals),
187 ( integer(Decimals)
188 -> truncate(Num, Decimals, Value)
189 ; Decimals == float
190 -> Value is float(Num)
191 )
192 -> Dict = prolog{type:number, value:Value}
193 ; Dict = prolog{type:rational, numerator:N, denominator:D}
194 ).
195plain_term_json(Num, Dict), number(Num) =>
196 Dict = prolog{type:number, value:Num}.
197plain_term_json(List, JList), is_list(List) =>
198 maplist(plain_term_json, List, JList).
199plain_term_json(Compound, Dict), compound(Compound) =>
200 compound_name_arguments(Compound, Name, Arguments),
201 Dict = prolog{type:compound, functor:Name, args:JArgs},
202 maplist(plain_term_json, Arguments, JArgs).
203
204truncate(Rat, Decimals, Value) :-
205 Z is Rat * 10**Decimals,
206 ZA is truncate(Z),
207 Value is float(ZA / 10**Decimals).
211:- det(constraints_json/2). 212constraints_json(Term, Dict) :-
213 term_attvars(Term, Attvars),
214 include(has_constraints, Attvars, CVars),
215 copy_term(CVars, Copy),
216 inline_constraints(Copy, []),
217 maplist(constraint_json, Copy, Constraints),
218 dict_create(Dict, #, Constraints).
219
220has_constraints(Var) :-
221 get_neg_var(Var, _List),
222 !.
223has_constraints(Var) :-
224 is_clpq_var(Var).
225
226constraint_json('| '(Var, {'\u2209'(Var, List)}), Pair) =>
227 Pair = Name-constraint{ type: not_in, set: JList},
228 var_name(Var, Name),
229 maplist(plain_term_json, List, JList).
230constraint_json('| '(Var, {Term}), Pair) =>
231 Pair = Name-constraint{ type: clpq, constraints: Constraints},
232 var_name(Var, Name),
233 comma_list(Term, Constraints0),
234 maplist(clpq_json(Var), Constraints0, Constraints).
235
236var_name('$VAR'(Name0), Name) =>
237 Name = Name0.
238var_name(Var, Name), ovar_var_name(Var, Name0) =>
239 Name = Name0.
240
241clpq_json(Var, Term, Dict), Term =.. [Op, Var, Arg] =>
242 Dict = constraint{type: Op, value: JArg},
243 plain_term_json(Arg, JArg).
244
245
246:- multifile
247 json:json_dict_pairs/2. 248
249json:json_dict_pairs(Dict, Pairs) :-
250 is_dict(Dict, Tag),
251 order(Tag, Order),
252 dict_keys(Dict, All),
253 sort(Order, Ordered),
254 ord_subtract(All, Ordered, Unordered),
255 phrase(json_pairs(Order, Dict), Pairs, Pairs1),
256 phrase(json_pairs(Unordered, Dict), Pairs1).
257
258json_pairs([], _) -->
259 [].
260json_pairs([H|T], Dict) -->
261 ( {get_dict(H, Dict, Value)}
262 -> [H-Value]
263 ; []
264 ),
265 json_pairs(T, Dict).
266
267order(scasp_result, [solver,inputs,query,time,answers]).
268order(scasp_answer, [answer,time,bindings,model,tree]).
269order(scasp_model_term, [truth, value, chs, assume, proved]).
270order(prolog, [type,functor,numerator,denominator,name,value]).
271order(constraint, [type,set,constraints,value])
s(CASP)
JSON I/O*/