New upstream version 8.1.30+dfsg
Lev Lamberov
3 years ago
142 | 142 | set(INSTALL_TESTS_DIR ${SWIPL_INSTALL_PREFIX}/test) |
143 | 143 | endif() |
144 | 144 | |
145 | if(NOT SWIPL_PKG_NAME) | |
146 | if(SWIPL_INSTALL_DIR STREQUAL "swi-prolog") | |
147 | set(SWIPL_PKG_NAME ${SWIPL_INSTALL_DIR}) | |
148 | else() | |
149 | set(SWIPL_PKG_NAME "swipl") | |
150 | endif() | |
151 | endif() | |
152 | ||
145 | 153 | if(MSVC) |
146 | 154 | add_compile_options(/W3) |
147 | 155 | else() |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1985-2014, University of Amsterdam, | |
5 | Copyright (c) 1985-2020, University of Amsterdam, | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
179 | 180 | ( Vars == v |
180 | 181 | -> findall(Templ, Goal, List), |
181 | 182 | List \== [] |
182 | ; findall(Vars-Templ, Goal, Answers), | |
183 | bind_bagof_keys(Answers,_), | |
183 | ; alloc_bind_key_list(Vars, VDict), | |
184 | findall(Vars-Templ, Goal, Answers), | |
185 | bind_bagof_keys(Answers, VDict), | |
184 | 186 | keysort(Answers, Sorted), |
185 | 187 | pick(Sorted, Vars, List) |
186 | 188 | ). |
189 | ||
190 | %! alloc_bind_key_list(+Vars, -VDict) is det. | |
191 | % | |
192 | % Pre-allocate the variable dictionary used by bind_bagof_keys/2. By | |
193 | % pre-allocating this list all variables bound become references from | |
194 | % the `Vars` of each answer to this dictionary. If we do not | |
195 | % preallocate we create a huge reference chain from VDict through each | |
196 | % of the answers, causing serious slowdown in the subsequent keysort. | |
197 | % | |
198 | % The slowdown was discovered by Jan Burse. | |
199 | ||
200 | alloc_bind_key_list(Vars, VDict) :- | |
201 | functor(Vars, _, Count), | |
202 | length(List, Count), | |
203 | '$append'(List, _, VDict). | |
187 | 204 | |
188 | 205 | %! bind_bagof_keys(+VarsTemplPairs, -SharedVars) |
189 | 206 | % |
242 | 259 | -> findall(Templ, Goal, Answers), |
243 | 260 | Answers \== [], |
244 | 261 | sort(Answers, List) |
245 | ; findall(Vars-Templ, Goal, Answers), | |
262 | ; alloc_bind_key_list(Vars, VDict), | |
263 | findall(Vars-Templ, Goal, Answers), | |
246 | 264 | ( ground(Answers) |
247 | -> sort(Answers,Sorted), | |
248 | pick(Sorted,Vars,List) | |
249 | ; bind_bagof_keys(Answers,_VDict), | |
265 | -> sort(Answers, Sorted), | |
266 | pick(Sorted, Vars, List) | |
267 | ; bind_bagof_keys(Answers, VDict), | |
250 | 268 | sort(Answers, Sorted), |
251 | 269 | pick(Sorted, Vars, Listu), |
252 | sort(Listu,List) % Listu ordering may be nixed by Vars | |
270 | sort(Listu, List) % Listu ordering may be nixed by Vars | |
253 | 271 | ) |
254 | 272 | ). |
3760 | 3760 | -> true |
3761 | 3761 | ; '$type_error'(callable, X) |
3762 | 3762 | ). |
3763 | '$must_be'(acyclic, X) :- !, | |
3764 | ( acyclic_term(X) | |
3765 | -> true | |
3766 | ; '$domain_error'(acyclic_term, X) | |
3767 | ). | |
3763 | 3768 | '$must_be'(oneof(Type, Domain, List), X) :- !, |
3764 | 3769 | '$must_be'(Type, X), |
3765 | 3770 | ( memberchk(X, List) |
54 | 54 | |
55 | 55 | start_tabling/3, % +Closure, +Wrapper, :Worker |
56 | 56 | start_subsumptive_tabling/3,% +Closure, +Wrapper, :Worker |
57 | moded_start_tabling/5, % +Closure, +Wrapper, :Worker, :Variant, ?ModeArgs | |
57 | start_abstract_tabling/3, % +Closure, +Wrapper, :Worker | |
58 | start_moded_tabling/5, % +Closure, +Wrapper, :Worker, | |
59 | % :Variant, ?ModeArgs | |
58 | 60 | |
59 | 61 | '$tbl_answer'/4, % +Trie, -Return, -ModeArgs, -Delay |
60 | 62 | |
73 | 75 | not_exists(0), |
74 | 76 | tabled_call(0), |
75 | 77 | start_tabling(+, +, 0), |
76 | start_tabling(+, +, 0, +, ?), | |
78 | start_abstract_tabling(+, +, 0), | |
79 | start_moded_tabling(+, +, 0, +, ?), | |
77 | 80 | current_table(:, -), |
78 | 81 | abolish_table_subgoals(:), |
79 | 82 | '$wfs_call'(0, :). |
270 | 273 | prolog_listen(untable, untable_reconsult). |
271 | 274 | |
272 | 275 | |
273 | %! start_tabling(:Wrapper, :Implementation) | |
274 | % | |
275 | % Execute Implementation using tabling. This predicate should not | |
276 | % be called directly. The table/1 directive causes a predicate to | |
277 | % be translated into a renamed implementation and a wrapper that | |
278 | % involves this predicate. | |
279 | % | |
280 | % @compat This interface may change or disappear without notice | |
281 | % from future versions. | |
282 | ||
283 | 276 | '$wrap_tabled'(Head, Options) :- |
284 | 277 | get_dict(mode, Options, subsumptive), |
285 | 278 | !, |
286 | 279 | set_pattributes(Head, Options), |
287 | 280 | '$wrap_predicate'(Head, table, Closure, Wrapped, |
288 | 281 | start_subsumptive_tabling(Closure, Head, Wrapped)). |
282 | '$wrap_tabled'(Head, Options) :- | |
283 | get_dict(subgoal_abstract, Options, _Abstract), | |
284 | !, | |
285 | set_pattributes(Head, Options), | |
286 | '$wrap_predicate'(Head, table, Closure, Wrapped, | |
287 | start_abstract_tabling(Closure, Head, Wrapped)). | |
289 | 288 | '$wrap_tabled'(Head, Options) :- |
290 | 289 | !, |
291 | 290 | set_pattributes(Head, Options), |
310 | 309 | tabled_attribute(dynamic). |
311 | 310 | tabled_attribute(tshared). |
312 | 311 | tabled_attribute(max_answers). |
313 | tabled_attribute(abstract_subgoal). | |
312 | tabled_attribute(subgoal_abstract). | |
314 | 313 | tabled_attribute(answer_abstract). |
315 | 314 | |
315 | %! start_tabling(:Closure, :Wrapper, :Implementation) | |
316 | % | |
317 | % Execute Implementation using tabling. This predicate should not be | |
318 | % called directly. The table/1 directive causes a predicate to be | |
319 | % translated into a renamed implementation and a wrapper that involves | |
320 | % this predicate. | |
321 | % | |
322 | % @arg Closure is the wrapper closure to find the predicate quickly. | |
323 | % It is also allowed to pass nothing. In that cases the predicate is | |
324 | % looked up using Wrapper. We suggest to pass `0` in this case. | |
325 | % | |
326 | % @compat This interface may change or disappear without notice | |
327 | % from future versions. | |
316 | 328 | |
317 | 329 | start_tabling(Closure, Wrapper, Worker) :- |
318 | 330 | '$tbl_variant_table'(Closure, Wrapper, Trie, Status, Skeleton), |
331 | start_tabling_2(Closure, Wrapper, Worker, Trie, Status, Skeleton). | |
332 | ||
333 | start_tabling_2(Closure, Wrapper, Worker, Trie, Status, Skeleton) :- | |
319 | 334 | tdebug(deadlock, 'Got table ~p, status ~p', [Trie, Status]), |
320 | 335 | ( Status == complete |
321 | 336 | -> trie_gen_compiled(Trie, Skeleton) |
341 | 356 | tdebug(schedule, 'Leader ~p done, status = ~p', [Goal, LStatus]), |
342 | 357 | done_leader(LStatus, Fresh, Skeleton, Clause). |
343 | 358 | |
344 | ||
345 | 359 | %! restart_tabling(+Closure, +Wrapper, +Worker) |
346 | 360 | % |
347 | 361 | % We were aborted due to a deadlock. Simply retry. We sleep a very |
356 | 370 | sleep(0.000001), |
357 | 371 | start_tabling(Closure, Wrapper, Worker). |
358 | 372 | |
359 | ||
360 | %! start_subsumptive_tabling(:Wrapper, :Implementation) | |
373 | restart_abstract_tabling(Closure, Wrapper, Worker) :- | |
374 | tdebug(user_goal(Wrapper, Goal)), | |
375 | tdebug(deadlock, 'Deadlock running ~p; retrying', [Goal]), | |
376 | sleep(0.000001), | |
377 | start_abstract_tabling(Closure, Wrapper, Worker). | |
378 | ||
379 | %! start_subsumptive_tabling(:Closure, :Wrapper, :Implementation) | |
361 | 380 | % |
362 | 381 | % (*) We should __not__ use trie_gen_compiled/2 here as this will |
363 | 382 | % enumerate all answers while '$tbl_answer_update_dl'/2 uses the |
403 | 422 | [GenSkeleton+Skeleton]). |
404 | 423 | |
405 | 424 | unify_subsumptive(X,X). |
425 | ||
426 | %! start_abstract_tabling(:Closure, :Wrapper, :Worker) | |
427 | % | |
428 | % Deal with ``table p/1 as subgoal_abstract(N)``. This is a merge | |
429 | % between variant and subsumptive tabling. If the goal is not | |
430 | % abstracted this is simple variant tabling. If the goal is abstracted | |
431 | % we must solve the more general goal and use answers from the | |
432 | % abstract table. | |
433 | % | |
434 | % Wrapper is e.g., user:p(s(s(s(X))),Y) | |
435 | % Worker is e.g., call(<closure>(p/2)(s(s(s(X))),Y)) | |
436 | ||
437 | start_abstract_tabling(Closure, Wrapper, Worker) :- | |
438 | '$tbl_abstract_table'(Closure, Wrapper, Trie, _Abstract, Status, Skeleton), | |
439 | tdebug(abstract, 'Wrapper=~p, Worker=~p, Skel=~p', | |
440 | [Wrapper, Worker, Skeleton]), | |
441 | ( is_most_general_term(Skeleton) % TBD: Fill and test Abstract | |
442 | -> start_tabling_2(Closure, Wrapper, Worker, Trie, Status, Skeleton) | |
443 | ; Status == complete | |
444 | -> '$tbl_answer_update_dl'(Trie, Skeleton) | |
445 | ; functor(Status, fresh, 2) | |
446 | -> '$tbl_table_status'(Trie, _, GenWrapper, GenSkeleton), | |
447 | abstract_worker(Worker, GenWrapper, GenWorker), | |
448 | catch(create_abstract_table(Trie, Status, Skeleton, GenSkeleton, GenWrapper, | |
449 | GenWorker), | |
450 | deadlock, | |
451 | restart_abstract_tabling(Closure, Wrapper, Worker)) | |
452 | ; Status == invalid | |
453 | -> '$tbl_table_status'(Trie, _, GenWrapper, GenSkeleton), | |
454 | reeval(ATrie, GenWrapper, GenSkeleton), | |
455 | Wrapper = GenWrapper, | |
456 | '$tbl_answer_update_dl'(ATrie, Skeleton) | |
457 | ; shift(call_info(GenSkeleton, Skeleton, Status)), | |
458 | unify_subsumptive(Skeleton, GenSkeleton) | |
459 | ). | |
460 | ||
461 | create_abstract_table(Trie, Fresh, Skeleton, GenSkeleton, Wrapper, Worker) :- | |
462 | tdebug(Fresh = fresh(SCC, WorkList)), | |
463 | tdebug(wl_goal(WorkList, Goal, _)), | |
464 | tdebug(schedule, 'Created component ~d for ~p', [SCC, Goal]), | |
465 | setup_call_catcher_cleanup( | |
466 | '$idg_set_current'(OldCurrent, Trie), | |
467 | run_leader(GenSkeleton, Worker, Fresh, LStatus, _Clause), | |
468 | Catcher, | |
469 | finished_leader(OldCurrent, Catcher, Fresh, Wrapper)), | |
470 | tdebug(schedule, 'Leader ~p done, status = ~p', [Goal, LStatus]), | |
471 | Skeleton = GenSkeleton, | |
472 | done_abstract_leader(LStatus, Fresh, GenSkeleton, Trie). | |
473 | ||
474 | abstract_worker(_:call(Term), _M:GenWrapper, call(GenTerm)) :- | |
475 | functor(Term, Closure, _), | |
476 | GenWrapper =.. [_|Args], | |
477 | GenTerm =.. [Closure|Args]. | |
478 | ||
479 | :- '$hide'((done_abstract_leader/4)). | |
480 | ||
481 | done_abstract_leader(complete, _Fresh, Skeleton, Trie) :- | |
482 | !, | |
483 | '$tbl_answer_update_dl'(Trie, Skeleton). | |
484 | done_abstract_leader(final, fresh(SCC, _Worklist), Skeleton, Trie) :- | |
485 | !, | |
486 | '$tbl_free_component'(SCC), | |
487 | '$tbl_answer_update_dl'(Trie, Skeleton). | |
488 | done_abstract_leader(_,_,_,_). | |
489 | ||
490 | %! done_leader(+Status, +Fresh, +Skeleton, -Clause) | |
491 | % | |
492 | % Called on completion of a table. Possibly destroys the component and | |
493 | % generates the answers from the complete table. The last cases deals | |
494 | % with leaders that are merged into a higher SCC (and thus no longer a | |
495 | % leader). | |
406 | 496 | |
407 | 497 | :- '$hide'((done_leader/4, finished_leader/4)). |
408 | 498 | |
506 | 596 | dependency(SrcSkeleton, Continuation, Skeleton, WorkList, AllDelays)) |
507 | 597 | ). |
508 | 598 | |
509 | %! moded_start_tabling(+Closure, :Wrapper, :Implementation, +Variant, +ModeArgs) | |
599 | %! start_moded_tabling(+Closure, :Wrapper, :Implementation, +Variant, +ModeArgs) | |
510 | 600 | % |
511 | 601 | % As start_tabling/2, but in addition separates the data stored in the |
512 | 602 | % answer trie in the Variant and ModeArgs. |
515 | 605 | '$set_predicate_attribute'(Head, tabled, true), |
516 | 606 | '$wrap_predicate'(Head, table, Closure, Wrapped, |
517 | 607 | ( ModeTest, |
518 | moded_start_tabling(Closure, Head, Wrapped, | |
608 | start_moded_tabling(Closure, Head, Wrapped, | |
519 | 609 | WrapperNoModes, ModeArgs) |
520 | 610 | )). |
521 | 611 | |
522 | 612 | |
523 | moded_start_tabling(Closure, Wrapper, Worker, WrapperNoModes, ModeArgs) :- | |
613 | start_moded_tabling(Closure, Wrapper, Worker, WrapperNoModes, ModeArgs) :- | |
524 | 614 | '$tbl_moded_variant_table'(Closure, WrapperNoModes, Trie, Status, Skeleton), |
525 | 615 | ( Status == complete |
526 | 616 | -> moded_gen_answer(Trie, Skeleton, ModeArgs) |
698 | 788 | %! tnot(:Goal) |
699 | 789 | % |
700 | 790 | % Tabled negation. |
791 | % | |
792 | % (*): Only variant tabling is allowed under tnot/1. | |
701 | 793 | |
702 | 794 | tnot(Goal0) :- |
703 | 795 | '$tnot_implementation'(Goal0, Goal), % verifies Goal is tabled |
712 | 804 | ; negation_suspend(Goal, Skeleton, Status) |
713 | 805 | ) |
714 | 806 | ; tdebug(tnot, 'tnot: ~p: fresh', [Goal]), |
715 | ( call(Goal), | |
807 | ( '$wrapped_implementation'(Goal, table, Implementation), % see (*) | |
808 | functor(Implementation, Closure, _), | |
809 | start_tabling(Closure, Goal, Implementation), | |
716 | 810 | fail |
717 | 811 | ; '$tbl_existing_variant_table'(_, Goal, Trie, NewStatus, NewSkeleton), |
718 | 812 | tdebug(tnot, 'tnot: fresh ~p now ~p', [Goal, NewStatus]), |
900 | 994 | abolish_table_subgoals(SubGoal0) :- |
901 | 995 | '$tbl_implementation'(SubGoal0, M:SubGoal), |
902 | 996 | !, |
903 | forall(( '$tbl_variant_table'(VariantTrie), | |
904 | trie_gen(VariantTrie, M:SubGoal, Trie) | |
905 | ), | |
906 | '$tbl_destroy_table'(Trie)). | |
997 | '$must_be'(acyclic, SubGoal), | |
998 | ( '$tbl_variant_table'(VariantTrie), | |
999 | trie_gen(VariantTrie, M:SubGoal, Trie), | |
1000 | '$tbl_destroy_table'(Trie), | |
1001 | fail | |
1002 | ; true | |
1003 | ). | |
907 | 1004 | abolish_table_subgoals(_). |
908 | 1005 | |
909 | 1006 | %! abolish_module_tables(+Module) is det. |
1014 | 1111 | system:term_expansion/2. |
1015 | 1112 | |
1016 | 1113 | wrappers(Spec, M) --> |
1017 | { tabling_defaults([ table_incremental-(incremental=true), | |
1018 | table_shared-(tshared=true), | |
1019 | table_subsumptive-((mode)=subsumptive) | |
1020 | ], | |
1021 | #{}, Defaults) | |
1114 | { tabling_defaults( | |
1115 | [ (table_incremental=true) - (incremental=true), | |
1116 | (table_shared=true) - (tshared=true), | |
1117 | (table_subsumptive=true) - ((mode)=subsumptive), | |
1118 | call(subgoal_size_restraint(Level)) - (subgoal_abstract=Level) | |
1119 | ], | |
1120 | #{}, Defaults) | |
1022 | 1121 | }, |
1023 | 1122 | wrappers(Spec, M, Defaults). |
1024 | 1123 | |
1101 | 1200 | |
1102 | 1201 | |
1103 | 1202 | tabling_defaults([], Dict, Dict). |
1104 | tabling_defaults([Flag-(Opt=Value)|T], Dict0, Dict) :- | |
1105 | ( current_prolog_flag(Flag, true) | |
1203 | tabling_defaults([Condition-(Opt=Value)|T], Dict0, Dict) :- | |
1204 | ( tabling_default(Condition) | |
1106 | 1205 | -> Dict1 = Dict0.put(Opt,Value) |
1107 | 1206 | ; Dict1 = Dict0 |
1108 | 1207 | ), |
1109 | 1208 | tabling_defaults(T, Dict1, Dict). |
1110 | 1209 | |
1210 | tabling_default(Flag=FValue) :- | |
1211 | !, | |
1212 | current_prolog_flag(Flag, FValue). | |
1213 | tabling_default(call(Term)) :- | |
1214 | call(Term). | |
1215 | ||
1216 | % Called from wrappers//2. | |
1217 | ||
1218 | subgoal_size_restraint(Level) :- | |
1219 | current_prolog_flag(max_table_subgoal_size_action, abstract), | |
1220 | current_prolog_flag(max_table_subgoal_size, Level). | |
1111 | 1221 | |
1112 | 1222 | %! table_options(+Options, +OptDictIn, -OptDictOut) |
1113 | 1223 | % |
1144 | 1254 | table_options(max_answers(Count), Opts0, Opts1) :- |
1145 | 1255 | !, |
1146 | 1256 | restraint(max_answers, Count, Opts0, Opts1). |
1147 | table_options(abstract_subgoal(Size), Opts0, Opts1) :- | |
1148 | !, | |
1149 | restraint(abstract_subgoal, Size, Opts0, Opts1). | |
1257 | table_options(subgoal_abstract(Size), Opts0, Opts1) :- | |
1258 | !, | |
1259 | restraint(subgoal_abstract, Size, Opts0, Opts1). | |
1150 | 1260 | table_options(answer_abstract(Size), Opts0, Opts1) :- |
1151 | 1261 | !, |
1152 | 1262 | restraint(answer_abstract, Size, Opts0, Opts1). |
263 | 263 | endif() |
264 | 264 | if(NOT MULTI_THREADED) |
265 | 265 | swipl_del_package(swipl-win "requires multi-threading") |
266 | swipl_del_package(tipc "requires multi-threading") | |
266 | 267 | endif() |
267 | 268 | |
268 | 269 | if(INSTALL_DOCUMENTATION) |
177 | 177 | * MAPLIST/2... * |
178 | 178 | *******************************/ |
179 | 179 | |
180 | %! maplist(:Goal, ?List) | |
181 | % | |
182 | % True if Goal can successfully be applied on all elements of | |
183 | % List. Arguments are reordered to gain performance as well as to | |
184 | % make the predicate deterministic under normal circumstances. | |
180 | %! maplist(:Goal, ?List1). | |
181 | %! maplist(:Goal, ?List1, ?List2). | |
182 | %! maplist(:Goal, ?List1, ?List2, ?List3). | |
183 | %! maplist(:Goal, ?List1, ?List2, ?List3, ?List4). | |
184 | % | |
185 | % True if Goal is successfully applied on all matching elements of the | |
186 | % list. The maplist family of predicates is defined as: | |
187 | % | |
188 | % ``` | |
189 | % maplist(P, [X11,...,X1n], ..., [Xm1,...,Xmn]) :- | |
190 | % P(X11, ..., Xm1), | |
191 | % ... | |
192 | % P(X1n, ..., Xmn). | |
193 | % ``` | |
194 | % | |
195 | % This family of predicates is deterministic iff Goal is deterministic | |
196 | % and List1 is a proper list, i.e., a list that ends in `[]`. | |
185 | 197 | |
186 | 198 | maplist(Goal, List) :- |
187 | 199 | maplist_(List, Goal). |
191 | 203 | call(Goal, Elem), |
192 | 204 | maplist_(Tail, Goal). |
193 | 205 | |
194 | %! maplist(:Goal, ?List1, ?List2) | |
195 | % | |
196 | % As maplist/2, operating on pairs of elements from two lists. | |
197 | ||
198 | 206 | maplist(Goal, List1, List2) :- |
199 | 207 | maplist_(List1, List2, Goal). |
200 | 208 | |
203 | 211 | call(Goal, Elem1, Elem2), |
204 | 212 | maplist_(Tail1, Tail2, Goal). |
205 | 213 | |
206 | %! maplist(:Goal, ?List1, ?List2, ?List3) | |
207 | % | |
208 | % As maplist/2, operating on triples of elements from three lists. | |
209 | ||
210 | 214 | maplist(Goal, List1, List2, List3) :- |
211 | 215 | maplist_(List1, List2, List3, Goal). |
212 | 216 | |
214 | 218 | maplist_([Elem1|Tail1], [Elem2|Tail2], [Elem3|Tail3], Goal) :- |
215 | 219 | call(Goal, Elem1, Elem2, Elem3), |
216 | 220 | maplist_(Tail1, Tail2, Tail3, Goal). |
217 | ||
218 | ||
219 | %! maplist(:Goal, ?List1, ?List2, ?List3, ?List4) | |
220 | % | |
221 | % As maplist/2, operating on quadruples of elements from four | |
222 | % lists. | |
223 | 221 | |
224 | 222 | maplist(Goal, List1, List2, List3, List4) :- |
225 | 223 | maplist_(List1, List2, List3, List4, Goal). |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2019, VU University Amsterdam | |
5 | Copyright (c) 2019-2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
6 | 7 | All rights reserved. |
7 | 8 | |
8 | 9 | Redistribution and use in source and binary forms, with or without |
36 | 37 | trimcore/0, |
37 | 38 | |
38 | 39 | abolish_table_info/0, |
40 | close_open_tables/1, % ? | |
39 | 41 | |
40 | 42 | str_cat/3, |
41 | 43 | |
78 | 80 | % Undocumented in the XSB manual. |
79 | 81 | |
80 | 82 | abolish_table_info. |
83 | ||
84 | %! close_open_tables(?Arg) | |
85 | % | |
86 | % Undocumented in the XSB manual. Tables are always closed on | |
87 | % exceptions, so it is unclear what this should do? | |
88 | ||
89 | close_open_tables(_). | |
81 | 90 | |
82 | 91 | %! str_cat(+Atom1, +Atom2, -Atom3) |
83 | 92 |
33 | 33 | */ |
34 | 34 | |
35 | 35 | :- module(xsb_source, []). |
36 | :- autoload(library(apply),[convlist/3,partition/4]). | |
37 | :- autoload(library(debug),[debug/3]). | |
38 | :- autoload(library(error),[instantiation_error/1]). | |
39 | :- autoload(library(lists),[append/3,flatten/2]). | |
40 | ||
36 | :- autoload(library(apply), [convlist/3,partition/4]). | |
37 | :- autoload(library(debug), [debug/3]). | |
38 | :- autoload(library(error), [instantiation_error/1]). | |
39 | :- autoload(library(occurs), [sub_term/2]). | |
41 | 40 | |
42 | 41 | /** <module> Support XSB source .P files |
43 | 42 | |
66 | 65 | file_name_extension(Path, 'P', File), |
67 | 66 | include_options(File, Include), |
68 | 67 | compiler_options(COptions), |
69 | append(Include, COptions, Extra), | |
68 | '$append'(Include, COptions, Extra), | |
70 | 69 | xsb_directives(File, Directives), |
71 | 70 | directive_exports(Directives, Public, Directives1), |
72 | 71 | ( Public == [] |
80 | 79 | (:- use_module(library(tables))) |
81 | 80 | | Out2 |
82 | 81 | ], |
83 | append(Extra, More, Out2), | |
82 | '$append'(Extra, More, Out2), | |
84 | 83 | ( nonvar(Module) |
85 | 84 | -> setup_call_cleanup( |
86 | 85 | '$set_source_module'(OldM, Module), |
87 | convlist(head_directive(File), Directives1, More0), | |
86 | phrase(head_directives(Directives1, File), More), | |
88 | 87 | '$set_source_module'(OldM)) |
89 | ; convlist(head_directive(File), Directives1, More0) | |
88 | ; phrase(head_directives(Directives1, File), More) | |
90 | 89 | ), |
91 | flatten(More0, More), | |
92 | 90 | debug(xsb(header), '~p: directives: ~p', [File, More]). |
93 | 91 | |
94 | 92 | include_options(File, Option) :- |
141 | 139 | export_decl(PI) --> |
142 | 140 | [PI]. |
143 | 141 | |
144 | %! head_directive(+File, +Directive, -PrefixedDirective) is semidet. | |
145 | ||
146 | head_directive(File, import(from(Preds, From)), | |
147 | (:- xsb_import(Preds, From))) :- | |
148 | assertz(xsb:moved_directive(File, import(from(Preds, From)))). | |
149 | head_directive(File, table(Preds as XSBOptions), Clauses) :- | |
150 | ignored_table_options(XSBOptions, Options), | |
151 | ( Options == true | |
152 | -> expand_term((:- table(Preds)), Clauses) | |
153 | ; expand_term((:- table(Preds as Options)), Clauses) | |
154 | ), | |
155 | assertz(xsb:moved_directive(File, table(Preds as XSBOptions))). | |
156 | head_directive(File, table(Preds), Clauses) :- | |
157 | expand_term((:- table(Preds)), Clauses), | |
158 | assertz(xsb:moved_directive(File, table(Preds))). | |
142 | %! head_directives(+Directives, +File)// is det. | |
143 | %! head_directives_s(+Directives, +State)// is det. | |
144 | ||
145 | head_directives(Directives, File) --> | |
146 | { current_prolog_flag(max_table_subgoal_size_action, Action), | |
147 | ( current_prolog_flag(max_table_subgoal_size, Size) | |
148 | -> true | |
149 | ; Size = -1 | |
150 | ) | |
151 | }, | |
152 | head_directives_s(Directives, | |
153 | #{file: File, | |
154 | max_table_subgoal_size_action: Action, | |
155 | max_table_subgoal_size:Size | |
156 | }). | |
157 | ||
158 | ||
159 | head_directives_s([], _) --> []. | |
160 | head_directives_s([H|T], State0) --> | |
161 | { update_state(H, State0, State) }, | |
162 | !, | |
163 | head_directives_s(T, State). | |
164 | head_directives_s([H|T], State) --> | |
165 | head_directive(H, State), | |
166 | head_directives_s(T, State). | |
167 | ||
168 | update_state(set_prolog_flag(max_table_subgoal_size_action, Action), | |
169 | State0, State) :- | |
170 | State = State0.put(max_table_subgoal_size_action, Action). | |
171 | update_state(set_prolog_flag(max_table_subgoal_size, Size), | |
172 | State0, State) :- | |
173 | State = State0.put(max_table_subgoal_size, Size). | |
174 | ||
175 | %! head_directive(+Directive, +State)// is det. | |
176 | ||
177 | head_directive(import(from(Preds, From)), State) --> | |
178 | !, | |
179 | { assertz(xsb:moved_directive(State.file, import(from(Preds, From)))) | |
180 | }, | |
181 | [ (:- xsb_import(Preds, From)) ]. | |
182 | head_directive(table(Preds as XSBOptions), State) --> | |
183 | !, | |
184 | { ignored_table_options(XSBOptions, Options), | |
185 | table_clauses(Preds, Options, Clauses, State), | |
186 | assertz(xsb:moved_directive(State.file, table(Preds as XSBOptions))) | |
187 | }, | |
188 | seq(Clauses). | |
189 | head_directive(table(Preds), State) --> | |
190 | !, | |
191 | { table_clauses(Preds, true, Clauses, State), | |
192 | assertz(xsb:moved_directive(State.file, table(Preds))) | |
193 | }, | |
194 | seq(Clauses). | |
195 | head_directive(_, _) --> | |
196 | []. | |
197 | ||
198 | seq([]) --> []. | |
199 | seq([H|T]) --> [H], seq(T). | |
159 | 200 | |
160 | 201 | ignored_table_options((A0,B0), Conj) :- |
161 | 202 | !, |
176 | 217 | supported_table_option(shared). |
177 | 218 | supported_table_option(private). |
178 | 219 | supported_table_option(max_answers(_)). |
179 | supported_table_option(abstract_subgoal(_)). | |
220 | supported_table_option(subgoal_abstract(_)). | |
180 | 221 | supported_table_option(answer_abstract(_)). |
181 | 222 | |
182 | 223 | mkconj(true, X, X) :- !. |
183 | 224 | mkconj(X, true, X) :- !. |
184 | 225 | mkconj(X, Y, (X,Y)) :- !. |
226 | ||
227 | table_clauses(Preds, Options0, Clauses, State) :- | |
228 | add_defaults(Options0, Options, State), | |
229 | ( Options == true | |
230 | -> expand_term((:- table(Preds)), Clauses) | |
231 | ; expand_term((:- table(Preds as Options)), Clauses) | |
232 | ). | |
233 | ||
234 | add_defaults(Opts, Opts, _) :- | |
235 | sub_term(subgoal_abstract(_), Opts), | |
236 | !. | |
237 | add_defaults(Opts0, Opts, State) :- | |
238 | #{max_table_subgoal_size_action:abstract, | |
239 | max_table_subgoal_size:Size} :< State, | |
240 | Size >= 0, | |
241 | !, | |
242 | mkconj(Opts0, subgoal_abstract(Size), Opts). | |
243 | add_defaults(Opts, Opts, _). | |
185 | 244 | |
186 | 245 | %! xsb_directives(+File, -Directives) is semidet. |
187 | 246 | % |
268 | 268 | comma_list(tnot(M:G), M) --> |
269 | 269 | !, |
270 | 270 | [tnot(G)]. |
271 | comma_list(system:G, _) --> | |
272 | !, | |
273 | [G]. | |
271 | 274 | comma_list(G, _) --> |
272 | 275 | [G]. |
273 | 276 |
104 | 104 | |
105 | 105 | '$timed_call_nested'(Goal, M:Options) :- |
106 | 106 | memberchk(max(MaxInterval, MaxHandler), Options), |
107 | !, | |
107 | 108 | run_max_goal(Goal, MaxInterval, MaxHandler, M:Options). |
108 | 109 | '$timed_call_nested'(Goal, M:Options) :- |
109 | 110 | memberchk(repeating(RepInterval, RepHandler), Options), |
46 | 46 | compiler_options/1, % +Options |
47 | 47 | |
48 | 48 | xsb_import/2, % +Preds, From |
49 | xsb_set_prolog_flag/2, % +Flag, +Value | |
49 | 50 | |
50 | 51 | fail_if/1, % :Goal |
51 | 52 | |
178 | 179 | |
179 | 180 | xsb_mapped_predicate(expand_file_name(File, Expanded), |
180 | 181 | xsb_expand_file_name(File, Expanded)). |
182 | xsb_mapped_predicate(set_prolog_flag(Flag, Value), | |
183 | xsb_set_prolog_flag(Flag, Value)). | |
181 | 184 | xsb_mapped_predicate(abolish_module_tables(UserMod), |
182 | 185 | abolish_module_tables(user)) :- |
183 | 186 | UserMod == usermod. |
311 | 314 | !. |
312 | 315 | map_module(XSB, Module) :- |
313 | 316 | assertz(mapped__module(XSB, Module)). |
317 | ||
318 | ||
319 | %! xsb_set_prolog_flag(+Flag, +Value) | |
320 | % | |
321 | % Map some XSB Prolog flags to their SWI-Prolog's equivalents. | |
322 | ||
323 | xsb_set_prolog_flag(unify_with_occurs_check, XSBVal) :- | |
324 | !, | |
325 | map_bool(XSBVal, Val), | |
326 | set_prolog_flag(occurs_check, Val). | |
327 | xsb_set_prolog_flag(Flag, Value) :- | |
328 | set_prolog_flag(Flag, Value). | |
329 | ||
330 | map_bool(on, true). | |
331 | map_bool(off, false). | |
314 | 332 | |
315 | 333 | |
316 | 334 | /******************************* |
167 | 167 | help_html(Matches, How, HTML) :- |
168 | 168 | phrase(html(html([ head([]), |
169 | 169 | body([ \match_type(How), |
170 | \man_pages(Matches, | |
171 | [ no_manual(fail), | |
172 | links(false), | |
173 | link_source(false), | |
174 | navtree(false), | |
175 | server(false) | |
176 | ]) | |
170 | dl(\man_pages(Matches, | |
171 | [ no_manual(fail), | |
172 | links(false), | |
173 | link_source(false), | |
174 | navtree(false), | |
175 | server(false) | |
176 | ])) | |
177 | 177 | ]) |
178 | 178 | ])), |
179 | 179 | Tokens), |
51 | 51 | :- autoload(library(option),[option/2,option/3,meta_options/3]). |
52 | 52 | :- autoload(library(prolog_clause),[clause_info/5]). |
53 | 53 | |
54 | :- set_prolog_flag(generate_debug_info, false). | |
54 | %:- set_prolog_flag(generate_debug_info, false). | |
55 | 55 | |
56 | 56 | :- module_transparent |
57 | 57 | listing/0. |
662 | 662 | portray_body(Body, BodyIndent, indent, RightPri, Out, Options) |
663 | 663 | ), |
664 | 664 | full_stop(Out). |
665 | do_portray_clause(Out, (:-use_module(File, Imports)), Options) :- | |
666 | length(Imports, Len), | |
667 | Len > 3, | |
668 | !, | |
665 | do_portray_clause(Out, (:-Directive), Options) :- | |
666 | wrapped_list_directive(Directive), | |
667 | !, | |
668 | Directive =.. [Name, Arg, List], | |
669 | 669 | option(indent(LeftMargin), Options, 0), |
670 | 670 | indent(Out, LeftMargin), |
671 | ListIndent is LeftMargin+14, | |
672 | format(Out, ':- use_module(~q,', [File]), | |
673 | portray_list(Imports, ListIndent, Out, Options), | |
674 | write(Out, ').\n'). | |
675 | do_portray_clause(Out, (:-module(Module, Exports)), Options) :- | |
676 | !, | |
677 | option(indent(LeftMargin), Options, 0), | |
678 | indent(Out, LeftMargin), | |
679 | ModuleIndent is LeftMargin+10, | |
680 | format(Out, ':- module(~q,', [Module]), | |
681 | portray_list(Exports, ModuleIndent, Out, Options), | |
671 | format(Out, ':- ~q(', [Name]), | |
672 | line_position(Out, Indent), | |
673 | format(Out, '~q,', [Arg]), | |
674 | nlindent(Out, Indent), | |
675 | portray_list(List, Indent, Out, Options), | |
682 | 676 | write(Out, ').\n'). |
683 | 677 | do_portray_clause(Out, (:-Directive), Options) :- |
684 | 678 | !, |
701 | 695 | '$put_token'(Out, '.'), |
702 | 696 | nl(Out). |
703 | 697 | |
698 | wrapped_list_directive(module(_,_)). | |
699 | %wrapped_list_directive(use_module(_,_)). | |
700 | %wrapped_list_directive(autoload(_,_)). | |
704 | 701 | |
705 | 702 | %! portray_body(+Term, +Indent, +DoIndent, +Priority, +Out, +Options) |
706 | 703 | % |
958 | 955 | !, |
959 | 956 | write(Out, []). |
960 | 957 | portray_list(List, Indent, Out, Options) :- |
961 | nlindent(Out, Indent), | |
962 | 958 | write(Out, '[ '), |
963 | 959 | EIndent is Indent + 2, |
964 | 960 | portray_list_elements(List, EIndent, Out, Options), |
1958 | 1958 | valid_decl_option(Option, Which), |
1959 | 1959 | !, |
1960 | 1960 | functor(Option, Name, _), |
1961 | colour_item(decl_option(Name), TB, Pos), | |
1962 | ( Pos = term_position(_,_,_,_,[ArgPos]) | |
1963 | -> ( arg(1, Option, Value), | |
1961 | ( Pos = term_position(_,_,FF,FT,[ArgPos]) | |
1962 | -> colour_item(decl_option(Name), TB, FF-FT), | |
1963 | ( arg(1, Option, Value), | |
1964 | 1964 | nonneg_or_false(Value) |
1965 | 1965 | -> colourise_term_arg(Value, TB, ArgPos) |
1966 | 1966 | ; colour_item(type_error(decl_option_value(Which)), TB, ArgPos) |
1967 | 1967 | ) |
1968 | ; true | |
1968 | ; colour_item(decl_option(Name), TB, Pos) | |
1969 | 1969 | ). |
1970 | 1970 | colourise_decl_options(_, Which, TB, Pos) :- |
1971 | 1971 | colour_item(type_error(decl_option(Which)), TB, Pos). |
0 | /* Part of SWI-Prolog | |
1 | ||
2 | Author: Jan Wielemaker | |
3 | E-mail: J.Wielemaker@vu.nl | |
4 | WWW: http://www.swi-prolog.org | |
5 | Copyright (c) 2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
7 | All rights reserved. | |
8 | ||
9 | Redistribution and use in source and binary forms, with or without | |
10 | modification, are permitted provided that the following conditions | |
11 | are met: | |
12 | ||
13 | 1. Redistributions of source code must retain the above copyright | |
14 | notice, this list of conditions and the following disclaimer. | |
15 | ||
16 | 2. Redistributions in binary form must reproduce the above copyright | |
17 | notice, this list of conditions and the following disclaimer in | |
18 | the documentation and/or other materials provided with the | |
19 | distribution. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
32 | POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | |
34 | ||
35 | :- module(prolog_deps, | |
36 | [ file_autoload_directives/3, % +File, -Directives, +Options | |
37 | file_auto_import/2 % +File, +Options | |
38 | ]). | |
39 | :- use_module(library(apply), [convlist/3, maplist/3]). | |
40 | :- use_module(library(filesex), [copy_file/2]). | |
41 | :- use_module(library(lists), [select/3, subtract/3, append/3, member/2]). | |
42 | :- use_module(library(option), [option/2, option/3]). | |
43 | :- use_module(library(pairs), [group_pairs_by_key/2]). | |
44 | :- use_module(library(pprint), [print_term/2]). | |
45 | :- use_module(library(prolog_code), [pi_head/2]). | |
46 | :- use_module(library(prolog_source), | |
47 | [ file_name_on_path/2, | |
48 | path_segments_atom/2, | |
49 | prolog_open_source/2, | |
50 | prolog_read_source_term/4, | |
51 | prolog_close_source/1 | |
52 | ]). | |
53 | :- use_module(library(prolog_xref), | |
54 | [ xref_source/1, | |
55 | xref_module/2, | |
56 | xref_called/4, | |
57 | xref_defined/3, | |
58 | xref_built_in/1 | |
59 | ]). | |
60 | :- use_module(library(readutil), [read_file_to_string/3]). | |
61 | :- use_module(library(solution_sequences), [distinct/2]). | |
62 | ||
63 | /** <module> Compute file dependencies | |
64 | ||
65 | This module computes file dependencies for _modules_ as a set of | |
66 | directives. | |
67 | */ | |
68 | ||
69 | ||
70 | %! file_autoload_directives(+File, -Directives, +Options) is det. | |
71 | % | |
72 | % Compute the dependencies as autoload/2 directives. Options | |
73 | % | |
74 | % - missing(+Bool) | |
75 | % If `true` (default `false`), only generate directives | |
76 | % for called predicates that are not already imported. | |
77 | % | |
78 | % - directive(+Directive) | |
79 | % Directive to use for adding dependencies. Defined | |
80 | % options are: | |
81 | % | |
82 | % - use_autoload/2 | |
83 | % (Default). This uses use_module/2 for files that | |
84 | % cannot be imported using use_autoload/2. | |
85 | % - use_autoload/1 | |
86 | % This uses use_module/1 for files that cannot be | |
87 | % imported using use_autoload/1. | |
88 | % - use_module/2 | |
89 | % - use_module/1 | |
90 | % | |
91 | % - update(Old) | |
92 | % Updated an existing set of directives. The returned | |
93 | % set of Directive starts with copies of Old. If a | |
94 | % member of Old is autoload/2 or use_module/2, new | |
95 | % dependencies are added at the end of this list. | |
96 | % New dependent files are added after the modified | |
97 | % copies of Old. Declared dependencies are never | |
98 | % removed, even if no proof of usage is found. | |
99 | % | |
100 | % If no directive(+Directive) option is provided a | |
101 | % default is determined from the given directives. | |
102 | ||
103 | file_autoload_directives(File, Directives, Options) :- | |
104 | xref_source(File), | |
105 | findall(Head, distinct(Head, undefined(File, Head, Options)), Missing), | |
106 | convlist(missing_autoload(File), Missing, Pairs), | |
107 | keysort(Pairs, Pairs1), | |
108 | group_pairs_by_key(Pairs1, Grouped), | |
109 | directives(Grouped, Directives, Options). | |
110 | ||
111 | %! undefined(+File, -Callable, +Options) | |
112 | % | |
113 | % Callable is called in File, but no definition can be found. If | |
114 | % File is not a module file we consider other files that are not | |
115 | % module files. | |
116 | ||
117 | undefined(File, Undef, Options) :- | |
118 | xref_module(File, _), | |
119 | !, | |
120 | xref_called_cond(File, Undef, Cond), | |
121 | \+ ( available(File, Undef, How, Options), | |
122 | How \== plain_file | |
123 | ), | |
124 | included_if_defined(Cond, Undef), | |
125 | Undef \= (_:_). | |
126 | undefined(File, Undef, Options) :- | |
127 | xref_called_cond(File, Undef, Cond), | |
128 | \+ available(File, Undef, _, Options), | |
129 | included_if_defined(Cond, Undef), | |
130 | Undef \= (_:_). | |
131 | ||
132 | %! included_if_defined(+Condition, +Callable) is semidet. | |
133 | ||
134 | included_if_defined(true, _) :- !. | |
135 | included_if_defined(false, _) :- !, fail. | |
136 | included_if_defined(fail, _) :- !, fail. | |
137 | included_if_defined(current_predicate(Name/Arity), Callable) :- | |
138 | \+ functor(Callable, Name, Arity), | |
139 | !. | |
140 | included_if_defined(\+ Cond, Callable) :- | |
141 | !, | |
142 | \+ included_if_defined(Cond, Callable). | |
143 | included_if_defined((A,B), Callable) :- | |
144 | !, | |
145 | included_if_defined(A, Callable), | |
146 | included_if_defined(B, Callable). | |
147 | included_if_defined((A;B), Callable) :- | |
148 | !, | |
149 | ( included_if_defined(A, Callable) | |
150 | ; included_if_defined(B, Callable) | |
151 | ). | |
152 | ||
153 | xref_called_cond(Source, Callable, Cond) :- | |
154 | xref_called(Source, Callable, By, Cond), | |
155 | By \= Callable. % recursive calls | |
156 | ||
157 | %! available(+File, +Callable, -HowDefined, +Options) | |
158 | % | |
159 | % True if Callable is available in File. | |
160 | ||
161 | available(File, Called, How, Options) :- | |
162 | xref_defined(File, Called, How0), | |
163 | ( How0 = imported(_) | |
164 | -> option(missing(true), Options) | |
165 | ; true | |
166 | ), | |
167 | !, | |
168 | How = How0. | |
169 | available(_, Called, How, _) :- | |
170 | built_in_predicate(Called), | |
171 | !, | |
172 | How = builtin. | |
173 | available(_, Called, How, _) :- | |
174 | Called = _:_, | |
175 | defined(_, Called), | |
176 | !, | |
177 | How = module_qualified. | |
178 | available(_, M:G, How, _) :- | |
179 | defined(ExportFile, G), | |
180 | xref_module(ExportFile, M), | |
181 | !, | |
182 | How = module_overruled. | |
183 | available(_, Called, How, _) :- | |
184 | defined(ExportFile, Called), | |
185 | \+ xref_module(ExportFile, _), | |
186 | !, | |
187 | How == plain_file. | |
188 | ||
189 | %! built_in_predicate(+Callable) | |
190 | % | |
191 | % True if Callable is a built-in | |
192 | ||
193 | built_in_predicate(Goal) :- | |
194 | strip_module(Goal, _, Plain), | |
195 | xref_built_in(Plain). | |
196 | ||
197 | %! defined(?File, ?Callable) | |
198 | % | |
199 | % True if Callable is defined in File and not imported. | |
200 | ||
201 | defined(File, Callable) :- | |
202 | xref_defined(File, Callable, How), | |
203 | How \= imported(_). | |
204 | ||
205 | ||
206 | /******************************* | |
207 | * GENERATE OUTPUT * | |
208 | *******************************/ | |
209 | ||
210 | missing_autoload(_Src, Head, File-Head) :- | |
211 | predicate_property(Head, autoload(File)), | |
212 | !. | |
213 | missing_autoload(Src, Head, From-Head) :- | |
214 | xref_defined(Src, Head, imported(From)), | |
215 | !. | |
216 | missing_autoload(_Src, Head, _) :- | |
217 | pi_head(PI, Head), | |
218 | print_message(warning, | |
219 | error(existence_error(procedure, PI), _)), | |
220 | fail. | |
221 | ||
222 | %! directives(+FileAndHeads, -Directives, +Options) is det. | |
223 | % | |
224 | % Assemble the final set of directives. Uses the option update(Old). | |
225 | ||
226 | directives(FileAndHeads, Directives, Options) :- | |
227 | option(update(Old), Options, []), | |
228 | phrase(update_directives(Old, FileAndHeads, RestDeps), Directives, Rest), | |
229 | update_style(Old, Options, Options1), | |
230 | maplist(directive(Options1), RestDeps, Rest0), | |
231 | sort(Rest0, Rest). | |
232 | ||
233 | update_directives([], Deps, Deps) --> | |
234 | []. | |
235 | update_directives([:-(H)|T], Deps0, Deps) --> | |
236 | { update_directive(H, Deps0, Deps1, Directive) }, | |
237 | !, | |
238 | [ :-(Directive) ], | |
239 | update_directives(T, Deps1, Deps). | |
240 | update_directives([H|T], Deps0, Deps) --> | |
241 | [ H ], | |
242 | update_directives(T, Deps0, Deps). | |
243 | ||
244 | update_directive(Dir0, Deps0, Deps, Dir) :- | |
245 | directive_file(Dir0, FileSpec), | |
246 | absolute_file_name(FileSpec, File, | |
247 | [ file_type(prolog), | |
248 | file_errors(fail), | |
249 | access(read) | |
250 | ]), | |
251 | select(DepFile-Heads, Deps0, Deps), | |
252 | same_dep_file(DepFile, File), | |
253 | !, | |
254 | ( Dir0 =.. [Pred,File,Imports] | |
255 | -> maplist(pi_head, PIs, Heads), | |
256 | subtract(PIs, Imports, New), | |
257 | append(Imports, New, NewImports), | |
258 | Dir =.. [Pred,File,NewImports] | |
259 | ; Dir = Dir0 | |
260 | ). | |
261 | ||
262 | directive_file(use_module(File), File). | |
263 | directive_file(use_module(File,_), File). | |
264 | directive_file(autoload(File), File). | |
265 | directive_file(autoload(File,_), File). | |
266 | ||
267 | same_dep_file(File, File) :- | |
268 | !. | |
269 | same_dep_file(Dep, _File) :- | |
270 | exists_file(Dep), | |
271 | !, | |
272 | fail. | |
273 | same_dep_file(Dep, File) :- | |
274 | user:prolog_file_type(Ext, prolog), | |
275 | file_name_extension(Dep, Ext, DepFile), | |
276 | same_file(DepFile, File), | |
277 | !. | |
278 | ||
279 | ||
280 | %! update_style(+OldDirectives, +Options0, -Options) | |
281 | % | |
282 | % Determine the directive to use for new dependencies. This | |
283 | % establishes a default based on existing dependencies. | |
284 | ||
285 | update_style(_Old, Options, Options) :- | |
286 | option(directive(_), Options), | |
287 | !. | |
288 | update_style(Old, Options, [directive(autoload/2)|Options]) :- | |
289 | memberchk((:- autoload(_,_)), Old), | |
290 | !. | |
291 | update_style(Old, Options, [directive(autoload/1)|Options]) :- | |
292 | memberchk((:- autoload(_)), Old), | |
293 | !. | |
294 | update_style(Old, Options, [directive(use_module/2)|Options]) :- | |
295 | memberchk((:- use_module(_,_)), Old), | |
296 | !. | |
297 | update_style(Old, Options, [directive(use_module/1)|Options]) :- | |
298 | memberchk((:- use_module(_)), Old), | |
299 | !. | |
300 | update_style(_, Options, Options). | |
301 | ||
302 | ||
303 | %! directive(+Options, +FileAndHeads, -Directive) | |
304 | % | |
305 | % Create a directive to import Heads from File. | |
306 | ||
307 | directive(Options, File-Heads, Directive) :- | |
308 | file_name_extension(File, pl, LibFile), | |
309 | file_name_on_path(LibFile, Lib0), | |
310 | segments(Lib0, Lib), | |
311 | maplist(pi_head, PIs, Heads), | |
312 | make_directive(Lib, PIs, Directive, Options). | |
313 | ||
314 | segments(Term0, Term) :- | |
315 | Term0 =.. [Alias,Atom], | |
316 | path_segments_atom(Segments, Atom), | |
317 | format(atom(Atom), '~q', [Segments]), | |
318 | !, | |
319 | Term =.. [Alias,Segments]. | |
320 | segments(FilePL, File) :- | |
321 | atom(FilePL), | |
322 | file_name_extension(File, pl, FilePL), | |
323 | !. | |
324 | segments(Term, Term). | |
325 | ||
326 | :- multifile | |
327 | prolog:no_autoload_module/1. | |
328 | ||
329 | make_directive(Lib, Import, (:- use_module(Lib, Import)), Options) :- | |
330 | option(directive(use_module/2), Options, use_autoload/2), | |
331 | !. | |
332 | make_directive(Lib, _Import, (:- use_module(Lib)), Options) :- | |
333 | option(directive(use_module/1), Options, use_autoload/2), | |
334 | !. | |
335 | make_directive(Lib, _Import, (:- use_module(Lib)), Options) :- | |
336 | option(directive(use_autoload/1), Options, use_autoload/2), | |
337 | prolog:no_autoload_module(Lib), | |
338 | !. | |
339 | make_directive(Lib, Import, (:- use_module(Lib, Import)), _) :- | |
340 | prolog:no_autoload_module(Lib), | |
341 | !. | |
342 | make_directive(Lib, _Import, (:- autoload(Lib)), Options) :- | |
343 | option(directive(use_autoload/1), Options, use_autoload/2), | |
344 | !. | |
345 | make_directive(Lib, Import, (:- autoload(Lib, Import)), _). | |
346 | ||
347 | ||
348 | /******************************* | |
349 | * REPLACE * | |
350 | *******************************/ | |
351 | ||
352 | %! file_auto_import(+File, +Options) | |
353 | % | |
354 | % Update the autoload/2 directives for File. This predicate __modifies | |
355 | % the file in place__. Defined options are: | |
356 | % | |
357 | % - backup(+Extension) | |
358 | % Create a backup of File using Extension. | |
359 | ||
360 | file_auto_import(File, Options) :- | |
361 | absolute_file_name(File, Path, | |
362 | [ file_type(prolog), | |
363 | access(read) | |
364 | ]), | |
365 | file_autoload_directives(Path, Directives, Options), | |
366 | ( option(backup(Ext), Options) | |
367 | -> file_name_extension(Path, Ext, Old), | |
368 | copy_file(Path, Old) | |
369 | ; true | |
370 | ), | |
371 | Edit = _{import:Directives, done:_}, | |
372 | ( has_import(Path) | |
373 | -> edit_file(Old, Path, Edit.put(replace,true)) | |
374 | ; edit_file(Old, Path, Edit.put(new,true)) | |
375 | ). | |
376 | ||
377 | has_import(InFile) :- | |
378 | setup_call_cleanup( | |
379 | prolog_open_source(InFile, In), | |
380 | ( repeat, | |
381 | prolog_read_source_term(In, Term, _Expanded, []), | |
382 | ( Term == end_of_file | |
383 | -> ! | |
384 | ; true | |
385 | ) | |
386 | ), | |
387 | prolog_close_source(In)), | |
388 | nonvar(Term), | |
389 | import_directive(Term), | |
390 | !. | |
391 | ||
392 | import_directive((:- use_module(_))). | |
393 | import_directive((:- use_module(_, _))). | |
394 | ||
395 | %! rewrite_term(+In, -Keep, -OutList, +Options) is semidet. | |
396 | ||
397 | rewrite_term(Never,_,_,_) :- | |
398 | never_rewrite(Never), | |
399 | !, | |
400 | fail. | |
401 | rewrite_term(Import,false,[],Options) :- | |
402 | Options.done == true, | |
403 | !, | |
404 | import_directive(Import). | |
405 | rewrite_term(In,false,Directives,Options) :- | |
406 | import_directive(In), | |
407 | !, | |
408 | append(Options.import, [nl], Directives), | |
409 | Options.done = true. | |
410 | rewrite_term(In,true,Directives,Options) :- | |
411 | In = (:- module(_,_)), | |
412 | Options.get(new) == true, | |
413 | !, | |
414 | append(Options.import, [nl], Directives), | |
415 | Options.done = true. | |
416 | ||
417 | never_rewrite((:- use_module(_, []))). | |
418 | ||
419 | edit_file(InFile, OutFile, Options) :- | |
420 | read_file_to_string(InFile, String, []), | |
421 | setup_call_cleanup( | |
422 | prolog_open_source(InFile, In), | |
423 | setup_call_cleanup( | |
424 | open(OutFile, write, Out), | |
425 | rewrite(In, Out, String, Options), | |
426 | close(Out)), | |
427 | prolog_close_source(In)). | |
428 | ||
429 | rewrite(In, Out, String, Options) :- | |
430 | prolog_read_source_term( | |
431 | In, Term, _Expanded, | |
432 | [ term_position(StartPos), | |
433 | subterm_positions(TermPos), | |
434 | comments(Comments) | |
435 | ]), | |
436 | stream_position_data(char_count, StartPos, StartChar), | |
437 | copy_comments(Comments, StartChar, String, Out), | |
438 | ( Term == end_of_file | |
439 | -> true | |
440 | ; ( nonvar(Term), | |
441 | rewrite_term(Term, Keep, List, Options) | |
442 | -> ( Keep == true | |
443 | -> copy_term_string(TermPos, String, Out) | |
444 | ; true | |
445 | ), | |
446 | forall(member(T, List), | |
447 | output_term(Out, T)), | |
448 | ( append(_, [nl], List) | |
449 | -> skip_blanks(In) | |
450 | ; true | |
451 | ) | |
452 | ; copy_term_string(TermPos, String, Out) | |
453 | ), | |
454 | rewrite(In, Out, String, Options) | |
455 | ). | |
456 | ||
457 | output_term(Out, nl) :- | |
458 | !, | |
459 | nl(Out). | |
460 | output_term(Out, Term) :- | |
461 | print_term(Term, [output(Out)]), | |
462 | format(Out, '.~n', []). | |
463 | ||
464 | copy_comments([Pos-H|T], StartChar, String, Out) :- | |
465 | stream_position_data(char_count, Pos, Start), | |
466 | Start < StartChar, | |
467 | !, | |
468 | string_length(H, Len), | |
469 | sub_string(String, Start, Len, _, Comment), | |
470 | End is Start+Len+1, | |
471 | layout_after(End, String, Layout), | |
472 | format(Out, '~s~s', [Comment, Layout]), | |
473 | copy_comments(T, StartChar, String, Out). | |
474 | copy_comments(_, _, _, _). | |
475 | ||
476 | copy_term_string(TermPos, String, Out) :- | |
477 | arg(1, TermPos, Start), | |
478 | arg(2, TermPos, End), | |
479 | Len is End - Start, | |
480 | sub_string(String, Start, Len, _, TermString), | |
481 | End1 is End + 1, | |
482 | full_stop_after(End1, String, Layout), | |
483 | format(Out, '~s~s', [TermString, Layout]). | |
484 | ||
485 | layout_after(Index, String, [H|T]) :- | |
486 | string_code(Index, String, H), | |
487 | code_type(H, space), | |
488 | !, | |
489 | Index2 is Index+1, | |
490 | layout_after(Index2, String, T). | |
491 | layout_after(_, _, []). | |
492 | ||
493 | full_stop_after(Index, String, [H|T]) :- | |
494 | string_code(Index, String, H), | |
495 | Index2 is Index+1, | |
496 | ( code_type(H, space) | |
497 | -> !, full_stop_after(Index2, String, T) | |
498 | ; H == 0'. | |
499 | -> !, layout_after(Index2, String, T) | |
500 | ). | |
501 | full_stop_after(_, _, []). | |
502 | ||
503 | skip_blanks(In) :- | |
504 | peek_code(In, C), | |
505 | code_type(C, space), | |
506 | !, | |
507 | get_code(In, _), | |
508 | skip_blanks(In). | |
509 | skip_blanks(_). |
562 | 562 | safe_primitive(copy_term(_,_)). |
563 | 563 | safe_primitive(system:duplicate_term(_,_)). |
564 | 564 | safe_primitive(system:copy_term_nat(_,_)). |
565 | safe_primitive(system:size_abstract_term(_,_,_)). | |
565 | 566 | safe_primitive(numbervars(_,_,_)). |
566 | 567 | safe_primitive(system:numbervars(_,_,_,_)). |
567 | 568 | safe_primitive(subsumes_term(_,_)). |
1234 | 1235 | % tabling |
1235 | 1236 | safe_prolog_flag(max_answers_for_subgoal,_). |
1236 | 1237 | safe_prolog_flag(max_answers_for_subgoal_action,_). |
1238 | safe_prolog_flag(max_table_answer_size,_). | |
1239 | safe_prolog_flag(max_table_answer_size_action,_). | |
1240 | safe_prolog_flag(max_table_subgoal_size,_). | |
1241 | safe_prolog_flag(max_table_subgoal_size_action,_). | |
1237 | 1242 | |
1238 | 1243 | |
1239 | 1244 | %! prolog:sandbox_allowed_expansion(:G) is det. |
270 | 270 | |
271 | 271 | %! order_by(+Spec, :Goal) |
272 | 272 | % |
273 | % Order solutions according to Spec. Spec is a list of terms, | |
274 | % where each element is one of. The ordering of solutions of Goal | |
275 | % that only differ in variables that are _not_ shared with Spec is | |
276 | % not changed. | |
273 | % Order solutions according to Spec. Spec is a list of terms, where | |
274 | % each element is one of. The ordering of solutions of Goal that only | |
275 | % differ in variables that are _not_ shared with Spec is not changed. | |
277 | 276 | % |
278 | 277 | % - asc(Term) |
279 | 278 | % Order solution according to ascending Term |
280 | 279 | % - desc(Term) |
281 | 280 | % Order solution according to descending Term |
281 | % | |
282 | % This predicate is based on findall/3 and (thus) variables in answers | |
283 | % are _copied_. | |
282 | 284 | |
283 | 285 | order_by(Spec, Goal) :- |
284 | 286 | must_be(list, Spec), |
778 | 778 | Returns non-zero if \arg{term} is a compound term using the list |
779 | 779 | constructor. See also PL_is_list() and PL_skip_list(). |
780 | 780 | |
781 | \cfunction{int}{PL_is_dict}{term_t} | |
782 | Returns non-zero if \arg{term} is a dict. See also PL_put_dict() | |
783 | and PL_get_dict_key(). | |
784 | ||
781 | 785 | \cfunction{int}{PL_is_atomic}{term_t} |
782 | 786 | Returns non-zero if \arg{term} is atomic (not a variable or compound). |
783 | 787 | |
964 | 968 | If \arg{t} is an atom, the system will look up or create the |
965 | 969 | corresponding module and assign an opaque pointer to it over {\em |
966 | 970 | module}. |
971 | ||
967 | 972 | \cfunction{int}{PL_get_arg}{size_t index, term_t +t, term_t -a} |
968 | 973 | If \arg{t} is compound and index is between 1 and arity (inclusive), |
969 | 974 | assign \arg{a} with a term reference to the argument. |
975 | ||
970 | 976 | \cfunction{int}{_PL_get_arg}{size_t index, term_t +t, term_t -a} |
971 | 977 | Same as PL_get_arg(), but no checking is performed, neither whether \arg{t} |
972 | 978 | is actually a term nor whether \arg{index} is a valid argument index. |
979 | ||
980 | \cfunction{int}{PL_get_dict_key}{atom_t key, term_t +dict, term_t -value} | |
981 | If \arg{dict} is a dict, get the associated value in \arg{value}. Fails | |
982 | silently if \arg{key} does not appear in \arg{dict} and with an | |
983 | exception if \arg{dict} is not a dict. | |
973 | 984 | \end{description} |
974 | 985 | |
975 | 986 | |
1343 | 1354 | Note that \arg{l} can be redefined within a {\tt PL_cons_list} call as |
1344 | 1355 | shown here because operationally its old value is consumed before its |
1345 | 1356 | new value is set. |
1357 | ||
1358 | \cfunction{int}{PL_put_dict}{term_t -h, atom_t tag, size_t len, | |
1359 | const atom_t *keys, term_t values} | |
1360 | Create a dict from a \arg{tag} and vector of atom-value pairs and put | |
1361 | the result in \arg{h}. The dict's key is set by \arg{tag}, which may | |
1362 | be \const{0} to leave the tag unbound. The \arg{keys} vector is a vector | |
1363 | of atoms of at least \arg{len} long. The \arg{values} is a term vector | |
1364 | allocated using PL_new_term_refs() of at least \arg{len} long. This | |
1365 | function returns \const{TRUE} on success, \const{FALSE} on a resource | |
1366 | error (leaving a resource error exception in the environment), | |
1367 | \const{-1} if some key or the \arg{tag} is invalid and \const{-2} if | |
1368 | there are duplicate keys. | |
1346 | 1369 | \end{description} |
1347 | 1370 | |
1348 | 1371 | |
2904 | 2927 | mp_set_memory_functions() in the GMP documentation. The action returns |
2905 | 2928 | \const{FALSE} if there is no GMP support or GMP is already initialised. |
2906 | 2929 | \end{description} |
2930 | ||
2931 | \cfunction{unsigned int}{PL_version}{int key} | |
2932 | Query version information. This function may be called before | |
2933 | PL_initialise(). If the key is unknown the function returns 0. | |
2934 | See \secref{abi-versions} for a more in-depth discussion on | |
2935 | binary compatibility. Defined keys are: | |
2936 | ||
2937 | \begin{description} | |
2938 | \termitem{PL_VERSION_SYSTEM}{} | |
2939 | SWI-Prolog version as $10,000 \times major + 100 \times minor + patch$. | |
2940 | \termitem{PL_VERSION_FLI}{} | |
2941 | Incremented if the foreign interface defined in this chapter changes in | |
2942 | a way that breaks backward compatibility. | |
2943 | \termitem{PL_VERSION_REC}{} | |
2944 | Incremented if the binary representation of terms as used by | |
2945 | PL_record_external() and fast_write/2 changes. | |
2946 | \termitem{PL_VERSION_QLF}{} | |
2947 | Incremented if the QLF file format changes. | |
2948 | \termitem{PL_VERSION_QLF_LOAD}{} | |
2949 | Represents the oldest loadable QLF file format version. | |
2950 | \termitem{PL_VERSION_VM}{} | |
2951 | A hash that represents the VM instructions and their arguments. | |
2952 | \termitem{PL_VERSION_BUILT_IN}{} | |
2953 | A hash that represents the names, arities and properties of all | |
2954 | built-in predicates defined in C. If this function is called | |
2955 | before PL_initialise() it returns 0. | |
2956 | \end{description} | |
2907 | 2957 | \end{description} |
2908 | 2958 | |
2909 | 2959 | \subsection{Querying Prolog} |
58 | 58 | |
59 | 59 | \newcommand{\vmajor}{8} |
60 | 60 | \newcommand{\vminor}{1} |
61 | \newcommand{\vpatch}{29} | |
61 | \newcommand{\vpatch}{30} | |
62 | 62 | \newcommand{\vtag}{} |
63 | \newcommand{\vmonth}{April} | |
63 | \newcommand{\vmonth}{May} | |
64 | 64 | \newcommand{\vyear}{2020} |
65 | 65 | |
66 | 66 | #ifdef BOOK |
350 | 350 | \cmdlineoptionitem{--version}{} |
351 | 351 | When given as the only option, it summarises the version and the |
352 | 352 | architecture identifier. Also available as \cmdlineoption{-v}. |
353 | ||
354 | \cmdlineoptionitem{--abi_version}{} | |
355 | Print a key (string) that represents the binary compatibility on | |
356 | a number of aspects. See \secref{abi-versions}. | |
353 | 357 | \end{description} |
354 | 358 | |
355 | 359 | |
1181 | 1185 | |
1182 | 1186 | |
1183 | 1187 | \begin{description} |
1188 | \prologflagitem{abi_version}{dict}{r} | |
1189 | The flag value is a dict with keys that describe the version of | |
1190 | the various Application Binary Interface (ABI) components. See | |
1191 | \secref{abi-versions} for details. | |
1192 | ||
1184 | 1193 | \prologflagitem{access_level}{atom}{rw} |
1185 | 1194 | This flag defines a normal `user' view (\const{user}, default) or a |
1186 | 1195 | `system' view. In system view all system code is fully accessible as if |
3501 | 3510 | start with a dollar (\chr{\$}) sign. |
3502 | 3511 | |
3503 | 3512 | \input{bit64.tex} |
3513 | ||
3514 | \section{Binary compatibility} \label{sec:abi-versions} | |
3515 | ||
3516 | \index{compatibility,binary}% | |
3517 | \index{ABI,compatibility}% | |
3518 | SWI-Prolog first of all attempts to maintain \jargon{source code} | |
3519 | compatibility between versions. Data and programs can often be | |
3520 | represented in binary form. This touches a number of interfaces | |
3521 | with varying degrees of compatibility. The relevant version numbers | |
3522 | and signatures are made available by PL_version(), the | |
3523 | \cmdlineoption{abi_version} and the Prolog flag | |
3524 | \prologflag{abi_version}. | |
3525 | ||
3526 | \begin{description} | |
3527 | \definition{Foreign extensions} | |
3528 | Dynamically loadable foreign extensions have the usual dependencies on | |
3529 | the architecture, ABI model of the (C) compiler, dynamic link library | |
3530 | format, etc. They also depend on the backward compatibility of the PL_* | |
3531 | API functions provided lib \file{libswipl}. | |
3532 | ||
3533 | A compatible API allows distribution of foreign extensions in binary | |
3534 | form, notably for platforms on which compilation is complicated (e.g., | |
3535 | Windows). This compatibility is therefore high on the priority list, but | |
3536 | must infrequently be compromised. | |
3537 | ||
3538 | PL_version(): \const{PL_VERSION_FLI}, \prologflag{abi_version} key: | |
3539 | \const{foreign_interface} | |
3540 | ||
3541 | \definition{Binary terms} | |
3542 | Terms may be represented in binary format using PL_record_external() and | |
3543 | fast_write/2. As these formats are used for storing binary terms in | |
3544 | databases or communicate terms between Prolog processes in binary form, | |
3545 | great care is taken to maintain compatibility. | |
3546 | ||
3547 | PL_version(): \const{PL_VERSION_REC}, \prologflag{abi_version} key: | |
3548 | \const{record} | |
3549 | ||
3550 | \definition{QLF files} | |
3551 | QLF files (see qcompile/1) are binary representation of Prolog file or | |
3552 | module. They represent clauses as sequences of \jargon{virtual machine} | |
3553 | (VM) instructions. Their compatibility relies on the QLF file format and | |
3554 | the ABI of the VM. Some care is taken to maintain compatibility. | |
3555 | ||
3556 | PL_version(): \const{PL_VERSION_QLF}, \const{PL_VERSION_QLF_LOAD} and | |
3557 | \const{PL_VERSION_VM}, \prologflag{abi_version} key: \const{qlf}, | |
3558 | \const{qlf_min_load}, \const{vmi} | |
3559 | ||
3560 | \definition{Saved states} | |
3561 | Saved states (see \cmdlineoption{-c} and qsave_program/2) is a zip file | |
3562 | that contains the entire Prolog database using the same representation | |
3563 | as QLF files. A saved state may contain additional resources, such as | |
3564 | foreign extensions, data files, etc. In addition to the dependency | |
3565 | concerns of QLF files, built-in and core library predicates may call | |
3566 | \emph{internal} foreign predicates. The interface between the public | |
3567 | built-ins and internal foreign predicates changes frequently. Patch | |
3568 | level releases in the \emph{stable branch} will as much as possible | |
3569 | maintain compatibility. | |
3570 | ||
3571 | The relevant ABI version keys are the same as for QLF files with one | |
3572 | addition: PL_version(): \const{PL_VERSION_BUILT_IN}, \prologflag{abi_version} | |
3573 | key: \const{built_in} | |
3574 | \end{description} | |
3575 |
839 | 839 | \subsection{Restraint subgoal size} |
840 | 840 | \label{sec:tabling-restraint-subgoal} |
841 | 841 | |
842 | Using the \term{abstract_subgoal}{Size} attribute, a tabled subgoal that | |
842 | Using the \term{subgoal_abstract}{Size} attribute, a tabled subgoal that | |
843 | 843 | that is too large is \jargon{abstracted} by replacing compound subterms |
844 | 844 | of the goal with variables. In a nutshell, a goal |
845 | 845 | \term{p}{s(s(s(s(s(0)))))} is converted into the semantically equivalent |
916 | 916 | |
917 | 917 | |
918 | 918 | /** uri_query_components(+QueryString, -ValueList) is det. |
919 | ||
920 | (*) We must malloc() because the individual query components use the | |
921 | text ring buffer, so with more query components then the ring size the | |
922 | original text gets corrupted. | |
919 | 923 | */ |
920 | 924 | |
921 | 925 | static foreign_t |
923 | 927 | { pl_wchar_t *s; |
924 | 928 | size_t len; |
925 | 929 | |
926 | if ( PL_get_wchars(string, &len, &s, CVT_ATOM|CVT_STRING|CVT_LIST) ) | |
927 | { return unify_query_string_components(list, len, s); | |
930 | if ( PL_get_wchars(string, &len, &s, CVT_ATOM|CVT_STRING|CVT_LIST|BUF_MALLOC) ) | |
931 | { int rc = unify_query_string_components(list, len, s); | |
932 | PL_free(s); /* See (*) */ | |
933 | return rc; | |
928 | 934 | } else if ( PL_is_list(list) ) |
929 | 935 | { term_t tail = PL_copy_term_ref(list); |
930 | 936 | term_t head = PL_new_term_ref(); |
10 | 10 | ${JQUERYFILE} |
11 | 11 | PATHS /usr/share/javascript/jquery |
12 | 12 | NO_DEFAULT_PATH) |
13 | # Deal with snap creation | |
14 | string(REPLACE "-sdk/current/" "/current/" JQUERYDIR "${JQUERYDIR}") | |
13 | 15 | endif() |
14 | 16 | |
15 | 17 | if(JQUERYDIR AND EXISTS ${JQUERYDIR}/${JQUERYFILE}) |
0 | 0 | cmake_minimum_required(VERSION 3.5) |
1 | 1 | project(swipl-jpl) |
2 | 2 | |
3 | set(JPL_VERSION 7.6.0) | |
3 | 4 | |
4 | 5 | #message(${CMAKE_CURRENT_SOURCE_DIR}) # <project>/packages/jpl |
5 | 6 | #message(${PROJECT_SOURCE_DIR}) # <project>/packages/jpl |
0 | 0 | # Deploying for users - on Linux |
1 | 1 | |
2 | Recall that to use JPL under linux one must have the following in place: | |
2 | To use JPL under Linux one must have the following in place (here showing the locations under Linux Mint distribution under packages `swi-prolog-nox` and `swi-prolog-java`): | |
3 | 3 | |
4 | * C Native JPL Library `libjpl.so`, generally found at `/usr/lib/swi-prolog/lib/amd64/libjpl.so` | |
5 | * Java API Jar file `jpl.jar` in the Java `CLASSPATH`, generally accessible from `/usr/share/java/jpl.jar`. | |
6 | * Prolog API as an SWI source module `jpl.pl` at `$SWI_HOME_DIR/library`, generally accessible from `/usr/lib/swi-prolog/library/jpl.pl` | |
7 | ||
8 | JPL is **generally distributed with official Linux**. For example, in Ubuntu-based systems, JPL is provided via package `swi-prolog-java`. That package includes the C library `libjpl.so`, the Java API `jpl.jar`, the Prolog module `jpl.pl` as well as all documentation associated. | |
4 | * A SWIPL install containing the core SWI system, which includes: | |
5 | * A SWIPL home directory (`SWI_HOME_DIR`), located at `/usr/lib/swi-prolog/` and containing the whole SWIPL core system, including a booting `.prc` file (`$SWI_HOME_DIR/boot64.prc`). | |
6 | * The "home" of SWIPL can be queried via [`current_prolog_flag(home, H)`](https://www.swi-prolog.org/pldoc/man?predicate=current_prolog_flag/2) | |
7 | * The C Native core SWIPL library `/usr/lib/libswipl.so`. | |
8 | * The set of C Native SWIPL libraries for each package (files `.so`), located in `/usr/lib/swi-prolog/lib/amd64/` | |
9 | * The JPL package, which includes: | |
10 | * The C Native JPL Library `libjpl.so` at `$SWI_HOME_DIR/lib/amd64/libjpl.so`. | |
11 | * The Java API JAR file `jpl.jar` in `$SWI_HOME_DIR/lib/jpl.jar`. | |
12 | * The Prolog API as an SWIPL source module `jpl.pl` at `$SWI_HOME_DIR/library`. | |
13 | ||
14 | ## Which SWIPL version to (not) use? | |
15 | ||
16 | JPL is **generally distributed with official Linux**. For example, in Ubuntu-based systems, JPL is provided via package `swi-prolog-java`. That package includes the C library `libjpl.so`, the Java API `jpl.jar`, the Prolog module `jpl.pl` as well as all associated documentation. | |
9 | 17 | |
10 | 18 | However, the **official packages are often out-of-date**. For Debian-based systems (Debian, Ubuntu, Mint, ...) you can get the latest stable and development versions via [this PPAs](http://www.swi-prolog.org/build/PPA.txt) provided directly by SWI-Prolog. |
11 | 19 | |
12 | To use JPL, use either SWI stable version 7.6.4 (available in standard Linux repos) or compile and install 8.1.x from SWI-devel repo. | |
13 | * **Note:** The official stable SWI 8.0.x versions (as of Jan 2020) have issues with the `libswipl.so/dll/dylib` library and makes JPL crash; see [issue](https://github.com/ssardina-research/packages-jpl/issues/21). It has been fixed in the git repo but will only show up with versions 8.1.x. | |
20 | Use either SWIPL stable version 7.6.4 (available in standard Linux repos) or compile & install 8.1.x from [SWI-devel repo](https://github.com/SWI-Prolog/swipl-devel) using CMAKE. | |
21 | * **Note:** The official stable SWI 8.0.x versions (as of Jan 2020) have issues with the `libswipl.so/dll/dylib` library and makes JPL crash; see [issue](https://github.com/ssardina-research/packages-jpl/issues/21). It has been fixed in the git repo but will only show up with versions 8.1.x. | |
22 | ||
23 | ## Configuring environment variables | |
14 | 24 | |
15 | Finally, to be **able to use JPL** you may need to make sure that: | |
25 | When embeeding SWIPL into a Java, one may needs to "tell" the Java application the right information, via environment variables, so that SWIPL is initialized properly and can find all resources. | |
16 | 26 | |
17 | * Extend environment library `LD_PRELOAD` for system to pre-load `libswipl.so`: | |
18 | * `export LD_PRELOAD=libswipl.so:$LD_PRELOAD` | |
19 | * Check [this post](https://answers.ros.org/question/132411/unable-to-load-existing-owl-in-semantic-map-editor/) and [this one](https://blog.cryptomilk.org/2014/07/21/what-is-preloading/) about library preloading. | |
20 | * Also, check [this](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=690734) and [this](https://github.com/yuce/pyswip/issues/10) posts. | |
21 | * Extend environment variable `LD_LIBRARY_PATH` to point to the directory where `libjpl.so` is located: | |
22 | * `export LD_LIBRARY_PATH=/usr/lib/swi-prolog/lib/amd64/` | |
23 | * Make sure `jpl.jar` is in your Java CLASSPATH. This is generally automatically done if environment variable `SWI_HOME_DIR` is correctly set to `/usr/lib/swi-prolog/`. | |
27 | In general, if the Java application will use the default executable of the system (i.e., the one that runs when executing `swipl`), then you only need to set-up `CLASSPATH` to include `jpl.jar` and possibly `LD_PRELOAD` to point to your active SWIPL `libswipl.so` library to avoid run-time errors. The executable has a pointer to the right information to initialize; see [here](https://www.swi-prolog.org/FAQ/FindResources.html). | |
24 | 28 | |
25 | To install JPL from scratch (e.g., to compiling it in order to develop it further) please refer to the [Developing JPL](Developing-JPL) guide. | |
29 | However, if your Java application will use an SWIPL & JPL version that is _not_ the exectuable default. | |
30 | ||
31 | ### Using stable distribution versions of SWIPL | |
32 | ||
33 | If the **Linux distribution install** of SWIPL & JPL is not the executable default but the one to be used, set-up the following environment variables: | |
34 | ||
35 | SWI_HOME_DIR=/usr/lib/swi-prolog/ # if default binary not pointing to this version | |
36 | LD_LIBRARY_PATH=/usr/lib/swi-prolog/lib/amd64/ # to find all .so, including libjpl.so | |
37 | CLASSPATH=/usr/lib/swi-prolog/lib/jpl.jar | |
38 | LD_PRELOAD=/usr/lib/libswipl.so # see below for explanation | |
39 | ||
40 | or in one line (for IDE Run configurations, for example): | |
41 | ||
42 | CLASSPATH=/usr/lib/swi-prolog/lib/jpl.jar;LD_LIBRARY_PATH=/usr/lib/swi-prolog/lib/amd64/;LD_PRELOAD=/usr/lib/libswipl.so;SWI_HOME_DIR=/usr/lib/swi-prolog/ | |
43 | ||
44 | Notice that, in this case, library `libswipl.so` will be found automatically, as it is located in the standard system-wide library dir `/usr/lib`. | |
45 | ||
46 | ### Using locally compiled and installed version of SWIPL | |
47 | ||
48 | Alternatively, if you have **compiled and installed** an SWIPL system, say, under directory `/usr/local/swipl-git/`, then the SWIPL home will be `/usr/local/swipl-git/lib/swipl/`, the executable binary will be `/usr/local/swipl-git/lib/swipl/bin/x86_64-linux/swipl` and the environment variables should be set-up as follows: | |
49 | ||
50 | SWI_HOME_DIR=/usr/local/swipl-git/lib/swipl/ # if binary exec not pointing to this SWIPL | |
51 | LD_LIBRARY_PATH=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/ # to find all .so, including libjpl.so | |
52 | CLASSPATH=/usr/local/swipl-git/lib/swipl/lib/jpl.jar | |
53 | LD_PRELOAD=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/libswipl.so # see below for explanation | |
54 | ||
55 | or in one line (for IDE Run configurations, for example): | |
56 | ||
57 | CLASSPATH=/usr/local/swipl-git/lib/swipl/lib/jpl.jar;LD_LIBRARY_PATH=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/;LD_PRELOAD=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/libswipl.so;SWI_HOME_DIR=/usr/local/swipl-git/lib/swipl/ | |
58 | ||
59 | ## Using the development tree of SWI+JPL that is yet not installed? | |
60 | ||
61 | If you want to run your application against a development tree of SWIPL & JPL that is not yet installed, then refer to [Developing JPL](TutorialDeveloping.md) guide. | |
62 | ||
26 | 63 | |
27 | 64 | ## Troubleshooting |
65 | ||
66 | ### Pre-loading `libswipl.so` | |
67 | ||
68 | The [libray preloading](https://blog.cryptomilk.org/2014/07/21/what-is-preloading/) of `libswipl.so` is often necessary to avoid the following run-time error (check [this](https://answers.ros.org/question/132411/unable-to-load-existing-owl-in-semantic-map-editor/), [this](https://github.com/yuce/pyswip/issues/10) and [this](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=690734) posts): | |
69 | ||
70 | ERROR: /usr/lib/swi-prolog/library/process.pl:53: | |
71 | /usr/lib/swi-prolog/library/process.pl:53: Initialization goal raised exception: | |
72 | '$open_shared_object'/3: /usr/lib/swi-prolog/lib/amd64/process.so: undefined symbol: Sfilefunctions | |
73 | ||
74 | ### [FATAL ERROR: Could not find system resources]. | |
75 | ||
76 | It is not finding the correct `libswipl.so`. |
97 | 97 | |
98 | 98 | `Term` instances are never changed by any activity within the Prolog engine: indeed; it doesn't know of their existence. |
99 | 99 | |
100 | The `Term` class is abstract, so it cannot be directly instantiated; to create a Term, create an instance of one of its subclasses. | |
100 | The `Term` class is abstract, so it cannot be directly instantiated; to create a Term, create an instance of one of its subclasses, which are the ones accounting for the various [data types in SWI-Prolog](https://www.swi-prolog.org/datatypes.html). | |
101 | 101 | |
102 | 102 | ### Atoms |
103 | 103 | |
234 | 234 | public Term arg0(int i); |
235 | 235 | ``` |
236 | 236 | |
237 | #### Lists as compound terms | |
238 | ||
239 | As usual in Prolog, lists are just compound terms with function `[|]` and two arguments: the _head_ element and the _tail_ list. For example: | |
240 | ||
241 | ```prolog | |
242 | ?- A = [1,2,3,4], A =.. [X|Y]. | |
243 | A = [1, 2, 3, 4], | |
244 | X = '[|]', | |
245 | Y = [1, [2, 3, 4]]. | |
246 | ```` | |
247 | ||
248 | We can build list compound terms in two ways. First, by converting an Array of terms (`Term[]`) into a Compound (list) term using utility `Util.termArrayToList`: | |
249 | ||
250 | ```java | |
251 | Term list = Util.termArrayToList(new Term[] | |
252 | { new Integer(1), new Variable("B"), new Atom("c") }); | |
237 | ### Lists | |
238 | ||
239 | In SWI-Prolog a list is either: | |
240 | ||
241 | * An empty list `[]`. In JPL, the empty list is the constant `JPL.LIST_NIL` and is a final object of class `Atom`. (Observe on the SWI side, from SWI-Prolog 7+, the empty list is not an atom but a reserved word.) | |
242 | * A `Compound` term with functor `[|]` and two arguments where the second one is itself a list. On the Prolog side: | |
243 | ||
244 | ?- A = [1,2,3,4], A =.. [X|Y]. | |
245 | A = [1, 2, 3, 4], | |
246 | X = '[|]', | |
247 | Y = [1, [2, 3, 4]]. | |
248 | ||
249 | While one can build non-empty lists by creating `Compound` terms, it can become really cumbersome, as the second argument always has to be another lits. | |
250 | ||
251 | So, class `Term` provides several _static_ methods to conveniently build non-empty lists, namely: | |
252 | ||
253 | ```java | |
254 | public static Term textToTerm(String text) | |
255 | public static Term termArrayToList(Term[] terms) | |
256 | public static Term stringArrayToList(String[] a) | |
257 | public static Term intArrayToList(int[] a) | |
258 | public static Term intArrayArrayToList(int[][] a) | |
259 | ``` | |
260 | ||
261 | Method `textToTerm(String text)` can actually build _any_ term form its String representation, including list terms: | |
262 | ||
263 | ```java | |
264 | Term list = Util.textToTerm("[1, B, [p(g), g(1)], c]"); | |
265 | ``` | |
266 | ||
267 | A second tool is `termArrayToList(Term[])`, which builds a list from an Array of Terms (`Term[]`) (the corresponding functors `[|]` are added automatically). For example: | |
268 | ||
269 | ```java | |
270 | Term list = Term.termArrayToList(new Term[] // list [1, B, hello] | |
271 | { new Integer(1), new Variable("B"), new Atom("hello") }); | |
253 | 272 | ``` |
254 | 273 | |
255 | The second way is by converting a String representing a list into a term via `Util.textToTerm`: | |
256 | ||
257 | ```java | |
258 | Term list = Util.textToTerm("[1, B, c]"); | |
259 | ``` | |
260 | ||
274 | Finally, one can build specific data-type lists using: | |
275 | * `stringArrayToList(String[] a)`: builds a list of atoms from an Array of Strings; | |
276 | * `intArrayToList(int[] a)`: builds a list of integers; | |
277 | * `intArrayArrayToList(int[][] a)`: builds a list of lists of integers. | |
278 | ||
279 | On the other direction, the following methods in `Term` class transform a list Term into another Java type: | |
280 | ||
281 | ```java | |
282 | public static String toString(Term t) | |
283 | public static Term[] listToTermArray(Term t) | |
284 | public static String[] atomListToStringArray(Term t) | |
285 | ``` | |
286 | ||
287 | When it comes to non-empty, compound, list terms, the behavior of `toString()` will depend on boolean `JPL.LIST_TOSTRING_TEXTUAL`: | |
288 | * If True, lists will be represented as String in the usual Prolog textual representation `[e1, e2, e3, ...., en]`. Note a space wil be added after each comma always. | |
289 | * If False, lists will be represented in infix notation with the list pair functor `[|]`, e.g., `[|](1, [|](2, [|](3, '[]')))` for list `[1, 2, 3]`. | |
261 | 290 | |
262 | 291 | |
263 | 292 | |
347 | 376 | ``` |
348 | 377 | |
349 | 378 | If the query has no solutions, this method returns `null`; otherwise, a non-null return indicates success. If the query is ground (i.e. contains no variables), the returned map will be empty (i.e. will contain no bindings). |
379 | ||
380 | If the query is non-ground (i.e., it includes variables), then bindings are retrieved by name, e.g.: | |
381 | ||
382 | ``` | |
383 | Map m = org.jpl7.Query.oneSolution("statistics(heap, X)"); | |
384 | long heapsize = m.get("X"); | |
385 | ``` | |
386 | ||
350 | 387 | |
351 | 388 | ### Obtaining all solutions |
352 | 389 | |
456 | 493 | |
457 | 494 | ## Gotchas |
458 | 495 | |
459 | ### Variables are named | |
460 | ||
461 | Instances of `org.jpl7.Variable` have names, and bindings are retrieved by name, e.g. | |
462 | ||
463 | ``` | |
464 | Map m = org.jpl7.Query.oneSolution("statistics(heap, X)"); | |
465 | long heapsize = m.get("X"); | |
466 | ``` | |
467 | ||
468 | 496 | ### Argument numbering |
469 | 497 | |
470 | 498 | The `Term[]` args of a `Compound` are indexed (like all Java arrays) from zero, whereas in Prolog the args of a structure are conventionally numbered from one. |
3 | 3 | |
4 | 4 | * Version [JPL 7.x](https://jpl7.org/) uses SWI Prolog V7 and has modernise JPL's APIs significantly. |
5 | 5 | |
6 | * Current version []7.4.0](https://jpl7.org/ReleaseNotes740.jsp) works with SWI versions V7.4.x to V7.7.x. It has a new implemention of JRefs as blobs to address Java objects from Prolog. | |
6 | * Version [7.6.0](https://jpl7.org/ReleaseNotes760.jsp) works with SWI versions V8.1.x+. It adds Rationals as a data type and has several term methods refactored into class Term. | |
7 | ||
8 | * Version [7.5.0](https://jpl7.org/ReleaseNotes750.jsp) works with SWI versions V7.4.x to V7.7.x. It has a new implemention of iterators ans solution methods in Queries and better handling of quoted terms. | |
9 | ||
10 | * Version [7.4.0](https://jpl7.org/ReleaseNotes740.jsp) works with SWI versions V7.4.x to V7.7.x. It has a new implemention of JRefs as blobs to address Java objects from Prolog. | |
7 | 11 | |
8 | 12 | * Versions [JPL 3.x,y](http://www.swi-prolog.org/packages/jpl/) implemented many changes and worked with SWI V5.2.0 or later (it used multi-threading FLI calls not available in older versions) and Java 2 runtime. It was tested with Microsoft Visual C/C++ 5 under Windows NT 4.0 (SP6a). |
9 | 13 |
14 | 14 | ## Versions up to 7.4 |
15 | 15 | |
16 | 16 | - Complete overhawl from version 3.x |
17 | - Check release notes for [7.4.0](https://jpl7.org/ReleaseNotes740.jsp). | |
18 | - Check release notes for [7.0.1](https://jpl7.org/ReleaseNotes701.jsp). | |
17 | - Check release notes for [7.4.0](ReleaseNotes740). | |
18 | - Check release notes for [7.0.1](ReleaseNotes701). | |
19 | 19 | |
20 | 20 | |
21 | 21 |
0 | # Release Notes - 7.6.0 | |
1 | ||
2 | - New `org.jpl7.Rational` type to handle [SWI rationals](https://www.swi-prolog.org/pldoc/man?section=rational). | |
3 | - Refactored several methods dealing with JPL terms, from `org.jpl7.Util` to `org.jpl7.Term`: | |
4 | - `Term textToTerm(String text)` | |
5 | - `String[] atomListToStringArray(Term t)` | |
6 | - `static Term intArrayArrayToList(int[][] a)` | |
7 | - `Term intArrayToList(int[] a)` | |
8 | - `boolean isList(Term term)` | |
9 | - `int listToLength(Term term)` | |
10 | - `Term[] listToTermArray(Term t)` | |
11 | - `Term stringArrayToList(String[] a)` | |
12 | - `Term termArrayToList(Term[] terms)` | |
13 | - Added a textual mode for `Term.toString()` to convert non-empty lists in Prolog textual style `[e2, e2, ..., en]` instead of the pre-fix functor-based style `'[|]'(e1, '[|]'(e2, '[|]'(...,'[|]'(en,'[]')..)`. | |
14 | - This textual mode is used when `JPL.LIST_TOSTRING_TEXTUAL` is True (default is True); otherwise default pre-fix style is used. | |
15 | - Added specific section for lists in documentation. | |
16 | ||
17 | ## Internal | |
18 | ||
19 | - More direct and simpler `Term.textToTerm(String text)` without using | |
20 | `getSolutionWithVarNames` and by renaming anonymous Variable terms to give them the textual name. | |
21 | - Migrated unit testing from JUnit3 to JUnit4. | |
22 | - Refactored the unit testing test suite; all test files subclass of `org.jpl7.java.test.junit.JPLTest`. | |
23 | - Modified init arguments and CMAKE configuration for SWI embeded engine unit testing to fix issue with engine not loading libraries. No more use of `libswipl.dll` as first argument; all packages available in unit tetsing now. | |
24 | - Added some static versions of instance methods in class `Term`.⏎ |
177 | 177 | [ssardina@Thinkpad-X1 build]$ |
178 | 178 | ``` |
179 | 179 | |
180 | ||
181 | ## Using non-installed development tree of SWIPL & JPL in Java application | |
182 | ||
183 | Suppose you are developing JPL as above, in this case at `/home/ssardina/git/soft/prolog/swipl-devel.git` | |
184 | ||
185 | However, you have a Java application X besides JPL itself and want to test that application under the current SWIPL+JPL development. There are several things that need to be set-up for your application to correctly access the SWIPL+JPL under development. | |
186 | ||
187 | First, we need to **setup various environment variables** so that the correct SWIPL+JPL is initialized and used: | |
188 | ||
189 | SWI_HOME_DIR=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home | |
190 | SWI_EXEC_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/src/swipl | |
191 | SWIPL_BOOT_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home/boot.prc | |
192 | LD_LIBRARY_PATH=/home/ssardina/git/soft/prolog/swipl-devel.git/build/packages/jpl | |
193 | LD_PRELOAD=/home/ssardina/git/soft/prolog/swipl-devel.git/build/src/libswipl.so | |
194 | CLASSPATH=/home/ssardina/git/soft/prolog/swipl-devel.git/packages/jpl/out/artifacts/jpl_jar/ | |
195 | ||
196 | The `CLASSPATH` needs to point to the `jpl.jar` file that needs to be us used in case `jpl.pl` requires it (to access JAVA from Prolog). | |
197 | ||
198 | In one line (to copy into the usual Run-configuration of IDE): | |
199 | ||
200 | LD_LIBRARY_PATH=/home/ssardina/git/soft/prolog/swipl-devel.git/build/packages/jpl;SWI_HOME_DIR=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home;SWIPL_BOOT_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home/boot.prc;CLASSPATH=/home/ssardina/git/soft/prolog/swipl-devel.git/packages/jpl/out/artifacts/jpl_jar/;LD_PRELOAD=/home/ssardina/git/soft/prolog/swipl-devel.git/build/src/libswipl.so;SWI_EXEC_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/src/swipl | |
201 | ||
202 | ||
203 | Second, we need to tell our applicatoin X development to use the development JPL Java, and NOT any other `jpl.jar` that may be in the system (e.g., due to a distribution installation). In our example, under IntelliJ, we define a library `jpl` in the project of the application pointing to directory: | |
204 | ||
205 | /home/ssardina/git/soft/prolog/swipl-devel.git/packages/jpl/out/production/jpl | |
206 | ||
207 | where all the classes for the currente devel JPL are located (if we are using IntelliJ). Then provded that library to use for your application/module for compilation and runtime. | |
208 | ||
209 | Third, and finally, you need to explicitly initialize the SWIPL JPL engine in your Java application to with the right home, executable, and most importantly `-F swipl` so that the initialization file `swipl.rc` in charge of setting up all the search paths: | |
210 | ||
211 | ```java | |
212 | String init_swi_config = | |
213 | String.format("%s -x %s -F swipl --home=%s -g true -q", | |
214 | System.getenv("SWI_EXEC_FILE"), # irrelevant for Windows | |
215 | System.getenv("SWIPL_BOOT_FILE"), | |
216 | System.getenv("SWI_HOME_DIR")); | |
217 | JPL.setDefaultInitArgs(init_swi_config.split("\\s+")); # initialize SWIPL engine | |
218 | JPL.init() | |
219 | ``` | |
220 | ||
221 | Because SWIPL tries to "guess" the location of the binary and boot file, in most cases, it also suffies to do: | |
222 | ||
223 | ```java | |
224 | String init_swi_config = | |
225 | String.format("dummy --home=%s -g true -q", | |
226 | System.getenv("SWI_HOME_DIR")); | |
227 | JPL.setDefaultInitArgs(init_swi_config.split("\\s+")); # initialize SWIPL engine | |
228 | ``` | |
229 | ||
230 | ||
231 |
13 | 13 | You may wish to load this database into an interactive Prolog session to experiment with the predicates in this database before experimenting with JPL. |
14 | 14 | |
15 | 15 | |
16 | ## Initializing The Prolog engine | |
16 | ## Initializing the Prolog engine | |
17 | 17 | |
18 | Although the `org.jpl7.JPL` class provides a number of methods for initializing the Prolog engine from within Java, their use is not usually necessary: Prolog will be automatically initialised with default parameters at the first attempt to use it. | |
18 | Although the `org.jpl7.JPL` class provides a number of methods for initializing the Prolog engine from within Java, their use is not usually necessary: Prolog will be _automatically initialised_ with default parameters at the first attempt to use it. | |
19 | ||
20 | By default, the SWIPL install accessible via the _default executable_ (i.e., the one that runs when one types `swipl`) will be initialized. If one, instead, _requires to use another install_ of SWIPL+JPL (e.g., the one under development or an alternative one installed in `/usr/local`), then we need to set-up a few variables to make sure the intended SWIPL resources are found. For example, suppose we intend that our Java-based application uses the SWIPL framework locally installed in `/usr/local/swipl/`. Then: | |
21 | ||
22 | SWI_HOME_DIR=/usr/local/swipl-git/lib/swipl/ # root of SWIPL install | |
23 | LD_LIBRARY_PATH=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/ # all .so nativ libs | |
24 | LD_PRELOAD=/usr/local/swipl-git/lib/swipl/lib/x86_64-linux/libswipl.so | |
25 | CLASSPATH=/usr/local/swipl-git/lib/swipl/lib/jpl.jar | |
26 | ||
27 | From here, [SWIPL will try to find/guess the resources](https://www.swi-prolog.org/FAQ/FindResources.html) and set-up the engine correctly. | |
28 | ||
29 | Note also that you need to tell your development environment (e.g., IntelliJ or ECLIPSE) to use the correct `jpl.jar` (rather than one coming with the default active SWIPL system) or even the place where the JPL compiled classes are located if you intend to use a development (but uninstall) version of JPL. | |
30 | ||
31 | Sometimes one needs to _explicitly initialize_ the engine (before a query triggers defaul initialization); for example, if one wants to use an SWIPL & JPL under a development tree that is not yet installed. Assuming that development is happening under `/home/ssardina/git/soft/prolog/swipl-devel.git`, the following code template will perform a comprehensive, and quiety, initialization (before any query is performed) (see [CLI options](https://www.swi-prolog.org/pldoc/man?section=cmdline) available): | |
32 | ||
33 | ```java | |
34 | String init_swi_config = | |
35 | String.format("%s -x %s -F swipl --home=%s -g true -q", | |
36 | System.getenv("SWI_EXEC_FILE"), # irrelevant for Windows | |
37 | System.getenv("SWIPL_BOOT_FILE"), | |
38 | System.getenv("SWI_HOME_DIR")); | |
39 | JPL.setDefaultInitArgs(init_swi_config.split("\\s+")); # initialize SWIPL engine | |
40 | JPL.init() | |
41 | ``` | |
42 | ||
43 | The option `-F swipl` will cause the script `$SWI_HOME_DIR/swipl.rc` to be loaded which will set-up all the search paths relative to the install. The above code will require the following environment variables: | |
44 | ||
45 | SWI_HOME_DIR=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home | |
46 | SWI_EXEC_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/src/swipl | |
47 | SWIPL_BOOT_FILE=/home/ssardina/git/soft/prolog/swipl-devel.git/build/home/boot.prc | |
48 | ||
49 | Because SWIPL tries to "guess" the location of the binary and boot file, in most cases, it also suffies to do: | |
50 | ||
51 | ```java | |
52 | String init_swi_config = | |
53 | String.format("dummy --home=%s -g true -q", | |
54 | System.getenv("SWI_HOME_DIR")); | |
55 | JPL.setDefaultInitArgs(init_swi_config.split("\\s+")); # initialize SWIPL engine | |
56 | ``` | |
19 | 57 | |
20 | 58 | |
21 | 59 |
71 | 71 | // process solution... |
72 | 72 | } |
73 | 73 | while (query1.hasMoreSolutions()) { // finish processing query1 |
74 | Map<String, Term> solution = query2.nextSolution(); | |
74 | Map<String, Term> solution = query1.nextSolution(); | |
75 | 75 | // process solution... |
76 | 76 | } |
77 | 77 | ``` |
148 | 148 | |
149 | 149 | [Queries from multi-threaded applications](https://jpl7.org/JavaApiOverview#queries-from-multi-threaded-applications) |
150 | 150 | |
151 | as well in this related issue at Github: https://github.com/SWI-Prolog/packages-jpl/issues/15 | |
151 | as well in this related [issue #15](https://github.com/SWI-Prolog/packages-jpl/issues/15) at Github: | |
152 | 152 | |
153 | 153 |
21 | 21 | * minimum impact deployability: runtime support for Prolog+Java apps must be a position-independent, self-sufficient filestore tree, requiring no changes to registries, system libraries, system configuration files etc; |
22 | 22 | * minimum dependency deployability: as with JVMs, the Prolog+Java runtime support must depend upon nothing which cannot be taken for granted in healthy OS installations; and |
23 | 23 | * minimum vulnerability deployability: the Prolog+Java runtime support must be immune to legitimate variations in its environment (PATH settings, other applications and libraries including other Prolog+Java apps, etc.). |
24 | ||
25 | ### Historical perspective | |
26 | ||
27 | JPL was originally dreamed to be independent of Prolog implementation, mapping only the classic Prolog term model to and from Java, and its Java-side implementation deliberately resisted adoption of post Java 1.4 features (some nice, but none irresistible), thereby maintaining compatibility with (now very) old JVMs which some deployment environments might be stuck with. | |
28 | ||
29 | Innovations in SWI Prolog 7 prompted a JPL overhaul (from 3.0.3 to 7.0.1) which changed the public API and warranted a rebrand (as "JPL7", in a nod to SWIPL7). | |
30 | ||
31 | (Summary taken from discussion in [this issue](https://github.com/SWI-Prolog/packages-jpl/issues/46).) | |
24 | 32 | |
25 | 33 | |
26 | 34 | ## About this page |
177 | 177 | Term Y = solutions[0].get("Y"); |
178 | 178 | if (X != Y) { |
179 | 179 | System.out.println(t7 + " failed:"); |
180 | System.out.println(Util.toString(solutions[0])); | |
180 | System.out.println(Util.subsToString(solutions[0])); | |
181 | 181 | System.out.println("\tThe variables to which X and Y are bound in the first solution should be identical."); |
182 | 182 | // System.exit(1); |
183 | 183 | } |
185 | 185 | Y = solutions[1].get("Y"); |
186 | 186 | if (X == Y) { |
187 | 187 | System.out.println(t7 + " failed:"); |
188 | System.out.println(Util.toString(solutions[1])); | |
188 | System.out.println(Util.subsToString(solutions[1])); | |
189 | 189 | System.out.println("\tThe variables to which X and Y are bound in the second solution should be distinct."); |
190 | 190 | // System.exit(1); |
191 | 191 | } |
192 | 192 | if (X.equals(Y)) { |
193 | 193 | System.out.println(t7 + " failed:"); |
194 | System.out.println(Util.toString(solutions[1])); | |
194 | System.out.println(Util.subsToString(solutions[1])); | |
195 | 195 | System.out.println("\tThe variables to which X and Y are bound in the second solution should not be \"equal\"."); |
196 | 196 | // System.exit(1); |
197 | 197 | } |
214 | 214 | } |
215 | 215 | |
216 | 216 | // corresponds with Prolog List: [a-a,a-b] |
217 | static Term test_9_solution = Util.termArrayToList(new Term[] { new Compound("-", new Term[] { a, a }), new Compound("-", new Term[] { a, b }) }); | |
217 | static Term test_9_solution = Term.termArrayToList(new Term[] { new Compound("-", new Term[] { a, a }), new Compound("-", new Term[] { a, b }) }); | |
218 | 218 | |
219 | 219 | static void test_9() { |
220 | 220 | System.out.print("test 9..."); |
1217 | 1217 | % |
1218 | 1218 | % == |
1219 | 1219 | % ?- jpl_pl_lib_version(V). |
1220 | % V = '7.4.0-alpha'. | |
1220 | % V = '7.6.0-alpha'. | |
1221 | 1221 | % == |
1222 | 1222 | |
1223 | 1223 | jpl_pl_lib_version(VersionString) :- |
1239 | 1239 | % Status = alpha. |
1240 | 1240 | % == |
1241 | 1241 | |
1242 | jpl_pl_lib_version(7, 4, 0, alpha). % jref as blob | |
1242 | jpl_pl_lib_version(7, 6, 0, alpha). % jref as blob | |
1243 | 1243 | |
1244 | 1244 | %! jpl_c_lib_version(-Version) |
1245 | 1245 | % |
54 | 54 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
55 | 55 | |
56 | 56 | /* update this to distinguish releases of this C library: */ |
57 | #define JPL_C_LIB_VERSION "7.4.0-alpha" | |
57 | #define JPL_C_LIB_VERSION "7.6.0-alpha" | |
58 | 58 | #define JPL_C_LIB_VERSION_MAJOR 7 |
59 | #define JPL_C_LIB_VERSION_MINOR 4 | |
59 | #define JPL_C_LIB_VERSION_MINOR 6 | |
60 | 60 | #define JPL_C_LIB_VERSION_PATCH 0 |
61 | 61 | #define JPL_C_LIB_VERSION_STATUS "alpha" |
62 | 62 |
88 | 88 | set(CMAKE_JAVA_COMPILE_FLAGS) |
89 | 89 | endif() |
90 | 90 | |
91 | ||
91 | 92 | add_jar(jpl_jar |
92 | 93 | SOURCES ${CLS} ${FLI} |
93 | OUTPUT_NAME jpl) | |
94 | OUTPUT_NAME jpl | |
95 | MANIFEST META-INF/MANIFEST.MF | |
96 | VERSION ${JPL_VERSION}) # VERSION creates jar with the -<version>jar format and a symblic to it. | |
94 | 97 | |
95 | 98 | if(JUNIT_JAR) |
96 | 99 | add_jar(jpltest |
0 | Name: org.jpl7 | |
1 | Implementation-Title: JPL | |
2 | Implementation-Version: 7.6.0 | |
3 | Implementation-Vendor: SWI-Prolog |
176 | 176 | * @return string representation of an Atom |
177 | 177 | */ |
178 | 178 | public String toString() { |
179 | return (JPL.isSimpleName(name) ? name : "'" + name + "'"); | |
179 | return (JPL.isSimpleName(name) || isListNil() ? name : "'" + name + "'"); | |
180 | 180 | } |
181 | 181 | |
182 | 182 | /** |
226 | 226 | |
227 | 227 | /** |
228 | 228 | * whether this Term denotes (syntax-specifically) a list cell |
229 | * see this does not check the shape of the second argument to check if it is a list | |
230 | * | |
231 | * So a list pair may not be a list itself and hence isList() will return false | |
232 | * as the second argument many not be a list | |
229 | 233 | * |
230 | 234 | * @return whether this Term denotes (syntax-specifically) a list cell |
231 | 235 | */ |
280 | 284 | } |
281 | 285 | |
282 | 286 | |
283 | ||
284 | /** | |
285 | * a prefix functional representation of a Compound of the form name(arg1,...), where 'name' is quoted iff necessary | |
286 | * (to be valid Prolog soutce text) and each argument is represented according to its toString() method. | |
287 | /** | |
288 | * | |
289 | * a prefix functional representation of a Compound of the form name(arg1,...), | |
290 | * where 'name' is quoted iff necessary | |
291 | * (to be valid Prolog source text) and each argument is represented according to its | |
292 | * toString() method. | |
293 | * | |
294 | * Lists are represented depending on JPL.LIST_TOSTRING_TEXTUAL | |
287 | 295 | * |
288 | 296 | * @return string representation of an Compound |
289 | 297 | */ |
290 | 298 | public String toString() { |
291 | return JPL.quotedName(name) + (args.length > 0 ? "(" + Term.toString(args) + ")" : ""); | |
292 | } | |
299 | if (isListPair() && JPL.LIST_TOSTRING_TEXTUAL) { // output nice Prolog [.,.,.,.,] format, not prefix format | |
300 | String head_str = arg(1).toString(); // must be at least 1 arg in compound | |
301 | String tail_str; | |
302 | if (arg(2).isListNil()) { | |
303 | return String.format("[%s]", head_str); | |
304 | } else { | |
305 | tail_str = arg(2).toString(); | |
306 | StringBuilder builder = new StringBuilder(tail_str); | |
307 | if (arg(2).isListPair()) { | |
308 | builder.deleteCharAt(builder.length()-1); // remove closing ] | |
309 | builder.deleteCharAt(0); // remove opening [ | |
310 | } | |
311 | return String.format("[%s, %s]", head_str, builder.toString()); | |
312 | } | |
313 | } // just return lists in pre-fix as '[|]'(head, '[|]'(head, '[|]'(head, .....) | |
314 | return JPL.quotedName(name) + | |
315 | (args.length > 0 ? "(" + Term.toString(args) + ")" : ""); | |
316 | } | |
317 | ||
318 | ||
293 | 319 | |
294 | 320 | /** |
295 | 321 | * the type of this term, as jpl.fli.Prolog.COMPOUND |
75 | 75 | public static String LIST_PAIR = LIST_PAIR_MODERN; // default unless/until |
76 | 76 | // setTraditional() is |
77 | 77 | // called successfully |
78 | // whether we want lists to be printed in pre-fix '[|]'(head, tails) or textual [....] format | |
79 | public static boolean LIST_TOSTRING_TEXTUAL = true; | |
78 | 80 | |
79 | 81 | private static String nativeLibraryName = "jpl"; |
80 | 82 | private static String nativeLibraryDir = null; |
165 | 165 | * @throws JPLException if term provided is not of right sort Atom or Compound |
166 | 166 | */ |
167 | 167 | public Query(String text) { |
168 | this(Util.textToTerm(text)); | |
168 | this(Term.textToTerm(text)); | |
169 | 169 | } |
170 | 170 | |
171 | 171 | |
204 | 204 | * the arguments of this Query's goal |
205 | 205 | */ |
206 | 206 | private static Term buildQueryTerm(String text, Term[] args) { |
207 | Term t = Util.textToTerm(text); | |
207 | Term t = Term.textToTerm(text); | |
208 | 208 | if (t instanceof Atom) { |
209 | 209 | return new Compound(text, args); |
210 | 210 | } else { |
435 | 435 | Term exception_term = Term.getTerm(new HashMap<term_t, Variable>(), exception_term_t); |
436 | 436 | close(); |
437 | 437 | throw new PrologException(exception_term); |
438 | } else { | |
438 | } else { // no more solution, close the query | |
439 | 439 | close(); |
440 | 440 | return false; |
441 | 441 | } |
455 | 455 | |
456 | 456 | /** |
457 | 457 | * Used to be used only by Utils.textToTerm but code has been integrated there already |
458 | * @return | |
458 | * @return a substituion from variable names to terms | |
459 | 459 | */ |
460 | 460 | @Deprecated |
461 | 461 | public final Map<String, Term> getSubstWithNameVars() { |
562 | 562 | String BindingVarName = ((Variable) BindingVarTerm).name; // its textual name ("Bindings" in example) |
563 | 563 | |
564 | 564 | Term TermVar = args[args.length - 2]; // the Query's last arg: a variable binding list; type Variable |
565 | String TermVarName = ((Variable) TermVar).name; // its textual name ("Bindings" in example) | |
565 | // String TermVarName = ((Variable) TermVar).name; // its textual name ("Bindings" in example) | |
566 | 566 | |
567 | 567 | // SECOND, we store what B was bound to as JPL Compound list instance BindingVarValue |
568 | 568 | // If B was bound to ['X' = _1, 'Y' = _2] in the current solution |
59 | 59 | * returns the i-th (1+) argument of a Term; |
60 | 60 | * |
61 | 61 | * defined only for Compound |
62 | * | |
62 | * | |
63 | 63 | * @param i the index of argument to return |
64 | 64 | * @return the i-th argument of a (Compound) Term |
65 | 65 | * @throws JPLException if Term is not a Compound |
104 | 104 | throw new JPLException("atomType() is undefined for " + this.typeName()); |
105 | 105 | } |
106 | 106 | |
107 | ||
108 | /** | |
109 | * Converts a Prolog source text to a corresponding JPL Term (in which each Variable has the appropriate name from | |
110 | * the source text). | |
107 | /** | |
108 | * The name of an Atom, Compound or Variable. | |
109 | * | |
110 | * @return the name of an Atom, Compound or Variable. | |
111 | * @throws JPLException | |
112 | * if this Term is not an Atom, Compound or Variable. | |
113 | */ | |
114 | public String name() { // overridden in Atom, Compound, Variable | |
115 | throw new JPLException("name() is undefined for " + this.typeName()); | |
116 | } | |
117 | ||
118 | public void setName(String name) { | |
119 | throw new JPLException("name() is undefined for " + this.typeName()); | |
120 | } | |
121 | ||
122 | /** | |
123 | * Converts a Prolog source text to a corresponding JPL Term | |
124 | * (in which each Variable has the appropriate name from the source text). | |
111 | 125 | * |
112 | 126 | * @param text A Prolog source text denoting a term |
113 | 127 | * @return Term a JPL Term equivalent to the given source text |
130 | 144 | // it might be better to use PL_chars_to_term() |
131 | 145 | Query q = new Query(new Compound("atom_to_term", |
132 | 146 | new Term[] { new Atom(text), new Variable("T"), new Variable("NVdict") })); |
147 | ||
133 | 148 | q.open(); |
134 | ||
135 | // quer is open, check if there is a solution | |
136 | 149 | if (q.hasMoreSolutions()) { |
137 | // cannot use this bc it gives anonymous vars, we lose the names | |
138 | // If we use this we will get T mmapped to Term mother(maria, _1, _2) but we want mother(maria, X, Y) | |
139 | 150 | Map<String, Term> s = q.nextSolution(); |
140 | 151 | |
141 | 152 | // New way of doing it (April 2020) |
147 | 158 | // Since the Term bound to T will use exactl the Variables _1, _2, etc, by changing their names |
148 | 159 | // the term T will now use Variables X, Y, etc as wanted! |
149 | 160 | //Term T = s.get("T"); |
150 | Term[] VarsMapList = Util.listToTermArray(s.get("NVdict")); // this is a Compound list of mappings | |
161 | Term[] VarsMapList = Term.listToTermArray(s.get("NVdict")); // this is a Compound list of mappings | |
151 | 162 | for (Term map : VarsMapList) { // map represents 'X' = _1 |
152 | String VarName = map.arg(1).name(); // extract the symbolic name | |
153 | Variable Var = (Variable) map.arg(2); // extract Variable object | |
154 | Var.setName(VarName); | |
163 | String VarName = map.arg(1).name(); // extract the symbolic name of the variable | |
164 | Variable Var = (Variable) map.arg(2); // extract the Variable object | |
165 | Var.setName(VarName); // set the name of the Variable object to the symbolic name | |
155 | 166 | } |
156 | 167 | |
157 | 168 | // Old way of doing it (before April 2020) - extremely involved! |
158 | 169 | //Map<String, Term> s = q.getSolutionWithVarNames(); |
159 | 170 | |
171 | ||
172 | // We MUST close the query explicitly or otherwise it will remain at the top of stack because we | |
173 | // just did q.nextSolution() and there may be more | |
160 | 174 | q.close(); |
175 | ||
161 | 176 | return (Term) s.get("T"); |
162 | 177 | } else { |
178 | q.close(); // redundant as q.hasMoreSolutions() would have closed it, but .... | |
163 | 179 | return null; |
164 | 180 | } |
165 | 181 | } |
166 | 182 | |
183 | /** | |
184 | * Converts a Prolog source text to a corresponding JPL Term (in which each Variable has the appropriate name from | |
185 | * the source text), replacing successive occurrences of ? in the text by the corresponding element of Term[] | |
186 | * params. (New in JPL 3.0.4) | |
187 | * | |
188 | * Throws PrologException containing error(syntax_error(_),_) if text is invalid. | |
189 | * | |
190 | * @param text A Prolog source text denoting a term | |
191 | * @param params parameters to be injected in each ? | |
192 | * @return Term a JPL Term equivalent to the given source text | |
193 | */ | |
194 | public static Term textParamsToTerm(String text, Term[] params) { | |
195 | return Term.textToTerm(text).putParams(params); | |
196 | } | |
197 | ||
198 | ||
199 | /** | |
200 | * returns the value (as an int) of an Integer or Float | |
201 | * | |
202 | * @return the value (as an int) of an Integer or Float | |
203 | * @throws JPLException | |
204 | * if this Term is a Compound, Atom or Variable | |
205 | */ | |
206 | public int intValue() { | |
207 | throw new JPLException("intValue() is undefined for " + this.typeName()); | |
208 | } | |
209 | ||
210 | /** | |
211 | * The (long) value of a Float or Integer. | |
212 | * | |
213 | * @return the (long) value of a Float or Integer. | |
214 | * @throws JPLException | |
215 | * if this Term is not a Float or Integer. | |
216 | */ | |
217 | public long longValue() { // overridden in Integer, GFloat | |
218 | throw new JPLException("longValue() is undefined for " + this.typeName()); | |
219 | } | |
167 | 220 | |
168 | 221 | /** |
169 | 222 | * the value (as a java.math.BigInteger) of an Integer, whether or not it is big |
198 | 251 | throw new JPLException("floatValue() is undefined for " + this.typeName()); |
199 | 252 | } |
200 | 253 | |
201 | /** | |
202 | * This method computes a substitution from a Term (the current object). | |
203 | * The bindings Map varnames_to_Terms maps names of Variables to Terms. | |
204 | * Thus, a substitution is as it is in mathematical logic, a sequence of the form \sigma = {t_0/x_0, ..., t_n/x_n}. | |
205 | * Once the substitution is computed, the substitution should satisfy | |
206 | * | |
207 | * \sigma T = t | |
208 | * | |
209 | * where T is the Term from which the substitution is computed, and t is the term_t which results from the Prolog | |
210 | * query. | |
211 | * <p> | |
212 | * | |
213 | * A second Map, vars_to_Vars, is required: this table holds the Variables that occur (thus far) in the unified term. | |
214 | * The Variable instances in this table are guaranteed to be unique and are keyed on Strings which are Prolog internal | |
215 | * representations of the variables. | |
216 | * | |
217 | * @param varnames_to_Terms | |
218 | * table holding Term substitutions, keyed on names of Variables. | |
219 | * @param vars_to_Vars | |
220 | * A Map holding the Variables that occur thus far in the term; keyed by internal (Prolog) string rep. | |
221 | */ | |
222 | protected void getSubst(Map<String, Term> varnames_to_Terms, Map<term_t, Variable> vars_to_Vars) { | |
223 | // overridden in Compound, Variable | |
224 | } | |
225 | ||
226 | /** | |
227 | * Just calls computeSubstitution for each Term in the array. | |
228 | * | |
229 | * @param varnames_to_Terms | |
230 | * a Map from variable names to Terms (what each variable string is to be replaced by) | |
231 | * @param vars_to_Vars | |
232 | * a Map from Prolog variables (which may be bounded in the engine) to JPL Variables (which are Java objects) | |
233 | * @param args | |
234 | * an array of Terms to which the substitution is to be applied | |
235 | */ | |
236 | protected static void getSubsts(Map<String, Term> varnames_to_Terms, Map<term_t, Variable> vars_to_Vars, | |
237 | Term[] args) { | |
238 | for (int i = 0; i < args.length; ++i) { | |
239 | args[i].getSubst(varnames_to_Terms, vars_to_Vars); | |
240 | } | |
241 | } | |
242 | 254 | |
243 | 255 | /** |
244 | 256 | * create and return a org.jpl7.Term representation of the given Prolog term |
255 | 267 | Int64Holder hInt64; |
256 | 268 | ObjectHolder hObject; |
257 | 269 | switch (Prolog.term_type(term)) { |
258 | case Prolog.VARIABLE: // 1 | |
259 | for (Iterator<term_t> i = vars_to_Vars.keySet().iterator(); i.hasNext();) { | |
260 | term_t varX = (term_t) i.next(); // a previously seen Prolog | |
261 | // variable | |
262 | if (Prolog.compare(varX, term) == 0) { // identical Prolog | |
263 | // variables? | |
264 | return (Term) vars_to_Vars.get(varX); // return the | |
265 | // associated JPL | |
266 | // Variable | |
270 | case Prolog.VARIABLE: // 1 | |
271 | for (Iterator<term_t> i = vars_to_Vars.keySet().iterator(); i.hasNext();) { | |
272 | term_t varX = (term_t) i.next(); // a previously seen Prolog | |
273 | // variable | |
274 | if (Prolog.compare(varX, term) == 0) { // identical Prolog | |
275 | // variables? | |
276 | return (Term) vars_to_Vars.get(varX); // return the | |
277 | // associated JPL | |
278 | // Variable | |
279 | } | |
267 | 280 | } |
268 | } | |
269 | // otherwise, the Prolog variable in term has not been seen before | |
270 | Variable Var = new Variable(); // allocate a new (sequentially | |
271 | // named) Variable to represent it | |
272 | Var.term_ = term; // this should become redundant... | |
273 | vars_to_Vars.put(term, Var); // use Hashtable(var,null), but only | |
274 | // need set(var) | |
275 | return Var; | |
276 | case Prolog.ATOM: // 2 | |
277 | hString = new StringHolder(); | |
278 | Prolog.get_atom_chars(term, hString); // ignore return val; assume | |
279 | // success... | |
280 | return new Atom(hString.value, "text"); | |
281 | case Prolog.STRING: // 5 | |
282 | hString = new StringHolder(); | |
283 | Prolog.get_string_chars(term, hString); // ignore return val; assume | |
284 | // success... | |
285 | return new Atom(hString.value, "string"); | |
286 | case Prolog.INTEGER: // 3 | |
287 | hInt64 = new Int64Holder(); | |
288 | if (Prolog.get_integer(term, hInt64)) { // assume it fails if Prolog | |
289 | // integer is bigger than a | |
290 | // Java long... | |
291 | return new org.jpl7.Integer(hInt64.value); | |
292 | } else { | |
281 | // otherwise, the Prolog variable in term has not been seen before | |
282 | Variable Var = new Variable(); // allocate a new (sequentially | |
283 | // named) Variable to represent it | |
284 | Var.term_ = term; // this should become redundant... | |
285 | vars_to_Vars.put(term, Var); // use Hashtable(var,null), but only | |
286 | // need set(var) | |
287 | return Var; | |
288 | case Prolog.ATOM: // 2 | |
293 | 289 | hString = new StringHolder(); |
294 | if (Prolog.get_integer_big(term, hString)) { | |
290 | Prolog.get_atom_chars(term, hString); // ignore return val; assume | |
291 | // success... | |
292 | return new Atom(hString.value, "text"); | |
293 | case Prolog.STRING: // 5 | |
294 | hString = new StringHolder(); | |
295 | Prolog.get_string_chars(term, hString); // ignore return val; assume | |
296 | // success... | |
297 | return new Atom(hString.value, "string"); | |
298 | case Prolog.INTEGER: // 3 | |
299 | hInt64 = new Int64Holder(); | |
300 | if (Prolog.get_integer(term, hInt64)) { // assume it fails if Prolog | |
301 | // integer is bigger than a | |
302 | // Java long... | |
303 | return new org.jpl7.Integer(hInt64.value); | |
304 | } else { | |
305 | hString = new StringHolder(); | |
306 | if (Prolog.get_integer_big(term, hString)) { | |
307 | // System.out.println("bigint = " + hString.value); | |
308 | return new org.jpl7.Integer(new java.math.BigInteger(hString.value)); | |
309 | } else { | |
310 | return new org.jpl7.Integer(-3); // arbitrary | |
311 | } | |
312 | } | |
313 | case Prolog.RATIONAL: // 4 | |
314 | hString = new StringHolder(); | |
315 | if (Prolog.get_rational(term, hString)) { | |
295 | 316 | // System.out.println("bigint = " + hString.value); |
296 | return new org.jpl7.Integer(new java.math.BigInteger(hString.value)); | |
317 | return new org.jpl7.Rational(hString.value); | |
297 | 318 | } else { |
298 | 319 | return new org.jpl7.Integer(-3); // arbitrary |
299 | 320 | } |
300 | } | |
301 | case Prolog.RATIONAL: // 4 | |
302 | hString = new StringHolder(); | |
303 | if (Prolog.get_rational(term, hString)) { | |
304 | // System.out.println("bigint = " + hString.value); | |
305 | return new org.jpl7.Rational(hString.value); | |
306 | } else { | |
307 | return new org.jpl7.Integer(-3); // arbitrary | |
308 | } | |
309 | case Prolog.FLOAT: // 5 | |
310 | DoubleHolder hFloatValue = new DoubleHolder(); | |
311 | Prolog.get_float(term, hFloatValue); // assume it succeeds... | |
312 | return new org.jpl7.Float(hFloatValue.value); | |
313 | case Prolog.COMPOUND: // 6 | |
314 | case Prolog.LIST_PAIR: // 9 | |
315 | hString = new StringHolder(); | |
316 | hInt = new IntHolder(); | |
317 | Prolog.get_name_arity(term, hString, hInt); // assume it succeeds | |
318 | Term args[] = new Term[hInt.value]; | |
319 | // term_t term1 = Prolog.new_term_refs(hArity.value); | |
320 | for (int i = 1; i <= hInt.value; i++) { | |
321 | term_t termi = Prolog.new_term_ref(); | |
322 | Prolog.get_arg(i, term, termi); | |
323 | args[i - 1] = Term.getTerm(vars_to_Vars, termi); | |
324 | } | |
325 | return new Compound(hString.value, args); | |
326 | case Prolog.LIST_NIL: // 7 | |
327 | return JPL.LIST_NIL; | |
328 | case Prolog.BLOB: // 8 | |
329 | hObject = new ObjectHolder(); | |
330 | if (Prolog.get_jref_object(term, hObject)) { | |
331 | if (hObject.value == null) { | |
332 | return JPL.JNULL; | |
321 | case Prolog.FLOAT: // 5 | |
322 | DoubleHolder hFloatValue = new DoubleHolder(); | |
323 | Prolog.get_float(term, hFloatValue); // assume it succeeds... | |
324 | return new org.jpl7.Float(hFloatValue.value); | |
325 | case Prolog.COMPOUND: // 6 | |
326 | case Prolog.LIST_PAIR: // 9 | |
327 | hString = new StringHolder(); | |
328 | hInt = new IntHolder(); | |
329 | Prolog.get_name_arity(term, hString, hInt); // assume it succeeds | |
330 | Term args[] = new Term[hInt.value]; | |
331 | // term_t term1 = Prolog.new_term_refs(hArity.value); | |
332 | for (int i = 1; i <= hInt.value; i++) { | |
333 | term_t termi = Prolog.new_term_ref(); | |
334 | Prolog.get_arg(i, term, termi); | |
335 | args[i - 1] = Term.getTerm(vars_to_Vars, termi); | |
336 | } | |
337 | return new Compound(hString.value, args); | |
338 | case Prolog.LIST_NIL: // 7 | |
339 | return JPL.LIST_NIL; | |
340 | case Prolog.BLOB: // 8 | |
341 | hObject = new ObjectHolder(); | |
342 | if (Prolog.get_jref_object(term, hObject)) { | |
343 | if (hObject.value == null) { | |
344 | return JPL.JNULL; | |
345 | } else { | |
346 | return new JRef(hObject.value); | |
347 | } | |
333 | 348 | } else { |
334 | return new JRef(hObject.value); | |
349 | throw new JPLException("unsupported blob type passed from Prolog"); | |
335 | 350 | } |
336 | } else { | |
337 | throw new JPLException("unsupported blob type passed from Prolog"); | |
338 | } | |
339 | default: // should never happen | |
340 | throw new JPLException("unknown term type=" + Prolog.term_type(term)); | |
351 | default: // should never happen | |
352 | throw new JPLException("unknown term type=" + Prolog.term_type(term)); | |
341 | 353 | } |
342 | 354 | } |
343 | 355 | |
357 | 369 | * if this Term is a Variable |
358 | 370 | */ |
359 | 371 | public boolean hasFunctor(String name, int arity) { // overridden in |
360 | // Atom, Compound | |
372 | // Atom, Compound | |
361 | 373 | return false; |
362 | 374 | } |
363 | 375 | |
412 | 424 | return false; |
413 | 425 | } |
414 | 426 | |
415 | /** | |
416 | * returns the value (as an int) of an Integer or Float | |
417 | * | |
418 | * @return the value (as an int) of an Integer or Float | |
419 | * @throws JPLException | |
420 | * if this Term is a Compound, Atom or Variable | |
421 | */ | |
422 | public int intValue() { | |
423 | throw new JPLException("intValue() is undefined for " + this.typeName()); | |
424 | } | |
427 | ||
425 | 428 | |
426 | 429 | /** |
427 | 430 | * whether this Term is an Atom (of any type) |
542 | 545 | return false; |
543 | 546 | } |
544 | 547 | |
545 | /** | |
546 | * Tests whether this Term denotes an empty list within the current syntax ("traditional" or "modern"). | |
547 | * | |
548 | * @return whether this Term denotes an empty list within the current syntax ("traditional" or "modern"). | |
549 | * @see org.jpl7.JPL#getSyntax() | |
550 | */ | |
551 | public boolean isListNil() { // overridden in Atom | |
552 | return false; | |
553 | } | |
554 | ||
555 | /** | |
556 | * Tests whether this Term is a list pair within the current syntax ("traditional" or "modern"). | |
557 | * | |
558 | * @return whether this Term is a list pair within the current syntax ("traditional" or "modern"). | |
559 | */ | |
560 | public boolean isListPair() { // overridden in Compound | |
561 | return false; | |
562 | } | |
563 | ||
564 | ||
565 | /** | |
566 | * Tests whether this Term is a list (empty or list pair) | |
567 | * | |
568 | * @return whether this Term is a list, empty or list pair | |
569 | */ | |
570 | public boolean isList() { // overridden in Compound | |
571 | return (isListNil() || isListPair()); | |
572 | } | |
548 | ||
573 | 549 | |
574 | 550 | /** |
575 | 551 | * Tests whether this Term is a Variable. |
580 | 556 | return this instanceof Variable; |
581 | 557 | } |
582 | 558 | |
583 | /** | |
584 | * @return the Object which this JRef references | |
585 | * @deprecated Use {@link JRef#object()} | |
586 | */ | |
587 | @Deprecated | |
588 | public Object jrefToObject() { // overridden in Compound and JRef | |
589 | throw new JPLException("term is neither a JRef nor a Compound representing @(null)"); | |
590 | } | |
591 | ||
592 | /** | |
593 | * The length of this list, iff it is one, else an exception is thrown. | |
594 | * | |
595 | * @throws JPLException if the term is not a list | |
596 | * @return the length (as an int) of this list, iff it is one. | |
597 | * @deprecated Use {@link Util#listToLength(Term)} | |
598 | */ | |
599 | @Deprecated | |
600 | public final int listLength() { | |
601 | if (this.isListPair()) { // was .hasFunctor(".", 2) | |
602 | return 1 + this.arg(2).listLength(); // TODO eliminate recursion | |
603 | } else if (this.isListNil()) { // was .hasFunctor("[]", 0) | |
604 | return 0; | |
605 | } else { | |
606 | throw new JPLException("term is not a list"); | |
607 | } | |
608 | } | |
609 | ||
610 | /** | |
611 | * The (long) value of a Float or Integer. | |
612 | * | |
613 | * @return the (long) value of a Float or Integer. | |
614 | * @throws JPLException | |
615 | * if this Term is not a Float or Integer. | |
616 | */ | |
617 | public long longValue() { // overridden in Integer, GFloat | |
618 | throw new JPLException("longValue() is undefined for " + this.typeName()); | |
619 | } | |
620 | ||
621 | /** | |
622 | * The name of an Atom, Compound or Variable. | |
623 | * | |
624 | * @return the name of an Atom, Compound or Variable. | |
625 | * @throws JPLException | |
626 | * if this Term is not an Atom, Compound or Variable. | |
627 | */ | |
628 | public String name() { // overridden in Atom, Compound, Variable | |
629 | throw new JPLException("name() is undefined for " + this.typeName()); | |
630 | } | |
631 | ||
632 | public void setName(String name) { | |
633 | throw new JPLException("name() is undefined for " + this.typeName()); | |
634 | } | |
559 | ||
560 | ||
635 | 561 | /** |
636 | 562 | * The Object which this org.jpl7.JRef refers to, iff this Term is a JRef or just JPL.JNULL. |
637 | 563 | * |
640 | 566 | */ |
641 | 567 | public Object object() { // overridden in JRef |
642 | 568 | if (this == JPL.JNULL) |
643 | return null; | |
644 | else | |
645 | throw new JPLException("this term is not a JRef"); | |
646 | } | |
647 | ||
648 | /** | |
649 | * Returns the JREF term for an object | |
650 | * | |
651 | * @param object object of interest | |
569 | return null; | |
570 | else | |
571 | throw new JPLException("this term is not a JRef"); | |
572 | } | |
573 | ||
574 | /** | |
575 | * Returns the JREF term for an object | |
576 | * | |
577 | * @param object object of interest | |
652 | 578 | * @return a new JRef which references object, or @(null) if object == null. |
653 | 579 | * @throws JPLException |
654 | 580 | * if object is a String. |
655 | 581 | * @deprecated Use {@link JPL#newJRef} |
656 | 582 | */ |
657 | @Deprecated | |
583 | @Deprecated | |
658 | 584 | public static final Term objectToJRef(Object object) { |
659 | 585 | if (object == null) { |
660 | 586 | return JPL.JNULL; |
732 | 658 | |
733 | 659 | protected Term putParams1(IntHolder next, Term[] ps) { |
734 | 660 | switch (this.type()) { |
735 | case Prolog.COMPOUND: | |
736 | return new Compound(this.name(), putParams2(this.args(), next, ps)); | |
737 | case Prolog.ATOM: | |
738 | if (!this.name().equals("?")) { | |
661 | case Prolog.COMPOUND: | |
662 | return new Compound(this.name(), putParams2(this.args(), next, ps)); | |
663 | case Prolog.ATOM: | |
664 | if (!this.name().equals("?")) { | |
665 | return this; | |
666 | } else if (next.value >= ps.length) { | |
667 | throw new JPLException("fewer actual params than formal params"); | |
668 | } else { | |
669 | return ps[next.value++]; | |
670 | } | |
671 | default: | |
739 | 672 | return this; |
740 | } else if (next.value >= ps.length) { | |
741 | throw new JPLException("fewer actual params than formal params"); | |
742 | } else { | |
743 | return ps[next.value++]; | |
744 | } | |
745 | default: | |
746 | return this; | |
747 | 673 | } |
748 | 674 | } |
749 | 675 | |
799 | 725 | * if this Term is not a JRef |
800 | 726 | * @deprecated Use {@link JRef#object()} |
801 | 727 | */ |
802 | @Deprecated | |
728 | @Deprecated | |
803 | 729 | public Object ref() { // overridden in JRef |
804 | 730 | throw new JPLException("this Term is not a JRef"); |
805 | 731 | } |
806 | 732 | |
807 | /** | |
808 | * returns an array of Terms whose elements are the respective members of this list, iff it is a list. | |
809 | * | |
810 | * @throws JPLException | |
811 | * if this Term is not a proper list. | |
812 | * @return an array of Terms whose elements are the respective members of this list, iff it is a list. | |
813 | */ | |
814 | public final Term[] toTermArray() { | |
815 | try { | |
816 | int len = Util.listToLength(this); // exception if not a well formed list | |
817 | Term[] ts = new Term[len]; | |
818 | Term t = this; | |
819 | for (int i = 0; i < len; i++) { // no need to check functor (it's a list) | |
820 | ts[i] = t.arg(1); | |
821 | t = t.arg(2); | |
822 | } | |
823 | return ts; | |
824 | } catch (JPLException e) { | |
825 | throw new JPLException("term is not a proper list"); | |
826 | } | |
733 | ||
734 | /** | |
735 | * @return the Object which this JRef references | |
736 | * @deprecated Use {@link JRef#object()} | |
737 | */ | |
738 | @Deprecated | |
739 | public Object jrefToObject() { // overridden in Compound and JRef | |
740 | throw new JPLException("term is neither a JRef nor a Compound representing @(null)"); | |
827 | 741 | } |
828 | 742 | |
829 | 743 | // ==================================================================/ |
840 | 754 | // Variable with which the term was unified. |
841 | 755 | // ==================================================================/ |
842 | 756 | |
757 | ||
758 | /** | |
759 | * This method computes a substitution from a Term (the current object). | |
760 | * The bindings Map varnames_to_Terms maps names of Variables to Terms. | |
761 | * Thus, a substitution is as it is in mathematical logic, a sequence of the form \sigma = {t_0/x_0, ..., t_n/x_n}. | |
762 | * Once the substitution is computed, the substitution should satisfy | |
763 | * | |
764 | * \sigma T = t | |
765 | * | |
766 | * where T is the Term from which the substitution is computed, and t is the term_t which results from the Prolog | |
767 | * query. | |
768 | * <p> | |
769 | * | |
770 | * A second Map, vars_to_Vars, is required: this table holds the Variables that occur (thus far) in the unified term. | |
771 | * The Variable instances in this table are guaranteed to be unique and are keyed on Strings which are Prolog internal | |
772 | * representations of the variables. | |
773 | * | |
774 | * @param varnames_to_Terms | |
775 | * table holding Term substitutions, keyed on names of Variables. | |
776 | * @param vars_to_Vars | |
777 | * A Map holding the Variables that occur thus far in the term; keyed by internal (Prolog) string rep. | |
778 | */ | |
779 | protected void getSubst(Map<String, Term> varnames_to_Terms, Map<term_t, Variable> vars_to_Vars) { | |
780 | // overridden in Compound, Variable | |
781 | } | |
782 | ||
783 | /** | |
784 | * Just calls computeSubstitution for each Term in the array. | |
785 | * | |
786 | * @param varnames_to_Terms | |
787 | * a Map from variable names to Terms (what each variable string is to be replaced by) | |
788 | * @param vars_to_Vars | |
789 | * a Map from Prolog variables (which may be bounded in the engine) to JPL Variables (which are Java objects) | |
790 | * @param args | |
791 | * an array of Terms to which the substitution is to be applied | |
792 | */ | |
793 | protected static void getSubsts(Map<String, Term> varnames_to_Terms, Map<term_t, Variable> vars_to_Vars, | |
794 | Term[] args) { | |
795 | for (int i = 0; i < args.length; ++i) { | |
796 | args[i].getSubst(varnames_to_Terms, vars_to_Vars); | |
797 | } | |
798 | } | |
799 | ||
843 | 800 | /** |
844 | 801 | * This method is used (by Compound.equals) to determine whether two Term arrays are pairwise equal, where two |
845 | 802 | * Terms are equal if they satisfy the equals predicate (defined differently in each Term subclass). |
895 | 852 | */ |
896 | 853 | public abstract String typeName(); |
897 | 854 | |
898 | } | |
855 | ||
856 | ||
857 | ||
858 | ||
859 | // ==================================================================/ | |
860 | // LIST METHODS | |
861 | // | |
862 | // All tools to deal specifically with lists that could be either | |
863 | // empty list JPL.LIST_NIL or Compound terms with functor [|]. | |
864 | // ==================================================================/ | |
865 | ||
866 | /** | |
867 | * Tests whether this Term denotes an empty list within the current syntax ("traditional" or "modern"). | |
868 | * | |
869 | * @return whether this Term denotes an empty list within the current syntax ("traditional" or "modern"). | |
870 | * @see org.jpl7.JPL#getSyntax() | |
871 | */ | |
872 | public boolean isListNil() { // overridden in Atom | |
873 | return false; | |
874 | } | |
875 | ||
876 | /** | |
877 | * Tests whether this Term is a list pair within the current | |
878 | * syntax ("traditional" or "modern"). | |
879 | * | |
880 | * Note that a list pair may not be a list itself and hence isList() will return false | |
881 | * as the second argument many not be a list | |
882 | * | |
883 | * @return whether this Term is a list pair within the current syntax ("traditional" or "modern"). | |
884 | */ | |
885 | public boolean isListPair() { // overridden in Compound | |
886 | return false; | |
887 | } | |
888 | ||
889 | /** | |
890 | * whether the Term represents a proper list | |
891 | * | |
892 | * @return whether the Term represents a proper list | |
893 | */ | |
894 | public final boolean isList() { | |
895 | return isList(this); | |
896 | } | |
897 | ||
898 | /** | |
899 | * whether the Term represents a proper list | |
900 | * | |
901 | * @param term the term to check if it is a list | |
902 | * @return whether the Term represents a proper list | |
903 | */ | |
904 | public static final boolean isList(Term term) { | |
905 | return listLength(term) >= 0; | |
906 | } | |
907 | ||
908 | ||
909 | ||
910 | /** | |
911 | * @param term any Term | |
912 | * @return the length of the proper list which the Term represents, else -1 | |
913 | */ | |
914 | public static int listLength(Term term) { | |
915 | int length = 0; | |
916 | Term head = term; | |
917 | while (head.isListPair()) { | |
918 | length++; | |
919 | head = head.arg(2); | |
920 | } | |
921 | return (head.isListNil() ? length : -1); | |
922 | } | |
923 | ||
924 | /** | |
925 | * @return the length of the proper list which the Term represents, else -1 | |
926 | */ | |
927 | public int listLength() { | |
928 | return Term.listLength(this); | |
929 | } | |
930 | ||
931 | /** | |
932 | * Converts an array of String to a corresponding JPL list of atoms | |
933 | * | |
934 | * @param a An array of String objects | |
935 | * @return Term a JPL list of atoms corresponding to the given String array | |
936 | */ | |
937 | public static Term stringArrayToList(String[] a) { | |
938 | Term list = JPL.LIST_NIL; | |
939 | for (int i = a.length - 1; i >= 0; i--) { | |
940 | list = new Compound(JPL.LIST_PAIR, new Term[] { new Atom(a[i]), list }); | |
941 | } | |
942 | return list; | |
943 | } | |
944 | ||
945 | /** | |
946 | * Converts an array of int to a corresponding JPL list | |
947 | * | |
948 | * @param a | |
949 | * An array of int values | |
950 | * @return Term a JPL list corresponding to the given int array | |
951 | */ | |
952 | public static Term intArrayToList(int[] a) { | |
953 | Term list = JPL.LIST_NIL; // was new Atom("[]"); | |
954 | for (int i = a.length - 1; i >= 0; i--) { | |
955 | list = new Compound(JPL.LIST_PAIR, new Term[] { new org.jpl7.Integer(a[i]), list }); | |
956 | } | |
957 | return list; | |
958 | } | |
959 | ||
960 | /** | |
961 | * Converts an array of arrays of int to a corresponding JPL list of lists | |
962 | * | |
963 | * @param a | |
964 | * An array of arrays of int values | |
965 | * @return Term a JPL list of lists corresponding to the given int array of arrays | |
966 | */ | |
967 | public static Term intArrayArrayToList(int[][] a) { | |
968 | Term list = JPL.LIST_NIL; // was new Atom("[]"); | |
969 | for (int i = a.length - 1; i >= 0; i--) { | |
970 | list = new Compound(JPL.LIST_PAIR, new Term[] { intArrayToList(a[i]), list }); | |
971 | } | |
972 | return list; | |
973 | } | |
974 | ||
975 | ||
976 | /** | |
977 | * Converts an array of Terms to a JPL representation of a Prolog list of terms whose members correspond to the | |
978 | * respective array elements. | |
979 | * | |
980 | * @param terms | |
981 | * An array of Term | |
982 | * @return Term a list of the array elements | |
983 | */ | |
984 | public static Term termArrayToList(Term[] terms) { | |
985 | Term list = JPL.LIST_NIL; // was new Atom("[]") | |
986 | for (int i = terms.length - 1; i >= 0; --i) { | |
987 | list = new Compound(JPL.LIST_PAIR, new Term[] { terms[i], list }); | |
988 | } | |
989 | return list; | |
990 | } | |
991 | ||
992 | ||
993 | /** | |
994 | * Converts a term representing a list of atoms into an array of Strings, each element | |
995 | * in the array being a String for the corresponding atom | |
996 | * e.g., [a, b, 1 | |
997 | * | |
998 | * | |
999 | * @param t a term representing a list of atoms | |
1000 | * @return an array of Strings, each element, null if t is not a list of atoms | |
1001 | */ | |
1002 | public static String[] atomListToStringArray(Term t) { | |
1003 | int n = Term.listLength(t); | |
1004 | String[] a; | |
1005 | if (n < 0) { | |
1006 | return null; | |
1007 | } else { | |
1008 | a = new String[n]; | |
1009 | } | |
1010 | int i = 0; | |
1011 | Term head = t; | |
1012 | while (head.isListPair()) { | |
1013 | Term x = head.arg(1); | |
1014 | if (x.isAtom()) { | |
1015 | a[i++] = x.name(); | |
1016 | } else { | |
1017 | return null; | |
1018 | } | |
1019 | head = head.arg(2); | |
1020 | } | |
1021 | return (head.isListNil() ? a : null); | |
1022 | } | |
1023 | ||
1024 | ||
1025 | ||
1026 | /** | |
1027 | * converts a proper list to an array of terms, else throws an exception | |
1028 | * | |
1029 | * @throws JPLException if the term passed is not itself a Prolog list term | |
1030 | * @return an array of terms whose successive elements are the corresponding members of the list (if it is a list) | |
1031 | */ | |
1032 | public static Term[] listToTermArray(Term t) { | |
1033 | int len = Term.listLength(t); // exception if not a well formed list | |
1034 | if (len < 0) { | |
1035 | throw new JPLException("term is not a proper list"); | |
1036 | } | |
1037 | Term[] ts = new Term[len]; | |
1038 | for (int i = 0; i < len; i++) { // no need to check functor (it's a list) | |
1039 | ts[i] = t.arg(1); | |
1040 | t = t.arg(2); | |
1041 | } | |
1042 | return ts; | |
1043 | } | |
1044 | ||
1045 | /** | |
1046 | * converts a proper list to an array of terms, else throws an exception | |
1047 | * | |
1048 | * @throws JPLException if the term passed is not itself a Prolog list term | |
1049 | * @return an array of terms whose successive elements are the corresponding members of the list (if it is a list) | |
1050 | */ | |
1051 | public final Term[] listToTermArray() { | |
1052 | return Term.listToTermArray(this); | |
1053 | } | |
1054 | ||
1055 | /** | |
1056 | * @deprecated Use org.jpl7.Term.termArrayToList(Term[] terms) | |
1057 | */ | |
1058 | @Deprecated | |
1059 | public final Term[] toTermArray() { | |
1060 | return listToTermArray(); | |
1061 | } | |
1062 | ||
1063 | ||
1064 | }⏎ |
45 | 45 | * @param terms |
46 | 46 | * An array of Term |
47 | 47 | * @return Term a list of the array elements |
48 | */ | |
48 | * @deprecated Use org.jpl7.Term.termArrayToList(Term[] terms) | |
49 | */ | |
50 | @Deprecated | |
49 | 51 | public static Term termArrayToList(Term[] terms) { |
50 | Term list = JPL.LIST_NIL; // was new Atom("[]") | |
51 | for (int i = terms.length - 1; i >= 0; --i) { | |
52 | list = new Compound(JPL.LIST_PAIR, new Term[] { terms[i], list }); | |
53 | } | |
54 | return list; | |
52 | return Term.termArrayToList(terms); | |
55 | 53 | } |
56 | 54 | |
57 | 55 | /** |
61 | 59 | * A Map from variable names to Terms. |
62 | 60 | * @return String A String representation of the variable bindings |
63 | 61 | */ |
64 | public static String toString(Map<String, Term> varnames_to_Terms) { | |
62 | public static String subsToString(Map<String, Term> varnames_to_Terms) { | |
65 | 63 | if (varnames_to_Terms == null) { |
66 | 64 | return "[no solution]"; |
67 | 65 | } else { |
73 | 71 | } |
74 | 72 | return s; |
75 | 73 | } |
74 | } | |
75 | ||
76 | /** | |
77 | * @deprecated Use org.jpl7.Util.subsToString(Map<String, Term>) | |
78 | */ | |
79 | @Deprecated | |
80 | public static String toString(Map<String, Term> varnames_to_Terms) { | |
81 | return subsToString(varnames_to_Terms); | |
76 | 82 | } |
77 | 83 | |
78 | 84 | /** |
93 | 99 | // the cast to Variable is necessary to access the (protected) |
94 | 100 | // .term_ field |
95 | 101 | vars_to_Vars.put(((Variable) nvs.arg(1).arg(2)).term_, new Variable(nvs.arg(1).arg(1).name())); // map |
96 | // the | |
97 | // Prolog | |
98 | // variable | |
99 | // to | |
100 | // a | |
101 | // new, | |
102 | // named | |
103 | // Variable | |
102 | // the | |
103 | // Prolog | |
104 | // variable | |
105 | // to | |
106 | // a | |
107 | // new, | |
108 | // named | |
109 | // Variable | |
104 | 110 | nvs = nvs.arg(2); // advance to next list cell |
105 | 111 | } |
106 | 112 | // maybe oughta check that nvs is [] ? |
107 | 113 | return vars_to_Vars; |
108 | 114 | } catch (java.lang.ClassCastException e) { // nvs is not of the expected |
109 | // structure | |
115 | // structure | |
110 | 116 | return null; |
111 | 117 | } |
112 | 118 | } |
113 | 119 | |
114 | 120 | /** |
115 | * Converts a Prolog source text to a corresponding JPL Term (in which each Variable has the appropriate name from | |
116 | * the source text). | |
117 | * | |
118 | * @param text A Prolog source text denoting a term | |
119 | * @return Term a JPL Term equivalent to the given source text | |
120 | * @throws PrologException containing error(syntax_error(_),_) if text is invalid as a term. | |
121 | 121 | * @deprecated Use org.jpl7.Term.textToTerm(String text) |
122 | 122 | */ |
123 | 123 | @Deprecated |
141 | 141 | } |
142 | 142 | |
143 | 143 | /** |
144 | * Converts an array of String to a corresponding JPL list | |
145 | * | |
146 | * @param a | |
147 | * An array of String objects | |
148 | * @return Term a JPL list corresponding to the given String array | |
149 | */ | |
144 | * @deprecated Use org.jpl7.Term.stringArrayToList(String[] a) | |
145 | */ | |
146 | @Deprecated | |
150 | 147 | public static Term stringArrayToList(String[] a) { |
151 | Term list = JPL.LIST_NIL; | |
152 | for (int i = a.length - 1; i >= 0; i--) { | |
153 | list = new Compound(JPL.LIST_PAIR, new Term[] { new Atom(a[i]), list }); | |
154 | } | |
155 | return list; | |
156 | } | |
157 | ||
158 | /** | |
159 | * Converts an array of int to a corresponding JPL list | |
160 | * | |
161 | * @param a | |
162 | * An array of int values | |
163 | * @return Term a JPL list corresponding to the given int array | |
164 | */ | |
148 | return Term.stringArrayToList(a); | |
149 | } | |
150 | ||
151 | /** | |
152 | * @deprecated Use org.jpl7.Term.intArrayToList(int[] a) | |
153 | */ | |
154 | @Deprecated | |
165 | 155 | public static Term intArrayToList(int[] a) { |
166 | Term list = JPL.LIST_NIL; // was new Atom("[]"); | |
167 | for (int i = a.length - 1; i >= 0; i--) { | |
168 | list = new Compound(JPL.LIST_PAIR, new Term[] { new org.jpl7.Integer(a[i]), list }); | |
169 | } | |
170 | return list; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Converts an array of arrays of int to a corresponding JPL list of lists | |
175 | * | |
176 | * @param a | |
177 | * An array of arrays of int values | |
178 | * @return Term a JPL list of lists corresponding to the given int array of arrays | |
179 | */ | |
156 | return Term.intArrayToList(a); | |
157 | } | |
158 | ||
159 | /** | |
160 | * @deprecated Use org.jpl7.Term.intArrayArrayToList(int[][] a) | |
161 | */ | |
162 | @Deprecated | |
180 | 163 | public static Term intArrayArrayToList(int[][] a) { |
181 | Term list = JPL.LIST_NIL; // was new Atom("[]"); | |
182 | for (int i = a.length - 1; i >= 0; i--) { | |
183 | list = new Compound(JPL.LIST_PAIR, new Term[] { intArrayToList(a[i]), list }); | |
184 | } | |
185 | return list; | |
186 | } | |
187 | ||
188 | /** | |
189 | * whether the Term represents a proper list | |
190 | * | |
191 | * @param term the term to check if it is a list | |
192 | * @return whether the Term represents a proper list | |
193 | */ | |
164 | return Term.intArrayArrayToList(a); | |
165 | } | |
166 | ||
167 | /** | |
168 | * @deprecated Use {@link Term#isList(Term)} | |
169 | */ | |
170 | @Deprecated | |
194 | 171 | public static final boolean isList(Term term) { |
195 | return listToLength(term) >= 0; | |
196 | } | |
172 | return Term.isList(term); | |
173 | } | |
174 | ||
197 | 175 | |
198 | 176 | /** |
199 | 177 | * @param term any Term |
200 | 178 | * @return the length of the proper list which the Term represents, else -1 |
201 | */ | |
179 | * @deprecated Use {@link Term#listLength(Term)} | |
180 | */ | |
181 | @Deprecated | |
202 | 182 | public static int listToLength(Term term) { |
203 | int length = 0; | |
204 | Term head = term; | |
205 | while (head.isListPair()) { | |
206 | length++; | |
207 | head = head.arg(2); | |
208 | } | |
209 | return (head.isListNil() ? length : -1); | |
210 | } | |
211 | ||
212 | /** | |
213 | * converts a proper list to an array of terms, else throws an exception | |
214 | * | |
215 | * @param t a list term | |
216 | * @throws JPLException if the term passed is not itself a Prolog list term | |
217 | * @return an array of terms whose successive elements are the corresponding members of the list (if it is a list) | |
218 | */ | |
183 | return Term.listLength(term); | |
184 | } | |
185 | ||
186 | /** | |
187 | * @deprecated Use {@link Term#listToTermArray(Term)} | |
188 | */ | |
189 | @Deprecated | |
219 | 190 | public static Term[] listToTermArray(Term t) { |
220 | 191 | try { |
221 | int len = Util.listToLength(t); // exception if not a list | |
192 | int len = Term.listLength(t); // exception if not a list | |
222 | 193 | Term[] ts = new Term[len]; |
223 | 194 | for (int i = 0; i < len; i++) { |
224 | 195 | ts[i] = t.arg(1); |
230 | 201 | } |
231 | 202 | } |
232 | 203 | |
204 | /** | |
205 | * @deprecated Use {@link Term#atomListToStringArray(Term)} | |
206 | */ | |
207 | @Deprecated | |
233 | 208 | public static String[] atomListToStringArray(Term t) { |
234 | int n = listToLength(t); | |
209 | int n = Term.listLength(t); | |
235 | 210 | String[] a; |
236 | 211 | if (n < 0) { |
237 | 212 | return null; |
2 | 2 | |
3 | 3 | class Version { |
4 | 4 | public final int major = 7; |
5 | public final int minor = 4; // jref as blob | |
5 | public final int minor = 6; // jref as blob | |
6 | 6 | public final int patch = 0; |
7 | 7 | public final String status = "alpha"; |
8 | 8 | } |
29 | 29 | public static void setUp() { |
30 | 30 | |
31 | 31 | setUpClass(); |
32 | Query.hasSolution(String.format("consult('%s/test_quoted_module.pl')", test_dir)); // only because we call e.g. jpl_pl_syntax/1 below | |
32 | Query.hasSolution(String.format("consult('%s/test_quoted_module.pl')", test_dir)); // .pl file to be used | |
33 | 33 | } |
34 | 34 | |
35 | 35 | |
61 | 61 | name = "existence_error(procedure, '/'(pepe, 1))"; |
62 | 62 | // name = "'/'(pepe, 1)"; |
63 | 63 | name = "'$c_call_prolog'"; |
64 | t = Util.textToTerm(name); | |
64 | t = Term.textToTerm(name); | |
65 | 65 | assertEquals("matching text-term", name, t.toString()); |
66 | 66 | } |
67 | 67 | |
165 | 165 | public void testUtilListToTermArray1() { |
166 | 166 | String goal = "T = [a,b,c]"; |
167 | 167 | Term list = Query.oneSolution(goal).get("T"); |
168 | Term[] array = Util.listToTermArray(list); | |
168 | Term[] array = Term.listToTermArray(list); | |
169 | 169 | assertTrue(array[2].isAtom() && array[2].name().equals("c")); |
170 | 170 | } |
171 | 171 | |
173 | 173 | public void testTermToTermArray1() { |
174 | 174 | String goal = "T = [a,b,c]"; |
175 | 175 | Term list = Query.oneSolution(goal).get("T"); |
176 | Term[] array = list.toTermArray(); | |
176 | Term[] array = list.listToTermArray(); | |
177 | 177 | assertTrue(array[2].isAtom() && array[2].name().equals("c")); |
178 | 178 | } |
179 | 179 | |
182 | 182 | @Test |
183 | 183 | public void testTextToTerm1() { |
184 | 184 | String text = "fred(B,p(A))"; |
185 | Term t = Util.textToTerm(text); | |
185 | Term t = Term.textToTerm(text); | |
186 | 186 | assertTrue("Util.textToTerm() converts \"fred(B,p(A))\" to a corresponding Term", |
187 | 187 | t.hasFunctor("fred", 2) && t.arg(1).isVariable() && t.arg(1).name().equals("B") |
188 | 188 | && t.arg(2).hasFunctor("p", 1) && t.arg(2).arg(1).isVariable() |
195 | 195 | public void testTextToTerm2() { |
196 | 196 | String text1 = "fred(?,2,?)"; |
197 | 197 | String text2 = "[first(x,y),A]"; |
198 | Term plist = Util.textToTerm(text2); | |
199 | Term[] ps = plist.toTermArray(); | |
200 | Term t = Util.textToTerm(text1).putParams(ps); | |
198 | Term plist = Term.textToTerm(text2); | |
199 | Term[] ps = plist.listToTermArray(); | |
200 | Term t = Term.textToTerm(text1).putParams(ps); | |
201 | 201 | assertTrue("fred(?,2,?) .putParams( [first(x,y),A] )", |
202 | 202 | t.hasFunctor("fred", 3) && t.arg(1).hasFunctor("first", 2) && t.arg(1).arg(1).hasFunctor("x", 0) |
203 | 203 | && t.arg(1).arg(2).hasFunctor("y", 0) && t.arg(2).hasFunctor(2, 0) && t.arg(3).isVariable() |
1 | 1 | |
2 | 2 | import org.jpl7.*; |
3 | 3 | import org.jpl7.Integer; |
4 | import org.jpl7.fli.Prolog; | |
5 | import org.junit.Before; | |
6 | 4 | import org.junit.BeforeClass; |
7 | 5 | import org.junit.Rule; |
8 | 6 | import org.junit.Test; |
50 | 48 | /////////////////////////////////////////////////////////////////////////////// |
51 | 49 | |
52 | 50 | |
51 | private static Term[] terms_pair_integers = new Term[]{new Integer(1), new Integer(2)}; | |
52 | private static Term[] terms_integers = new Term[]{new Integer(1), new Integer(2), new Integer(3)}; | |
53 | private static Term[] terms_atoms = new Term[]{new Atom("a"), new Atom("b"), new Atom("c")}; | |
54 | ||
55 | // Several list terms of numbers | |
56 | private static Term list_empty = Term.textToTerm("[]"); | |
57 | private static Term list_unit = Term.textToTerm("[1]"); | |
58 | private static Term list_unit_complex = Term.textToTerm("[[1,2,3]]"); | |
59 | private static Term list_simple = Term.textToTerm("[1,2,3]"); | |
60 | private static Term list_complex = Term.textToTerm("[1, [1,2,3], 3]"); | |
61 | ||
62 | private static Term[] lists_many = new Term[]{list_empty, list_unit, list_unit_complex, list_simple, list_complex}; | |
63 | private static Term[] lists_many_noempty = new Term[]{list_unit, list_unit_complex, list_simple, list_complex}; | |
64 | ||
65 | ||
53 | 66 | |
54 | 67 | /////////////////////////////////////////////////////////////////////////////// |
55 | 68 | // TESTS |
56 | 69 | /////////////////////////////////////////////////////////////////////////////// |
57 | 70 | |
58 | ||
59 | @Test | |
60 | public void testArrayToList1() { | |
61 | Term l2 = Util.termArrayToList( | |
62 | new Term[]{new Atom("a"), new Atom("b"), new Atom("c"), new Atom("d"), new Atom("e")}); | |
63 | Query q9 = new Query(new Compound("append", new Term[]{new Variable("Xs"), new Variable("Ys"), l2})); | |
64 | assertTrue("append(Xs,Ys,[a,b,c,d,e]) has 6 solutions", q9.allSolutions().length == 6); | |
65 | } | |
66 | ||
67 | @Test | |
68 | public void testArrayToList2() { | |
69 | String goal = "append(Xs,Ys,[a,b,c,d,e])"; | |
70 | assertTrue(goal + " has 6 solutions", Query.allSolutions(goal).length == 6); | |
71 | } | |
72 | ||
73 | @Test | |
74 | public void testArrayToList3() { | |
75 | final String[] expectedSolutions = { "a", "b", "c", "d", "e"}; | |
76 | ||
77 | Term l2 = Util.termArrayToList( | |
78 | new Term[] { new Atom("a"), new Atom("b"), new Atom("c"), new Atom("d"), new Atom("e") }); | |
79 | Query query = new Query(new Compound("member", new Term[] { new Variable("X"), l2 })); | |
80 | ||
81 | Map<String, Term>[] sol = query.allSolutions(); | |
82 | for (int i = 0; i < sol.length; i++) { | |
83 | assertEquals(expectedSolutions[i], sol[i].get("X").toString()); | |
84 | } | |
85 | } | |
86 | ||
87 | @Test | |
88 | public void testArrayToList4() { | |
89 | final String[] expectedSolutionsX = { "[]", "[a]", "[a, b]", "[a, b, c]"}; | |
90 | final String[] expectedSolutionsY = { "[a, b, c]", "[b, c]", "[c]", "[]"}; | |
91 | ||
92 | Term l2 = Util.termArrayToList( | |
93 | new Term[] { new Atom("a"), new Atom("b"), new Atom("c") }); | |
94 | Query query = new Query(new Compound("append", new Term[] { new Variable("X"), new Variable("Y"), l2 })); | |
95 | ||
96 | Map<String, Term>[] sol = query.allSolutions(); | |
97 | for (int i = 0; i < sol.length; i++) { | |
98 | ||
99 | String ListX = Arrays.toString(Util.atomListToStringArray(sol[i].get("X"))); | |
100 | String ListY = Arrays.toString(Util.atomListToStringArray(sol[i].get("Y"))); | |
101 | ||
102 | ||
103 | assertEquals("Bad X in append(X, Y, [a, b, c])", expectedSolutionsX[i], ListX); | |
104 | assertEquals("Bad Y in append(X, Y, [a, b, c])", expectedSolutionsY[i], ListY); | |
105 | ||
106 | } | |
107 | } | |
108 | ||
109 | ||
110 | ||
111 | ||
112 | ||
113 | ||
114 | ||
115 | @Test | |
116 | public void testLength1() { | |
117 | Query q5 = new Query(new Compound("length", new Term[]{new Variable("Zs"), new Integer(2)})); | |
118 | Term zs = q5.oneSolution().get("Zs"); | |
119 | assertTrue("length(Zs,2) binds Zs to a list of two distinct variables " + zs.toString(), | |
120 | zs.isListPair() && zs.arg(1).isVariable() && zs.arg(2).isListPair() && zs.arg(2).arg(1).isVariable() | |
121 | && zs.arg(2).arg(2).isListNil() && !zs.arg(1).name().equals(zs.arg(2).arg(1).name())); | |
122 | } | |
123 | 71 | |
124 | 72 | @Test |
125 | 73 | public void testListNil1() { |
133 | 81 | } |
134 | 82 | } |
135 | 83 | |
84 | ||
85 | @Test | |
86 | public void testListNil2() { | |
87 | Term x; | |
88 | ||
89 | x = Query.oneSolution("X = []").get("X"); | |
90 | assertTrue("term should be empty list", x.isListNil()); | |
91 | assertTrue("Util.isList on empty list", Term.isList(x)); | |
92 | assertTrue("term is not a ListPair", !x.isListPair()); | |
93 | ||
94 | x = Query.oneSolution("X = [1, 2, 3]").get("X"); | |
95 | assertTrue("term should NOT be empty list", !x.isListNil()); | |
96 | assertTrue("Util.isList on non-empty list", Term.isList(x)); | |
97 | assertTrue("term is not a ListPair", x.isListPair()); | |
98 | } | |
99 | ||
100 | @Test | |
101 | public void testIsList() { | |
102 | final String[] options = { "[]", "[1]", "[1,2,3]", "[1, [a, b, c], 2]", "[[1,2,3]]"}; | |
103 | ||
104 | Term x; | |
105 | for (String opt : options) { | |
106 | x = Query.oneSolution(String.format("X = %s", opt)).get("X"); | |
107 | assertTrue("term should be empty list - Util", Term.isList(x)); | |
108 | assertTrue("term should be empty list - Util", x.isList()); | |
109 | } | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | @Test | |
115 | public void testIsPairList() { | |
116 | final String[] options = { "[]", "[1]", "[1,2,3]", "[1, [a, b, c], 2]", "[[1,2,3]]"}; | |
117 | ||
118 | Term t; | |
119 | for (Term t2 : lists_many_noempty) { | |
120 | String msg = String.format("term %s should be a pair list", t2.toString()); | |
121 | assertTrue(msg, t2.isListPair()); | |
122 | } | |
123 | ||
124 | t = new Compound(JPL.LIST_PAIR, terms_pair_integers); | |
125 | assertTrue("term is a pair list (even though second arg is not a list)", t.isListPair()); | |
126 | ||
127 | ||
128 | assertTrue("empty list term is not a list pair", !JPL.LIST_NIL.isListPair()); | |
129 | ||
130 | t = new Compound(JPL.LIST_PAIR, terms_integers); | |
131 | assertTrue("term is not a pair list, has more than two arguments", !t.isListPair()); | |
132 | ||
133 | t = new Compound("hello", terms_integers); | |
134 | assertTrue("term is not a pair list, not JPL.PAIR_LIST functor", !t.isListPair()); | |
135 | ||
136 | } | |
137 | ||
138 | @Test | |
139 | public void testIsPairList2() { | |
140 | Term t = new Compound(JPL.LIST_PAIR, | |
141 | new Term[]{new Integer(1), new Integer(2)}); | |
142 | ||
143 | String msg = String.format("term %s should be a pair list", t.toString()); | |
144 | assertTrue(msg, t.isListPair()); | |
145 | ||
146 | assertEquals("[1, 2]", t.toString()); | |
147 | } | |
148 | ||
136 | 149 | @Test |
137 | 150 | public void testListCons1() { |
138 | 151 | Term x = Query.oneSolution("X = [a]").get("X"); |
141 | 154 | } else { |
142 | 155 | assertTrue("list constructor is [|]/2", x.isCompound() && x.name().equals("[|]")); |
143 | 156 | } |
157 | } | |
158 | ||
159 | ||
160 | ||
161 | ||
162 | ||
163 | @Test | |
164 | public void testArrayToList1() { | |
165 | Term l = Term.termArrayToList( | |
166 | new Term[]{new Atom("a"), new Atom("b"), new Atom("c"), | |
167 | new Atom("d"), new Atom("e")}); | |
168 | Query q = new Query(new Compound("append", | |
169 | new Term[]{new Variable("Xs"), new Variable("Ys"), l})); | |
170 | ||
171 | assertTrue("append(Xs,Ys,[a,b,c,d,e]) has 6 solutions", q.allSolutions().length == 6); | |
172 | } | |
173 | ||
174 | ||
175 | @Test | |
176 | public void testArrayToList2() { | |
177 | final String[] expectedSolutions = { "a", "b", "c", "d", "e"}; | |
178 | ||
179 | Term l = Term.termArrayToList( | |
180 | new Term[] { new Atom("a"), new Atom("b"), new Atom("c"), | |
181 | new Atom("d"), new Atom("e") }); | |
182 | Query query = new Query(new Compound("member", | |
183 | new Term[] { new Variable("X"), l })); | |
184 | ||
185 | Map<String, Term>[] sol = query.allSolutions(); | |
186 | for (int i = 0; i < sol.length; i++) { | |
187 | assertEquals(expectedSolutions[i], sol[i].get("X").toString()); | |
188 | } | |
189 | } | |
190 | ||
191 | @Test | |
192 | public void testArrayToList3() { | |
193 | final String[] expectedSolutionsX = { "[]", "[a]", "[a, b]", "[a, b, c]"}; | |
194 | final String[] expectedSolutionsY = { "[a, b, c]", "[b, c]", "[c]", "[]"}; | |
195 | ||
196 | Term l = Term.termArrayToList( | |
197 | new Term[] { new Atom("a"), new Atom("b"), new Atom("c") }); | |
198 | Query q = new Query(new Compound("append", // append(X, Y, [a, b, c]) | |
199 | new Term[] { new Variable("X"), new Variable("Y"), l })); | |
200 | ||
201 | Map<String, Term>[] sol = q.allSolutions(); | |
202 | for (int i = 0; i < sol.length; i++) { | |
203 | ||
204 | String ListX = Arrays.toString(Term.atomListToStringArray(sol[i].get("X"))); | |
205 | String ListY = Arrays.toString(Term.atomListToStringArray(sol[i].get("Y"))); | |
206 | ||
207 | ||
208 | assertEquals("Bad X in append(X, Y, [a, b, c])", expectedSolutionsX[i], ListX); | |
209 | assertEquals("Bad Y in append(X, Y, [a, b, c])", expectedSolutionsY[i], ListY); | |
210 | ||
211 | } | |
212 | } | |
213 | ||
214 | ||
215 | @Test | |
216 | public void testStringToList() { | |
217 | String goal = "append(Xs,Ys,[a,b,c,d,e])"; | |
218 | assertTrue(goal + " has 6 solutions", Query.allSolutions(goal).length == 6); | |
219 | } | |
220 | ||
221 | ||
222 | ||
223 | ||
224 | ||
225 | @Test | |
226 | public void testLength1() { | |
227 | Query q5 = new Query(new Compound("length", new Term[]{new Variable("Zs"), new Integer(2)})); | |
228 | Term zs = q5.oneSolution().get("Zs"); | |
229 | assertTrue("length(Zs,2) binds Zs to a list of two distinct variables " + zs.toString(), | |
230 | zs.isListPair() && zs.arg(1).isVariable() && | |
231 | zs.arg(2).isListPair() && zs.arg(2).arg(1).isVariable() | |
232 | && zs.arg(2).arg(2).isListNil() && | |
233 | !zs.arg(1).name().equals(zs.arg(2).arg(1).name())); | |
144 | 234 | } |
145 | 235 | |
146 | 236 | @Test |
187 | 277 | // } |
188 | 278 | |
189 | 279 | |
280 | @Test | |
281 | public void test_textToTerm_and_toString() { | |
282 | final String[] options = { "[]", "[1,2,3]", "[1]", "[1,g(2,3,5),[1,2,3],abc,[1],a,[],b]", "[[1,2,3]]" }; | |
283 | final String[] options2 = { "[]", "[1, 2, 3]", "[1]", "[1, g(2, 3, 5), [1, 2, 3], abc, [1], a, [], b]", "[[1, 2, 3]]" }; | |
284 | ||
285 | Term t; | |
286 | Term s; | |
287 | String msg; | |
288 | String opt, opt2; | |
289 | for (int i = 0; i < options.length; i++) { | |
290 | opt = options[i]; | |
291 | msg = String.format("test Term.textToTerm on: %s", opt); | |
292 | ||
293 | t = Term.textToTerm(opt); | |
294 | s = Query.oneSolution(String.format("X = %s", opt)).get("X"); | |
295 | assertTrue(msg, t.isList()); | |
296 | assertEquals(t, s); | |
297 | ||
298 | opt2 = options2[i]; | |
299 | msg = String.format("test Term.toString() on: %s", opt); | |
300 | assertEquals(msg, opt2, s.toString()); | |
301 | ||
302 | } | |
303 | } | |
304 | ||
305 | ||
190 | 306 | } |
54 | 54 | |
55 | 55 | @Test |
56 | 56 | public void testTerm1() { |
57 | Term args = Util.textToTerm("[1,2,3,4,5]"); | |
57 | Term args = Term.textToTerm("[1,2,3,4,5]"); | |
58 | 58 | Term t = new Compound("member", new Term[] { new Integer(1), args } ); |
59 | 59 | Query q = new Query(t); |
60 | 60 | assertTrue("Query should have succeded, but it did not!", q.hasSolution()); |
98 | 98 | |
99 | 99 | @Test |
100 | 100 | public void testString3() { |
101 | Term[] args = new Term[] { new Integer(1), Util.textToTerm("[1,2,3,4,5]") }; | |
101 | Term[] args = new Term[] { new Integer(1), Term.textToTerm("[1,2,3,4,5]") }; | |
102 | 102 | |
103 | 103 | Query q = new Query("member(?, ?)", args); |
104 | 104 | assertTrue("Query should have succeded, but it did not!", q.hasSolution()); |
106 | 106 | |
107 | 107 | @Test |
108 | 108 | public void testString4() { |
109 | Term[] args = new Term[] { new Integer(1), Util.textToTerm("[1,2,3,4,5]") }; | |
109 | Term[] args = new Term[] { new Integer(1), Term.textToTerm("[1,2,3,4,5]") }; | |
110 | 110 | |
111 | 111 | Query q = new Query("member", args); |
112 | 112 | assertTrue("Query should have succeded, but it did not!", q.hasSolution()); |
153 | 153 | // Error in number of placeholder matching arguments (too many terms) |
154 | 154 | @Test |
155 | 155 | public void testStringErr3() { |
156 | Term[] args = new Term[] { new Integer(1), Util.textToTerm("[1,2,3,4,5]") }; | |
156 | Term[] args = new Term[] { new Integer(1), Term.textToTerm("[1,2,3,4,5]") }; | |
157 | 157 | |
158 | 158 | try { |
159 | 159 | Query q = new Query("member(?, ?, ?)", args); |
169 | 169 | // Error in number of placeholder matching arguments (too many terms) |
170 | 170 | @Test |
171 | 171 | public void testStringErr4() { |
172 | Term[] args = new Term[] { new Integer(1), Util.textToTerm("[1,2,3,4,5]") }; | |
172 | Term[] args = new Term[] { new Integer(1), Term.textToTerm("[1,2,3,4,5]") }; | |
173 | 173 | |
174 | 174 | try { |
175 | 175 | Query q = new Query("member(?)", args); |
528 | 528 | |
529 | 529 | list_clauses([]). |
530 | 530 | list_clauses([H|T]) :- |
531 | portray_clause(H), | |
531 | ( system_undefined(H) | |
532 | -> true | |
533 | ; portray_clause(H) | |
534 | ), | |
532 | 535 | list_clauses(T). |
536 | ||
537 | system_undefined((undefined :- tnot(undefined))). | |
538 | system_undefined((answer_count_restraint :- tnot(answer_count_restraint))). | |
539 | system_undefined((radial_restraint :- tnot(radial_restraint))). | |
533 | 540 | |
534 | 541 | dict_bindings(Dict, Bindings) :- |
535 | 542 | dict_pairs(Dict, _Tag, Pairs), |
69 | 69 | * [[rdf_retractall/3]] |
70 | 70 | * [[rdf_retractall/4]] |
71 | 71 | * [[rdf_update/4]] |
72 | * [[rdf_update/5]] | |
73 | 72 | |
74 | 73 | ## Update view, transactions and snapshots {#semweb-update-view} |
75 | 74 |
363 | 363 | %! rdf_update(+S, +P, +O, ++Action) is det. |
364 | 364 | %! rdf_update(+S, +P, +O, +G, ++Action) is det. |
365 | 365 | % |
366 | % Replaces one of the three fields on the matching triples | |
366 | % Replaces one of the three (four) fields on the matching triples | |
367 | 367 | % depending on Action: |
368 | 368 | % |
369 | 369 | % * subject(Resource) |
375 | 375 | % literal(Value). |
376 | 376 | % * graph(Graph) |
377 | 377 | % Moves the triple from its current named graph to Graph. |
378 | % This only works with rdf_update/4 and will throw an error when | |
379 | % used with rdf_update/3. | |
380 | % | |
381 | % The argument matching the action must be ground. If this | |
382 | % argument is equivalent to the current value, no action is | |
383 | % performed. Otherwise, the requested action is performed on all | |
384 | % matching triples. For example, all resources typed `rdfs:Class` | |
385 | % can be changed to `owl:Class` using | |
378 | % This only works with rdf_update/5 and throws an error when | |
379 | % used with rdf_update/4. | |
380 | % | |
381 | % The argument matching Action must be ground. If this argument is | |
382 | % equivalent to the current value, no action is performed. Otherwise, | |
383 | % the requested action is performed on all matching triples. For | |
384 | % example, all resources typed `rdfs:Class` can be changed to | |
385 | % `owl:Class` using | |
386 | 386 | % |
387 | 387 | % ``` |
388 | 388 | % ?- rdf_update(_, rdf:type, rdfs:'Class', |
566 | 566 | % useful to remove all triples coming from a loaded file. See also |
567 | 567 | % rdf_unload/1. |
568 | 568 | |
569 | %! rdf_update(+Subject, +Predicate, +Object, +Action) is det. | |
570 | % | |
571 | % Replaces one of the three fields on the matching triples | |
569 | %! rdf_update(+Subject, +Predicate, +Object, ++Action) is det. | |
570 | %! rdf_update(+Subject, +Predicate, +Object, +Graph, ++Action) is det | |
571 | % | |
572 | % Replaces one of the three (four) fields on the matching triples | |
572 | 573 | % depending on Action: |
573 | 574 | % |
574 | 575 | % * subject(Resource) |
580 | 581 | % literal(Value). |
581 | 582 | % * graph(Graph) |
582 | 583 | % Moves the triple from its current named graph to Graph. |
583 | ||
584 | %! rdf_update(+Subject, +Predicate, +Object, +Graph, +Action) is det | |
585 | % | |
586 | % As rdf_update/4 but allows for specifying the graph. | |
584 | % This only works with rdf_update/5 and throws an error when | |
585 | % used with rdf_update/4. | |
587 | 586 | |
588 | 587 | |
589 | 588 | /******************************* |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2000-2015, University of Amsterdam | |
5 | Copyright (c) 2000-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | CWI, Amsterdam | |
7 | 8 | All rights reserved. |
8 | 9 | |
9 | 10 | Redistribution and use in source and binary forms, with or without |
2726 | 2727 | validate_completeness(dtd_parser *p, sgml_environment *env) |
2727 | 2728 | { if ( !complete(env) ) |
2728 | 2729 | { wchar_t buf[MAXNMLEN+50]; |
2729 | ||
2730 | swprintf(buf, MAXNMLEN+50, L"Incomplete element: <%s>", | |
2730 | buf[MAXNMLEN+49] = 0; | |
2731 | swprintf(buf, MAXNMLEN+49, L"Incomplete element: <%s>", | |
2731 | 2732 | env->element->name->name); |
2732 | 2733 | |
2733 | 2734 | gripe(p, ERC_VALIDATE, buf); /* TBD: expected */ |
5480 | 5481 | static wchar_t * |
5481 | 5482 | format_location(wchar_t *s, size_t len, dtd_srcloc *l) |
5482 | 5483 | { int first = TRUE; |
5483 | wchar_t *e = &s[len]; | |
5484 | ||
5484 | wchar_t *e = &s[len-1]; | |
5485 | ||
5486 | assert(len > 0); | |
5485 | 5487 | if ( !l || l->type == IN_NONE || len == 0 ) |
5486 | 5488 | return s; |
5487 | 5489 | |
5488 | e[-1] = L'\0'; | |
5490 | *e = L'\0'; | |
5489 | 5491 | for( ; l && l->type != IN_NONE; |
5490 | 5492 | l = l->parent, first = FALSE ) |
5491 | 5493 | { if ( !first ) |
5586 | 5588 | int dtdmode = FALSE; |
5587 | 5589 | void *freeme = NULL; |
5588 | 5590 | |
5591 | buf[MAX_MESSAGE_LEN] = 0; | |
5589 | 5592 | va_start(args, e); |
5590 | 5593 | |
5591 | 5594 | memset(&error, 0, sizeof(error)); |
50 | 50 | /** get configured values, with reasonable defaults |
51 | 51 | */ |
52 | 52 | Preferences::Preferences(QObject *parent) : |
53 | QSettings("SWI-Prolog", "pqConsole", parent) | |
53 | QSettings("swi-prolog", "pqConsole", parent) | |
54 | 54 | { qDebug() << "Loading preferences from " << fileName(); |
55 | 55 | |
56 | console_font = value("console_font", QFont("courier", 12)).value<QFont>(); | |
56 | QFont default_font("Monospace"); | |
57 | default_font.setStyleHint(QFont::Monospace); | |
58 | console_font = value("console_font", default_font).value<QFont>(); | |
57 | 59 | wrapMode = static_cast<ConsoleEditBase::LineWrapMode>(value("wrapMode", ConsoleEditBase::WidgetWidth).toInt()); |
58 | 60 | |
59 | 61 | console_out_fore = value("console_out_fore", 0).toInt(); |
75 | 75 | ! to use tabs (@on). PceEmacs detects body_indentation and |
76 | 76 | ! indent_tabs from the first clause when editing an existing file. |
77 | 77 | |
78 | !emacs_prolog_mode.body_indentation: 4 | |
79 | !emacs_prolog_mode.cond_indentation: 4 | |
80 | !emacs_prolog_mode.indent_tabs: @off | |
78 | !emacs_prolog_mode.body_indentation: 4 | |
79 | !emacs_prolog_mode.cond_indentation: 4 | |
80 | !emacs_prolog_mode.indent_tabs: @off | |
81 | ||
82 | ! How to add a new set of dependencies for ->update_dependencies | |
83 | ! (^c^d). Possible values are autoload/1, autoload/2, use_module/1 | |
84 | ! and use_module/2. | |
85 | ||
86 | !emacs_prolog_mode.dependency_directive: autoload/2 | |
81 | 87 | |
82 | 88 | ! Comment column for M-; This may be refined by mode (e.g. emacs_prolog_mode, |
83 | 89 | ! etc.) |
0 | XPCE: a portable GUI toolkit | |
1 | ============================ | |
2 | ||
3 | Author: | |
4 | ======= | |
5 | ||
6 | Jan Wielemaker jan@swi.psy.uva.nl | |
7 | Anjo Anjewierden anjo@swi.psy.uva.nl | |
8 | SWI, | |
9 | University of Amsterdam | |
10 | Roetersstraat 15 | |
11 | 1018 WB Amsterdam | |
12 | The Netherlands | |
13 | http://www.swi.psy.uva.nl | |
14 | ||
15 | URL: | |
16 | ==== | |
17 | ||
18 | xpce-bugs@swi.psy.uva.nl Bug reports | |
19 | xpce-request@swi.psy.uva.nl General info and mailing list | |
20 | xpce@swi.psy.uva.nl Mailing list | |
21 | http://swi-prolog.org/packages/xpce Project Home Page | |
22 | ftp://swi.psy.uva.nl/xpce Various public resources | |
23 | ||
24 | OS Platforms: | |
25 | ============= | |
26 | ||
27 | Unix/X11 (most brands, including 64-bit platforms) | |
28 | Win32 (Windows 95/98/ME, NT/2000/XP, Intel) | |
29 | ||
30 | Hosting languages | |
31 | ================= | |
32 | ||
33 | SWI-Prolog http://www.swi-prolog.org | |
34 | ||
35 | Ports to the following have existed and are in not too bad | |
36 | shape. | |
37 | ||
38 | Quintus Prolog http://www.sics.se/quintus/ | |
39 | SICStus Prolog http://www.sics.se/ | |
40 | ||
41 | Considering the costs of maintaining portable Prolog | |
42 | code given the current status of the standard, we will only | |
43 | produce versions for other Prolog systems if this situation | |
44 | improves or we get hold of sufficient resources to maintain | |
45 | portability. | |
46 | ||
47 | Documentation | |
48 | ============= | |
49 | ||
50 | # Programming in XPCE/Prolog | |
51 | Userguide to get you started. Explains the interface, object | |
52 | model as well as creating new classes. Provides `technique' | |
53 | sections, explaining how commonly encountered problems may | |
54 | be solved using XPCE. | |
55 | ||
56 | # Course Notes | |
57 | Document explaining roughly the same material as ``Programming | |
58 | in XPCE/Prolog'' in a condensed form. | |
59 | ||
60 | # Reference Manual | |
61 | Available using the built-in online help-system. Includes | |
62 | various fully dynamic viewpoints to the reference material. | |
63 | ||
64 | ||
65 | Licenses | |
66 | ======== | |
67 | ||
68 | * XPCE is distributed as free software with sufficient escapes | |
69 | to generate non-free applications. The license conditions are | |
70 | in the source-files. An overall discussion on the license | |
71 | issues can be found with SWI-Prolog, which is distributed under | |
72 | exactly these conditions. For details, see: | |
73 | ||
74 | http://www.swi-prolog.org/license.html |
0 | # Installing XPCE/Prolog from source | |
1 | ||
2 | Normally, xpce is provided as `packages/xpce` in the SWI-Prolog sources. | |
3 | It is build as part of SWI-Prolog. See | |
4 | http://www.swi-prolog.org/build/index.txt for building SWI-Prolog and | |
5 | xpce. | |
6 | ||
7 | The documentation below is in part out of date, but left as a reference. | |
8 | Configuration, compilation and installation is based on the GNU autoconf | |
9 | package. | |
10 | ||
11 | ## Required tools | |
12 | ||
13 | - GNU-Make | |
14 | Non-gnu versions of make will fail. | |
15 | ||
16 | - GCC or clang | |
17 | Necessary on most machines, though you might get away with | |
18 | another ANSI C compiler. | |
19 | ||
20 | - libXpm | |
21 | The X11 XPM (XPixMap) format libary for handling coloured and | |
22 | masked images. For any popular Unix platform you should be | |
23 | able to find this package. For the Windows built we provide | |
24 | a port at https://github.com/SWI-Prolog/libXpm.git | |
25 | ||
26 | - libjpeg | |
27 | The JPEG group library for handling JPEG images. | |
28 | ||
29 | - Freetype | |
30 | Not really required, but if present the system will use the | |
31 | Freetype library to realise scalable and antialiased fonts. | |
32 | Its presence is detected by looking for the program xft-config, | |
33 | which is also used to determine compile and link flags. If | |
34 | you want to build WITHOUT XFT and you have the library installed, | |
35 | set the environment variable XFTCONFIG=false. | |
36 | ||
37 | ||
38 | For all other required tools, both the GNU, BSD and System-V versions | |
39 | are supposed to work properly. | |
40 | ||
41 | ## Bluffers Installation Guide | |
42 | ||
43 | To install XPCE/SWI-Prolog from the sources: | |
44 | ||
45 | 1. Build SWI-Prolog according to the instructions and install it. | |
46 | 2. Determine an installation prefix (normally use the same as for | |
47 | SWI-Prolog, we use `linux' in this example). | |
48 | 3. Run the following commands | |
49 | ||
50 | % mkdir linux | |
51 | % cd linux | |
52 | % ../src/configure | |
53 | % make | |
54 | % make install | |
55 | ||
56 | # Detailed Installation Guide | |
57 | ||
58 | We start at the SWI-Prolog installation, as this needs some special | |
59 | considerations on some platforms. | |
60 | ||
61 | ||
62 | ## Choosing the build-directory | |
63 | ||
64 | You can place the directory for building XPCE/Prolog anywhere. A good | |
65 | choice is /usr/local/src or, if you are installing as a private user, | |
66 | $HOME/src. Unpack the Prolog and XPCE archives from the same directory: | |
67 | ||
68 | % gunzip < pl-<version>.tar.gz | tar xvfB - | |
69 | % gunzip < xpce-<version>.tar.gz | tar xvfB - | |
70 | ||
71 | NOTES: | |
72 | ||
73 | - Some versions of tar hate reading from a pipe. In that case | |
74 | use `gunzip file.tar.gz' followed by `tar xvf file.tar' to extract | |
75 | the archives | |
76 | ||
77 | - If you are using GNU-tar, `tar zxvf file.tar.gz' is easier. | |
78 | ||
79 | ||
80 | ## Choosing a build sub-directory | |
81 | ||
82 | For easy cleanup or building for multiple directories, both SWI-Prolog | |
83 | and XPCE are normally built in a directory next to the src directory. | |
84 | The name is not important. Good examples are `sunos' `linux', etc. In | |
85 | the examples below, we use `linux'. | |
86 | ||
87 | ||
88 | ## The Destination Prefix (configure --prefix=dir) | |
89 | ||
90 | GNU autoconf-based packages accept the flag --prefix=<dir> to specify | |
91 | the destination. The installation will use the following subdirectories: | |
92 | ||
93 | ``` | |
94 | bin For making *links* to the executables | |
95 | man/man1 For installing the manual pages | |
96 | include For installing the SWI-Prolog.h header file | |
97 | lib/pl-<version> For installing libs, executables, etc. | |
98 | lib For installing public shared objects (if any) | |
99 | ``` | |
100 | ||
101 | The default prefix is /usr/local. If you choose another one (assume | |
102 | /home/projects/bigmoney), do (if the directory structure is not yet | |
103 | available): | |
104 | ||
105 | % cd /home/projects/bigmoney | |
106 | % mkdir bin man man/man1 include lib | |
107 | ||
108 | Make sure the binary directory is in your PATH! | |
109 | ||
110 | ## Preparing SWI-Prolog | |
111 | ||
112 | % cd pl-<version> | |
113 | % mkdir linux | |
114 | % cd linux | |
115 | % ../src/configure | |
116 | ||
117 | ## Shared libraries or not? | |
118 | ||
119 | By default, the installation atempts to build SWI-Prolog and load xpce | |
120 | as a shared object (.so file on most Unix machines) into Prolog. This | |
121 | installation is better to maintain and prepares SWI-Prolog for loading | |
122 | custom extensions written in C in a well supported manner. | |
123 | ||
124 | Now, shared libraries are used on all systems and the the static | |
125 | alternative is no longer actively maintained. When porting to a new OS, | |
126 | please check the shared library facilities of the SWI-Prolog plld tool | |
127 | and make sure it runs on your environment. | |
128 | ||
129 | ## Preparing XPCE | |
130 | ||
131 | XPCE extracts most information about the configuration from SWI-Prolog, | |
132 | so it is generally much easier. Most of the configure run is simple, but | |
133 | configure needs to find out where the X11 libraries and include files | |
134 | are and you may have multiple. Normally, it will first try | |
135 | /usr/include/X11 and /usr/lib. If you have only one version of X11 | |
136 | around, generally configure will be able to find it. | |
137 | ||
138 | If you have multiple copies of X11 around, you have to decide which to | |
139 | use. If you are compiling for local usage, use the one most of your | |
140 | local packages use to improve resource sharing. Otherwise, use the one | |
141 | distributed with the OS or known to be most commonly in use by your user | |
142 | community. For example, our system has the MIT X11R6 libs and includes | |
143 | in /usr/lib and /usr/include/X11 and the OpenWindows versions in | |
144 | /usr/openwin/lib and /usr/openwin/include/X11. For local usage, we | |
145 | configure without options to use the X11R6 version, used by most of the | |
146 | other X11 software we run locally. For distribution, we configure using: | |
147 | ||
148 | --x-includes=/usr/openwin/include --x-libraries=/usr/openwin/lib | |
149 | ||
150 | ## Checking Program versions | |
151 | ||
152 | Just to make sure your programs are accessible and of the right version, | |
153 | try: | |
154 | ||
155 | % swipl -v | |
156 | SWI-Prolog version 5.3.9 for i686-linux | |
157 | % make -v | |
158 | GNU Make 3.80 | |
159 | ... | |
160 | % gcc -v | |
161 | gcc -v | |
162 | Reading specs from /usr/lib/gcc-lib/i586-suse-linux/3.3.1/specs | |
163 | ... | |
164 | gcc version 3.3.1 (SuSE Linux) | |
165 | ||
166 | Now, run configure: | |
167 | ||
168 | % cd xpce-<version> | |
169 | % mkdir linux | |
170 | % ../src/configure <options> | |
171 | ||
172 | ## Building the library | |
173 | ||
174 | Now, make the XPCE library: | |
175 | ||
176 | % make xpce | |
177 | ||
178 | If you have configured for using shared libraries, the -fPIC flag should | |
179 | be passed to the compiler. If this is not the case, please look closely | |
180 | at the steps above. If all goes well, the compilation should finish with | |
181 | few warnings, resulting in the library libXPCE.a | |
182 | ||
183 | ||
184 | ## Building the interface: | |
185 | ||
186 | With write premission to the Prolog home directory, now do the following | |
187 | to make the interface. | |
188 | ||
189 | % make pl-itf | |
190 | ||
191 | This command will run either `make pl-shared' or `make pl-static', | |
192 | depending on whether SWI-Prolog handles shared objects. The first builds | |
193 | the pl2xpce.so shared object, and the second builds an XPCE executable | |
194 | holding both the Prolog kernel and the XPCE library called `xpce'. | |
195 | ||
196 | Both versions will put various things in the SWI-Prolog home directory | |
197 | to make XPCE known to Prolog: | |
198 | ||
199 | * A link to the xpce build-directory | |
200 | * A swipl.rc script to register the xpce library | |
201 | * A Makefile to recompile the XPCE/Prolog quick-load-files | |
202 | ||
203 | ## Testing XPCE | |
204 | ||
205 | Now, if you have build for a shared object, xpce is a dynamically | |
206 | loadable Prolog library, so to test it simply do: | |
207 | ||
208 | % swipl | |
209 | ?- manpce. | |
210 | ||
211 | which should start the manual tools. | |
212 | ||
213 | ## Installing the XPCE library | |
214 | ||
215 | Finally, to install the XPCE libraries, do: | |
216 | ||
217 | % make install | |
218 | ||
219 | Which will: | |
220 | ||
221 | - Create a directory xpce-<version> in the Prolog home and | |
222 | copy the Prolog libraries, manual data and other resources | |
223 | into this directory. | |
224 | ||
225 | - In the Prolog home, make a link from xpce to xpce-<version> | |
226 | ||
227 | - run `make' in the Prolog home directory to make quick-load | |
228 | versions of some large and frequently used library packages. | |
229 | ||
230 | - in $exec_prefix/bin, make links to the xpce and xpce-client | |
231 | executables |
192 | 192 | javascript_mode.pl language_mode.pl latex_mode.pl logtalk_mode.pl |
193 | 193 | man_mode.pl outline_mode.pl prolog_mode.pl prompt.pl rdf_mode.pl |
194 | 194 | script_mode.pl server.pl sgml_mode.pl shell.pl swi_prolog.pl |
195 | text_mode.pl turtle_mode.pl window.pl yaml_mode.pl cmake_mode.pl) | |
195 | text_mode.pl turtle_mode.pl window.pl yaml_mode.pl cmake_mode.pl | |
196 | help_buffer.pl) | |
196 | 197 | |
197 | 198 | set(XPCE_DATA_prolog_lib_english pce_messages.pl) |
198 | 199 | |
385 | 386 | set(XPCE_QLF_emacs emacs/window.pl emacs/buffer.pl emacs/application.pl |
386 | 387 | emacs/buffer_menu.pl emacs/server.pl emacs/history.pl |
387 | 388 | emacs/fundamental_mode.pl emacs/language_mode.pl emacs/outline_mode.pl |
388 | emacs/bookmarks.pl) | |
389 | emacs/bookmarks.pl emacs/help_buffer.pl) |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
Binary diff not shown
0 | #!/bin/sh | |
1 | ||
2 | function confirm () | |
3 | { while true; do | |
4 | echo -n "$1 " | |
5 | read answer | |
6 | case "$answer" in | |
7 | y*) return 0 | |
8 | ;; | |
9 | n*) return 1 | |
10 | ;; | |
11 | *) | |
12 | echo "Please answer yes or no" | |
13 | ;; | |
14 | esac | |
15 | done | |
16 | } | |
17 | ||
18 | version=`cat VERSION` | |
19 | versiondate=`date +"%B %Y"` | |
20 | major=`echo $version | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/'` | |
21 | minor=`echo $version | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/'` | |
22 | patch=`echo $version | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/'` | |
23 | ||
24 | tmp=.tmp$$ | |
25 | ||
26 | f=src/Makefile.in | |
27 | sed "s/^PCEVERSIONDATE=.*/PCEVERSIONDATE=$versiondate/" $f > $tmp | |
28 | if cmp $f $tmp; then | |
29 | rm -f $tmp | |
30 | else | |
31 | cp $tmp $f | |
32 | echo "Updated PCEVERSIONDATE in $f" | |
33 | fi | |
34 | ||
35 | f=src/h/interface.h | |
36 | sed "s/^#define PCE_VERSION.*/#define PCE_VERSION "\""$version, $versiondate"\"/ $f > $tmp | |
37 | if cmp $f $tmp; then | |
38 | rm -f $tmp | |
39 | else | |
40 | cp $tmp $f | |
41 | echo "Updated #define PCE_VERSION in $f" | |
42 | fi | |
43 | ||
44 | rm -f $tmp |
2 | 2 | Author: Jan Wielemaker and Anjo Anjewierden |
3 | 3 | E-mail: jan@swi.psy.uva.nl |
4 | 4 | WWW: http://www.swi.psy.uva.nl/projects/xpce/ |
5 | Copyright (c) 2000-2011, University of Amsterdam | |
5 | Copyright (c) 2000-2020, University of Amsterdam | |
6 | 6 | All rights reserved. |
7 | 7 | |
8 | 8 | Redistribution and use in source and binary forms, with or without |
103 | 103 | @br |
104 | 104 | ]. |
105 | 105 | element(div, A, C) --> % <DIV> |
106 | element(p, A, C). % TBD: Should force clearance of | |
106 | element(p, A, C). % TBD: Should force clearance of | |
107 | element(span, _, C) --> | |
108 | seq(C). | |
107 | 109 | % shape-graphicals! |
108 | 110 | element(br, _, _) --> % <BR> |
109 | 111 | [ @br, |
325 | 327 | ] |
326 | 328 | ). |
327 | 329 | element(a, Attr, Content) --> % <A NAME=<Label>> ... </A> |
328 | { memberchk(name=Label, Attr) | |
330 | { memberchk(id=Label, Attr) | |
331 | ; memberchk(name=Label, Attr) | |
329 | 332 | }, |
330 | 333 | !, |
331 | 334 | [ \anchor(Label, Content) |
359 | 362 | % Preformatted output |
360 | 363 | |
361 | 364 | element(pre, _, Content) --> % <PRE> |
362 | [ @br, | |
365 | [ \parskip, | |
363 | 366 | \group([ \setfont(fixed, @on), |
364 | 367 | \pre(Content) |
365 | 368 | ]), |
380 | 383 | element(meta, _, _) --> % <META> |
381 | 384 | []. |
382 | 385 | element(link, _, _) --> % <LINK> |
386 | []. | |
387 | element(script, _, _) --> % <SCRIPT> | |
383 | 388 | []. |
384 | 389 | element(body, Attributes, Content) --> % <BODY> |
385 | 390 | [ \body(Attributes) |
538 | 543 | catch(number_chars(Num, Chars), _, fail), |
539 | 544 | Frac is Num/100. |
540 | 545 | |
546 | seq([]) --> []. | |
547 | seq([H|T]) --> [H], seq(T). | |
548 | ||
541 | 549 | /******************************* |
542 | 550 | * MESSAGES * |
543 | 551 | *******************************/ |
50 | 50 | |
51 | 51 | :- pce_begin_class(emacs, application, |
52 | 52 | "PceEmacs main object"). |
53 | ||
54 | class_variable(icon_image, image*, @pce_image). | |
53 | 55 | |
54 | 56 | variable(buffer_list, dict, get, "List of buffers maintained"). |
55 | 57 | variable(history, history, get, "History of visited places"). |
86 | 86 | :- consult(language_mode). |
87 | 87 | :- consult(outline_mode). |
88 | 88 | :- consult(bookmarks). |
89 | :- consult(help_buffer). | |
89 | 90 | |
90 | 91 | |
91 | 92 | /******************************* |
0 | /* Part of XPCE --- The SWI-Prolog GUI toolkit | |
1 | ||
2 | Author: Jan Wielemaker | |
3 | E-mail: J.Wielemaker@vu.nl | |
4 | WWW: http://www.swi-prolog.org | |
5 | Copyright (c) 2020, VU University Amsterdam | |
6 | CWI, Amsterdam | |
7 | All rights reserved. | |
8 | ||
9 | Redistribution and use in source and binary forms, with or without | |
10 | modification, are permitted provided that the following conditions | |
11 | are met: | |
12 | ||
13 | 1. Redistributions of source code must retain the above copyright | |
14 | notice, this list of conditions and the following disclaimer. | |
15 | ||
16 | 2. Redistributions in binary form must reproduce the above copyright | |
17 | notice, this list of conditions and the following disclaimer in | |
18 | the documentation and/or other materials provided with the | |
19 | distribution. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
32 | POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | |
34 | ||
35 | :- module(emacs_show_help, []). | |
36 | :- use_module(library(pce), [new/2, pce_open/3, send/2, op(_,_,_)]). | |
37 | :- autoload(library(sgml), [load_html/3]). | |
38 | :- autoload(library(lynx/html_text),[html_text/2]). | |
39 | :- autoload(library(pce_emacs), [start_emacs/0]). | |
40 | ||
41 | /** <module> Capture help in a PceEmacs buffer | |
42 | ||
43 | This module captures the output of _Documentation_ in the PceEmacs | |
44 | buffer ``*Documentation*``. | |
45 | ||
46 | @tbd We should made the output of html_text/2 interceptable at a | |
47 | higher level of abstraction such that we can create nice | |
48 | coloured fragments. | |
49 | */ | |
50 | ||
51 | :- multifile | |
52 | prolog_help:show_html_hook/1. | |
53 | ||
54 | prolog_help:show_html_hook(HTMLString) :- | |
55 | thread_self(pce), | |
56 | start_emacs, | |
57 | send(@emacs, location_history), | |
58 | setup_call_cleanup( | |
59 | open_string(HTMLString, In), | |
60 | load_html(stream(In), DOM, []), | |
61 | close(In)), | |
62 | new(B, emacs_buffer(@nil, '*Documentation*')), | |
63 | send(B, mode, text), | |
64 | send(B, clear), | |
65 | setup_call_cleanup( | |
66 | pce_open(B, write, Out), | |
67 | ( set_stream(Out, newline(posix)), | |
68 | with_output_to(Out, html_text(DOM, [])) | |
69 | ), | |
70 | close(Out)), | |
71 | send(B, modified, @off), | |
72 | ( send(B?editors, empty) | |
73 | -> send(B, open, tab) | |
74 | ; send(B?editors, for_all, message(@arg1, caret, 0)), | |
75 | get(B?editors?head, frame, Frame), | |
76 | send(Frame, tab, B, @on), | |
77 | send(Frame, expose) | |
78 | ), | |
79 | send(@emacs, location_history, title := 'Documentation'). | |
80 | ||
81 | ||
82 |
52 | 52 | delete_breakpoint/1, |
53 | 53 | manpce/1, |
54 | 54 | prolog_ide/1, |
55 | rational/1, | |
55 | 56 | spypce/1, |
56 | trace/1, | |
57 | 57 | tracepce/1, |
58 | 58 | atomic_list_concat/2, |
59 | 59 | breakpoint_property/2, |
64 | 64 | set_stream/2, |
65 | 65 | source_file_property/2, |
66 | 66 | string_codes/2, |
67 | term_string/2, | |
67 | 68 | term_to_atom/2, |
68 | 69 | absolute_file_name/3, |
69 | 70 | atomic_list_concat/3, |
70 | 71 | between/3, |
71 | 72 | compound_name_arity/3, |
72 | 73 | default/3, |
74 | file_autoload_directives/3, | |
73 | 75 | file_name_extension/3, |
74 | 76 | get_dict/3, |
75 | 77 | nb_setarg/3, |
78 | rational/3, | |
76 | 79 | send_list/3, |
77 | 80 | setup_call_cleanup/3, |
81 | stream_position_data/3, | |
78 | 82 | strip_module/3, |
79 | 83 | xref_prolog_flag/4, |
84 | get_dict/5, | |
80 | 85 | sub_string/5 |
81 | 86 | ]). |
82 | 87 | |
111 | 116 | view_threads = button(prolog), |
112 | 117 | view_debug_messages = button(prolog), |
113 | 118 | - = button(prolog), |
119 | check_dependencies = button(prolog), | |
120 | update_dependencies = key('\\C-c\\C-d') + button(prolog), | |
114 | 121 | check_clause = key('\\C-c\\C-s') + button(prolog), |
115 | 122 | setup_auto_indent = button(prolog), |
116 | 123 | insert_full_stop = key(.), |
171 | 178 | typing). |
172 | 179 | class_variable(auto_colourise_size_limit, int, 100000, |
173 | 180 | "Auto-colourise if buffer is smaller then this"). |
181 | class_variable(dependency_directive, | |
182 | { 'autoload/1', | |
183 | 'autoload/2', | |
184 | 'use_module/1', | |
185 | 'use_module/2' | |
186 | }, 'autoload/2', | |
187 | "How to insert new dependencies"). | |
174 | 188 | |
175 | 189 | variable(varmark_style, style*, get, "How to mark variables"). |
176 | 190 | variable(has_var_marks, bool := @off, get, "Optimise a bit"). |
186 | 200 | variable(cond_indentation, int, get, "Indent step for conditional"). |
187 | 201 | variable(quasiquotation_syntax, |
188 | 202 | name*, both, "Default quasiquotation syntax"). |
203 | variable(dependency_directive, | |
204 | { 'autoload/1', | |
205 | 'autoload/2', | |
206 | 'use_module/1', | |
207 | 'use_module/2' | |
208 | }, | |
209 | both, | |
210 | "How to insert new dependencies"). | |
189 | 211 | |
190 | 212 | class_variable(quasiquotation_syntax, name*, @nil). |
191 | 213 | class_variable(body_indentation, int, 4). |
192 | 214 | class_variable(cond_indentation, int, 4). |
193 | 215 | class_variable(indent_tabs, bool, @off, |
194 | 216 | "Use tabs for indentation"). |
195 | ||
196 | 217 | |
197 | 218 | icon(_, I:image) :<- |
198 | 219 | "Return icon for mode":: |
890 | 911 | "Consult selected text":: |
891 | 912 | get(M, selection, point(From, To)), |
892 | 913 | send(M, consult_region, From, To). |
914 | ||
915 | ||
916 | /******************************* | |
917 | * DEPENDENCIES * | |
918 | *******************************/ | |
919 | ||
920 | :- meta_predicate | |
921 | to_kill_buffer(0). | |
922 | ||
923 | check_dependencies(E) :-> | |
924 | "See whether any dependencies are missing":: | |
925 | get(E, text_buffer, TB), | |
926 | file_autoload_directives(TB, Directives, [missing(true)]), | |
927 | count_dependencies(Directives, Count), | |
928 | ( Directives == [] | |
929 | -> send(E, report, status, 'No missing dependencies') | |
930 | ; to_kill_buffer(maplist(portray_clause, Directives)), | |
931 | send(E, report, warning, | |
932 | 'WARNING: %d missing dependencies. \c | |
933 | Use ^Y to insert required directives at caret.', | |
934 | Count) | |
935 | ). | |
936 | ||
937 | insert_dependencies(E) :-> | |
938 | "Insert :- autoload/2 directives":: | |
939 | ( get(E, mark_status, active) | |
940 | -> get(E, selection, point(From, To)) | |
941 | ; From = 0, | |
942 | To = 0 | |
943 | ), | |
944 | update_dependencies(E, From, To). | |
945 | ||
946 | update_dependencies(E) :-> | |
947 | "Update existing dependencies or add new block":: | |
948 | get(E, find_dependencies, point(From, To)), | |
949 | update_dependencies(E, From, To). | |
950 | ||
951 | update_dependencies(E, From, To) :- | |
952 | read_terms_in_range(E, From, To, Terms), | |
953 | directive_options(E, Terms, DirOptions), | |
954 | get(E, text_buffer, TB), | |
955 | file_autoload_directives(TB, Directives, [update(Terms)|DirOptions]), | |
956 | ( append(Terms, New, Directives) | |
957 | -> ( New == [] | |
958 | -> send(E, report, status, 'No updates required') | |
959 | ; add_new_dependencies(E, New, To), | |
960 | count_dependencies(New, Count), | |
961 | send(E, report, status, 'Added %d new dependencies', Count) | |
962 | ) | |
963 | ; send(E, delete, From, To), | |
964 | add_new_dependencies(E, Directives, From), | |
965 | send(E, report, status, 'Updated dependencies') | |
966 | ). | |
967 | ||
968 | add_new_dependencies(E, Directives, At) :- | |
969 | send(@emacs, location_history), | |
970 | send(E, caret, At), | |
971 | send(@emacs, location_history, title := 'Update dependencies'), | |
972 | setup_call_cleanup( | |
973 | pce_open(E, update, Out), | |
974 | ( seek(Out, At, bof, _), | |
975 | with_output_to(Out, maplist(portray_clause, Directives)) | |
976 | ), | |
977 | close(Out)), | |
978 | get(E, caret, End), | |
979 | send(E, selection, At, End, highlight), | |
980 | send(E, auto_colourise_buffer). | |
981 | ||
982 | directive_options(_E, Terms, []) :- | |
983 | member(:-(Directive), Terms), | |
984 | is_dependency(Directive), | |
985 | !. | |
986 | directive_options(E, _, [directive(Pred)]) :- | |
987 | get(E, dependency_directive, Atom), | |
988 | term_string(Pred, Atom). | |
989 | ||
990 | count_dependencies(Directives, Deps) :- | |
991 | maplist(directive_deps, Directives, Counts), | |
992 | sum_list(Counts, Deps). | |
993 | ||
994 | directive_deps((:- autoload(_, Preds)), Count) :- | |
995 | !, | |
996 | length(Preds, Count). | |
997 | directive_deps((:- use_module(_, Preds)), Count) :- | |
998 | !, | |
999 | length(Preds, Count). | |
1000 | directive_deps(_, 1). | |
1001 | ||
1002 | to_kill_buffer(Goal) :- | |
1003 | new(E, editor), | |
1004 | setup_call_cleanup( | |
1005 | pce_open(E, write, Out), | |
1006 | with_output_to(Out, Goal), | |
1007 | close(Out)), | |
1008 | get(E?text_buffer, size, Size), | |
1009 | send(E, grab, 0, Size), | |
1010 | free(E). | |
1011 | ||
1012 | read_selection(E, Terms:prolog) :<- | |
1013 | "Read the selection as a list of terms":: | |
1014 | get(E, selection, point(From, To)), | |
1015 | read_terms_in_range(E, From, To, Terms). | |
1016 | ||
1017 | read_terms_in_range(E, From, To, Terms) :- | |
1018 | To > From, | |
1019 | !, | |
1020 | setup_call_cleanup( | |
1021 | pce_open(E, read, In), | |
1022 | ( seek(In, From, bof, _), | |
1023 | read_terms_to(In, To, Terms) | |
1024 | ), | |
1025 | close(In)). | |
1026 | read_terms_in_range(_, _, _, []). | |
1027 | ||
1028 | read_terms_to(In, End, Terms) :- | |
1029 | quiet_read_next(In, Term, _, Here), | |
1030 | !, | |
1031 | ( Term == end_of_file | |
1032 | -> Terms = [] | |
1033 | ; ( Here > End | |
1034 | -> Terms = [] | |
1035 | ; Terms = [Term|Rest], | |
1036 | read_terms_to(In, End, Rest) | |
1037 | ) | |
1038 | ). | |
1039 | read_terms_to(_, _, []). | |
1040 | ||
1041 | find_dependencies(E, Range:point) :<- | |
1042 | "Get start and end of dependencies":: | |
1043 | setup_call_cleanup( | |
1044 | pce_open(E, read, In), | |
1045 | find_dependencies(In, #{}, Dict), | |
1046 | close(In)), | |
1047 | get(E, text_buffer, TB), | |
1048 | ( _{start:Start, end:End0} :< Dict | |
1049 | -> get(TB, scan, End0, line, 1, start, End), | |
1050 | new(Range, point(Start, End)) | |
1051 | ; _{module_decl_end:Start0} :< Dict | |
1052 | -> get(TB, scan, Start0, line, 1, start, Start), | |
1053 | new(Range, point(Start, Start)) | |
1054 | ; _{program_start:Start0} :< Dict | |
1055 | -> get(TB, scan, Start0, line, -1, start, Start), | |
1056 | new(Range, point(Start, Start)) | |
1057 | ). | |
1058 | ||
1059 | find_dependencies(In, State0, State) :- | |
1060 | quiet_read_next(In, Term, F, T), | |
1061 | ( Term = :-(Directive) | |
1062 | -> update_dep_state(Directive, F, T, State0, State1), | |
1063 | find_dependencies(In, State1, State) | |
1064 | ; State = State0.put(program_start, F) | |
1065 | ). | |
1066 | ||
1067 | update_dep_state(module(_,_), _, T, State0, State) :- | |
1068 | !, | |
1069 | State = State0.put(module_decl_end, T). | |
1070 | update_dep_state(Decl, S, E, State0, State) :- | |
1071 | is_dependency(Decl), | |
1072 | !, | |
1073 | ( get_dict(end, State0, _, State, E) | |
1074 | -> true | |
1075 | ; State = State0.put(#{start:S, end:E}) | |
1076 | ). | |
1077 | update_dep_state(_, _, _, State, State). | |
1078 | ||
1079 | is_dependency(autoload(_)). | |
1080 | is_dependency(use_module(_)). | |
1081 | is_dependency(autoload(_,_)). | |
1082 | is_dependency(use_module(_,_)). | |
1083 | ||
1084 | quiet_read_next(In, Term, From, To) :- | |
1085 | between(1, 10, _), | |
1086 | read_term(In, Term, | |
1087 | [ syntax_errors(quiet), | |
1088 | term_position(Pos) | |
1089 | ]), | |
1090 | nonvar(Term), | |
1091 | stream_position_data(char_count, Pos, From), | |
1092 | character_count(In, To), | |
1093 | !. | |
893 | 1094 | |
894 | 1095 | |
895 | 1096 | /******************************* |
1546 | 1546 | *******************************/ |
1547 | 1547 | |
1548 | 1548 | location_history(M, Start:start=[int], Len:length=[int], |
1549 | Title:title=[char_array]) :-> | |
1549 | Always:always=[bool], Title:title=[char_array]) :-> | |
1550 | 1550 | "Add location to the editor history":: |
1551 | 1551 | ( Start == @default |
1552 | 1552 | -> get(M, caret, Caret), |
1553 | 1553 | get(M, scan, Caret, line, 0, start, SOF) |
1554 | 1554 | ; SOF = Start |
1555 | 1555 | ), |
1556 | ( send(M, history_not_interesting, SOF) | |
1556 | ( Always \== @on, | |
1557 | send(M, history_not_interesting, SOF) | |
1557 | 1558 | -> true |
1558 | 1559 | ; get(M, text_buffer, TB), |
1559 | 1560 | new(_, emacs_history_fragment(TB, SOF, Len, Title)) |
0 | XPCE Agenda | |
1 | ||
2 | ||
3 | TO DO: | |
4 | *) Selection Service interaction (not only cut-buffers) | |
5 | *) Editor/Text | |
6 | 1) Multi Kills backward: buggy | |
7 | 2) Handle non-printable characters correctly | |
8 | *) Bitmaps: | |
9 | 1) Scaling | |
10 | 2) Stencils | |
11 | *) `Resizer' object: inverted box to avoid redisplay | |
12 | 1) ->object: Graphical* | |
13 | 2) ->active: Boolean | |
14 | 3) ->execute: move attached object | |
15 | *) Creating new expression classes? | |
16 | *) NAME_forwards AND NAME_forward!! | |
17 | *) Window ->grab_keyboard werkt niet zonder Window ->grab_pointer! | |
18 | *) list_browser, editor: subclass of dialog_item? | |
19 | *) Efficient constraint handling for spatials | |
20 | 1) Trap updates for spatials at class graphical? | |
21 | *) Communicate with host on CWD (current directory) | |
22 | *) Clone/save: | |
23 | 3) Relations (connection, constraint, hyper): | |
24 | - Internal <-> external relations | |
25 | *) Creation: exploit `variable <-initial_value' (also function) | |
26 | Integrate with resource system. Part of `object ->initialise'? | |
27 | *) Improve consistency of groups | |
28 | *) Print \t as space for xwn-draw.c text functions | |
29 | *) Add ->report: progress and ->report: done | |
30 | ||
31 | Multi-Screen access | |
32 | ||
33 | *) Resolve logical-font names. | |
34 | *) Handling destruction of visual tool | |
35 | *) Fix bitmaps | |
36 | *) Resolve CurrentDisplay usage; | |
37 | 1) Display of current-event? | |
38 | 2) DisplayManager <- current | |
39 | 3) Display of some graphical | |
40 | *) Display <->class --> resource_class |
0 | #!/bin/sh | |
1 | # | |
2 | # Check for symbols defined as COMMON and appearing in the global symbol | |
3 | # table. This indicates that the COMMON definition is not visible when | |
4 | # the function is defined, which causes errors on some linkers (Linux on | |
5 | # IA_64 is one of them). | |
6 | # | |
7 | # Note: this script only works on Linux/i386. No worries, its only for | |
8 | # me to find all such problems. | |
9 | ||
10 | grep -w COMMON */*.h | \ | |
11 | sed 's/.*COMMON([^)]*)[ ]\([a-zA-Z_0-9]*\).*/\1/' | \ | |
12 | sort -u > Common.def | |
13 | ||
14 | nm ../linux/pl2xpce.so | \ | |
15 | grep -w T | \ | |
16 | sed 's/.* T //' | \ | |
17 | sort -u > Common.glb | |
18 | ||
19 | comm -12 Common.def Common.glb | |
20 | ||
21 | rm -f Common.def Common.glb |
0 | .NOCHECK | |
1 | ||
2 | ARCH=pc | |
3 | OS=windows3.1 | |
4 | VERSION=4.8.5, Dec. 1994 | |
5 | ||
6 | MAKE=wmake /h | |
7 | CC=wcc386 | |
8 | CXX=wpp386 | |
9 | CWFLAGS= | |
10 | COFLAGS=/d1 | |
11 | CIFLAGS=-I.. -I..\..\.. | |
12 | CMFLAGS=-fpc -bt=windows | |
13 | CFLAGS=$(CWFLAGS) $(COFLAGS) $(CIFLAGS) $(CMFLAGS) | |
14 | LD=wlink | |
15 | #LDFLAGS=system win386 debug all | |
16 | LDFLAGS=system win386 | |
17 | WST=msw | |
18 | ||
19 | LN=copy | |
20 | ||
21 | MKPROTO=mkproto -p | |
22 | CLPROTO=grep -vw NewClass | |
23 | ETAGS=etags | |
24 | ||
25 | .c.obj: | |
26 | $(CC) /zq $(CFLAGS) $*.c | |
27 | ||
28 | .cxx.obj | |
29 | $(CXX) /zq $(CFLAGS) $*.cxx |
0 | ||
1 | * Make the window border-line an X-window border | |
2 | * Merge displacements of windows with updateConnectionsGraphical() | |
3 | * Find a solution for ->display: Picture: should display the | |
4 | <-decoration rather than the window itself. | |
5 | * Make sure the move- and resize-gestures can be attached to | |
6 | windows. | |
7 | * Update documentation |
0 | XPCE TODO List | |
1 | ||
2 | [Badly maintained] | |
3 | ||
4 | Frames and Windows | |
5 | ================== | |
6 | ||
7 | One of the annoying things at the moment is that frames are no windows | |
8 | and therefore can be nested nor embedded in other XPCE GUI stuff. I | |
9 | propose to make class frame a subclass of class Window, providing tiled | |
10 | layout of subwindows. Other things that gets closer with this are MDI | |
11 | and `docking' as windows can be re-parented more easily. | |
12 | ||
13 | The other toplevel (shell-widget) code of class Frame can be integrated | |
14 | in class Window. Steps: | |
15 | ||
16 | * Create class frame_window below window and move the client-side | |
17 | (tile) stuff there. | |
18 | ||
19 | * Move relevant frame behaviour to class window. | |
20 | ||
21 | * Remove class frame and rename frame_window to frame. | |
22 | ||
23 | Consequences: | |
24 | ||
25 | * Simple windows (no tiled) that are ->open'ed no longer have an | |
26 | associated frame. | |
27 | ||
28 | * <-frame will need an extra argument to indicate the desired frame | |
29 | as frames are now nested. | |
30 | ||
31 | Text handling | |
32 | ============= | |
33 | ||
34 | The use of LocalString() can cause problems. Errors from alloca() are | |
35 | non-portable and some systems have severe limits on what you can do with | |
36 | alloca(). | |
37 | ||
38 | ||
39 |
0 | Multi-threading XPCE | |
1 | ||
2 | Message Passing | |
3 | =============== | |
4 | ||
5 | * Move global-data to thread-local data. These are the 3 variables defined | |
6 | in trace.h. Simple | |
7 | ||
8 | ||
9 | Program objects | |
10 | =============== | |
11 | ||
12 | * Simplest: lock resolveImplementationGoal() | |
13 | drawback: executes obtainers and other potentionally expensive code that | |
14 | need not lock | |
15 | ||
16 | * Alternative: | |
17 | Lock class-access methods: | |
18 | getSendMethodClass() | |
19 | getGetMethodClass() | |
20 | Also manipulation methods on same lock: | |
21 | realising/method adding operations | |
22 | ||
23 | Graphics | |
24 | ======== | |
25 | ||
26 | Make state maintained by xdraw.c and msdraw.c thread-safe. Options: | |
27 | ||
28 | * Lock d_*() ... d_done() sequences | |
29 | ||
30 | * Use thread-local-data graphical resources | |
31 | ||
32 | * Make changedWindow() and display-manipulation thread-safe. | |
33 | ||
34 | ||
35 | User objects | |
36 | ============ | |
37 | ||
38 | * Lock at the window level while changes are pending: | |
39 | When changing a graphical, grab the window-mutex. | |
40 | ||
41 | * GrabWindow | |
42 | * Window is released after it is updated and repainted (i.e. ->flush) | |
43 | ||
44 | * User objects: | |
45 | ||
46 | + leave to user (simple) | |
47 | + Provide basic security on data objects (chains, vector, table) | |
48 | ||
49 | - `ForAll' can take long and risks deadlocks! | |
50 | ||
51 | + Allow objects to have a mutex associated? | |
52 | ||
53 | - send(Obj, mutex, {write,all,none}) | |
54 | - write: lock sends to this object | |
55 | - read: lock all | |
56 | ||
57 | Work-threads | |
58 | ============ | |
59 | ||
60 |
0 | MS-Windows Port TODO List | |
1 | Jan Wielemaker | |
2 | ||
3 | % Last updated: Fri Mar 19 1999 | |
4 | ||
5 | Images: | |
6 | ||
7 | * TBD: Save in MS-Windows format | |
8 | ||
9 | Timers: | |
10 | ||
11 | * FIX: Sometimes stops after closing some window. | |
12 | * TBD: Implement timers with a time of > 2**16 milliseconds. | |
13 | ||
14 | GUI: | |
15 | ||
16 | * Uwe Lesta: | |
17 | ||
18 | `` If you like i can tell you some things | |
19 | where the use of the dialog elements | |
20 | can be make more elegant (windows like). | |
21 | e.g. a combobox ( a text_item with a value_set ) | |
22 | on windows you can also select a value by open the box | |
23 | and drag down to the value you want. | |
24 | Or an other example your list browser e.g. | |
25 | Demo programs. I open it select the Program (all with the keyboard) | |
26 | that i like and than ?? I need the mouse. | |
27 | with which key can i open it. ? | |
28 | (Alt+O don't work, but the selecton is green not blue) | |
29 | '' | |
30 | ||
31 | BUGS: | |
32 | ||
33 | * new(X, colour('#00ffff')) fails. | |
34 | * drawing boxes of very small size fails (see remark in msdraw.c). | |
35 | * Symbol-font not mounted correctly |
0 | dnl SWI-Prolog specific autoconf macros | |
1 | ||
2 | dnl Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 Free Software | |
3 | dnl Foundation, Inc. | |
4 | dnl Copyright 2011, Roberto Bagnara, BUGSENG srl. | |
5 | dnl | |
6 | dnl This file is part of SWI-Prolog. | |
7 | dnl | |
8 | dnl This library is free software; you can redistribute it and/or modify | |
9 | dnl it under the terms of the GNU Lesser General Public License as published | |
10 | dnl by the Free Software Foundation; either version 3 of the License, or (at | |
11 | dnl your option) any later version. | |
12 | dnl | |
13 | dnl This library is distributed in the hope that it will be useful, but | |
14 | dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
16 | dnl License for more details. | |
17 | dnl | |
18 | dnl You should have received a copy of the GNU Lesser General Public License | |
19 | dnl along with this library. If not, see http://www.gnu.org/licenses/. | |
20 | ||
21 | ||
22 | dnl All the "FOR_BUILD" macros have been copied from the GNU MP Library | |
23 | dnl and then slightly modified. | |
24 | ||
25 | ||
26 | dnl SWI_PROG_CC_FOR_BUILD | |
27 | dnl --------------------- | |
28 | dnl Establish CC_FOR_BUILD, a C compiler for the build system. | |
29 | dnl | |
30 | dnl If CC_FOR_BUILD is set then it's expected to work, otherwise some | |
31 | dnl likely candidates are tried. | |
32 | ||
33 | AC_DEFUN([SWI_PROG_CC_FOR_BUILD], | |
34 | [AC_REQUIRE([AC_PROG_CC]) | |
35 | if test -n "$CC_FOR_BUILD"; then | |
36 | SWI_PROG_CC_FOR_BUILD_WORKS($CC_FOR_BUILD,, | |
37 | [AC_MSG_ERROR([Specified CC_FOR_BUILD doesn't seem to work])]) | |
38 | else | |
39 | for i in cc gcc clang c89 c99 "$CC" "$CC $CFLAGS $CPPFLAGS"; do | |
40 | SWI_PROG_CC_FOR_BUILD_WORKS($i, | |
41 | [CC_FOR_BUILD=$i | |
42 | break]) | |
43 | done | |
44 | if test -z "$CC_FOR_BUILD"; then | |
45 | AC_MSG_ERROR([Cannot find a build system compiler]) | |
46 | fi | |
47 | fi | |
48 | ||
49 | AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler]) | |
50 | AC_SUBST(CC_FOR_BUILD) | |
51 | ]) | |
52 | ||
53 | ||
54 | dnl SWI_PROG_CC_FOR_BUILD_WORKS(cc/cflags[,[action-if-good][,action-if-bad]]) | |
55 | dnl ------------------------------------------------------------------------- | |
56 | dnl See if the given cc/cflags works on the build system. | |
57 | dnl | |
58 | dnl It seems easiest to just use the default compiler output, rather than | |
59 | dnl figuring out the .exe or whatever at this stage. | |
60 | ||
61 | AC_DEFUN([SWI_PROG_CC_FOR_BUILD_WORKS], | |
62 | [AC_MSG_CHECKING([build system compiler $1]) | |
63 | # remove anything that might look like compiler output to our "||" expression | |
64 | rm -f conftest* a.out b.out a.exe a_out.exe | |
65 | cat >conftest.c <<EOF | |
66 | int | |
67 | main () | |
68 | { | |
69 | exit(0); | |
70 | } | |
71 | EOF | |
72 | swi_compile="$1 -DHAVE_CONFIG_H conftest.c" | |
73 | cc_for_build_works=no | |
74 | if AC_TRY_EVAL(swi_compile); then | |
75 | if (./a.out || ./b.out || ./a.exe || ./a_out.exe || ./conftest) >&AC_FD_CC 2>&1; then | |
76 | cc_for_build_works=yes | |
77 | fi | |
78 | fi | |
79 | rm -f conftest* a.out b.out a.exe a_out.exe | |
80 | AC_MSG_RESULT($cc_for_build_works) | |
81 | if test "$cc_for_build_works" = yes; then | |
82 | ifelse([$2],,:,[$2]) | |
83 | else | |
84 | ifelse([$3],,:,[$3]) | |
85 | fi | |
86 | ]) | |
87 | ||
88 | ||
89 | dnl SWI_PROG_EXEEXT_FOR_BUILD | |
90 | dnl ------------------------- | |
91 | dnl Determine EXEEXT_FOR_BUILD, the build system executable suffix. | |
92 | dnl | |
93 | dnl The idea is to find what "-o conftest$foo" will make it possible to run | |
94 | dnl the program with ./conftest. On Unix-like systems this is of course | |
95 | dnl nothing, for DOS it's ".exe", or for a strange RISC OS foreign file | |
96 | dnl system cross compile it can be ",ff8" apparently. Not sure if the | |
97 | dnl latter actually applies to a build-system executable, maybe it doesn't, | |
98 | dnl but it won't hurt to try. | |
99 | ||
100 | AC_DEFUN([SWI_PROG_EXEEXT_FOR_BUILD], | |
101 | [AC_REQUIRE([SWI_PROG_CC_FOR_BUILD]) | |
102 | AC_CACHE_CHECK([for build system executable suffix], | |
103 | swi_cv_prog_exeext_for_build, | |
104 | [cat >conftest.c <<EOF | |
105 | int | |
106 | main () | |
107 | { | |
108 | exit (0); | |
109 | } | |
110 | EOF | |
111 | for i in .exe ,ff8 ""; do | |
112 | swi_compile="$CC_FOR_BUILD conftest.c -o conftest$i" | |
113 | if AC_TRY_EVAL(swi_compile); then | |
114 | if (./conftest) 2>&AC_FD_CC; then | |
115 | swi_cv_prog_exeext_for_build=$i | |
116 | break | |
117 | fi | |
118 | fi | |
119 | done | |
120 | rm -f conftest* | |
121 | if test "${swi_cv_prog_exeext_for_build+set}" != set; then | |
122 | AC_MSG_ERROR([Cannot determine executable suffix]) | |
123 | fi | |
124 | ]) | |
125 | AC_SUBST(EXEEXT_FOR_BUILD,$swi_cv_prog_exeext_for_build) | |
126 | ]) |
0 | /* XPM */ | |
1 | static char * pce16_xpm[] = { | |
2 | "16 16 188 2", | |
3 | " c None", | |
4 | ". c #EE8B39", | |
5 | "+ c #E93932", | |
6 | "@ c #DA3533", | |
7 | "# c #F39B38", | |
8 | "$ c #F79E32", | |
9 | "% c #F7A43C", | |
10 | "& c #F69B37", | |
11 | "* c #F58E2F", | |
12 | "= c #F4832C", | |
13 | "- c #F2752B", | |
14 | "; c #EF6C30", | |
15 | "> c #EF552B", | |
16 | ", c #EF3322", | |
17 | "' c #F6AD41", | |
18 | ") c #FAB74E", | |
19 | "! c #FAB64B", | |
20 | "~ c #F8A633", | |
21 | "{ c #F79B31", | |
22 | "] c #F58D2F", | |
23 | "^ c #F37C29", | |
24 | "/ c #F27231", | |
25 | "( c #F26D42", | |
26 | "_ c #F04D36", | |
27 | ": c #EA382C", | |
28 | "< c #FBDAA2", | |
29 | "[ c #FEEECF", | |
30 | "} c #FFEDCC", | |
31 | "| c #FCD28E", | |
32 | "1 c #F8A437", | |
33 | "2 c #F69231", | |
34 | "3 c #F6964C", | |
35 | "4 c #FAC5A7", | |
36 | "5 c #FCDBCE", | |
37 | "6 c #FBC3B9", | |
38 | "7 c #F1817C", | |
39 | "8 c #FBDDB3", | |
40 | "9 c #FFFFFF", | |
41 | "0 c #FAFCFF", | |
42 | "a c #F6FAFE", | |
43 | "b c #FEFFFF", | |
44 | "c c #FAC681", | |
45 | "d c #F79634", | |
46 | "e c #FCE1CB", | |
47 | "f c #FAFEFF", | |
48 | "g c #F7FFFF", | |
49 | "h c #FDEBEA", | |
50 | "i c #DF7773", | |
51 | "j c #F7B56C", | |
52 | "k c #FEF1E0", | |
53 | "l c #FBFDFF", | |
54 | "m c #D9DADA", | |
55 | "n c #787778", | |
56 | "o c #C2C5C8", | |
57 | "p c #FFEBD4", | |
58 | "q c #FBA147", | |
59 | "r c #F5F6F6", | |
60 | "s c #BFC0C1", | |
61 | "t c #878688", | |
62 | "u c #D3DCDD", | |
63 | "v c #E39090", | |
64 | "w c #F5A353", | |
65 | "x c #FFF4E9", | |
66 | "y c #929294", | |
67 | "z c #1C1819", | |
68 | "A c #9C9C9E", | |
69 | "B c #D7D5D1", | |
70 | "C c #CBB6A2", | |
71 | "D c #E7EAEC", | |
72 | "E c #F4F4F4", | |
73 | "F c #797879", | |
74 | "G c #262224", | |
75 | "H c #B9C0C2", | |
76 | "I c #E08D8E", | |
77 | "J c #B82828", | |
78 | "K c #F48E39", | |
79 | "L c #FBD0A7", | |
80 | "M c #E3E4E5", | |
81 | "N c #BEBFC1", | |
82 | "O c #C8C9CC", | |
83 | "P c #D1D3D3", | |
84 | "Q c #D3D4D5", | |
85 | "R c #B3B5B7", | |
86 | "S c #F7F9F9", | |
87 | "T c #DADBDC", | |
88 | "U c #C1C3C4", | |
89 | "V c #F1F6F5", | |
90 | "W c #CD464A", | |
91 | "X c #AC191B", | |
92 | "Y c #F27B29", | |
93 | "Z c #F5903F", | |
94 | "` c #FCD4B5", | |
95 | " . c #FFFCF9", | |
96 | ".. c #FFFCF5", | |
97 | "+. c #D6BBA7", | |
98 | "@. c #BDBEBF", | |
99 | "#. c #BFC0C2", | |
100 | "$. c #A29A99", | |
101 | "%. c #F7CEC0", | |
102 | "&. c #FFFEFE", | |
103 | "*. c #FEECEA", | |
104 | "=. c #DE6A6B", | |
105 | "-. c #B8151B", | |
106 | ";. c #A21B1D", | |
107 | ">. c #E66928", | |
108 | ",. c #EA7227", | |
109 | "'. c #EC7421", | |
110 | "). c #F07D2D", | |
111 | "!. c #F37A27", | |
112 | "~. c #F17427", | |
113 | "{. c #8D7C75", | |
114 | "]. c #7C7D7F", | |
115 | "^. c #B15C46", | |
116 | "/. c #F53B19", | |
117 | "(. c #EB2D25", | |
118 | "_. c #D7151B", | |
119 | ":. c #BD0D14", | |
120 | "<. c #A70D12", | |
121 | "[. c #931112", | |
122 | "}. c #D35728", | |
123 | "|. c #D1551D", | |
124 | "1. c #CC581D", | |
125 | "2. c #DD6022", | |
126 | "3. c #ED6727", | |
127 | "4. c #F46326", | |
128 | "5. c #C65C35", | |
129 | "6. c #785954", | |
130 | "7. c #F14024", | |
131 | "8. c #ED2B24", | |
132 | "9. c #D7181E", | |
133 | "0. c #B71016", | |
134 | "a. c #9E0B0F", | |
135 | "b. c #850406", | |
136 | "c. c #8C1613", | |
137 | "d. c #DF5132", | |
138 | "e. c #D7451D", | |
139 | "f. c #DB4C20", | |
140 | "g. c #E75123", | |
141 | "h. c #F05326", | |
142 | "i. c #F04E26", | |
143 | "j. c #F34523", | |
144 | "k. c #D04034", | |
145 | "l. c #ED2622", | |
146 | "m. c #E01B22", | |
147 | "n. c #C8161C", | |
148 | "o. c #AD1015", | |
149 | "p. c #98090C", | |
150 | "q. c #820405", | |
151 | "r. c #CF2A1D", | |
152 | "s. c #DE321F", | |
153 | "t. c #EF3823", | |
154 | "u. c #F23422", | |
155 | "v. c #EF2F24", | |
156 | "w. c #EC2824", | |
157 | "x. c #E72022", | |
158 | "y. c #D91920", | |
159 | "z. c #C9141A", | |
160 | "A. c #B81016", | |
161 | "B. c #9E0A0E", | |
162 | "C. c #840305", | |
163 | "D. c #740303", | |
164 | "E. c #D31E22", | |
165 | "F. c #E02124", | |
166 | "G. c #DD2527", | |
167 | "H. c #CD3133", | |
168 | "I. c #D81E23", | |
169 | "J. c #D7181F", | |
170 | "K. c #CB161E", | |
171 | "L. c #C01319", | |
172 | "M. c #A72024", | |
173 | "N. c #99181B", | |
174 | "O. c #910406", | |
175 | "P. c #7A0001", | |
176 | "Q. c #6F0202", | |
177 | "R. c #9C8489", | |
178 | "S. c #B6A9AC", | |
179 | "T. c #A08384", | |
180 | "U. c #B51E25", | |
181 | "V. c #B51319", | |
182 | "W. c #994649", | |
183 | "X. c #ABA3A6", | |
184 | "Y. c #A4979A", | |
185 | "Z. c #97999C", | |
186 | "`. c #A0A2A4", | |
187 | " + c #7B7B7F", | |
188 | ".+ c #C4C7CA", | |
189 | "++ c #ACAFB1", | |
190 | "@+ c #888A8C", | |
191 | " . + @ ", | |
192 | " # $ % & * = - ; > , ", | |
193 | " ' ) ! ~ { ] ^ / ( _ : ", | |
194 | " < [ } | 1 2 3 4 5 6 7 ", | |
195 | " 8 9 0 a b c d e 9 f g h i ", | |
196 | " j k l m n o p q 9 r s t u v ", | |
197 | " w x l y z A B C D E F G H I J ", | |
198 | " K L 9 M N O P Q R S T U V W X ", | |
199 | " Y Z ` ...+.@.#.$.%.&.*.=.-.;.", | |
200 | " >.,.'.).!.~.{.].^./.(._.:.<.[.", | |
201 | " }.|.1.2.3.4.5.6.7.8.9.0.a.b.c.", | |
202 | " d.e.f.g.h.i.j.k.l.m.n.o.p.q. ", | |
203 | " r.s.t.u.v.w.x.y.z.A.B.C.D. ", | |
204 | " E.F.G.H.I.J.K.L.M.N.O.P.Q. ", | |
205 | " R.S.T.U.V.W.X.Y. ", | |
206 | " Z. `. +.+++@+ "}; |
0 | /* XPM */ | |
1 | static char *swipl48_xpm[] = { | |
2 | /* columns rows colors chars-per-pixel */ | |
3 | "48 48 225 2 ", | |
4 | " c #231F20", | |
5 | ". c #6A0B0E", | |
6 | "X c #730B0E", | |
7 | "o c #770E11", | |
8 | "O c #6D0C10", | |
9 | "+ c #691928", | |
10 | "@ c #49243A", | |
11 | "# c #403E3F", | |
12 | "$ c #591D2F", | |
13 | "% c #092C49", | |
14 | "& c #17314C", | |
15 | "* c #153352", | |
16 | "= c #26384E", | |
17 | "- c #293B51", | |
18 | "; c #313E51", | |
19 | ": c #163E64", | |
20 | "> c #452840", | |
21 | ", c #394557", | |
22 | "< c #3C424F", | |
23 | "1 c #1E446B", | |
24 | "2 c #4C4A4A", | |
25 | "3 c #454D5A", | |
26 | "4 c #575557", | |
27 | "5 c #49515E", | |
28 | "6 c #6D5054", | |
29 | "7 c #4C5462", | |
30 | "8 c #555B66", | |
31 | "9 c #656364", | |
32 | "0 c #67676C", | |
33 | "q c #746869", | |
34 | "w c #676A73", | |
35 | "e c #6D7179", | |
36 | "r c #74767A", | |
37 | "t c #5C6069", | |
38 | "y c #870E12", | |
39 | "u c #930F14", | |
40 | "i c #851013", | |
41 | "p c #941115", | |
42 | "a c #9D1116", | |
43 | "s c #99161A", | |
44 | "d c #A41217", | |
45 | "f c #AC1419", | |
46 | "g c #A41419", | |
47 | "h c #B3141A", | |
48 | "j c #BB151B", | |
49 | "k c #BF181E", | |
50 | "l c #B13519", | |
51 | "z c #981C29", | |
52 | "x c #963233", | |
53 | "c c #AA242D", | |
54 | "v c #A11C2A", | |
55 | "b c #C3161C", | |
56 | "n c #CC171E", | |
57 | "m c #CB1C1F", | |
58 | "M c #D5181F", | |
59 | "N c #D0171E", | |
60 | "B c #CD301E", | |
61 | "V c #DC1920", | |
62 | "C c #D41920", | |
63 | "Z c #CD1921", | |
64 | "A c #E31B22", | |
65 | "S c #EB1C23", | |
66 | "D c #D32C2F", | |
67 | "F c #EE2323", | |
68 | "G c #EE2C22", | |
69 | "H c #E82624", | |
70 | "J c #EF3422", | |
71 | "K c #E83B23", | |
72 | "L c #F03C21", | |
73 | "P c #F03722", | |
74 | "I c #EF3E3E", | |
75 | "U c #DB4B1F", | |
76 | "Y c #C4451C", | |
77 | "T c #D4452F", | |
78 | "R c #E94723", | |
79 | "E c #F04421", | |
80 | "W c #F14B21", | |
81 | "Q c #E75621", | |
82 | "! c #F15321", | |
83 | "~ c #F25B21", | |
84 | "^ c #EE463B", | |
85 | "/ c #F36420", | |
86 | "( c #F36C20", | |
87 | ") c #F47421", | |
88 | "_ c #F57B21", | |
89 | "` c #EC6C35", | |
90 | "' c #BC3957", | |
91 | "] c #DB374A", | |
92 | "[ c #824A49", | |
93 | "{ c #A94C46", | |
94 | "} c #9D506B", | |
95 | "| c #BB5569", | |
96 | " . c #866969", | |
97 | ".. c #887A7A", | |
98 | "X. c #956768", | |
99 | "o. c #AF6667", | |
100 | "O. c #CD4A45", | |
101 | "+. c #EF4E49", | |
102 | "@. c #F17053", | |
103 | "#. c #D96A6E", | |
104 | "$. c #E97875", | |
105 | "%. c #C85678", | |
106 | "&. c #F58321", | |
107 | "*. c #F68B21", | |
108 | "=. c #F69422", | |
109 | "-. c #F79C22", | |
110 | ";. c #F48537", | |
111 | ":. c #F79838", | |
112 | ">. c #F8A423", | |
113 | ",. c #F8A923", | |
114 | "<. c #BA877A", | |
115 | "1. c #F58448", | |
116 | "2. c #F58755", | |
117 | "3. c #EA8459", | |
118 | "4. c #F5AB4D", | |
119 | "5. c #F19471", | |
120 | "6. c #F3AA72", | |
121 | "7. c #36629B", | |
122 | "8. c #3D69A3", | |
123 | "9. c #325D93", | |
124 | "0. c #526896", | |
125 | "q. c #787B83", | |
126 | "w. c #6A7994", | |
127 | "e. c #587CB3", | |
128 | "r. c #4D6EA7", | |
129 | "t. c #5E6594", | |
130 | "y. c #B06E93", | |
131 | "u. c #7C828F", | |
132 | "i. c #6C8BBE", | |
133 | "p. c #6383B8", | |
134 | "a. c #718AB8", | |
135 | "s. c #7888A9", | |
136 | "d. c #5E80B5", | |
137 | "f. c #7993C3", | |
138 | "g. c #848384", | |
139 | "h. c #8C8B8C", | |
140 | "j. c #898787", | |
141 | "k. c #958B8B", | |
142 | "l. c #949293", | |
143 | "z. c #9C9B9B", | |
144 | "x. c #989799", | |
145 | "c. c #8F8F92", | |
146 | "v. c #A39F9F", | |
147 | "b. c #B58F8F", | |
148 | "n. c #8792AB", | |
149 | "m. c #989BA3", | |
150 | "M. c #8F94B5", | |
151 | "N. c #A19FA0", | |
152 | "B. c #BB9CB0", | |
153 | "V. c #99A4BE", | |
154 | "C. c #A4A3A3", | |
155 | "Z. c #A9A6A6", | |
156 | "A. c #AEADAD", | |
157 | "S. c #A4A5AA", | |
158 | "D. c #B0AFAF", | |
159 | "F. c #B8A8A9", | |
160 | "G. c #B3ACB3", | |
161 | "H. c #B3B2B2", | |
162 | "J. c #B8B7B7", | |
163 | "K. c #BCBBBB", | |
164 | "L. c #B6B6B9", | |
165 | "P. c #A8ACB5", | |
166 | "I. c #CA9697", | |
167 | "U. c #D99292", | |
168 | "Y. c #DD8588", | |
169 | "T. c #E6938C", | |
170 | "R. c #F5AA88", | |
171 | "E. c #F6B78B", | |
172 | "W. c #EEAA94", | |
173 | "Q. c #C1BEBE", | |
174 | "!. c #C5B4B5", | |
175 | "~. c #D2B2B1", | |
176 | "^. c #E5B8B9", | |
177 | "/. c #EFB1A7", | |
178 | "(. c #CE9A9A", | |
179 | "). c #FAC48D", | |
180 | "_. c #F9CDB3", | |
181 | "`. c #849CC8", | |
182 | "'. c #8BA2CC", | |
183 | "]. c #99A7CA", | |
184 | "[. c #98ABD2", | |
185 | "{. c #A3AAC5", | |
186 | "}. c #ACB3C3", | |
187 | "|. c #BBBDC4", | |
188 | " X c #AAB9D9", | |
189 | ".X c #B2BDD8", | |
190 | "XX c #C0BFC0", | |
191 | "oX c #B7C2DC", | |
192 | "OX c #BEC2CE", | |
193 | "+X c #B9C5E1", | |
194 | "@X c #BAC7E2", | |
195 | "#X c #C4C3C4", | |
196 | "$X c #CCCBCB", | |
197 | "%X c #C6C6C8", | |
198 | "&X c #D9CDCD", | |
199 | "*X c #CCCED4", | |
200 | "=X c #D4D3D3", | |
201 | "-X c #DBDBDB", | |
202 | ";X c #D7D7DA", | |
203 | ":X c #D0D1D7", | |
204 | ">X c #F9D7C9", | |
205 | ",X c #E5DCDA", | |
206 | "<X c #FBDBD6", | |
207 | "1X c #EDCBCA", | |
208 | "2X c #FDE8D7", | |
209 | "3X c #C2CDE5", | |
210 | "4X c #CBD4E9", | |
211 | "5X c #CCD5EA", | |
212 | "6X c #D4DCED", | |
213 | "7X c #D9DCE7", | |
214 | "8X c #DCE3F1", | |
215 | "9X c #E4E4E4", | |
216 | "0X c #ECEBEC", | |
217 | "qX c #E4E5EA", | |
218 | "wX c #FCEBE8", | |
219 | "eX c #FCF2EC", | |
220 | "rX c #E5EAF5", | |
221 | "tX c #EAEDF6", | |
222 | "yX c #E3E8F4", | |
223 | "uX c #EEF2F9", | |
224 | "iX c #F2F2F2", | |
225 | "pX c #F3F6FB", | |
226 | "aX c #FFFFFF", | |
227 | "sX c #FBF5F5", | |
228 | "dX c None", | |
229 | /* pixels */ | |
230 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX-X;X=X=X=X$X$X$X#XdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX", | |
231 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX9X9X9X-X-X-X;X;X=X=X=X$X%X#X#XXXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX", | |
232 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdX9X9X9X9X9X-X9X-X-X;X;X=X=X$X$X%X#XK.J.J.H.dXdXdXdXdXdXdXdXdXdXdXdXdX", | |
233 | "dXdXdXdXdXdXdXdXdXdXdXdXqXqX9X9X*X|.}.].V.{.}.OX$X=X=X$X$X%X#XXXK.J.H.D.dXdXdXdXdXdXdXdXdXdXdXdX", | |
234 | "dXdXdXdXdXdXdXdXdXdX0X0XqX*X}.f.i.p.p.d.e.e.r.r.r.s.L.%X$X$X%XXXQ.J.L.D.A.H.dXdXdXdXdXdXdXdXdXdX", | |
235 | "dXdXdXdXdXdXdXdXdX0XqX:X[.'.`.f.f.f.p.p.d.p.s.n.n.d.0.w.A.$X$X%X#XK.J.H.A.A.D.dXdXdXdXdXdXdXdXdX", | |
236 | "dXdXdXdXdXdXdXdX0XqXoX[.[.'.'.f.f.f.M.L.$X-X-X-X-X=X$XXXn.x.XX$X#XK.K.L.D.D.D.D.dXdXdXdXdXdXdXdX", | |
237 | "dXdXdXdXdXdXdX0XqX.X XG.B.{.'.'.`.|.7XqX0X0X0X9X9X9X-X-X=X$XXX%X#X!.!.I.F.A.A.D.D.dXdXdXdXdXdXdX", | |
238 | "dXdXdXdXdXdX0XqXoXoX XU.) _ 3.N.*X0XiXiXiX0X0X9X9X9X9X-X;X=X=X#X$.F S O.G.G.A.A.D.D.dXdXdXdXdXdX", | |
239 | "dXdXdXdXdXiX0X3X@X@XoX.X;.&.&.&._.sXiX>X/.6.5.2.1.5.T./.&X-X^.^ G F S I.J.J.D.D.Z.D.D.dXdXdXdXdX", | |
240 | "dXdXdXdX0X0X7X3X3X3X@X+X5.*.*.*.*.E.:.*.&.&._ _ ( ( ~ ~ ! $.+.E G F S !.J.D.D.D.x.C.D.D.dXdXdXdX", | |
241 | "dXdXdXdXiXqX5X6X4X4X3X@XR.=.-.-.-.=.-.=.*.*.&._ _ ( / ~ ! W E L J F S !.K.J.D.D.Z.u.D.D.dXdXdXdX", | |
242 | "dXdXdXiX0X7X6X6X6X5X4X3X6.-.>.>.>.,.>.-.=.=.*.&._ ( ( ~ ~ W E L J G F !.K.L.H.A.A.e N.D.D.dXdXdX", | |
243 | "dXdXdXiXqX8XyX8X8X6X7X5X4.>.,.,.,.,.,.>.-.=.*.&._ ) ( / ~ ! W E J G F ~.K.L.H.D.D.h.r D.D.D.dXdX", | |
244 | "dXdXiX0XrXtXtXrXrX8X6X&X>.).2XeXeX2X_.4.>.-.=.*.&._ ( / W.<X2XwX<X/.+.$.K.J.H.A.A.C.5 C.D.D.dXdX", | |
245 | "dXdX0X0XuXuXuXuXtX8X7X6.wXaXaXaXaXaXaXeX).-.=.*.&._ 2.wXaXaXaXaXaXaXwX$.I.J.H.A.A.A.t h.D.D.dXdX", | |
246 | "dXiX0X0XpXpXaXpXuXqXE.wXaXaXaXaXaXaXaXaXaXE.-.*.&.1.eXaXaXaXaXaXaXaXaXaX$.F.D.D.D.D.r 0 Z.D.H.dX", | |
247 | "dX0X0XtXpXpXaXpXuX,X_.aXaXaXaXaXaXaXaXaXaXeX-.*.&.>XaXaXaXaXaXaXaXaXaXaX<X#.D.D.D.D.c., C.D.D.dX", | |
248 | "dX0X0XtXpXpXpXpXuX6.sXaXaXaXaXiX=X%X=XiXaXaXE.*.1.aXaXaXaXaXiX=X#X=XiXaXaXY.b.D.A.A.m.% c.D.D.dX", | |
249 | "dX0XqXtXpXpXpXuX>X6.aXaXaXaXsX%Xl.9 h.K.sXaX>X*.E.aXaXaXaXiXXXh.9 l.#XiXaX^.| D.D.A.Z.& r A.D.H.", | |
250 | "dX0X9XyXrXtXtXtXW.E.aXaXaXaX9Xz.iXr x.-XaX2X*./.aXaXaXaX-Xz.pX4 N.9XaX1Xb Z.A.D.A., t A.D.H.", | |
251 | "0X0X7XqXyXyXrXqX;.6.aXaXaXaX-Xl.2 j.=XaX&X(.~.iXaXaXaX=Xj.2 l.-XaX^.j y.A.D.A., 7 S.D.H.", | |
252 | "9X0X7X7X8X8X8X&X_ ;.aXaXaXaX0XL.2 # H.-X#X%X$X#XA.9XaXaX9XH.# 2 H.0XaXU.j o.D.A.A.5 , C.D.D.", | |
253 | "9X9X7X6X6X6X6X^._ _ >XaXaXaXaX-XJ.Z.J.=X%X%X-X-X$XJ.z.aXaXaX=XJ.A.K.;XaXiXD h { A.D.A., , z.D.D.", | |
254 | "9X9X7X4X4X4X4XW.) ) 2.sXaXaXaXaXiXqX0XaXD.$X-X-X&XJ.c.qXaXaXaXiX0XiXaXpXU.j h g A.D.A.= - N.D.D.", | |
255 | "9X9X;X@X@X3X3XU.( ( _ 5.eXaXaXaXaXaXaXaXC.Q.=X=X%XD.j.9XaXaXaXaXaXaXaXW.b j f a Z.D.C.% , N.D.H.", | |
256 | "9X9X;X+X+X+X+XY./ ( ( ) 1._.eXaXaXsX,X5.<.Z.J.J.D.x. .@.1XeXaXaXsX1X#.n j h d a Z.D.l.% , C.D.H.", | |
257 | "dX,X;X X X+X.XY.Q / / ( ( ( ( ` 2.) ) _ O.<.l.l.j.q T R G G +.+.S M m b j f a u Z.A.q.% 8 Z.D.H.", | |
258 | "dX-X,X X X X X(.U ~ ~ / / ( / ( / / / / / { 9 9 4 [ L P G F F S V C n k f d u x D.A.5 % w A.D.dX", | |
259 | "dX;X;X.X[.[.[.B.U l U U Q Q Q / ~ ~ ~ ! ! R 6 4 4 T P G F F S A C k h a d i o X.D.z.% % g.A.D.dX", | |
260 | "dX-X7XXX'.[.[.[.E U W U l Q B Y Q ! ! W W E O.4 { J G G F S A j a k g i d p i k.D.w % = z.D.H.dX", | |
261 | "dXdX;X:X'.'.'.`.#.K E R R W U R W E W E E L K [ K G F F S A M n f j h g a y i v.z.& % 8 Z.D.H.dX", | |
262 | "dXdX=X;X{.`.f.`.y.B B K B K K E E L L L L J J D G F S S V M N n j f a p o O [ Z.7 % % h.A.A.dXdX", | |
263 | "dXdX=X=X%Xa.f.f.M.J B P B l L J P P P J G G F F F F S V M n b j f p X p y X X.e % % 8 N.D.D.dXdX", | |
264 | "dXdXdX$X=XV.i.i.f.] G G G J G G G G G G G F F S S A V M m b j h d d p y o o 6 % % & c.A.D.dXdXdX", | |
265 | "dXdXdX$X$X#Xa.p.e.%.m Z H F F F F F F S S S S A V M n b b j f g a p y X . O & % % e Z.D.H.dXdXdX", | |
266 | "dXdXdXdX%X$XP.d.e.y.M N A A A S S S S A A V V M N n b b h d g a p y i o . + % % 8 C.A.A.dXdXdXdX", | |
267 | "dXdXdXdXdX%X%XM.e.w.V V ] | V A A D D V M M m b b j h d g v s i u + $ X . $ % 5 x.A.A.H.dXdXdXdX", | |
268 | "dXdXdXdXdX#X#XK.y.r.M ' r.8.t.} ..c.h.X.D j k j h f v X.h.l.<.6 @ % % @ . @ 4 x.A.A.H.dXdXdXdXdX", | |
269 | "dXdXdXdXdXdXQ.Q.|.f.} 8.8.7.0.g.A.|.K.N. .x c v v z q v.J.Q.S.u.2 % % % @ 9 z.A.A.A.dXdXdXdXdXdX", | |
270 | "dXdXdXdXdXdXdXJ.L.L.m.0.7.9.0 m.OX=X=XJ.j., * % % & <.H.=X-X%XZ.0 % % , u.Z.A.A.D.dXdXdXdXdXdXdX", | |
271 | "dXdXdXdXdXdXdXdXL.L.L.Z.c.9.9 C.S.u.u.C.c.3 % % % = u.Z.q.e m.Z.q < r z.Z.D.A.D.dXdXdXdXdXdXdXdX", | |
272 | "dXdXdXdXdXdXdXdXdXL.D.H.D.C.9 q.1 : : * 0 < % % % < 0 - % % = r 9 z.A.A.A.A.H.dXdXdXdXdXdXdXdXdX", | |
273 | "dXdXdXdXdXdXdXdXdXdXdXD.D.D.h.z.l.u.w 7 5 < & % & , 5 8 w j.x.C.g.D.A.A.A.H.dXdXdXdXdXdXdXdXdXdX", | |
274 | "dXdXdXdXdXdXdXdXdXdXdXdXD.D.A.A.D.D.A.Z.C.N.z.z.z.N.C.Z.A.A.A.A.D.D.D.D.dXdXdXdXdXdXdXdXdXdXdXdX", | |
275 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdXH.D.D.D.D.D.D.D.H.D.D.D.D.D.D.D.A.D.D.D.dXdXdXdXdXdXdXdXdXdXdXdXdXdX", | |
276 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXH.H.D.D.D.D.D.D.D.D.D.D.D.H.L.dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX", | |
277 | "dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXH.H.H.H.H.H.dXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdXdX" | |
278 | }; |
960 | 960 | |
961 | 961 | |
962 | 962 | #ifdef XPM_PCEIMAGE |
963 | #include "bitmaps/pce16.xpm" | |
963 | #include "bitmaps/swipl48.xpm" | |
964 | 964 | #include "bitmaps/hadjusttile.xpm" |
965 | 965 | #include "bitmaps/vadjusttile.xpm" |
966 | 966 | #include "bitmaps/up.xpm" |
1034 | 1034 | stdImage(NAME_intItemImage, &INT_ITEM_IMAGE, |
1035 | 1035 | (char*)intarrows_bits, intarrows_width, intarrows_height); |
1036 | 1036 | #ifdef XPM_PCEIMAGE |
1037 | stdXPMImage(NAME_pceImage, NULL, pce16_xpm); | |
1037 | stdXPMImage(NAME_pceImage, NULL, swipl48_xpm); | |
1038 | 1038 | stdXPMImage(NAME_hadjustTileImage, NULL, hadjusttile_xpm); |
1039 | 1039 | stdXPMImage(NAME_vadjustTileImage, NULL, vadjusttile_xpm); |
1040 | 1040 | stdXPMImage(NAME_scrollUpImage, &SCROLL_UP_IMAGE, up_xpm); |
813 | 813 | Chain members; /* its member frames */ |
814 | 814 | Name kind; /* {user,service} */ |
815 | 815 | Chain modal; /* Stack of modal frames */ |
816 | Image icon_image; /* Image of the icon */ | |
816 | 817 | End; |
817 | 818 | |
818 | 819 |
0 | #!/bin/sh | |
1 | # | |
2 | # install - install a program, script, or datafile | |
3 | # This comes from X11R5. | |
4 | # | |
5 | # Calling this script install-sh is preferred over install.sh, to prevent | |
6 | # `make' implicit rules from creating a file called install from it | |
7 | # when there is no Makefile. | |
8 | # | |
9 | # This script is compatible with the BSD install script, but was written | |
10 | # from scratch. | |
11 | # | |
12 | ||
13 | ||
14 | # set DOITPROG to echo to test this script | |
15 | ||
16 | # Don't use :- since 4.3BSD and earlier shells don't like it. | |
17 | doit="${DOITPROG-}" | |
18 | ||
19 | ||
20 | # put in absolute paths if you don't have them in your path; or use env. vars. | |
21 | ||
22 | mvprog="${MVPROG-mv}" | |
23 | cpprog="${CPPROG-cp}" | |
24 | chmodprog="${CHMODPROG-chmod}" | |
25 | chownprog="${CHOWNPROG-chown}" | |
26 | chgrpprog="${CHGRPPROG-chgrp}" | |
27 | stripprog="${STRIPPROG-strip}" | |
28 | rmprog="${RMPROG-rm}" | |
29 | mkdirprog="${MKDIRPROG-mkdir}" | |
30 | ||
31 | tranformbasename="" | |
32 | transform_arg="" | |
33 | instcmd="$mvprog" | |
34 | chmodcmd="$chmodprog 0755" | |
35 | chowncmd="" | |
36 | chgrpcmd="" | |
37 | stripcmd="" | |
38 | rmcmd="$rmprog -f" | |
39 | mvcmd="$mvprog" | |
40 | src="" | |
41 | dst="" | |
42 | dir_arg="" | |
43 | ||
44 | while [ x"$1" != x ]; do | |
45 | case $1 in | |
46 | -c) instcmd="$cpprog" | |
47 | shift | |
48 | continue;; | |
49 | ||
50 | -d) dir_arg=true | |
51 | shift | |
52 | continue;; | |
53 | ||
54 | -m) chmodcmd="$chmodprog $2" | |
55 | shift | |
56 | shift | |
57 | continue;; | |
58 | ||
59 | -o) chowncmd="$chownprog $2" | |
60 | shift | |
61 | shift | |
62 | continue;; | |
63 | ||
64 | -g) chgrpcmd="$chgrpprog $2" | |
65 | shift | |
66 | shift | |
67 | continue;; | |
68 | ||
69 | -s) stripcmd="$stripprog" | |
70 | shift | |
71 | continue;; | |
72 | ||
73 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` | |
74 | shift | |
75 | continue;; | |
76 | ||
77 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` | |
78 | shift | |
79 | continue;; | |
80 | ||
81 | *) if [ x"$src" = x ] | |
82 | then | |
83 | src=$1 | |
84 | else | |
85 | # this colon is to work around a 386BSD /bin/sh bug | |
86 | : | |
87 | dst=$1 | |
88 | fi | |
89 | shift | |
90 | continue;; | |
91 | esac | |
92 | done | |
93 | ||
94 | if [ x"$src" = x ] | |
95 | then | |
96 | echo "install: no input file specified" | |
97 | exit 1 | |
98 | else | |
99 | true | |
100 | fi | |
101 | ||
102 | if [ x"$dir_arg" != x ]; then | |
103 | dst=$src | |
104 | src="" | |
105 | ||
106 | if [ -d $dst ]; then | |
107 | instcmd=: | |
108 | else | |
109 | instcmd=mkdir | |
110 | fi | |
111 | else | |
112 | ||
113 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command | |
114 | # might cause directories to be created, which would be especially bad | |
115 | # if $src (and thus $dsttmp) contains '*'. | |
116 | ||
117 | if [ -f $src -o -d $src ] | |
118 | then | |
119 | true | |
120 | else | |
121 | echo "install: $src does not exist" | |
122 | exit 1 | |
123 | fi | |
124 | ||
125 | if [ x"$dst" = x ] | |
126 | then | |
127 | echo "install: no destination specified" | |
128 | exit 1 | |
129 | else | |
130 | true | |
131 | fi | |
132 | ||
133 | # If destination is a directory, append the input filename; if your system | |
134 | # does not like double slashes in filenames, you may need to add some logic | |
135 | ||
136 | if [ -d $dst ] | |
137 | then | |
138 | dst="$dst"/`basename $src` | |
139 | else | |
140 | true | |
141 | fi | |
142 | fi | |
143 | ||
144 | ## this sed command emulates the dirname command | |
145 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` | |
146 | ||
147 | # Make sure that the destination directory exists. | |
148 | # this part is taken from Noah Friedman's mkinstalldirs script | |
149 | ||
150 | # Skip lots of stat calls in the usual case. | |
151 | if [ ! -d "$dstdir" ]; then | |
152 | defaultIFS=' | |
153 | ' | |
154 | IFS="${IFS-${defaultIFS}}" | |
155 | ||
156 | oIFS="${IFS}" | |
157 | # Some sh's can't handle IFS=/ for some reason. | |
158 | IFS='%' | |
159 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` | |
160 | IFS="${oIFS}" | |
161 | ||
162 | pathcomp='' | |
163 | ||
164 | while [ $# -ne 0 ] ; do | |
165 | pathcomp="${pathcomp}${1}" | |
166 | shift | |
167 | ||
168 | if [ ! -d "${pathcomp}" ] ; | |
169 | then | |
170 | $mkdirprog "${pathcomp}" | |
171 | else | |
172 | true | |
173 | fi | |
174 | ||
175 | pathcomp="${pathcomp}/" | |
176 | done | |
177 | fi | |
178 | ||
179 | if [ x"$dir_arg" != x ] | |
180 | then | |
181 | $doit $instcmd $dst && | |
182 | ||
183 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && | |
184 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && | |
185 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && | |
186 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi | |
187 | else | |
188 | ||
189 | # If we're going to rename the final executable, determine the name now. | |
190 | ||
191 | if [ x"$transformarg" = x ] | |
192 | then | |
193 | dstfile=`basename $dst` | |
194 | else | |
195 | dstfile=`basename $dst $transformbasename | | |
196 | sed $transformarg`$transformbasename | |
197 | fi | |
198 | ||
199 | # don't allow the sed command to completely eliminate the filename | |
200 | ||
201 | if [ x"$dstfile" = x ] | |
202 | then | |
203 | dstfile=`basename $dst` | |
204 | else | |
205 | true | |
206 | fi | |
207 | ||
208 | # Make a temp file name in the proper directory. | |
209 | ||
210 | dsttmp=$dstdir/#inst.$$# | |
211 | ||
212 | # Move or copy the file name to the temp name | |
213 | ||
214 | $doit $instcmd $src $dsttmp && | |
215 | ||
216 | trap "rm -f ${dsttmp}" 0 && | |
217 | ||
218 | # and set any options; do chmod last to preserve setuid bits | |
219 | ||
220 | # If any of these fail, we abort the whole thing. If we want to | |
221 | # ignore errors from any of these, just make sure not to ignore | |
222 | # errors from the above "$doit $instcmd $src $dsttmp" command. | |
223 | ||
224 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && | |
225 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && | |
226 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && | |
227 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && | |
228 | ||
229 | # Now rename the file to the real destination. | |
230 | ||
231 | $doit $rmcmd -f $dstdir/$dstfile && | |
232 | $doit $mvcmd $dsttmp $dstdir/$dstfile | |
233 | ||
234 | fi && | |
235 | ||
236 | ||
237 | exit 0 |
0 | #!/bin/sh | |
1 | ||
2 | # mkproto file ... | |
3 | # | |
4 | # Generate the proto.h files in the various subdirectories. mkproto is a | |
5 | # public domain program to generate ANSI prototypes from C-sources. | |
6 | ||
7 | mkproto -p -d COMMON -D '#define COMMON(type) SO_LOCAL type' $* | \ | |
8 | grep -vw NewClass | grep -v pceMT |
0 | #!/bin/sh | |
1 | ||
2 | arch=$1 | |
3 | ||
4 | echo "[ERROR: No machine description file for PLARCH=$arch]" | |
5 | ||
6 | arches=`ls md | grep -v CVS | sed 's/md-\(.*\)\.h/\1/'` | |
7 | ||
8 | echo "" | |
9 | echo "Please edit PLARCH in Makefile to be one of:" | |
10 | for a in $arches; do echo " $a"; done | |
11 | exit 1 |
0 | #!/bin/sh | |
1 | # Author: Stepan Kasal <kasal@suse.cz> | |
2 | # | |
3 | # Version: 0.1 | |
4 | # this shell script is public domain ;-) | |
5 | # Modified: Thu Feb 17 2000 (JW) | |
6 | # Avoid use of ln -sf (GNU specific) | |
7 | # Avoid use of GNU sed extensions | |
8 | # If all fails due to other links, make an absolute link. | |
9 | # Modified: Thu Mar 9 2000 (JW) | |
10 | # Avoid using grep -q (GNU specific) | |
11 | # | |
12 | # Purpose: Make relative links between the binary and lib directory to | |
13 | # achieve a relocatable object. Notably useful for generating RPM files. | |
14 | ||
15 | check_path() | |
16 | { dir=$(dirname "$1") | |
17 | file=$(basename "$1") | |
18 | cdir=$(cd $dir && pwd) | |
19 | ||
20 | echo $cdir/$file | |
21 | } | |
22 | ||
23 | compare() | |
24 | { test $# = 4 && test "$1" = "$3" && from=$2 && to=$4 | |
25 | } | |
26 | ||
27 | if test $# != 2 ; then | |
28 | echo "usage: $0 from to | |
29 | creates relative symbolic link from \$1 to \$2" >&2 | |
30 | exit 1 | |
31 | fi | |
32 | ||
33 | from=$1 | |
34 | to=$2 | |
35 | ||
36 | from=$(check_path "$from") | |
37 | to=$(check_path "$to") | |
38 | ||
39 | # Make sure $to points to destination file instead of dir | |
40 | ||
41 | if [ -d $to ]; then | |
42 | to=$to/`basename $from`; | |
43 | fi | |
44 | ||
45 | abs_to="$to" | |
46 | abs_from="$from" | |
47 | ||
48 | # Remove leading / and replace repeated // into a single / | |
49 | ||
50 | from=`echo $from | sed -e 's,//*,/,g' -e 's,/,,'` | |
51 | to=`echo $to | sed -e 's,//*,/,g' -e 's,/,,'` | |
52 | ||
53 | # Now get rid of the common start. | |
54 | ||
55 | while compare `echo $from|sed "s,/, ,"` `echo $to|sed "s,/, ,"` | |
56 | do test a = a | |
57 | done | |
58 | ||
59 | # Remove all but the last segment of $to into .. and put the from after this | |
60 | ||
61 | relf="`echo $to | sed -e 's,[^/][^/]*/,../,g' -e 's,[^/][^/]*$,,'`$from" | |
62 | ||
63 | rm -f "$abs_to" | |
64 | # Cygwin specific test to find out if a symlink exists with a .exe suffix. | |
65 | # Newer ln(1) create symlinks to executables also with a .exe suffix. | |
66 | [ -s "$abs_to".exe ] && rm -f "$abs_to".exe | |
67 | ||
68 | # Now, all can be in vain due to other symbolic links. If this is the case, | |
69 | # link absolute after all. | |
70 | ||
71 | if (cd `dirname $abs_to` && test -e $relf); then | |
72 | ln -s "$relf" "$abs_to" | |
73 | else | |
74 | echo "`basename $0`: Making abolute link to $abs_from" | |
75 | ln -s "$abs_from" "$abs_to" | |
76 | fi |
42 | 42 | assign(app, members, newObject(ClassChain, EAV)); |
43 | 43 | assign(app, kind, NAME_user); |
44 | 44 | assign(app, modal, newObject(ClassChain, EAV)); |
45 | obtainClassVariablesObject(app); | |
45 | 46 | |
46 | 47 | appendChain(TheApplications, app); |
47 | 48 | |
203 | 204 | IV(NAME_kind, "{user,service}", IV_BOTH, |
204 | 205 | NAME_debugging, "If service, events cannot be debugged"), |
205 | 206 | IV(NAME_modal, "chain", IV_NONE, |
206 | NAME_event, "Frame for modal operation") | |
207 | NAME_event, "Frame for modal operation"), | |
208 | IV(NAME_iconImage, "image*", IV_BOTH, | |
209 | NAME_icon, "Image used for the iconic representation") | |
207 | 210 | }; |
208 | 211 | |
209 | 212 | /* Send Methods */ |
238 | 241 | |
239 | 242 | /* Resources */ |
240 | 243 | |
241 | #define rc_application NULL | |
242 | /* | |
243 | 244 | static classvardecl rc_application[] = |
244 | { | |
245 | }; | |
246 | */ | |
245 | { RC(NAME_iconImage, "image*", "@nil", | |
246 | "Image displayed for an icon") | |
247 | }; | |
247 | 248 | |
248 | 249 | /* Class Declaration */ |
249 | 250 |
267 | 267 | COMMON(int) write_gif_file(IOSTREAM *fd, XImage *img, XImage *msk, |
268 | 268 | Display *disp, Colormap cmap); |
269 | 269 | COMMON(XImage *) attachXpmImageImage(Image image, XpmImage *xpm); |
270 | COMMON(unsigned long *) XImageToRGBA(XImage *img, XImage *msk, | |
271 | Display *disp, Colormap cmap, size_t *lenp); | |
270 | 272 | |
271 | 273 | /* xcolour.c */ |
272 | 274 | COMMON(status) allocNearestColour(Display *display, Colormap map, |
274 | 276 | |
275 | 277 | extern XtAppContext ThePceXtAppContext; /* X toolkit application context */ |
276 | 278 | |
279 | COMMON(unsigned long*) ws_image_to_rgba(Image image, Image mask, size_t *lenp); | |
280 | ||
277 | 281 | #endif /*_PCE_X11_INCLUDED*/ |
278 | 282 |
72 | 72 | |
73 | 73 | XftPatternAddString(p, XFT_FAMILY, fam); |
74 | 74 | XftPatternAddDouble(p, XFT_PIXEL_SIZE, (double)valInt(f->points)*fscale); |
75 | if ( f->style == NAME_italic ) | |
75 | if ( f->style == NAME_italic || f->style == NAME_oblique ) | |
76 | 76 | XftPatternAddInteger(p, XFT_SLANT, XFT_SLANT_ITALIC); |
77 | 77 | else if ( f->style == NAME_roman ) |
78 | 78 | XftPatternAddInteger(p, XFT_SLANT, XFT_SLANT_ROMAN); |
46 | 46 | static void destroyFrame(Widget, FrameObj, XtPointer); |
47 | 47 | static status updateAreaFrame(FrameObj fr, Int border); |
48 | 48 | static int ws_group_frame(FrameObj fr); |
49 | static int ws_set_pid_frame(FrameObj fr); | |
50 | static void ws_set_net_icon_frame(FrameObj fr); | |
49 | 51 | |
50 | 52 | #define MainWindow(fr) ( isNil(fr->members->head) ? (Any) fr : \ |
51 | 53 | fr->members->head->value ) |
143 | 145 | |
144 | 146 | XtDestroyWidget(w); |
145 | 147 | } |
148 | } | |
149 | ||
150 | ||
151 | static Image | |
152 | getIconFrame(FrameObj fr) | |
153 | { if ( notNil(fr->application) && notNil(fr->application->icon_image) ) | |
154 | return fr->application->icon_image; | |
155 | ||
156 | return fr->icon_image; | |
146 | 157 | } |
147 | 158 | |
148 | 159 | |
153 | 164 | Widget w; |
154 | 165 | DisplayObj d = fr->display; |
155 | 166 | DisplayWsXref r = d->ws_ref; |
167 | Image icon; | |
156 | 168 | |
157 | 169 | XtSetArg(args[n], XtNtitle, nameToMB(fr->label)); n++; |
158 | 170 | XtSetArg(args[n], XtNmappedWhenManaged, False); n++; |
176 | 188 | { XtSetArg(args[n], XtNsaveUnder, True); |
177 | 189 | n++; |
178 | 190 | } |
179 | if ( notNil(fr->icon_image) ) | |
191 | if ( notNil(icon=getIconFrame(fr)) ) | |
180 | 192 | { XtSetArg(args[n], XtNiconPixmap, |
181 | getXrefObject(fr->icon_image, fr->display)); | |
193 | getXrefObject(icon, fr->display)); | |
182 | 194 | n++; |
183 | if ( notNil(fr->icon_image->mask) ) | |
195 | if ( notNil(icon->mask) ) | |
184 | 196 | { XtSetArg(args[n], XtNiconMask, |
185 | getXrefObject(fr->icon_image->mask, fr->display)); | |
197 | getXrefObject(icon->mask, fr->display)); | |
186 | 198 | n++; |
187 | 199 | } |
188 | 200 | } |
262 | 274 | |
263 | 275 | ws_frame_background(fr, fr->background); /* Why is this necessary? */ |
264 | 276 | ws_group_frame(fr); |
277 | if ( notNil(fr->application) && notNil(fr->application->icon_image) ) | |
278 | ws_set_pid_frame(fr); /* group in Ubuntu dock */ | |
279 | ||
280 | ws_set_net_icon_frame(fr); | |
265 | 281 | } |
266 | 282 | |
267 | 283 | |
409 | 425 | |
410 | 426 | fail; |
411 | 427 | } |
428 | ||
429 | static int | |
430 | ws_set_pid_frame(FrameObj fr) | |
431 | { Widget w = widgetFrame(fr); | |
432 | DisplayWsXref r = fr->display->ws_ref; | |
433 | unsigned int xpid = getpid(); | |
434 | static Atom _net_wm_pid = 0; | |
435 | ||
436 | if ( !_net_wm_pid ) | |
437 | _net_wm_pid = XInternAtom(r->display_xref, | |
438 | "_NET_WM_PID", | |
439 | False); | |
440 | ||
441 | XChangeProperty(r->display_xref, | |
442 | XtWindow(w), | |
443 | _net_wm_pid, | |
444 | XA_CARDINAL, 32, PropModeReplace, | |
445 | (unsigned char *) &xpid, 1); | |
446 | ||
447 | return TRUE; | |
448 | } | |
449 | ||
412 | 450 | |
413 | 451 | #ifdef O_XDND |
414 | 452 | /******************************* |
1363 | 1401 | } |
1364 | 1402 | |
1365 | 1403 | |
1404 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
1405 | See https://stackoverflow.com/questions/10699927/xlib-argb-window-icon | |
1406 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
1407 | ||
1408 | static void | |
1409 | ws_set_net_icon_frame(FrameObj fr) | |
1410 | { unsigned long *buffer; | |
1411 | size_t length; | |
1412 | Image icon = getIconFrame(fr); | |
1413 | ||
1414 | if ( notNil(icon) && | |
1415 | getXrefObject(icon, fr->display) && | |
1416 | (buffer=ws_image_to_rgba(icon, DEFAULT, &length)) ) | |
1417 | { Widget w = widgetFrame(fr); | |
1418 | DisplayWsXref r = fr->display->ws_ref; | |
1419 | static Atom _net_wm_icon = 0; | |
1420 | static Atom cardinal = 0; | |
1421 | ||
1422 | if ( !_net_wm_icon ) { | |
1423 | _net_wm_icon = XInternAtom(r->display_xref, | |
1424 | "_NET_WM_ICON", | |
1425 | False); | |
1426 | cardinal = XInternAtom(r->display_xref, "CARDINAL", False); | |
1427 | } | |
1428 | ||
1429 | XChangeProperty(r->display_xref, | |
1430 | XtWindow(w), | |
1431 | _net_wm_icon, | |
1432 | cardinal, 32, | |
1433 | PropModeReplace, (const unsigned char*) buffer, length); | |
1434 | ||
1435 | free(buffer); | |
1436 | } | |
1437 | } | |
1438 | ||
1439 | ||
1366 | 1440 | void |
1367 | 1441 | ws_set_icon_label_frame(FrameObj fr) |
1368 | 1442 | { Widget w = widgetFrame(fr); |
149 | 149 | return errorPce(image, NAME_cannotSaveObject, NAME_noImage); |
150 | 150 | |
151 | 151 | succeed; |
152 | } | |
153 | ||
154 | ||
155 | unsigned long * | |
156 | ws_image_to_rgba(Image image, Image mask, size_t *lenp) | |
157 | { XImage *img, *msk = NULL; | |
158 | int img_free=FALSE; | |
159 | int msk_free=FALSE; | |
160 | DisplayObj d = image->display; | |
161 | DisplayWsXref r; | |
162 | unsigned long *data; | |
163 | ||
164 | if ( isNil(d) ) | |
165 | d = CurrentDisplay(image); | |
166 | r = d->ws_ref; | |
167 | ||
168 | if ( isDefault(mask) ) | |
169 | mask = image->mask; | |
170 | ||
171 | if ( !(img=getXImageImage(image)) ) | |
172 | { if ( (img = getXImageImageFromScreen(image)) ) | |
173 | img_free = TRUE; | |
174 | else | |
175 | return NULL; | |
176 | } | |
177 | ||
178 | if ( notNil(mask) ) | |
179 | { if ( !(msk=getXImageImage(mask)) ) | |
180 | { if ( (msk = getXImageImageFromScreen(mask)) ) | |
181 | msk_free = TRUE; | |
182 | } | |
183 | } | |
184 | ||
185 | data = XImageToRGBA(img, msk, r->display_xref, 0, lenp); | |
186 | if ( img_free ) XDestroyImage(img); | |
187 | if ( msk_free ) XDestroyImage(msk); | |
188 | ||
189 | return data; | |
152 | 190 | } |
153 | 191 | |
154 | 192 |
98 | 98 | }; |
99 | 99 | |
100 | 100 | struct table |
101 | { int size; | |
101 | { int size; | |
102 | 102 | Symbol symbols[1]; |
103 | 103 | }; |
104 | 104 | |
834 | 834 | c = pixelToColor(img, pixel, &info); |
835 | 835 | r = intensityXColor(c); |
836 | 836 | r = rescale(r, BRIGHT, scale); |
837 | if ( Sputc(r, fd) == EOF ) | |
837 | if ( Sputc(r, fd) == EOF ) | |
838 | 838 | return -1; |
839 | 839 | } |
840 | 840 | } |
882 | 882 | |
883 | 883 | return 0; |
884 | 884 | } |
885 | ||
886 | ||
887 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
888 | Translate an XImage and an optional mask into an RBGA image in a format | |
889 | that is suitable for _NET_WM_ICON. | |
890 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
891 | ||
892 | unsigned long * | |
893 | XImageToRGBA(XImage *img, XImage *msk, | |
894 | Display *disp, Colormap cmap, size_t *lenp) | |
895 | { int width = img->width; | |
896 | int height = img->height; | |
897 | XPixelInfo img_info; | |
898 | XPixelInfo msk_info; | |
899 | XColor img_cdata[256]; | |
900 | XColor msk_cdata[256]; | |
901 | int msk_is_bitmap = TRUE; | |
902 | int x, y; | |
903 | unsigned long *data, *p; | |
904 | const int scale = 255; | |
905 | size_t len; | |
906 | ||
907 | if ( msk && (msk->height != height || msk->width != width) ) | |
908 | msk = NULL; | |
909 | ||
910 | if ( img->format != XYBitmap ) | |
911 | { img_info.cinfo = img_cdata; | |
912 | makeXPixelInfo(&img_info, img, disp, cmap); | |
913 | } | |
914 | if ( msk ) | |
915 | { if ( msk->format == XYBitmap || | |
916 | (msk->format == ZPixmap && msk->bits_per_pixel == 1) ) | |
917 | { msk_is_bitmap = TRUE; | |
918 | } else | |
919 | { msk_is_bitmap = FALSE; | |
920 | msk_info.cinfo = msk_cdata; | |
921 | makeXPixelInfo(&msk_info, msk, disp, cmap); | |
922 | } | |
923 | } | |
924 | ||
925 | len = 2+width*height; | |
926 | if ( lenp ) | |
927 | *lenp = len; | |
928 | if ( !(data = malloc(len*sizeof(*data))) ) | |
929 | return data; | |
930 | p = data; | |
931 | *p++ = width; | |
932 | *p++ = height; | |
933 | ||
934 | for(y=0; y<height; y++) | |
935 | { for(x=0; x<width; x++) | |
936 | { XColor *c; | |
937 | unsigned int r, g, b, a; | |
938 | union | |
939 | { unsigned int i32; | |
940 | char c32[4]; | |
941 | } upix; | |
942 | ||
943 | c = pixelToColor(img, XGetPixel(img, x, y), &img_info); | |
944 | r = rescale(c->red, BRIGHT, scale); | |
945 | g = rescale(c->green, BRIGHT, scale); | |
946 | b = rescale(c->blue, BRIGHT, scale); | |
947 | ||
948 | if ( msk ) | |
949 | { unsigned long pixel = XGetPixel(msk, x, y); | |
950 | if ( msk_is_bitmap ) | |
951 | { a = pixel ? scale : 0; | |
952 | } else | |
953 | { XColor *c; | |
954 | int r; | |
955 | ||
956 | c = pixelToColor(img, pixel, &msk_info); | |
957 | r = intensityXColor(c); | |
958 | a = rescale(r, BRIGHT, scale); | |
959 | } | |
960 | } else | |
961 | { a = 255; | |
962 | } | |
963 | ||
964 | upix.c32[0] = b; /* blue */ | |
965 | upix.c32[1] = g; /* green */ | |
966 | upix.c32[2] = r; /* red */ | |
967 | upix.c32[3] = a; | |
968 | *p++ = upix.i32; | |
969 | } | |
970 | } | |
971 | ||
972 | return data; | |
973 | } |
0 | /* Part of XPCE --- The SWI-Prolog GUI toolkit | |
1 | ||
2 | Author: Jan Wielemaker and Anjo Anjewierden | |
3 | E-mail: J.Wielemaker@vu.nl | |
4 | WWW: http://www.swi-prolog.org/projects/xpce/ | |
5 | Copyright (c) 2013, University of Amsterdam | |
6 | VU University Amsterdam | |
7 | All rights reserved. | |
8 | ||
9 | Redistribution and use in source and binary forms, with or without | |
10 | modification, are permitted provided that the following conditions | |
11 | are met: | |
12 | ||
13 | 1. Redistributions of source code must retain the above copyright | |
14 | notice, this list of conditions and the following disclaimer. | |
15 | ||
16 | 2. Redistributions in binary form must reproduce the above copyright | |
17 | notice, this list of conditions and the following disclaimer in | |
18 | the documentation and/or other materials provided with the | |
19 | distribution. | |
20 | ||
21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
27 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
31 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
32 | POSSIBILITY OF SUCH DAMAGE. | |
33 | */ | |
34 | ||
35 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
36 | SYNOPSIS: | |
37 | xpce-copy [-v] [-c] [-m mode] from to | |
38 | xpce-copy [-v] [-c] [-m mode] [-p] file file ... dir | |
39 | ||
40 | Simple install replacement to be used for XPCE installation. The | |
41 | configure install.sh script is very slow, while all operating systems | |
42 | appear to be using different versions of install. This should solve this | |
43 | problem. | |
44 | ||
45 | This installer is also used to install the system under windows to avoid | |
46 | the limitiations and portability issues around the Windows command | |
47 | interpreter and copy command. | |
48 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
49 | ||
50 | #ifdef HAVE_CONFIG_H | |
51 | #include <config.h> | |
52 | #endif | |
53 | ||
54 | #include <stdio.h> | |
55 | #include <stdlib.h> | |
56 | #include <ctype.h> | |
57 | #include <sys/types.h> | |
58 | #include <sys/stat.h> | |
59 | #ifdef HAVE_UNISTD_H | |
60 | #include <unistd.h> | |
61 | #endif | |
62 | #include <fcntl.h> | |
63 | #include <errno.h> | |
64 | #include <time.h> | |
65 | #include <string.h> | |
66 | ||
67 | #ifndef MAXPATHLEN | |
68 | #define MAXPATHLEN 1024 | |
69 | #endif | |
70 | ||
71 | #ifndef TRUE | |
72 | #define TRUE 1 | |
73 | #define FALSE 0 | |
74 | #endif | |
75 | ||
76 | #define bool int | |
77 | #define shift (argc--, argv++) | |
78 | ||
79 | #define CPBUFSIZE 8192 | |
80 | ||
81 | #ifndef O_BINARY | |
82 | #define O_BINARY 0 | |
83 | #endif | |
84 | ||
85 | #if defined(_MSC_VER) || defined(__MINGW32__) | |
86 | #ifndef __WINDOWS__ | |
87 | #define __WINDOWS__ | |
88 | #endif | |
89 | #endif | |
90 | ||
91 | #ifdef __WINDOWS__ | |
92 | #include <io.h> /* read, write, etc */ | |
93 | #include <direct.h> /* mkdir, chdir */ | |
94 | #define IsDirSep(c) ((c) == '/' || (c) == '\\') | |
95 | #define DIRSEP '\\' | |
96 | #define mode_t unsigned short | |
97 | #else | |
98 | #define IsDirSep(c) ((c) == '/') | |
99 | #define DIRSEP '/' | |
100 | #endif | |
101 | ||
102 | /******************************* | |
103 | * SETTINGS * | |
104 | *******************************/ | |
105 | ||
106 | unsigned short mode; | |
107 | bool set_mode; | |
108 | bool copy; | |
109 | char * program; | |
110 | int verbose=0; | |
111 | bool makedirs; | |
112 | bool strippath = -1; /* i.e. use basename() */ | |
113 | bool installdirs = FALSE; /* -d */ | |
114 | bool newer_only = FALSE; | |
115 | ||
116 | static int | |
117 | get_mode(const char *s, unsigned short *m) | |
118 | { unsigned short mode = 0; | |
119 | ||
120 | while(*s >= '0' && *s <= '7') | |
121 | { mode = (mode << 3) + *s++ - '0'; | |
122 | } | |
123 | ||
124 | if ( *s ) | |
125 | return FALSE; | |
126 | ||
127 | *m = mode; | |
128 | return TRUE; | |
129 | } | |
130 | ||
131 | ||
132 | static int | |
133 | isdir(const char *path) | |
134 | { struct stat buf; | |
135 | char tmp[MAXPATHLEN]; | |
136 | char *s; | |
137 | ||
138 | strcpy(tmp, path); /* delete trailing / to work */ | |
139 | s = tmp+strlen(tmp); /* around bugs in some runtime */ | |
140 | if ( s>tmp && s[-1] == '/' ) /* libraries */ | |
141 | *--s = 0; | |
142 | ||
143 | if ( stat(tmp, &buf) < 0 || | |
144 | (buf.st_mode & S_IFMT) != S_IFDIR ) | |
145 | return FALSE; | |
146 | ||
147 | return TRUE; | |
148 | } | |
149 | ||
150 | ||
151 | static void | |
152 | get_file_mode(const char *name, int fd, mode_t *m) | |
153 | { struct stat buf; | |
154 | ||
155 | #ifdef HAVE_FSTAT | |
156 | if ( fstat(fd, &buf) == 0 ) | |
157 | #else | |
158 | if ( stat(name, &buf) == 0 ) | |
159 | #endif | |
160 | *m = buf.st_mode; | |
161 | else | |
162 | *m = 0755; /* default (hack) */ | |
163 | } | |
164 | ||
165 | ||
166 | static int | |
167 | last_modified(const char *name, time_t *t) | |
168 | { struct stat buf; | |
169 | ||
170 | if ( stat(name, &buf) == 0 ) | |
171 | { *t = buf.st_mtime; | |
172 | return 0; | |
173 | } else | |
174 | return -1; | |
175 | } | |
176 | ||
177 | ||
178 | const char * | |
179 | basename(const char *path) | |
180 | { const char *base; | |
181 | ||
182 | for(base=path; *path; path++) | |
183 | { if ( IsDirSep(*path) ) | |
184 | base = path+1; | |
185 | } | |
186 | ||
187 | return base; | |
188 | } | |
189 | ||
190 | ||
191 | char * | |
192 | dirname(const char *path) /* returns malloced directory name */ | |
193 | { const char *base = basename(path); | |
194 | char *rval; | |
195 | ||
196 | while(base > path && IsDirSep(base[-1]) ) | |
197 | base--; | |
198 | ||
199 | if ( !(rval = malloc(base-path+1)) ) | |
200 | { perror("malloc"); | |
201 | exit(1); | |
202 | } | |
203 | memcpy(rval, path, base-path); | |
204 | rval[base-path] = '\0'; | |
205 | ||
206 | return rval; | |
207 | } | |
208 | ||
209 | ||
210 | static int | |
211 | makedir(char *path) | |
212 | { again: | |
213 | ||
214 | #ifdef __WINDOWS__ | |
215 | if ( mkdir(path) == 0 ) | |
216 | #else | |
217 | if ( mkdir(path, 0777) == 0 ) | |
218 | #endif | |
219 | { free(path); | |
220 | return TRUE; | |
221 | } | |
222 | ||
223 | if ( errno == ENOENT ) | |
224 | { if ( makedir(dirname(path)) ) | |
225 | goto again; | |
226 | } | |
227 | ||
228 | free(path); | |
229 | return FALSE; | |
230 | } | |
231 | ||
232 | ||
233 | static char * | |
234 | str_store(const char *in) | |
235 | { char *rval; | |
236 | ||
237 | if ( (rval = malloc(strlen(in)+1)) ) | |
238 | { strcpy(rval, in); | |
239 | return rval; | |
240 | } | |
241 | ||
242 | perror("malloc"); | |
243 | exit(1); | |
244 | } | |
245 | ||
246 | ||
247 | static int | |
248 | install_dir(const char *name) | |
249 | { if ( !isdir(name) ) | |
250 | return makedir(str_store(name)); | |
251 | ||
252 | return TRUE; | |
253 | } | |
254 | ||
255 | ||
256 | static int | |
257 | install_file(const char *from, const char *to) | |
258 | { int fdfrom, fdto; | |
259 | char buf[CPBUFSIZE]; | |
260 | int rval; | |
261 | int n; | |
262 | mode_t m; | |
263 | ||
264 | if ( newer_only ) | |
265 | { time_t to_time; | |
266 | ||
267 | if ( last_modified(to, &to_time) == 0 ) | |
268 | { time_t from_time; | |
269 | ||
270 | if ( last_modified(from, &from_time) != 0 ) | |
271 | { perror(from); | |
272 | return FALSE; | |
273 | } | |
274 | ||
275 | if ( difftime(from_time, to_time) < 0.0 ) | |
276 | { if ( verbose >= 2 ) | |
277 | fprintf(stderr, "Skipped %s (not modified)\n", to); | |
278 | return TRUE; | |
279 | } | |
280 | } | |
281 | } | |
282 | ||
283 | if ( (fdfrom = open(from, O_RDONLY|O_BINARY)) < 0 ) | |
284 | { perror(from); | |
285 | return FALSE; | |
286 | } | |
287 | ||
288 | if ( set_mode ) | |
289 | m = mode; | |
290 | else | |
291 | get_file_mode(from, fdfrom, &m); | |
292 | ||
293 | unlink(to); | |
294 | again: | |
295 | if ( (fdto = open(to, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, m)) < 0 ) | |
296 | { if ( errno == ENOENT && makedir(dirname(to)) ) | |
297 | goto again; | |
298 | perror(to); | |
299 | close(fdfrom); | |
300 | return FALSE; | |
301 | } | |
302 | ||
303 | while( (n = read(fdfrom, buf, CPBUFSIZE)) > 0 ) | |
304 | { char *b = buf; | |
305 | ||
306 | while(n > 0) | |
307 | { int n2; | |
308 | ||
309 | if ( (n2=write(fdto, b, n)) < 0 ) | |
310 | { perror(to); | |
311 | rval = FALSE; | |
312 | goto out; | |
313 | } | |
314 | b += n2; | |
315 | n -= n2; | |
316 | } | |
317 | } | |
318 | if ( n < 0 ) | |
319 | { perror(from); | |
320 | rval = FALSE; | |
321 | } else | |
322 | rval = TRUE; | |
323 | ||
324 | out: | |
325 | close(fdfrom); | |
326 | close(fdto); | |
327 | ||
328 | return rval; | |
329 | } | |
330 | ||
331 | ||
332 | const char * | |
333 | strip_path(const char *path, int strip) | |
334 | { if ( strip < 0 ) | |
335 | return basename(path); | |
336 | else | |
337 | { const char *base = path; | |
338 | ||
339 | while(strip-- > 0) | |
340 | { while( IsDirSep(*base) ) | |
341 | base++; | |
342 | while( *base && !IsDirSep(*base) ) | |
343 | base++; | |
344 | while( IsDirSep(*base) ) | |
345 | base++; | |
346 | } | |
347 | ||
348 | return base; | |
349 | } | |
350 | } | |
351 | ||
352 | ||
353 | static int | |
354 | install_file_in_dir(const char *file, const char *dir) | |
355 | { char path[MAXPATHLEN]; | |
356 | const char *base = strip_path(file, strippath); | |
357 | int rval; | |
358 | ||
359 | sprintf(path, "%s%c%s", dir, DIRSEP, base); | |
360 | ||
361 | if ( (rval = install_file(file, path)) && verbose ) | |
362 | printf("%s\n", base); | |
363 | ||
364 | return rval; | |
365 | } | |
366 | ||
367 | /******************************* | |
368 | * IGNORE * | |
369 | *******************************/ | |
370 | ||
371 | #define MAXLINE 1024 | |
372 | #define EOS '\0' | |
373 | ||
374 | int compilePattern(const char *p); | |
375 | int matchPattern(const char *s); | |
376 | ||
377 | typedef struct icell *Icell; | |
378 | ||
379 | struct icell | |
380 | { char *pattern; | |
381 | Icell next; | |
382 | }; | |
383 | ||
384 | typedef struct | |
385 | { Icell head; | |
386 | Icell tail; | |
387 | } ilist, *Ilist; | |
388 | ||
389 | ilist _ignore_patterns; | |
390 | Ilist ignore_patterns = &_ignore_patterns; | |
391 | ||
392 | void | |
393 | to_ignore_list(Ilist ign, const char *pattern) | |
394 | { char *p = str_store(pattern); | |
395 | Icell c = malloc(sizeof(struct icell)); | |
396 | ||
397 | c->pattern = p; | |
398 | c->next = NULL; | |
399 | if ( ign->tail ) | |
400 | { ign->tail->next = c; | |
401 | ign->tail = c; | |
402 | } else | |
403 | { ign->head = ign->tail = c; | |
404 | } | |
405 | } | |
406 | ||
407 | ||
408 | int | |
409 | ignore(Ilist ign, const char *name) | |
410 | { Icell c; | |
411 | ||
412 | for(c = ignore_patterns->head; c; c=c->next) | |
413 | { compilePattern(c->pattern); | |
414 | if ( matchPattern(name) ) | |
415 | return TRUE; | |
416 | } | |
417 | for(c = ign->head; c; c=c->next) | |
418 | { compilePattern(c->pattern); | |
419 | if ( matchPattern(name) ) | |
420 | return TRUE; | |
421 | } | |
422 | ||
423 | return FALSE; | |
424 | } | |
425 | ||
426 | ||
427 | static void | |
428 | ignoreForDir(Ilist l, char *d) | |
429 | { char n[MAXPATHLEN]; | |
430 | FILE *fd; | |
431 | ||
432 | sprintf(n, "%s%c.cvsignore", d, DIRSEP); | |
433 | if ( (fd = fopen(n, "r")) ) | |
434 | { char p[MAXLINE]; | |
435 | ||
436 | while( fgets(p, sizeof(p), fd) ) | |
437 | { char *s = p; | |
438 | int len; | |
439 | ||
440 | while(*s && *s < ' ') | |
441 | s++; | |
442 | len = strlen(s); | |
443 | ||
444 | while( len > 0 && s[len-1] < ' ' ) | |
445 | len--; | |
446 | s[len] = EOS; | |
447 | ||
448 | if ( len > 0 ) | |
449 | { if ( verbose ) | |
450 | printf("ignore %s in %s\n", s, d); | |
451 | to_ignore_list(l, s); | |
452 | } | |
453 | } | |
454 | ||
455 | fclose(fd); | |
456 | } | |
457 | } | |
458 | ||
459 | ||
460 | /******************************* | |
461 | * WILDCHART MATCH * | |
462 | *******************************/ | |
463 | ||
464 | #define succeed return(TRUE); | |
465 | #define fail return(FALSE); | |
466 | #ifndef uchar | |
467 | #define uchar unsigned char | |
468 | #endif | |
469 | ||
470 | #define MAXCODE 512 | |
471 | ||
472 | #define ANY 128 | |
473 | #define STAR 129 | |
474 | #define ALT 130 | |
475 | #define JMP 131 | |
476 | #define ANYOF 132 | |
477 | #define EXIT 133 | |
478 | ||
479 | #define NOCURL 0 | |
480 | #define CURL 1 | |
481 | ||
482 | #define warning(text) \ | |
483 | (fprintf(stderr, "%s: bad pattern: %s\n", program, text), \ | |
484 | exit(0)) | |
485 | ||
486 | #define Output(c) { if ( Out->size > MAXCODE-1 ) \ | |
487 | { warning("pattern too large"); \ | |
488 | return (char *) NULL; \ | |
489 | } \ | |
490 | Out->code[Out->size++] = c; \ | |
491 | } | |
492 | #define setMap(c) { map[(c)/8] |= 1 << ((c) % 8); } | |
493 | ||
494 | static struct _pattern_buffer | |
495 | { int size; | |
496 | uchar code[MAXCODE]; | |
497 | } default_pattern_buffer; | |
498 | ||
499 | static char *compile_pattern(struct _pattern_buffer*, const char *, int); | |
500 | static int match_pattern(uchar *, const char *); | |
501 | ||
502 | int | |
503 | compilePattern(const char *p) | |
504 | { default_pattern_buffer.size = 0; | |
505 | if ( compile_pattern(&default_pattern_buffer, p, NOCURL) == (char *) NULL ) | |
506 | fail; | |
507 | ||
508 | succeed; | |
509 | } | |
510 | ||
511 | ||
512 | static char * | |
513 | compile_pattern(struct _pattern_buffer *Out, const char *p, int curl) | |
514 | { char c; | |
515 | ||
516 | for(;;) | |
517 | { switch(c = *p++) | |
518 | { case EOS: | |
519 | break; | |
520 | case '\\': | |
521 | Output(*p == EOS ? '\\' : (*p & 0x7f)); | |
522 | if (*p == EOS ) | |
523 | break; | |
524 | p++; | |
525 | continue; | |
526 | case '?': | |
527 | Output(ANY); | |
528 | continue; | |
529 | case '*': | |
530 | Output(STAR); | |
531 | continue; | |
532 | case '[': | |
533 | { uchar *map; | |
534 | int n; | |
535 | ||
536 | Output(ANYOF); | |
537 | map = &Out->code[Out->size]; | |
538 | Out->size += 16; | |
539 | if ( Out->size >= MAXCODE ) | |
540 | { warning("Pattern too long"); | |
541 | return (char *) NULL; | |
542 | } | |
543 | ||
544 | for( n=0; n < 16; n++) | |
545 | map[n] = 0; | |
546 | ||
547 | for(;;) | |
548 | { switch( c = *p++ ) | |
549 | { case '\\': | |
550 | if ( *p == EOS ) | |
551 | { warning("Unmatched '['"); | |
552 | return (char *)NULL; | |
553 | } | |
554 | setMap(*p); | |
555 | p++; | |
556 | continue; | |
557 | case ']': | |
558 | break; | |
559 | default: | |
560 | if ( p[-1] != ']' && p[0] == '-' && p[1] != ']' ) | |
561 | { register int chr; | |
562 | ||
563 | for ( chr=p[-1]; chr <= p[1]; chr++ ) | |
564 | setMap(chr); | |
565 | p += 2; | |
566 | } else | |
567 | setMap(c); | |
568 | continue; | |
569 | } | |
570 | break; | |
571 | } | |
572 | ||
573 | continue; | |
574 | } | |
575 | case '{': | |
576 | { int ai, aj = -1; | |
577 | ||
578 | for(;;) | |
579 | { Output(ALT); ai = Out->size; Output(0); | |
580 | if ( (p = compile_pattern(Out, p, CURL)) == (char *) NULL ) | |
581 | return (char *) NULL; | |
582 | if ( aj > 0 ) | |
583 | Out->code[aj] = Out->size - aj; | |
584 | if ( *p == ',' ) | |
585 | { Output(JMP); aj = Out->size; Output(0); | |
586 | Out->code[ai] = Out->size - ai; | |
587 | Output(ALT); ai = Out->size; Output(0); | |
588 | p++; | |
589 | } else if ( *p == '}' ) | |
590 | { p++; | |
591 | break; | |
592 | } else | |
593 | { warning("Unmatched '{'"); | |
594 | return (char *) NULL; | |
595 | } | |
596 | } | |
597 | ||
598 | continue; | |
599 | } | |
600 | case '}': | |
601 | case ',': | |
602 | if ( curl == CURL ) | |
603 | { p--; | |
604 | return (char *)p; | |
605 | } | |
606 | /*FALLTHROUGH*/ | |
607 | default: | |
608 | Output(c & 0x7f); | |
609 | continue; | |
610 | } | |
611 | ||
612 | Output(EXIT); | |
613 | return (char *)p; | |
614 | } | |
615 | } | |
616 | ||
617 | ||
618 | int | |
619 | matchPattern(const char *s) | |
620 | { return match_pattern(default_pattern_buffer.code, s); | |
621 | } | |
622 | ||
623 | ||
624 | static int | |
625 | match_pattern(uchar *p, const char *s) | |
626 | { uchar c; | |
627 | ||
628 | for(;;) | |
629 | { switch( c = *p++ ) | |
630 | { case EXIT: | |
631 | return (*s == EOS ? TRUE : FALSE); | |
632 | case ANY: /* ? */ | |
633 | if ( *s == EOS ) | |
634 | fail; | |
635 | s++; | |
636 | continue; | |
637 | case ANYOF: /* [...] */ | |
638 | if ( p[*s / 8] & (1 << (*s % 8)) ) | |
639 | { p += 16; | |
640 | s++; | |
641 | continue; | |
642 | } | |
643 | fail; | |
644 | case STAR: /* * */ | |
645 | do | |
646 | { if ( match_pattern(p, s) ) | |
647 | succeed; | |
648 | } while( *s++ ); | |
649 | fail; | |
650 | case JMP: /* { ... } */ | |
651 | p += *p; | |
652 | continue; | |
653 | case ALT: | |
654 | if ( match_pattern(p+1, s) ) | |
655 | succeed; | |
656 | p += *p; | |
657 | continue; | |
658 | default: /* character */ | |
659 | if ( c != (uchar) *s ) | |
660 | fail; | |
661 | s++; | |
662 | continue; | |
663 | } | |
664 | } | |
665 | } | |
666 | ||
667 | /******************************* | |
668 | * MAIN * | |
669 | *******************************/ | |
670 | ||
671 | void | |
672 | usage() | |
673 | { fprintf(stderr, " Usage: %s options file ... directory\n", program); | |
674 | fprintf(stderr, " or: %s options from to\n", program); | |
675 | fprintf(stderr, " or: %s [-C dir] -d dir ...\n", program); | |
676 | fprintf(stderr, "options: [-v[N]] [-n] [-c] [-p[N]] [-C dir] [-m mode]\n"); | |
677 | exit(1); | |
678 | } | |
679 | ||
680 | ||
681 | int | |
682 | main(int argc, char **argv) | |
683 | { char *out; | |
684 | int errors = 0; | |
685 | ||
686 | program = argv[0]; | |
687 | shift; | |
688 | while(argc > 0 && argv[0][0] == '-') | |
689 | { char *opts = &argv[0][1]; | |
690 | ||
691 | shift; | |
692 | for( ; *opts; opts++ ) | |
693 | { switch( *opts ) | |
694 | { case 'c': | |
695 | copy = TRUE; | |
696 | break; | |
697 | case 'p': | |
698 | strippath = 0; | |
699 | makedirs = TRUE; | |
700 | if ( isdigit(opts[1]&0xff) ) | |
701 | { opts++; | |
702 | strippath = *opts - '0'; | |
703 | } | |
704 | break; | |
705 | case 'd': | |
706 | installdirs = TRUE; | |
707 | break; | |
708 | case 'n': | |
709 | newer_only = TRUE; | |
710 | break; | |
711 | case 'v': | |
712 | verbose++; | |
713 | if ( isdigit(opts[1]&0xff) ) | |
714 | { opts++; | |
715 | verbose = *opts - '0'; | |
716 | } | |
717 | break; | |
718 | case 'C': | |
719 | { char *dir = argv[0]; | |
720 | ||
721 | shift; | |
722 | if ( chdir(dir) != 0 ) | |
723 | { perror(dir); | |
724 | exit(1); | |
725 | } | |
726 | break; | |
727 | } | |
728 | case 'm': | |
729 | if ( argc > 0 && get_mode(argv[0], &mode) ) | |
730 | { shift; | |
731 | set_mode = TRUE; | |
732 | } | |
733 | break; | |
734 | default: | |
735 | usage(); | |
736 | } | |
737 | } | |
738 | } | |
739 | ||
740 | if ( argc == 0 ) | |
741 | usage(); | |
742 | out = argv[argc-1]; | |
743 | ||
744 | if ( installdirs ) | |
745 | { int i; | |
746 | ||
747 | for(i=0; i<argc; i++) | |
748 | { if ( !install_dir(argv[i]) ) | |
749 | errors++; | |
750 | } | |
751 | } else | |
752 | { if ( isdir(out) ) | |
753 | { int i; | |
754 | ||
755 | to_ignore_list(ignore_patterns, "*~"); | |
756 | to_ignore_list(ignore_patterns, "*.bak"); | |
757 | to_ignore_list(ignore_patterns, "*.old"); | |
758 | to_ignore_list(ignore_patterns, ".cvsignore"); | |
759 | to_ignore_list(ignore_patterns, "CVS"); | |
760 | ignoreForDir(ignore_patterns, out); | |
761 | ||
762 | for(i=0; i<argc-1; i++) | |
763 | { if ( ignore(ignore_patterns, argv[i]) ) | |
764 | continue; | |
765 | ||
766 | if ( isdir(argv[i]) ) | |
767 | { if ( verbose ) | |
768 | fprintf(stderr, "Skipping directory %s\n", argv[i]); | |
769 | continue; | |
770 | } | |
771 | ||
772 | if ( !install_file_in_dir(argv[i], out) ) | |
773 | errors++; | |
774 | } | |
775 | } else | |
776 | { if ( !install_file(argv[0], out) ) | |
777 | errors++; | |
778 | } | |
779 | } | |
780 | ||
781 | return errors ? 1 : 0; | |
782 | } |
93 | 93 | build_PPAs() |
94 | 94 | { git branch -D ppa || true |
95 | 95 | git checkout -b ppa |
96 | for distro in xenial bionic disco eoan; do | |
96 | for distro in xenial bionic disco eoan focal; do | |
97 | 97 | ./scripts/make-ppa --distro=$distro --push |
98 | 98 | done |
99 | 99 | git checkout master |
101 | 101 | } |
102 | 102 | |
103 | 103 | build() |
104 | { build_pdf | |
105 | build_win32 | |
106 | build_win64 | |
107 | build_source | |
108 | build_PPAs | |
104 | { if [ $(uname) = Darwin ]; then | |
105 | build_macosx_gcc | |
106 | else | |
107 | build_pdf | |
108 | build_win32 | |
109 | build_win64 | |
110 | build_source | |
111 | build_PPAs | |
112 | fi | |
109 | 113 | } |
110 | 114 | |
111 | 115 | ################ |
126 | 130 | } |
127 | 131 | |
128 | 132 | upload_macosx() |
129 | { upload_file bin build.macosx/swipl-${version}-1.x86_64.dmg | |
133 | { if [ -f build.macosx-gcc/swipl-${version}-1.x86_64.dmg ]; then | |
134 | echo "Uploading fast GCC version" | |
135 | upload_file bin build.macosx-gcc/swipl-${version}-1.x86_64.dmg | |
136 | else | |
137 | echo "WARNING: uploading slow Clang version" | |
138 | upload_file bin build.macosx/swipl-${version}-1.x86_64.dmg | |
139 | fi | |
130 | 140 | } |
131 | 141 | |
132 | 142 | upload_pdf() |
7 | 7 | PL_VERSION=`cat VERSION` |
8 | 8 | VTAG=HEAD |
9 | 9 | TARGET_DISTRO=none |
10 | distros="xenial bionic disco eoan" | |
10 | distros="xenial bionic disco eoan focal" | |
11 | 11 | build=true |
12 | 12 | buildbin=false |
13 | 13 | push=false |
88 | 88 | - libxt6 |
89 | 89 | - odbc-postgresql |
90 | 90 | - tdsodbc |
91 | - libtcmalloc-minimal4 | |
91 | 92 | - unixodbc |
92 | 93 | build-packages: |
93 | 94 | - libarchive-dev |
114 | 115 | - zlib1g-dev |
115 | 116 | - libyaml-dev |
116 | 117 | - libglvnd-dev |
118 | - libgoogle-perftools-dev |
7 | 7 | # This file is processed using defatom, compiled from defatom.c to |
8 | 8 | # produce pl-atom.ic, pl-atom.ih, pl-funct.ic and pl-funct.ih. |
9 | 9 | |
10 | A abi "abi" | |
10 | 11 | A abort "abort" |
11 | 12 | A aborted "$aborted" |
12 | 13 | A abs "abs" |
91 | 92 | A btree "btree" |
92 | 93 | A buffer "buffer" |
93 | 94 | A buffer_size "buffer_size" |
95 | A built_in "built_in" | |
94 | 96 | A built_in_procedure "built_in_procedure" |
95 | 97 | A busy "busy" |
96 | 98 | A byte "byte" |
321 | 323 | A floor "floor" |
322 | 324 | A force "force" |
323 | 325 | A foreign "foreign" |
326 | A foreign_interface "foreign_interface" | |
324 | 327 | A foreign_function "$foreign_function" |
325 | 328 | A foreign_return_value "foreign_return_value" |
326 | 329 | A fork "fork" |
619 | 622 | A prove ":-" |
620 | 623 | A public "public" |
621 | 624 | A punct "punct" |
625 | A qlf "qlf" | |
626 | A qlf_min_load "qlf_min_load" | |
622 | 627 | A quasi_quotation "quasi_quotation" |
623 | 628 | A quasi_quotation_position "quasi_quotation_position" |
624 | 629 | A quasi_quotation_syntax "quasi_quotation_syntax" |
136 | 136 | sandbox.pl prolog_format.pl prolog_install.pl check_installation.pl |
137 | 137 | solution_sequences.pl iostream.pl dicts.pl yall.pl tabling.pl |
138 | 138 | lazy_lists.pl prolog_jiti.pl zip.pl obfuscate.pl wfs.pl |
139 | prolog_wrap.pl prolog_trace.pl prolog_code.pl intercept.pl) | |
139 | prolog_wrap.pl prolog_trace.pl prolog_code.pl intercept.pl | |
140 | prolog_deps.pl) | |
140 | 141 | if(INSTALL_DOCUMENTATION) |
141 | 142 | set(SWIPL_DATA_library ${SWIPL_DATA_library} help.pl) |
142 | 143 | endif() |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2008-2017, University of Amsterdam | |
5 | Copyright (c) 2008-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | All rights reserved. |
8 | 8 | |
67 | 67 | /* PLVERSION_TAG: a string, normally "", but for example "rc1" */ |
68 | 68 | |
69 | 69 | #ifndef PLVERSION |
70 | #define PLVERSION 80129 | |
70 | #define PLVERSION 80130 | |
71 | 71 | #endif |
72 | 72 | #ifndef PLVERSION_TAG |
73 | 73 | #define PLVERSION_TAG "" |
74 | 74 | #endif |
75 | ||
76 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
77 | This number is incremented when the SWI-Prolog PL_*() functions or one | |
78 | of the data types is modified such that old binary extensions cannot run | |
79 | reliably with the current version. This version is introduced in | |
80 | SWI-Prolog 8.1.30. The most recent violation of compatibility was | |
81 | between versions 8.1.21 and 8.1.22 with the introduction of rational | |
82 | numbers are atomic type. | |
83 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
84 | ||
85 | #define PL_FLI_VERSION 2 /* PL_*() functions */ | |
86 | #define PL_REC_VERSION 3 /* PL_record_external(), fastrw */ | |
87 | #define PL_QLF_LOADVERSION 67 /* load all versions later >= X */ | |
88 | #define PL_QLF_VERSION 67 /* save version number */ | |
75 | 89 | |
76 | 90 | |
77 | 91 | /******************************* |
190 | 204 | size_t arity; |
191 | 205 | } t; |
192 | 206 | } term_value_t; |
207 | ||
193 | 208 | |
194 | 209 | #ifndef TRUE |
195 | 210 | #define TRUE (1) |
484 | 499 | PL_EXPORT(int) PL_get_module(term_t t, module_t *module) WUNUSED; |
485 | 500 | PL_EXPORT(int) PL_get_arg_sz(size_t index, term_t t, term_t a) WUNUSED; |
486 | 501 | PL_EXPORT(int) PL_get_arg(int index, term_t t, term_t a) WUNUSED; |
502 | PL_EXPORT(int) PL_get_dict_key(atom_t key, term_t dict, term_t value); | |
487 | 503 | PL_EXPORT(int) PL_get_list(term_t l, term_t h, term_t t) WUNUSED; |
488 | 504 | PL_EXPORT(int) PL_get_head(term_t l, term_t h) WUNUSED; |
489 | 505 | PL_EXPORT(int) PL_get_tail(term_t l, term_t t) WUNUSED; |
504 | 520 | PL_EXPORT(int) PL_is_callable(term_t t); |
505 | 521 | PL_EXPORT(int) PL_is_functor(term_t t, functor_t f); |
506 | 522 | PL_EXPORT(int) PL_is_list(term_t t); |
523 | PL_EXPORT(int) PL_is_dict(term_t t); | |
507 | 524 | PL_EXPORT(int) PL_is_pair(term_t t); |
508 | 525 | PL_EXPORT(int) PL_is_atomic(term_t t); |
509 | 526 | PL_EXPORT(int) PL_is_number(term_t t); |
530 | 547 | PL_EXPORT(int) PL_put_list(term_t l) WUNUSED; |
531 | 548 | PL_EXPORT(int) PL_put_nil(term_t l); |
532 | 549 | PL_EXPORT(int) PL_put_term(term_t t1, term_t t2); |
550 | PL_EXPORT(int) PL_put_dict(term_t t, atom_t tag, size_t len, | |
551 | const atom_t *keys, term_t values); | |
533 | 552 | |
534 | 553 | /* construct a functor or list-cell */ |
535 | 554 | PL_EXPORT(int) PL_cons_functor(term_t h, functor_t f, ...) WUNUSED; |
837 | 856 | #define CVT_EXCEPTION 0x00001000 /* throw exception on error */ |
838 | 857 | #define CVT_VARNOFAIL 0x00002000 /* return 2 if argument is unbound */ |
839 | 858 | |
840 | #define BUF_DISCARDABLE 0x00000000 | |
841 | #define BUF_RING 0x00010000 | |
842 | #define BUF_MALLOC 0x00020000 | |
843 | #define BUF_ALLOW_STACK 0x00040000 /* allow pointer into (global) stack */ | |
859 | #define BUF_DISCARDABLE 0x00000000 /* Store in single thread-local buffer */ | |
860 | #define BUF_RING 0x00010000 /* Store in ring of 16 buffers */ | |
861 | #define BUF_MALLOC 0x00020000 /* Store using PL_malloc() */ | |
862 | #define BUF_ALLOW_STACK 0x00040000 /* Allow pointer into (global) stack */ | |
863 | #define BUF_NORING 0x00080000 /* Do not store in ring */ | |
844 | 864 | |
845 | 865 | |
846 | 866 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
1085 | 1105 | PL_EXPORT(int) PL_current_prolog_flag(atom_t name, int type, void *ptr); |
1086 | 1106 | |
1087 | 1107 | |
1108 | /******************************* | |
1109 | * VERSIONS * | |
1110 | *******************************/ | |
1111 | ||
1112 | #define PL_VERSION_SYSTEM 1 /* Prolog version */ | |
1113 | #define PL_VERSION_FLI 2 /* PL_* compatibility */ | |
1114 | #define PL_VERSION_REC 3 /* PL_record_external() compatibility */ | |
1115 | #define PL_VERSION_QLF 4 /* Saved QLF format version */ | |
1116 | #define PL_VERSION_QLF_LOAD 5 /* Min loadable QLF format version */ | |
1117 | #define PL_VERSION_VM 6 /* VM signature */ | |
1118 | #define PL_VERSION_BUILT_IN 7 /* Built-in predicate signature */ | |
1119 | ||
1120 | PL_EXPORT(unsigned int) PL_version(int which); | |
1121 | ||
1122 | ||
1088 | 1123 | /******************************** |
1089 | 1124 | * QUERY PROLOG * |
1090 | 1125 | *********************************/ |
0 | % Author: Bart Demoen K.U.Leuven | |
1 | % Date: Oct 21 1996 | |
2 | ||
3 | makeground([]) . | |
4 | makeground([X|R]) :- mkgr(X) , makeground(R) . | |
5 | ||
6 | mkgr(X) :- var(X) , ! , (X = g ; X = i ; X = v) . | |
7 | mkgr(_) . | |
8 | ||
9 | mymember(X,[Y|R]) :- mm(X,R,Y) . | |
10 | mm(X,_,X) . | |
11 | mm(X,[Y|R],_) :- mm(X,R,Y) . | |
12 | ||
13 | :- table(compute1/4) . | |
14 | ||
15 | compute(Vars,DRs,Mal,DR) :- compute1(Vars,DRs,Mal,DR), fail . | |
16 | compute(Vars,DRs,Mal,DR) :- compute1(Vars,DRs,Mal,DR). | |
17 | ||
18 | compute1(Vars,DRs,Mal,DR) :- | |
19 | findall(Mal,(lookup(Vars,DRs),makeground(Mal)),All), | |
20 | sort(All,DR) . | |
21 | ||
22 | lookup([],[]) . | |
23 | lookup([V|VarList],[DR|DRList]) :- mymember(V,DR) , lookup(VarList,DRList) . | |
24 | ||
25 | fail_iff_0([],_) :- fail . | |
26 | ||
27 | iffequal_2([_,_],[[g,g],[i,i],[v,v]]) . | |
28 | ||
29 | iff_1([_],[[g]]) . | |
30 | ||
31 | iff_2([_,_], | |
32 | [[g,g], | |
33 | [i,i], | |
34 | [i,v]]) . | |
35 | ||
36 | iff_3([_,_,_], | |
37 | [[g,g,g], | |
38 | [i,g,i], | |
39 | [i,g,v], | |
40 | [i,i,g], | |
41 | [i,i,i], | |
42 | [i,i,v], | |
43 | [i,v,g], | |
44 | [i,v,i], | |
45 | [i,v,v]]) . | |
46 | ||
47 | iff_4([_,_,_,_], | |
48 | [[g,g,g,g], | |
49 | [i,g,g,i], | |
50 | [i,g,g,v], | |
51 | [i,g,i,g], | |
52 | [i,g,i,i], | |
53 | [i,g,i,v], | |
54 | [i,g,v,g]|R]) :- r4_1(R) . | |
55 | r4_1([ | |
56 | [i,g,v,i], | |
57 | [i,g,v,v], | |
58 | [i,i,g,g], | |
59 | [i,i,g,i], | |
60 | [i,i,g,v], | |
61 | [i,i,i,g], | |
62 | [i,i,i,i], | |
63 | [i,i,i,v], | |
64 | [i,i,v,g], | |
65 | [i,i,v,i], | |
66 | [i,i,v,v]|R]) :- r4_2(R) . | |
67 | r4_2([ | |
68 | [i,v,g,g], | |
69 | [i,v,g,i], | |
70 | [i,v,g,v], | |
71 | [i,v,i,g], | |
72 | [i,v,i,i], | |
73 | [i,v,i,v], | |
74 | [i,v,v,g], | |
75 | [i,v,v,i], | |
76 | [i,v,v,v]]) . | |
77 | ||
78 | ||
79 | iff_5([_,_,_,_,_], | |
80 | [[g,g,g,g,g], | |
81 | [i,g,g,g,i], | |
82 | [i,g,g,g,v], | |
83 | [i,g,g,i,g], | |
84 | [i,g,g,i,i], | |
85 | [i,g,g,i,v], | |
86 | [i,g,g,v,g], | |
87 | [i,g,g,v,i], | |
88 | [i,g,g,v,v], | |
89 | [i,g,i,g,g]|R]) :- r5_1(R) . | |
90 | r5_1([ | |
91 | [i,g,i,g,i], | |
92 | [i,g,i,g,v], | |
93 | [i,g,i,i,g], | |
94 | [i,g,i,i,i], | |
95 | [i,g,i,i,v], | |
96 | [i,g,i,v,g], | |
97 | [i,g,i,v,i], | |
98 | [i,g,i,v,v], | |
99 | [i,g,v,g,g], | |
100 | [i,g,v,g,i]|R]) :- r5_2(R) . | |
101 | r5_2([ | |
102 | [i,g,v,g,v], | |
103 | [i,g,v,i,g], | |
104 | [i,g,v,i,i], | |
105 | [i,g,v,i,v], | |
106 | [i,g,v,v,g], | |
107 | [i,g,v,v,i], | |
108 | [i,g,v,v,v], | |
109 | [i,i,g,g,g], | |
110 | [i,i,g,g,i]|R]) :- r5_3(R) . | |
111 | r5_3([ | |
112 | [i,i,g,g,v], | |
113 | [i,i,g,i,g], | |
114 | [i,i,g,i,i], | |
115 | [i,i,g,i,v], | |
116 | [i,i,g,v,g], | |
117 | [i,i,g,v,i], | |
118 | [i,i,g,v,v], | |
119 | [i,i,i,g,g], | |
120 | [i,i,i,g,i]|R]) :- r5_4(R) . | |
121 | r5_4([ | |
122 | [i,i,i,g,v], | |
123 | [i,i,i,i,g], | |
124 | [i,i,i,i,i], | |
125 | [i,i,i,i,v], | |
126 | [i,i,i,v,g], | |
127 | [i,i,i,v,i], | |
128 | [i,i,i,v,v], | |
129 | [i,i,v,g,g], | |
130 | [i,i,v,g,i]|R]) :- r5_5(R) . | |
131 | r5_5([ | |
132 | [i,i,v,g,v], | |
133 | [i,i,v,i,g], | |
134 | [i,i,v,i,i], | |
135 | [i,i,v,i,v], | |
136 | [i,i,v,v,g], | |
137 | [i,i,v,v,i], | |
138 | [i,i,v,v,v], | |
139 | [i,v,g,g,g], | |
140 | [i,v,g,g,i]|R]) :- r5_6(R) . | |
141 | r5_6([ | |
142 | [i,v,g,g,v], | |
143 | [i,v,g,i,g], | |
144 | [i,v,g,i,i], | |
145 | [i,v,g,i,v], | |
146 | [i,v,g,v,g], | |
147 | [i,v,g,v,i], | |
148 | [i,v,g,v,v], | |
149 | [i,v,i,g,g], | |
150 | [i,v,i,g,i]|R]) :- r5_7(R) . | |
151 | r5_7([ | |
152 | [i,v,i,g,v], | |
153 | [i,v,i,i,g], | |
154 | [i,v,i,i,i], | |
155 | [i,v,i,i,v], | |
156 | [i,v,i,v,g], | |
157 | [i,v,i,v,i], | |
158 | [i,v,i,v,v], | |
159 | [i,v,v,g,g]|R]) :- r5_8(R) . | |
160 | r5_8([ | |
161 | [i,v,v,g,i], | |
162 | [i,v,v,g,v], | |
163 | [i,v,v,i,g], | |
164 | [i,v,v,i,i], | |
165 | [i,v,v,i,v], | |
166 | [i,v,v,v,g], | |
167 | [i,v,v,v,i], | |
168 | [i,v,v,v,v]]) . | |
169 | ||
170 | iff_6([_,_,_,_,_,_], | |
171 | [[g,g,g,g,g,g], | |
172 | [i,g,g,g,g,i], | |
173 | [i,g,g,g,g,v], | |
174 | [i,g,g,g,i,g], | |
175 | [i,g,g,g,i,i]|R]) :- r6_1(R) . | |
176 | r6_1([ | |
177 | [i,g,g,g,i,v], | |
178 | [i,g,g,g,v,g], | |
179 | [i,g,g,g,v,i], | |
180 | [i,g,g,g,v,v], | |
181 | [i,g,g,i,g,g], | |
182 | [i,g,g,i,g,i]|R]) :- r6_2(R) . | |
183 | r6_2([ | |
184 | [i,g,g,i,g,v], | |
185 | [i,g,g,i,i,g], | |
186 | [i,g,g,i,i,i], | |
187 | [i,g,g,i,i,v], | |
188 | [i,g,g,i,v,g], | |
189 | [i,g,g,i,v,i], | |
190 | [i,g,g,i,v,v]|R]) :- r6_3(R) . | |
191 | r6_3([ | |
192 | [i,g,g,v,g,g], | |
193 | [i,g,g,v,g,i], | |
194 | [i,g,g,v,g,v], | |
195 | [i,g,g,v,i,g], | |
196 | [i,g,g,v,i,i], | |
197 | [i,g,g,v,i,v], | |
198 | [i,g,g,v,v,g], | |
199 | [i,g,g,v,v,i]|R]) :- r6_4(R) . | |
200 | r6_4([ | |
201 | [i,g,g,v,v,v], | |
202 | [i,g,i,g,g,g], | |
203 | [i,g,i,g,g,i], | |
204 | [i,g,i,g,g,v], | |
205 | [i,g,i,g,i,g], | |
206 | [i,g,i,g,i,i], | |
207 | [i,g,i,g,i,v], | |
208 | [i,g,i,g,v,g]|R]) :- r6_5(R) . | |
209 | r6_5([ | |
210 | [i,g,i,g,v,i], | |
211 | [i,g,i,g,v,v], | |
212 | [i,g,i,i,g,g], | |
213 | [i,g,i,i,g,i], | |
214 | [i,g,i,i,g,v], | |
215 | [i,g,i,i,i,g], | |
216 | [i,g,i,i,i,i], | |
217 | [i,g,i,i,i,v], | |
218 | [i,g,i,i,v,g]|R]) :- r6_6(R) . | |
219 | r6_6([ | |
220 | [i,g,i,i,v,i], | |
221 | [i,g,i,i,v,v], | |
222 | [i,g,i,v,g,g], | |
223 | [i,g,i,v,g,i], | |
224 | [i,g,i,v,g,v], | |
225 | [i,g,i,v,i,g], | |
226 | [i,g,i,v,i,i], | |
227 | [i,g,i,v,i,v]|R]) :- r6_7(R) . | |
228 | r6_7([ | |
229 | [i,g,i,v,v,g], | |
230 | [i,g,i,v,v,i], | |
231 | [i,g,i,v,v,v], | |
232 | [i,g,v,g,g,g], | |
233 | [i,g,v,g,g,i], | |
234 | [i,g,v,g,g,v], | |
235 | [i,g,v,g,i,g]|R]) :- r6_8(R) . | |
236 | r6_8([ | |
237 | [i,g,v,g,i,i], | |
238 | [i,g,v,g,i,v], | |
239 | [i,g,v,g,v,g], | |
240 | [i,g,v,g,v,i], | |
241 | [i,g,v,g,v,v], | |
242 | [i,g,v,i,g,g]|R]) :- r6_9(R) . | |
243 | r6_9([ | |
244 | [i,g,v,i,g,i], | |
245 | [i,g,v,i,g,v], | |
246 | [i,g,v,i,i,g], | |
247 | [i,g,v,i,i,i], | |
248 | [i,g,v,i,i,v], | |
249 | [i,g,v,i,v,g], | |
250 | [i,g,v,i,v,i]|R]) :- r6_10(R) . | |
251 | r6_10([ | |
252 | [i,g,v,i,v,v], | |
253 | [i,g,v,v,g,g], | |
254 | [i,g,v,v,g,i], | |
255 | [i,g,v,v,g,v], | |
256 | [i,g,v,v,i,g], | |
257 | [i,g,v,v,i,i], | |
258 | [i,g,v,v,i,v]|R]) :- r6_11(R) . | |
259 | r6_11([ | |
260 | [i,g,v,v,v,g], | |
261 | [i,g,v,v,v,i], | |
262 | [i,g,v,v,v,v], | |
263 | [i,i,g,g,g,g], | |
264 | [i,i,g,g,g,i], | |
265 | [i,i,g,g,g,v], | |
266 | [i,i,g,g,i,g], | |
267 | [i,i,g,g,i,i]|R]) :- r6_12(R) . | |
268 | r6_12([ | |
269 | [i,i,g,g,i,v], | |
270 | [i,i,g,g,v,g], | |
271 | [i,i,g,g,v,i], | |
272 | [i,i,g,g,v,v], | |
273 | [i,i,g,i,g,g], | |
274 | [i,i,g,i,g,i], | |
275 | [i,i,g,i,g,v]|R]) :- r6_13(R) . | |
276 | r6_13([ | |
277 | [i,i,g,i,i,g], | |
278 | [i,i,g,i,i,i], | |
279 | [i,i,g,i,i,v], | |
280 | [i,i,g,i,v,g], | |
281 | [i,i,g,i,v,i], | |
282 | [i,i,g,i,v,v], | |
283 | [i,i,g,v,g,g]|R]) :- r6_14(R) . | |
284 | r6_14([ | |
285 | [i,i,g,v,g,i], | |
286 | [i,i,g,v,g,v], | |
287 | [i,i,g,v,i,g], | |
288 | [i,i,g,v,i,i], | |
289 | [i,i,g,v,i,v], | |
290 | [i,i,g,v,v,g], | |
291 | [i,i,g,v,v,i], | |
292 | [i,i,g,v,v,v]|R]) :- r6_15(R) . | |
293 | r6_15([ | |
294 | [i,i,i,g,g,g], | |
295 | [i,i,i,g,g,i], | |
296 | [i,i,i,g,g,v], | |
297 | [i,i,i,g,i,g], | |
298 | [i,i,i,g,i,i], | |
299 | [i,i,i,g,i,v], | |
300 | [i,i,i,g,v,g], | |
301 | [i,i,i,g,v,i]|R]) :- r6_16(R) . | |
302 | r6_16([ | |
303 | [i,i,i,g,v,v], | |
304 | [i,i,i,i,g,g], | |
305 | [i,i,i,i,g,i], | |
306 | [i,i,i,i,g,v], | |
307 | [i,i,i,i,i,g], | |
308 | [i,i,i,i,i,i], | |
309 | [i,i,i,i,i,v]|R]) :- r6_17(R) . | |
310 | r6_17([ | |
311 | [i,i,i,i,v,g], | |
312 | [i,i,i,i,v,i], | |
313 | [i,i,i,i,v,v], | |
314 | [i,i,i,v,g,g], | |
315 | [i,i,i,v,g,i], | |
316 | [i,i,i,v,g,v], | |
317 | [i,i,i,v,i,g]|R]) :- r6_18(R) . | |
318 | r6_18([ | |
319 | [i,i,i,v,i,i], | |
320 | [i,i,i,v,i,v], | |
321 | [i,i,i,v,v,g], | |
322 | [i,i,i,v,v,i], | |
323 | [i,i,i,v,v,v], | |
324 | [i,i,v,g,g,g], | |
325 | [i,i,v,g,g,i]|R]) :- r6_19(R) . | |
326 | r6_19([ | |
327 | [i,i,v,g,g,v], | |
328 | [i,i,v,g,i,g], | |
329 | [i,i,v,g,i,i], | |
330 | [i,i,v,g,i,v], | |
331 | [i,i,v,g,v,g], | |
332 | [i,i,v,g,v,i], | |
333 | [i,i,v,g,v,v], | |
334 | [i,i,v,i,g,g]|R]) :- r6_21(R) . | |
335 | r6_21([ | |
336 | [i,i,v,i,g,i], | |
337 | [i,i,v,i,g,v], | |
338 | [i,i,v,i,i,g], | |
339 | [i,i,v,i,i,i], | |
340 | [i,i,v,i,i,v], | |
341 | [i,i,v,i,v,g], | |
342 | [i,i,v,i,v,i]|R]) :- r6_31(R) . | |
343 | r6_31([ | |
344 | [i,i,v,i,v,v], | |
345 | [i,i,v,v,g,g], | |
346 | [i,i,v,v,g,i], | |
347 | [i,i,v,v,g,v], | |
348 | [i,i,v,v,i,g], | |
349 | [i,i,v,v,i,i], | |
350 | [i,i,v,v,i,v]|R]) :- r6_41(R) . | |
351 | r6_41([ | |
352 | [i,i,v,v,v,g], | |
353 | [i,i,v,v,v,i], | |
354 | [i,i,v,v,v,v], | |
355 | [i,v,g,g,g,g], | |
356 | [i,v,g,g,g,i], | |
357 | [i,v,g,g,g,v], | |
358 | [i,v,g,g,i,g], | |
359 | [i,v,g,g,i,i]|R]) :- r6_51(R) . | |
360 | r6_51([ | |
361 | [i,v,g,g,i,v], | |
362 | [i,v,g,g,v,g], | |
363 | [i,v,g,g,v,i], | |
364 | [i,v,g,g,v,v], | |
365 | [i,v,g,i,g,g], | |
366 | [i,v,g,i,g,i], | |
367 | [i,v,g,i,g,v], | |
368 | [i,v,g,i,i,g]|R]) :- r6_61(R) . | |
369 | r6_61([ | |
370 | [i,v,g,i,i,i], | |
371 | [i,v,g,i,i,v], | |
372 | [i,v,g,i,v,g], | |
373 | [i,v,g,i,v,i], | |
374 | [i,v,g,i,v,v], | |
375 | [i,v,g,v,g,g], | |
376 | [i,v,g,v,g,i]|R]) :- r6_71(R) . | |
377 | r6_71([ | |
378 | [i,v,g,v,g,v], | |
379 | [i,v,g,v,i,g], | |
380 | [i,v,g,v,i,i], | |
381 | [i,v,g,v,i,v], | |
382 | [i,v,g,v,v,g]|R]) :- r6_81(R) . | |
383 | r6_81([ | |
384 | [i,v,g,v,v,i], | |
385 | [i,v,g,v,v,v], | |
386 | [i,v,i,g,g,g], | |
387 | [i,v,i,g,g,i], | |
388 | [i,v,i,g,g,v], | |
389 | [i,v,i,g,i,g], | |
390 | [i,v,i,g,i,i]|R]) :- r6_91(R) . | |
391 | r6_91([ | |
392 | [i,v,i,g,i,v], | |
393 | [i,v,i,g,v,g], | |
394 | [i,v,i,g,v,i], | |
395 | [i,v,i,g,v,v], | |
396 | [i,v,i,i,g,g], | |
397 | [i,v,i,i,g,i], | |
398 | [i,v,i,i,g,v]|R]) :- r6_111(R) . | |
399 | r6_111([ | |
400 | [i,v,i,i,i,g], | |
401 | [i,v,i,i,i,i], | |
402 | [i,v,i,i,i,v], | |
403 | [i,v,i,i,v,g], | |
404 | [i,v,i,i,v,i], | |
405 | [i,v,i,i,v,v]|R]) :- r6_221(R) . | |
406 | r6_221([ | |
407 | [i,v,i,v,g,g], | |
408 | [i,v,i,v,g,i], | |
409 | [i,v,i,v,g,v], | |
410 | [i,v,i,v,i,g], | |
411 | [i,v,i,v,i,i], | |
412 | [i,v,i,v,i,v]|R]) :- r6_331(R) . | |
413 | r6_331([ | |
414 | [i,v,i,v,v,g], | |
415 | [i,v,i,v,v,i], | |
416 | [i,v,i,v,v,v], | |
417 | [i,v,v,g,g,g], | |
418 | [i,v,v,g,g,i], | |
419 | [i,v,v,g,g,v]|R]) :- r6_441(R) . | |
420 | r6_441([ | |
421 | [i,v,v,g,i,g], | |
422 | [i,v,v,g,i,i], | |
423 | [i,v,v,g,i,v], | |
424 | [i,v,v,g,v,g], | |
425 | [i,v,v,g,v,i], | |
426 | [i,v,v,g,v,v], | |
427 | [i,v,v,i,g,g]|R]) :- r6_551(R) . | |
428 | r6_551([ | |
429 | [i,v,v,i,g,i], | |
430 | [i,v,v,i,g,v], | |
431 | [i,v,v,i,i,g], | |
432 | [i,v,v,i,i,i], | |
433 | [i,v,v,i,i,v], | |
434 | [i,v,v,i,v,g]|R]) :- r6_661(R) . | |
435 | r6_661([ | |
436 | [i,v,v,i,v,i], | |
437 | [i,v,v,i,v,v], | |
438 | [i,v,v,v,g,g], | |
439 | [i,v,v,v,g,i], | |
440 | [i,v,v,v,g,v], | |
441 | [i,v,v,v,i,g]|R]) :- r6_771(R) . | |
442 | r6_771([ | |
443 | [i,v,v,v,i,i], | |
444 | [i,v,v,v,i,v], | |
445 | [i,v,v,v,v,g], | |
446 | [i,v,v,v,v,i], | |
447 | [i,v,v,v,v,v]]) . |
0 | :- [exec]. | |
1 | :- [kalah_ox]. | |
2 | %:- import start_forest_view/1 from tables. | |
3 | %?- start_forest_view(userout). | |
4 | ||
5 | % Don't abstract -- no finite model. | |
6 | ?- set_prolog_flag(max_table_subgoal_size,200000). | |
7 | ?- set_prolog_flag(max_table_subgoal_size_action,error). | |
8 | test :- exec,fail. |
0 | :- table(play_2 / 2) . | |
1 | play_2([ _164 , _165 ], _309 ) :- initialize_3( _345 , _347 ) , _345 = [ _164 , _171 , _172 ] , displaygame_2( _388 , _390 ) , _388 = [ _171 , _172 ] , play_3( _429 , _431 ) , _429 = [ _171 , _172 , _165 ] , compute([[ _171 , _172 , _165 ],[ _171 , _172 ],[ _164 , _171 , _172 ]],[ _431 , _390 , _347 ],[ _164 , _165 ], _309 ) . | |
2 | :- table(play_3 / 2) . | |
3 | play_3([ _164 , _165 , _166 ], _268 ) :- gameover_3( _306 , _308 ) , _306 = [ _164 , _165 , _166 ] , announce_1( _349 , _351 ) , _349 = [ _166 ] , compute([[ _166 ],[ _164 , _165 , _166 ]],[ _351 , _308 ],[ _164 , _165 , _166 ], _268 ) . | |
4 | play_3([ _164 , _165 , _166 ], _391 ) :- choosemove_3( _429 , _431 ) , _429 = [ _164 , _165 , _173 ] , move_3( _472 , _474 ) , _472 = [ _173 , _164 , _180 ] , displaygame_2( _515 , _517 ) , _515 = [ _180 , _165 ] , nextplayer_2( _556 , _558 ) , _556 = [ _165 , _192 ] , play_3( _597 , _599 ) , _597 = [ _180 , _192 , _166 ] , compute([[ _180 , _192 , _166 ],[ _165 , _192 ],[ _180 , _165 ],[ _173 , _164 , _180 ],[ _164 , _165 , _173 ]],[ _599 , _558 , _517 , _474 , _431 ],[ _164 , _165 , _166 ], _391 ) . | |
5 | :- table(choosemove_3 / 2) . | |
6 | choosemove_3([ _164 , _200 , _166 ], _343 ) :- iff_1( _381 , _383 ) , _381 = [ _200 ] , lookahead_1( _420 , _422 ) , _420 = [ _171 ] , iff_1( _459 , _461 ) , _459 = [ _260 ] , iff_1( _498 , _500 ) , _498 = [ _268 ] , alphabeta_6( _537 , _539 ) , _537 = [ _171 , _164 , _260 , _268 , _166 , _178 ] , compute([[ _171 , _164 , _260 , _268 , _166 , _178 ],[ _268 ],[ _260 ],[ _171 ],[ _200 ]],[ _539 , _500 , _461 , _422 , _383 ],[ _164 , _200 , _166 ], _343 ) . | |
7 | choosemove_3([ _164 , _190 , _166 ], _246 ) :- iff_1( _284 , _286 ) , _284 = [ _190 ] , genlegal_1( _323 , _325 ) , _323 = [ _166 ] , compute([[ _166 ],[ _190 ]],[ _325 , _286 ],[ _164 , _190 , _166 ], _246 ) . | |
8 | :- table(alphabeta_6 / 2) . | |
9 | alphabeta_6([ _198 , _165 , _166 , _167 , _168 , _169 ], _270 ) :- iff_1( _314 , _316 ) , _314 = [ _198 ] , value_2( _353 , _355 ) , _353 = [ _165 , _169 ] , compute([[ _165 , _169 ],[ _198 ]],[ _355 , _316 ],[ _198 , _165 , _166 , _167 , _168 , _169 ], _270 ) . | |
10 | alphabeta_6([ _164 , _165 , _166 , _167 , _168 , _169 ], _597 ) :- iff_1( _641 , _643 ) , _641 = [ _281 ] , myis_2( _680 , _682 ) , _680 = [ _164 , _281 ] , allmoves_2( _721 , _723 ) , _721 = [ _165 , _181 ] , iff_2( _762 , _764 ) , _762 = [ _337 , _167 ] , myis_2( _803 , _805 ) , _803 = [ _186 , _337 ] , iff_2( _844 , _846 ) , _844 = [ _368 , _166 ] , myis_2( _885 , _887 ) , _885 = [ _195 , _368 ] , iff_2( _926 , _928 ) , _926 = [ _399 , _164 ] , myis_2( _967 , _969 ) , _967 = [ _204 , _399 ] , iff_1( _1008 , _1010 ) , _1008 = [ _447 ] , iff_3( _1047 , _1049 ) , _1047 = [ _455 , _168 , _169 ] , evaluateandchoose_7( _1090 , _1092 ) , _1090 = [ _181 , _165 , _204 , _186 , _195 , _447 , _455 ] , compute([[ _181 , _165 , _204 , _186 , _195 , _447 , _455 ],[ _455 , _168 , _169 ],[ _447 ],[ _204 , _399 ],[ _399 , _164 ],[ _195 , _368 ],[ _368 , _166 ],[ _186 , _337 ],[ _337 , _167 ],[ _165 , _181 ],[ _164 , _281 ],[ _281 ]],[ _1092 , _1049 , _1010 , _969 , _928 , _887 , _846 , _805 , _764 , _723 , _682 , _643 ],[ _164 , _165 , _166 , _167 , _168 , _169 ], _597 ) . | |
11 | :- table(allmoves_2 / 2) . | |
12 | allmoves_2([ _164 , _190 ], _251 ) :- iff_2( _287 , _289 ) , _287 = [ _190 , _166 ] , move_2( _328 , _330 ) , _328 = [ _164 , _166 ] , compute([[ _164 , _166 ],[ _190 , _166 ]],[ _330 , _289 ],[ _164 , _190 ], _251 ) . | |
13 | allmoves_2([ _164 , _196 ], _289 ) :- iff_3( _325 , _327 ) , _325 = [ _196 , _166 , _167 ] , move_2( _368 , _370 ) , _368 = [ _164 , _166 ] , allmoves_2( _409 , _411 ) , _409 = [ _164 , _167 ] , compute([[ _164 , _167 ],[ _164 , _166 ],[ _196 , _166 , _167 ]],[ _411 , _370 , _327 ],[ _164 , _196 ], _289 ) . | |
14 | :- table(evaluateandchoose_7 / 2) . | |
15 | evaluateandchoose_7([ _236 , _165 , _166 , _167 , _168 , _169 , _170 ], _486 ) :- iff_3( _532 , _534 ) , _532 = [ _236 , _171 , _172 ] , move_3( _575 , _577 ) , _575 = [ _171 , _165 , _179 ] , alphabeta_6( _618 , _620 ) , _618 = [ _166 , _179 , _167 , _168 , _188 , _189 ] , iff_2( _667 , _669 ) , _667 = [ _356 , _189 ] , myis_2( _708 , _710 ) , _708 = [ _194 , _356 ] , cutoff_9( _749 , _751 ) , _749 = [ _171 , _194 , _166 , _167 , _168 , _172 , _165 , _169 , _170 ] , compute([[ _171 , _194 , _166 , _167 , _168 , _172 , _165 , _169 , _170 ],[ _194 , _356 ],[ _356 , _189 ],[ _166 , _179 , _167 , _168 , _188 , _189 ],[ _171 , _165 , _179 ],[ _236 , _171 , _172 ]],[ _751 , _710 , _669 , _620 , _577 , _534 ],[ _236 , _165 , _166 , _167 , _168 , _169 , _170 ], _486 ) . | |
16 | evaluateandchoose_7([ _197 , _162 , _163 , _164 , _165 , _166 , _215 ], _269 ) :- iff_1( _315 , _317 ) , _315 = [ _197 ] , iff_3( _354 , _356 ) , _354 = [ _215 , _166 , _164 ] , compute([[ _215 , _166 , _164 ],[ _197 ]],[ _356 , _317 ],[ _197 , _162 , _163 , _164 , _165 , _166 , _215 ], _269 ) . | |
17 | :- table(cutoff_9 / 2) . | |
18 | cutoff_9([ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _226 ], _297 ) :- iff_3( _347 , _349 ) , _347 = [ _226 , _164 , _165 ] , myis_2( _390 , _392 ) , _390 = [ _165 , _168 ] , compute([[ _165 , _168 ],[ _226 , _164 , _165 ]],[ _392 , _349 ],[ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _226 ], _297 ) . | |
19 | cutoff_9([ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _172 ], _369 ) :- myis_2( _419 , _421 ) , _419 = [ _167 , _165 ] , myis_2( _460 , _462 ) , _460 = [ _165 , _168 ] , evaluateandchoose_7( _501 , _503 ) , _501 = [ _169 , _170 , _166 , _165 , _168 , _164 , _172 ] , compute([[ _169 , _170 , _166 , _165 , _168 , _164 , _172 ],[ _165 , _168 ],[ _167 , _165 ]],[ _503 , _462 , _421 ],[ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _172 ], _369 ) . | |
20 | cutoff_9([ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _172 ], _334 ) :- myis_2( _384 , _386 ) , _384 = [ _165 , _167 ] , evaluateandchoose_7( _425 , _427 ) , _425 = [ _169 , _170 , _166 , _167 , _168 , _171 , _172 ] , compute([[ _169 , _170 , _166 , _167 , _168 , _171 , _172 ],[ _165 , _167 ]],[ _427 , _386 ],[ _164 , _165 , _166 , _167 , _168 , _169 , _170 , _171 , _172 ], _334 ) . | |
21 | :- table(move_2 / 2) . | |
22 | move_2([ _164 , _217 ], _373 ) :- iff_3( _409 , _411 ) , _409 = [ _217 , _166 , _167 ] , iff_1( _452 , _454 ) , _452 = [ _245 ] , member_2( _491 , _493 ) , _491 = [ _166 , _245 ] , stonesinhole_3( _532 , _534 ) , _532 = [ _166 , _164 , _192 ] , extendmove_4( _575 , _577 ) , _575 = [ _192 , _166 , _164 , _167 ] , compute([[ _192 , _166 , _164 , _167 ],[ _166 , _164 , _192 ],[ _166 , _245 ],[ _245 ],[ _217 , _166 , _167 ]],[ _577 , _534 , _493 , _454 , _411 ],[ _164 , _217 ], _373 ) . | |
23 | move_2([ _196 , _204 ], _256 ) :- iff_4( _292 , _294 ) , _292 = [ _196 , _165 , _166 , _167 ] , iff_1( _337 , _339 ) , _337 = [ _204 ] , compute([[ _204 ],[ _196 , _165 , _166 , _167 ]],[ _339 , _294 ],[ _196 , _204 ], _256 ) . | |
24 | :- table(member_2 / 2) . | |
25 | member_2([ _161 , _183 ], _219 ) :- iff_3( _255 , _257 ) , _255 = [ _183 , _161 , _164 ] , compute([[ _183 , _161 , _164 ]],[ _257 ],[ _161 , _183 ], _219 ) . | |
26 | member_2([ _164 , _190 ], _254 ) :- iff_3( _290 , _292 ) , _290 = [ _190 , _166 , _167 ] , member_2( _333 , _335 ) , _333 = [ _164 , _167 ] , compute([[ _164 , _167 ],[ _190 , _166 , _167 ]],[ _335 , _292 ],[ _164 , _190 ], _254 ) . | |
27 | :- table(stonesinhole_3 / 2) . | |
28 | stonesinhole_3([ _164 , _203 , _166 ], _329 ) :- iff_5( _367 , _369 ) , _367 = [ _203 , _168 , _169 , _170 , _171 ] , nthmember_3( _414 , _416 ) , _414 = [ _164 , _168 , _166 ] , iff_1( _457 , _459 ) , _457 = [ _263 ] , myis_2( _496 , _498 ) , _496 = [ _166 , _263 ] , compute([[ _166 , _263 ],[ _263 ],[ _164 , _168 , _166 ],[ _203 , _168 , _169 , _170 , _171 ]],[ _498 , _459 , _416 , _369 ],[ _164 , _203 , _166 ], _329 ) . | |
29 | :- table(extendmove_4 / 2) . | |
30 | extendmove_4([ _164 , _165 , _166 , _201 ], _283 ) :- iff_1( _323 , _325 ) , _323 = [ _201 ] , iff_2( _362 , _364 ) , _362 = [ _230 , _165 ] , myis_2( _403 , _405 ) , _403 = [ _164 , _230 ] , compute([[ _164 , _230 ],[ _230 , _165 ],[ _201 ]],[ _405 , _364 , _325 ],[ _164 , _165 , _166 , _201 ], _283 ) . | |
31 | extendmove_4([ _164 , _165 , _166 , _167 ], _346 ) :- iff_2( _386 , _388 ) , _386 = [ _239 , _165 ] , myis_2( _427 , _429 ) , _427 = [ _164 , _239 ] , distributestones_4( _468 , _470 ) , _468 = [ _164 , _165 , _166 , _184 ] , move_2( _513 , _515 ) , _513 = [ _184 , _167 ] , compute([[ _184 , _167 ],[ _164 , _165 , _166 , _184 ],[ _164 , _239 ],[ _239 , _165 ]],[ _515 , _470 , _429 , _388 ],[ _164 , _165 , _166 , _167 ], _346 ) . | |
32 | :- table(move_3 / 2) . | |
33 | move_3([ _207 , _165 , _166 ], _354 ) :- iff_3( _392 , _394 ) , _392 = [ _207 , _167 , _168 ] , stonesinhole_3( _435 , _437 ) , _435 = [ _167 , _165 , _175 ] , distributestones_4( _478 , _480 ) , _478 = [ _175 , _167 , _165 , _183 ] , move_3( _523 , _525 ) , _523 = [ _168 , _183 , _166 ] , compute([[ _168 , _183 , _166 ],[ _175 , _167 , _165 , _183 ],[ _167 , _165 , _175 ],[ _207 , _167 , _168 ]],[ _525 , _480 , _437 , _394 ],[ _207 , _165 , _166 ], _354 ) . | |
34 | move_3([ _189 , _165 , _166 ], _252 ) :- iff_1( _290 , _292 ) , _290 = [ _189 ] , swap_2( _329 , _331 ) , _329 = [ _165 , _166 ] , compute([[ _165 , _166 ],[ _189 ]],[ _331 , _292 ],[ _189 , _165 , _166 ], _252 ) . | |
35 | :- table(distributestones_4 / 2) . | |
36 | distributestones_4([ _164 , _165 , _166 , _167 ], _298 ) :- distributemyholes_5( _338 , _340 ) , _338 = [ _164 , _165 , _166 , _175 , _176 ] , distributeyourholes_3( _385 , _387 ) , _385 = [ _176 , _175 , _167 ] , compute([[ _176 , _175 , _167 ],[ _164 , _165 , _166 , _175 , _176 ]],[ _387 , _340 ],[ _164 , _165 , _166 , _167 ], _298 ) . | |
37 | :- table(distributemyholes_5 / 2) . | |
38 | distributemyholes_5([ _164 , _165 , _241 , _249 , _168 ], _515 ) :- iff_5( _557 , _559 ) , _557 = [ _241 , _170 , _171 , _172 , _173 ] , iff_5( _604 , _606 ) , _604 = [ _249 , _175 , _176 , _172 , _173 ] , iff_2( _651 , _653 ) , _651 = [ _282 , _165 ] , myis_2( _692 , _694 ) , _692 = [ _164 , _282 ] , pickupanddistribute_4( _733 , _735 ) , _733 = [ _165 , _164 , _170 , _175 ] , iff_2( _778 , _780 ) , _778 = [ _348 , _171 ] , myis_2( _819 , _821 ) , _819 = [ _176 , _348 ] , iff_3( _860 , _862 ) , _860 = [ _378 , _164 , _165 ] , myis_2( _903 , _905 ) , _903 = [ _168 , _378 ] , compute([[ _168 , _378 ],[ _378 , _164 , _165 ],[ _176 , _348 ],[ _348 , _171 ],[ _165 , _164 , _170 , _175 ],[ _164 , _282 ],[ _282 , _165 ],[ _249 , _175 , _176 , _172 , _173 ],[ _241 , _170 , _171 , _172 , _173 ]],[ _905 , _862 , _821 , _780 , _735 , _694 , _653 , _606 , _559 ],[ _164 , _165 , _241 , _249 , _168 ], _515 ) . | |
39 | distributemyholes_5([ _164 , _165 , _237 , _167 , _247 ], _501 ) :- iff_5( _543 , _545 ) , _543 = [ _237 , _170 , _171 , _172 , _173 ] , iff_1( _590 , _592 ) , _590 = [ _247 ] , pickupanddistribute_4( _629 , _631 ) , _629 = [ _165 , _164 , _170 , _181 ] , checkcapture_7( _674 , _676 ) , _674 = [ _165 , _164 , _181 , _189 , _172 , _191 , _192 ] , updatekalah_5( _725 , _727 ) , _725 = [ _192 , _165 , _164 , _171 , _201 ] , iff_5( _772 , _774 ) , _772 = [ _400 , _189 , _201 , _191 , _173 ] , checkiffinished_2( _819 , _821 ) , _819 = [ _400 , _167 ] , compute([[ _400 , _167 ],[ _400 , _189 , _201 , _191 , _173 ],[ _192 , _165 , _164 , _171 , _201 ],[ _165 , _164 , _181 , _189 , _172 , _191 , _192 ],[ _165 , _164 , _170 , _181 ],[ _247 ],[ _237 , _170 , _171 , _172 , _173 ]],[ _821 , _774 , _727 , _676 , _631 , _592 , _545 ],[ _164 , _165 , _237 , _167 , _247 ], _501 ) . | |
40 | :- table(checkcapture_7 / 2) . | |
41 | checkcapture_7([ _164 , _165 , _166 , _167 , _168 , _169 , _170 ], _632 ) :- iff_3( _678 , _680 ) , _678 = [ _290 , _164 , _165 ] , myis_2( _721 , _723 ) , _721 = [ _175 , _290 ] , iff_2( _762 , _764 ) , _762 = [ _321 , _175 ] , myis_2( _803 , _805 ) , _803 = [ _184 , _321 ] , nthmember_3( _844 , _846 ) , _844 = [ _184 , _168 , _195 ] , iff_1( _887 , _889 ) , _887 = [ _382 ] , myis_2( _926 , _928 ) , _926 = [ _195 , _382 ] , iff_1( _967 , _969 ) , _967 = [ _419 ] , nsubstitute_4( _1006 , _1008 ) , _1006 = [ _184 , _166 , _419 , _167 ] , iff_1( _1051 , _1053 ) , _1051 = [ _460 ] , nsubstitute_4( _1090 , _1092 ) , _1090 = [ _175 , _168 , _460 , _169 ] , iff_2( _1135 , _1137 ) , _1135 = [ _494 , _195 ] , myis_2( _1176 , _1178 ) , _1176 = [ _170 , _494 ] , compute([[ _170 , _494 ],[ _494 , _195 ],[ _175 , _168 , _460 , _169 ],[ _460 ],[ _184 , _166 , _419 , _167 ],[ _419 ],[ _195 , _382 ],[ _382 ],[ _184 , _168 , _195 ],[ _184 , _321 ],[ _321 , _175 ],[ _175 , _290 ],[ _290 , _164 , _165 ]],[ _1178 , _1137 , _1092 , _1053 , _1008 , _969 , _928 , _889 , _846 , _805 , _764 , _723 , _680 ],[ _164 , _165 , _166 , _167 , _168 , _169 , _170 ], _632 ) . | |
42 | checkcapture_7([ _161 , _162 , _198 , _163 , _208 , _165 , _218 ], _267 ) :- iffequal_2( _313 , _315 ) , _313 = [ _198 , _163 ] , iffequal_2( _354 , _356 ) , _354 = [ _208 , _165 ] , iff_1( _395 , _397 ) , _395 = [ _218 ] , compute([[ _218 ],[ _208 , _165 ],[ _198 , _163 ]],[ _397 , _356 , _315 ],[ _161 , _162 , _198 , _163 , _208 , _165 , _218 ], _267 ) . | |
43 | :- table(checkiffinished_2 / 2) . | |
44 | checkiffinished_2([ _210 , _218 ], _388 ) :- iff_5( _424 , _426 ) , _424 = [ _210 , _167 , _168 , _169 , _170 ] , iff_4( _471 , _473 ) , _471 = [ _218 , _167 , _168 , _175 ] , zero_1( _516 , _518 ) , _516 = [ _167 ] , sumlist_2( _555 , _557 ) , _555 = [ _169 , _186 ] , iff_3( _596 , _598 ) , _596 = [ _290 , _170 , _186 ] , myis_2( _639 , _641 ) , _639 = [ _175 , _290 ] , compute([[ _175 , _290 ],[ _290 , _170 , _186 ],[ _169 , _186 ],[ _167 ],[ _218 , _167 , _168 , _175 ],[ _210 , _167 , _168 , _169 , _170 ]],[ _641 , _598 , _557 , _518 , _473 , _426 ],[ _210 , _218 ], _388 ) . | |
45 | checkiffinished_2([ _210 , _218 ], _388 ) :- iff_5( _424 , _426 ) , _424 = [ _210 , _167 , _168 , _169 , _170 ] , iff_4( _471 , _473 ) , _471 = [ _218 , _169 , _173 , _170 ] , zero_1( _516 , _518 ) , _516 = [ _169 ] , sumlist_2( _555 , _557 ) , _555 = [ _167 , _186 ] , iff_3( _596 , _598 ) , _596 = [ _290 , _168 , _186 ] , myis_2( _639 , _641 ) , _639 = [ _173 , _290 ] , compute([[ _173 , _290 ],[ _290 , _168 , _186 ],[ _167 , _186 ],[ _169 ],[ _218 , _169 , _173 , _170 ],[ _210 , _167 , _168 , _169 , _170 ]],[ _641 , _598 , _557 , _518 , _473 , _426 ],[ _210 , _218 ], _388 ) . | |
46 | checkiffinished_2([ _179 , _161 ], _205 ) :- iffequal_2( _241 , _243 ) , _241 = [ _179 , _161 ] , compute([[ _179 , _161 ]],[ _243 ],[ _179 , _161 ], _205 ) . | |
47 | :- table(updatekalah_5 / 2) . | |
48 | updatekalah_5([ _198 , _165 , _166 , _210 , _167 ], _302 ) :- iff_1( _344 , _346 ) , _344 = [ _198 ] , iffequal_2( _383 , _385 ) , _383 = [ _210 , _167 ] , iff_2( _424 , _426 ) , _424 = [ _242 , _166 ] , myis_2( _465 , _467 ) , _465 = [ _165 , _242 ] , compute([[ _165 , _242 ],[ _242 , _166 ],[ _210 , _167 ],[ _198 ]],[ _467 , _426 , _385 , _346 ],[ _198 , _165 , _166 , _210 , _167 ], _302 ) . | |
49 | updatekalah_5([ _207 , _165 , _166 , _167 , _168 ], _349 ) :- iff_1( _391 , _393 ) , _391 = [ _207 ] , iff_2( _430 , _432 ) , _430 = [ _246 , _166 ] , myis_2( _471 , _473 ) , _471 = [ _165 , _246 ] , iff_2( _512 , _514 ) , _512 = [ _276 , _167 ] , myis_2( _553 , _555 ) , _553 = [ _168 , _276 ] , compute([[ _168 , _276 ],[ _276 , _167 ],[ _165 , _246 ],[ _246 , _166 ],[ _207 ]],[ _555 , _514 , _473 , _432 , _393 ],[ _207 , _165 , _166 , _167 , _168 ], _349 ) . | |
50 | updatekalah_5([ _164 , _165 , _166 , _167 , _168 ], _327 ) :- iff_1( _369 , _371 ) , _369 = [ _237 ] , myis_2( _408 , _410 ) , _408 = [ _164 , _237 ] , iff_3( _449 , _451 ) , _449 = [ _267 , _167 , _164 ] , myis_2( _492 , _494 ) , _492 = [ _168 , _267 ] , compute([[ _168 , _267 ],[ _267 , _167 , _164 ],[ _164 , _237 ],[ _237 ]],[ _494 , _451 , _410 , _371 ],[ _164 , _165 , _166 , _167 , _168 ], _327 ) . | |
51 | :- table(distributeyourholes_3 / 2) . | |
52 | distributeyourholes_3([ _182 , _190 , _162 ], _230 ) :- iff_1( _268 , _270 ) , _268 = [ _182 ] , iffequal_2( _307 , _309 ) , _307 = [ _190 , _162 ] , compute([[ _190 , _162 ],[ _182 ]],[ _309 , _270 ],[ _182 , _190 , _162 ], _230 ) . | |
53 | distributeyourholes_3([ _164 , _219 , _227 ], _448 ) :- iff_5( _486 , _488 ) , _486 = [ _219 , _168 , _169 , _170 , _171 ] , iff_5( _533 , _535 ) , _533 = [ _227 , _168 , _169 , _175 , _171 ] , iff_1( _580 , _582 ) , _580 = [ _254 ] , myis_2( _619 , _621 ) , _619 = [ _254 , _164 ] , iff_1( _660 , _662 ) , _660 = [ _287 ] , myis_2( _699 , _701 ) , _699 = [ _164 , _287 ] , nonzero_1( _740 , _742 ) , _740 = [ _168 ] , distribute_3( _779 , _781 ) , _779 = [ _164 , _170 , _175 ] , compute([[ _164 , _170 , _175 ],[ _168 ],[ _164 , _287 ],[ _287 ],[ _254 , _164 ],[ _254 ],[ _227 , _168 , _169 , _175 , _171 ],[ _219 , _168 , _169 , _170 , _171 ]],[ _781 , _742 , _701 , _662 , _621 , _582 , _535 , _488 ],[ _164 , _219 , _227 ], _448 ) . | |
54 | distributeyourholes_3([ _164 , _230 , _238 ], _546 ) :- iff_5( _584 , _586 ) , _584 = [ _230 , _168 , _169 , _170 , _171 ] , iff_5( _631 , _633 ) , _631 = [ _238 , _168 , _169 , _175 , _171 ] , iff_1( _678 , _680 ) , _678 = [ _267 ] , myis_2( _717 , _719 ) , _717 = [ _164 , _267 ] , iff_1( _758 , _760 ) , _758 = [ _298 ] , distribute_3( _797 , _799 ) , _797 = [ _298 , _170 , _175 ] , iff_2( _840 , _842 ) , _840 = [ _334 , _164 ] , myis_2( _881 , _883 ) , _881 = [ _194 , _334 ] , iff_1( _922 , _924 ) , _922 = [ _368 ] , iff_5( _961 , _963 ) , _961 = [ _376 , _168 , _169 , _175 , _171 ] , distributestones_4( _1008 , _1010 ) , _1008 = [ _194 , _368 , _376 , _203 ] , compute([[ _194 , _368 , _376 , _203 ],[ _376 , _168 , _169 , _175 , _171 ],[ _368 ],[ _194 , _334 ],[ _334 , _164 ],[ _298 , _170 , _175 ],[ _298 ],[ _164 , _267 ],[ _267 ],[ _238 , _168 , _169 , _175 , _171 ],[ _230 , _168 , _169 , _170 , _171 ]],[ _1010 , _963 , _924 , _883 , _842 , _799 , _760 , _719 , _680 , _633 , _586 ],[ _164 , _230 , _238 ], _546 ) . | |
55 | distributeyourholes_3([ _164 , _218 , _226 ], _400 ) :- iff_5( _438 , _440 ) , _438 = [ _218 , _168 , _169 , _170 , _171 ] , iff_4( _485 , _487 ) , _485 = [ _226 , _168 , _169 , _176 ] , zero_1( _530 , _532 ) , _530 = [ _168 ] , sumlist_2( _569 , _571 ) , _569 = [ _170 , _187 ] , iff_4( _610 , _612 ) , _610 = [ _299 , _164 , _187 , _171 ] , myis_2( _655 , _657 ) , _655 = [ _176 , _299 ] , compute([[ _176 , _299 ],[ _299 , _164 , _187 , _171 ],[ _170 , _187 ],[ _168 ],[ _226 , _168 , _169 , _176 ],[ _218 , _168 , _169 , _170 , _171 ]],[ _657 , _612 , _571 , _532 , _487 , _440 ],[ _164 , _218 , _226 ], _400 ) . | |
56 | :- table(pickupanddistribute_4 / 2) . | |
57 | pickupanddistribute_4([ _197 , _165 , _207 , _215 ], _315 ) :- iff_1( _355 , _357 ) , _355 = [ _197 ] , iff_3( _394 , _396 ) , _394 = [ _207 , _168 , _169 ] , iff_2( _437 , _439 ) , _437 = [ _215 , _171 ] , distribute_3( _478 , _480 ) , _478 = [ _165 , _169 , _171 ] , compute([[ _165 , _169 , _171 ],[ _215 , _171 ],[ _207 , _168 , _169 ],[ _197 ]],[ _480 , _439 , _396 , _357 ],[ _197 , _165 , _207 , _215 ], _315 ) . | |
58 | pickupanddistribute_4([ _164 , _165 , _217 , _225 ], _416 ) :- iff_3( _456 , _458 ) , _456 = [ _217 , _168 , _169 ] , iff_2( _499 , _501 ) , _499 = [ _225 , _171 ] , iff_1( _540 , _542 ) , _540 = [ _255 ] , myis_2( _579 , _581 ) , _579 = [ _164 , _255 ] , iff_2( _620 , _622 ) , _620 = [ _286 , _164 ] , myis_2( _661 , _663 ) , _661 = [ _182 , _286 ] , pickupanddistribute_4( _702 , _704 ) , _702 = [ _182 , _165 , _169 , _171 ] , compute([[ _182 , _165 , _169 , _171 ],[ _182 , _286 ],[ _286 , _164 ],[ _164 , _255 ],[ _255 ],[ _225 , _171 ],[ _217 , _168 , _169 ]],[ _704 , _663 , _622 , _581 , _542 , _501 , _458 ],[ _164 , _165 , _217 , _225 ], _416 ) . | |
59 | :- table(distribute_3 / 2) . | |
60 | distribute_3([ _182 , _190 , _162 ], _230 ) :- iff_1( _268 , _270 ) , _268 = [ _182 ] , iffequal_2( _307 , _309 ) , _307 = [ _190 , _162 ] , compute([[ _190 , _162 ],[ _182 ]],[ _309 , _270 ],[ _182 , _190 , _162 ], _230 ) . | |
61 | distribute_3([ _164 , _220 , _228 ], _467 ) :- iff_3( _505 , _507 ) , _505 = [ _220 , _167 , _168 ] , iff_3( _548 , _550 ) , _548 = [ _228 , _169 , _170 ] , iff_1( _591 , _593 ) , _591 = [ _257 ] , myis_2( _630 , _632 ) , _630 = [ _164 , _257 ] , iff_2( _671 , _673 ) , _671 = [ _288 , _164 ] , myis_2( _712 , _714 ) , _712 = [ _181 , _288 ] , iff_2( _753 , _755 ) , _753 = [ _319 , _167 ] , myis_2( _794 , _796 ) , _794 = [ _169 , _319 ] , distribute_3( _835 , _837 ) , _835 = [ _181 , _168 , _170 ] , compute([[ _181 , _168 , _170 ],[ _169 , _319 ],[ _319 , _167 ],[ _181 , _288 ],[ _288 , _164 ],[ _164 , _257 ],[ _257 ],[ _228 , _169 , _170 ],[ _220 , _167 , _168 ]],[ _837 , _796 , _755 , _714 , _673 , _632 , _593 , _550 , _507 ],[ _164 , _220 , _228 ], _467 ) . | |
62 | distribute_3([ _161 , _184 , _192 ], _236 ) :- iff_1( _274 , _276 ) , _274 = [ _184 ] , iff_1( _313 , _315 ) , _313 = [ _192 ] , compute([[ _192 ],[ _184 ]],[ _315 , _276 ],[ _161 , _184 , _192 ], _236 ) . | |
63 | :- table(value_2 / 2) . | |
64 | value_2([ _194 , _165 ], _291 ) :- iff_5( _327 , _329 ) , _327 = [ _194 , _167 , _168 , _169 , _170 ] , iff_3( _374 , _376 ) , _374 = [ _223 , _168 , _170 ] , myis_2( _417 , _419 ) , _417 = [ _165 , _223 ] , compute([[ _165 , _223 ],[ _223 , _168 , _170 ],[ _194 , _167 , _168 , _169 , _170 ]],[ _419 , _376 , _329 ],[ _194 , _165 ], _291 ) . | |
65 | :- table(gameover_3 / 2) . | |
66 | gameover_3([ _202 , _165 , _212 ], _333 ) :- iff_2( _371 , _373 ) , _371 = [ _202 , _169 ] , iff_1( _412 , _414 ) , _412 = [ _212 ] , pieces_1( _451 , _453 ) , _451 = [ _176 ] , iff_2( _490 , _492 ) , _490 = [ _260 , _176 ] , myis_2( _531 , _533 ) , _531 = [ _169 , _260 ] , compute([[ _169 , _260 ],[ _260 , _176 ],[ _176 ],[ _212 ],[ _202 , _169 ]],[ _533 , _492 , _453 , _414 , _373 ],[ _202 , _165 , _212 ], _333 ) . | |
67 | gameover_3([ _202 , _210 , _165 ], _336 ) :- iff_5( _374 , _376 ) , _374 = [ _202 , _168 , _169 , _170 , _171 ] , iffequal_2( _421 , _423 ) , _421 = [ _210 , _165 ] , pieces_1( _462 , _464 ) , _462 = [ _176 ] , iff_2( _501 , _503 ) , _501 = [ _260 , _176 ] , myis_2( _542 , _544 ) , _542 = [ _169 , _260 ] , compute([[ _169 , _260 ],[ _260 , _176 ],[ _176 ],[ _210 , _165 ],[ _202 , _168 , _169 , _170 , _171 ]],[ _544 , _503 , _464 , _423 , _376 ],[ _202 , _210 , _165 ], _336 ) . | |
68 | gameover_3([ _208 , _165 , _166 ], _358 ) :- iff_5( _396 , _398 ) , _396 = [ _208 , _168 , _169 , _170 , _171 ] , pieces_1( _443 , _445 ) , _443 = [ _176 ] , iff_2( _482 , _484 ) , _482 = [ _261 , _176 ] , myis_2( _523 , _525 ) , _523 = [ _171 , _261 ] , nextplayer_2( _564 , _566 ) , _564 = [ _165 , _166 ] , compute([[ _165 , _166 ],[ _171 , _261 ],[ _261 , _176 ],[ _176 ],[ _208 , _168 , _169 , _170 , _171 ]],[ _566 , _525 , _484 , _445 , _398 ],[ _208 , _165 , _166 ], _358 ) . | |
69 | :- table(announce_1 / 2) . | |
70 | announce_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
71 | announce_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
72 | announce_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
73 | :- table(nthmember_3 / 2) . | |
74 | nthmember_3([ _164 , _209 , _166 ], _380 ) :- iff_3( _418 , _420 ) , _418 = [ _209 , _167 , _168 ] , iff_1( _461 , _463 ) , _461 = [ _240 ] , myis_2( _500 , _502 ) , _500 = [ _164 , _240 ] , iff_2( _541 , _543 ) , _541 = [ _271 , _164 ] , myis_2( _582 , _584 ) , _582 = [ _179 , _271 ] , nthmember_3( _623 , _625 ) , _623 = [ _179 , _168 , _166 ] , compute([[ _179 , _168 , _166 ],[ _179 , _271 ],[ _271 , _164 ],[ _164 , _240 ],[ _240 ],[ _209 , _167 , _168 ]],[ _625 , _584 , _543 , _502 , _463 , _420 ],[ _164 , _209 , _166 ], _380 ) . | |
75 | nthmember_3([ _184 , _192 , _164 ], _244 ) :- iff_1( _282 , _284 ) , _282 = [ _184 ] , iff_3( _321 , _323 ) , _321 = [ _192 , _164 , _165 ] , compute([[ _192 , _164 , _165 ],[ _184 ]],[ _323 , _284 ],[ _184 , _192 , _164 ], _244 ) . | |
76 | :- table(nsubstitute_4 / 2) . | |
77 | nsubstitute_4([ _189 , _197 , _163 , _207 ], _277 ) :- iff_1( _317 , _319 ) , _317 = [ _189 ] , iff_3( _356 , _358 ) , _356 = [ _197 , _165 , _166 ] , iff_3( _399 , _401 ) , _399 = [ _207 , _163 , _166 ] , compute([[ _207 , _163 , _166 ],[ _197 , _165 , _166 ],[ _189 ]],[ _401 , _358 , _319 ],[ _189 , _197 , _163 , _207 ], _277 ) . | |
78 | nsubstitute_4([ _164 , _215 , _166 , _225 ], _419 ) :- iff_3( _459 , _461 ) , _459 = [ _215 , _168 , _169 ] , iff_3( _502 , _504 ) , _502 = [ _225 , _168 , _171 ] , iff_1( _545 , _547 ) , _545 = [ _255 ] , myis_2( _584 , _586 ) , _584 = [ _164 , _255 ] , iff_2( _625 , _627 ) , _625 = [ _286 , _164 ] , myis_2( _666 , _668 ) , _666 = [ _182 , _286 ] , nsubstitute_4( _707 , _709 ) , _707 = [ _182 , _169 , _166 , _171 ] , compute([[ _182 , _169 , _166 , _171 ],[ _182 , _286 ],[ _286 , _164 ],[ _164 , _255 ],[ _255 ],[ _225 , _168 , _171 ],[ _215 , _168 , _169 ]],[ _709 , _668 , _627 , _586 , _547 , _504 , _461 ],[ _164 , _215 , _166 , _225 ], _419 ) . | |
79 | :- table(nextplayer_2 / 2) . | |
80 | nextplayer_2([ _179 , _187 ], _230 ) :- iff_1( _266 , _268 ) , _266 = [ _179 ] , iff_1( _305 , _307 ) , _305 = [ _187 ] , compute([[ _187 ],[ _179 ]],[ _307 , _268 ],[ _179 , _187 ], _230 ) . | |
81 | nextplayer_2([ _179 , _187 ], _230 ) :- iff_1( _266 , _268 ) , _266 = [ _179 ] , iff_1( _305 , _307 ) , _305 = [ _187 ] , compute([[ _187 ],[ _179 ]],[ _307 , _268 ],[ _179 , _187 ], _230 ) . | |
82 | :- table(legal_1 / 2) . | |
83 | legal_1([ _196 ], _350 ) :- iff_3( _384 , _386 ) , _384 = [ _196 , _165 , _166 ] , iff_1( _427 , _429 ) , _427 = [ _221 ] , myis_2( _466 , _468 ) , _466 = [ _221 , _165 ] , iff_1( _507 , _509 ) , _507 = [ _254 ] , myis_2( _546 , _548 ) , _546 = [ _165 , _254 ] , legal_1( _587 , _589 ) , _587 = [ _166 ] , compute([[ _166 ],[ _165 , _254 ],[ _254 ],[ _221 , _165 ],[ _221 ],[ _196 , _165 , _166 ]],[ _589 , _548 , _509 , _468 , _429 , _386 ],[ _196 ], _350 ) . | |
84 | legal_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
85 | :- table(genlegal_1 / 2) . | |
86 | genlegal_1([ _202 ], _308 ) :- iff_3( _342 , _344 ) , _342 = [ _202 , _165 , _166 ] , iff_1( _385 , _387 ) , _385 = [ _229 ] , member_2( _424 , _426 ) , _424 = [ _165 , _229 ] , genlegal_1( _465 , _467 ) , _465 = [ _166 ] , compute([[ _166 ],[ _165 , _229 ],[ _229 ],[ _202 , _165 , _166 ]],[ _467 , _426 , _387 , _344 ],[ _202 ], _308 ) . | |
87 | genlegal_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
88 | :- table(swap_2 / 2) . | |
89 | swap_2([ _189 , _197 ], _264 ) :- iff_5( _300 , _302 ) , _300 = [ _189 , _164 , _165 , _166 , _167 ] , iff_5( _347 , _349 ) , _347 = [ _197 , _166 , _167 , _164 , _165 ] , compute([[ _197 , _166 , _167 , _164 , _165 ],[ _189 , _164 , _165 , _166 , _167 ]],[ _349 , _302 ],[ _189 , _197 ], _264 ) . | |
90 | :- table(displaygame_2 / 2) . | |
91 | displaygame_2([ _164 , _187 ], _240 ) :- iff_1( _276 , _278 ) , _276 = [ _187 ] , show_1( _315 , _317 ) , _315 = [ _164 ] , compute([[ _164 ],[ _187 ]],[ _317 , _278 ],[ _164 , _187 ], _240 ) . | |
92 | displaygame_2([ _164 , _193 ], _275 ) :- iff_1( _311 , _313 ) , _311 = [ _193 ] , swap_2( _350 , _352 ) , _350 = [ _164 , _171 ] , show_1( _391 , _393 ) , _391 = [ _171 ] , compute([[ _171 ],[ _164 , _171 ],[ _193 ]],[ _393 , _352 , _313 ],[ _164 , _193 ], _275 ) . | |
93 | :- table(show_1 / 2) . | |
94 | show_1([ _204 ], _350 ) :- iff_5( _384 , _386 ) , _384 = [ _204 , _166 , _167 , _168 , _169 ] , reverse_2( _431 , _433 ) , _431 = [ _166 , _175 ] , writestones_1( _472 , _474 ) , _472 = [ _175 ] , writekalahs_2( _511 , _513 ) , _511 = [ _167 , _169 ] , writestones_1( _552 , _554 ) , _552 = [ _168 ] , compute([[ _168 ],[ _167 , _169 ],[ _175 ],[ _166 , _175 ],[ _204 , _166 , _167 , _168 , _169 ]],[ _554 , _513 , _474 , _433 , _386 ],[ _204 ], _350 ) . | |
95 | :- table(writestones_1 / 2) . | |
96 | writestones_1([ _164 ], _215 ) :- displayholes_1( _249 , _251 ) , _249 = [ _164 ] , compute([[ _164 ]],[ _251 ],[ _164 ], _215 ) . | |
97 | :- table(displayholes_1 / 2) . | |
98 | displayholes_1([ _189 ], _271 ) :- iff_3( _305 , _307 ) , _305 = [ _189 , _165 , _166 ] , writepile_1( _348 , _350 ) , _348 = [ _165 ] , displayholes_1( _387 , _389 ) , _387 = [ _166 ] , compute([[ _166 ],[ _165 ],[ _189 , _165 , _166 ]],[ _389 , _350 , _307 ],[ _189 ], _271 ) . | |
99 | displayholes_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
100 | :- table(writepile_1 / 2) . | |
101 | writepile_1([ _164 ], _269 ) :- iff_1( _303 , _305 ) , _303 = [ _209 ] , myis_2( _342 , _344 ) , _342 = [ _164 , _209 ] , wr_1( _383 , _385 ) , _383 = [ _164 ] , compute([[ _164 ],[ _164 , _209 ],[ _209 ]],[ _385 , _344 , _305 ],[ _164 ], _269 ) . | |
102 | writepile_1([ _164 ], _269 ) :- iff_1( _303 , _305 ) , _303 = [ _209 ] , myis_2( _342 , _344 ) , _342 = [ _164 , _209 ] , wr_1( _383 , _385 ) , _383 = [ _164 ] , compute([[ _164 ],[ _164 , _209 ],[ _209 ]],[ _385 , _344 , _305 ],[ _164 ], _269 ) . | |
103 | :- table(writekalahs_2 / 2) . | |
104 | writekalahs_2([ _164 , _165 ], _250 ) :- wr_1( _286 , _288 ) , _286 = [ _164 ] , wr_1( _325 , _327 ) , _325 = [ _165 ] , compute([[ _165 ],[ _164 ]],[ _327 , _288 ],[ _164 , _165 ], _250 ) . | |
105 | :- table(zero_1 / 2) . | |
106 | zero_1([ _188 ], _217 ) :- iff_1( _251 , _253 ) , _251 = [ _188 ] , compute([[ _188 ]],[ _253 ],[ _188 ], _217 ) . | |
107 | :- table(nonzero_1 / 2) . | |
108 | nonzero_1([ _164 ], _252 ) :- iff_1( _286 , _288 ) , _286 = [ _215 ] , myis_2( _325 , _327 ) , _325 = [ _164 , _215 ] , compute([[ _164 , _215 ],[ _215 ]],[ _327 , _288 ],[ _164 ], _252 ) . | |
109 | :- table(reverse_2 / 2) . | |
110 | reverse_2([ _164 , _165 ], _252 ) :- iff_1( _288 , _290 ) , _288 = [ _212 ] , rev_3( _327 , _329 ) , _327 = [ _164 , _212 , _165 ] , compute([[ _164 , _212 , _165 ],[ _212 ]],[ _329 , _290 ],[ _164 , _165 ], _252 ) . | |
111 | :- table(rev_3 / 2) . | |
112 | rev_3([ _182 , _190 , _162 ], _230 ) :- iff_1( _268 , _270 ) , _268 = [ _182 ] , iffequal_2( _307 , _309 ) , _307 = [ _190 , _162 ] , compute([[ _190 , _162 ],[ _182 ]],[ _309 , _270 ],[ _182 , _190 , _162 ], _230 ) . | |
113 | rev_3([ _194 , _165 , _166 ], _293 ) :- iff_3( _331 , _333 ) , _331 = [ _194 , _167 , _168 ] , iff_3( _374 , _376 ) , _374 = [ _228 , _167 , _165 ] , rev_3( _417 , _419 ) , _417 = [ _168 , _228 , _166 ] , compute([[ _168 , _228 , _166 ],[ _228 , _167 , _165 ],[ _194 , _167 , _168 ]],[ _419 , _376 , _333 ],[ _194 , _165 , _166 ], _293 ) . | |
114 | :- table(sumlist_2 / 2) . | |
115 | sumlist_2([ _164 , _165 ], _252 ) :- iff_1( _288 , _290 ) , _288 = [ _212 ] , sumlist_3( _327 , _329 ) , _327 = [ _164 , _212 , _165 ] , compute([[ _164 , _212 , _165 ],[ _212 ]],[ _329 , _290 ],[ _164 , _165 ], _252 ) . | |
116 | :- table(sumlist_3 / 2) . | |
117 | sumlist_3([ _182 , _190 , _162 ], _230 ) :- iff_1( _268 , _270 ) , _268 = [ _182 ] , iffequal_2( _307 , _309 ) , _307 = [ _190 , _162 ] , compute([[ _190 , _162 ],[ _182 ]],[ _309 , _270 ],[ _182 , _190 , _162 ], _230 ) . | |
118 | sumlist_3([ _201 , _165 , _166 ], _326 ) :- iff_3( _364 , _366 ) , _364 = [ _201 , _167 , _168 ] , iff_2( _407 , _409 ) , _407 = [ _234 , _165 ] , myis_2( _448 , _450 ) , _448 = [ _173 , _234 ] , sumlist_3( _489 , _491 ) , _489 = [ _168 , _173 , _166 ] , compute([[ _168 , _173 , _166 ],[ _173 , _234 ],[ _234 , _165 ],[ _201 , _167 , _168 ]],[ _491 , _450 , _409 , _366 ],[ _201 , _165 , _166 ], _326 ) . | |
119 | :- table(lookahead_1 / 2) . | |
120 | lookahead_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
121 | lookahead_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
122 | :- table(initialize_3 / 2) . | |
123 | initialize_3([ _187 , _195 , _203 ], _260 ) :- iff_1( _298 , _300 ) , _298 = [ _187 ] , iff_1( _337 , _339 ) , _337 = [ _195 ] , iff_1( _376 , _378 ) , _376 = [ _203 ] , compute([[ _203 ],[ _195 ],[ _187 ]],[ _378 , _339 , _300 ],[ _187 , _195 , _203 ], _260 ) . | |
124 | initialize_3([ _187 , _195 , _203 ], _260 ) :- iff_1( _298 , _300 ) , _298 = [ _187 ] , iff_1( _337 , _339 ) , _337 = [ _195 ] , iff_1( _376 , _378 ) , _376 = [ _203 ] , compute([[ _203 ],[ _195 ],[ _187 ]],[ _378 , _339 , _300 ],[ _187 , _195 , _203 ], _260 ) . | |
125 | :- table(pieces_1 / 2) . | |
126 | pieces_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
127 | pieces_1([ _176 ], _205 ) :- iff_1( _239 , _241 ) , _239 = [ _176 ] , compute([[ _176 ]],[ _241 ],[ _176 ], _205 ) . | |
128 | :- table(myis_2 / 2) . | |
129 | myis_2([ _179 , _187 ], _230 ) :- iff_1( _266 , _268 ) , _266 = [ _179 ] , iff_1( _305 , _307 ) , _305 = [ _187 ] , compute([[ _187 ],[ _179 ]],[ _307 , _268 ],[ _179 , _187 ], _230 ) . | |
130 | :- table(wr_1 / 2) . | |
131 | wr_1([ _161 ], _186 ) :- compute([],[],[ _161 ], _186 ) . | |
132 | exec :- wr_1( _163 , _164 ) . | |
133 | exec :- myis_2( _163 , _164 ) . | |
134 | exec :- pieces_1( _163 , _164 ) . | |
135 | exec :- initialize_3( _163 , _164 ) . | |
136 | exec :- lookahead_1( _163 , _164 ) . | |
137 | exec :- sumlist_3( _163 , _164 ) . | |
138 | exec :- sumlist_2( _163 , _164 ) . | |
139 | exec :- rev_3( _163 , _164 ) . | |
140 | exec :- reverse_2( _163 , _164 ) . | |
141 | exec :- nonzero_1( _163 , _164 ) . | |
142 | exec :- zero_1( _163 , _164 ) . | |
143 | exec :- writekalahs_2( _163 , _164 ) . | |
144 | exec :- writepile_1( _163 , _164 ) . | |
145 | exec :- displayholes_1( _163 , _164 ) . | |
146 | exec :- writestones_1( _163 , _164 ) . | |
147 | exec :- show_1( _163 , _164 ) . | |
148 | exec :- swap_2( _163 , _164 ) . | |
149 | exec :- displaygame_2( _163 , _164 ) . | |
150 | exec :- member_2( _163 , _164 ) . | |
151 | exec :- genlegal_1( _163 , _164 ) . | |
152 | exec :- legal_1( _163 , _164 ) . | |
153 | exec :- nextplayer_2( _163 , _164 ) . | |
154 | exec :- nsubstitute_4( _163 , _164 ) . | |
155 | exec :- nthmember_3( _163 , _164 ) . | |
156 | exec :- announce_1( _163 , _164 ) . | |
157 | exec :- gameover_3( _163 , _164 ) . | |
158 | exec :- value_2( _163 , _164 ) . | |
159 | exec :- distribute_3( _163 , _164 ) . | |
160 | exec :- pickupanddistribute_4( _163 , _164 ) . | |
161 | exec :- checkiffinished_2( _163 , _164 ) . | |
162 | exec :- updatekalah_5( _163 , _164 ) . | |
163 | exec :- checkcapture_7( _163 , _164 ) . | |
164 | exec :- distributemyholes_5( _163 , _164 ) . | |
165 | exec :- distributeyourholes_3( _163 , _164 ) . | |
166 | exec :- distributestones_4( _163 , _164 ) . | |
167 | exec :- stonesinhole_3( _163 , _164 ) . | |
168 | exec :- move_3( _163 , _164 ) . | |
169 | exec :- extendmove_4( _163 , _164 ) . | |
170 | exec :- move_2( _163 , _164 ) . | |
171 | exec :- allmoves_2( _163 , _164 ) . | |
172 | exec :- cutoff_9( _163 , _164 ) . | |
173 | exec :- evaluateandchoose_7( _163 , _164 ) . | |
174 | exec :- alphabeta_6( _163 , _164 ) . | |
175 | exec :- choosemove_3( _163 , _164 ) . | |
176 | exec :- play_3( _163 , _164 ) . | |
177 | exec :- play_2( _163 , _164 ) . | |
178 | ||
179 | ||
180 | show :- wr_1( _163 , _164 ) , write(wr_1( _163 , _164 )) , nl , fail . | |
181 | show :- myis_2( _163 , _164 ) , write(myis_2( _163 , _164 )) , nl , fail . | |
182 | show :- pieces_1( _163 , _164 ) , write(pieces_1( _163 , _164 )) , nl , fail . | |
183 | show :- initialize_3( _163 , _164 ) , write(initialize_3( _163 , _164 )) , nl , fail . | |
184 | show :- lookahead_1( _163 , _164 ) , write(lookahead_1( _163 , _164 )) , nl , fail . | |
185 | show :- sumlist_3( _163 , _164 ) , write(sumlist_3( _163 , _164 )) , nl , fail . | |
186 | show :- sumlist_2( _163 , _164 ) , write(sumlist_2( _163 , _164 )) , nl , fail . | |
187 | show :- rev_3( _163 , _164 ) , write(rev_3( _163 , _164 )) , nl , fail . | |
188 | show :- reverse_2( _163 , _164 ) , write(reverse_2( _163 , _164 )) , nl , fail . | |
189 | show :- nonzero_1( _163 , _164 ) , write(nonzero_1( _163 , _164 )) , nl , fail . | |
190 | show :- zero_1( _163 , _164 ) , write(zero_1( _163 , _164 )) , nl , fail . | |
191 | show :- writekalahs_2( _163 , _164 ) , write(writekalahs_2( _163 , _164 )) , nl , fail . | |
192 | show :- writepile_1( _163 , _164 ) , write(writepile_1( _163 , _164 )) , nl , fail . | |
193 | show :- displayholes_1( _163 , _164 ) , write(displayholes_1( _163 , _164 )) , nl , fail . | |
194 | show :- writestones_1( _163 , _164 ) , write(writestones_1( _163 , _164 )) , nl , fail . | |
195 | show :- show_1( _163 , _164 ) , write(show_1( _163 , _164 )) , nl , fail . | |
196 | show :- displaygame_2( _163 , _164 ) , write(displaygame_2( _163 , _164 )) , nl , fail . | |
197 | show :- swap_2( _163 , _164 ) , write(swap_2( _163 , _164 )) , nl , fail . | |
198 | show :- genlegal_1( _163 , _164 ) , write(genlegal_1( _163 , _164 )) , nl , fail . | |
199 | show :- legal_1( _163 , _164 ) , write(legal_1( _163 , _164 )) , nl , fail . | |
200 | show :- nextplayer_2( _163 , _164 ) , write(nextplayer_2( _163 , _164 )) , nl , fail . | |
201 | show :- nsubstitute_4( _163 , _164 ) , write(nsubstitute_4( _163 , _164 )) , nl , fail . | |
202 | show :- nthmember_3( _163 , _164 ) , write(nthmember_3( _163 , _164 )) , nl , fail . | |
203 | show :- announce_1( _163 , _164 ) , write(announce_1( _163 , _164 )) , nl , fail . | |
204 | show :- gameover_3( _163 , _164 ) , write(gameover_3( _163 , _164 )) , nl , fail . | |
205 | show :- value_2( _163 , _164 ) , write(value_2( _163 , _164 )) , nl , fail . | |
206 | show :- distribute_3( _163 , _164 ) , write(distribute_3( _163 , _164 )) , nl , fail . | |
207 | show :- pickupanddistribute_4( _163 , _164 ) , write(pickupanddistribute_4( _163 , _164 )) , nl , fail . | |
208 | show :- distributeyourholes_3( _163 , _164 ) , write(distributeyourholes_3( _163 , _164 )) , nl , fail . | |
209 | show :- updatekalah_5( _163 , _164 ) , write(updatekalah_5( _163 , _164 )) , nl , fail . | |
210 | show :- checkiffinished_2( _163 , _164 ) , write(checkiffinished_2( _163 , _164 )) , nl , fail . | |
211 | show :- checkcapture_7( _163 , _164 ) , write(checkcapture_7( _163 , _164 )) , nl , fail . | |
212 | show :- distributemyholes_5( _163 , _164 ) , write(distributemyholes_5( _163 , _164 )) , nl , fail . | |
213 | show :- distributestones_4( _163 , _164 ) , write(distributestones_4( _163 , _164 )) , nl , fail . | |
214 | show :- move_3( _163 , _164 ) , write(move_3( _163 , _164 )) , nl , fail . | |
215 | show :- extendmove_4( _163 , _164 ) , write(extendmove_4( _163 , _164 )) , nl , fail . | |
216 | show :- stonesinhole_3( _163 , _164 ) , write(stonesinhole_3( _163 , _164 )) , nl , fail . | |
217 | show :- member_2( _163 , _164 ) , write(member_2( _163 , _164 )) , nl , fail . | |
218 | show :- move_2( _163 , _164 ) , write(move_2( _163 , _164 )) , nl , fail . | |
219 | show :- cutoff_9( _163 , _164 ) , write(cutoff_9( _163 , _164 )) , nl , fail . | |
220 | show :- evaluateandchoose_7( _163 , _164 ) , write(evaluateandchoose_7( _163 , _164 )) , nl , fail . | |
221 | show :- allmoves_2( _163 , _164 ) , write(allmoves_2( _163 , _164 )) , nl , fail . | |
222 | show :- alphabeta_6( _163 , _164 ) , write(alphabeta_6( _163 , _164 )) , nl , fail . | |
223 | show :- choosemove_3( _163 , _164 ) , write(choosemove_3( _163 , _164 )) , nl , fail . | |
224 | show :- play_3( _163 , _164 ) , write(play_3( _163 , _164 )) , nl , fail . | |
225 | show :- play_2( _163 , _164 ) , write(play_2( _163 , _164 )) , nl , fail . |
0 | ||
1 | :- import xsb_error_get_tag/2 from error_handler. | |
2 | ||
3 | %test:- | |
4 | % test_fail,write('fail succeeded!'). | |
5 | test:- | |
6 | catch(test_error,E, | |
7 | ( xsb_error_get_tag(E,T), | |
8 | numbervars(T, 0, _, [singletons(true)]), | |
9 | format('~p~n', [error(T)]) | |
10 | )). | |
11 | ||
12 | %test_fail:- | |
13 | % abolish_all_tables, | |
14 | % set_prolog_flag(max_table_subgoal_size,4), | |
15 | % set_prolog_flag(max_table_subgoal_size_action,failure), | |
16 | % p(_X). | |
17 | ||
18 | test_error:- | |
19 | abolish_all_tables, | |
20 | set_prolog_flag(max_table_subgoal_size,4), | |
21 | set_prolog_flag(max_table_subgoal_size_action,error), | |
22 | p(_X). | |
23 | ||
24 | :- table p/1. | |
25 | p(X):- p(f(X)). | |
26 | ||
27 | ||
28 | ||
29 |
0 | error(resource_error(tripwire(max_table_subgoal_size,xsb_test_calldepth:p(_)))) |
0 | :- import close_open_tables/1 from machine. | |
1 | ||
2 | :- set_prolog_flag(max_table_answer_size,25). | |
3 | :- set_prolog_flag(max_table_subgoal_size,25). | |
4 | :- set_prolog_flag(max_table_subgoal_size_action,error). | |
5 | ||
6 | :- table p/1. | |
7 | p(X):- X = f(X). | |
8 | ||
9 | :- table r/1. | |
10 | r(X):- make_term(100,X). | |
11 | ||
12 | make_term(0,0):-!. | |
13 | make_term(N,f(X)):- | |
14 | N1 is N - 1, | |
15 | make_term(N1,X). | |
16 | ||
17 | test:- set_prolog_flag(unify_with_occurs_check,off),fail. | |
18 | test:- catch(r(_X),error(_Type,context(_Msg,_)),writeln(caught_r)),fail. | |
19 | test:- catch(p(_X),error(_Type,context(_Msg,_)),writeln(caught_p)),fail. | |
20 | test:- X = f(X),catch(s(X),error(_Type,context(_Msg,_)),writeln(caught_s_1)),fail. | |
21 | test:- make_term(100,X),catch(s(X),error(_Type,context(_Msg,_)),writeln(caught_s_2)),fail. | |
22 | test:- close_open_tables(non_memory_error),fail. | |
23 | test:- abolish_all_tables,fail. | |
24 | test:- test_uwoc, fail. | |
25 | test:- set_prolog_flag(unify_with_occurs_check,off), | |
26 | set_prolog_flag(max_table_answer_size,infinite), | |
27 | set_prolog_flag(max_table_subgoal_size,infinite), | |
28 | fail. | |
29 | test. | |
30 | ||
31 | test_uwoc:- set_prolog_flag(unify_with_occurs_check,on),fail. | |
32 | test_uwoc:- catch(r(_X),error(_Type,context(_Msg,_)),writeln(uwoc_caught_r)),fail. | |
33 | test_uwoc:- catch(p(_X),error(_Type,context(_Msg,_)),writeln(uwoc_caught_p)),fail. | |
34 | test_uwoc:- X = f(X),catch(s(X),error(_Type,context(_Msg,_)),writeln(uwoc_caught_s_1)),fail. | |
35 | test_uwoc:- make_term(100,X),catch(s(X),error(_Type,context(_Msg,_)),writeln(uwoc_caught_s_2)),fail. | |
36 | ||
37 | :- table s/1. | |
38 | s(_). |
0 | ||
1 | /* Test of handling large subgoals and answers */ | |
2 | ||
3 | test:- test_large_ground_subgoal,writeln(test_large_ground_subgoal),fail. | |
4 | test:- test_large_ground_answer,writeln(test_large_ground_answer),fail. | |
5 | test:- test_subgoal_abstraction(50000,_L),writeln(test_subgoal_abstraction),fail. | |
6 | test:- test_answer_abstraction(50000,_L),writeln(test_answer_abstraction),fail. | |
7 | test:- test_subgoal_answer_abstraction(50000,_L,_M),writeln(test_subgoal_answer_abstraction),fail. | |
8 | test:- catch(test_var_limit(1900,_L2),_E,writeln(subgoal_var_limit_one_caught)),fail. %new | |
9 | test:- catch(test_var_limit(100000,_L2),_E,writeln(subgoal_var_limit_two_tested)),fail. | |
10 | test:- catch(a_var(100000,_L2),_E,writeln(answer_var_limit_tested)),fail. | |
11 | test. | |
12 | ||
13 | %--------- | |
14 | ||
15 | test_large_ground_subgoal:- makelist(50000,X),s(X). | |
16 | :-table s/1. | |
17 | s(_X). | |
18 | ||
19 | %--------- | |
20 | ||
21 | test_large_ground_answer:- a(50000,_X). | |
22 | :- table a/2. | |
23 | a(N,X):- makelist(N,X). | |
24 | ||
25 | %--------- | |
26 | ||
27 | :-table sa/1 as subgoal_abstract(10). | |
28 | sa(_X). | |
29 | ||
30 | test_subgoal_abstraction(N,L):- | |
31 | abolish_all_tables, | |
32 | set_prolog_flag(max_table_subgoal_size_action,abstract), | |
33 | makelist(N,L), | |
34 | sa(L). | |
35 | ||
36 | :- table r/2. | |
37 | r(N,L):- makelist(N,L). | |
38 | ||
39 | %--------- | |
40 | ||
41 | test_answer_abstraction(N,L):- | |
42 | abolish_all_tables, | |
43 | set_prolog_flag(max_table_answer_size,10), | |
44 | set_prolog_flag(max_table_answer_size_action,bounded_rationality), | |
45 | r(N,L). | |
46 | ||
47 | %--------- | |
48 | ||
49 | :- table b/3 as subgoal_abstract(10). | |
50 | b(N,_L,M):- makelist(N,M). | |
51 | ||
52 | test_subgoal_answer_abstraction(N,L,M):- | |
53 | abolish_all_tables, | |
54 | set_prolog_flag(max_table_subgoal_size_action,abstract), | |
55 | set_prolog_flag(max_table_answer_size,10), | |
56 | set_prolog_flag(max_table_answer_size_action,bounded_rationality), | |
57 | makelist(N,L), | |
58 | b(N,L,M). | |
59 | ||
60 | test_var_limit(N):- | |
61 | set_prolog_flag(max_table_subgoal_var_num,N), | |
62 | set_prolog_flag(max_table_answer_var_num,N), | |
63 | test_var_limit(N,_L2). | |
64 | ||
65 | test_var_limit(N,L2):- | |
66 | set_prolog_flag(max_table_subgoal_size,10000000), | |
67 | set_prolog_flag(max_table_answer_size,10000000), | |
68 | abolish_all_tables, | |
69 | makevarlist(N,L1), | |
70 | s(L1), | |
71 | makevarlist(N,L2), | |
72 | s(L2), | |
73 | L1 = L2, | |
74 | writeln(test_var_limit_1_succeeded). | |
75 | ||
76 | %--------- | |
77 | ||
78 | test_large_nonground_answer:- a(50000,_X). | |
79 | :- table a_var/2. | |
80 | a_var(N,X):- | |
81 | makevarlist(N,X), | |
82 | writeln(test_a_var_succeeded). | |
83 | ||
84 | %--------- | |
85 | ||
86 | makelist(0,[]):- !. | |
87 | makelist(N,[N|T]):- N1 is N - 1, makelist(N1,T). | |
88 | ||
89 | makevarlist(0,[]):- !. | |
90 | makevarlist(N,[_N|T]):- N1 is N - 1, makevarlist(N1,T). | |
91 |
0 | test_large_ground_subgoal | |
1 | test_large_ground_answer | |
2 | test_subgoal_abstraction | |
3 | test_answer_abstraction | |
4 | test_subgoal_answer_abstraction | |
5 | test_var_limit_1_succeeded | |
6 | test_var_limit_1_succeeded | |
7 | test_a_var_succeeded |
2 | 2 | get_residual(p(3,3),[]) |
3 | 3 | get_residual(p(4,4),[]) |
4 | 4 | get_residual(p(5,5),[]) |
5 | get_residual(p(A,B),[restraint_number_of_answers]) | |
5 | get_residual(p(A,B),[answer_count_restraint]) |
0 | ||
1 | :- table p/1. | |
2 | p(_X). | |
3 | ||
4 | :- table q/1 as subgoal_abstract(2). | |
5 | q(_X). | |
6 | ||
7 | % error -- "deep" terms | |
8 | test:- set_prolog_flag(unify_with_occurs_check,off),fail. | |
9 | test:- set_prolog_flag(max_table_subgoal_size_action,error),set_prolog_flag(max_table_subgoal_size,2),fail. | |
10 | test:- catch(p(f(f(f(1)))),_E,(writeln(error(e1)),fail)),writeln(success(e1)),fail. | |
11 | test:- abolish_table_pred(p/1),fail. | |
12 | test:- catch(p(f(f(f(1)))),_E,(writeln(error(e2)),fail)),writeln(success(e2)),fail. | |
13 | test:- abolish_table_call(p(f(f(f(1))))),fail. | |
14 | test:- abolish_all_tables,fail. | |
15 | % | |
16 | % error -- cyclic terms | |
17 | test:- X = f(X),catch(p(X),_E,(writeln(error(ce1)),fail)),writeln(success(ce1)),fail. | |
18 | test:- abolish_table_pred(p/1),fail. | |
19 | test:- X = f(X),catch(p(X),_E,(writeln(error(ce2)),fail)),writeln(success(ce2)),fail. | |
20 | test:- X = f(X),catch(abolish_table_call(p(X)),_E,(writeln(error(ce3)),fail)),fail. | |
21 | test:- abolish_all_tables,fail. | |
22 | % | |
23 | % error -- "deep" terms / tnot | |
24 | test:- catch(tnot(p(f(f(f(1))))),_E,(writeln(error(e3)),fail)),writeln(success(e3)),fail. | |
25 | test:- abolish_table_pred(p/1),fail. | |
26 | test:- catch(tnot(p(f(f(f(1))))),_E,(writeln(error(e4)),fail)),writeln(success(e4)),fail. | |
27 | test:- abolish_table_call(p(f(f(f(1))))),fail. | |
28 | test:- abolish_all_tables,fail. | |
29 | % | |
30 | % error -- cyclic terms / tnot | |
31 | test:- X = f(X),catch(tnot(p(X)),_E,(writeln(error(ce4)),fail)),writeln(success(ce4)),fail. | |
32 | test:- abolish_table_pred(p/1),fail. | |
33 | test:- X = f(X),catch(tnot(p(X)),_E,(writeln(error(ce5)),fail)),writeln(success(ce5)),fail. | |
34 | test:- X = f(X),catch(abolish_table_call(p(X)),_E,(writeln(error(ce6)),fail)),fail. | |
35 | test:- abolish_all_tables,fail. | |
36 | % | |
37 | %% abstraction -- "deep" terms | |
38 | test:- set_prolog_flag(max_table_subgoal_size_action,abstract),fail. | |
39 | test:- catch(q(f(f(f(1)))),_E,(writeln(error(a1)),fail)),writeln(success(a1)),fail. | |
40 | test:- abolish_table_pred(q/1),fail. | |
41 | test:- catch(q(f(f(f(1)))),_E,(writeln(error(a2)),fail)),writeln(success(a2)),fail. | |
42 | test:- abolish_table_call(q(f(f(f(1))))),fail. | |
43 | test:- abolish_all_tables,fail. | |
44 | % | |
45 | % abstraction -- cyclic terms | |
46 | test:- X = f(X),catch(q(X),_E,(writeln(error(ca1)),fail)),writeln(success(ca1)),fail. | |
47 | test:- abolish_table_pred(q/1),fail. | |
48 | test:- X = f(X),catch(q(X),_E,(writeln(error(ca2)),fail)),writeln(success(ca2)),fail. | |
49 | test:- X = f(X),catch(abolish_table_call(q(X)),_E,(writeln(error(cae3)),fail)),fail. | |
50 | test:- abolish_all_tables,fail. | |
51 | % | |
52 | % abstraction -- "deep" terms / tnot | |
53 | test:- catch(tnot(q(f(f(f(1))))),_E,(writeln(error(a3)),fail)),writeln(success(a3)),fail. | |
54 | test:- abolish_table_pred(q/1),fail. | |
55 | test:- catch(tnot(q(f(f(f(1))))),_E,(writeln(error(a4)),fail)),writeln(success(a4)),fail. | |
56 | test:- abolish_table_call(q(f(f(f(1))))),fail. | |
57 | test:- abolish_all_tables,fail. | |
58 | %% | |
59 | % abstraction -- cyclic terms / tnot | |
60 | test:- X = f(X),catch(tnot(q(X)),_E,(writeln(error(ca4)),fail)),writeln(success(ca3)),fail. | |
61 | test:- abolish_table_pred(q/1),fail. | |
62 | test:- X = f(X),catch(tnot(q(X)),_E,(writeln(error(ca4)),fail)),writeln(success(ca4)),fail. | |
63 | test:- X = f(X),catch(abolish_table_call(q(X)),_E,(writeln(error(cae4)),fail)),fail. | |
64 | test:- abolish_all_tables,fail. | |
65 | % | |
66 | %TBD: floundering goals are not yet detected properly | |
67 | %test:- catch(tnot(q(_X)),_E,(writeln(error(f1)),fail)),fail. | |
68 | %% | |
69 | test:- X = f(X),catch(tnot(X),_E,(writeln(error(c1)),fail)),fail. | |
70 | %% | |
71 | test:- set_prolog_flag(max_table_subgoal_size_action,error),fail. | |
72 | test. |
0 | error(a3) | |
1 | error(a4) | |
2 | error(c1) | |
3 | error(ca4) | |
4 | error(ca4) | |
5 | error(cae3) | |
6 | error(cae4) | |
7 | error(ce1) | |
8 | error(ce2) | |
9 | error(ce3) | |
10 | error(ce4) | |
11 | error(ce5) | |
12 | error(ce6) | |
13 | error(e1) | |
14 | error(e2) | |
15 | error(e3) | |
16 | error(e4) | |
17 | success(a1) | |
18 | success(a2) | |
19 | success(ca1) | |
20 | success(ca2) |
0 | ||
1 | /* | |
2 | Need to test out doubles for p3/p7 | |
3 | */ | |
4 | ||
5 | :- compiler_options([spec_off]). | |
6 | ||
7 | %:- set_prolog_flag(max_table_subgoal_size_action,failure). | |
8 | :- set_prolog_flag(max_table_subgoal_size_action,abstract). | |
9 | :- set_prolog_flag(max_table_subgoal_size,2). | |
10 | %:- import start_forest_view/1 from tables. | |
11 | %?- start_forest_view(userout). | |
12 | ||
13 | %-------------------- | |
14 | :- table p1/1. | |
15 | p1(X):- Y = f(X),p1(Y). | |
16 | p1(1). | |
17 | ||
18 | %-------------------- | |
19 | :- table p11/1. | |
20 | p11(X):- p11(f(X)). | |
21 | p11(1). | |
22 | ||
23 | %-------------------- | |
24 | :- table p12/1. | |
25 | p12(X):- Y = [X], | |
26 | % writeln(calling(p12(Y))), | |
27 | p12(Y). | |
28 | p12(1). | |
29 | ||
30 | %-------------------- | |
31 | :- table p2/1. | |
32 | p2(1). | |
33 | p2(X):- Y = f(X),p2(Y). | |
34 | ||
35 | %-------------------- | |
36 | :- table p21/1. | |
37 | p21(1). | |
38 | p21(X):- p21(f(X)). | |
39 | ||
40 | %-------------------- | |
41 | :- table p22/1. | |
42 | p22(1). | |
43 | p22(X):- p22([X]). | |
44 | ||
45 | %-------------------- | |
46 | :- table p3/1. | |
47 | p3(X):- %writeln(entering_clause(X)), | |
48 | p3(f(X)). | |
49 | % writeln(succeeded_clause(X)). | |
50 | p3(X):- %writeln(entering_fact(X)), | |
51 | X = f(1). | |
52 | %writeln(succeeded_fact(X)). | |
53 | %p3(X):- X = f(1). | |
54 | ||
55 | %p3(f(f(f(f(f(f(1))))))). | |
56 | %p3(f(f(f(f(f(1)))))). | |
57 | %-------------------- | |
58 | :- table p31/1. | |
59 | p31(X):- | |
60 | %writeln(calling([X])), | |
61 | p31([X]). | |
62 | p31([1]). | |
63 | ||
64 | %-------------------- | |
65 | ||
66 | :- table p4/1. | |
67 | %p4(f(f(f(f(f(f(1))))))). | |
68 | p4(f(1)). | |
69 | p4(X):- | |
70 | %writeln(calling(p4(f(X)))), | |
71 | p4(f(X)). | |
72 | ||
73 | %-------------------- | |
74 | ||
75 | :- table p41/1. | |
76 | p41([1]). | |
77 | p41(X):- | |
78 | %writeln(calling(p41([X]))), | |
79 | p41([X]). | |
80 | ||
81 | %-------------------- | |
82 | ||
83 | :- table p5/1. | |
84 | p5(f(g(f(1)))). | |
85 | p5(f(g(f(2)))). | |
86 | ||
87 | %-------------------- | |
88 | ||
89 | :- table p6/1. | |
90 | p6(_X). | |
91 | p6(X):- p6(f(X)). | |
92 | ||
93 | %-------------------- | |
94 | ||
95 | :- table p7/1. | |
96 | p7(X):- p7(f(X)). | |
97 | p7(_X). | |
98 | ||
99 | %-------------------- | |
100 | ||
101 | :- table d1/2. | |
102 | d1(1,1). | |
103 | d1(X,Y):- d1(f(X),f(Y)). | |
104 | ||
105 | %-------------------- | |
106 | ||
107 | :- table d11/2. | |
108 | d11(1,1). | |
109 | d11(X,Y):- d11([X],[Y]). | |
110 | ||
111 | %-------------------- | |
112 | ||
113 | :- table d2/2. | |
114 | d2(X,Y):- d2(f(X),f(Y)). | |
115 | d2(1,1). | |
116 | ||
117 | %-------------------- | |
118 | ||
119 | :- table p8/1. | |
120 | p8(X):- p8(f(X)). | |
121 | p8(f(f(f(1)))). | |
122 | p8(f(f(g(2)))). | |
123 | p8(f(f(f(3)))). | |
124 | p8(f(f(g(4)))). | |
125 | ||
126 | %-------------------- | |
127 | ||
128 | %-------------------- | |
129 | :- table n1/1. | |
130 | ||
131 | n1(X):- tnot(n1(f(X))). | |
132 | n1(1). | |
133 | ||
134 | %-------------------- | |
135 | ||
136 | test:- setof(X,p1(X),Xs), | |
137 | (Xs == [1] -> writeln('>>>>>succeeded(p1)') | |
138 | ; writeln('>>>>>failed(p1)') ),fail. | |
139 | test:- setof(X,p11(X),Xs), | |
140 | (Xs == [1] -> writeln('>>>>>succeeded(p11)') | |
141 | ; writeln('>>>>>failed(p11)') ),fail. | |
142 | test:- setof(X,p2(X),Xs), | |
143 | (Xs == [1] -> writeln('>>>>>succeeded(p2)') | |
144 | ; writeln('>>>>>failed(p2)') ),fail. | |
145 | test:- setof(X,p21(X),Xs), | |
146 | (Xs == [1] -> writeln('>>>>>succeeded(p21)') | |
147 | ; writeln('>>>>>failed(p21)') ),fail. | |
148 | test:- setof(X,p3(X),Xs), | |
149 | (Xs == [1,f(1)] -> writeln('>>>>>succeeded(p3)') | |
150 | ; writeln('>>>>>failed(p3)') ),fail. | |
151 | test:- setof(X,p31(X),Xs), | |
152 | (Xs == [1,[1]] -> writeln('>>>>>succeeded(p31)') | |
153 | ; writeln('>>>>>failed(p31)') ),fail. | |
154 | test:- setof(X,p4(X),Xs), | |
155 | (Xs == [1,f(1)] -> writeln('>>>>>succeeded(p4)') | |
156 | ; writeln('>>>>>failed(p4)') ),fail. | |
157 | test:- setof(X,p41(X),Xs), | |
158 | (Xs == [1,[1]] -> writeln('>>>>>succeeded(p41)') | |
159 | ; writeln('>>>>>failed(p41)') ),fail. | |
160 | test:- test5. | |
161 | test:- test5a. | |
162 | test:- test5b. | |
163 | test:- test6. | |
164 | test:- test7. | |
165 | test:- testd1. | |
166 | test:- testd11. | |
167 | test. | |
168 | ||
169 | test5:- abolish_all_tables, | |
170 | setof(X,p5(f(g(f(X)))),Xs), | |
171 | (Xs == [1,2] -> writeln('>>>>>succeeded(p5)') | |
172 | ; writeln('>>>>>failed(p5)') ),fail. | |
173 | test5a:- abolish_all_tables, | |
174 | (p5(_),fail ; true), | |
175 | setof(X,p5(f(g(f(X)))),Xs), | |
176 | (Xs == [1,2] -> writeln('>>>>>succeeded(p5a)') | |
177 | ; writeln('>>>>>failed(p5a)') ),fail. | |
178 | test5b:- abolish_all_tables, | |
179 | (p5(_),fail ; true), | |
180 | findall(1,p5(f(g(f(3)))),Xs), | |
181 | (Xs == [] -> writeln('>>>>>succeeded(p5b)') | |
182 | ; writeln('>>>>>failed(p5b)') ),fail. | |
183 | ||
184 | test6:- abolish_all_tables, | |
185 | (p6(_),fail ; true), | |
186 | findall(X,get_residual(p6(X),_Y),Xs), | |
187 | (Xs = [_,f(_),f(f(_))] -> writeln('>>>>>succeeded(p6)') | |
188 | ; writeln('>>>>>failed(p6)') ),fail. | |
189 | ||
190 | test7:- abolish_all_tables, | |
191 | (p7(_),fail ; true), | |
192 | findall(X,get_residual(p7(X),_Y),Xs), | |
193 | (Xs = [_,f(_),f(f(_))] -> writeln('>>>>>succeeded(p7)') | |
194 | ; writeln('>>>>>failed(p7)') ),fail. | |
195 | ||
196 | testd1:- abolish_all_tables, | |
197 | setof([X,Y],d1(X,Y),Xs), | |
198 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d1)') | |
199 | ; writeln('>>>>>failed(d1)') ),fail. | |
200 | testd11:- abolish_all_tables, | |
201 | setof([X,Y],d11(X,Y),Xs), | |
202 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d11)') | |
203 | ; writeln('>>>>>failed(d11)') ),fail. | |
204 | ||
205 | testd2:- abolish_all_tables, | |
206 | setof([X,Y],d2(X,Y),Xs), | |
207 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d2)') | |
208 | ; writeln('>>>>>failed(d2)') ),fail. |
0 | ||
1 | /* | |
2 | Need to test out doubles for p3/p7 | |
3 | */ | |
4 | ||
5 | :- compiler_options([spec_off]). | |
6 | ||
7 | :- set_prolog_flag(max_table_subgoal_size_action,abstract). | |
8 | %:- set_prolog_flag(max_table_subgoal_depth,2). | |
9 | ||
10 | %:- import start_forest_view/1 from tables. | |
11 | %?- start_forest_view(userout). | |
12 | ||
13 | %-------------------- | |
14 | :- table p1/1 as subgoal_abstract(2). | |
15 | p1(X):- Y = f(X),p1(Y). | |
16 | p1(1). | |
17 | ||
18 | %-------------------- | |
19 | :- table p11/1 as subgoal_abstract(2). | |
20 | p11(X):- p11(f(X)). | |
21 | p11(1). | |
22 | ||
23 | %-------------------- | |
24 | :- table p12/1 as subgoal_abstract(2). | |
25 | p12(X):- Y = [X], | |
26 | % writeln(calling(p12(Y))), | |
27 | p12(Y). | |
28 | p12(1). | |
29 | ||
30 | %-------------------- | |
31 | :- table p2/1 as subgoal_abstract(2). | |
32 | p2(1). | |
33 | p2(X):- Y = f(X),p2(Y). | |
34 | ||
35 | %-------------------- | |
36 | :- table p21/1 as subgoal_abstract(2). | |
37 | p21(1). | |
38 | p21(X):- p21(f(X)). | |
39 | ||
40 | %-------------------- | |
41 | :- table p22/1 as subgoal_abstract(2). | |
42 | p22(1). | |
43 | p22(X):- p22([X]). | |
44 | ||
45 | %-------------------- | |
46 | :- table p3/1 as subgoal_abstract(2). | |
47 | p3(X):- %writeln(entering_clause(X)), | |
48 | p3(f(X)). | |
49 | % writeln(succeeded_clause(X)). | |
50 | p3(X):- %writeln(entering_fact(X)), | |
51 | X = f(1). | |
52 | %writeln(succeeded_fact(X)). | |
53 | %p3(X):- X = f(1). | |
54 | ||
55 | %p3(f(f(f(f(f(f(1))))))). | |
56 | %p3(f(f(f(f(f(1)))))). | |
57 | %-------------------- | |
58 | :- table p31/1 as subgoal_abstract(2). | |
59 | p31(X):- | |
60 | %writeln(calling([X])), | |
61 | p31([X]). | |
62 | p31([1]). | |
63 | ||
64 | %-------------------- | |
65 | ||
66 | :- table p4/1 as subgoal_abstract(2). | |
67 | %p4(f(f(f(f(f(f(1))))))). | |
68 | p4(f(1)). | |
69 | p4(X):- | |
70 | %writeln(calling(p4(f(X)))), | |
71 | p4(f(X)). | |
72 | ||
73 | %-------------------- | |
74 | ||
75 | :- table p41/1 as subgoal_abstract(2). | |
76 | p41([1]). | |
77 | p41(X):- | |
78 | %writeln(calling(p41([X]))), | |
79 | p41([X]). | |
80 | ||
81 | %-------------------- | |
82 | ||
83 | :- table p5/1 as subgoal_abstract(2). | |
84 | p5(f(g(f(1)))). | |
85 | p5(f(g(f(2)))). | |
86 | ||
87 | %-------------------- | |
88 | ||
89 | :- table p6/1 as subgoal_abstract(2). | |
90 | p6(_X). | |
91 | p6(X):- p6(f(X)). | |
92 | ||
93 | %-------------------- | |
94 | ||
95 | :- table p7/1 as subgoal_abstract(2). | |
96 | p7(X):- p7(f(X)). | |
97 | p7(_X). | |
98 | ||
99 | %-------------------- | |
100 | ||
101 | :- table d1/2 as subgoal_abstract(2). | |
102 | d1(1,1). | |
103 | d1(X,Y):- d1(f(X),f(Y)). | |
104 | ||
105 | %-------------------- | |
106 | ||
107 | :- table d11/2 as subgoal_abstract(2). | |
108 | d11(1,1). | |
109 | d11(X,Y):- d11([X],[Y]). | |
110 | ||
111 | %-------------------- | |
112 | ||
113 | :- table d2/2 as subgoal_abstract(2). | |
114 | d2(X,Y):- d2(f(X),f(Y)). | |
115 | d2(1,1). | |
116 | ||
117 | %-------------------- | |
118 | ||
119 | :- table p8/1 as subgoal_abstract(2). | |
120 | p8(X):- p8(f(X)). | |
121 | p8(f(f(f(1)))). | |
122 | p8(f(f(g(2)))). | |
123 | p8(f(f(f(3)))). | |
124 | p8(f(f(g(4)))). | |
125 | ||
126 | %-------------------- | |
127 | ||
128 | %-------------------- | |
129 | :- table n1/1 as subgoal_abstract(2). | |
130 | ||
131 | n1(X):- tnot(n1(f(X))). | |
132 | n1(1). | |
133 | ||
134 | %-------------------- | |
135 | ||
136 | test:- setof(X,p1(X),Xs), | |
137 | (Xs == [1] -> writeln('>>>>>succeeded(p1)') | |
138 | ; writeln('>>>>>failed(p1)') ),fail. | |
139 | test:- setof(X,p11(X),Xs), | |
140 | (Xs == [1] -> writeln('>>>>>succeeded(p11)') | |
141 | ; writeln('>>>>>failed(p11)') ),fail. | |
142 | test:- setof(X,p2(X),Xs), | |
143 | (Xs == [1] -> writeln('>>>>>succeeded(p2)') | |
144 | ; writeln('>>>>>failed(p2)') ),fail. | |
145 | test:- setof(X,p21(X),Xs), | |
146 | (Xs == [1] -> writeln('>>>>>succeeded(p21)') | |
147 | ; writeln('>>>>>failed(p21)') ),fail. | |
148 | test:- setof(X,p3(X),Xs), | |
149 | (Xs == [1,f(1)] -> writeln('>>>>>succeeded(p3)') | |
150 | ; writeln('>>>>>failed(p3)') ),fail. | |
151 | test:- setof(X,p31(X),Xs), | |
152 | (Xs == [1,[1]] -> writeln('>>>>>succeeded(p31)') | |
153 | ; writeln('>>>>>failed(p31)') ),fail. | |
154 | test:- setof(X,p4(X),Xs), | |
155 | (Xs == [1,f(1)] -> writeln('>>>>>succeeded(p4)') | |
156 | ; writeln('>>>>>failed(p4)') ),fail. | |
157 | test:- setof(X,p41(X),Xs), | |
158 | (Xs == [1,[1]] -> writeln('>>>>>succeeded(p41)') | |
159 | ; writeln('>>>>>failed(p41)') ),fail. | |
160 | test:- test5. | |
161 | test:- test5a. | |
162 | test:- test5b. | |
163 | test:- test6. | |
164 | test:- test7. | |
165 | test:- testd1. | |
166 | test:- testd11. | |
167 | test. | |
168 | ||
169 | test5:- abolish_all_tables, | |
170 | setof(X,p5(f(g(f(X)))),Xs), | |
171 | (Xs == [1,2] -> writeln('>>>>>succeeded(p5)') | |
172 | ; writeln('>>>>>failed(p5)') ),fail. | |
173 | test5a:- abolish_all_tables, | |
174 | (p5(_),fail ; true), | |
175 | setof(X,p5(f(g(f(X)))),Xs), | |
176 | (Xs == [1,2] -> writeln('>>>>>succeeded(p5a)') | |
177 | ; writeln('>>>>>failed(p5a)') ),fail. | |
178 | test5b:- abolish_all_tables, | |
179 | (p5(_),fail ; true), | |
180 | findall(1,p5(f(g(f(3)))),Xs), | |
181 | (Xs == [] -> writeln('>>>>>succeeded(p5b)') | |
182 | ; writeln('>>>>>failed(p5b)') ),fail. | |
183 | ||
184 | test6:- abolish_all_tables, | |
185 | (p6(_),fail ; true), | |
186 | findall(X,get_residual(p6(X),_Y),Xs), | |
187 | (Xs = [_,f(_),f(f(_))] -> writeln('>>>>>succeeded(p6)') | |
188 | ; writeln('>>>>>failed(p6)') ),fail. | |
189 | ||
190 | test7:- abolish_all_tables, | |
191 | (p7(_),fail ; true), | |
192 | findall(X,get_residual(p7(X),_Y),Xs), | |
193 | (Xs = [_,f(_),f(f(_))] -> writeln('>>>>>succeeded(p7)') | |
194 | ; writeln('>>>>>failed(p7)') ),fail. | |
195 | ||
196 | testd1:- abolish_all_tables, | |
197 | setof([X,Y],d1(X,Y),Xs), | |
198 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d1)') | |
199 | ; writeln('>>>>>failed(d1)') ),fail. | |
200 | testd11:- abolish_all_tables, | |
201 | setof([X,Y],d11(X,Y),Xs), | |
202 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d11)') | |
203 | ; writeln('>>>>>failed(d11)') ),fail. | |
204 | ||
205 | testd2:- abolish_all_tables, | |
206 | setof([X,Y],d2(X,Y),Xs), | |
207 | (Xs = [[1,1]] -> writeln('>>>>>succeeded(d2)') | |
208 | ; writeln('>>>>>failed(d2)') ),fail. |
0 | >>>>>succeeded(d1) | |
1 | >>>>>succeeded(d11) | |
2 | >>>>>succeeded(p1) | |
3 | >>>>>succeeded(p11) | |
4 | >>>>>succeeded(p2) | |
5 | >>>>>succeeded(p21) | |
6 | >>>>>succeeded(p3) | |
7 | >>>>>succeeded(p31) | |
8 | >>>>>succeeded(p4) | |
9 | >>>>>succeeded(p41) | |
10 | >>>>>succeeded(p5) | |
11 | >>>>>succeeded(p5a) | |
12 | >>>>>succeeded(p5b) | |
13 | >>>>>succeeded(p6) | |
14 | >>>>>succeeded(p7) |
0 | >>>>>succeeded(d1) | |
1 | >>>>>succeeded(d11) | |
2 | >>>>>succeeded(p1) | |
3 | >>>>>succeeded(p11) | |
4 | >>>>>succeeded(p2) | |
5 | >>>>>succeeded(p21) | |
6 | >>>>>succeeded(p3) | |
7 | >>>>>succeeded(p31) | |
8 | >>>>>succeeded(p4) | |
9 | >>>>>succeeded(p41) | |
10 | >>>>>succeeded(p5) | |
11 | >>>>>succeeded(p5a) | |
12 | >>>>>succeeded(p5b) | |
13 | >>>>>succeeded(p6) | |
14 | >>>>>succeeded(p7) |
52 | 52 | )). |
53 | 53 | |
54 | 54 | run_table_test(Test) :- |
55 | reset_table_defaults, | |
55 | 56 | xsb_test(table_tests,Test,xsb_test_tables:swi_test(Test)). |
56 | 57 | |
57 | 58 | swi_test(M:_P) :- |
58 | 59 | abolish_all_tables, |
59 | M:test. | |
60 | M:test, | |
61 | reset_table_defaults. | |
62 | ||
63 | reset_table_defaults :- | |
64 | set_prolog_flag(max_table_answer_size, infinite), | |
65 | set_prolog_flag(max_table_answer_size_action, error), | |
66 | set_prolog_flag(max_table_subgoal_size, infinite), | |
67 | set_prolog_flag(max_table_subgoal_size_action, error), | |
68 | set_prolog_flag(max_answers_for_subgoal, infinite), | |
69 | set_prolog_flag(max_answers_for_subgoal_action, error). | |
70 | ||
60 | 71 | |
61 | 72 | :- begin_tests(xsb_test_tables, [sto(rational_trees)]). |
62 | 73 | |
67 | 78 | table_test(abol_test3a). % atp gc diff preds |
68 | 79 | table_test(abol_test3b). % atp gc diff preds + valid |
69 | 80 | table_test(abol_test3c). % atp gc diff preds + valid + multiple gcs |
70 | table_test(atc_test). | |
71 | 81 | table_test(abolish_cascade). % cascading abolish for subgoals with gc etc. |
72 | 82 | table_test(abolish_cascade_pred). |
73 | 83 | table_test(abolish_cycle). |
74 | 84 | table_test(abolish_dag). |
75 | 85 | table_test(abolish_neg_cycle). |
76 | 86 | table_test(abolish_neg_dag). |
87 | table_test(atc_test). | |
88 | table_test(concomp). | |
89 | table_test(expand). | |
90 | table_test(ins). | |
91 | table_test(large_arity_tables). | |
92 | table_test(lrbug). | |
93 | table_test(pps). | |
77 | 94 | table_test(pred_abolish_cycle). |
78 | 95 | table_test(pred_abolish_dag). |
79 | 96 | table_test(recursive_aboltest). |
80 | table_test(ins). | |
81 | table_test(large_arity_tables). | |
82 | table_test(concomp). | |
83 | table_test(lrbug). | |
84 | 97 | table_test(tabbug1). |
85 | table_test(pps). | |
86 | 98 | table_test(test_3vwfs_1). % WFS with answer subsumption |
87 | %table_test(test_maxans_decl). % max_answers(Count) restraint | |
99 | table_test(test_calldepth). | |
100 | table_test(test_cyclic_tabling).% Cyclic term handling | |
101 | table_test(test_large_tabled_terms). | |
102 | table_test(test_maxans_decl). % max_answers(Count) restraint | |
103 | table_test(test_negcycle). | |
104 | table_test(test_tda). % subgoal_abstract restraint (abstract) | |
105 | table_test(test_tda_i). % subgoal_abstract restraint (abstract) | |
88 | 106 | |
89 | 107 | :- end_tests(xsb_test_tables). |
1086 | 1086 | if ( d->canonical != d->name ) |
1087 | 1087 | remove_string(d->canonical); |
1088 | 1088 | PL_free(d); |
1089 | ||
1090 | return; | |
1089 | 1091 | } |
1090 | 1092 | } |
1091 | 1093 |
1714 | 1714 | setGITVersion(); |
1715 | 1715 | } |
1716 | 1716 | |
1717 | static int | |
1718 | abi_version_dict(term_t dict) | |
1719 | { GET_LD | |
1720 | const atom_t keys[] = { ATOM_foreign_interface, | |
1721 | ATOM_record, | |
1722 | ATOM_qlf, | |
1723 | ATOM_qlf_min_load, | |
1724 | ATOM_vmi, | |
1725 | ATOM_built_in }; | |
1726 | term_t values = PL_new_term_refs(6); | |
1727 | ||
1728 | return ( PL_unify_integer(values+0, PL_version(PL_VERSION_FLI)) && | |
1729 | PL_unify_integer(values+1, PL_version(PL_VERSION_REC)) && | |
1730 | PL_unify_integer(values+2, PL_version(PL_VERSION_QLF)) && | |
1731 | PL_unify_integer(values+3, PL_version(PL_VERSION_QLF_LOAD)) && | |
1732 | PL_unify_integer(values+4, PL_version(PL_VERSION_VM)) && | |
1733 | PL_unify_integer(values+5, PL_version(PL_VERSION_BUILT_IN)) && | |
1734 | ||
1735 | PL_put_dict(dict, ATOM_abi, 6, keys, values) ); | |
1736 | } | |
1737 | ||
1738 | ||
1739 | void | |
1740 | setABIVersionPrologFlag(void) | |
1741 | { GET_LD | |
1742 | fid_t fid = PL_open_foreign_frame(); | |
1743 | term_t t = PL_new_term_ref(); | |
1744 | ||
1745 | if ( abi_version_dict(t) ) | |
1746 | setPrologFlag("abi_version", FF_READONLY|FT_TERM, t); | |
1747 | ||
1748 | PL_discard_foreign_frame(fid); | |
1749 | } | |
1750 | ||
1717 | 1751 | |
1718 | 1752 | void |
1719 | 1753 | cleanupPrologFlags(void) |
74 | 74 | } |
75 | 75 | |
76 | 76 | |
77 | void | |
77 | int | |
78 | 78 | PL_save_text(PL_chars_t *text, int flags) |
79 | 79 | { if ( (flags & BUF_MALLOC) && text->storage != PL_CHARS_MALLOC ) |
80 | 80 | { size_t bl = bufsize_text(text, text->length+1); |
81 | 81 | void *new = PL_malloc(bl); |
82 | 82 | |
83 | memcpy(new, text->text.t, bl); | |
84 | text->text.t = new; | |
85 | text->storage = PL_CHARS_MALLOC; | |
83 | if ( new ) | |
84 | { memcpy(new, text->text.t, bl); | |
85 | text->text.t = new; | |
86 | text->storage = PL_CHARS_MALLOC; | |
87 | } else | |
88 | { return FALSE; | |
89 | } | |
86 | 90 | } else if ( text->storage == PL_CHARS_LOCAL ) |
87 | 91 | { Buffer b = findBuffer(BUF_RING); |
88 | 92 | size_t bl = bufsize_text(text, text->length+1); |
101 | 105 | |
102 | 106 | text->storage = PL_CHARS_RING; |
103 | 107 | } |
108 | ||
109 | return TRUE; | |
104 | 110 | } |
105 | 111 | |
106 | 112 | |
119 | 125 | { memcpy(text->buf, text->text.t, bl); |
120 | 126 | text->text.t = text->buf; |
121 | 127 | text->storage = PL_CHARS_LOCAL; |
128 | } else if ( (flags&BUF_NORING) ) | |
129 | { return PL_save_text(text, BUF_MALLOC); | |
122 | 130 | } else |
123 | 131 | { Buffer b = findBuffer(BUF_RING); |
124 | 132 | |
344 | 352 | |
345 | 353 | Sclose(fd); |
346 | 354 | |
347 | return TRUE; | |
355 | goto out; | |
348 | 356 | } else |
349 | 357 | { Sclose(fd); |
350 | 358 | if ( r != text->buf ) |
357 | 365 | { goto error; |
358 | 366 | } |
359 | 367 | |
360 | succeed; | |
368 | out: | |
369 | if ( (flags&BUF_NORING) && text->storage == PL_CHARS_RING ) | |
370 | return PL_save_text(text, BUF_MALLOC); | |
371 | ||
372 | return TRUE; | |
361 | 373 | |
362 | 374 | maybe_write: |
363 | 375 | if ( (flags & (CVT_WRITE|CVT_WRITE_CANONICAL)) ) |
78 | 78 | int PL_concat_text(int n, PL_chars_t **text, PL_chars_t *result); |
79 | 79 | |
80 | 80 | void PL_free_text(PL_chars_t *text); |
81 | void PL_save_text(PL_chars_t *text, int flags); | |
81 | int PL_save_text(PL_chars_t *text, int flags); | |
82 | 82 | |
83 | 83 | COMMON(int) PL_get_text__LD(term_t l, PL_chars_t *text, int flags ARG_LD); |
84 | 84 | COMMON(atom_t) textToAtom(PL_chars_t *text); |
0 | 0 | #define PLHOME "@PLHOME@" |
1 | 1 | #cmakedefine PLSHAREDHOME "@PLSHAREDHOME@" |
2 | #cmakedefine PLPKGNAME "@SWIPL_PKG_NAME@" | |
2 | 3 | #define PLARCH "@PLARCH@" |
3 | 4 | #define C_CC "@C_CC@" |
4 | 5 | #define C_CXX "@C_CXX@" |
3572 | 3572 | return TRUE; |
3573 | 3573 | } |
3574 | 3574 | |
3575 | if ( n1->value.f <= PLMAXINT && n1->value.f >= PLMININT ) | |
3575 | if ( n1->value.f <= (float)PLMAXINT && n1->value.f >= (float)PLMININT ) | |
3576 | 3576 | { if ( n1->value.f > 0 ) |
3577 | 3577 | { r->value.i = (int64_t)(n1->value.f + 0.5); |
3578 | 3578 | if ( r->value.i < 0 ) /* Why can this happen? */ |
506 | 506 | |
507 | 507 | int |
508 | 508 | saveWakeup(wakeup_state *state, int forceframe ARG_LD) |
509 | { Word h; | |
510 | ||
511 | state->flags = 0; | |
509 | { state->flags = 0; | |
512 | 510 | state->outofstack = LD->outofstack; |
513 | 511 | |
514 | if ( *(h=valTermRef(LD->attvar.head)) || | |
512 | if ( *valTermRef(LD->attvar.head) || | |
515 | 513 | exception_term || |
516 | 514 | forceframe ) |
517 | 515 | { term_t s; |
516 | Word h; | |
518 | 517 | |
519 | 518 | if ( !(state->fid = PL_open_foreign_frame()) ) |
520 | 519 | return FALSE; /* no space! */ |
526 | 525 | exception_term = 0; |
527 | 526 | } |
528 | 527 | |
529 | if ( *h ) | |
528 | if ( *(h=valTermRef(LD->attvar.head)) ) | |
530 | 529 | { state->flags |= WAKEUP_STATE_WAKEUP; |
531 | 530 | s = PL_new_term_refs(2); |
532 | 531 |
140 | 140 | } |
141 | 141 | |
142 | 142 | |
143 | static inline int | |
144 | is_key(word w) | |
145 | { return isAtom(w) || isTaggedInt(w); | |
146 | } | |
147 | ||
148 | ||
149 | 143 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
150 | 144 | dict_lookup_ptr() returns a pointer to the value for a given key |
151 | 145 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
198 | 192 | if ( count > 0 ) |
199 | 193 | { data++; /* skip to key */ |
200 | 194 | deRef2(data, n1); |
201 | if ( !is_key(*n1) ) | |
195 | if ( !is_dict_key(*n1) ) | |
202 | 196 | return -1; |
203 | 197 | |
204 | 198 | for(; count > 1; count--, data += 2, n1=n2) |
205 | 199 | { deRef2(data+2, n2); |
206 | if ( !is_key(*n2) ) | |
200 | if ( !is_dict_key(*n2) ) | |
207 | 201 | return -1; |
208 | 202 | if ( *n1 < *n2 ) |
209 | 203 | continue; |
590 | 584 | { Word p = valTermRef(t); |
591 | 585 | |
592 | 586 | deRef(p); |
593 | if ( is_key(*p) ) | |
587 | if ( is_dict_key(*p) ) | |
594 | 588 | { *np = *p; |
595 | 589 | return TRUE; |
596 | 590 | } |
615 | 609 | { Word np, vp; |
616 | 610 | |
617 | 611 | deRef2(&f->arguments[0], np); |
618 | if ( is_key(*np) ) | |
612 | if ( is_dict_key(*np) ) | |
619 | 613 | { *name = *np; |
620 | 614 | deRef2(&f->arguments[1], vp); |
621 | 615 | *value = linkVal(vp); |
1160 | 1154 | return FALSE; |
1161 | 1155 | |
1162 | 1156 | deRef(np); |
1163 | if ( is_key(*np) ) | |
1157 | if ( is_dict_key(*np) ) | |
1164 | 1158 | { Word vp; |
1165 | 1159 | |
1166 | 1160 | if ( (vp=dict_lookup_ptr(dict, *np PASS_LD)) ) |
1651 | 1645 | return FALSE; |
1652 | 1646 | goto retry; |
1653 | 1647 | } |
1648 | } | |
1649 | ||
1650 | return FALSE; | |
1651 | } | |
1652 | ||
1653 | ||
1654 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
1655 | Part of FLI | |
1656 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
1657 | ||
1658 | int | |
1659 | PL_get_dict_key(atom_t key, term_t dict, term_t value) | |
1660 | { GET_LD | |
1661 | word d; | |
1662 | Word vp; | |
1663 | ||
1664 | if ( !is_dict_key(key) ) | |
1665 | return -1; | |
1666 | if ( !get_dict_ex(dict, &d, FALSE PASS_LD) ) | |
1667 | return FALSE; | |
1668 | if ( (vp=dict_lookup_ptr(d, key PASS_LD)) ) | |
1669 | { *valTermRef(value) = linkVal(vp); | |
1670 | return TRUE; | |
1654 | 1671 | } |
1655 | 1672 | |
1656 | 1673 | return FALSE; |
62 | 62 | return ( fd->name == ATOM_dict && fd->arity%2 == 1 ); |
63 | 63 | } |
64 | 64 | |
65 | static inline int | |
66 | is_dict_key(word w) | |
67 | { return isAtom(w) || isTaggedInt(w); | |
68 | } | |
69 | ||
65 | 70 | #endif /*PL_DICT_H_INCLUDED*/ |
203 | 203 | }; |
204 | 204 | |
205 | 205 | |
206 | #define SIGNATURE_SEED (0x1a3be34a) | |
207 | ||
208 | static unsigned int | |
209 | predicate_signature(const Definition def) | |
210 | { char str[256]; | |
211 | ||
212 | Ssprintf(str, "%s/%d/%d", | |
213 | stringAtom(def->functor->name), | |
214 | (int)def->functor->arity, | |
215 | def->flags); | |
216 | ||
217 | return MurmurHashAligned2(str, strlen(str), SIGNATURE_SEED); | |
218 | } | |
219 | ||
220 | ||
206 | 221 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
207 | 222 | The extensions chain is used to allow calling PL_register_extensions() |
208 | 223 | *before* PL_initialise() to get foreign extensions in embedded systems |
323 | 338 | |
324 | 339 | def->impl.foreign.function = f->function; |
325 | 340 | createForeignSupervisor(def, f->function); |
341 | ||
342 | if ( !extensions_loaded ) | |
343 | GD->foreign.signature ^= predicate_signature(def); | |
326 | 344 | } else |
327 | 345 | { assert(0); |
328 | 346 | } |
3845 | 3845 | |
3846 | 3846 | |
3847 | 3847 | /******************************* |
3848 | * DICT * | |
3849 | *******************************/ | |
3850 | ||
3851 | int | |
3852 | PL_put_dict(term_t t, atom_t tag, | |
3853 | size_t len, const atom_t *keys, term_t values) | |
3854 | { GET_LD | |
3855 | Word p, p0; | |
3856 | size_t size = len*2+2; | |
3857 | ||
3858 | if ( (p0=p=allocGlobal(size)) ) | |
3859 | { *p++ = dict_functor(len); | |
3860 | if ( tag ) | |
3861 | { if ( isAtom(tag) ) | |
3862 | { *p++ = tag; | |
3863 | } else | |
3864 | { invalid: | |
3865 | gTop -= size; | |
3866 | return -1; | |
3867 | } | |
3868 | } else | |
3869 | { setVar(*p++); | |
3870 | } | |
3871 | ||
3872 | for(; len-- > 0; keys++, values++) | |
3873 | { *p++ = linkVal(valTermRef(values)); | |
3874 | if ( is_dict_key(*keys) ) | |
3875 | *p++ = *keys; | |
3876 | else | |
3877 | goto invalid; | |
3878 | } | |
3879 | ||
3880 | if ( dict_order(p0, TRUE PASS_LD) ) | |
3881 | { setHandle(t, consPtr(p0, TAG_COMPOUND|STG_GLOBAL)); | |
3882 | DEBUG(CHK_SECURE, checkStacks(NULL)); | |
3883 | return TRUE; | |
3884 | } | |
3885 | ||
3886 | gTop -= size; | |
3887 | return -2; | |
3888 | } | |
3889 | ||
3890 | return FALSE; | |
3891 | } | |
3892 | ||
3893 | ||
3894 | /******************************* | |
3848 | 3895 | * TYPE * |
3849 | 3896 | *******************************/ |
3850 | 3897 | |
4590 | 4637 | |
4591 | 4638 | return FALSE; |
4592 | 4639 | } |
4640 | ||
4641 | #ifndef SIGABRT | |
4642 | #define SIGABRT 6 /* exit 134 --> aborted */ | |
4643 | #endif | |
4593 | 4644 | |
4594 | 4645 | void |
4595 | 4646 | PL_abort_process(void) |
5298 | 5349 | |
5299 | 5350 | |
5300 | 5351 | /******************************* |
5352 | * VERSION * | |
5353 | *******************************/ | |
5354 | ||
5355 | unsigned int | |
5356 | PL_version(int which) | |
5357 | { switch(which) | |
5358 | { case PL_VERSION_SYSTEM: return PLVERSION; | |
5359 | case PL_VERSION_FLI: return PL_FLI_VERSION; | |
5360 | case PL_VERSION_REC: return PL_REC_VERSION; | |
5361 | case PL_VERSION_QLF: return PL_QLF_VERSION; | |
5362 | case PL_VERSION_QLF_LOAD: return PL_QLF_LOADVERSION; | |
5363 | case PL_VERSION_VM: return VM_SIGNATURE; | |
5364 | case PL_VERSION_BUILT_IN: return GD->foreign.signature; | |
5365 | default: return 0; | |
5366 | } | |
5367 | } | |
5368 | ||
5369 | ||
5370 | /******************************* | |
5301 | 5371 | * INIT * |
5302 | 5372 | *******************************/ |
5303 | 5373 |
438 | 438 | COMMON(int) setBackQuotes(atom_t a, unsigned int *flagp); |
439 | 439 | COMMON(int) setRationalSyntax(atom_t a, unsigned int *flagp); |
440 | 440 | COMMON(void) initPrologFlags(void); |
441 | COMMON(void) setABIVersionPrologFlag(void); | |
441 | 442 | COMMON(void) cleanupPrologFlags(void); |
442 | 443 | |
443 | 444 | /* pl-pro.c */ |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 1997-2019, University of Amsterdam | |
5 | Copyright (c) 1997-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
238 | 238 | InitialiseHandle initialise_tail; |
239 | 239 | PL_dispatch_hook_t dispatch_events; /* PL_dispatch_hook() */ |
240 | 240 | |
241 | unsigned int signature; /* Foreign predicate signature */ | |
241 | 242 | int _loaded; /* system extensions are loaded */ |
242 | 243 | } foreign; |
243 | 244 |
1056 | 1056 | cref = cref->next; |
1057 | 1057 | } |
1058 | 1058 | } |
1059 | ||
1060 | DEBUG(CHK_SECURE, | |
1061 | { for(cref=clist->first_clause; cref; cref=cref->next) | |
1062 | { assert(false(cref->value.clause, CL_ERASED)); | |
1063 | } | |
1064 | }); | |
1065 | 1059 | |
1066 | 1060 | clist->erased_clauses = 0; /* see (*) */ |
1067 | 1061 | } |
2 | 2 | Author: Jan Wielemaker |
3 | 3 | E-mail: J.Wielemaker@vu.nl |
4 | 4 | WWW: http://www.swi-prolog.org |
5 | Copyright (c) 2012-2019, University of Amsterdam | |
5 | Copyright (c) 2012-2020, University of Amsterdam | |
6 | 6 | VU University Amsterdam |
7 | 7 | CWI, Amsterdam |
8 | 8 | All rights reserved. |
115 | 115 | |
116 | 116 | |
117 | 117 | static const char * |
118 | optcmp(const char *av, const char *opt) | |
119 | { for(; *av && *opt && *av != '='; av++, opt++) | |
120 | { if ( *av == *opt || | |
121 | (*av == '-' && *opt == '_') || | |
122 | (*av == '_' && *opt == '-') ) | |
123 | continue; | |
124 | ||
125 | return NULL; | |
126 | } | |
127 | ||
128 | if ( !*opt ) | |
129 | { if ( *av == '=' ) | |
130 | av++; | |
131 | return av; | |
132 | } else | |
133 | { return NULL; | |
134 | } | |
135 | } | |
136 | ||
137 | ||
138 | static const char * | |
118 | 139 | longopt(const char *opt, int argc, const char **argv) |
119 | { size_t optlen = strlen(opt); | |
120 | ||
121 | for(; argc > 0; argc--, argv++) | |
140 | { for(; argc > 0; argc--, argv++) | |
122 | 141 | { const char *a = argv[0]; |
142 | const char *v; | |
123 | 143 | |
124 | 144 | if ( *a++ == '-' && *a++ == '-' ) |
125 | 145 | { if ( *a == EOS ) /* --: end of args */ |
126 | 146 | return NULL; |
127 | if ( strncmp(a, opt, optlen) == 0 && a[optlen] == '=' ) | |
128 | return &a[optlen+1]; | |
147 | if ( (v=optcmp(a, opt)) && *v ) | |
148 | return v; | |
129 | 149 | } |
130 | 150 | } |
131 | 151 | |
135 | 155 | |
136 | 156 | static const char * |
137 | 157 | is_longopt(const char *optstring, const char *name) |
138 | { size_t len = strlen(name); | |
139 | ||
140 | if ( strncmp(optstring, name, len) == 0 ) | |
141 | { if ( optstring[len] == '=' ) | |
142 | return &optstring[len+1]; | |
143 | if ( optstring[len] == EOS ) | |
144 | return ""; | |
158 | { const char *v; | |
159 | ||
160 | if ( (v=optcmp(optstring, name)) ) | |
161 | { return *v ? v : ""; | |
145 | 162 | } |
146 | 163 | |
147 | 164 | return NULL; |
148 | 165 | } |
149 | 166 | |
167 | ||
168 | static const char * | |
169 | skip_wsep(const char *s) | |
170 | { if ( *s == '-' || *s == '_' ) | |
171 | s++; | |
172 | return s; | |
173 | } | |
150 | 174 | |
151 | 175 | static int |
152 | 176 | is_bool_opt(const char *opt, const char *name, int *val) |
168 | 192 | } |
169 | 193 | |
170 | 194 | return -1; |
171 | } else if ( strncmp(opt, "no-", 3) == 0 && | |
172 | (optval=is_longopt(opt+3,name)) ) | |
173 | { if ( *optval == EOS ) | |
174 | { *val = FALSE; | |
175 | return TRUE; | |
176 | } | |
177 | ||
178 | return -1; | |
179 | 195 | } else if ( strncmp(opt, "no", 2) == 0 && |
180 | (optval=is_longopt(opt+2,name)) ) | |
196 | (optval=is_longopt(skip_wsep(opt+2),name)) ) | |
181 | 197 | { if ( *optval == EOS ) |
182 | 198 | { *val = FALSE; |
183 | 199 | return TRUE; |
1113 | 1129 | "%s: Usage:\n", |
1114 | 1130 | " 1) %s [options] prolog-file ... [-- arg ...]\n", |
1115 | 1131 | " 2) %s [options] [-o executable] -c prolog-file ...\n", |
1116 | " 3) %s --help Display this message (also -h)\n", | |
1117 | " 4) %s --version Display version information\n", | |
1118 | " 4) %s --arch Display architecture\n", | |
1119 | " 6) %s --dump-runtime-variables[=format]\n" | |
1132 | " 3) %s --help Display this message (also -h)\n", | |
1133 | " 4) %s --version Display version information\n", | |
1134 | " 5) %s --abi-version Display ABI version key\n", | |
1135 | " 6) %s --arch Display architecture\n", | |
1136 | " 7) %s --dump-runtime-variables[=format]\n" | |
1120 | 1137 | " Dump link info in sh(1) format\n", |
1121 | 1138 | "\n", |
1122 | 1139 | "Options:\n", |
1137 | 1154 | " --quiet[=bool] (-q) Do (not) suppress informational messages\n", |
1138 | 1155 | " --traditional Disable extensions of version 7\n", |
1139 | 1156 | " --home=DIR Use DIR as SWI-Prolog home\n", |
1140 | " --stack_limit=size[BKMG] Specify maximum size of Prolog stacks\n", | |
1141 | " --table_space=size[BKMG] Specify maximum size of SLG tables\n", | |
1157 | " --stack-limit=size[BKMG] Specify maximum size of Prolog stacks\n", | |
1158 | " --table-space=size[BKMG] Specify maximum size of SLG tables\n", | |
1142 | 1159 | #ifdef O_PLMT |
1143 | " --shared_table_space=size[BKMG] Maximum size of shared SLG tables\n", | |
1160 | " --shared-table-space=size[BKMG] Maximum size of shared SLG tables\n", | |
1144 | 1161 | #endif |
1145 | 1162 | " --pce[=bool] Make the xpce gui available\n", |
1146 | 1163 | " --pldoc[=port] Start PlDoc server [at port]\n", |
1147 | 1164 | #ifdef __WINDOWS__ |
1148 | " --win_app Behave as Windows application\n", | |
1165 | " --win-app Behave as Windows application\n", | |
1149 | 1166 | #endif |
1150 | 1167 | #ifdef O_DEBUG |
1151 | 1168 | " -d topic,topic,... Enable C-source DEBUG channels\n", |
1152 | 1169 | #endif |
1153 | 1170 | "\n", |
1154 | 1171 | "Boolean options may be written as --name=bool, --name, --no-name ", |
1155 | "or --noname\n", | |
1172 | "or --noname.\n", | |
1173 | "Both '-' or '_' are accepted as word-separator for long options.\n", | |
1156 | 1174 | NULL |
1157 | 1175 | }; |
1158 | 1176 | const cline *lp = lines; |
1197 | 1215 | } |
1198 | 1216 | |
1199 | 1217 | |
1218 | #ifndef PLPKGNAME | |
1219 | #define PLPKGNAME "swipl" | |
1220 | #endif | |
1221 | ||
1222 | static int | |
1223 | abi_version(void) | |
1224 | { setupProlog(); | |
1225 | Sprintf(PLPKGNAME "-abi-%d-%d-%08x-%08x\n", | |
1226 | PL_FLI_VERSION, | |
1227 | PL_QLF_LOADVERSION, | |
1228 | GD->foreign.signature, | |
1229 | VM_SIGNATURE); | |
1230 | ||
1231 | return TRUE; | |
1232 | } | |
1233 | ||
1234 | ||
1200 | 1235 | static int |
1201 | 1236 | arch(void) |
1202 | 1237 | { Sprintf("%s\n", PLARCH); |
1207 | 1242 | |
1208 | 1243 | static int |
1209 | 1244 | giveVersionInfo(const char *a) |
1210 | { if ( a[0] != '-' || a[1] != '-' ) | |
1245 | { const char *v; | |
1246 | ||
1247 | if ( *a++ != '-' || *a++ != '-' ) | |
1211 | 1248 | return FALSE; |
1212 | 1249 | |
1213 | if ( streq(a, "--help") ) | |
1250 | if ( (v=is_longopt(a, "help")) && !*v ) | |
1214 | 1251 | return usage(); |
1215 | if ( streq(a, "--arch") ) | |
1252 | if ( (v=is_longopt(a, "arch")) && !*v ) | |
1216 | 1253 | return arch(); |
1217 | if ( streq(a, "--version") ) | |
1254 | if ( (v=is_longopt(a, "version")) && !*v ) | |
1218 | 1255 | return version(); |
1256 | if ( (v=is_longopt(a, "abi_version")) && !*v ) | |
1257 | return abi_version(); | |
1219 | 1258 | |
1220 | 1259 | return FALSE; |
1221 | 1260 | } |
600 | 600 | |
601 | 601 | mark.term = f; |
602 | 602 | mark.fdef = f->definition; |
603 | pushSegStack(&LD->cycle.lstack, mark, cycle_mark); | |
603 | if ( !pushSegStack(&LD->cycle.lstack, mark, cycle_mark) ) | |
604 | return FALSE; | |
604 | 605 | f->definition = (functor_t)consUInt(info->size); |
605 | 606 | /* overflow test (should not be possible) */ |
606 | 607 | DEBUG(CHK_SECURE, assert(valUInt(f->definition) == (uintptr_t)info->size)); |
614 | 615 | Sdprintf("Added %s/%d\n", |
615 | 616 | stringAtom(valueFunctor(functor)->name), |
616 | 617 | arityFunctor(functor))); |
617 | pushWorkAgenda(agenda, arity, f->arguments); | |
618 | if ( !pushWorkAgenda(agenda, arity, f->arguments) ) | |
619 | return FALSE; | |
618 | 620 | continue; |
619 | 621 | } |
620 | 622 | default: |
685 | 687 | size_t size; |
686 | 688 | size_t rsize = SIZERECORD(flags); |
687 | 689 | term_agenda agenda; |
690 | int rc; | |
688 | 691 | |
689 | 692 | DEBUG(CHK_SECURE, checkData(valTermRef(t))); |
690 | 693 | |
697 | 700 | info.lock = !(info.external || (flags&R_NOLOCK)); |
698 | 701 | |
699 | 702 | initTermAgenda(&agenda, 1, valTermRef(t)); |
700 | compile_term_to_heap(&agenda, &info PASS_LD); | |
703 | rc = compile_term_to_heap(&agenda, &info PASS_LD); | |
701 | 704 | clearTermAgenda(&agenda); |
702 | 705 | restoreVars(&info); |
703 | 706 | unvisit(PASS_LD1); |
704 | 707 | |
705 | size = rsize + sizeOfBuffer(&info.code); | |
706 | if ( allocate ) | |
707 | record = (*allocate)(closure, size); | |
708 | else | |
709 | record = PL_malloc_atomic_unmanaged(size); | |
710 | ||
711 | if ( record ) | |
712 | { | |
708 | if ( rc ) | |
709 | { size = rsize + sizeOfBuffer(&info.code); | |
710 | if ( allocate ) | |
711 | record = (*allocate)(closure, size); | |
712 | else | |
713 | record = PL_malloc_atomic_unmanaged(size); | |
714 | ||
715 | if ( record ) | |
716 | { | |
713 | 717 | #ifdef REC_MAGIC |
714 | record->magic = REC_MAGIC; | |
718 | record->magic = REC_MAGIC; | |
715 | 719 | #endif |
716 | record->gsize = (unsigned int)info.size; /* only 28-bit */ | |
717 | record->nvars = info.nvars; | |
718 | record->size = (int)size; | |
719 | record->flags = flags; | |
720 | if ( flags & R_DUPLICATE ) | |
721 | { record->references = 1; | |
722 | } | |
723 | memcpy(addPointer(record, rsize), info.code.base, sizeOfBuffer(&info.code)); | |
720 | record->gsize = (unsigned int)info.size; /* only 28-bit */ | |
721 | record->nvars = info.nvars; | |
722 | record->size = (int)size; | |
723 | record->flags = flags; | |
724 | if ( flags & R_DUPLICATE ) | |
725 | { record->references = 1; | |
726 | } | |
727 | memcpy(addPointer(record, rsize), info.code.base, sizeOfBuffer(&info.code)); | |
728 | } | |
729 | } else | |
730 | { record = NULL; | |
724 | 731 | } |
725 | 732 | discardBuffer(&info.code); |
726 | 733 | |
749 | 756 | #define REC_GROUND 0x10 /* Record is ground */ |
750 | 757 | #define REC_VMASK 0xe0 /* Version mask */ |
751 | 758 | #define REC_VSHIFT 5 /* shift for version mask */ |
752 | #define REC_VERSION 0x03 /* Version id */ | |
753 | 759 | |
754 | 760 | #define REC_SZMASK (REC_32|REC_64) /* SIZE_MASK */ |
755 | 761 | |
759 | 765 | #define REC_SZ REC_32 |
760 | 766 | #endif |
761 | 767 | |
762 | #define REC_HDR (REC_SZ|(REC_VERSION<<REC_VSHIFT)) | |
768 | #define REC_HDR (REC_SZ|(PL_REC_VERSION<<REC_VSHIFT)) | |
763 | 769 | #define REC_COMPAT(m) (((m)&(REC_VMASK|REC_SZMASK)) == REC_HDR) |
764 | 770 | |
765 | 771 | typedef struct record_data |
1843 | 1849 | if ( !b.version_map ) |
1844 | 1850 | { Sdprintf("PL_recorded_external(): " |
1845 | 1851 | "Incompatible version (%d, current %d)\n", |
1846 | save_version, REC_VERSION); | |
1852 | save_version, PL_REC_VERSION); | |
1847 | 1853 | fail; |
1848 | 1854 | } |
1849 | 1855 | } |
140 | 140 | #ifdef O_LOCALE |
141 | 141 | initLocale(); |
142 | 142 | #endif |
143 | setABIVersionPrologFlag(); | |
143 | 144 | GD->io_initialised = TRUE; |
144 | 145 | GD->clauses.cgc_space_factor = 8; |
145 | 146 | GD->clauses.cgc_stack_factor = 0.03; |
281 | 281 | { PRED_LD |
282 | 282 | PL_chars_t input, sep, pad; |
283 | 283 | int rc = FALSE; |
284 | int flags = CVT_ATOM|CVT_STRING|CVT_LIST|CVT_EXCEPTION; | |
284 | int flags = CVT_ATOM|CVT_STRING|CVT_LIST|CVT_EXCEPTION|BUF_NORING; | |
285 | 285 | |
286 | 286 | input.storage = PL_CHARS_VIRGIN; |
287 | 287 | sep.storage = PL_CHARS_VIRGIN; |
137 | 137 | static int add_answer_count_restraint(void); |
138 | 138 | static int add_radial_restraint(void); |
139 | 139 | static int tbl_wl_tripwire(worklist *wl, atom_t action, atom_t wire); |
140 | static int tbl_pred_tripwire(Definition def, atom_t action, atom_t wire); | |
140 | 141 | |
141 | 142 | #define WL_IS_SPECIAL(wl) (((intptr_t)(wl)) & 0x1) |
142 | 143 | #define WL_IS_WORKLIST(wl) ((wl) && !WL_IS_SPECIAL(wl)) |
2197 | 2198 | |
2198 | 2199 | for(; pp < ep; pp++) |
2199 | 2200 | { Word ap = *pp; |
2200 | *p++ = makeRefG(ap); | |
2201 | ||
2202 | if ( isVar(*ap) ) | |
2203 | *p++ = makeRefG(ap); | |
2204 | else | |
2205 | *p++ = *ap; | |
2201 | 2206 | } |
2202 | 2207 | |
2203 | 2208 | if ( PL_is_variable(ret) ) |
2236 | 2241 | #define AT_SHARED 0x0004 /* find a shared table */ |
2237 | 2242 | #define AT_PRIVATE 0x0008 /* find a private table */ |
2238 | 2243 | #define AT_NOCLAIM 0x0010 /* Do not claim ownership */ |
2244 | ||
2245 | ||
2246 | #define AT_ABSTRACT 0x0020 /* subgoal_abstract(N) tabling */ | |
2239 | 2247 | #define AT_SCOPE_MASK (AT_SHARED|AT_PRIVATE) |
2248 | ||
2249 | static inline size_t | |
2250 | pred_max_table_subgoal_size(const Definition def ARG_LD) | |
2251 | { size_t limit; | |
2252 | ||
2253 | limit = def->tabling ? def->tabling->subgoal_abstract : (size_t)-1; | |
2254 | if ( limit == (size_t)-1 ) | |
2255 | limit = LD->tabling.restraint.max_table_subgoal_size; | |
2256 | ||
2257 | return limit; | |
2258 | } | |
2259 | ||
2240 | 2260 | |
2241 | 2261 | static trie * |
2242 | 2262 | get_answer_table(Definition def, term_t t, term_t ret, atom_t *clrefp, |
2249 | 2269 | tmp_buffer vars; |
2250 | 2270 | mark m; |
2251 | 2271 | int shared; |
2272 | size_abstract sa = {.from_depth = 2, .size = (size_t)-1}; | |
2252 | 2273 | |
2253 | 2274 | #ifdef O_PLMT |
2254 | 2275 | if ( (flags & AT_SCOPE_MASK) ) |
2270 | 2291 | shared = FALSE; |
2271 | 2292 | #endif |
2272 | 2293 | |
2294 | if ( def ) /* otherwise we don't need it anyway */ | |
2295 | sa.size = pred_max_table_subgoal_size(def PASS_LD); | |
2273 | 2296 | variants = variant_table(shared PASS_LD); |
2274 | 2297 | initBuffer(&vars); |
2275 | 2298 | |
2276 | 2299 | retry: |
2277 | 2300 | Mark(m); |
2278 | 2301 | v = valTermRef(t); |
2279 | rc = trie_lookup(variants, NULL, &node, v, (flags&AT_CREATE), &vars PASS_LD); | |
2280 | ||
2281 | if ( rc == TRUE ) | |
2282 | { if ( node->value ) | |
2302 | rc = trie_lookup_abstract(variants, NULL, &node, v, (flags&AT_CREATE), | |
2303 | &sa, &vars PASS_LD); | |
2304 | ||
2305 | if ( rc > 0 ) | |
2306 | { if ( rc == TRIE_ABSTRACTED ) | |
2307 | { atom_t action = LD->tabling.restraint.max_table_subgoal_size_action; | |
2308 | ||
2309 | DEBUG(MSG_TABLING_RESTRAINT, | |
2310 | Sdprintf("Trapped by subgoal size restraint\n")); | |
2311 | if ( action == ATOM_abstract && !(flags&AT_ABSTRACT) ) | |
2312 | action = ATOM_error; | |
2313 | ||
2314 | if ( action != ATOM_abstract ) | |
2315 | { if ( tbl_pred_tripwire(def, action, ATOM_max_table_subgoal_size) ) | |
2316 | { sa.size = (size_t)-1; | |
2317 | emptyBuffer(&vars); | |
2318 | goto retry; | |
2319 | } else | |
2320 | { discardBuffer(&vars); | |
2321 | return NULL; | |
2322 | } | |
2323 | } | |
2324 | } | |
2325 | ||
2326 | if ( node->value ) | |
2283 | 2327 | { atrie = symbol_trie(node->value); |
2284 | 2328 | } else if ( (flags&AT_CREATE) ) |
2285 | 2329 | { atom_t symb; |
3045 | 3089 | { if ( !wrapper ) |
3046 | 3090 | wrapper = PL_new_term_ref(); |
3047 | 3091 | |
3048 | if ( unify_trie_term(atrie->data.variant, NULL, wrapper PASS_LD) ) | |
3049 | { int flags = true(atrie, TRIE_ISSHARED) ? AT_SHARED : AT_PRIVATE; | |
3050 | return ( get_answer_table(NULL, wrapper, skeleton, | |
3092 | if ( atrie->data.variant && wrapper && | |
3093 | unify_trie_term(atrie->data.variant, NULL, wrapper PASS_LD) ) | |
3094 | { worklist *wl = atrie->data.worklist; | |
3095 | Definition def = WL_IS_WORKLIST(wl) ? wl->predicate : NULL; | |
3096 | int flags = true(atrie, TRIE_ISSHARED) ? AT_SHARED : AT_PRIVATE; | |
3097 | return ( get_answer_table(def, wrapper, skeleton, | |
3051 | 3098 | NULL, flags|AT_NOCLAIM PASS_LD) != NULL); |
3052 | 3099 | } |
3053 | 3100 | |
3290 | 3337 | { Word kp; |
3291 | 3338 | trie_node *node; |
3292 | 3339 | atom_t action; |
3293 | size_t abstract; | |
3340 | size_abstract sa = {.from_depth = 2}; | |
3294 | 3341 | int rc; |
3295 | 3342 | |
3296 | 3343 | #ifdef O_PLMT |
3301 | 3348 | if ( true(wl->table, TRIE_ISMAP) ) |
3302 | 3349 | return wkl_mode_add_answer(wl, A2, A3 PASS_LD); |
3303 | 3350 | |
3304 | abstract = pred_max_table_answer_size(wl->predicate PASS_LD); | |
3351 | sa.size = pred_max_table_answer_size(wl->predicate PASS_LD); | |
3305 | 3352 | rc = trie_lookup_abstract(wl->table, NULL, &node, kp, |
3306 | TRUE, abstract, NULL PASS_LD); | |
3353 | TRUE, &sa, NULL PASS_LD); | |
3307 | 3354 | if ( rc > 0 ) /* ok or abstracted */ |
3308 | 3355 | { idg_node *idg; |
3309 | 3356 | |
4200 | 4247 | */ |
4201 | 4248 | |
4202 | 4249 | static int |
4203 | tbl_variant_table(term_t closure, term_t variant, term_t Trie, term_t status, term_t ret, | |
4204 | int flags ARG_LD) | |
4250 | tbl_variant_table(term_t closure, term_t variant, term_t Trie, | |
4251 | term_t abstract, term_t status, term_t ret, int flags ARG_LD) | |
4205 | 4252 | { trie *atrie; |
4206 | 4253 | Definition def = NULL; |
4207 | 4254 | atom_t clref = 0; |
4230 | 4277 | PRED_IMPL("$tbl_variant_table", 5, tbl_variant_table, 0) |
4231 | 4278 | { PRED_LD |
4232 | 4279 | |
4233 | return tbl_variant_table(A1, A2, A3, A4, A5, AT_CREATE PASS_LD); | |
4280 | return tbl_variant_table(A1, A2, A3, 0, A4, A5, AT_CREATE PASS_LD); | |
4281 | } | |
4282 | ||
4283 | ||
4284 | /** '$tbl_abstract_table'(+Closure, :Wrapper, -Trie, | |
4285 | -Abstract, -Status, -Skeleton) | |
4286 | ||
4287 | Abstract is one of `0` or a generalization of Wrapper | |
4288 | */ | |
4289 | ||
4290 | static | |
4291 | PRED_IMPL("$tbl_abstract_table", 6, tbl_abstract_table, 0) | |
4292 | { PRED_LD | |
4293 | ||
4294 | return tbl_variant_table(A1, A2, A3, A4, A5, A6, AT_CREATE|AT_ABSTRACT PASS_LD); | |
4234 | 4295 | } |
4235 | 4296 | |
4236 | 4297 | |
4238 | 4299 | PRED_IMPL("$tbl_moded_variant_table", 5, tbl_moded_variant_table, 0) |
4239 | 4300 | { PRED_LD |
4240 | 4301 | |
4241 | return tbl_variant_table(A1, A2, A3, A4, A5, AT_CREATE|AT_MODED PASS_LD); | |
4302 | return tbl_variant_table(A1, A2, A3, 0, A4, A5, AT_CREATE|AT_MODED PASS_LD); | |
4242 | 4303 | } |
4243 | 4304 | |
4244 | 4305 | |
6490 | 6551 | PL_put_atom(av+0, wire) && |
6491 | 6552 | PL_put_atom(av+1, action) && |
6492 | 6553 | PL_put_atom(av+2, trie_symbol(wl->table)) && |
6554 | PL_call_predicate(NULL, PL_Q_PASS_EXCEPTION, pred, av) ); | |
6555 | } | |
6556 | ||
6557 | ||
6558 | static int | |
6559 | tbl_pred_tripwire(Definition def, atom_t action, atom_t wire) | |
6560 | { GET_LD | |
6561 | static predicate_t pred = NULL; | |
6562 | term_t av; | |
6563 | ||
6564 | if ( !pred ) | |
6565 | pred = PL_predicate("tripwire", 3, "$tabling"); | |
6566 | ||
6567 | DEBUG(MSG_TABLING_RESTRAINT, | |
6568 | Sdprintf("Calling %s\n", procedureName(pred))); | |
6569 | ||
6570 | return ( (av = PL_new_term_refs(3)) && | |
6571 | PL_put_atom(av+0, wire) && | |
6572 | PL_put_atom(av+1, action) && | |
6573 | unify_definition(MODULE_user, av+2, def, 0, GP_QUALIFY) && | |
6493 | 6574 | PL_call_predicate(NULL, PL_Q_PASS_EXCEPTION, pred, av) ); |
6494 | 6575 | } |
6495 | 6576 | |
6814 | 6895 | PRED_DEF("$tbl_wkl_answer_trie", 2, tbl_wkl_answer_trie, 0) |
6815 | 6896 | PRED_DEF("$tbl_wkl_work", 6, tbl_wkl_work, NDET) |
6816 | 6897 | PRED_DEF("$tbl_variant_table", 5, tbl_variant_table, 0) |
6898 | PRED_DEF("$tbl_abstract_table", 6, tbl_abstract_table, 0) | |
6817 | 6899 | PRED_DEF("$tbl_existing_variant_table", 5, tbl_existing_variant_table, 0) |
6818 | 6900 | PRED_DEF("$tbl_moded_variant_table", 5, tbl_moded_variant_table, 0) |
6819 | 6901 | #ifdef O_PLMT |
1860 | 1860 | ldnew->prolog_flag.table = copyHTable(ldold->prolog_flag.table); |
1861 | 1861 | PL_UNLOCK(L_PLFLAG); |
1862 | 1862 | } |
1863 | ldnew->tabling.restraint = ldold->tabling.restraint; | |
1863 | 1864 | if ( !ldnew->thread.info->debug ) |
1864 | 1865 | { ldnew->_debugstatus.tracing = FALSE; |
1865 | 1866 | ldnew->_debugstatus.debugging = DBG_OFF; |
665 | 665 | |
666 | 666 | int |
667 | 667 | trie_lookup_abstract(trie *trie, trie_node *node, trie_node **nodep, |
668 | Word k, int add, size_t abstract, TmpBuffer vars ARG_LD) | |
668 | Word k, int add, size_abstract *abstract, | |
669 | TmpBuffer vars ARG_LD) | |
669 | 670 | { term_agenda_P agenda; |
670 | 671 | size_t var_number = 0; |
671 | 672 | int rc = TRUE; |
672 | 673 | size_t compounds = 0; |
673 | 674 | tmp_buffer varb; |
675 | size_abstract sa = {.from_depth = 1, .size = (size_t)-1}; | |
674 | 676 | size_t aleft = (size_t)-1; |
675 | 677 | |
676 | 678 | TRIE_STAT_INC(trie, lookups); |
677 | 679 | if ( !node ) |
678 | 680 | node = &trie->root; |
681 | if ( abstract ) | |
682 | sa = *abstract; | |
679 | 683 | |
680 | 684 | initTermAgenda_P(&agenda, 1, k); |
681 | 685 | while( node ) |
695 | 699 | break; /* finished toplevel */ |
696 | 700 | } |
697 | 701 | |
698 | if ( compounds == 1 ) | |
699 | aleft = abstract; | |
702 | if ( compounds == sa.from_depth ) | |
703 | aleft = sa.size; | |
700 | 704 | |
701 | 705 | w = *p; |
702 | 706 | switch( tag(w) ) |
703 | 707 | { case TAG_VAR: |
704 | 708 | if ( isVar(w) ) |
705 | { add_var: | |
709 | { word w2; | |
710 | ||
711 | add_var: | |
706 | 712 | if ( var_number++ == 0 && !vars ) |
707 | 713 | { vars = &varb; |
708 | 714 | initBuffer(vars); |
709 | 715 | } |
710 | 716 | addBuffer(vars, p, Word); |
711 | *p = w = ((((word)var_number))<<LMASK_BITS)|TAG_VAR; | |
717 | w2 = ((((word)var_number))<<LMASK_BITS)|TAG_VAR; | |
718 | if ( tag(w) == TAG_VAR ) | |
719 | *p = w2; | |
720 | w = w2; | |
712 | 721 | } |
713 | 722 | node = follow_node(trie, node, w, add PASS_LD); |
714 | 723 | break; |
761 | 770 | |
762 | 771 | for(; pp < ep; pp++) |
763 | 772 | { Word vp = *pp; |
764 | setVar(*vp); | |
773 | if ( tag(*vp) == TAG_VAR ) | |
774 | setVar(*vp); | |
765 | 775 | } |
766 | 776 | if ( vars == &varb ) |
767 | 777 | discardBuffer(vars); |
1301 | 1311 | |
1302 | 1312 | static int |
1303 | 1313 | trie_insert(term_t Trie, term_t Key, term_t Value, trie_node **nodep, |
1304 | int update, size_t abstract ARG_LD) | |
1314 | int update, size_abstract *abstract ARG_LD) | |
1305 | 1315 | { trie *trie; |
1306 | 1316 | |
1307 | 1317 | if ( get_trie(Trie, &trie) ) |
1383 | 1393 | PRED_IMPL("trie_insert", 3, trie_insert, 0) |
1384 | 1394 | { PRED_LD |
1385 | 1395 | |
1386 | return trie_insert(A1, A2, A3, NULL, FALSE, (size_t)-1 PASS_LD); | |
1396 | return trie_insert(A1, A2, A3, NULL, FALSE, NULL PASS_LD); | |
1387 | 1397 | } |
1388 | 1398 | |
1389 | 1399 | /** |
1399 | 1409 | PRED_IMPL("trie_insert", 2, trie_insert, 0) |
1400 | 1410 | { PRED_LD |
1401 | 1411 | |
1402 | return trie_insert(A1, A2, 0, NULL, FALSE, (size_t)-1 PASS_LD); | |
1412 | return trie_insert(A1, A2, 0, NULL, FALSE, NULL PASS_LD); | |
1403 | 1413 | } |
1404 | 1414 | |
1405 | 1415 | |
1412 | 1422 | static |
1413 | 1423 | PRED_IMPL("$trie_insert_abstract", 3, trie_insert_abstract, 0) |
1414 | 1424 | { PRED_LD |
1415 | size_t size; | |
1416 | ||
1417 | return ( PL_get_size_ex(A2, &size ) && | |
1418 | trie_insert(A1, A3, 0, NULL, FALSE, size PASS_LD) > 0 ); | |
1425 | size_abstract sa = {.from_depth = 1}; | |
1426 | ||
1427 | return ( PL_get_size_ex(A2, &sa.size ) && | |
1428 | trie_insert(A1, A3, 0, NULL, FALSE, &sa PASS_LD) > 0 ); | |
1419 | 1429 | } |
1420 | 1430 | |
1421 | 1431 | |
1432 | 1442 | PRED_IMPL("trie_update", 3, trie_update, 0) |
1433 | 1443 | { PRED_LD |
1434 | 1444 | |
1435 | return trie_insert(A1, A2, A3, NULL, TRUE, (size_t)-1 PASS_LD); | |
1445 | return trie_insert(A1, A2, A3, NULL, TRUE, NULL PASS_LD); | |
1436 | 1446 | } |
1437 | 1447 | |
1438 | 1448 | |
1452 | 1462 | { PRED_LD |
1453 | 1463 | trie_node *node; |
1454 | 1464 | |
1455 | return ( trie_insert(A1, A2, A3, &node, FALSE, (size_t)-1 PASS_LD) && | |
1465 | return ( trie_insert(A1, A2, A3, &node, FALSE, NULL PASS_LD) && | |
1456 | 1466 | PL_unify_pointer(A4, node) ); |
1457 | 1467 | } |
1458 | 1468 |
131 | 131 | struct idg_node *IDG; /* Node in the IDG graph */ |
132 | 132 | } data; |
133 | 133 | } trie; |
134 | ||
135 | typedef struct size_abstract | |
136 | { int from_depth; /* start below depth */ | |
137 | size_t size; /* limit each term to size */ | |
138 | } size_abstract; | |
134 | 139 | |
135 | 140 | #define acquire_trie(t) ATOMIC_INC(&(t)->references) |
136 | 141 | #define release_trie(t) do { if ( ATOMIC_DEC(&(t)->references) == 0 ) \ |
168 | 173 | term_t term ARG_LD); |
169 | 174 | COMMON(int) trie_lookup_abstract(trie *trie, |
170 | 175 | trie_node *root, trie_node **nodep, Word k, |
171 | int add, size_t abstract, | |
176 | int add, size_abstract *abstract, | |
172 | 177 | TmpBuffer vars ARG_LD); |
173 | 178 | COMMON(int) trie_error(int rc, term_t culprit); |
174 | 179 | COMMON(int) trie_trie_error(int rc, trie *trie); |
195 | 200 | trie_lookup(trie *trie, trie_node *node, trie_node **nodep, |
196 | 201 | Word k, int add, TmpBuffer vars ARG_LD) |
197 | 202 | { return trie_lookup_abstract(trie, node, nodep, k, add, |
198 | (size_t)-1, vars PASS_LD); | |
203 | NULL, vars PASS_LD); | |
199 | 204 | } |
200 | 205 | |
201 | 206 | #endif /*_PL_TRIE_H*/ |
4136 | 4136 | FR->clause = NULL; |
4137 | 4137 | goto exit_checking_wakeup; |
4138 | 4138 | case FALSE: |
4139 | FR->clause = NULL; | |
4139 | 4140 | if ( exception_term ) |
4140 | 4141 | THROW_EXCEPTION; |
4141 | 4142 | DEBUG(CHK_SECURE, assert(BFR->value.PC == PC)); |
174 | 174 | first. The last byte has its 0x80 mask set. |
175 | 175 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ |
176 | 176 | |
177 | #define LOADVERSION 67 /* load all versions later >= X */ | |
178 | #define VERSION 67 /* save version number */ | |
179 | 177 | #define QLFMAGICNUM 0x716c7374 /* "qlst" on little-endian machine */ |
180 | 178 | |
181 | 179 | #define XR_REF 0 /* reference to previous */ |
2822 | 2820 | { IOSTREAM *fd = state->wicFd; |
2823 | 2821 | |
2824 | 2822 | putMagic(saveMagic, fd); |
2825 | putInt64(VERSION, fd); | |
2823 | putInt64(PL_QLF_VERSION, fd); | |
2826 | 2824 | putInt64(VM_SIGNATURE, fd); |
2827 | 2825 | if ( systemDefaults.home ) |
2828 | 2826 | putString(systemDefaults.home, STR_NOLEN, fd); |
3044 | 3042 | if ( cversion ) |
3045 | 3043 | { int vm_signature; |
3046 | 3044 | |
3047 | if ( !PL_unify_integer(cversion, VERSION) || | |
3048 | !PL_unify_integer(minload, LOADVERSION) || | |
3045 | if ( !PL_unify_integer(cversion, PL_QLF_VERSION) || | |
3046 | !PL_unify_integer(minload, PL_QLF_LOADVERSION) || | |
3049 | 3047 | !PL_unify_integer(csig, (int)VM_SIGNATURE) ) |
3050 | 3048 | goto out; |
3051 | 3049 | |
3175 | 3173 | initSourceMarks(state); |
3176 | 3174 | |
3177 | 3175 | putMagic(qlfMagic, state->wicFd); |
3178 | putInt64(VERSION, state->wicFd); | |
3176 | putInt64(PL_QLF_VERSION, state->wicFd); | |
3179 | 3177 | putInt64(VM_SIGNATURE, state->wicFd); |
3180 | 3178 | |
3181 | 3179 | putString(absname, STR_NOLEN, state->wicFd); |
3324 | 3322 | |
3325 | 3323 | if ( !qlfVersion(state, magic, &lversion) ) |
3326 | 3324 | return FALSE; |
3327 | if ( lversion < LOADVERSION ) | |
3325 | if ( lversion < PL_QLF_LOADVERSION ) | |
3328 | 3326 | return qlfError(state, "incompatible version (file: %d, Prolog: %d)", |
3329 | lversion, VERSION); | |
3327 | lversion, PL_QLF_VERSION); | |
3330 | 3328 | state->saved_version = lversion; |
3331 | 3329 | |
3332 | 3330 | vm_signature = getInt(state->wicFd); |
360 | 360 | } |
361 | 361 | |
362 | 362 | |
363 | /** '$wrapped_implementation'(:Goal, +Name, -Wrapped) | |
364 | * | |
365 | * Calling Wrapped calls the predicate referenced by Goal as seen | |
366 | * from the wrapper Name. | |
367 | */ | |
368 | ||
369 | static | |
370 | PRED_IMPL("$wrapped_implementation", 3, wrapped_implementation, | |
371 | PL_FA_TRANSPARENT) | |
372 | { PRED_LD | |
373 | Procedure proc; | |
374 | atom_t wname; | |
375 | Code codes; | |
376 | term_t head = PL_new_term_ref(); | |
377 | ||
378 | if ( !PL_get_atom_ex(A2, &wname) || | |
379 | !get_procedure(A1, &proc, head, GP_RESOLVE) ) | |
380 | return FALSE; | |
381 | ||
382 | if ( (codes = find_wrapper(proc->definition, wname)) ) | |
383 | { atom_t aref = codes[2]; | |
384 | size_t arity = proc->definition->functor->arity; | |
385 | ||
386 | if ( arity > 0 ) | |
387 | { Word p; | |
388 | term_t impl = PL_new_term_ref(); | |
389 | ||
390 | if ( (p=allocGlobal(1+arity)) ) | |
391 | { Word a = valTermRef(head); | |
392 | size_t i; | |
393 | ||
394 | deRef(a); | |
395 | a = valueTerm(*a)->arguments; | |
396 | p[0] = lookupFunctorDef(aref, arity); | |
397 | for(i=0; i<arity; i++) | |
398 | p[i+1] = linkVal(&a[i]); | |
399 | *valTermRef(impl) = consPtr(p, TAG_COMPOUND|STG_GLOBAL); | |
400 | return PL_unify(A3, impl); | |
401 | } | |
402 | } else | |
403 | { return PL_unify_atom(A3, aref); | |
404 | } | |
405 | } | |
406 | ||
407 | return FALSE; | |
408 | } | |
409 | ||
410 | ||
363 | 411 | /** |
364 | 412 | * unwrap_predicate(:Head, ?Name) is semidet. |
365 | 413 | * |
425 | 473 | * PUBLISH PREDICATES * |
426 | 474 | *******************************/ |
427 | 475 | |
476 | #define META PL_FA_TRANSPARENT | |
477 | ||
428 | 478 | BeginPredDefs(wrap) |
429 | PRED_DEF("$c_wrap_predicate", 5, c_wrap_predicate, PL_FA_TRANSPARENT) | |
430 | PRED_DEF("unwrap_predicate", 2, uwrap_predicate, PL_FA_TRANSPARENT) | |
431 | PRED_DEF("$wrapped_predicate", 2, wrapped_predicate, PL_FA_TRANSPARENT) | |
432 | PRED_DEF("$closure_predicate", 2, closure_predicate, 0) | |
479 | PRED_DEF("$c_wrap_predicate", 5, c_wrap_predicate, META) | |
480 | PRED_DEF("unwrap_predicate", 2, uwrap_predicate, META) | |
481 | PRED_DEF("$wrapped_predicate", 2, wrapped_predicate, META) | |
482 | PRED_DEF("$wrapped_implementation", 3, wrapped_implementation, META) | |
483 | PRED_DEF("$closure_predicate", 2, closure_predicate, 0) | |
433 | 484 | EndPredDefs |
816 | 816 | PL_chars_t txt; |
817 | 817 | int rc = TRUE; |
818 | 818 | |
819 | PL_get_text(t, &txt, CVT_STRING); | |
820 | if ( txt.storage != PL_CHARS_LOCAL ) | |
821 | PL_save_text(&txt, BUF_MALLOC); | |
819 | PL_get_text(t, &txt, CVT_STRING|BUF_NORING); | |
822 | 820 | |
823 | 821 | if ( true(options, PL_WRT_QUOTED) ) |
824 | 822 | { int quote; |