This commit is contained in:
Simon Forman
2022-09-12 13:50:40 -07:00
parent 77bd7790f5
commit f640f437f1
2 changed files with 56 additions and 94 deletions
-93
View File
@@ -75,99 +75,6 @@ S_times = Symbol('times')
# return (q, (p, stack)), expression, dictionary
@inscribe
@FunctionWrapper
def branch(stack, expression, dictionary):
'''
Use a Boolean value to select one of two quoted programs to run.
::
branch == roll< choice i
::
False [F] [T] branch
--------------------------
F
True [F] [T] branch
-------------------------
T
'''
(then, (else_, (flag, stack))) = stack
return stack, concat(then if flag else else_, expression), dictionary
@inscribe
@FunctionWrapper
def ifte(stack, expression, dictionary):
'''
If-Then-Else Combinator
::
... [if] [then] [else] ifte
---------------------------------------------------
... [[else] [then]] [...] [if] infra select i
... [if] [then] [else] ifte
-------------------------------------------------------
... [else] [then] [...] [if] infra first choice i
Has the effect of grabbing a copy of the stack on which to run the
if-part using infra.
'''
(else_, (then, (if_, stack))) = stack
expression = (S_infra, (S_first, (S_choice, (S_i, expression))))
stack = (if_, (stack, (then, (else_, stack))))
return stack, expression, dictionary
@inscribe
@FunctionWrapper
def cond(stack, expression, dictionary):
'''
This combinator works like a case statement. It expects a single quote
on the stack that must contain zero or more condition quotes and a
default quote. Each condition clause should contain a quoted predicate
followed by the function expression to run if that predicate returns
true. If no predicates return true the default function runs.
It works by rewriting into a chain of nested `ifte` expressions, e.g.::
[[[B0] T0] [[B1] T1] [D]] cond
-----------------------------------------
[B0] [T0] [[B1] [T1] [D] ifte] ifte
'''
conditions, stack = stack
if conditions:
expression = _cond(conditions, expression)
try:
# Attempt to preload the args to first ifte.
(P, (T, (E, expression))) = expression
except ValueError:
# If, for any reason, the argument to cond should happen to contain
# only the default clause then this optimization will fail.
pass
else:
stack = (E, (T, (P, stack)))
return stack, expression, dictionary
def _cond(conditions, expression):
(clause, rest) = conditions
if not rest: # clause is [D]
return clause
P, T = clause
return (P, (T, (_cond(rest, ()), (S_ifte, expression))))
@inscribe
@FunctionWrapper
def dip(stack, expression, dictionary):