The user can declare initial, possibly recursive programs by composing the tokens described above. Programs are sequentially written into , starting with at address 1. To declare a new token (program) we write decl(m, n, NAME, body), where NAME is the textual name of the code. Textual names are of interest only for the user, since the system immediately translates any new name into the smallest integer which gets associated with the topmost unused code address; then is incremented. Argument denotes the code's number of expected arguments on top of the data stack ds; denotes the number of return values; body is a string of names of previously defined instructions, and possibly one new name to allow for cross-recursion. Once the interpreter comes across a user-defined token, it simply calls the code in starting with that body's first token; once the code is executed, the interpreter returns to the address of the next token, using the callstack . All of this is quite similar to the case of self-made functions defined by the system itself -- compare instruction def in section A.2.2.
Here are some samples of user-defined tokens or programs composed from the primitive instructions defined above. Declarations omit parantheses for argument lists of instructions.
decl(-1,-1,defnp, c0 toD pushdp dec toD qot def up rt0 dec intpf cpn qot ret)
decl(-1,-1,calltp, qot topf dof intpf cpn qot ret)
decl(-1,-1,endnp,qot ret qot fromD cpnb fromD up delD fromD ex bsf ret)
decl(-1, -1, TAILREC, qot c1 c1 def up qot c2 outb qot ex rt0 del up dec topf dof qot c3 outb qot ret qot c1 outb c3 bsjmp) declares a tail recursion scheme TAILREC with a functional argument. Suppose the data stack ds holds three values , val, and codenum above the current base pointer. Then TAILREC will create a function that returns val if , else applies the 2-argument function represented by codenum, where the arguments are and the result of calling the 2-argument function itself on the value .
For example, the following code fragment uses TAILREC to implement yet another version of FAC(n): (qot c1 mul qot TAILREC ret). Assuming on ds, it first quotes the constant c1 (the return value for the terminal case ) and the function mul, then applies TAILREC.
To fully understand a given program, one may need to know which instruction has got which number. For the sake of completeness, and to permit precise re-implementation, we include the full list here:
1: 1toD, 2: 2toD, 3: mvdsk, 4: xAD, 5: xSA, 6: bsf, 7: boostq, 8: add, 9: mul, 10: powr, 11: sub, 12: div, 13: inc, 14: dec, 15: by2, 16: getq, 17: insq, 18: findb, 19: incQ, 20: decQ, 21: pupat, 22: setpat, 23: insn, 24: mvn, 25: deln, 26: intpf, 27: def, 28: topf, 29: dof, 30: oldf, 31: bsjmp, 32: ret, 33: rt0, 34: neg, 35: eq, 36: grt, 37: clear, 38: del, 39: up, 40: ex, 41: jmp1, 42: outn, 43: inn, 44: cpn, 45: xmn, 46: outb, 47: inb, 48: cpnb, 49: xmnb, 50: ip2ds, 51: pip, 52: pushdp, 53: dp2ds, 54: toD, 55: fromD, 56: delD, 57: tsk, 58: c0, 59: c1, 60: c2, 61: c3, 62: c4, 63: c5, 64: exec, 65: qot, 66: nop, 67: fak, 68: fak2, 69: c999, 70: testexp, 71: defnp, 72: calltp, 73: endnp.