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 # 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 @inscribe
@FunctionWrapper @FunctionWrapper
def app1(S, expression, dictionary): def app1(S, expression, dictionary):
@ -277,68 +221,3 @@ def times(stack, expression, dictionary):
# return 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.:: It works by rewriting into a chain of nested `ifte` expressions, e.g.::
[[D]] cond [[D]] cond
---------------- (Kind of pointless) ----------------
D D
[[[IF] THEN] [D]] cond [[[IF] THEN] [D]] cond
@ -2058,6 +2058,7 @@ def cond(stack, expr, dictionary):
----------------------------------- (multiple conditions) ----------------------------------- (multiple conditions)
[IF] [THEN] [[...] cond] ifte [IF] [THEN] [[...] cond] ifte
The middle case isn't actually implemented. It's implied by the The middle case isn't actually implemented. It's implied by the
base case and the "multiple conditions" case. base case and the "multiple conditions" case.
''' '''
@ -2081,6 +2082,69 @@ def cond(stack, expr, dictionary):
return 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__': if __name__ == '__main__':
import sys import sys