All pastes #928023 Raw Edit

Stuff

public text v1 · immutable
·published 2008-03-04 19:06 UTC
rendered paste body
-*- fill-column:73; ais523autofill:t; -*-

Commands are given in the form (removed from stack -- added to stack),
in pseudo-Overload (that is, () delimit a quoting list, etc.). The
leftmost value always refers to the TOS. x, x1, x2, x3, etc. refer to
'anything that might be at that point'; likewise for y, y1, y2, y3, etc..
{ and } are used to refer to 'either a quoting or a nonquoting list'. If
a command changes program flow in an unusual manner, the change to the
program and IP (written as [_ip]) will be shown below in the format
(before -- after); a semicolon is used to separate different lists in the
'before' and 'after' if more than one list is relevant.
Each command also has an example. (As these examples are unquoted, it's
occasionally nontrivial to figure out whether a punctuation mark is part
of the example or part of the sentence; therefore the examples should not
be taken to be normative.)

Pointers as commands

]x[  ( -- )
     ([_ip]]x[;[x]y -- ]x[;[x][_ip]y)
     A pointer causes an unconditional jump to the command to which it
     points.

Quoting lists as commands

(x)  ( -- (x))
     A quoting list pushes a copy of itself onto the stack.

     Example: [x](abc)(def)(]x[) leaves the stack as ((]x[)(def)(abc))
     without changing the program.

z(x) ( -- (x))
     (z[_ip](x) -- z[_ip])
     When modified by z, a quoting list pushes itself onto the stack,
     removing itself from any list it might have been in before. (This
     modifies the program). Any pointers that pointed to or within the
     original list now point to the corresponding place on or within the
     stack.

     Example: z[x](abc)z(def)z(]x[) leaves the stack as
     ((]x[)(def)[x](abc)) and the program as zzz.

Nonquoting lists as commands

,  ( -- (]x[))
   ([x][_ip], -- [x],[_ip])
   , pushes a pointer to the occurrence of , that was called onto the
   stack. As with all the pointer-pushing commands, it's in a quoted
   list.

   Example: ,? is equivalent to (,)A (they both leave an unquoted , on
   top of the stack.)

.  ([x1]x -- (]x1[) [x1]x)
   . pushes a pointer to the old TOS onto the stack.
   
   Example: .? is equivalent to : (they both push a copy of the TOS onto
   the stack), but .z? is a no-op (because it moves the TOS back onto the
   stack, in the same position).

z. (]x[ -- [(x becomes the stack)]) or ({]x[} -- [(x becomes the stack)])
   This causes whatever TOS points to to become the stack. The old TOS is
   detached from the old stack (in case anything's still pointing to the
   old stack). As the variable table's immediately after the stack, this
   also has the effect of changing the variable table.

   Example: 5U.z. leaves the stack as (<><[#2]><[#3]><[#4]><[#5]>);
   anything that was previously on the stack is now gone, as the list
   used to store the stack has been changed.

*  ({x1 x2 x3...} {y1 y2 y3...} -- {y1 y2 y3... x1 x2 x3...})
   This concatenates two lists; anything that pointed to an element of
   either of the lists continues to point to its analogue in the
   concatenated list, but anything that pointed to one of the lists
   themselves will now point to an empty detached list with the same
   quoting status. The resulting list is quoting if both original lists
   were quoting, or nonquoting if both original lists were nonquoting;
   it's unspecified whether it's quoting or not if the original lists
   differed in quoting status. The elements of the list that was on top
   of the stack come last in the concatenation.
   If either of the top two stack elements isn't a list, it's listified
   in the normal manner by enclosing it in a quoting list before the
   concatenation.

   Example: 23* is equivalent to (:*)(::**)* or to (:*::**), which
   happens to be a representation of the number 6. (* can in fact be used
   for multiplication, although it leaves a non-normalized answer). 23*N
   is exactly equivalent to 6.

^  ({x1 x2 x3...} -- )
   ([_ip]^y... -- ^[y1]y...;{[_ip]x1 x2 x3...]y1[})
   If y is a pointer itself, y1 instead points to y's target.
   ^ is like 'eval' in other languages. It detaches the TOS, then appends
   a pointer to the next command (or where the next command points if
   it's a pointer; this makes recursive programs possible without using
   infinite heap space) to the old TOS, and moves the IP to the first
   element of the old TOS.

   Example: (123)^ is exactly equivalent to 123, and .(123)^; is exactly
   equivalent to .123; or ([#123]). (This method of parsing ASCII strings
   to numbers is not recommended without first checking that the string
   contains nothing but digits, because it could lead to arbitrary code
   being executed.)

~  (x1 x2 -- x2 x1)
   Effect on pointers: ([y1]x1 [y2]x2 -- [y2]x2 [y1]x1)
   ~ swaps the top two elements of the stack.

   Example: (1)(2)~ is equivalent to (2)(1).

`  (x {x1 x2 x3...} -- x)
   ([_ip]^y... -- ^[y1]y...;{[_ip]x1 x2 x3...]y1[})
   ` is exactly equivalent to ~^ (it swaps the top two stack elements,
   and then interprets the new top element as code and runs it like a
   subroutine).

   Example: 'k1` returns a function that always returns the identity
   function (it means the same as the Unlambda `ki).

&  ({x1 x2 x3...} {y1 y2 y3...} -- {x1 x2 x3... y1 y2 y3...})
   & is exactly equivalent to ~* (it concatenates the top two stack
   elements in the reverse order to *).

   Example: (feel)(un)&(ing)* is equivalent to (unfeeling); this
   technique can be used to translate lambda-calculus expressions into
   Overload.

@  (x1 x2 x3 -- x1 x3 x2)
   Effect on pointers: ([y1]x1 [y2]x2 [y3]x3 -- [y1]x1 [y3]x3 [y2]x2)
   @ swaps the second and third stack elements.

   Example: (1)(2)(3)@~ is equivalent to (3)(2)(1).

?  (]y1[ -- x1) or ({]y1[} -- x1) where [y1]x1 appears elsewhere
   ? detaches TOS (which must be a pointer or a list containing nothing
   but a pointer), and pushes a copy of what the old TOS pointed to onto
   the stack. If TOS was a one-past-the-end pointer, it instead pushes an
   empty nonquoting list onto the stack (one-past-the-ends are converted
   into <> whenever an explicit value is needed).

   Example: z(ab[x]cde)(]x[)? is equivalent to z(abcde)(c)A.

z? (]y1[ -- x1) or ({]y1[} -- x1) where [y1]x1 appears elsewhere
   When modified by z, ? detaches TOS (which must be a pointer or a list
   containing nothing but a pointer), and moves what it pointed to onto
   the stack, removing what it pointed to from its original location. If
   TOS was a one-past-the-end pointer, it instead pushes an empty
   nonquoting list onto the stack (one-past-the-ends are converted into
   <> whenever an explicit value is needed). 

   Example: z(ab[x]cde)(]x[)z? is equivalent to z(abde)(c)A.

=  (]y1[ x -- ) or ({]y1[} x -- ) changing [y1]x1 to [y1]x;x
   = detaches TOS (which must be a pointer or a list containing nothing
   but a pointer), and moves the second stack element to take the place
   of what it was pointing to, detaching what it was pointing to to make
   room.

   Example: z(ab[x]cde)(f)(]x[)= is equivalent to z(ab(f)de).

/  (]y1[ x -- ) or ({]y1[} x -- ) changing [y1]x1 to x [y1]x1
   / detaches TOS (which must be a pointer or a list containing nothing
   but a pointer), and moves the second stack element between what TOS
   was pointing to and the element before it (or at the start of the list
   containing the element TOS was pointing to if it was pointing to the
   first element of a list).

   Example: z(ab[x]cde)(f)(]x[)/ is equivalent to z(ab(f)cde).

\  (]y1[ -- ) or ({]y1[} -- ) detaching [y1]x1
   \ detaches TOS (which must be a pointer or a list containing nothing
   but a pointer), and also detaches whatever it was pointing to (doing
   nothing but causing the pointer to end up pointing to a nonquoting
   list in an undelimited list if it was pointing one-past-the-end
   beforehand).

   Examples: z(ab[x]cde)(]x[)\ is equivalent to z(abde).
	     .\ is equivalent to !.

:  (x -- x x)
   : pushes a copy of TOS onto the stack. Any pointers that pointed to or
   into TOS end up pointing to the original (second on the stack), rather
   than the new copy.

   Examples: (a): is equivalent to (a)(a).
	     (:apSS):apSS is equivalent to (:apSS)(:apSS)apSS
					or (:apSS)("(:apSS"))SS
					or ("(:apSS"))S(:apSS)S
             so it prints (:apSS):apSS. (This is not the simplest
	     Overload quine, but it's one of the most obvious.)

!  (x -- )
   ! detaches TOS. (If nothing was pointing at or within TOS, this has
   the same effect as popping the stack.)

   Example: (a)(b)! is equivalent to (a).

z! (x -- )
   z! detaches TOS. Its contents are removed from its delimiters; the
   delimiters stay behind as an empty list (getting immediately
   garbage-collected unless something was pointing at them), and the old
   TOS's contents become an undelimited list. If TOS doesn't have
   delimiters, the effect is the same as if ! were used.

   Example: (abc).A~z! leaves a pointer to the undelimited list abc on
   the stack. (This effect is hard to achieve without using z!).

_  ({x1 x2 x3...} x -- )
   ([_ip]_[y1]y -- [y1]y;{[_ip]x1 x2 x3... z(x)A]y1[})
   _ quotes the second stack element, prepends z, appends A, appends it
   to TOS, and then does ^. The practical effect of this is that the
   second stack element will disappear temporarily whilst the TOS is
   executed, and will reappear afterwards; this is the 'dip' combinator
   from Joy.

   Example: (~)_ is equivalent to @.

}  (x -- x+1)
   } detaches TOS, and pushes a representation of a number 1 greater than
   it onto the stack. The representation used is unspecified (although it
   will always be normalised if TOS was normalised), and if TOS wasn't a
   representation of a number the behaviour is undefined.

   Example: 4} is equivalent to 5.

{  (x -- x?x-1:0)
   { detaches TOS, and pushes a representation of a number 1 less than it
   onto the stack, or a representation of 0 if there was a 0 on top of
   the stack. The representation used is unspecified (it can be
   non-normalised even if TOS was normalised), and if TOS wasn't a
   representation of a number the behaviour is undefined.

   Example: 4{N is equivalent to 3.

+  (x1 x2 -- x1+x2)
   + detaches the top two stack elements, and pushes a representation of
   their sum onto the sack. The representation used is unspecified (it
   will be normalised if TOS was previously normalised, even if the
   second stack element wasn't), and if either of the top two stack
   elements wasn't a representation of a number the behaviour is
   undefined. 

   Example: 35+ is equivalent to 8.

-  (y1 y2 -- y2-y1) with integers or pointers;
   ({y1} y2 -- y2-y1), (y1 {y2} -- y2-y1), or ({y1} {y2} -- y2-y1) with
   pointers.
   - works with both integers and pointers, and has two separate
   meanings.

   If the top two stack elements are both pointers or lists containing
   nothing but pointers, then both are detached, and a representation of
   the 'difference' between the pointers is pushed onto the stack. This
   'difference' is defined as the number of consecutive D commands that
   would transform the first pointer into the second (using the original
   definition of D, if it's been redefined; unless this command is
   redefined itself, it's immune to command redefinition). If no number
   of consecutive D commands would transform the first pointer into the
   second, or both pointers point to the same target (that is, zero D
   commands would transform the first into the second), a representation
   of 0 is pushed onto the stack.

   Otherwise, the top two stack elements are interpreted as numbers and
   detached (there is undefined behaviour if either of them wasn't a
   number). If the number that the TOS represented was less than the
   number that the second stack element represented, an unspecified
   representation of their difference (not necessarily normalised, even
   if both original numbers were normalised) is pushed onto the
   stack. Otherwise, an unspecified representation of 0 is pushed onto
   the stack.

   Examples: (a[x]bc[y]de)(]y[)(]x[)-N is equivalent to (abcde)2.
	     63-N is equivalent to 3.
	     36-N is equivalent to 0.

'  ( -- (x))
   ([_ip]'xy -- 'x[_ip]y)
   ' pushes a quoting list containing a copy of the element that would be
   the next command to be executed onto the stack, then transfers
   execution unconditionally to what would be the next-but-one
   command. In the case where ' is last in a list, it pushes (<>) onto
   the stack, then transfers execution to the end of the list; when this
   happens, it's unspecified whether or not a <> is inserted at the end
   of the list that the ' is in.

   Example: '*8*S is equivalent to (*)8*S or (********)S, and outputs
   eight stars.

z' ( -- (x))
   (z[_ip]'xy -- z'[_ip]y)
   z' is almost the same as ', but moves the next command to be executed
   into a quoting list and places it on the stack, instead of copying;
   this leads to the program being modified. There definitely won't be a
   stray <> inserted when z' is used at the end of a list.

   Example: (z'a)l will push (a) onto the stack, then push a quoting list
   containing a pointer to the z onto the stack (because on the second
   iteration the a will have gone and the next element will be the
   l-added pointer pointing back to the z), and then exit the loop
   (because the next command reached will be the pointer to return from
   the loop that will have been added by the ^ implied by the l).

0  ( -- (!()))
   0 pushes (!()) onto the stack; therefore, if the resulting list is
   interpreted as a function, it will act differently if ! has been
   redefined.

   Example: 0 has the same effect as (!()).

1  ( -- ())
   1 pushes an empty quoting list onto the stack.
   
   Example: 1^ has no effect.

2  ( -- (:*))
   2 pushes (:*) (the normalised representation of 2) onto the stack. The
   resulting list will act differently if it's interpreted as a function
   and either : or * has been redefined.

   Example: 22+ is equivalent to 22*N.

3, 4, 5, 6, 7, 8, and 9 are defined in a similar way to 2; each pushes a
   normalised representation of the appropriate digit onto the stack.

;  (x1 x10 x100... ]y1[ -- x1+x10*10+x100*100+...) or
   (x1 x10 x100... {]y1[} -- x1+x10*10+x100*100+...)
   ; takes the TOS (interpreting it as a number), adds it to ten times
   the second stack element, adds the total to a hundred times the third
   stack element, and so on in increasing powers of 10. This continues
   until a stack element that's either a pointer or a list containing
   nothing but a pointer is found. All the numbers and the pointers are
   detached, and a normalised representation of the resulting sum is
   pushed onto the stack. If TOS happens to be a pointer or list
   containing only a pointer, it's detached and a normalised
   representation of 0 is pushed onto the stack. All representations so
   pushed are quoting lists. If any of the elements checked is neither a
   pointer, a list containing only a pointer, or a quoting list, the
   behaviour is undefined. (This command is intended as a wimpmode for
   decimal numbers, but knowing Overload it's probably got other uses as
   well.) 

   Example: ,65536; is equivalent to 48^N. (Yes, ^ can be used to do
   exponentiation; 8 pushes (:::::::*******) onto the stack, so when it's
   executed, the original string (:::***) (for 4) and seven copies are
   pushed onto the stack, and then concatenated, leading to
   4*4*4*4*4*4*4*4 or 65536.)

A  (]y1[ -- ]y2[) or ({]y1[} -- {]y2[}) given [y1]{[y2]x1 x2...},
   or changing [y1]]x1[ to ([y2]]x1[), or changing {... x1 [y1]} to
   {... x1 <[y2]>}, or as zA
   A causes a pointer at TOS (or a list containing nothing but a pointer)
   to point to the first element of the list it was pointing to. If it
   was pointing to a pointer, that pointer is placed into a quoting list
   to give the command somewhere to point TOS to; if it was pointing
   one-past-the-end, an empty nonquoting list is created there to give
   the command somewhere to point TOS to.

   If there isn't a pointer or list containing nothing but a pointer at
   TOS, A instead has the same effect as zA.

   Example: 4.A? is equivalent to 4(:)zA.

zA ({x1 x2...} -- x1)
   zA replaces a list at TOS with its first element. It has no effect on
   a pointer, an it causes an empty list to become nonquoting (because
   the one-past-the-end position, its implied 'first element', becomes
   <>). For purposes of determining what happens to pointers, the first
   element of TOS is detached from it, then TOS is detached, and then the
   old first element of TOS is pushed onto the stack.

   Example: 'aA pushes the nonquoting list normally represented as a
   onto the stack. (zA, or A in situations where it has the same effect
   as zA (like this one), are simple ways to place nonquoting lists onto
   the stack.)

a  (]y1[ -- ]y2[) or ({]y1[} -- {]y2[}) given [y2]{... x1 [y1]x2 x3...}, or
   changing ...x1 [y1]x2 x3... to [y2](...x1 x2 x3...), or as za
   a causes a pointer at TOS to point to the list containing the element
   it's pointing to. If it's pointing to an element of a nondelimited
   list (which cannot be pointed to), the nondelimited list is made into
   a quoting list and TOS is changed to point to that.

   If there isn't a pointer or list containing nothing but a pointer at
   TOS, a instead has the same effect as za.

   Examples: .a?pS prints out the entire stack, including a pointer to the
	     stack at TOS, on standard output. 

	     ,aS prints ,aS on standard output; this is a
	     quine-by-cheating, as the program reads its own source
	     code. (This situation involves a nondelimited list.)

za (x -- (x))
   za places a quoting list around TOS (any pointers pointing to it end
   up pointing inside the new quoting list).

   Example: za(!z)& is one way to implement k.

C  ( -- (]y1[ ]y2[...)) where [y1], [y2], etc. point to the first
   elements of nondelimited lists
   C pushes a list containing a pointer to the first element of each
   nondelimited list currently in the program's memory onto the
   stack. (Lists that have been garbage-collected don't count).

   Example: I can't think of one right now.

c  (too complicated to fit into one of these diagrams; see text)
   c is the call/cc operator, which Overload shares with languages like
   Scheme and Unlambda. It generates a continuation consisting of what
   the state of the program would be if c returned without doing
   anything, pushes it onto the stack, and then does the same as `
   (i.e. swaps the top two stack elements and evaluates the new TOS). If
   the continuation is called, it takes the program back in time to the
   calculated state that would have occurred if c has done nothing,
   except that the top element of the stack, and anything it points to,
   are preserved and remain where they were before (i.e. the TOS remains
   on top of the stack). It's unspecified what happens to anything
   pointing to the TOS or within it when the continuation is called, if
   such pointers don't get garbage-collected; they'll either continue
   pointing to the TOS, or they'll point to a copy of it in an
   unspecified context. (Therefore, this situation should be avoided in
   portable programs by avoiding situations in which the TOS contains a
   pointer to something which points back to or within the TOS). However,
   pointers from within the TOS to within the TOS will be handled
   correctly.
   
   The state recorded by c contains the IP, program, stack, variables,
   and any nondelimited lists, but not the hashtable, command
   definitions, or IP movement definitions.

   The c command is not guaranteed to work if any of the
   originally-defined commands have been redefined.

   It is completely legal for a continuation to 'escape' the function
   called using the c command (see the second example
   below). Continuations consist of Overload code themselves, and can
   even be deparsed and printed by pS if you want to inspect them for
   debugging (there is no guarantee that they'll be readable, however).

   Examples: (a)(b)(c)(~!~!~!(d)`)c is equivalent to (a)(b)(c)(d).
	     1c:^ is an infinite loop. (Due to the way the stack behaves,
	     a program consisting of only c:^ is also an infinite loop,
	     due to the implied <> on the stack to start with; but there
	     are shorter infinite loops in Overload (l is an infinite
	     loop for example).)

D  (]y1[ -- ]y2[) or ({]y1[} -- {]y2[}) with {...x1 [y1]x2 [y2]x3...} or
   changing {...x1 [y1]x2} to {...x1 [y1]x2 [y2]<>}, or as zD
   D changes a TOS to point to the element after the one it's currently
   pointing to in the same list (changing a one-past-the-end position to
   <> if that's needed to make the command make sense; if it was pointing
   to the last element, it points one-past-the-end instead.)

   If TOS isn't a pointer or list containing nothing but a pointer, D has
   the same effect as zD.

   Example: (ab[x]cde)(]x[)D? is equivalent to (abcde)(d)A.

zD ({x1 x2 x3...} -- {x2 x3...})
   zD detaches the first element of the list at TOS; if TOS is actually a
   pointer, it's instead detached and replaced with an empty quoting
   list.

   Example: (abcde)D is equivalent to (bcde).

d  (]y1[ -- ]y2[) or ({]y1[} -- {]y2[}) with {...x1 [y2]x2 [y1]x3...} or
   {[y1]x1 x2... x9 [y2]}
   d causes a pointer at TOS to point to the previous element of the same
   list it's pointing to. If it was pointing to the first element of a
   list, it's retargeted to point one-past-the-end in that list.

   Examples: (ab[x]cde)(]x[)d? is equivalent to (abcde)(b)A.
	     (abcde).A:d-N is equivalent to (abcde)5.

e  (x {y1 y2 y3...} -- {x(y1) x(y2) x(y3)...})
   (N.B. in this example, x(y1) denotes 'application of x to y1'; this is
   written at a higher level than most other examples. See the text for
   more details.)

   The TOS is treated as a function. It's detached and remembered; in
   turn, each of the elements of the second stack element are pushed onto
   the stack, the commands in the remembered TOS are run, and the
   resulting TOS is detached and remembered. Once all the elements in the
   second stack element have been used, a list (of unspecified quoting
   status) containing all the remembered calculated TOSs (not the
   original TOS, which is now allowed to be garbage-collected if
   nothing's pointing to it) is pushed onto the stack, leaving the
   elements in the same order. Elements in the original second stack
   element are processed from first to last. If the second stack element
   is a pointer rather than a list, it's made into a quoting list
   containing just that pointer so the e command can be run.

   Any temporaries used by the e command are part of the state that can
   be recorded in a continuation by c. The e command is not guaranteed to
   work if any originally defined command has been redefined.

   Examples: (abc)(a)e is equivalent to ((a)(b)(c)), apart from the
	     unspecifiedness of the quoting status in the first example;
	     (abc)(:)e! is equivalent to (a)A(b)A(c)A.

f  ({x1 x2 x3... } y -- )
   ([_ip]f -- f[_y1];{[_ip]x1 x2 x3... x1 x2 x3... ...[(y times)] ]_y1[})
   f is equivalent to the command sequence `^ (and won't necessarily work
   if either of those commands have been redefined). For its most common
   use, it treats the second stack element as a number, repeats the first
   stack element that many times, and interprets the repeated stack
   element as code and runs it as if it were a subroutine. The code and
   repeat-count are popped.

   Example: 9((*)S)f outputs *********.

g  (x -- [(1 if x was 0, or 0 otherwise)])
   g replaces the top element of the stack with a representation of 1 if
   it was a representation of 0, or a representation of 0 if it was a
   representation of some other number. If the top element of the stack
   isn't a number, it behaves as the command sequence ()` would do (if `
   has been redefined, or ~ or ^ have been redefined, instead the
   behaviour is undefined). The representation used and the quotingness
   of the output list are undefined.

   Example: V:1O-g((Too big!<[$b]>)S<>)f reads a number, and prints an
   error message and returns if the entered number was greater than 10.

H