THe old compiler-to-Python.
This commit is contained in:
parent
38a9b93488
commit
fb8faf917d
|
|
@ -0,0 +1,140 @@
|
|||
eq [false] [true] [false] cmp
|
||||
gt [true] [false] [false] cmp
|
||||
lt [false] [false] [true] cmp
|
||||
neq [true] [false] [true] cmp
|
||||
le [false] [true] [true] cmp
|
||||
ge [true] [true] [false] cmp
|
||||
? dup bool
|
||||
!- 0 >=
|
||||
++ 1 +
|
||||
-- 1 -
|
||||
<{} [] swap
|
||||
<<{} [] rollup
|
||||
abs dup 0 < [] [neg] branch
|
||||
anamorphism [pop []] swap [dip swons] genrec
|
||||
and nulco [nullary [false]] dip branch
|
||||
app1 grba infrst
|
||||
app2 [grba swap grba swap] dip [infrst] cons ii
|
||||
app3 3 appN
|
||||
appN [grabN] codi map reverse disenstacken
|
||||
at drop first
|
||||
average [sum] [size] cleave /
|
||||
b [i] dip i
|
||||
binary unary popd
|
||||
ccccons ccons ccons
|
||||
ccons cons cons
|
||||
clear [] swaack pop
|
||||
cleave fork popdd
|
||||
clop cleave popdd
|
||||
cmp [[>] swap] dipd [ifte] ccons [=] swons ifte
|
||||
codi cons dip
|
||||
codireco codi reco
|
||||
dinfrirst dip infrst
|
||||
dipd [dip] codi
|
||||
disenstacken swaack pop
|
||||
divmod [/] [%] clop
|
||||
down_to_zero [0 >] [dup --] while
|
||||
drop [rest] times
|
||||
dupdd [dup] dipd
|
||||
dupd [dup] dip
|
||||
dupdipd dup dipd
|
||||
dupdip dupd dip
|
||||
enstacken stack [clear] dip
|
||||
first uncons pop
|
||||
flatten <{} [concat] step
|
||||
fork [i] app2
|
||||
fourth rest third
|
||||
gcd true [tuck mod dup 0 >] loop pop
|
||||
genrec [[genrec] ccccons] nullary swons concat ifte
|
||||
grabN <{} [cons] times
|
||||
grba [stack popd] dip
|
||||
hypot [sqr] ii + sqrt
|
||||
ifte [nullary] dipd swap branch
|
||||
ii [dip] dupdip i
|
||||
infra swons swaack [i] dip swaack
|
||||
infrst infra first
|
||||
<< lshift
|
||||
lshift [2 *] times
|
||||
make_generator [codireco] ccons
|
||||
mod %
|
||||
neg 0 swap -
|
||||
not [true] [false] branch
|
||||
nulco [nullary] cons
|
||||
nullary [stack] dinfrirst
|
||||
null [] swap concat bool not
|
||||
of swap at
|
||||
or nulco [nullary] dip [true] branch
|
||||
over [dup] dip swap
|
||||
pam [i] map
|
||||
pm [+] [-] clop
|
||||
popdd [pop] dipd
|
||||
popd [pop] dip
|
||||
popopdd [popop] dipd
|
||||
popopd [popop] dip
|
||||
popopop pop popop
|
||||
popop pop pop
|
||||
pow 1 roll> swap [*] cons times
|
||||
product 1 swap [*] step
|
||||
quoted [unit] dip
|
||||
range [0 <=] [-- dup] anamorphism
|
||||
range_to_zero unit [down_to_zero] infra
|
||||
reco rest cons
|
||||
rest uncons popd
|
||||
reverse <{} shunt
|
||||
rolldown roll<
|
||||
roll< swapd swap
|
||||
roll> swap swapd
|
||||
rollup roll>
|
||||
rrest rest rest
|
||||
>> rshift
|
||||
rshift [2 /] times
|
||||
run <{} infra
|
||||
second rest first
|
||||
shift uncons [swons] dip
|
||||
shunt [swons] step
|
||||
size [pop ++] step_zero
|
||||
small dup null [rest null] [pop true] branch
|
||||
spiral_next [[[abs] ii <=] [[<>] [pop !-] or] and] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte
|
||||
split_at [drop] [take] clop
|
||||
split_list [take reverse] [drop] clop
|
||||
sqr dup mul
|
||||
stackd [stack] dip
|
||||
step_zero 0 roll> step
|
||||
stuncons stack uncons
|
||||
sum [+] step_zero
|
||||
swapd [swap] dip
|
||||
swoncat swap concat
|
||||
swons swap cons
|
||||
tailrec [i] genrec
|
||||
take <<{} [shift] times pop
|
||||
ternary binary popd
|
||||
third rest second
|
||||
tuck dup swapd
|
||||
unary nullary popd
|
||||
uncons [first] [rest] cleave
|
||||
unit [] cons
|
||||
unquoted [i] dip
|
||||
unstack [[] swaack] dip swoncat swaack pop
|
||||
unswons uncons swap
|
||||
while swap nulco dupdipd concat loop
|
||||
x dup i
|
||||
step [_step0] x
|
||||
_step0 _step1 [popopop] [_stept] branch
|
||||
_step1 [?] dipd roll<
|
||||
_stept [uncons] dipd [dupdipd] dip x
|
||||
times [_times0] x
|
||||
_times0 _times1 [popopop] [_timest] branch
|
||||
_times1 [dup 0 >] dipd roll<
|
||||
_timest [[--] dip dupdipd] dip x
|
||||
map [_map0] cons [[] [_map?] [_mape]] dip tailrec
|
||||
_map? pop bool not
|
||||
_mape popd reverse
|
||||
_map0 [_map1] dipd _map2
|
||||
_map1 stackd shift
|
||||
_map2 [infrst] cons dipd roll< swons
|
||||
_isnt_bool not not
|
||||
_isnt_two_bools [_isnt_bool] ii
|
||||
_\/_ [_isnt_bool] [not] branch
|
||||
/\ _isnt_two_bools [pop false] [] branch
|
||||
\/ _isnt_two_bools [] [pop true] branch
|
||||
xor [] [not] branch
|
||||
|
|
@ -0,0 +1,921 @@
|
|||
/*
|
||||
|
||||
████████╗██╗ ██╗██╗ ██╗███╗ ██╗
|
||||
╚══██╔══╝██║ ██║██║ ██║████╗ ██║
|
||||
██║ ███████║██║ ██║██╔██╗ ██║
|
||||
██║ ██╔══██║██║ ██║██║╚██╗██║
|
||||
██║ ██║ ██║╚██████╔╝██║ ╚████║
|
||||
╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝
|
||||
|
||||
A dialect of Joy. Version -10.0.0.
|
||||
|
||||
Copyright © 2018, 2019, 2020 Simon Forman
|
||||
|
||||
This file is part of Thun
|
||||
|
||||
Thun is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Thun is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(Big fonts are from Figlet "ANSI Shadow" http://www.patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=formatter and "Small".)
|
||||
|
||||
Thun is an implementation of a dialect of the Joy executable notation.
|
||||
|
||||
Table of Contents
|
||||
Parser & Grammar
|
||||
Semantics
|
||||
Functions
|
||||
Combinators
|
||||
Definitions
|
||||
Compiler
|
||||
to Prolog
|
||||
to Machine Code
|
||||
Meta-Programming
|
||||
Expand/Contract Definitions
|
||||
Formatter
|
||||
Partial Reducer
|
||||
|
||||
*/
|
||||
|
||||
:- use_module(library(clpfd)).
|
||||
:- use_module(library(dcg/basics)).
|
||||
:- use_module(library(gensym)).
|
||||
:- dynamic func/3.
|
||||
:- dynamic def/2.
|
||||
|
||||
|
||||
/*
|
||||
An entry point.
|
||||
*/
|
||||
|
||||
joy(InputString, StackIn, StackOut) :-
|
||||
text_to_expression(InputString, Expression),
|
||||
!,
|
||||
thun(Expression, StackIn, StackOut).
|
||||
|
||||
/*
|
||||
|
||||
██████╗ █████╗ ██████╗ ███████╗███████╗██████╗ ██╗
|
||||
██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗ ██║
|
||||
██████╔╝███████║██████╔╝███████╗█████╗ ██████╔╝ ████████╗
|
||||
██╔═══╝ ██╔══██║██╔══██╗╚════██║██╔══╝ ██╔══██╗ ██╔═██╔═╝
|
||||
██║ ██║ ██║██║ ██║███████║███████╗██║ ██║ ██████║
|
||||
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝
|
||||
|
||||
██████╗ ██████╗ █████╗ ███╗ ███╗███╗ ███╗ █████╗ ██████╗
|
||||
██╔════╝ ██╔══██╗██╔══██╗████╗ ████║████╗ ████║██╔══██╗██╔══██╗
|
||||
██║ ███╗██████╔╝███████║██╔████╔██║██╔████╔██║███████║██████╔╝
|
||||
██║ ██║██╔══██╗██╔══██║██║╚██╔╝██║██║╚██╔╝██║██╔══██║██╔══██╗
|
||||
╚██████╔╝██║ ██║██║ ██║██║ ╚═╝ ██║██║ ╚═╝ ██║██║ ██║██║ ██║
|
||||
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
|
||||
|
||||
The grammar of Joy is very simple. A Joy expression is zero or more Joy
|
||||
terms (separated by blanks, see below) and terms can be
|
||||
integers, Booleans, quoted Joy expressions, or symbols (names of
|
||||
functions.)
|
||||
|
||||
joy ::= term*
|
||||
|
||||
term ::= integer | bool | '[' joy ']' | symbol
|
||||
|
||||
integer ::= [ '-' | '+' ] ('0'...'9')+
|
||||
bool ::= 'true' | 'false'
|
||||
symbol ::= char+
|
||||
|
||||
char ::= <Any non-space other than '[' and ']'.>
|
||||
|
||||
There are a few wrinkles in the handling of blank space between terms
|
||||
because we want to be able to omit it around brackets:
|
||||
|
||||
Valid expressions:
|
||||
|
||||
1 2 3
|
||||
1[2]3
|
||||
1 [ 2 ] 3
|
||||
true
|
||||
truedat (a symbol prefixed with the name of a boolean)
|
||||
|
||||
Invalid:
|
||||
|
||||
12three (symbols can't start with numbers, and this shouldn't parse
|
||||
as [12 three].)
|
||||
|
||||
Symbols can be made of any non-blank characters except '['and ']' which
|
||||
are fully reserved for list literals (aka "quotes"). 'true' and 'false'
|
||||
would be valid symbols but they are reserved for Boolean literals.
|
||||
|
||||
Integers are converted to Prolog integers, symbols and bools to Prolog
|
||||
atoms, and list literals to Prolog lists.
|
||||
|
||||
For now strings are neglected in favor of lists of numbers. (But there's
|
||||
no support for parsing string notation and converting to lists of ints.)
|
||||
|
||||
First lex the stream of codes into tokens separated by square brackets
|
||||
or whitespace. We keep the brackets and throw away the blanks.
|
||||
*/
|
||||
|
||||
joy_lex([tok(Token)|Ls]) --> chars(Token), !, joy_lex(Ls).
|
||||
joy_lex([ lbracket|Ls]) --> "[", !, joy_lex(Ls).
|
||||
joy_lex([ rbracket|Ls]) --> "]", !, joy_lex(Ls).
|
||||
|
||||
joy_lex(Ls) --> [Space], {code_type(Space, space)}, !, joy_lex(Ls).
|
||||
|
||||
joy_lex([]) --> [].
|
||||
|
||||
% Then parse the tokens converting them to Prolog values and building up
|
||||
% the list structures (if any.)
|
||||
|
||||
joy_parse([J|Js]) --> joy_term(J), !, joy_parse(Js).
|
||||
joy_parse([]) --> [].
|
||||
|
||||
joy_term(list(J)) --> [lbracket], !, joy_parse(J), [rbracket].
|
||||
joy_term(Atomic) --> [tok(Codes)], {joy_token(Atomic, Codes)}.
|
||||
|
||||
joy_token(int(I), Codes) :- number(I, Codes, []), !. % See dcg/basics.
|
||||
joy_token(bool(true), `true`) :- !.
|
||||
joy_token(bool(false), `false`) :- !.
|
||||
joy_token(symbol(S), Codes) :- atom_codes(S, Codes).
|
||||
|
||||
|
||||
text_to_expression(Text, Expression) :-
|
||||
phrase(joy_lex(Tokens), Text), !,
|
||||
phrase(joy_parse(Expression), Tokens).
|
||||
|
||||
% Apologies for all the (green, I hope) cuts. The strength of the Joy
|
||||
% syntax is that it's uninteresting.
|
||||
|
||||
chars([Ch|Rest]) --> char(Ch), chars(Rest).
|
||||
chars([Ch]) --> char(Ch).
|
||||
|
||||
char(Ch) --> [Ch], {Ch \== 0'[, Ch \== 0'], code_type(Ch, graph)}.
|
||||
|
||||
|
||||
/* Here is an example of Joy code:
|
||||
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
It probably seems unreadable but with a little familiarity it becomes
|
||||
just as legible as any other notation. This function accepts two
|
||||
integers on the stack and increments or decrements one of them such that
|
||||
the new pair of numbers is the next coordinate pair in a square spiral
|
||||
(like that used to construct an Ulam Spiral). It is adapted from the
|
||||
code in the answer here:
|
||||
|
||||
https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777
|
||||
|
||||
It can be used with the x combinator to make a kind of generator for
|
||||
spiral square coordinates.
|
||||
|
||||
|
||||
|
||||
███████╗███████╗███╗ ███╗ █████╗ ███╗ ██╗████████╗██╗ ██████╗███████╗
|
||||
██╔════╝██╔════╝████╗ ████║██╔══██╗████╗ ██║╚══██╔══╝██║██╔════╝██╔════╝
|
||||
███████╗█████╗ ██╔████╔██║███████║██╔██╗ ██║ ██║ ██║██║ ███████╗
|
||||
╚════██║██╔══╝ ██║╚██╔╝██║██╔══██║██║╚██╗██║ ██║ ██║██║ ╚════██║
|
||||
███████║███████╗██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║╚██████╗███████║
|
||||
╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝
|
||||
|
||||
The fundamental Joy relation involves an expression and two stacks. One
|
||||
stack serves as input and the other as output.
|
||||
|
||||
thun(Expression, InputStack, OutputStack)
|
||||
|
||||
The null expression (denoted by an empty Prolog list) is effectively an
|
||||
identity function and serves as the end-of-processing marker. As a
|
||||
matter of efficiency (of Prolog) the thun/3 predicate picks off the first
|
||||
term of the expression (if any) and passes it to thun/4 which can then
|
||||
take advantage of Prolog indexing on the first term of a predicate. */
|
||||
|
||||
thun([], S, S).
|
||||
thun([Term|E], Si, So) :- thun(Term, E, Si, So).
|
||||
|
||||
/* The thun/4 predicate was originally written in terms of the thun/3
|
||||
predicate, which was very elegant, but prevented (I assume but have not
|
||||
checked) tail-call recursion. In order to alleviate this, partial
|
||||
reduction is used to generate the actual thun/4 rules, see below.
|
||||
|
||||
Original thun/4 code:
|
||||
|
||||
thun(int(I), E, Si, So) :- thun(E, [ int(I)|Si], So).
|
||||
thun(bool(B), E, Si, So) :- thun(E, [bool(B)|Si], So).
|
||||
thun(list(L), E, Si, So) :- thun(E, [list(L)|Si], So).
|
||||
thun(symbol(Def), E, Si, So) :- def(Def, Body), append(Body, E, Eo), thun(Eo, Si, So).
|
||||
thun(symbol(Func), E, Si, So) :- func(Func, Si, S), thun(E, S, So).
|
||||
thun(symbol(Combo), E, Si, So) :- combo(Combo, Si, S, E, Eo), thun(Eo, S, So).
|
||||
|
||||
Integers, Boolean values, and lists are put onto the stack, symbols are
|
||||
dispatched to one of three kinds of processing: functions, combinators
|
||||
and definitions (see "defs.txt".) */
|
||||
|
||||
thun(A, [], S, [A|S]) :- var(A), !.
|
||||
thun(A, [T|E], S, So) :- var(A), !, thun(T, E, [A|S], So).
|
||||
|
||||
% Literals turn out okay.
|
||||
|
||||
thun(int(A), [], B, [int(A)|B]).
|
||||
thun(int(C), [A|B], D, E) :- thun(A, B, [int(C)|D], E).
|
||||
|
||||
thun(bool(A), [], B, [bool(A)|B]).
|
||||
thun(bool(C), [A|B], D, E) :- thun(A, B, [bool(C)|D], E).
|
||||
|
||||
thun(list(A), [], B, [list(A)|B]).
|
||||
thun(list(C), [A|B], D, E) :- thun(A, B, [list(C)|D], E).
|
||||
|
||||
% Partial reduction works for func/3 cases.
|
||||
|
||||
thun(symbol(A), [], B, C) :- func(A, B, C).
|
||||
thun(symbol(A), [C|D], B, F) :- func(A, B, E), thun(C, D, E, F).
|
||||
|
||||
% Combinators look ok too.
|
||||
|
||||
% thun(symbol(A), D, B, C) :- combo(A, B, C, D, []).
|
||||
% thun(symbol(A), C, B, G) :- combo(A, B, F, C, [D|E]), thun(D, E, F, G).
|
||||
|
||||
% However, in this case, I think the original version will be more
|
||||
% efficient.
|
||||
|
||||
thun(symbol(Combo), E, Si, So) :- combo(Combo, Si, S, E, Eo), thun(Eo, S, So).
|
||||
|
||||
% In the reduced rules Prolog will redo all the work of the combo/5
|
||||
% predicate on backtracking through the second rule. It will try
|
||||
% combo/5, which usually won't end in Eo=[] so the first rule fails, then
|
||||
% it will try combo/5 again in the second rule. In the original form
|
||||
% after combo/5 has completed Prolog has computed Eo and can index on it
|
||||
% for thun/3.
|
||||
%
|
||||
% Neither functions nor definitions can affect the expression so this
|
||||
% consideration doesn't apply to those rules. The unification of the
|
||||
% head clauses will distinguish the cases for them.
|
||||
|
||||
% Definitions don't work though (See "Partial Reducer" section below.)
|
||||
% I hand-wrote the def/3 cases here.
|
||||
|
||||
thun(symbol(D), [], Si, So) :- def(D, [DH| E]), thun(DH, E, Si, So).
|
||||
thun(symbol(D), [H|E0], Si, So) :- def(D, [DH|DE]),
|
||||
append(DE, [H|E0], E), /* ................. */ thun(DH, E, Si, So).
|
||||
|
||||
% Partial reduction has been the subject of a great deal of research and
|
||||
% I'm sure there's a way to make definitions work, but it's beyond the
|
||||
% scope of the project at the moment. It works well enough as-is that I'm
|
||||
% happy to manually write out two rules by hand.
|
||||
|
||||
% Some error handling.
|
||||
|
||||
thun(symbol(Unknown), _, _, _) :-
|
||||
\+ def(Unknown, _),
|
||||
\+ func(Unknown, _, _),
|
||||
\+ combo(Unknown, _, _, _, _),
|
||||
write("Unknown: "),
|
||||
writeln(Unknown),
|
||||
fail.
|
||||
|
||||
/*
|
||||
|
||||
███████╗██╗ ██╗███╗ ██╗ ██████╗████████╗██╗ ██████╗ ███╗ ██╗███████╗
|
||||
██╔════╝██║ ██║████╗ ██║██╔════╝╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
|
||||
█████╗ ██║ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
|
||||
██╔══╝ ██║ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
|
||||
██║ ╚██████╔╝██║ ╚████║╚██████╗ ██║ ██║╚██████╔╝██║ ╚████║███████║
|
||||
╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
|
||||
|
||||
*/
|
||||
|
||||
func(words, S, [Words|S]) :- words(Words).
|
||||
|
||||
func(swap, [A, B|S], [B, A|S]).
|
||||
func(dup, [A|S], [A, A|S]).
|
||||
func(pop, [_|S], S ).
|
||||
|
||||
func(cons, [list(A), B |S], [list([B|A])|S]).
|
||||
func(concat, [list(A), list(B)|S], [list(C)|S]) :- append(B, A, C).
|
||||
func(flatten, [list(A)|S], [list(B)|S]) :- flatten(A, B).
|
||||
func(swaack, [list(R)|S], [list(S)|R]).
|
||||
func(stack, S , [list(S)|S]).
|
||||
func(clear, _ , []).
|
||||
func(first, [list([X|_])|S], [ X |S]).
|
||||
func(rest, [list([_|X])|S], [list(X)|S]).
|
||||
func(unit, [X|S], [list([X])|S]).
|
||||
|
||||
func(rolldown, [A, B, C|S], [B, C, A|S]).
|
||||
func(dupd, [A, B|S], [A, B, B|S]).
|
||||
func(over, [A, B|S], [B, A, B|S]).
|
||||
func(tuck, [A, B|S], [A, B, A|S]).
|
||||
func(dupdd, [A, B, C|D], [A, B, C, C|D]).
|
||||
|
||||
% func(stackd, [A|B], [A, list(B)|B]). % Doesn't compile.
|
||||
|
||||
func(shift, [list([B|A]), list(C)|D], [list(A), list([B|C])|D]).
|
||||
|
||||
func(rollup, Si, So) :- func(rolldown, So, Si).
|
||||
func(uncons, Si, So) :- func(cons, So, Si).
|
||||
|
||||
func(bool, [ int(0)|S], [bool(false)|S]).
|
||||
func(bool, [ list([])|S], [bool(false)|S]).
|
||||
func(bool, [bool(false)|S], [bool(false)|S]).
|
||||
|
||||
func(bool, [ int(N)|S], [bool(true)|S]) :- N #\= 0.
|
||||
func(bool, [list([_|_])|S], [bool(true)|S]).
|
||||
func(bool, [ bool(true)|S], [bool(true)|S]).
|
||||
% func(bool, [A|S], [bool(true)|S]) :- \+ func(bool, [A], [bool(false)]).
|
||||
|
||||
func('empty?', [ list([])|S], [ bool(true)|S]).
|
||||
func('empty?', [ list([_|_])|S], [bool(false)|S]).
|
||||
|
||||
func('list?', [ list(_)|S], [ bool(true)|S]).
|
||||
func('list?', [ bool(_)|S], [bool(false)|S]).
|
||||
func('list?', [ int(_)|S], [bool(false)|S]).
|
||||
func('list?', [symbol(_)|S], [bool(false)|S]).
|
||||
|
||||
func('one-or-more?', [list([_|_])|S], [ bool(true)|S]).
|
||||
func('one-or-more?', [ list([])|S], [bool(false)|S]).
|
||||
|
||||
func(and, [bool(true), bool(true)|S], [ bool(true)|S]).
|
||||
func(and, [bool(true), bool(false)|S], [bool(false)|S]).
|
||||
func(and, [bool(false), bool(true)|S], [bool(false)|S]).
|
||||
func(and, [bool(false), bool(false)|S], [bool(false)|S]).
|
||||
|
||||
func(or, [bool(true), bool(true)|S], [ bool(true)|S]).
|
||||
func(or, [bool(true), bool(false)|S], [ bool(true)|S]).
|
||||
func(or, [bool(false), bool(true)|S], [ bool(true)|S]).
|
||||
func(or, [bool(false), bool(false)|S], [bool(false)|S]).
|
||||
|
||||
func( + , [int(A), int(B)|S], [int(A + B)|S]).
|
||||
func( - , [int(A), int(B)|S], [int(B - A)|S]).
|
||||
func( * , [int(A), int(B)|S], [int(A * B)|S]).
|
||||
func( / , [int(A), int(B)|S], [int(B div A)|S]).
|
||||
func('%', [int(A), int(B)|S], [int(B mod A)|S]).
|
||||
% func( + , [int(A), int(B)|S], [int(C)|S]) :- C #= A + B.
|
||||
% func( - , [int(A), int(B)|S], [int(C)|S]) :- C #= B - A.
|
||||
% func( * , [int(A), int(B)|S], [int(C)|S]) :- C #= A * B.
|
||||
% func( / , [int(A), int(B)|S], [int(C)|S]) :- C #= B div A.
|
||||
% func('%', [int(A), int(B)|S], [int(C)|S]) :- C #= B mod A.
|
||||
|
||||
func('/%', [int(A), int(B)|S], [int(B div A), int(B mod A)|S]).
|
||||
func( pm , [int(A), int(B)|S], [int(A + B), int(B - A)|S]).
|
||||
% func('/%', [int(A), int(B)|S], [int(C), int(D)|S]) :- C #= B div A, D #= B mod A.
|
||||
% func( pm , [int(A), int(B)|S], [int(C), int(D)|S]) :- C #= A + B, D #= B - A.
|
||||
|
||||
func(>, [int(A), int(B)|S], [ bool(B > A)|S]).
|
||||
func(<, [int(A), int(B)|S], [ bool(B < A)|S]).
|
||||
func(=, [int(A), int(B)|S], [ bool(eq(B, A))|S]).
|
||||
func(>=, [int(A), int(B)|S], [ bool(B >= A)|S]).
|
||||
func(<=, [int(A), int(B)|S], [ bool(B =< A)|S]).
|
||||
func(<>, [int(A), int(B)|S], [bool(neq(B, A))|S]).
|
||||
% func(>, [int(A), int(B)|S], [T|S]) :- B #> A #<==> R, r_truth(R, T).
|
||||
% func(<, [int(A), int(B)|S], [T|S]) :- B #< A #<==> R, r_truth(R, T).
|
||||
% func(=, [int(A), int(B)|S], [T|S]) :- B #= A #<==> R, r_truth(R, T).
|
||||
% func(>=, [int(A), int(B)|S], [T|S]) :- B #>= A #<==> R, r_truth(R, T).
|
||||
% func(<=, [int(A), int(B)|S], [T|S]) :- B #=< A #<==> R, r_truth(R, T).
|
||||
% func(<>, [int(A), int(B)|S], [T|S]) :- B #\= A #<==> R, r_truth(R, T).
|
||||
|
||||
func(sqr) --> func(dup), func(mul). % Pretty neat.
|
||||
|
||||
r_truth(0, bool(false)).
|
||||
r_truth(1, bool(true)).
|
||||
|
||||
|
||||
/*
|
||||
|
||||
██████╗ ██████╗ ███╗ ███╗██████╗ ██╗███╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗
|
||||
██╔════╝██╔═══██╗████╗ ████║██╔══██╗██║████╗ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝
|
||||
██║ ██║ ██║██╔████╔██║██████╔╝██║██╔██╗ ██║███████║ ██║ ██║ ██║██████╔╝███████╗
|
||||
██║ ██║ ██║██║╚██╔╝██║██╔══██╗██║██║╚██╗██║██╔══██║ ██║ ██║ ██║██╔══██╗╚════██║
|
||||
╚██████╗╚██████╔╝██║ ╚═╝ ██║██████╔╝██║██║ ╚████║██║ ██║ ██║ ╚██████╔╝██║ ██║███████║
|
||||
╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
||||
|
||||
*/
|
||||
|
||||
combo(i, [list(P)|S], S, Ei, Eo) :- append(P, Ei, Eo).
|
||||
combo(dip, [list(P), X|S], S, Ei, Eo) :- append(P, [X|Ei], Eo).
|
||||
combo(dipd, [list(P), X, Y|S], S, Ei, Eo) :- append(P, [Y, X|Ei], Eo).
|
||||
|
||||
combo(dupdip, [list(P), X|S], [X|S], Ei, Eo) :- append(P, [X|Ei], Eo).
|
||||
|
||||
combo(branch, [list(T), list(_), bool(true)|S], S, Ei, Eo) :- append(T, Ei, Eo).
|
||||
combo(branch, [list(_), list(F), bool(false)|S], S, Ei, Eo) :- append(F, Ei, Eo).
|
||||
|
||||
combo(loop, [list(_), bool(false)|S], S, E, E ).
|
||||
combo(loop, [list(B), bool(true)|S], S, Ei, Eo) :- append(B, [list(B), symbol(loop)|Ei], Eo).
|
||||
|
||||
combo(step, [list(_), list([])|S], S, E, E ).
|
||||
combo(step, [list(P), list([X|Z])|S], [X|S], Ei, Eo) :- append(P, [list(Z), list(P), symbol(step)|Ei], Eo).
|
||||
|
||||
combo(times, [list(_), int(0)|S], S, E, E ).
|
||||
combo(times, [list(P), int(1)|S], S, Ei, Eo) :- append(P, Ei, Eo).
|
||||
combo(times, [list(P), int(N)|S], S, Ei, Eo) :- N #>= 2, M #= N - 1, append(P, [int(M), list(P), symbol(times)|Ei], Eo).
|
||||
combo(times, [list(_), int(N)|S], S, _, _ ) :- N #< 0, fail.
|
||||
|
||||
combo(genrec, [R1, R0, Then, If|S],
|
||||
[ Else, Then, If|S], E, [symbol(ifte)|E]) :-
|
||||
append(R0, [list([If, Then, R0, R1, symbol(genrec)])|R1], Else).
|
||||
|
||||
/*
|
||||
This is a crude but servicable implementation of the map combinator.
|
||||
|
||||
Obviously it would be nice to take advantage of the implied parallelism.
|
||||
Instead the quoted program, stack, and terms in the input list are
|
||||
transformed to simple Joy expressions that run the quoted program on
|
||||
prepared copies of the stack that each have one of the input terms on
|
||||
top. These expressions are collected in a list and the whole thing is
|
||||
evaluated (with infra) on an empty list, which becomes the output list.
|
||||
|
||||
The chief advantage of doing it this way (as opposed to using Prolog's
|
||||
map) is that the whole state remains in the pending expression, so
|
||||
there's nothing stashed in Prolog's call stack. This preserves the nice
|
||||
property that you can interrupt the Joy evaluation and save or transmit
|
||||
the stack+expression knowing that you have all the state.
|
||||
*/
|
||||
|
||||
combo(map, [list(_), list([])|S], [list([])|S], E, E ) :- !.
|
||||
combo(map, [list(P), list(List)|S], [list(Mapped), list([])|S], E, [symbol(infra)|E]) :-
|
||||
prepare_mapping(list(P), S, List, Mapped).
|
||||
|
||||
% Set up a program for each term in ListIn
|
||||
%
|
||||
% [term S] [P] infrst
|
||||
%
|
||||
% prepare_mapping(P, S, ListIn, ListOut).
|
||||
|
||||
prepare_mapping(Pl, S, In, Out) :- prepare_mapping(Pl, S, In, [], Out).
|
||||
|
||||
prepare_mapping( _, _, [], Out, Out) :- !.
|
||||
prepare_mapping( Pl, S, [T|In], Acc, Out) :-
|
||||
prepare_mapping(Pl, S, In, [list([T|S]), Pl, symbol(infrst)|Acc], Out).
|
||||
|
||||
|
||||
/*
|
||||
|
||||
██████╗ ███████╗███████╗██╗███╗ ██╗██╗████████╗██╗ ██████╗ ███╗ ██╗███████╗
|
||||
██╔══██╗██╔════╝██╔════╝██║████╗ ██║██║╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝
|
||||
██║ ██║█████╗ █████╗ ██║██╔██╗ ██║██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗
|
||||
██║ ██║██╔══╝ ██╔══╝ ██║██║╚██╗██║██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║
|
||||
██████╔╝███████╗██║ ██║██║ ╚████║██║ ██║ ██║╚██████╔╝██║ ╚████║███████║
|
||||
╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
|
||||
|
||||
*/
|
||||
|
||||
joy_def(Codes) :-
|
||||
text_to_expression(Codes, [symbol(Name)|Body]),
|
||||
% writeln(Name),
|
||||
assert_def(Name, Body).
|
||||
|
||||
assert_defs(DefsFile) :-
|
||||
read_file_to_codes(DefsFile, Codes, []),
|
||||
lines(Codes, Lines),
|
||||
maplist(joy_def, Lines).
|
||||
|
||||
assert_def(Symbol, Body) :-
|
||||
( % Don't let this "shadow" functions or combinators.
|
||||
\+ func(Symbol, _, _),
|
||||
\+ combo(Symbol, _, _, _, _)
|
||||
) -> ( % Replace any existing defs of this name.
|
||||
retractall(def(Symbol, _)),
|
||||
assertz(def(Symbol, Body))
|
||||
) ; true.
|
||||
|
||||
% Split on newline chars a list of codes into a list of lists of codes
|
||||
% one per line. Helper function.
|
||||
lines([], []) :- !.
|
||||
lines(Codes, [Line|Lines]) :- append(Line, [0'\n|Rest], Codes), !, lines(Rest, Lines).
|
||||
lines(Codes, [Codes]).
|
||||
|
||||
:- assert_defs("defs.txt").
|
||||
|
||||
|
||||
% A meta function that finds the names of all available functions.
|
||||
|
||||
words(Words) :-
|
||||
findall(Name, clause(func(Name, _, _), _), Funcs),
|
||||
findall(Name, clause(combo(Name, _, _, _, _), _), Combos, Funcs),
|
||||
findall(Name, clause(def(Name, _), _), Words0, Combos),
|
||||
list_to_set(Words0, Words1),
|
||||
sort(Words1, Words).
|
||||
|
||||
|
||||
/*
|
||||
|
||||
██████╗ ██████╗ ███╗ ███╗██████╗ ██╗██╗ ███████╗██████╗
|
||||
██╔════╝██╔═══██╗████╗ ████║██╔══██╗██║██║ ██╔════╝██╔══██╗
|
||||
██║ ██║ ██║██╔████╔██║██████╔╝██║██║ █████╗ ██████╔╝
|
||||
██║ ██║ ██║██║╚██╔╝██║██╔═══╝ ██║██║ ██╔══╝ ██╔══██╗
|
||||
╚██████╗╚██████╔╝██║ ╚═╝ ██║██║ ██║███████╗███████╗██║ ██║
|
||||
╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝
|
||||
_ ___ _ _
|
||||
| |_ ___ | _ \_ _| |_| |_ ___ _ _
|
||||
| _/ _ \ | _/ || | _| ' \/ _ \ ' \
|
||||
\__\___/ |_| \_, |\__|_||_\___/_||_|
|
||||
|__/
|
||||
|
||||
|
||||
We have a tabulator predicate.
|
||||
|
||||
*/
|
||||
|
||||
tabs(N) --> { N #> 0, M #= N - 1 },
|
||||
tab, tabs(M).
|
||||
|
||||
tabs(0) --> [].
|
||||
|
||||
nl --> "\n".
|
||||
|
||||
tab --> " ".
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Convert Prolog terms to Python source.
|
||||
|
||||
*/
|
||||
|
||||
% stack_to_python(F) --> { writeln(F), fail }.
|
||||
|
||||
stack_to_python(S) --> {atom(S), !, atom_codes(S, C)}, C.
|
||||
stack_to_python([]) --> "stack", !.
|
||||
stack_to_python([Term|Tail]) -->
|
||||
"(", term_to_python(Term), ", ", stack_to_python(Tail), ")".
|
||||
|
||||
|
||||
% Unify unbound terms with fresh Python identifiers.
|
||||
pyvar(Prefix, Term, Codes) :-
|
||||
( var(Term) -> gensym(Prefix, Term) ; atom(Term) ),
|
||||
atom_codes(Term, Codes).
|
||||
|
||||
term_to_python(Term) -->
|
||||
{ pyvar(v, Term, Var) }, !, Var.
|
||||
|
||||
term_to_python(bool(Term)) --> term_to_python(Term).
|
||||
|
||||
term_to_python(int(Term)) -->
|
||||
{ ( integer(Term) ->
|
||||
number_codes(Term, Int)
|
||||
;
|
||||
pyvar(i, Term, Int)
|
||||
)
|
||||
},
|
||||
Int.
|
||||
|
||||
term_to_python(list(Term)) --> list_to_python(Term).
|
||||
|
||||
term_to_python(Term) --> Term.
|
||||
|
||||
|
||||
list_to_python(Term) -->
|
||||
{ pyvar(s, Term, Var) }, !, Var.
|
||||
|
||||
list_to_python([]) --> "()", !.
|
||||
|
||||
list_to_python([Term|Tail]) -->
|
||||
"(", term_to_python(Term), ", ", list_to_python(Tail), ")".
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Generate Python code.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
code_gen([Head|Tail]) --> Head, code_gen(Tail).
|
||||
code_gen([]) --> [].
|
||||
|
||||
cg, Term --> [Term], cg.
|
||||
cg --> [].
|
||||
|
||||
compile_fn(Name) --> gronk_fn(Name), cg, !.
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
██████╗ ██████╗ ██████╗ ███╗ ██╗██╗ ██╗
|
||||
██╔════╝ ██╔══██╗██╔═══██╗████╗ ██║██║ ██╔╝
|
||||
██║ ███╗██████╔╝██║ ██║██╔██╗ ██║█████╔╝
|
||||
██║ ██║██╔══██╗██║ ██║██║╚██╗██║██╔═██╗
|
||||
╚██████╔╝██║ ██║╚██████╔╝██║ ╚████║██║ ██╗
|
||||
╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝
|
||||
|
||||
(GRONK stands for "I am bad at naming things.")
|
||||
|
||||
With gronk we're juggling four things:
|
||||
|
||||
The incoming joy expression
|
||||
The outgoing code tokens (for the code gen)
|
||||
The incoming stack representation
|
||||
and outgoing stack representation
|
||||
|
||||
The basic formula is like so (the indent level is an implementation
|
||||
detail):
|
||||
|
||||
gronk_fn_body(
|
||||
[joy expression]
|
||||
StackIn,
|
||||
StackOut,
|
||||
[code gen tokens]
|
||||
).
|
||||
|
||||
(Let's leave out DCGs for now, eh? Since I don't actually know how they
|
||||
work really yet, do I? ;P )
|
||||
|
||||
*/
|
||||
|
||||
gronk_fn(Name, Expr, CodeGens)
|
||||
:-
|
||||
CodeGens = ["def ", Name,"(stack, expression, dictionary):", nl,
|
||||
tab, stack_to_python(StackIn), " = stack", nl|Cs],
|
||||
CGTail = [tab, "return ", stack_to_python(StackOut), ", expression, dictionary", nl],
|
||||
reset_gensym(s), reset_gensym(v), reset_gensym(i),
|
||||
gronk_fn_list(Expr, StackIn, StackOut, CGTail, Cs, 1).
|
||||
|
||||
|
||||
gronk_fn_list(
|
||||
[list(BodyFalse), list(BodyTrue), symbol(branch)|Js],
|
||||
[bool(B)|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
CodeGens,
|
||||
IndentLevel)
|
||||
:-
|
||||
!,
|
||||
J #= IndentLevel + 1,
|
||||
CodeGens = [
|
||||
tabs(IndentLevel), "if ", term_to_python(B), ":", nl|Cs0],
|
||||
True = [tabs(J), stack_to_python(Stack), " = ", stack_to_python(StackT), nl,
|
||||
tabs(IndentLevel), "else:", nl|Cs1],
|
||||
False = [tabs(J), stack_to_python(Stack), " = ", stack_to_python(StackF), nl|Ck],
|
||||
gronk_fn_list(BodyTrue, StackIn, StackT, True, Cs0, J),
|
||||
gronk_fn_list(BodyFalse, StackIn, StackF, False, Cs1, J),
|
||||
gronk_fn_list(Js, Stack, StackOut, CGTail, Ck, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[list(Body), symbol(loop)|Js],
|
||||
[bool(B)|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
CodeGens,
|
||||
IndentLevel)
|
||||
:-
|
||||
!,
|
||||
J #= IndentLevel + 1,
|
||||
CodeGens = [
|
||||
tabs(IndentLevel), term_to_python(Tos), " = ", term_to_python(B), nl,
|
||||
tabs(IndentLevel), "while ", term_to_python(Tos), ":", nl|Cs
|
||||
],
|
||||
gronk_fn_list(Body, StackIn, [bool(Tos)|Stack], [tabs(J), stack_to_python(StackIn), " = ", stack_to_python(Stack), nl|Ck], Cs, J),
|
||||
gronk_fn_list(Js, StackIn, StackOut, CGTail, Ck, IndentLevel).
|
||||
% ^^^^^^^ wha!? not Stack!?
|
||||
|
||||
gronk_fn_list(
|
||||
[list(Body), symbol(dip)|Js],
|
||||
[Term|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
Cs,
|
||||
IndentLevel)
|
||||
:-
|
||||
!,
|
||||
gronk_fn_list(Body, StackIn, Stack, Ck, Cs, IndentLevel),
|
||||
gronk_fn_list(Js, [Term|Stack], StackOut, CGTail, Ck, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(step)|Js],
|
||||
[list(Body), list(B)|Stack0],
|
||||
Stack,
|
||||
CGTail,
|
||||
CodeGens,
|
||||
IndentLevel)
|
||||
:-
|
||||
!,
|
||||
J #= IndentLevel + 1,
|
||||
CodeGens = [
|
||||
tabs(IndentLevel), stack_to_python(Stack1), " = ", stack_to_python(Stack0), nl,
|
||||
tabs(IndentLevel), "while ", term_to_python(B), ":", nl,
|
||||
tabs(J), "(", term_to_python(T), ", ", term_to_python(B), ") = ", term_to_python(B), nl|CG2
|
||||
],
|
||||
CG1 = [tabs(J), stack_to_python(Stack1), " = ", stack_to_python(Stack2), nl|CG0],
|
||||
gronk_fn_list(Body, [T|Stack1], Stack2, CG1, CG2, J),
|
||||
gronk_fn_list(Js, Stack1, Stack, CGTail, CG0, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(abs)|Js],
|
||||
[In|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
[tabs(IndentLevel), term_to_python(Out), " = abs(", term_to_python(In), ")", nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
!, % green cut
|
||||
gronk_fn_list(Js, [Out|StackIn], StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(bool)|Js],
|
||||
[In|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
[tabs(IndentLevel), term_to_python(Out), " = bool(", term_to_python(In), ")", nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
!, % green cut
|
||||
gronk_fn_list(Js, [bool(Out)|StackIn], StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(stack)|Js],
|
||||
StackIn,
|
||||
StackOut,
|
||||
CGTail,
|
||||
[tabs(IndentLevel), stack_to_python(Stack), " = (", stack_to_python(StackIn), ", ", stack_to_python(StackIn), ")", nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
!, % green cut
|
||||
gronk_fn_list(Js, Stack, StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(swaack)|Js],
|
||||
[list(S)|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
% [tabs(IndentLevel), "pass", nl|Cs],
|
||||
[tabs(IndentLevel), stack_to_python(Stack), " = (", stack_to_python(StackIn), ", ", stack_to_python(S), ")", nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
!, % green cut
|
||||
gronk_fn_list(Js, Stack, StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(Sym)|Js],
|
||||
[int(B), int(A)|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
[tabs(IndentLevel), term_to_python(int(C)), " = ", term_to_python(int(A)), Op, term_to_python(int(B)), nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
bin_math_op(Sym, Op), !, % green cut
|
||||
gronk_fn_list(Js, [int(C)|StackIn], StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list(
|
||||
[symbol(Sym)|Js],
|
||||
[int(B), int(A)|StackIn],
|
||||
StackOut,
|
||||
CGTail,
|
||||
[tabs(IndentLevel), term_to_python(bool(C)), " = ", term_to_python(int(A)), Op, term_to_python(int(B)), nl|Cs],
|
||||
IndentLevel)
|
||||
:-
|
||||
bin_bool_op(Sym, Op), !, % green cut
|
||||
gronk_fn_list(Js, [bool(C)|StackIn], StackOut, CGTail, Cs, IndentLevel).
|
||||
|
||||
gronk_fn_list([symbol(Sym)|Js], S0, S, C0, C, IndentLevel) :-
|
||||
yin(Sym),
|
||||
func(Sym, S0, S1), !, % green cut
|
||||
gronk_fn_list(Js, S1, S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([symbol(Sym)|Js], S0, S, C0, C, IndentLevel) :-
|
||||
yin(Sym),
|
||||
def(Sym, Body), !, % green cut
|
||||
append(Body, Js, Expr),
|
||||
gronk_fn_list(Expr, S0, S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([bool(true)|Js], S0, S, C0, C, IndentLevel) :- !, % green cut
|
||||
gronk_fn_list(Js, [bool("True")|S0], S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([bool(false)|Js], S0, S, C0, C, IndentLevel) :- !, % green cut
|
||||
gronk_fn_list(Js, [bool("False")|S0], S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([int(I)|Js], S0, S, C0, C, IndentLevel) :- !, % green cut
|
||||
gronk_fn_list(Js, [int(I)|S0], S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([list(L)|Js], S0, S, C0, C, IndentLevel) :- !, % green cut
|
||||
gronk_fn_list(Js, [list(L)|S0], S, C0, C, IndentLevel).
|
||||
|
||||
gronk_fn_list([], Stack, Stack, Cs, Cs, _).
|
||||
|
||||
|
||||
bin_math_op(+, " + ").
|
||||
bin_math_op(-, " - ").
|
||||
bin_math_op(*, " * ").
|
||||
bin_math_op(div, " // ").
|
||||
bin_math_op( / , " // ").
|
||||
bin_math_op(mod, " % ").
|
||||
bin_math_op('%', " % ").
|
||||
|
||||
bin_bool_op(>, " > ").
|
||||
bin_bool_op(<, " < ").
|
||||
bin_bool_op(=, " == ").
|
||||
bin_bool_op(>=, " >= ").
|
||||
bin_bool_op(<=, " <= ").
|
||||
bin_bool_op(<>, " != ").
|
||||
|
||||
yin(bool).
|
||||
yin(cons).
|
||||
yin(dip).
|
||||
yin(dup).
|
||||
yin(dupd).
|
||||
yin(dupdd).
|
||||
yin(first).
|
||||
yin(gcd).
|
||||
yin(over).
|
||||
yin(pop).
|
||||
yin(product).
|
||||
yin(rest).
|
||||
yin(rolldown).
|
||||
yin(rollup).
|
||||
yin(shift).
|
||||
yin(step).
|
||||
yin(stackd).
|
||||
yin(sum).
|
||||
yin(swap).
|
||||
yin(tuck).
|
||||
yin(uncons).
|
||||
yin(unit).
|
||||
yin(Sym) :- def(Sym, Body), maplist(yins, Body).
|
||||
|
||||
yins(int(_)).
|
||||
yins(bool(_)).
|
||||
yins(list(_)).
|
||||
|
||||
yins(symbol(Sym)) :- yin(Sym).
|
||||
yins(symbol(Sym)) :- bin_math_op(Sym, _).
|
||||
yins(symbol(Sym)) :- bin_bool_op(Sym, _).
|
||||
|
||||
|
||||
/*
|
||||
concat
|
||||
flatten
|
||||
swaack
|
||||
clear
|
||||
bool+
|
||||
|
||||
list ops (empty? list? ...)
|
||||
logic ops (and or ...)
|
||||
|
||||
COMBINATORS
|
||||
|
||||
*/
|
||||
|
||||
|
||||
gronk(Name, BodyText) :-
|
||||
text_to_expression(BodyText, Expr),
|
||||
gronk_fn(Name, Expr, Out),
|
||||
code_gen(Out, A, []), !,
|
||||
string_codes(S, A),
|
||||
writeln(""),
|
||||
writeln(S).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
do :-
|
||||
gronk("abs", `abs`),
|
||||
gronk("ccons", `ccons`),
|
||||
gronk("cons", `cons`),
|
||||
gronk("decr", `--`),
|
||||
gronk("dup", `dup`),
|
||||
gronk("dupd", `dupd`),
|
||||
gronk("dupdd", `dupdd`),
|
||||
gronk("first", `first`),
|
||||
gronk("fourth", `fourth`),
|
||||
gronk("incr", `++`),
|
||||
gronk("non_negative", `!-`),
|
||||
gronk("pop", `pop`),
|
||||
gronk("popd", `popd`),
|
||||
gronk("popop", `popop`),
|
||||
gronk("popopd", `popopd`),
|
||||
gronk("quoted", `quoted`),
|
||||
gronk("reco", `reco`),
|
||||
gronk("rest", `rest`),
|
||||
gronk("rrest", `rrest`),
|
||||
gronk("second", `second`),
|
||||
gronk("shift", `shift`),
|
||||
gronk("sqr", `sqr`),
|
||||
gronk("stackd", `stackd`), % Compiling func(stackd, ...) doesn't work.
|
||||
gronk("swons", `swons`),
|
||||
gronk("third", `third`),
|
||||
gronk("truthy", `?`),
|
||||
gronk("tuckl", `<{}`),
|
||||
gronk("tuckld", `<<{}`),
|
||||
gronk("uncons", `uncons`),
|
||||
gronk("unit", `unit`),
|
||||
gronk("unswons", `unswons`),
|
||||
gronk("gcd", `gcd`),
|
||||
gronk("sum", `sum`),
|
||||
gronk("product", `product`),
|
||||
writeln("").
|
||||
Loading…
Reference in New Issue