Prolog "transpiler"

Admin User, erstellt 07. Apr. 2024
         
/**
* Modern Albufeira Prolog Interpreter
*
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
*
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
*
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
*
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
/*******************************************************************/
/* Transpiler Begin */
/*******************************************************************/
/**
* transpilepy_begin(B):
* transpilepy_begin(B, O):
* The predicate succeeds in writing an empty Python file B.
*/
% transpilepy_begin(+Atom)
transpilepy_begin(OutName) :-
transpilepy_begin(OutName, []).
% transpilepy_begin(+Atom, +List)
transpilepy_begin(OutName, Opts) :-
decode_transpilepy_opts(Opts, v(0,''), v(Flags,Doge)),
copy_text('playerpy/cross/header.py', OutName),
setup_once_cleanup(
open(OutName, append, OutStream),
transpilepy_init(OutStream, Flags, Doge),
close(OutStream)).
% transpilepy_init(+Stream, +Integer, +Atom)
transpilepy_init(OutStream, Flags, Doge) :-
(Flags /\ 2 =\= 0 ->
cross_clear;
true),
(Flags /\ 1 =\= 0 ->
write(OutStream, 'from '),
write(OutStream, Doge),
write(OutStream, ' import (add, Clause, Goal, run, Compound,\n'),
write(OutStream, ' Cache, make_defined)\n'),
write(OutStream, 'def main():\n')
; write(OutStream, 'from nova.store import (Clause, add, Compound,\n'),
write(OutStream, ' Cache, make_defined, Place, Skeleton)\n'),
write(OutStream, 'from nova.machine import (Goal, run)\n'),
write(OutStream, 'import nova.special as special\n'),
write(OutStream, 'import nova.runtime as runtime\n'),
write(OutStream, 'import nova.eval as eval\n')).
/*******************************************************************/
/* Transpile Add */
/*******************************************************************/
/**
* transpilepy_add(A, B):
* transpilepy_add(A, B, O):
* The predicate succeeds in cross compiling the Prolog text file A
* into the Python file B.
*/
% transpilepy_add(+Atom, +Atom)
transpilepy_add(InName, OutName) :-
transpilepy_add(InName, OutName, []).
% transpilepy_add(+Atom, +Atom, +List)
transpilepy_add(InName, OutName, Opts) :-
decode_transpilepy_opts(Opts, v(0,''), v(Flags,_)),
setup_once_cleanup(
open(OutName, append, OutStream),
transpilepy_loading(InName, OutStream, Flags),
close(OutStream)).
% transpilepy_loading(+Atom, +Stream, +Integer)
transpilepy_loading(InName, OutStream, Flags) :-
setup_once_cleanup(
cross_loading_begin(InName),
transpilepy_file(InName, OutStream, Flags),
cross_loading_end).
% transpilepy_file(+Atom, +Stream, +Integer)
transpilepy_file(InName, OutStream, Flags) :-
setup_once_cleanup(
open(InName, read, InStream),
transpilepy_stream(InName, InStream, OutStream, Flags),
close(InStream)).
% transpilepy_stream(+Atom, +Stream, +Stream, +Integer)
transpilepy_stream(InName, InStream, OutStream, Flags) :-
setup_once_cleanup(
asserta(cross_including(InName, InStream)),
transpilepy_lines(InStream, OutStream, Flags),
once(retract(cross_including(InName, InStream)))).
% transpilepy_lines(+Stream, +Stream, +Integer)
transpilepy_lines(InStream, OutStream, Flags) :-
repeat,
read_term(InStream, Term, [singletons(Names)]),
(Term = end_of_file -> !;
skipped_directive(Term) ->
skipped_warning,
fail;
cross_singleton_check(Names),
expand_term(Term, Term2),
cross_style_static(Term2, Flags, List2, List),
cross_replace_term(Term2, Flags, List, []),
member(Term3, List2),
sys_trans_horn(Term3, Help),
transpilepy_horn(Help, OutStream, Flags),
fail).
% transpilepy_horn(+Clause_or_goal, +Stream, +Integer)
transpilepy_horn(V, _, _) :- var(V),
throw(error(instantiation_error,_)).
transpilepy_horn(Help, OutStream, Flags) :- Help = tr_clause(_,Head,_), !,
functor(Head, F, N),
cross_pred_type(F, N, O),
sys_encode_horn(Help, Encode, O),
makepy_print(Encode, Printable),
makepy_print_atom(F, G),
(Flags /\ 1 =\= 0 ->
write(OutStream, ' ');
true),
write(OutStream, add(G, N, Printable)),
write(OutStream, '\n'),
cross_touch_pred(F, N, 1).
transpilepy_horn(Help, OutStream, Flags) :- Help = tr_goal(_), !,
sys_encode_horn(Help, Encode, 1),
makepy_print(Encode, Printable),
(Flags /\ 1 =\= 0 ->
write(OutStream, ' ');
true),
write(OutStream, run(Printable)),
write(OutStream, '\n').
transpilepy_horn(T, _, _) :-
throw(error(type_error(tr_clause_or_goal, T),_)).
/*******************************************************************/
/* Transpile End */
/*******************************************************************/
/**
* transpilepy_end(B):
* transpilepy_end(B, O):
* The predicate succeeds adding an epilogue to the Python file B.
*/
% transpilepy_end(+Atom)
transpilepy_end(OutName) :-
transpilepy_end(OutName, []).
% transpilepy_end(+Atom, +List)
transpilepy_end(OutName, Opts) :-
decode_transpilepy_opts(Opts, v(0,''), v(Flags,_)),
setup_once_cleanup(
open(OutName, append, OutStream),
transpilepy_fini(OutStream, Flags),
close(OutStream)).
% transpilepy_fini(+Stream, +Integer)
transpilepy_fini(OutStream, Flags) :-
(Flags /\ 2 =\= 0 ->
cross_defered(Term3, Flags),
sys_trans_horn(Term3, Help),
transpilepy_horn(Help, OutStream, Flags);
true),
fail.
transpilepy_fini(_, _).
/*******************************************************************/
/* Make Printable */
/*******************************************************************/
% makepy_print(+IRClauseOrGoal, -PyObject)
makepy_print(T, _) :- var(T),
throw(error(instantiation_error,_)).
makepy_print(ir_clause(A,B,W,C), 'Clause'(I,X,Y,W,Z)) :- !,
K is W+1,
makepy_print_list(A, X, v(K,[]), v(J,R)),
makepy_print_list(B, Y, v(J,R), v(I,_)),
makepy_print_option(C, Z).
makepy_print(ir_goal(A), 'Goal'(I,X)) :- !,
makepy_print_list(A, X, v(0,[]), v(I,_)).
makepy_print(T, _) :-
throw(error(type_error(ir_clause_or_goal, T),_)).
% makepy_print_option(+IROption, -PyObjec)
makepy_print_option(T, _) :- var(T),
throw(error(instantiation_error,_)).
makepy_print_option(nothing, 'NotImplemented') :- !.
makepy_print_option(just(F), G) :- !,
makepy_print_const(F, G).
makepy_print_option(T, _) :-
throw(error(type_error(ir_option, T),_)).
% makepy_print_list(+IRList, -PyList, -List, +List)
makepy_print_list(V, _) --> {var(V),
throw(error(instantiation_error,_))}.
makepy_print_list([X|L], [Y|R]) --> !,
makepy_print_instr(X, Y),
makepy_print_list(L, R).
makepy_print_list([], []) --> !.
makepy_print_list(T, _) -->
{throw(error(type_error(ir_list, T),_))}.
% makepy_print_instr(+IRInstr, -PyInstr, -List, +List)
makepy_print_instr(V, _) --> {var(V),
throw(error(instantiation_error,_))}.
makepy_print_instr(first_var(_,G), 'Place'(-1)) --> {var(G)}, !.
makepy_print_instr(first_var(W,_), 'Place'(V)) --> !,
(makepy_print_current_recycle([W|R]) ->
makepy_print_set_recycle(R);
makepy_print_current_max(W),
{H is W+1},
makepy_print_set_max(H)),
{V is (-W)-2}.
makepy_print_instr(var(W,G), 'Place'(W)) --> !,
({var(G)} ->
makepy_print_current_recycle(R),
makepy_print_set_recycle([W|R]);
[]).
makepy_print_instr(functor(F,L), 'Skeleton'(G, X)) --> !,
{makepy_print_const(F, G)},
makepy_print_list(L, X).
makepy_print_instr(const(F), G) --> !,
{makepy_print_const(F, G)}.
makepy_print_instr(T) -->
{throw(error(type_error(ir_instr, T),_))}.
% makepy_print_current_max(-Integer, -List, +List)
makepy_print_current_max(I, v(I,R), v(I,R)).
% makepy_print_set_max(+Integer, -List, +List)
makepy_print_set_max(I, v(_,R), v(I,R)).
% makepy_print_current_recycle(-List, -List, +List)
makepy_print_current_recycle(R, v(I,R), v(I,R)).
% makepy_print_set_recycle(+List, -List, +List)
makepy_print_set_recycle(R, v(I,_), v(I,R)).
% makepy_print_alternatives(+List, -PyAlternatives)
makepy_print_alternatives(T, _) :- var(T),
throw(error(instantiation_error,_)).
makepy_print_alternatives([X|L], [Y|R]) :- !,
makepy_print(X, Y),
makepy_print_alternatives(L, R).
makepy_print_alternatives([], []) :- !.
makepy_print_alternatives(T, _) :-
throw(error(type_error(ir_alter, T),_)).
/*******************************************************************/
/* Constants */
/*******************************************************************/
% makepy_print_const(+Const, -PyConst)
makepy_print_const(T, _) :- var(T),
throw(error(instantiation_error,_)).
makepy_print_const(functor(F,L), 'Compound'(G, R)) :- !,
makepy_print_const(F, G),
makepy_print_args(L, R).
makepy_print_const(site(F), 'Cache'(G)) :- !,
makepy_print_atom(F, G).
makepy_print_const(link(Q), 'make_defined'(R)) :- !,
makepy_print_alternatives(Q, R).
makepy_print_const(A, B) :- number(A), !,
makepy_print_number(A, B).
makepy_print_const(A, B) :- reference(A), !,
makepy_print_reference(A, B).
makepy_print_const(A, B) :- atom(A), !,
makepy_print_atom(A, B).
makepy_print_const(T, _) :-
throw(error(type_error(ir_const, T),_)).
% makepy_print_args(+List, -PyList)
makepy_print_args([X|L], [Y|R]) :-
makepy_print_const(X, Y),
makepy_print_args(L, R).
makepy_print_args([], []).
/*************************************************************/
/* Number Utility */
/*************************************************************/
% make_print_reference(+Number, -PyNumber)
makepy_print_number(A, A).
/*************************************************************/
/* Reference Utility */
/*************************************************************/
% makepy_print_reference(+Reference, -PyReference)
makepy_print_reference(0rNone, 'None') :- !.
makepy_print_reference(0rFalse, 'False') :- !.
makepy_print_reference(0rTrue, 'True') :- !.
makepy_print_reference(A, _) :-
throw(error(domain_error(printable,A),_)).
/*************************************************************/
/* Atom Utility */
/*************************************************************/
% makepy_print_atom(+Atom, -PyAtom)
makepy_print_atom(X, Y) :-
atom_codes(X, L),
crosspy_escape_codes(L, R, [0'"]),
atom_codes(Y, [0'"|R]).
% crosspy_escape_codes(+List, -List, +List)
crosspy_escape_codes([X|L]) -->
crosspy_escape_code(X),
crosspy_escape_codes(L).
crosspy_escape_codes([]) --> [].
% crosspy_escape_code(+Integer, -List, +List)
crosspy_escape_code(X) --> {crosspy_is_escape(Y, X)}, !, [0'\\, Y].
crosspy_escape_code(X) --> {crosspy_is_meta(X)}, !, [0'\\, X].
crosspy_escape_code(X) --> {cross_is_cntrl(X)}, !, crosspy_escape_code2(X).
crosspy_escape_code(X) --> {cross_is_invalid(X)}, !, crosspy_escape_code2(X).
crosspy_escape_code(X) --> [X].
% crosspy_escape_code(+Integer, -List, +List)
crosspy_escape_code2(X) --> {X =< 0xFF}, !,
{atom_integer(J, 16, X), atom_codes(J, H), length(H, N), M is 2-N},
[0'\\, 0'x], cross_escape_zeros(M), cross_escape_codes2(H).
crosspy_escape_code2(X) --> {X =< 0xFFFF}, !,
{atom_integer(J, 16, X), atom_codes(J, H), length(H, N), M is 4-N},
[0'\\, 0'u], cross_escape_zeros(M), cross_escape_codes2(H).
crosspy_escape_code2(X) -->
{atom_integer(J, 16, X), atom_codes(J, H), length(H, N), M is 8-N},
[0'\\, 0'U], cross_escape_zeros(M), cross_escape_codes2(H).
% crosspy_is_escape(+Code, -Code)
crosspy_is_escape(0'n, 0'\n).
crosspy_is_escape(0't, 0'\t).
crosspy_is_escape(0'b, 0'\b).
crosspy_is_escape(0'f, 0'\f).
crosspy_is_escape(0'r, 0'\r).
crosspy_is_escape(0'a, 0'\a).
crosspy_is_escape(0'v, 0'\v).
% crosspy_is_meta(+Code)
crosspy_is_meta(0'\').
crosspy_is_meta(0'\").
crosspy_is_meta(0'\\).
/*******************************************************************/
/* Decode Transpile Python Options */
/*******************************************************************/
% decode_transpilepy_opts(+List, +Pair, -Pair)
decode_transpilepy_opts(V, _, _) :- var(V),
throw(error(instantiation_error,_)).
decode_transpilepy_opts([X|L], I, O) :- !,
decode_transpilepy_opt(X, I, H),
decode_transpilepy_opts(L, H, O).
decode_transpilepy_opts([], H, H) :- !.
decode_transpilepy_opts(L, _, _) :-
throw(error(type_error(list,L),_)).
% decode_transpilepy_opt(+Option, +Pair, -Pair)
decode_transpilepy_opt(V, _, _) :- var(V),
throw(error(instantiation_error,_)).
decode_transpilepy_opt(main_entry(B), v(F,Y), v(G,Y)) :- !,
sys_opt_boolean(B, 1, F, G).
decode_transpilepy_opt(defer_meta(B), v(F,Y), v(G,Y)) :- !,
sys_opt_boolean(B, 2, F, G).
decode_transpilepy_opt(doge(A),v(X,_), v(X,A)) :- !,
sys_check_atom(A).
decode_transpilepy_opt(O, _, _) :-
throw(error(type_error(transpilepy_option,O),_)).