cond
This commit is contained in:
parent
77bd7790f5
commit
f640f437f1
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -2031,6 +2031,56 @@ def ifte(stack, expr, dictionary):
|
|||
return stack, expr, dictionary
|
||||
|
||||
|
||||
S_cond = Symbol('cond')
|
||||
|
||||
|
||||
@inscribe
|
||||
def cond(stack, expr, 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.::
|
||||
|
||||
[[D]] cond
|
||||
---------------- (Kind of pointless)
|
||||
D
|
||||
|
||||
[[[IF] THEN] [D]] cond
|
||||
---------------------------- (with single condition, same as ifte)
|
||||
[IF] [THEN] [D] ifte
|
||||
|
||||
|
||||
[[[IF] THEN] ...] cond
|
||||
----------------------------------- (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.
|
||||
'''
|
||||
conditions, stack = get_n_items(1, stack)
|
||||
isnt_stack(conditions)
|
||||
if not conditions:
|
||||
raise StackUnderflowError('cond without default clause')
|
||||
|
||||
condition_clause, conditions = conditions
|
||||
isnt_stack(condition_clause)
|
||||
|
||||
if not conditions: # This is the default clause, run it.
|
||||
expr = push_quote(condition_clause, expr)
|
||||
else:
|
||||
if_, then = get_n_items(1, condition_clause)
|
||||
isnt_stack(if_)
|
||||
else_ = (conditions, (S_cond, ()))
|
||||
stack = (else_, (then, (if_, stack)))
|
||||
expr = push_quote((S_ifte, ()), expr)
|
||||
|
||||
return stack, expr, dictionary
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
|
|
@ -2041,5 +2091,10 @@ if __name__ == '__main__':
|
|||
## stack = J(dictionary=dictionary)
|
||||
## except SystemExit:
|
||||
## pass
|
||||
stack, _ = run("5 10 [>][++][*]ifte", (), dictionary)
|
||||
jcode = "5 10 [>][++][*]ifte"
|
||||
jcode = '1 2 [[+]] cond'
|
||||
jcode = '1 2 [[[>] -] [[<] +] [*]] cond'
|
||||
jcode = '2 1 [[[>] -] [[<] +] [*]] cond'
|
||||
jcode = '3 3 [[[>] -] [[<] +] [*]] cond'
|
||||
stack, _ = run(jcode, (), dictionary)
|
||||
print(stack_to_string(stack), '•')
|
||||
|
|
|
|||
Loading…
Reference in New Issue