- '''
- Run the quoted program on TOS on the items in the list under it, push a
- new list with the results (in place of the program and original list.
- '''
-# (quote, (aggregate, stack)) = S
-# results = list_to_stack([
-# joy((term, stack), quote, dictionary)[0][0]
-# for term in iter_stack(aggregate)
-# ])
-# return (results, stack), expression, dictionary
- (quote, (aggregate, stack)) = S
- if not aggregate:
- return (aggregate, stack), expression, dictionary
- batch = ()
- for term in iter_stack(aggregate):
- s = term, stack
- batch = (s, (quote, (S_infra, (S_first, batch))))
- stack = (batch, ((), stack))
- return stack, (S_infra, expression), dictionary
+ '''
+ Run the quoted program on TOS on the items in the list under it, push a
+ new list with the results in place of the program and original list.
+ '''
+ # (quote, (aggregate, stack)) = S
+ # results = list_to_stack([
+ # joy((term, stack), quote, dictionary)[0][0]
+ # for term in iter_stack(aggregate)
+ # ])
+ # return (results, stack), expression, dictionary
+ (quote, (aggregate, stack)) = S
+ if not aggregate:
+ return (aggregate, stack), expression, dictionary
+ batch = ()
+ for term in iter_stack(aggregate):
+ s = term, stack
+ batch = (s, (quote, (S_infra, (S_first, batch))))
+ stack = (batch, ((), stack))
+ return stack, (S_infra, expression), dictionary
+
+
+@inscribe
+@FunctionWrapper
+def primrec(stack, expression, dictionary):
+ '''
+ From the "Overview of the language JOY":
+
+ > The primrec combinator expects two quoted programs in addition to a
+ data parameter. For an integer data parameter it works like this: If
+ the data parameter is zero, then the first quotation has to produce
+ the value to be returned. If the data parameter is positive then the
+ second has to combine the data parameter with the result of applying
+ the function to its predecessor.::
+
+ 5 [1] [*] primrec
+
+ > Then primrec tests whether the top element on the stack (initially
+ the 5) is equal to zero. If it is, it pops it off and executes one of
+ the quotations, the [1] which leaves 1 on the stack as the result.
+ Otherwise it pushes a decremented copy of the top element and
+ recurses. On the way back from the recursion it uses the other
+ quotation, [*], to multiply what is now a factorial on top of the
+ stack by the second element on the stack.::
+
+ n [Base] [Recur] primrec
+
+ 0 [Base] [Recur] primrec
+ ------------------------------
+ Base
+
+ n [Base] [Recur] primrec
+ ------------------------------------------ n > 0
+ n (n-1) [Base] [Recur] primrec Recur
+
+ '''
+ recur, (base, (n, stack)) = stack
+ if n <= 0:
+ expression = concat(base, expression)
+ else:
+ expression = S_primrec, concat(recur, expression)
+ stack = recur, (base, (n - 1, (n, stack)))
+ return stack, expression, dictionary