Prolog "brainfog"

         
/**
* 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 sys_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 sys_components of the library.
*
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
/**
* See also:
* The Elements of Computing Systems
* Nisan, N. and Schocken, S. - June 15, 2021, MIT Press
* https://mitpress.mit.edu/9780262539807/the-elements-of-computing-systems/
*/
:- ensure_loaded(library(lists)).
:- ensure_loaded(library(hiord)).
/**
* emulate(G):
* The predicate fails always. As a side effect it emulates G
* on an abstract π-WAM. The only side effects consumed or
* produced by the π-WAM is their input and output.
*/
% emulate(+Goal)
emulate(GOAL) :-
sys_comp_goal(GOAL, _, [], CODE, []),
term_variables(CODE, LIST),
copy_term(LIST, STATE),
sys_number_list(LIST, 0, 1),
sys_number_list(STATE, 0, 0),
sys_run(0, CODE, 0, STATE).
% sys_number_list(+List, +Integer, +Integer)
sys_number_list([], _, _).
sys_number_list([X|L], X, D) :-
Y is X+D,
sys_number_list(L, Y, D).
/**
* execute(G):
* The predicate fails always. As a side effect it runs G on a
* CPU backend for π-WAM. The only side effects consumed or
* produced by the π-WAM is their input and output.
*/
% execute(+Goal)
execute(GOAL) :-
sys_comp_goal(GOAL, _, [], CODE, []),
term_variables(CODE, LIST),
copy_term(LIST, STATE),
sys_number_list(LIST, 0, 1),
maplist(sys_pack_instr, CODE, CODE2),
sys_number_list(STATE, 0, 0),
ir_piwam_new(CODE2, STATE, PIWAM),
ir_piwam_run(PIWAM).
/***************************************************************/
/* Evaluator */
/***************************************************************/
% sys_run(+Integer, +List, +Integer, +List)
sys_run(PC, CODE, ACCU, STATE) :-
nth0(PC, CODE, INSTR),
INSTR = (ACT, OBJ, REL),
ACT = (FUN, MODE, COND),
sys_run_get(MODE, OBJ, STATE, VALUE),
sys_run_fun(FUN, ACCU, VALUE, ACCU2),
sys_run_set(MODE, OBJ, STATE, ACCU2, STATE2),
sys_run_jump(COND, ACCU2, REL, REL2),
PC2 is PC+1+REL2,
sys_run(PC2, CODE, ACCU2, STATE2).
% sys_run_get(+Atom, +Integer, +Compound, -Integer)
sys_run_get(get, OBJ, STATE, VALUE) :- nth0(OBJ, STATE, VALUE).
sys_run_get(cst, OBJ, _, OBJ).
sys_run_get(set, _, _, 0).
sys_run_get(out, _, _, 0).
sys_run_get(in, _, _, VALUE) :-
write(': '),
flush_output,
sys_readbig(TEMP),
sys_int32(TEMP, VALUE).
% sys_run_fun(+Atom, +Integer, +Integer, -Integer)
sys_run_fun(val, _, VALUE, VALUE).
sys_run_fun(acc, ACCU, _, ACCU).
sys_run_fun(add, ACCU, VALUE, ACCU2) :-
TEMP is VALUE+ACCU,
sys_int32(TEMP, ACCU2).
sys_run_fun(sub, ACCU, VALUE, ACCU2) :-
TEMP is VALUE-ACCU,
sys_int32(TEMP, ACCU2).
sys_run_fun(mul, ACCU, VALUE, ACCU2) :-
TEMP is VALUE*ACCU,
sys_int32(TEMP, ACCU2).
sys_run_fun(nil, _, _, ACCU2) :-
ACCU2 = [].
sys_run_fun(cons, ACCU, VALUE, ACCU2) :-
ACCU2 = [VALUE|ACCU].
sys_run_fun(car, ACCU, _, ACCU2) :-
ACCU = [ACCU2|_].
sys_run_fun(cdr, ACCU, _, ACCU2) :-
ACCU = [_|ACCU2].
% sys_run_set(+Atom, +Integer, +Compound, +Integer, -Compound)
sys_run_set(get, _, STATE, _, STATE).
sys_run_set(cst, _, STATE, _, STATE).
sys_run_set(set, OBJ, STATE, ACCU2, STATE2) :-
nth0(OBJ, STATE, _, TEMP),
nth0(OBJ, STATE2, ACCU2, TEMP).
sys_run_set(out, _, STATE, ACCU2, STATE) :- write(ACCU2), nl.
sys_run_set(in, _, STATE, _, STATE).
% sys_run_jump(+Atom, +Integer, +Integer, -Integer)
sys_run_jump(eq, ACCU, REL, REL2) :- (ACCU =:= 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(nq, ACCU, REL, REL2) :- (ACCU =\= 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(ls, ACCU, REL, REL2) :- (ACCU < 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(gr, ACCU, REL, REL2) :- (ACCU > 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(lq, ACCU, REL, REL2) :- (ACCU =< 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(gq, ACCU, REL, REL2) :- (ACCU >= 0 -> REL2 = REL; REL2 = 0).
sys_run_jump(unit, ACCU, REL, REL2) :- (ACCU \= [] -> REL2 = REL; REL2 = 0).
sys_run_jump(pair, ACCU, REL, REL2) :- (ACCU \= [_|_] -> REL2 = REL; REL2 = 0).
sys_run_jump(true, _, REL, REL).
/***************************************************************/
/* Utilities */
/***************************************************************/
% sys_int32(+Integer, -Integer)
sys_int32(ALPHA, RESULT) :-
MASKED is ALPHA /\ 0xFFFFFFFF,
(MASKED >= 0x80000000 ->
RESULT is MASKED - 0x100000000;
RESULT = MASKED).
% sys_readbig(-Integer)
sys_readbig(RESULT) :-
get_atom(ATOM, []),
sub_atom(ATOM, 0, _, 1, CROPED),
atom_integer(CROPED, 10, RESULT).
/***************************************************************/
/* Compiler */
/***************************************************************/
% sys_comp_goal(+Goal, +List, +List, -List, +List)
sys_comp_goal(TERM is EXPR, STACK, CODE) --> !,
sys_comp_arith(EXPR, STACK), sys_comp_is(TERM, STACK, CODE).
sys_comp_goal(out(LIST), STACK, CODE) --> !,
sys_comp_build(LIST, STACK), [((acc,out,true),0,0)], phrase(CODE).
sys_comp_goal(in(LIST), STACK, CODE) --> !,
[((val,in,true),0,0)], sys_comp_is(LIST, STACK, CODE).
sys_comp_goal(EXPR=:=EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,nq),TEMP,REL)], phrase(CODE).
sys_comp_goal(EXPR=\=EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,eq),TEMP,REL)], phrase(CODE).
sys_comp_goal(EXPR<EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,gq),TEMP,REL)], phrase(CODE).
sys_comp_goal(EXPR>EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,lq),TEMP,REL)], phrase(CODE).
sys_comp_goal(EXPR=<EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,gr),TEMP,REL)], phrase(CODE).
sys_comp_goal(EXPR>=EXPR2, STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)], sys_comp_arith(EXPR2, STACK),
[((sub,get,ls),TEMP,REL)], phrase(CODE).
sys_comp_goal(between(TERM,TERM2,VAR), STACK, CODE) --> !, {length(CODE, REL)},
sys_comp_build(TERM, STACK), [((acc,set,true),VAR,0)],
{REL2 is REL+3}, sys_comp_build(TERM2, STACK), [((sub,get,gr),VAR,REL2)],
{REL3 is -REL2-2}, phrase(CODE),
[((val,get,true),VAR,0), ((add,cst,true),1,0), ((acc,set,true),VAR,REL3)].
sys_comp_goal((GOAL, GOAL2), STACK, CODE) --> !,
{sys_comp_goal(GOAL2, STACK, CODE, CODE2, [])},
sys_comp_goal(GOAL, STACK, CODE2).
% sys_comp_arith(+Expr, +List, -List, +List)
sys_comp_arith(CONST, _) --> {integer(CONST)}, !,
[((val,cst,true),CONST,0)].
sys_comp_arith(VAR, _) --> {var(VAR)}, !,
[((val,get,true),VAR,0)].
sys_comp_arith(EXPR+EXPR2, [TEMP|STACK]) --> !,
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)],
sys_comp_arith(EXPR2, STACK), [((add,get,true),TEMP,0)].
sys_comp_arith(EXPR-EXPR2, [TEMP|STACK]) --> !,
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)],
sys_comp_arith(EXPR2, STACK), [((sub,get,true),TEMP,0)].
sys_comp_arith(EXPR*EXPR2, [TEMP|STACK]) --> !,
sys_comp_arith(EXPR, STACK), [((acc,set,true),TEMP,0)],
sys_comp_arith(EXPR2, STACK), [((mul,get,true),TEMP,0)].
% sys_comp_build(+Term, +List, -List, +List)
sys_comp_build(CONST, _) --> {integer(CONST)}, !,
[((val,cst,true),CONST,0)].
sys_comp_build(VAR, _) --> {var(VAR)}, !,
[((val,get,true),VAR,0)].
sys_comp_build([], _) --> !,
[((nil,cst,true),0,0)].
sys_comp_build([TERM|REST], [TEMP|STACK]) --> !,
sys_comp_build(TERM, STACK), [((acc,set,true),TEMP,0)],
sys_comp_build(REST, STACK), [((cons,get,true),TEMP,0)].
% sys_comp_is(+Term, +List, +List, -List, +List)
sys_comp_is(CONST, _, CODE) --> {integer(CONST)}, !, {length(CODE, REL)},
[((sub,cst,nq),CONST,REL)], phrase(CODE).
sys_comp_is(VAR, _, CODE) --> {var(VAR)}, !,
[((acc,set,true),VAR,0)], phrase(CODE).
sys_comp_is([], _, CODE) --> !, {length(CODE, REL)},
[((acc,cst,unit),0,REL)], phrase(CODE).
sys_comp_is([TERM|REST], STACK, CODE) --> !, {sys_comp_cdr(REST, STACK, CODE, CODE2, []),
sys_comp_car(TERM, STACK, CODE2, CODE3, []), length(CODE3, REL)},
[((acc,cst,pair),0,REL)], phrase(CODE3).
% sys_comp_car(+Term, +List, +List, -List, +List)
sys_comp_car(TERM, [TEMP|STACK], CODE) -->
[((acc,set,true),TEMP,0), ((car,cst,true),0,0)], sys_comp_is(TERM, STACK, CODE).
% sys_comp_cdr(+Term, +List, +List, -List, +List)
sys_comp_cdr(REST, [TEMP|STACK], CODE) -->
[((val,get,true),TEMP,0), ((cdr,cst,true),0,0)], sys_comp_is(REST, STACK, CODE).
/***************************************************************/
/* Encoder */
/***************************************************************/
% sys_pack_fun(+Atom, -Integer)
sys_pack_fun(val, 0).
sys_pack_fun(acc, 1).
sys_pack_fun(add, 2).
sys_pack_fun(sub, 3).
sys_pack_fun(mul, 4).
sys_pack_fun(nil, 8).
sys_pack_fun(cons, 9).
sys_pack_fun(car, 10).
sys_pack_fun(cdr, 11).
% sys_pack_mode(+Atom, -Integer)
sys_pack_mode(get, 0).
sys_pack_mode(cst, 1).
sys_pack_mode(set, 2).
sys_pack_mode(out, 4).
sys_pack_mode(in, 5).
% sys_pack_jump(+Atom, -Integer)
sys_pack_jump(eq, 0).
sys_pack_jump(nq, 1).
sys_pack_jump(ls, 2).
sys_pack_jump(gr, 3).
sys_pack_jump(lq, 4).
sys_pack_jump(gq, 5).
sys_pack_jump(unit, 8).
sys_pack_jump(pair, 9).
sys_pack_jump(true, 15).
% sys_pack_act(+Triple, -Integer)
sys_pack_act((FUN, MODE, COND), ACT) :-
sys_pack_fun(FUN, VAL),
sys_pack_mode(MODE, VAL2),
sys_pack_jump(COND, VAL3),
ACT is (VAL<<8) \/ (VAL2<<4) \/ VAL3.
% sys_pack_instr(+Tripple, -Integer)
sys_pack_instr((ACT, OBJ, REL), INSTR) :-
sys_pack_act(ACT, VAL),
INSTR is (VAL<<20) \/ ((OBJ + 512)<<10) \/ (REL + 512).
/*******************************************************************/
/* Foreign Predicates */
/*******************************************************************/
:- ensure_loaded(foreign(edge/piwamlib)).