Thun/implementations/oldlog/source/fuuu.pl

528 lines
12 KiB
Prolog

f, [foo] --> [bar]. % f([bar|A], [foo|A]).
g, [bas] --> [quo]. % g([quo|A], [bas|A]).
end, [end] --> []. % end(A, [end|A]).
k --> f, g, end.
% k(A, B) :- f(A, C), g(C, D), end(D, B).
/* So I DON'T know what I was doing.
f replaces foo with bar and then passes the whole enchilada on to the
next predicate. I guess I somehow thought it was building an output list
or something?
*/
/*
?- gronk("fn", `[swap] [] branch `).
def fn(stack, expression, dictionary):
(v1, (v2, (v3, stack))) = stack
if v1:
stack = (v2, (v3, stack))
else:
stack = (v3, (v2, stack))
return stack, expression, dictionary
?- gronk("fn", `[swap] [] branch pop`).
def fn(stack, expression, dictionary):
(v1, (v2, (v3, stack))) = stack
if v1:
(v4, stack) = (v2, (v3, stack))
else:
(v4, stack) = (v3, (v2, stack))
return stack, expression, dictionary
?- gronk("fn", `over over > [swap] [] branch pop`).
def fn(stack, expression, dictionary):
(v1, (v2, stack)) = stack
v3 = v2 > v1
if v3:
(v4, stack) = (v1, (v2, stack))
else:
(v4, stack) = (v2, (v1, stack))
return stack, expression, dictionary
Here's a case where factoring the pop to after the branch results in
inefficient code. (Compare the function below to the versions above. It
doesn't create and then immediately discard a v4 variable.)
?- gronk("fn", `[swap pop] [pop] branch`).
def fn(stack, expression, dictionary):
(v1, (v2, (v3, stack))) = stack
if v1:
stack = (v3, stack)
else:
stack = (v2, stack)
return stack, expression, dictionary
*/
/*
gronk_fn_list([symbol(*)], [int(A),int(A)|B], StackOut, [tab,"return ",stack_to_python(StackOut),", expression, dictionary",nl], CGTail, 1)
def fn(stack, expression, dictionary):
tos = True
while tos:
(v1, (v2, stack)) = stack
v3 = v2 % v1
tos = v3 > 0
stack = (v3, (v1, stack))
(v4, stack) = stack
return stack, expression, dictionary
Close, but broken. THe boundaries between blocks are too permeable.
?- gronk("fn", `true [>] loop`).
def fn(stack, expression, dictionary):
(v1, (v2, stack)) = stack
tos = True
while tos:
v3 = v1 > v2
tos = v3
return stack, expression, dictionary
gronk_fn_list(
[symbol(*)],
[int(A),int(A)|B],
StackOut,
[tab,"return ",stack_to_python(StackOut),", expression, dictionary",nl],
CGTail,
1
).
?- gronk("fn", `stack`).
def fn(stack, expression, dictionary):
stack = stack
return ((), stack), expression, dictionary
SHould be
?- gronk("fn", `stack`).
def fn(stack, expression, dictionary):
return (stack, stack), expression, dictionary
Okay then...
?- gronk("fn", `over over + stack dup`).
def fn(stack, expression, dictionary):
(i1, (i2, stack)) = stack
v1 = i2 + i1
(v2, stack) = ((v1, (i1, (i2, stack))), (v1, (i1, (i2, stack))))
return (v2, (v2, stack)), expression, dictionary
*/
/*
gronk_fn_body([int(A), int(B)|S], StackOut, IndentLevel, [symbol(Sym)|D], E) :-
[symbol(Sym)|D]=[symbol(Sym)|F],
bin_math_op(Sym, Op),
G=F,
gronk_fn_body([int(C)|S],
StackOut,
IndentLevel,
G,
H),
E=[tabs(IndentLevel), term_to_python(C), " = ", term_to_python(A), Op, term_to_python(B), nl|H].
gronk_fn_body([int(A), int(B)|S], StackOut, IndentLevel, [symbol(Sym)|D], E) :-
[symbol(Sym)|D]=[symbol(Sym)|F],
bin_bool_op(Sym, Op),
G=F,
gronk_fn_body([bool(C)|S],
StackOut,
IndentLevel,
G,
H),
E=[tabs(IndentLevel), term_to_python(C), " = ", term_to_python(A), Op, term_to_python(B), nl|H].
gronk_fn_body(S, S, _, A, [tab, "return ", stack_to_python(S), ", expression, dictionary", nl|A]).
Yeah, that can't be right... I'm basically in "How did this ever work?" territory.
?- gronk("fn", `+ +`).
def fn(stack, expression, dictionary):
(v1, (v2, (v3, stack))) = stack
v4 = v1 + v2
v5 = v4 + v3
return (v5, stack), expression, dictionary
?- gronk("fn", `+ * - div mod`).
def fn(stack, expression, dictionary):
(v1, (v2, (v3, (v4, (v5, (v6, stack)))))) = stack
v7 = v1 + v2
v8 = v7 * v3
v9 = v8 - v4
v10 = v9 // v5
v11 = v10 % v6
return (v11, stack), expression, dictionary
?- gronk_fn("name", [symbol(+)], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, stack)) = stack
stack = (v3, stack)
return stack, expression, dictionary
v3 = v1 + v2
Reversing the order reversed the output... I wish i knew what I was
doing... :)
?- gronk_fn("name", [symbol(+)], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, stack)) = stack
v3 = v1 + v2
stack = (v3, stack)
return stack, expression, dictionary
?- gronk_fn("name", [symbol(+), symbol(+)], Out), code_gen(Out, A, []), !, string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, (v3, stack))) = stack
v4 = v1 + v2
v5 = v4 + v3
stack = (v5, stack)
return stack, expression, dictionary
Whatever, it works now.
*/
/*
?- gronk_fn("name", [], [], Out), code_gen(Out, In, []).
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, "return stack, expression, dictionary", nl],
In = "def name(stack, expressio...nary
".
?- listing(cg).
cg(A, D) :-
A=[C|B],
cg(B, E),
phrase(C, D, E).
cg(A, A).
?- gronk_fn("name", [], [], Out), cg(Out,C).
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, "return stack, expression, dictionary", nl],
C = "def name(stack, expressio...nary
" ;
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, "return stack, expression, dictionary", nl],
C = [100, 101, 102, 32, 110, 97, 109, 101, 40|...] .
?- phrase((gronk_fn("name", []), cg), [], Out).
Out = "def name(stack, expressio...nary
" ;
Out = [100, 101, 102, 32, 110, 97, 109, 101, 40|...] ;
Out = [100, 101, 102, 32, 110, 97, 109, 101, 40|...] ;
Out = [100, 101, 102, 32, 110, 97, 109, 101, 40|...] ;
Out = [100, 101, 102, 32, 110, 97, 109, 101, 40|...] ;
Out = [100, 101, 102, 32, 110, 97, 109, 101, "(stack, expression, dictionary):"|...] ;
Out = [100, 101, 102, 32, "name", "(stack, expression, dictionary):", nl, tab, "return stack, expression, dictionary"|...] .
Bleah.
?- gronk_fn("name", [symbol(+)], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, stack)) = stack
stack = (v3, stack)
return stack, expression, dictionary
v3 = v1 + v2
Almost, but not quite. The assignment is happening after the return call!
=-=-=-=--=-=-=-=-==-=-
?- gronk_fn("name", [], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
stack = stack
stack = stack
return stack, expression, dictionary
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, stack_to_python([]), " = stack", nl, tab|...],
A = "def name(stack, expressio...nary
",
S = "def name(stack, expression, dictionary):\n stack = stack\n stack = stack\n return stack, expression, dictionary\n" .
?- gronk_fn("name", [symbol(+)], Out), writeln(Out).
[def ,name,(stack, expression, dictionary):,nl,tab,stack_to_python([int(_274090),int(_274100)|_274096]), = stack,nl,tab,stack = ,stack_to_python([int(_274110)|_274096]),nl,tab,return stack, expression, dictionary,nl,tabs(1),term_to_python(_274110), = ,term_to_python(_274090), + ,term_to_python(_274100),nl]
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, stack_to_python([int(_274090), int(...)|...]), " = stack", nl, tab|...] .
?- gronk_fn("name", [symbol(+)], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, stack)) = stack
stack = (v3, stack)
return stack, expression, dictionary
v3 = v1 + v2
Out = ["def ", "name", "(stack, expression, dictionary):", nl, tab, stack_to_python([int(v1), int(...)]), " = stack", nl, tab|...],
A = "def name(stack, expressio...+ v2
",
S = "def name(stack, expression, dictionary):\n (v1, (v2, stack)) = stack\n stack = (v3, stack)\n return stack, expression, dictionary\n v3 = v1 + v2\n" .
=-=-=-=--=-=-=-=-==-=-
There we go...
?- gronk_fn("name", [symbol(+)], Out), code_gen(Out, A, []), string_codes(S, A), writeln(""), writeln(S).
def name(stack, expression, dictionary):
(v1, (v2, stack)) = stack
v3 = v1 + v2
stack = (v3, stack)
return stack, expression, dictionary
?- do(`dup dup +`).
(v5, stack) = stack
stack = ((v5 + v5), (v5, stack))
true .
That's better.
?- do(`[* / - + dup] [dup + over *] branch * * `).
tos, stack = stack
if tos:
(v16, (v17, stack)) = stack
stack = ((v17 * (v16 + v16)), (v17, stack))
else:
(v18, (v19, (v20, (v21, (v22, stack))))) = stack
stack = (((v21 - (v20 // (v18 * v19))) + v22), (((v21 - (v20 // (v18 * v19))) + v22), stack))
(v23, (v24, (v25, stack))) = stack
stack = (((v23 * v24) * v25), stack)
true .
That's beautiful.
Of course, if we carried through the expression for the stack...
tos, stack = stack
if tos:
(v16, (v17, stack)) = stack
(v23, (v24, (v25, stack))) = ((v17 * (v16 + v16)), (v17, stack))
else:
(v18, (v19, (v20, (v21, (v22, stack))))) = stack
(v23, (v24, (v25, stack))) = (((v21 - (v20 // (v18 * v19))) + v22), (((v21 - (v20 // (v18 * v19))) + v22), stack))
stack = (((v23 * v24) * v25), stack)
we could assign the new variables directly from the previous stage,
saving the packing and unpacking of the "stack" tuple.
"Something to think about."
With symbolic Booleans this works now (there were a lot of bugs but I
don't know what they were.)
?- do(`<= [+] [-] branch`).
(v1, (v2, stack)) = stack
stack = ((v2 <= v1), stack)
tos, stack = stack
if tos:
(v3, (v4, stack)) = stack
stack = ((v4 - v3), stack)
else:
(v5, (v6, stack)) = stack
stack = ((v5 + v6), stack)
true.
Now we can compile GCD:
?- do(`true [tuck % dup 0 >] loop pop`).
stack = True, stack
tos, stack = stack
while tos:
(v9, (v10, stack)) = stack
stack = ((v10 % v9), ((v10 % v9), (v9, stack)))
stack = 0, stack
(v11, (v12, stack)) = stack
stack = ((v12 > v11), stack)
tos, stack = stack
(v13, stack) = stack
stack = stack
true.
It's not ideal, for example, it computes v10 % v9 twice. :(
We would like, e.g.:
tos = True
while tos:
(v9, (v10, stack)) = stack
vN = v10 % v9
stack = ((vN), ((vN), (v9, stack)))
(v11, (v12, stack)) = 0, stack
stack = ((v12 > v11), stack)
tos, stack = stack
(v13, stack) = stack
stack = stack
tos = True
while tos:
(v9, (v10, stack)) = stack
vN = v10 % v9
stack = ((vN), ((vN), (v9, stack)))
(v12, stack) = stack
stack = ((v12 > 0), stack)
tos, stack = stack
(v13, stack) = stack
tos = True
while tos:
(v9, (v10, stack)) = stack
vN = v10 % v9
stack = ((vN), ((vN), (v9, stack)))
(v12, stack) = stack
tos = (v12 > 0)
(v13, stack) = stack
tos = True
while tos:
(v9, (v10, stack)) = stack
vN = v10 % v9
(v12, stack) = ((vN), ((vN), (v9, stack)))
tos = (v12 > 0)
(v13, stack) = stack
tos = True
while tos:
(v9, (v10, stack)) = stack
vN = v10 % v9
stack = (vN, (v9, stack))
tos = (vN > 0)
(v13, stack) = stack
Anyhow... I could keep going but you get the idea. The simple
mechanical translation results in correct but inefficient code.
I'm not too worried about it, this is great progress nonetheless, but it
would be nice to tighten up that code gen.
What's that "stack = stack" doing in there?
do(`[[dup dup] [dup] branch dup [dup] loop dup] loop dup`).
do(`[dup] [[dup dup dup] [dup dup] branch] branch`).
*/