528 lines
12 KiB
Prolog
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`).
|
|
|
|
|
|
*/
|