dipd, dipdd, cmp

This commit is contained in:
Simon Forman 2022-09-12 15:17:32 -07:00
parent f640f437f1
commit 8778f12b68
2 changed files with 65 additions and 122 deletions

View File

@ -75,62 +75,6 @@ S_times = Symbol('times')
# return (q, (p, stack)), expression, dictionary
@inscribe
@FunctionWrapper
def dip(stack, expression, dictionary):
'''
The dip combinator expects a quoted program on the stack and below it
some item, it hoists the item into the expression and runs the program
on the rest of the stack.
::
... x [Q] dip
-------------------
... Q x
'''
try:
(quote, (x, stack)) = stack
except ValueError:
raise StackUnderflowError('Not enough values on stack.')
expression = (x, expression)
return stack, concat(quote, expression), dictionary
@inscribe
@FunctionWrapper
def dipd(S, expression, dictionary):
'''
Like dip but expects two items.
::
... y x [Q] dip
---------------------
... Q y x
'''
(quote, (x, (y, stack))) = S
expression = (y, (x, expression))
return stack, concat(quote, expression), dictionary
@inscribe
@FunctionWrapper
def dipdd(S, expression, dictionary):
'''
Like dip but expects three items.
::
... z y x [Q] dip
-----------------------
... Q z y x
'''
(quote, (x, (y, (z, stack)))) = S
expression = (z, (y, (x, expression)))
return stack, concat(quote, expression), dictionary
@inscribe
@FunctionWrapper
def app1(S, expression, dictionary):
@ -277,68 +221,3 @@ def times(stack, expression, dictionary):
# return stack, expression, dictionary
@inscribe
@FunctionWrapper
def loop(stack, expression, dictionary):
'''
Basic loop combinator.
::
... True [Q] loop
-----------------------
... Q [Q] loop
... False [Q] loop
------------------------
...
'''
try:
quote, stack = stack
except ValueError:
raise StackUnderflowError('Not enough values on stack.')
if not isinstance(quote, tuple):
raise NotAListError('Loop body not a list.')
try:
(flag, stack) = stack
except ValueError:
raise StackUnderflowError('Not enough values on stack.')
if flag:
expression = concat(quote, (quote, (S_loop, expression)))
return stack, expression, dictionary
@inscribe
@FunctionWrapper
def cmp_(stack, expression, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
::
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, (E, (G, (b, (a, stack)))) = stack
expression = concat(G if a > b else L if a < b else E, expression)
return stack, expression, dictionary
# FunctionWrapper(cleave),
# FunctionWrapper(while_),
for name, primitive in getmembers(genlib, isfunction):
inscribe(SimpleFunctionWrapper(primitive))

View File

@ -2046,7 +2046,7 @@ def cond(stack, expr, dictionary):
It works by rewriting into a chain of nested `ifte` expressions, e.g.::
[[D]] cond
---------------- (Kind of pointless)
----------------
D
[[[IF] THEN] [D]] cond
@ -2058,6 +2058,7 @@ def cond(stack, expr, dictionary):
----------------------------------- (multiple conditions)
[IF] [THEN] [[...] cond] ifte
The middle case isn't actually implemented. It's implied by the
base case and the "multiple conditions" case.
'''
@ -2081,6 +2082,69 @@ def cond(stack, expr, dictionary):
return stack, expr, dictionary
@inscribe
def dipd(stack, expr, dictionary):
'''
The dipd combinator is like dip but expects two items.
... y x [Q] dipd
----------------------
... Q y x
'''
quote, x, y, stack = get_n_items(3, stack)
isnt_stack(quote)
expr = push_quote((y, (x, ())), expr)
expr = push_quote(quote, expr)
return stack, expr, dictionary
@inscribe
def dipdd(stack, expr, dictionary):
'''
The dipdd combinator is like dip but expects three items.
... y x z [Q] dipdd
-------------------------
... Q y x z
'''
quote, x, y, z, stack = get_n_items(3, stack)
isnt_stack(quote)
expr = push_quote((z, (y, (x, ()))), expr)
expr = push_quote(quote, expr)
return stack, expr, dictionary
@inscribe
def cmp_(stack, expr, dictionary):
'''
cmp takes two values and three quoted programs on the stack and runs
one of the three depending on the results of comparing the two values:
::
a b [G] [E] [L] cmp
------------------------- a > b
G
a b [G] [E] [L] cmp
------------------------- a = b
E
a b [G] [E] [L] cmp
------------------------- a < b
L
'''
L, E, G, b, a, stack = get_n_items(5, stack)
isnt_stack(L)
isnt_stack(E)
isnt_stack(G)
isnt_int(b)
isnt_int(a)
expr = push_quote(G if a > b else L if a < b else E, expr)
return stack, expr, dictionary
if __name__ == '__main__':
import sys