PageRenderTime 535ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/src/compiler/pl2am.pl

https://code.google.com/
Perl | 1781 lines | 1617 code | 163 blank | 1 comment | 26 complexity | bd8308a3b7e3828b67af46f69277535b MD5 | raw file
Possible License(s): EPL-1.0, GPL-2.0
  1. /*****************************************************************
  2. Time-stamp: <2008-10-29 10:41:19 banbara>
  3. NAME
  4. pl2am: Translating Prolog into WAM-based Intermediate Code
  5. USAGE
  6. # sicstus
  7. ?- [pl2am].
  8. ?- pl2am([File1, File2, [Op1,..,OpN]]).
  9. PARAMETERS
  10. File1 is an input prolog file name.
  11. File2 is an output file name.
  12. Op ::= ed | ac | ie | rc | idx | clo
  13. ed : eliminate disjunctions
  14. ac : arithmetic compilation
  15. ie : inline expansion
  16. rc : optimise recursive call
  17. idx: switch_on_hash (2nd. level indexing)
  18. clo: generate closure for meta predicates
  19. DESCRIPTION
  20. This program translates Prolog program into WAM-based intermediate codes.
  21. Generated codes can be translated into Java program by using am2j.pl,
  22. and then compiled and executed by usual java utilities
  23. with the Prolog Cafe runtime system.
  24. COPYRIGHT
  25. pl2am (Translating Prolog into WAM-based Intermediate Code)
  26. Copyright (C) 1997-2008 by
  27. Mutsunori Banbara (banbara@kobe-u.ac.jp) and
  28. Naoyuki Tamura (tamura@kobe-u.ac.jp)
  29. SEE ALSO
  30. http://kaminari.istc.kobe-u.ac.jp/PrologCafe/
  31. *****************************************************************/
  32. /*****************************************************************
  33. WAM-BASED INTERMEDIATE INSTRUCTIONS
  34. Put Instructions
  35. ================
  36. put_var(X)
  37. put_int(i, X)
  38. put_float(f, X)
  39. put_con(f/n, X)
  40. put_con(c, X),
  41. put_list(Xi, Xj, Xk)
  42. put_str(Xi, Y, Xj)
  43. put_str_args([Xi,..,Xn], Y)
  44. put_clo(p:G, X)
  45. put_cont(p:BinG, C)
  46. put_cont(BinG, C)
  47. Get Instructions
  48. ================
  49. get_val(Xi, Xj)
  50. get_int(i, Xi, Xj)
  51. get_float(f, Xi, Xj)
  52. get_con(c, Xi, Xj)
  53. get_ground(g, Xi, Xj)
  54. get_list(X)
  55. get_str(f/n, Xi, Xj)
  56. Unify Instructions
  57. ==================
  58. unify_var(X)
  59. unify_val(X)
  60. unify_int(i, X)
  61. unify_float(f, X)
  62. unify_con(c, X)
  63. unify_ground(g, X)
  64. unify_void(i)
  65. Choice Instructions
  66. ===================
  67. try(Li, Lj)
  68. retry(Li, Lj)
  69. trust(L)
  70. Indexing Instructions
  71. =====================
  72. switch_on_term(Lv, Li, Lf, Lc, Ls, Ll)
  73. switch_on_hash(TAG, i, L, hashtable)
  74. Control Instructions
  75. ====================
  76. execute(p:BinG)
  77. execute(BinG)
  78. inline(G)
  79. Other Instructions
  80. ==================
  81. (:- G)
  82. comment(Message)
  83. debug(Message)
  84. info(Message)
  85. begin_predicate(p, f/n)
  86. end_predicate(p, f/n)
  87. import_package(p)
  88. import_package(p, f/n)
  89. main(f/n, public): [Instructions]
  90. main(f/n, non-public): [Instructions]
  91. L: [Instructions]
  92. label(L)
  93. deref(Ri, Rj)
  94. set(Ri, Rj)
  95. setB0
  96. goto(L)
  97. decl_term_vars([R1,...,Rn])
  98. decl_pred_vars([R1,...,Rn])
  99. new_hash(TAG, i)
  100. put_hash(X, L, TAG)
  101. static([Instructions])
  102. Notation
  103. ********
  104. X ::= a(i) | S
  105. Y ::= y(i) | S
  106. S ::= s(i) | si(i) | sf(i)
  107. L ::= f/n | f/n+i | f/n+TAG | f/n+TAG+i | f/n+TAG+i+i
  108. TAG ::= var | int | flo | con | str | lis | top | sub | nil
  109. BinG ::= C | f(A1,..,An, C)
  110. G ::= f(A1,..,An)
  111. A ::= void | X
  112. C ::= cont | p(N)
  113. R ::= cont | econt | a(i) | arg(i) | ea(i)
  114. *****************************************************************/
  115. /*****************************************************************
  116. Declarations
  117. *****************************************************************/
  118. :- op(1170, xfx, (:-)).
  119. :- op(1170, xfx, (-->)).
  120. :- op(1170, fx, (:-)).
  121. :- op(1170, fx, (?-)).
  122. :- op( 500, yfx, (#)).
  123. :- op(1150, fx, (dynamic)).
  124. :- op(1150, fx, (meta_predicate)).
  125. :- op(1150, fx, (package)). % Prolog Cafe specific
  126. :- op(1150, fx, (public)).
  127. :- op(1150, fx, (import)). % Prolog Cafe specific
  128. :- op(1150, fx, (mode)).
  129. :- op(1150, fx, (multifile)).
  130. :- op(1150, fx, (block)).
  131. :- dynamic internal_clause/2.
  132. :- dynamic internal_predicates/2.
  133. :- dynamic dynamic_predicates/2.
  134. :- dynamic meta_predicates/3.
  135. :- dynamic package_name/1.
  136. :- dynamic public_predicates/2.
  137. :- dynamic import_package/2.
  138. :- dynamic internal_declarations/1.
  139. :- dynamic file_name/1.
  140. :- dynamic dummy_clause_counter/1.
  141. :- dynamic pl2am_flag/1.
  142. :- dynamic fail_flag/0. % used for generating label(fail/0) or not
  143. % :- module('com.googlecode.prolog_cafe.compiler.pl2am', [main/0,pl2am/1]).
  144. package(_).
  145. :- package 'com.googlecode.prolog_cafe.compiler.pl2am'.
  146. :- public main/0, pl2am/1.
  147. /*****************************************************************
  148. Main
  149. *****************************************************************/
  150. main :-
  151. read(X),
  152. pl2am(X).
  153. pl2am([PrologFile, AsmFile, Opts]) :-
  154. read_in_program(PrologFile, Opts),
  155. open(AsmFile, write, Out),
  156. compile_all_predicates(Out),
  157. close(Out).
  158. pl2am(_).
  159. /*****************************************************************
  160. Read in Program
  161. *****************************************************************/
  162. read_in_program(File, Opts) :-
  163. pl2am_preread(File, Opts),
  164. open(File, read, In),
  165. repeat,
  166. read(In, X),
  167. assert_clause(X),
  168. X == end_of_file,
  169. !,
  170. close(In),
  171. pl2am_postread.
  172. %%% Pre-init
  173. pl2am_preread(File, Opts) :-
  174. retractall(internal_clause(_,_)),
  175. retractall(internal_predicates(_,_)),
  176. retractall(dynamic_predicates(_,_)),
  177. retractall(meta_predicates(_,_,_)),
  178. retractall(package_name(_)),
  179. retractall(public_predicates(_,_)),
  180. retractall(import_package(_,_)),
  181. retractall(internal_declarations(_)),
  182. retractall(file_name(_)),
  183. retractall(dummy_clause_counter(_)),
  184. retractall(pl2am_flag(_)),
  185. retractall(fail_flag),
  186. assert(file_name(File)),
  187. assert(dummy_clause_counter(0)),
  188. assert_compile_opts(Opts),
  189. assert_default_decls.
  190. assert_default_decls :-
  191. builtin_meta_predicates(Pred, Arity, Mode),
  192. assert(meta_predicates(Pred, Arity, Mode)),
  193. fail.
  194. assert_default_decls.
  195. assert_compile_opts([]) :- !.
  196. assert_compile_opts([O|Os]) :-
  197. assert_copts(O),
  198. assert_compile_opts(Os).
  199. assert_copts(O) :-
  200. clause(pl2am_flag(O), _),
  201. !.
  202. assert_copts(O) :-
  203. copt_expr(O),
  204. !,
  205. assert(pl2am_flag(O)).
  206. assert_copts(O) :-
  207. pl2am_error([O,is,an,invalid,option,for,pl2am]),
  208. fail.
  209. copt_expr(ed).
  210. copt_expr(ac).
  211. copt_expr(ie).
  212. copt_expr(rc).
  213. copt_expr(rc(_,_)).
  214. copt_expr(idx).
  215. copt_expr(clo).
  216. %%% Post-init
  217. pl2am_postread :-
  218. assert_import('com.googlecode.prolog_cafe.lang'),
  219. assert_import('com.googlecode.prolog_cafe.builtin'),
  220. assert_dummy_package,
  221. assert_dummy_public.
  222. assert_dummy_package :-
  223. clause(package_name(_), _),
  224. !.
  225. assert_dummy_package :-
  226. assert(package_name(user)).
  227. assert_dummy_public :-
  228. clause(public_predicates(_,_), _),
  229. !.
  230. assert_dummy_public :-
  231. assert(public_predicates(_,_)).
  232. %%% Assert Clauses
  233. assert_clause(end_of_file) :- !.
  234. assert_clause((:- dynamic G)) :- !,
  235. conj_to_list(G, G1),
  236. assert_dynamic_predicates(G1).
  237. assert_clause((:- module(M, PList))) :- !,
  238. assert_package(M),
  239. assert_public_predicates(PList).
  240. assert_clause((:- meta_predicate G)) :- !,
  241. conj_to_list(G, G1),
  242. assert_meta_predicates(G1).
  243. assert_clause((:- package G)) :- !,
  244. assert_package(G).
  245. assert_clause((:- public G)) :- !,
  246. conj_to_list(G, G1),
  247. assert_public_predicates(G1).
  248. assert_clause((:- import G)) :- !,
  249. assert_import(G).
  250. assert_clause((:- mode _G)) :- !,
  251. pl2am_message(['*** WARNING',mode,declaration,is,not,supported,yet]).
  252. assert_clause((:- multifile _G)) :- !,
  253. pl2am_message(['*** WARNING',multifile,declaration,is,not,supported,yet]).
  254. assert_clause((:- block _G)) :- !,
  255. pl2am_message(['*** WARNING',block,declaration,is,not,supported,yet]).
  256. assert_clause((:- G)) :- !,
  257. call(G),
  258. assert_declarations(G).
  259. assert_clause(Clause) :-
  260. preprocess(Clause, Cl),
  261. assert_cls(Cl).
  262. %%% Dynamic Declaration
  263. assert_dynamic_predicates([]) :- !.
  264. assert_dynamic_predicates([G|Gs]) :-
  265. assert_dynamic(G),
  266. assert_dynamic_predicates(Gs).
  267. assert_dynamic(G) :-
  268. \+ clause(package_name('com.googlecode.prolog_cafe.builtin'), _),
  269. G = F/A,
  270. functor(Head, F, A),
  271. system_predicate(Head),
  272. !,
  273. pl2am_error([can,not,redefine,builtin,predicate,F/A]),
  274. fail.
  275. assert_dynamic(G) :-
  276. G = F/A,
  277. clause(dynamic_predicates(F,A), _), !.
  278. assert_dynamic(G) :-
  279. G = F/A,
  280. assert(dynamic_predicates(F,A)), !.
  281. assert_dynamic(G) :-
  282. pl2am_error([G,is,an,invalid,dynamic,declaration]),
  283. fail.
  284. %%% Meta Predicates Declaration
  285. assert_meta_predicates([]) :- !.
  286. assert_meta_predicates([G|Gs]) :-
  287. assert_meta(G),
  288. assert_meta_predicates(Gs).
  289. assert_meta(G) :-
  290. functor(G, F, A),
  291. clause(meta_predicates(F, A, _), _),
  292. !.
  293. assert_meta(G) :-
  294. functor(G, F, A),
  295. G =.. [_|M],
  296. mode_expr(M),
  297. !,
  298. assert(meta_predicates(F, A, M)).
  299. assert_meta(G) :-
  300. pl2am_error([G,is,an,invalid,meta_predicate,declaration]),
  301. fail.
  302. %%% Package Declaration
  303. assert_package(G) :-
  304. clause(package_name(G1), _),
  305. G \== G1,
  306. !,
  307. pl2am_error([duplicate,package,declarations,:,G1,and,G]),
  308. fail.
  309. assert_package(G) :-
  310. atom(G),
  311. !,
  312. assert(package_name(G)),
  313. retractall(import_package(G, _)).
  314. assert_package(G) :-
  315. pl2am_error([G,is,invalid,package,declaration]),
  316. fail.
  317. %%% Public Declaration
  318. assert_public_predicates([]) :- !.
  319. assert_public_predicates([G|Gs]) :-
  320. assert_public(G),
  321. assert_public_predicates(Gs).
  322. assert_public(F/A) :-
  323. predspec_expr(F/A),
  324. clause(public_predicates(F, A), _),
  325. !.
  326. assert_public(F/A) :-
  327. predspec_expr(F/A),
  328. assert(public_predicates(F, A)).
  329. %%% Import Declaration
  330. assert_import(G) :-
  331. atom(G),
  332. !,
  333. assert_impt(G, (*)).
  334. assert_import(M:P) :-
  335. atom(M),
  336. (predspec_expr(P) ; atom(P)),
  337. !,
  338. assert_impt(M, P).
  339. assert_import(G) :-
  340. pl2am_error([G,is,invalid,import,declaration]),
  341. fail.
  342. assert_impt(M, _P) :-
  343. clause(package_name(M), _),
  344. !.
  345. assert_impt(M, P) :-
  346. clause(import_package(M, P0), _),
  347. (P0 == (*) ; P0 == P),
  348. !.
  349. assert_impt(M, P) :-
  350. assert(import_package(M, P)).
  351. %%% Assert Declaration (:- G)
  352. assert_declarations(G) :-
  353. clause(internal_declarations(G), _),
  354. !.
  355. assert_declarations(G) :-
  356. assert(internal_declarations(G)).
  357. %%% Assert Cluase
  358. assert_cls((Head :- Body)) :- !,
  359. assert_predicate(Head),
  360. assert(internal_clause(Head, Body)).
  361. assert_cls(Head) :- !,
  362. assert_predicate(Head),
  363. assert(internal_clause(Head, true)).
  364. assert_predicate(Head) :-
  365. \+ clause(package_name('com.googlecode.prolog_cafe.builtin'), _),
  366. system_predicate(Head),
  367. !,
  368. functor(Head, Functor, Arity),
  369. pl2am_error([can,not,redefine,builtin,predicate,Functor/Arity]),
  370. fail.
  371. assert_predicate(Head) :-
  372. functor(Head, Functor, Arity),
  373. clause(internal_predicates(Functor, Arity), _),
  374. !.
  375. assert_predicate(Head) :-
  376. functor(Head, Functor, Arity),
  377. assert(internal_predicates(Functor, Arity)).
  378. %%% Preprocess
  379. preprocess(Cl0, Cl) :-
  380. clause(pl2am_flag(ed), _),
  381. !,
  382. expand_term(Cl0, Cl1),
  383. eliminate_disjunction(Cl1, Cl).
  384. preprocess(Cl0, Cl) :-
  385. expand_term(Cl0, Cl).
  386. eliminate_disjunction(Cl0, Cl) :-
  387. eliminate_disj(Cl0, Cl, DummyCls),
  388. assert_dummy_clauses(DummyCls).
  389. assert_dummy_clauses([]) :- !.
  390. assert_dummy_clauses([C|Cs]) :-
  391. assert_clause(C),
  392. assert_dummy_clauses(Cs).
  393. /*****************************************************************
  394. Compile Prolog Program
  395. *****************************************************************/
  396. compile_all_predicates(Out) :- % output declarations (ex. op/3)
  397. clause(internal_declarations(G), _),
  398. writeq(Out, (:- G)), write(Out, '.'), nl(Out),
  399. fail.
  400. compile_all_predicates(_) :- % treat dynamic declaration
  401. findall(Functor/Arity, dynamic_predicates(Functor, Arity), PredSpecs),
  402. assert_init_clauses(PredSpecs),
  403. fail.
  404. compile_all_predicates(Out) :- % compile predicate
  405. clause(internal_predicates(Functor, Arity), _),
  406. compile_predicate(Functor, Arity, Instructions, []),
  407. write_asm(Out, Instructions),
  408. nl(Out),
  409. fail.
  410. compile_all_predicates(Out):- nl(Out).
  411. write_asm(_, []) :- !.
  412. write_asm(Out, [Instruction|Instructions]) :- !,
  413. write_asm(Out, Instruction),
  414. write_asm(Out, Instructions).
  415. write_asm(Out, begin_predicate(P, FA)) :- !,
  416. writeq(Out, begin_predicate(P, FA)), write(Out, '.'), nl(Out).
  417. write_asm(Out, end_predicate(P, FA)) :- !,
  418. writeq(Out, end_predicate(P, FA)), write(Out, '.'), nl(Out).
  419. write_asm(Out, comment(Comment0)) :- !,
  420. copy_term(Comment0, Comment),
  421. numbervars(Comment, 0, _),
  422. tab(Out, 8), writeq(Out, comment(Comment)), write(Out, '.'), nl(Out).
  423. write_asm(Out, (Label: Instruction)) :- !,
  424. writeq(Out, Label), write(Out, ' :'), nl(Out),
  425. write_asm(Out, Instruction).
  426. write_asm(Out, Instruction) :-
  427. tab(Out, 8), writeq(Out, Instruction), write(Out, '.'), nl(Out).
  428. /****************************************************************
  429. Treat Dynamic Declaration
  430. ****************************************************************/
  431. assert_init_clauses([]) :- !.
  432. assert_init_clauses(PredSpecs) :-
  433. collect_init_cls(PredSpecs, Cls),
  434. assert_init_cls(Cls),
  435. !.
  436. collect_init_cls([], []) :- !.
  437. collect_init_cls([F/A|FAs], [Cls|Cls1]) :-
  438. clause(internal_predicates(F,A), _),
  439. !,
  440. functor(Head, F, A),
  441. findall(assertz((Head :- Body)), internal_clause(Head, Body), Cls),
  442. retractall(internal_predicates(F,A)),
  443. retractall(internal_clause(Head, _)),
  444. collect_init_cls(FAs, Cls1).
  445. %collect_init_cls([FA|FAs], [hash_put(P,FA,[])|Cls]) :-
  446. collect_init_cls([FA|FAs], ['$new_indexing_hash'(P,FA,_)|Cls]) :-
  447. clause(package_name(P), _),
  448. !,
  449. collect_init_cls(FAs, Cls).
  450. assert_init_cls([]) :- !.
  451. assert_init_cls(Cls) :-
  452. list_to_conj(Cls, Body),
  453. assert_clause(('$init' :- Body)).
  454. /****************************************************************
  455. Compile Predicate
  456. ****************************************************************/
  457. compile_predicate(Functor, Arity) -->
  458. {functor(Head, Functor, Arity)},
  459. {findall((Head :- Body), internal_clause(Head, Body), Clauses)},
  460. {clause(package_name(P), _)},
  461. [begin_predicate(P, Functor/Arity)],
  462. generate_info(Functor, Arity),
  463. generate_import,
  464. compile_pred(Clauses, Functor/Arity),
  465. [end_predicate(P, Functor/Arity)].
  466. %%% Program Code
  467. compile_pred([], _) --> [], !.
  468. compile_pred([Clause], FA) --> !,
  469. {check_modifier(FA, MF)}, % checks public or non-public
  470. [main(FA, MF): []],
  471. [PutGroundTerm], % generates put instructions of ground terms
  472. [FA: []],
  473. [comment(Clause)],
  474. [setB0], % set B0 register for cut
  475. [DeclLocalVars], % generates the declarations of local variables
  476. {FA = _/A},
  477. set_arguments(1, A, arg, a, set), % set arg(N) to a(N).
  478. {GTI0 = [1,[],[]]}, % GTI0 = [SN,SAlloc,PutGroundTerm]
  479. compile_clause(Clause, GTI0, GTI, LTI),
  480. {GTI = [_,_,PutGroundTerm0], pl2am_rev(PutGroundTerm0, PutGroundTerm)},
  481. {LTI = [XN,_,PN|_], generate_var_decl([1,1], [XN,PN], DeclLocalVars, [])}.
  482. compile_pred(Clauses, FA) -->
  483. {check_modifier(FA, MF)}, % checks public or non-public
  484. [main(FA,MF): []],
  485. [PutGroundTerm], % generates ground terms
  486. [OPT1],
  487. [PutLabel], % generates label declarations
  488. [NewHash], % generates new_hash
  489. [PutHash], % generates pub_hash
  490. %
  491. [FA: []],
  492. {FA = Functor/Arity},
  493. set_arguments(1, Arity, arg, ea, set), % set arg(N) to engine.areg(N)
  494. [set(cont, econt)], % set cont to engine.cont
  495. [OPT2],
  496. [OPT3],
  497. [setB0], % set B0 register for cut
  498. generate_switch(Clauses, FA, GLI), % generates control and indexing instructions.
  499. {GTI0 = [1,[],[]]}, % GTI0 = [SN,SAlloc,PutGroundTerm]
  500. compile_pred2(Clauses, FA, 1, GTI0, GTI),
  501. %
  502. {GTI = [_,SAlloc,PutGroundTerm0], pl2am_rev(PutGroundTerm0, PutGroundTerm)},
  503. {GLI = [PutLabel, Hash0]},
  504. % replace the hash key with s(i), si(i), or sf(i)
  505. {replace_hash_keys(Hash0, SAlloc, NewHash, PutHash0)},
  506. {PutHash0 == [] -> PutHash = [] ; PutHash = static(PutHash0)},
  507. % generate code for the recursize call optimization
  508. {clause(pl2am_flag(rc(Functor,Arity)), _) ->
  509. OPT1 = label(FA+top), OPT2 = goto(FA+top), OPT3 = FA+top: []
  510. ;
  511. OPT1 = [], OPT2 = [], OPT3 = []
  512. }.
  513. compile_pred2([], _, _, GTI, GTI) --> !.
  514. compile_pred2([Clause|Clauses], FA, N, GTI0, GTI) -->
  515. [FA+N: []],
  516. [comment(Clause)],
  517. [DeclLocalVars], % generates the declarations of local variables
  518. [decl_pred_vars([cont])],
  519. {FA = _/Arity},
  520. set_arguments(1, Arity, ea, a, set), % set engine.areg(N) to a(N).
  521. [set(econt, cont)], % set engine.cont to cont
  522. compile_clause(Clause, GTI0, GTI1, LTI),
  523. {N1 is N + 1},
  524. compile_pred2(Clauses, FA, N1, GTI1, GTI),
  525. {LTI = [XN,_,PN|_], generate_var_decl([1,1], [XN,PN], DeclLocalVars, [])}.
  526. %%% Control and Indexing instructions
  527. generate_switch(Clauses, FA, [Label, Hash]) -->
  528. % generates try, retry, trust, switch_on_term, and switch_on_hash
  529. {generate_switch0(Clauses, FA, Instrs, [])},
  530. % generates sub-labels for BP
  531. generate_bp_label(Instrs, FA+sub, 1, Ls0, SWTs),
  532. % generates fail label (fail_flag may be asserted by generate_switch0/4)
  533. {(retract(fail_flag) -> Ls1 = [label(fail/0)|Ls0] ; Ls1 = Ls0)},
  534. % generates labels for clauses
  535. {length(Clauses, N)},
  536. {generate_cl_label(FA, 1, N, Ls2)},
  537. {pl2am_append(Ls1, Ls2, Label)},
  538. % generates new_hash and put_hash instructions for switch_on_hash
  539. {gen_hash(SWTs, Hash, [])}.
  540. generate_switch0(Clauses, FA) -->
  541. {get_indices(Clauses, FA, 1, Is)},
  542. generate_switch1(Is, FA).
  543. %%% 1st. Indexing
  544. generate_switch1(Is, FA) -->
  545. {FA = _/0},
  546. !,
  547. generate_tries(Is).
  548. generate_switch1(Is, _) -->
  549. {all_variable_indices(Is)},
  550. !,
  551. generate_tries(Is).
  552. generate_switch1(Is, FA) -->
  553. [switch_on_term(LV,LI,LF,LC,LS,LL)],
  554. generate_sw(Is, FA, var, LV, [], PIs0),
  555. generate_sw(Is, FA, int, LI, PIs0, PIs1),
  556. generate_sw(Is, FA, flo, LF, PIs1, PIs2),
  557. generate_sw(Is, FA, con, LC, PIs2, PIs3),
  558. generate_sw(Is, FA, str, LS, PIs3, PIs4),
  559. generate_sw(Is, FA, lis, LL, PIs4, _).
  560. generate_sw(Is, FA, Tag, L, PIs0, PIs) -->
  561. {select_indices(Is, Tag, Is1)},
  562. generate_sw1(Is1, FA, Tag, L, PIs0, PIs).
  563. %%% 2nd. Indexing
  564. generate_sw1([], _, _, fail/0, PIs, PIs) --> !, {assert_fail}.
  565. generate_sw1([I], _, _, L, PIs, PIs) --> !, {I = [L|_]}.
  566. generate_sw1(Is, FA, Tag, L, PIs0, PIs) -->
  567. {no_switch_on_hash(Is, Tag)},
  568. !,
  569. generate_sw2(Is, FA, Tag, L, PIs0, PIs).
  570. generate_sw1(Is, FA, Tag, FA+Tag, PIs0, PIs) -->
  571. generate_sw(Is, FA, nil, L, PIs0, PIs),
  572. {count_unique_hash(Is, Size, Keys)},
  573. [FA+Tag: switch_on_hash(Tag, Size, L, HT)],
  574. {generate_hash_table(Keys, Is, LIs)},
  575. generate_hash_tries(LIs, FA+Tag, 0, HT).
  576. no_switch_on_hash(Is, Tag) :-
  577. clause(pl2am_flag(idx), _),
  578. !,
  579. (Tag = var ; Tag = lis ; Tag = nil ; count_unique_hash(Is, C, _), C < 2).
  580. no_switch_on_hash(_, _).
  581. generate_sw2(Is, _, _, L, PIs, PIs) -->
  582. {pl2am_member((L,Is), PIs)},
  583. !.
  584. generate_sw2(Is, FA, Tag, FA+Tag, PIs0, [(FA+Tag,Is)|PIs0]) -->
  585. [FA+Tag: []],
  586. generate_tries(Is).
  587. generate_hash_tries([], _, _, []) --> !.
  588. generate_hash_tries([K:[]|LIs], L0, N, [K:fail/0|Ls]) --> !,
  589. {assert_fail},
  590. generate_hash_tries(LIs, L0, N, Ls).
  591. generate_hash_tries([K:[I]|LIs], L0, N, [K:L|Ls]) --> !,
  592. {I = [L|_]},
  593. generate_hash_tries(LIs, L0, N, Ls).
  594. generate_hash_tries([K:Is|LIs], L0, N, [K:L0+N|Ls]) -->
  595. [L0+N: []],
  596. generate_tries(Is),
  597. {N1 is N + 1},
  598. generate_hash_tries(LIs, L0, N1, Ls).
  599. generate_hash_table([], _, []) :- !.
  600. generate_hash_table([K|Ks], Is0, [K:Is|LIs]) :-
  601. select_hash(Is0, K, Is),
  602. generate_hash_table(Ks, Is0, LIs).
  603. select_hash([], _, []).
  604. select_hash([I|Is0], K, [I|Is]) :-
  605. I = [_,_,Tag,Hash],
  606. (Tag = var ; K = Hash),
  607. !,
  608. select_hash(Is0, K, Is).
  609. select_hash([_|Is0], K, Is) :-
  610. select_hash(Is0, K, Is).
  611. %%% Choice Point (try, retry, trust)
  612. generate_tries([I|Is]) -->
  613. {I = [L|_]},
  614. [try(L)],
  615. generate_tries1(Is).
  616. generate_tries1([I]) --> !,
  617. {I = [L|_]},
  618. [trust(L)].
  619. generate_tries1([I|Is]) -->
  620. {I = [L|_]},
  621. [retry(L)],
  622. generate_tries1(Is).
  623. get_indices([], _, _, []).
  624. get_indices([_|Clauses], FA, N, [[FA+N]|Is]) :-
  625. FA = _/0,
  626. !,
  627. N1 is N + 1,
  628. get_indices(Clauses, FA, N1, Is).
  629. get_indices([Clause|Clauses], FA, N, [[FA+N,A1,Tag,Hash]|Is]) :-
  630. Clause = (Head :- _),
  631. arg(1, Head, A1),
  632. get_hash(A1, Tag, Hash),
  633. N1 is N + 1,
  634. get_indices(Clauses, FA, N1, Is).
  635. get_hash(X, var, 0) :- var(X), !.
  636. get_hash(X, int, X) :- integer(X), !.
  637. get_hash(X, flo, X) :- float(X), !.
  638. get_hash(X, con, X) :- atom(X), !.
  639. get_hash(X, lis, '.'/2) :- X = [_|_], !.
  640. get_hash(X, str, F/A) :- functor(X, F, A), !.
  641. all_variable_indices([]).
  642. all_variable_indices([[_,_,var,_]|Is]) :-
  643. all_variable_indices(Is).
  644. count_unique_hash([], 0, []).
  645. count_unique_hash([I|Is], C, K) :-
  646. count_unique_hash(Is, C0, K0),
  647. I = [_,_,Tag,Hash],
  648. ((Tag = var ; pl2am_member([_,_,_,Hash], Is)) ->
  649. C = C0, K = K0
  650. ;
  651. C is C0 + 1, K = [Hash|K0]
  652. ).
  653. select_indices([], _, []).
  654. select_indices([I|Is0], Tag, [I|Is]) :-
  655. I = [_,_,T|_],
  656. (Tag = var ; Tag = T ; T = var),
  657. !,
  658. select_indices(Is0, Tag, Is).
  659. select_indices([_|Is0], Tag, Is) :-
  660. select_indices(Is0, Tag, Is).
  661. %%% Assert Fail Flag
  662. assert_fail:- clause(fail_flag, _), !.
  663. assert_fail:- assert(fail_flag).
  664. %%% Generate Labels for Backtrack Point
  665. generate_bp_label([], _, _, [], []) --> !.
  666. generate_bp_label([X|Xs], CL, N, Ls, [X|Hs]) -->
  667. {X = switch_on_hash(_,_,_,_)},
  668. !,
  669. [X],
  670. generate_bp_label(Xs, CL, N, Ls, Hs).
  671. generate_bp_label([try(L)|Xs], CL, N, [label(CL+N)|Ls], Hs) --> !,
  672. [try(L, CL+N)],
  673. [CL+N: []],
  674. {N1 is N+1},
  675. generate_bp_label(Xs, CL, N1, Ls, Hs).
  676. generate_bp_label([retry(L)|Xs], CL, N, [label(CL+N)|Ls], Hs) --> !,
  677. [retry(L, CL+N)],
  678. [CL+N: []],
  679. {N1 is N+1},
  680. generate_bp_label(Xs, CL, N1, Ls, Hs).
  681. generate_bp_label([(L:X)|Xs], _, _, [label(L)|Ls], Hs) --> !,
  682. [L: []],
  683. generate_bp_label([X|Xs], L, 1, Ls, Hs).
  684. generate_bp_label([X|Xs], CL, N, Ls, Hs) -->
  685. [X],
  686. generate_bp_label(Xs, CL, N, Ls, Hs).
  687. generate_cl_label(_, I, N, []) :-
  688. I > N,
  689. !.
  690. generate_cl_label(FA, I, N, [label(FA+I)|Ls]) :-
  691. I1 is I+1,
  692. generate_cl_label(FA, I1, N, Ls).
  693. %%% Generate Hash instructions for switch_on_hash
  694. gen_hash([]) --> !.
  695. gen_hash([switch_on_hash(T,S,_,H)|Xs]) --> !,
  696. [new_hash(T,S)],
  697. gen_put_hash(H, T),
  698. gen_hash(Xs).
  699. gen_put_hash([], _) --> !.
  700. gen_put_hash([K:V|Xs], T) -->
  701. [put_hash(K, V, T)],
  702. gen_put_hash(Xs, T).
  703. replace_hash_keys([], _, [], []) :- !.
  704. replace_hash_keys([put_hash(K,L,H)|Xs], SA, NHs, [put_hash(X,L,H)|PHs]) :- !,
  705. replace_key(K, SA, X),
  706. replace_hash_keys(Xs, SA, NHs, PHs).
  707. replace_hash_keys([X|Xs], SA, [X|NHs], PHs) :-
  708. replace_hash_keys(Xs, SA, NHs, PHs).
  709. replace_key(K, Alloc, X) :-
  710. integer(K),
  711. allocated(Alloc, K:int, [X,yes]),
  712. !.
  713. replace_key(K, Alloc, X) :-
  714. float(K),
  715. allocated(Alloc, K:flo, [X,yes]),
  716. !.
  717. replace_key(K, Alloc, X) :-
  718. atom(K),
  719. allocated(Alloc, K:con, [X,yes]),
  720. !.
  721. replace_key(K, Alloc, X) :-
  722. nonvar(K),
  723. K = F/A,
  724. atom(F),
  725. integer(A),
  726. allocated(Alloc, K:con, [X,yes]),
  727. !.
  728. replace_key(K, _, _) :-
  729. pl2am_error([replacement,of,hash,key,K,failed]),
  730. fail.
  731. %%% Import Declarations
  732. generate_import -->
  733. {findall((P,C), import_package(P, C), X)},
  734. gen_import(X).
  735. gen_import([]) --> !.
  736. gen_import([(P,'*')|Xs]) --> !,
  737. [import_package(P)],
  738. gen_import(Xs).
  739. gen_import([(P,C)|Xs]) -->
  740. [import_package(P, C)],
  741. gen_import(Xs).
  742. %%% Information
  743. generate_info(Functor, Arity) -->
  744. {clause(file_name(File), _)},
  745. [info([Functor/Arity, File])].
  746. %%% Check the Modifier of Predicate F/A.
  747. check_modifier('$init'/0, public) :- !.
  748. check_modifier(F/A, public) :-
  749. clause(public_predicates(F, A), _),
  750. !.
  751. check_modifier(_, non-public).
  752. %%% generate a list of registers with given range.
  753. range_reg(I, N, _, []) :- I > N, !.
  754. range_reg(I, N, A, [R|Rs]) :-
  755. I =< N,
  756. I1 is I+1,
  757. R =.. [A, I],
  758. range_reg(I1, N, A, Rs).
  759. %%% generate set instructions
  760. gen_set([], []) --> !.
  761. gen_set([X|Xs], [Y|Ys]) --> [set(X, Y)], gen_set(Xs, Ys).
  762. %%% generate deref instructions
  763. gen_deref([], []) --> !.
  764. gen_deref([X|Xs], [Y|Ys]) --> [deref(X, Y)], gen_deref(Xs, Ys).
  765. %%% generate set and deref instructions
  766. set_arguments(SN, EN, R1, R2, Flag) -->
  767. {range_reg(SN, EN, R1, L1)},
  768. {range_reg(SN, EN, R2, L2)},
  769. gen_set_arg(Flag, L1, L2).
  770. gen_set_arg(set, L1, L2) --> gen_set(L1, L2).
  771. gen_set_arg(deref, L1, L2) --> gen_deref(L1, L2).
  772. %%% generate decl_var instructions
  773. generate_var_decl([X0,P0], [XN,PN]) -->
  774. {X1 is XN-1, P1 is PN-1},
  775. {range_reg(X0, X1, a, XL)},
  776. {range_reg(P0, P1, p, PL)},
  777. gen_decl_term_vars(XL),
  778. gen_decl_pred_vars(PL).
  779. gen_decl_term_vars([]) --> !.
  780. gen_decl_term_vars(XL) --> [decl_term_vars(XL)].
  781. gen_decl_pred_vars([]) --> !.
  782. gen_decl_pred_vars(PL) --> [decl_pred_vars(PL)].
  783. /****************************************************************
  784. Compile Clause
  785. ****************************************************************/
  786. compile_clause((Head :- Body), GTI0, GTI, LTI) -->
  787. {pretreat_body(Body, Goals0)}, % cut, rename, compile aith exp.
  788. {localize_meta(Goals0, Goals)}, % add package name for meta predicates
  789. {precompile(Head, Goals, Instrs)}, % generate get, put, put_clo, put_cont, inline
  790. [comment((Head :- Goals))], % output precompiled clause
  791. compile_chunks(Instrs, GTI0, GTI, LTI),
  792. !.
  793. compile_clause(Clause, _, _, _) -->
  794. {pl2am_error([compilation,of,Clause,failed])},
  795. {fail}.
  796. %%%%%%%%%% Pretreat Body and Compile Arithmetic Expressions
  797. pretreat_body(Body, Goals) :-
  798. pretreat_body0(Body, Cut, Goals0, []),
  799. pretreat_cut(Cut, Goals0, Goals).
  800. pretreat_cut(Cut, Gs, Gs) :- var(Cut), !.
  801. pretreat_cut('$cut'(Level), ['$cut'(Level)|Gs], ['$neck_cut'|Gs]) :- !.
  802. pretreat_cut('$cut'(Level), Gs, ['$get_level'(Level)|Gs]).
  803. pretreat_body0(G, _) --> {var(G)}, !, [call(G)].
  804. pretreat_body0(!, Cut) --> !, {Cut = '$cut'(Level)}, ['$cut'(Level)].
  805. pretreat_body0(otherwise, _) --> !.
  806. pretreat_body0(true, _) --> !.
  807. pretreat_body0(fail, _) --> !, [fail].
  808. pretreat_body0(false, _) --> !, [fail].
  809. pretreat_body0(halt, _) --> !, [halt].
  810. pretreat_body0(abort, _) --> !, [abort].
  811. pretreat_body0((G1,G2), Cut) --> !, pretreat_body0(G1, Cut), pretreat_body0(G2, Cut).
  812. pretreat_body0(G, _) --> pretreat_builtin(G), !.
  813. pretreat_body0(G, _) --> {functor(G, F, A), clause(dynamic_predicates(F, A), _)}, !, [call(G)].
  814. pretreat_body0(G, _) --> [G].
  815. %%% rename builtins
  816. pretreat_builtin(X = Y) --> !, ['$unify'(X, Y)].
  817. pretreat_builtin(X \= Y) --> !, ['$not_unifiable'(X, Y)].
  818. pretreat_builtin(X == Y) --> !, ['$equality_of_term'(X, Y)].
  819. pretreat_builtin(X \== Y) --> !, ['$inequality_of_term'(X, Y)].
  820. pretreat_builtin(?=(X, Y)) --> !, ['$identical_or_cannot_unify'(X, Y)].
  821. pretreat_builtin(X @< Y) --> !, ['$before'(X, Y)].
  822. pretreat_builtin(X @> Y) --> !, ['$after'(X, Y)].
  823. pretreat_builtin(X @=< Y) --> !, ['$not_after'(X, Y)].
  824. pretreat_builtin(X @>= Y) --> !, ['$not_before'(X, Y)].
  825. pretreat_builtin(compare(Op,X,Y)) --> {Op == (=)}, !, ['$equality_of_term'(X, Y)].
  826. pretreat_builtin(compare(Op,X,Y)) --> {Op == (<)}, !, ['$before'(X, Y)].
  827. pretreat_builtin(compare(Op,X,Y)) --> {Op == (>)}, !, ['$after'(X, Y)].
  828. pretreat_builtin(X =.. Y) --> !, ['$univ'(X, Y)].
  829. pretreat_builtin(X =:= Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$arith_equal'(U, V)].
  830. pretreat_builtin(X =\= Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$arith_not_equal'(U, V)].
  831. pretreat_builtin(X > Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$greater_than'(U, V)].
  832. pretreat_builtin(X >= Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$greater_or_equal'(U, V)].
  833. pretreat_builtin(X < Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$less_than'(U, V)].
  834. pretreat_builtin(X =< Y) --> !, pretreat_is(U, X), pretreat_is(V, Y), ['$less_or_equal'(U, V)].
  835. pretreat_builtin(Z is X) --> !, pretreat_is0(Z, X).
  836. pretreat_is(Z, X) --> {var(X)}, !, {X = Z}.
  837. pretreat_is(Z, X) --> pretreat_is0(Z, X).
  838. pretreat_is0(Z, X) --> {clause(pl2am_flag(ac), _)}, !, precompile_is(X, Z).
  839. pretreat_is0(Z, X) --> [is(Z, X)].
  840. %%% compile aithmetic expressions
  841. precompile_is(X, A) --> {var(X)}, !, [is(A, X)].
  842. precompile_is(X, A) --> {number(X)}, !, {X = A}.
  843. precompile_is(X, A) --> {builtin_arith_constant(X)}, !, {X = A}.
  844. precompile_is(+(X), A) --> !, precomp_is(X, A).
  845. precompile_is(-(X), A) --> !, precompile_is(-1*X, A).
  846. precompile_is(X+Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$plus'(U, V, A)].
  847. precompile_is(X-Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$minus'(U, V, A)].
  848. precompile_is(X*Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$multi'(U, V, A)].
  849. precompile_is(X/Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$float_quotient'(U, V, A)].
  850. precompile_is(X//Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$int_quotient'(U, V, A)].
  851. precompile_is(X mod Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$mod'(U, V, A)].
  852. precompile_is(X rem Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$mod'(U, V, A)].
  853. precompile_is(X/\Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$bitwise_conj'(U, V, A)].
  854. precompile_is(X\/Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$bitwise_disj'(U, V, A)].
  855. precompile_is(X#Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$bitwise_exclusive_or'(U, V, A)].
  856. precompile_is(\(X), A) --> !, precomp_is(X, U), ['$bitwise_neg'(U, A)].
  857. precompile_is(X<<Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$shift_left'(U, V, A)].
  858. precompile_is(X>>Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$shift_right'(U, V, A)].
  859. precompile_is([X], A) --> !, precomp_is(X, A).
  860. precompile_is(abs(X), A) --> !, precomp_is(X, U), ['$abs'(U, A)].
  861. precompile_is(min(X,Y), A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$min'(U, V, A)].
  862. precompile_is(max(X,Y), A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$max'(U, V, A)].
  863. precompile_is(round(X), A) --> !, precomp_is(X, U), ['$round'(U, A)].
  864. precompile_is(floor(X), A) --> !, precomp_is(X, U), ['$floor'(U, A)].
  865. precompile_is(ceiling(X), A) --> !, precomp_is(X, U), ['$ceil'(U, A)].
  866. precompile_is(sin(X), A) --> !, precomp_is(X, U), ['$sin'(U, A)].
  867. precompile_is(cos(X), A) --> !, precomp_is(X, U), ['$cos'(U, A)].
  868. precompile_is(tan(X), A) --> !, precomp_is(X, U), ['$tan'(U, A)].
  869. precompile_is(asin(X), A) --> !, precomp_is(X, U), ['$asin'(U, A)].
  870. precompile_is(acos(X), A) --> !, precomp_is(X, U), ['$acos'(U, A)].
  871. precompile_is(atan(X), A) --> !, precomp_is(X, U), ['$atan'(U, A)].
  872. precompile_is(sqrt(X), A) --> !, precomp_is(X, U), ['$sqrt'(U, A)].
  873. precompile_is(log(X), A) --> !, precomp_is(X, U), ['$log'(U, A)].
  874. precompile_is(exp(X), A) --> !, precomp_is(X, U), ['$exp'(U, A)].
  875. precompile_is(X**Y, A) --> !, precomp_is(X, U), precomp_is(Y, V), ['$pow'(U, V, A)].
  876. precompile_is(degrees(X), A) --> !, precomp_is(X, U), ['$degrees'(U, A)].
  877. precompile_is(radians(X), A) --> !, precomp_is(X, U), ['$radians'(U, A)].
  878. precompile_is(rint(X), A) --> !, precomp_is(X, U), ['$rint'(U, A)].
  879. precompile_is(float(X), A) --> !, precomp_is(X, U), ['$float'(U, A)].
  880. precompile_is(float_integer_part(X), A) --> !, precomp_is(X, U), ['$float_integer_part'(U, A)].
  881. precompile_is(float_fractional_part(X), A) --> !, precomp_is(X, U), ['$float_fractional_part'(U, A)].
  882. precompile_is(truncate(X),A) --> !, precomp_is(X, U), ['$truncate'(U, A)].
  883. precompile_is(sign(X), A) --> !, precomp_is(X, U), ['$sign'(U, A)].
  884. precompile_is(X, _) -->
  885. {pl2am_error([unknown,arithemetic,expression,X])},
  886. {fail}.
  887. precomp_is(X, A) --> {var(X)}, {var(A)}, !, {X = A}.
  888. precomp_is(X, A) --> precompile_is(X, A).
  889. %%%%%%%%%% Add Pacakge (module) name to meta predicates
  890. localize_meta(G0, G) :-
  891. clause(package_name(P), _),
  892. localize_meta(G0, P, G),
  893. !.
  894. localize_meta([], _, []) :- !.
  895. localize_meta([G|Gs], P, [G1|Gs1]) :-
  896. localize_meta_goal(G, P, X),
  897. (X = P:Y -> G1 = Y ; G1 = X),
  898. localize_meta(Gs, P, Gs1).
  899. localize_meta_goal(G, P, G1) :- var(G), !,
  900. localize_meta_goal(call(G), P, G1).
  901. localize_meta_goal(P:G, _, G1) :- !,
  902. localize_meta_goal(G, P, G1).
  903. localize_meta_goal((X,Y), P, (X1,Y1)) :- !,
  904. localize_meta_goal(X, P, X1),
  905. localize_meta_goal(Y, P, Y1).
  906. localize_meta_goal((X->Y), P, (X1->Y1)) :- !,
  907. localize_meta_goal(X, P, X1),
  908. localize_meta_goal(Y, P, Y1).
  909. localize_meta_goal((X;Y), P, (X1;Y1)) :- !,
  910. localize_meta_goal(X, P, X1),
  911. localize_meta_goal(Y, P, Y1).
  912. localize_meta_goal(G, P, G1) :-
  913. functor(G, F, A),
  914. (clause(meta_predicates(F, A, M), _) ; builtin_local_predicates(F, A, M)),
  915. !,
  916. G =.. [F|As],
  917. localize_meta_args(M, As, P, As1),
  918. G1 =.. [F|As1].
  919. localize_meta_goal(G, P, call(P:G)) :- var(P), !.
  920. localize_meta_goal(G, _, G) :- system_predicate(G), !.
  921. localize_meta_goal(G, P, P:G).
  922. localize_meta_args([], [], _, []) :- !.
  923. localize_meta_args([:|Ms], [A|As], P, [P:A|As1]) :-
  924. (var(A) ; A \= _:_),
  925. !,
  926. localize_meta_args(Ms, As, P, As1).
  927. localize_meta_args([_|Ms], [A|As], P, [A|As1]) :-
  928. localize_meta_args(Ms, As, P, As1).
  929. %%%%%%%%%% Precompile Clause and Optimize Recursive Call
  930. precompile(Head, Goals, Instrs) :-
  931. precompile_head(Head, Instrs0, Bs),
  932. precompile_body(Goals, Bs, []),
  933. optimize_recursive_call(Head, Instrs0, Instrs).
  934. %%% Precompile head (generates get instructions)
  935. precompile_head(Head) -->
  936. {Head =.. [_|Args]},
  937. precomp_head(Args, 1).
  938. precomp_head([], _) --> !.
  939. precomp_head([A|As], I) -->
  940. [get(A, a(I))],
  941. {I1 is I + 1},
  942. precomp_head(As, I1).
  943. %%% Precompile body
  944. %%% (generates put, put_clo, put_cont, and inline instructions)
  945. precompile_body(Goals) -->
  946. {clause(pl2am_flag(ie), _)},
  947. !,
  948. {pickup_inline_goals(Goals, IGs, Gs)},
  949. precomp_inline(IGs, Gs).
  950. precompile_body(Goals) -->
  951. precomp_body(Goals).
  952. precomp_body([]) --> !, [execute(cont)].
  953. precomp_body([M:G|Cont]) --> !,
  954. binarize_body(G, Cont, G1),
  955. [execute(M:G1)].
  956. precomp_body([G|Cont]) -->
  957. binarize_body(G, Cont, G1),
  958. [execute(G1)].
  959. /*---------------------------------------------------------------
  960. Binarization technique was developed by P.Tarau and M.Boyer,
  961. please see:
  962. * "Elementary Logic Programs"
  963. P.Tarau and M.Boyer
  964. Programming Language Implementation and Logic Programming,
  965. pp.159--173, LNCS 456, Springer Verlag, 1990
  966. ----------------------------------------------------------------*/
  967. binarize_body(G, Cont, G1) -->
  968. {G =.. [F|Args]},
  969. {functor(G, F, A)},
  970. precomp_call(Args, Us, F, A),
  971. %precomp_call(Args, Us), % for no closure
  972. precomp_cont(Cont, V),
  973. {pl2am_append(Us, [V], Ws)},
  974. {G1 =.. [F|Ws]}.
  975. precomp_call([], []) --> !.
  976. precomp_call([A|As], [U|Us]) -->
  977. [put(A, U)],
  978. precomp_call(As, Us).
  979. precomp_cont([], cont) --> !.
  980. precomp_cont([M:G|Cont], V) --> !,
  981. binarize_body(G, Cont, G1),
  982. [put_cont(M:G1, V)].
  983. precomp_cont([G|Cont], V) -->
  984. binarize_body(G, Cont, G1),
  985. [put_cont(G1, V)].
  986. precomp_inline([], Gs1) --> !, precomp_body(Gs1).
  987. precomp_inline([fail|_], _) --> !, [inline(fail)].
  988. precomp_inline([G|Gs], Gs1) -->
  989. {G =.. [F|Args]},
  990. {functor(G, F, A)},
  991. precomp_call(Args, Us, F, A),
  992. %precomp_call(Args, Us),
  993. {G1 =.. [F|Us]},
  994. [inline(G1)],
  995. precomp_inline(Gs, Gs1).
  996. pickup_inline_goals([], [], []) :- !.
  997. pickup_inline_goals([G|Gs], [G|IGs], BGs) :-
  998. builtin_inline_predicates(G),
  999. !,
  1000. pickup_inline_goals(Gs, IGs, BGs).
  1001. pickup_inline_goals(Gs, [], Gs).
  1002. %%% Generate Closure
  1003. precomp_call(As, Us, Functor, Arity) -->
  1004. {clause(pl2am_flag(clo), _)},
  1005. {clause(meta_predicates(Functor, Arity, Mode), _)},
  1006. !,
  1007. {clause(package_name(P), _)},
  1008. precomp_closure(Mode, As, P, Us).
  1009. precomp_call(As, Us, _, _) --> precomp_call(As, Us).
  1010. precomp_closure([], [], _, []) --> !.
  1011. precomp_closure([:|Ms], [A|As], P, [U|Us]) -->
  1012. {get_closure(A, P, C)},
  1013. !,
  1014. [put_clo(C, U)],
  1015. precomp_closure(Ms, As, P, Us).
  1016. precomp_closure([_|Ms], [A|As], P, [U|Us]) -->
  1017. [put(A, U)],
  1018. precomp_closure(Ms, As, P, Us).
  1019. get_closure(G, _, _) :- var(G), !, fail.
  1020. get_closure(_, P, _) :- var(P), !, fail.
  1021. get_closure(P:G, _, Clo) :- !, get_closure(G, P, Clo).
  1022. get_closure(G, P, P:G) :- % ???
  1023. atom(P),
  1024. callable(G),
  1025. functor(G, F, A),
  1026. \+ clause(dynamic_predicates(F,A), _),
  1027. !.
  1028. %%% Optimize Recursive Call
  1029. optimize_recursive_call(Head, Instrs0, Instrs) :-
  1030. clause(pl2am_flag(rc), _),
  1031. !,
  1032. optimize_rc(Instrs0, Head, Instrs, []).
  1033. optimize_recursive_call(_, Instrs, Instrs).
  1034. optimize_rc([], _) --> !.
  1035. optimize_rc([execute(Goal)|Xs], Head) -->
  1036. {functor(Head, F, A)},
  1037. {functor(Goal, F, A1)},
  1038. {A+1 =:= A1},
  1039. !,
  1040. {assert_copts(rc(F, A))},
  1041. {Goal =.. [F|Args]},
  1042. {range_reg(1, A, ea, Rs0)},
  1043. {pl2am_append(Rs0, [econt], Rs)},
  1044. gen_set(Args, Rs),
  1045. [goto(F/A+top)],
  1046. optimize_rc(Xs, Head).
  1047. optimize_rc([X|Xs], Head) -->
  1048. [X],
  1049. optimize_rc(Xs, Head).
  1050. %%%%%%%%%% Compile Clause
  1051. compile_chunks(Chunk, GTI0, GTI, LTI) -->
  1052. {alloc_voids(Chunk, [], Alloc)}, % check void variables
  1053. compile_chunk(Chunk, Alloc, GTI0, GTI, LTI).
  1054. compile_chunk([], _, GTI, GTI, []) --> !.
  1055. compile_chunk(Chunk, Alloc, GTI0, GTI, LTI) -->
  1056. {free_x_reg(Chunk, 1, XN), YN = 1, PN = 1},
  1057. {LTI0 = [XN, YN, PN, Alloc]},
  1058. comp_chunk(Chunk, LTI0, LTI, GTI0, GTI).
  1059. comp_chunk([], LTI, LTI, GTI, GTI) --> !.
  1060. comp_chunk([(L:[])|Cs], LTI0, LTI, GTI0, GTI) --> !,
  1061. [L:[]],
  1062. comp_chunk(Cs, LTI0, LTI, GTI0, GTI).
  1063. comp_chunk([(L:C)|Cs], LTI0, LTI, GTI0, GTI) --> !,
  1064. [L:[]],
  1065. comp_chunk([C|Cs], LTI0, LTI, GTI0, GTI).
  1066. comp_chunk([C|Cs], LTI0, LTI, GTI0, GTI) --> !,
  1067. comp_instr(C, LTI0, LTI1, GTI0, GTI1),
  1068. comp_chunk(Cs, LTI1, LTI, GTI1, GTI).
  1069. %%% finds an available number A-register
  1070. free_x_reg([], XN, XN).
  1071. free_x_reg([get(_,V)|Cs], XN0, XN) :- nonvar(V), V = a(N), !,
  1072. XN1 is max(N+1, XN0),
  1073. free_x_reg(Cs, XN1, XN).
  1074. free_x_reg([put(_,V)|Cs], XN0, XN) :- nonvar(V), V = a(N), !,
  1075. XN1 is max(N+1, XN0),
  1076. free_x_reg(Cs, XN1, XN).
  1077. free_x_reg([_|Cs], XN0, XN) :-
  1078. free_x_reg(Cs, XN0, XN).
  1079. %%% finds void variables and allocates them in Alloc.
  1080. alloc_voids(Chunks, Alloc0, Alloc) :-
  1081. variables(Chunks, Vars),
  1082. alloc_voids1(Vars, Chunks, Alloc0, Alloc).
  1083. alloc_voids1([], _, Alloc, Alloc).
  1084. alloc_voids1([V|Vars], Chunks, Alloc0, Alloc) :-
  1085. count_variable(V, Chunks, 1),
  1086. !,
  1087. Alloc1 = [[V,void,_Seen]|Alloc0],
  1088. alloc_voids1(Vars, Chunks, Alloc1, Alloc).
  1089. alloc_voids1([_|Vars], Chunks, Alloc0, Alloc) :-
  1090. alloc_voids1(Vars, Chunks, Alloc0, Alloc).
  1091. %%%%%%%%%% Compile Precompiled Instructions: get, put, put_clo, and put_cont
  1092. /*
  1093. comp_instr(+Instr, +LTI0, ?LTI, +GTI0, ?GTI)
  1094. Instr : Intermediate instruction
  1095. LTI : [XN, YN, PN, Alloc]
  1096. XN : The register a(XN) is available for "Term".
  1097. YN : The register y(YN) is available for "Term[]".
  1098. PN : The register p(PN) is available for "Predicate".
  1099. Alloc : [[VarTerm, Register, Seen],...]
  1100. GTI : [SN, SAlloc, SInstrs]
  1101. SN : The registers s(SN), si(SN), or sf(SN) are available for static "Term".
  1102. SAlloc : [[NonVarTerm:Type, Register, Seen],...]
  1103. SInstrs : list of instructions for static terms.
  1104. Seen : Unbound variable | yes | void
  1105. Type : int | flo | con | str | lis | arr
  1106. */
  1107. comp_instr(get(X, A), LTI0, LTI, GTI0, GTI) --> !,
  1108. gen_get(X, A, LTI0, LTI, GTI0, GTI).
  1109. comp_instr(put(X, V), LTI0, LTI, GTI0, GTI) --> !,
  1110. gen_put(X, V, LTI0, LTI, GTI0, GTI).
  1111. comp_instr(put_clo(X, V), LTI0, LTI, GTI0, GTI) --> !,
  1112. gen_put_clo(X, V, LTI0, LTI, GTI0, GTI).
  1113. comp_instr(put_cont(X, V), LTI0, LTI, GTI0, GTI) --> !,
  1114. gen_put_cont(X, V, LTI0, LTI, GTI0, GTI).
  1115. comp_instr(Instr, LTI, LTI, GTI, GTI) -->
  1116. [Instr].
  1117. %%%%%%%%%% put instructions
  1118. gen_put(_, A, _, _, _, _) --> {nonvar(A)}, !,
  1119. {pl2am_error([A,should,be,an,unbound,variable])},
  1120. {fail}.
  1121. gen_put(X, A, LTI0, LTI, GTI, GTI) --> {var(X)}, !,
  1122. {assign_reg(X, R, Seen, LTI0, LTI)},
  1123. gen_put_var(R, Seen, A).
  1124. gen_put(X, A, LTI, LTI, GTI0, GTI) --> {integer(X)}, !,
  1125. {assign_sreg(X:int, R, Seen, GTI0, GTI1)},
  1126. gen_put_int(X, R, Seen, A, GTI1, GTI).
  1127. gen_put(X, A, LTI, LTI, GTI0, GTI) --> {float(X)}, !,
  1128. {assign_sreg(X:flo, R, Seen, GTI0, GTI1)},
  1129. gen_put_float(X, R, Seen, A, GTI1, GTI).
  1130. gen_put(X, A, LTI, LTI, GTI0, GTI) --> {atom(X)}, !,
  1131. {assign_sreg(X:con, R, Seen, GTI0, GTI1)},
  1132. gen_put_con(X, R, Seen, A, GTI1, GTI).
  1133. gen_put(X, A, LTI0, LTI, GTI0, GTI) -->
  1134. {ground(X), X = [X1|X2]},
  1135. !,
  1136. gen_put_args([X1,X2], [R1,R2], LTI0, LTI, GTI0, GTI1),
  1137. {assign_sreg(X:lis, R, Seen, GTI1, GTI2)},
  1138. gen_put_list([R1,R2], R, Seen, A, GTI2, GTI).
  1139. gen_put(X, A, LTI0, LTI, GTI0, GTI) -->
  1140. {ground(X), X =..[_|Args], functor(X,F,N)},
  1141. !,
  1142. {assign_sreg(F/N:con, R0, Seen0, GTI0, GTI1)},
  1143. gen_put_con(F/N, R0, Seen0, _, GTI1, GTI2),
  1144. gen_put_args(Args, Regs, LTI0, LTI, GTI2, GTI3),
  1145. {assign_sreg(Args:arr, R1, Seen1, GTI3, GTI4)},
  1146. gen_put_str_args(Regs, R1, Seen1, _, GTI4, GTI5),
  1147. {assign_sreg(X:str, R, Seen, GTI5, GTI6)},
  1148. gen_put_str([R0,R1], R, Seen, A, GTI6, GTI).
  1149. gen_put(X, A, LTI0, LTI, GTI0, GTI) -->
  1150. {X = [X1|X2]},
  1151. !,
  1152. gen_put_args([X1,X2], [R1,R2], LTI0, LTI1, GTI0, GTI),
  1153. {assign_reg(_, R, Seen, LTI1, LTI)},
  1154. {Seen = yes, R = A},
  1155. [put_list(R1, R2, R)].
  1156. gen_put(X, A, LTI0, LTI, GTI0, GTI) -->
  1157. {X =..[_|Args], functor(X,F,N)},
  1158. !,
  1159. {assign_sreg(F/N:con, R0, Seen0, GTI0, GTI1)},
  1160. gen_put_con(F/N, R0, Seen0, _, GTI1, GTI2),
  1161. gen_put_args(Args, Regs, LTI0, LTI1, GTI2, GTI),
  1162. {inc_YN(R1, LTI1, LTI2)},
  1163. {assign_reg(_, R, Seen, LTI2, LTI)},
  1164. {Seen = yes, R = A},
  1165. [put_str_args(Regs, R1)],
  1166. [put_str(R0, R1, R)].
  1167. gen_put_var(void, _, A) --> !, {A = void}. % void is a special constant.
  1168. gen_put_var(R, Seen, A) --> {var(Seen)}, !,
  1169. {Seen = yes, R = A},
  1170. [put_var(R)].
  1171. gen_put_var(R, _, A) --> {R = A}.
  1172. gen_put_int(X, R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1173. {Seen = yes, R = A},
  1174. {add_instr(put_int(X, R), GTI0, GTI)}.
  1175. gen_put_int(_, R, _, A, GTI, GTI) --> {R = A}.
  1176. gen_put_float(X, R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1177. {Seen = yes, R = A},
  1178. {add_instr(put_float(X, R), GTI0, GTI)}.
  1179. gen_put_float(_, R, _, A, GTI, GTI) --> {R = A}.
  1180. gen_put_con(X, R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1181. {Seen = yes, R = A},
  1182. {add_instr(put_con(X, R), GTI0, GTI)}.
  1183. gen_put_con(_, R, _, A, GTI, GTI) --> {R = A}.
  1184. gen_put_list([R1,R2], R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1185. {Seen = yes, R = A},
  1186. {add_instr(put_list(R1, R2, R), GTI0, GTI)}.
  1187. gen_put_list(_, R, _, A, GTI, GTI) --> {R = A}.
  1188. gen_put_str_args(Regs, R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1189. {Seen = yes, R = A},
  1190. {add_instr(put_str_args(Regs, R), GTI0, GTI)}.
  1191. gen_put_str_args(_, R, _, A, GTI, GTI) --> {R = A}.
  1192. gen_put_str([R0,R1], R, Seen, A, GTI0, GTI) --> {var(Seen)}, !,
  1193. {Seen = yes, R = A},
  1194. {add_instr(put_str(R0, R1, R), GTI0, GTI)}.
  1195. gen_put_str(_, R, _, A, GTI, GTI) --> {R = A}.
  1196. gen_put_args([], [], LTI, LTI, GTI, GTI) --> !.
  1197. gen_put_args([X|Xs], [R|Rs], LTI0, LTI, GTI0, GTI) -->
  1198. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1199. gen_put_args(Xs, Rs, LTI1, LTI, GTI1, GTI).
  1200. gen_put_clo(P:X, A, LTI0, LTI, GTI0, GTI) -->
  1201. {X =..[F|Args]},
  1202. !,
  1203. gen_put_args(Args, Regs, LTI0, LTI1, GTI0, GTI),
  1204. {assign_reg(_, R, Seen, LTI1, LTI)},
  1205. {Seen = yes, R = A},
  1206. {X1 =..[F|Regs]},
  1207. {(clause(package_name(P), _) -> CLO = X1 ; CLO = P:X1)},
  1208. [put_clo(CLO, R)].
  1209. %%%%%%%%%% get instructions
  1210. gen_get(X, A, LTI0, LTI, GTI0, GTI) -->
  1211. gen_get([A=X], LTI0, LTI, GTI0, GTI).
  1212. gen_get([], LTI, LTI, GTI, GTI) --> !.
  1213. gen_get([A=X|_], LTI, LTI, GTI, GTI) -->
  1214. {var(A)},
  1215. !,
  1216. {pl2am_error([A,must,not,be,a,variable,in,get(X,A)])},
  1217. {fail}.
  1218. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1219. {var(X)},
  1220. {assign_reg(X, R, Seen, LTI0, LTI1)},
  1221. {nonvar(Seen)},
  1222. !,
  1223. gen_get_var(R, Seen, A),
  1224. gen_get(Instrs, LTI1, LTI, GTI0, GTI).
  1225. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1226. {var(X)},
  1227. !,
  1228. {add_alloc([X,A,yes], LTI0, LTI1)},
  1229. gen_get(Instrs, LTI1, LTI, GTI0, GTI).
  1230. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1231. {integer(X)},
  1232. !,
  1233. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1234. [get_int(X, R, A)],
  1235. gen_get(Instrs, LTI1, LTI, GTI1, GTI).
  1236. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1237. {float(X)},
  1238. !,
  1239. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1240. [get_float(X, R, A)],
  1241. gen_get(Instrs, LTI1, LTI, GTI1, GTI).
  1242. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1243. {atom(X)},
  1244. !,
  1245. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1246. [get_con(X, R, A)],
  1247. gen_get(Instrs, LTI1, LTI, GTI1, GTI).
  1248. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1249. {ground(X)},
  1250. !,
  1251. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1252. [get_ground(X, R, A)],
  1253. gen_get(Instrs, LTI1, LTI, GTI1, GTI).
  1254. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1255. {X = [X1|X2]},
  1256. !,
  1257. [get_list(A)],
  1258. gen_unify([X1,X2], Instrs1, LTI0, LTI1, GTI0, GTI1),
  1259. gen_get(Instrs1, LTI1, LTI2, GTI1, GTI2),
  1260. gen_get(Instrs, LTI2, LTI, GTI2, GTI).
  1261. gen_get([A=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1262. {X =.. [F|Args], functor(X, F, N)},
  1263. {assign_sreg(F/N:con, R, Seen, GTI0, GTI1)},
  1264. gen_put_con(F/N, R, Seen, _, GTI1, GTI2),
  1265. [get_str(F/N, R, A)],
  1266. gen_unify(Args, Instrs1, LTI0, LTI1, GTI2, GTI3),
  1267. gen_get(Instrs1, LTI1, LTI2, GTI3, GTI4),
  1268. gen_get(Instrs, LTI2, LTI, GTI4, GTI).
  1269. gen_get_var(void, _, _) --> !.
  1270. gen_get_var(R, _, A) --> [get_val(R, A)].
  1271. %%%%%%%%%% unify instructions
  1272. gen_unify([], [], LTI, LTI, GTI, GTI) --> !.
  1273. gen_unify([X|Xs], Instrs, LTI0, LTI, GTI0, GTI) -->
  1274. {var(X)},
  1275. !,
  1276. {assign_reg(X, R, Seen, LTI0, LTI1)},
  1277. gen_unify_var(R, Seen),
  1278. gen_unify(Xs, Instrs, LTI1, LTI, GTI0, GTI).
  1279. gen_unify([X|Xs], Instrs, LTI0, LTI, GTI0, GTI) -->
  1280. {integer(X)},
  1281. !,
  1282. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1283. [unify_int(X, R)],
  1284. gen_unify(Xs, Instrs, LTI1, LTI, GTI1, GTI).
  1285. gen_unify([X|Xs], Instrs, LTI0, LTI, GTI0, GTI) -->
  1286. {float(X)},
  1287. !,
  1288. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1289. [unify_float(X, R)],
  1290. gen_unify(Xs, Instrs, LTI1, LTI, GTI1, GTI).
  1291. gen_unify([X|Xs], Instrs, LTI0, LTI, GTI0, GTI) -->
  1292. {atom(X)},
  1293. !,
  1294. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1295. [unify_con(X, R)],
  1296. gen_unify(Xs, Instrs, LTI1, LTI, GTI1, GTI).
  1297. gen_unify([X|Xs], Instrs, LTI0, LTI, GTI0, GTI) -->
  1298. {ground(X)},
  1299. !,
  1300. gen_put(X, R, LTI0, LTI1, GTI0, GTI1),
  1301. [unify_ground(X, R)],
  1302. gen_unify(Xs, Instrs, LTI1, LTI, GTI1, GTI).
  1303. gen_unify([X|Xs], [R=X|Instrs], LTI0, LTI, GTI0, GTI) -->
  1304. {assign_reg(_, R, Seen, LTI0, LTI1)},
  1305. gen_unify_var(R, Seen),
  1306. gen_unify(Xs, Instrs, LTI1, LTI, GTI0, GTI).
  1307. %%% unify_void, unify_variable, unify_value
  1308. gen_unify_var(void, _) --> !, [unify_void(1)].
  1309. gen_unify_var(R, Seen) --> {var(Seen)}, !,
  1310. {Seen = yes},
  1311. [unify_var(R)].
  1312. gen_unify_var(R, _) --> [unify_val(R)].
  1313. %%%%%%%%%% generate continuation goal
  1314. gen_put_cont(X, R, LTI0, LTI, GTI, GTI) -->
  1315. {inc_PN(R, LTI0, LTI)},
  1316. [put_cont(X, R)].
  1317. %%% A register
  1318. assign_reg(X, Reg, Seen, LTI0, LTI) :- nonvar(X), !,
  1319. pl2am_error([X,must,be,unbound,variable,in,assign_reg(X,Reg,Seen,LTI0,LTI)]),
  1320. fail.
  1321. assign_reg(X, Reg, Seen, [XN,YN,PN,Alloc], [XN,YN,PN,Alloc]) :-
  1322. allocated(Alloc, X, [Reg,Seen]),
  1323. !.
  1324. assign_reg(X, Reg, Seen, [XN,YN,PN,Alloc], [XN1,YN,PN,Alloc1]) :-
  1325. Reg = a(XN),
  1326. XN1 is XN + 1,
  1327. Alloc1 = [[X,Reg,Seen]|Alloc].
  1328. allocated([[V|X]|_], V0, X) :- V == V0, !.
  1329. allocated([_|Alloc], V0, X) :- allocated(Alloc, V0, X).
  1330. %%% S register
  1331. assign_sreg(X, Reg, Seen, GTI0, GTI) :- \+ ground(X), !,
  1332. pl2am_error([X,must,be,ground,term,in,assign_sreg(X,Reg,Seen,GTI0,GTI)]),
  1333. fail.
  1334. assign_sreg(X, Reg, Seen, [SN,SAlloc,SInstrs], [SN,SAlloc,SInstrs]) :-
  1335. allocated(SAlloc, X, [Reg,Seen]),
  1336. !.
  1337. assign_sreg(X:T, Reg, Seen, [SN,SAlloc,SInstrs], [SN1,SAlloc1,SInstrs]) :-
  1338. assign_sreg0(T, SN, Reg),
  1339. SN1 is SN+1,
  1340. SAlloc1 = [[X:T,Reg,Seen]|SAlloc].
  1341. assign_sreg0(int, SN, si(SN)) :- !.
  1342. assign_sreg0(flo, SN, sf(SN)) :- !.
  1343. assign_sreg0(_, SN, s(SN)) :- !.
  1344. %assign_sreg0(con, SN, sc(SN)) :- !.
  1345. %assign_sreg0(str, SN, ss(SN)) :- !.
  1346. %assign_sreg0(lis, SN, sl(SN)) :- !.
  1347. %assign_sreg0(arr, SN, sa(SN)) :- !.
  1348. %%% incriment YN
  1349. inc_YN(y(YN), [XN,YN|Zs], [XN,YN1|Zs]) :- YN1 is YN+1.
  1350. %%% incriment PN
  1351. inc_PN(p(PN), [XN,YN,PN|Zs], [XN,YN,PN1|Zs]) :- PN1 is PN+1.
  1352. %%% add an instruction to GTI
  1353. add_instr(Instr, [SN,SAlloc,SInstrs0], [SN,SAlloc,[Instr|SInstrs0]]).
  1354. %%% add an allocation to LTI
  1355. add_alloc(E, [XN,YN,PN,Alloc0], [XN,YN,PN,[E|Alloc0]]).
  1356. /*****************************************************************
  1357. Built-in Predicates and Constants
  1358. *****************************************************************/
  1359. builtin_meta_predicates((^), 2, [?,:]).
  1360. builtin_meta_predicates(call, 1, [:]).
  1361. builtin_meta_predicates(once, 1, [:]).
  1362. builtin_meta_predicates((\+), 1, [:]).
  1363. builtin_meta_predicates(findall, 3, [?,:,?]).
  1364. builtin_meta_predicates(bagof, 3, [?,:,?]).
  1365. builtin_meta_predicates(setof, 3, [?,:,?]).
  1366. builtin_meta_predicates(on_exception, 3, [?,:,:]).
  1367. builtin_meta_predicates(catch, 3, [:,?,:]).
  1368. builtin_meta_predicates(synchronized, 2, [?,:]).
  1369. builtin_meta_predicates(freeze, 2, [?,:]).
  1370. builtin_local_predicates(assert, 1, [:]).
  1371. builtin_local_predicates(asserta, 1, [:]).
  1372. builtin_local_predicates(assertz, 1, [:]).
  1373. builtin_local_predicates(retract, 1, [:]).
  1374. builtin_local_predicates(retractall, 1, [:]).
  1375. builtin_local_predicates(clause, 2, [:,?]).
  1376. builtin_local_predicates(abolish, 1, [:]).
  1377. % Control constructs
  1378. builtin_inline_predicates(fail).
  1379. builtin_inline_predicates('$get_level'(_)).
  1380. builtin_inline_predicates('$neck_cut').
  1381. builtin_inline_predicates('$cut'(_)).
  1382. % Term unification
  1383. builtin_inline_predicates('$unify'(_,_)).
  1384. builtin_inline_predicates('$not_unifiable'(_,_)).
  1385. % Type testing
  1386. builtin_inline_predicates(var(_)).
  1387. builtin_inline_predicates(atom(_)).
  1388. builtin_inline_predicates(integer(_)).
  1389. builtin_inline_predicates(float(_)).
  1390. builtin_inline_predicates(atomic(_)).
  1391. builtin_inline_predicates(nonvar(_)).
  1392. builtin_inline_predicates(number(_)).
  1393. builtin_inline_predicates(java(_)).
  1394. builtin_inline_predicates(java(_,_)).
  1395. builtin_inline_predicates(closure(_)).
  1396. builtin_inline_predicates(ground(_)).
  1397. % Term comparison
  1398. builtin_inline_predicates('$equality_of_term'(_,_)).
  1399. builtin_inline_predicates('$inequality_of_term'(_,_)).
  1400. builtin_inline_predicates('$after'(_,_)).
  1401. builtin_inline_predicates('$before'(_,_)).
  1402. builtin_inline_predicates('$not_after'(_,_)).
  1403. builtin_inline_predicates('$not_before'(_,_)).
  1404. builtin_inline_predicates('$identical_or_cannot_unify'(_,_)).
  1405. % Term creation and decomposition
  1406. builtin_inline_predicates(copy_term(_,_)).
  1407. % Arithmetic evaluation
  1408. builtin_inline_predicates(is(_,_)).
  1409. builtin_inline_predicates('$abs'(_,_)).
  1410. builtin_inline_predicates('$asin'(_,_)).
  1411. builtin_inline_predicates('$acos'(_,_)).
  1412. builtin_inline_predicates('$atan'(_,_)).
  1413. builtin_inline_predicates('$bitwise_conj'(_,_,_)).
  1414. builtin_inline_predicates('$bitwise_disj'(_,_,_)).
  1415. builtin_inline_predicates('$bitwise_exclusive_or'(_,_,_)).
  1416. builtin_inline_predicates('$bitwise_neg'(_,_)).
  1417. builtin_inline_predicates('$ceil'(_,_)).
  1418. builtin_inline_predicates('$cos'(_,_)).
  1419. builtin_inline_predicates('$degrees'(_,_)).
  1420. builtin_inline_predicates('$exp'(_,_)).
  1421. builtin_inline_predicates('$float_quotient'(_,_,_)).
  1422. builtin_inline_predicates('$floor'(_,_)).
  1423. builtin_inline_predicates('$int_quotient'(_,_,_)).
  1424. builtin_inline_predicates('$log'(_,_)).
  1425. builtin_inline_predicates('$max'(_,_,_)).
  1426. builtin_inline_predicates('$min'(_,_,_)).
  1427. builtin_inline_predicates('$minus'(_,_,_)).
  1428. builtin_inline_predicates('$mod'(_,_,_)).
  1429. builtin_inline_predicates('$multi'(_,_,_)).
  1430. builtin_inline_predicates('$plus'(_,_,_)).
  1431. builtin_inline_predicates('$pow'(_,_,_)).
  1432. builtin_inline_predicates('$radians'(_,_)).
  1433. builtin_inline_predicates('$rint'(_,_)).
  1434. builtin_inline_predicates('$round'(_,_)).
  1435. builtin_inline_predicates('$shift_left'(_,_,_)).
  1436. builtin_inline_predicates('$shift_right'(_,_,_)).
  1437. builtin_inline_predicates('$sin'(_,_)).
  1438. builtin_inline_predicates('$sqrt'(_,_)).
  1439. builtin_inline_predicates('$tan'(_,_)).
  1440. builtin_inline_predicates('$float'(_,_)).
  1441. builtin_inline_predicates('$float_integer_part'(_,_)).
  1442. builtin_inline_predicates('$float_fractional_part'(_,_)).
  1443. builtin_inline_predicates('$truncate'(_,_)).
  1444. builtin_inline_predicates('$sign'(_,_)).
  1445. % Arithmetic comparison
  1446. builtin_inline_predicates('$arith_equal'(_,_)).
  1447. builtin_inline_predicates('$arith_not_equal'(_,_)).
  1448. builtin_inline_predicates('$greater_or_equal'(_,_)).
  1449. builtin_inline_predicates('$greater_than'(_,_)).
  1450. builtin_inline_predicates('$less_or_equal'(_,_)).
  1451. builtin_inline_predicates('$less_than'(_,_)).
  1452. builtin_arith_constant(random).
  1453. builtin_arith_constant(pi).
  1454. builtin_arith_constant(e).
  1455. /*****************************************************************
  1456. Eliminate disjunctions
  1457. *****************************************************************/
  1458. % The clause a :- b;c is converted into a :- b. and a :- c.
  1459. % In addition,
  1460. % (C1 -> C2) is converted into ((C1,!,C2) ; fail).
  1461. % ((C1 -> C2) ; C3) is converted into ((C1,!,C2) ; C3).
  1462. % not(C) is converted into ((C,!,fail) ; true).
  1463. % \+(C) is converted into ((C,!,fail) ; true).
  1464. % And then all of disjunctions are eliminated.
  1465. %
  1466. % Note: this is based on flatten.pl in holmer's benchmark.
  1467. eliminate_disj(Cl, NewCl, DummyCls) :-
  1468. extract_disj(Cl, NewCl, Disjs, []),
  1469. treat_disj(Disjs, DummyCls, []).
  1470. extract_disj(Cl, Cl) --> {var(Cl)}, !.
  1471. extract_disj(Cl, (H :- NewB)) --> {Cl = (H :- B)}, !,
  1472. extract_disj(B, NewB, Cl).
  1473. extract_disj(Cl, Cl) --> !.
  1474. extract_disj(G, G, _) --> {var(G)}, !.
  1475. extract_disj((G1, G2), (NewG1, NewG2), Cl) --> !,
  1476. extract_disj(G1, NewG1, Cl),
  1477. extract_disj(G2, NewG2, Cl).
  1478. extract_disj(G, NewG, Cl) --> {is_disj(G, DisjG)}, !,
  1479. {retract(dummy_clause_counter(N))},
  1480. [disj(DisjG, N, NewG, Cl)],
  1481. {N1 is N+1},
  1482. {assert(dummy_clause_counter(N1))}.
  1483. extract_disj(G, G, _) --> !.
  1484. is_disj((C1->C2), ((C1,!,C2);fail)) :- !.
  1485. is_disj(((C1->C2);C3), ((C1,!,C2);C3)) :- !.
  1486. is_disj((C1;C2), (C1;C2)) :- !.
  1487. is_disj(not(C),((C,!,fail);true)) :- !.
  1488. is_disj(\+(C),((C,!,fail);true)).
  1489. treat_disj([]) --> !.
  1490. treat_disj([disj((A;B),N,X,C)|Disjs]) -->
  1491. {variables((A;B), Vars)},
  1492. {variables(C, CVars)},
  1493. {intersect_vars(Vars, CVars, Args)},
  1494. {clause(file_name(File), _)},
  1495. {list_to_string(['$dummy_', N, '_', File], Name)},
  1496. {X =.. [Name|Args]},
  1497. {copy_term((X :- A), DummyCla)},
  1498. {copy_term((X :- B), DummyClb)},
  1499. [DummyCla],
  1500. [DummyClb],
  1501. treat_disj(Disjs).
  1502. intersect_vars(V1, V2, Out) :-
  1503. sort(V1, Sorted1),
  1504. sort(V2, Sorted2),
  1505. intersect_sorted_vars(Sorted1, Sorted2, Out).
  1506. intersect_sorted_vars([], _, []) :- !.
  1507. intersect_sorted_vars(_, [], []).
  1508. intersect_sorted_vars([X|Xs], [Y|Ys], [X|Rs]) :- X == Y, !,
  1509. intersect_sorted_vars(Xs, Ys, Rs).
  1510. intersect_sorted_vars([X|Xs], [Y|Ys], Rs) :- X @< Y, !,
  1511. intersect_sorted_vars(Xs,[Y|Ys],Rs).
  1512. intersect_sorted_vars([X|Xs], [Y|Ys], Rs) :- X @> Y, !,
  1513. intersect_sorted_vars([X|Xs],Ys,Rs).
  1514. /*****************************************************************
  1515. Utilities
  1516. *****************************************************************/
  1517. %%% print
  1518. pl2am_error(M) :- pl2am_message(['***','PL2ASM','ERROR'|M]).
  1519. pl2am_message([]) :- nl, flush_output(user_output).
  1520. pl2am_message([M|Ms]) :- write(M), write(' '), pl2am_message(Ms).
  1521. %%% format
  1522. mode_expr([]).
  1523. mode_expr([M|Ms]) :- nonvar(M), pl2am_member(M, [:,+,-,?]), !, mode_expr(Ms).
  1524. predspec_expr(F/A) :- atom(F), integer(A).
  1525. %%% list
  1526. pl2am_append([], Zs, Zs).
  1527. pl2am_append([X|Xs], Ys, [X|Zs]) :- pl2am_append(Xs, Ys, Zs).
  1528. pl2am_rev(L, R) :- pl2am_rev(L, [], R).
  1529. pl2am_rev([], R, R).
  1530. pl2am_rev([X|L], Y, R) :- pl2am_rev(L, [X|Y], R).
  1531. pl2am_member(X, [X|_]).
  1532. pl2am_member(X, [_|Ys]) :- pl2am_member(X, Ys).
  1533. pl2am_memq(X, [Y|_]) :- X==Y, !.
  1534. pl2am_memq(X, [_|Ys]) :- pl2am_memq(X, Ys).
  1535. flatten_list([]) --> !.
  1536. flatten_list([L1|L2]) --> !, flatten_list(L1), flatten_list(L2).
  1537. flatten_list(L) --> [L].
  1538. flatten_code([]) --> !.
  1539. flatten_code([(L: C)|Code]) --> !,
  1540. [L: []],
  1541. flatten_code([C|Code]).
  1542. flatten_code([Code1|Code2]) --> !,
  1543. flatten_code(Code1),
  1544. flatten_code(Code2).
  1545. flatten_code(Code) --> [Code].
  1546. %%% transform
  1547. conj_to_list(X, _) :- var(X), !,
  1548. pl2am_error([variable,X,can,not,be,converted,to,'[A|B]',expression]),
  1549. fail.
  1550. conj_to_list(((X1,X2),Xs), Y) :- !, conj_to_list((X1,(X2,Xs)), Y).
  1551. conj_to_list((X,Xs), [X|Zs]) :- !, conj_to_list(Xs, Zs).
  1552. conj_to_list((X), [X]).
  1553. list_to_string(List, String) :-
  1554. list_to_chars(List, Chars0),
  1555. flatten_list(Chars0, Chars, []),
  1556. atom_codes(String, Chars).
  1557. list_to_chars([], []) :- !.
  1558. list_to_chars([L|Ls], [C|Cs]) :- atom(L), !,
  1559. atom_codes(L, C),
  1560. list_to_chars(Ls, Cs).
  1561. list_to_chars([L|Ls], [C|Cs]) :- number(L), !,
  1562. number_codes(L, C),
  1563. list_to_chars(Ls, Cs).
  1564. list_to_conj(X, Y) :-
  1565. flatten_list(X, L, []),
  1566. list_to_conj0(L, Y).
  1567. list_to_conj0(X, _) :- var(X), !,
  1568. pl2am_error([variable,X,can,not,be,converted,to,'(A,B)',expression]),
  1569. fail.
  1570. list_to_conj0([X], (X)).
  1571. list_to_conj0([X|Xs], (X,Ys)) :- !, list_to_conj0(Xs, Ys).
  1572. %%% misc
  1573. variables(X, Vs) :- variables(X, [], Vs).
  1574. variables(X, Vs, Vs) :- var(X), pl2am_memq(X, Vs), !.
  1575. variables(X, Vs, [X|Vs]) :- var(X), !.
  1576. variables(X, Vs0, Vs0) :- atomic(X), !.
  1577. variables([X|Xs], Vs0, Vs) :- !, variables(X, Vs0, Vs1), variables(Xs, Vs1, Vs).
  1578. variables(X, Vs0, Vs) :- X =.. Xs, variables(Xs, Vs0, Vs).
  1579. count_variable(V, X, 1) :- V == X, !.
  1580. count_variable(_, X, 0) :- var(X), !.
  1581. count_variable(_, X, 0) :- atomic(X), !.
  1582. count_variable(V, [X|Y], N) :- !,
  1583. count_variable(V, X, N1),
  1584. count_variable(V, Y, N2),
  1585. N is N1 + N2.
  1586. count_variable(V, X, N) :-
  1587. X =.. Xs,
  1588. count_variable(V, Xs, N).
  1589. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1590. % END
  1591. % written by SICStus Prolog 3.12.8