cond
This commit is contained in:
parent
77bd7790f5
commit
f640f437f1
|
|
@ -75,99 +75,6 @@ S_times = Symbol('times')
|
||||||
# return (q, (p, stack)), expression, dictionary
|
# 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
|
@inscribe
|
||||||
@FunctionWrapper
|
@FunctionWrapper
|
||||||
def dip(stack, expression, dictionary):
|
def dip(stack, expression, dictionary):
|
||||||
|
|
|
||||||
|
|
@ -2031,6 +2031,56 @@ def ifte(stack, expr, dictionary):
|
||||||
return 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__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
@ -2041,5 +2091,10 @@ if __name__ == '__main__':
|
||||||
## stack = J(dictionary=dictionary)
|
## stack = J(dictionary=dictionary)
|
||||||
## except SystemExit:
|
## except SystemExit:
|
||||||
## pass
|
## 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), '•')
|
print(stack_to_string(stack), '•')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue