Forth Quines

or

On some of the differences between Forth and other languages

A quine is a program that produces its complete source code as its only output. Developing the shortest non-empty quine in any programming language is often used as a challenge, and the length of the shortest non-empty quine in a language is sometimes seen as reflecting the expressive power of the language.

Here, I list some Forth quines, starting with the shortest ones, then eliminating various features of Forth, and see how the quines become longer. The elimination features are the section headings.

Full Forth

First, the empty program is a quine in Forth and some (but not all) other languages; however, apart from pointing out languages that require some overhead for doing even nothing, this is not a very interesting quine. So, the next Forth quine is:

source type
This is an ANS Forth program (author unknown). It just takes the current input line and prints it.

Eliminate interpretation

Some other languages do not allow directly interpreting code, but require that code is wrapped in a function. The corresponding restriction in Forth would be to define a Forth word that outputs its own definition. Here it is:

: quine [ source ] sliteral type ;
Again, this is an ANS Forth program (by Neal Bridges <12hr3sj64c0vj7f@corp.supernews.com>). In addition to accessing the current input line, this also uses the brackets to execute SOURCE at compile time, and SLITERAL to shift the string from compile-time to run-time.

Eliminate SOURCE

Many other languages do not provide access to the current input line, so let's eliminate SOURCE and TIB from our toolbox. The next obvious thing to use is Forth's decompiler. Unfortunately, its output is not standardized and differs slightly between Forth systems, but the following is ANS Forth code:
: QUINE         S" SEE QUINE" EVALUATE ;
And it is an exact quine on Win32Forth V6.11.10 (by George Hubert <1159545962.598745.86730@c28g2000cwb.googlegroups.com>. Here are some variations of this for other Forth systems: PFE 0.33.34:
: quine
     S" see quine" EVALUATE ; 
Gforth 0.6.2:
: quine  
  s\" see quine" evaluate ;

Eliminate SEE

Many other languages don't provide decompilers, either, and the system-specific nature of the SEE-based quines is not so nice, so let's eliminate SEE as well:
s" 2dup cr 115 emit 34 emit space type 34 emit space type cr" 2dup cr 115 emit 34 emit space type 34 emit space type cr
This is an ANS Forth program (by Joe Knapka <654Sg.92$DU3.4@tornado.texas.rr.com>). You can eliminate the CRs for shortening the program. However, this version does not generate a word, but is interpreted directly.

As word

Here is a variation on the quine above that defines a word (by Anton Ertl):
s" 2constant s : quine 115 emit 34 emit space [ s ] sliteral 2dup type 34 emit type ;"2constant s : quine 115 emit 34 emit space [ s ] sliteral 2dup type 34 emit type ;
This is ANS Forth code. Note that this uses [ s ] sliteral instead of just s in order to allow QUINE to work even if the S" buffer has been overwritten by another S".

Only colon definitions

The previous solution still does something outside colon definitions. Let's eliminate that (by Anton Ertl):
: s s" ; : quine [ char ' parse : s s' ] sliteral type 34 emit space s type 34 emit s type ;"; : quine [ char ' parse : s s' ] sliteral type 34 emit space s type 34 emit s type ;
This is ANS Forth code. Here we can reference s directly, because the string is compiled into a colon definition.

Eliminate interpretation

The previous solution still uses [, ], and SLITERAL. Since Algol-family languages cannot do this, let's eliminate that (by Anton Ertl):
: s s" ; : quine 58 emit space 115 emit space 115 emit 34 emit space s type 34 emit s type ;"; : quine 58 emit space 115 emit space 115 emit 34 emit space s type 34 emit s type ;
This is ANS Forth code.

Only one colon definition

This solution in ANS Forth has only one colon definition (By Joe Knapka <dNvTg.919$5o5.306@tornado.texas.rr.com>):
: quine s" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit 32 emit type 32 101 110 105 117 113 32 59 32 9 0 do emit loop" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit 32 emit type 32 101 110 105 117 113 32 59 32 9 0 do emit loop ; quine 
Simplified by Anton Ertl:
: quine s" 2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit type ;"2dup 32 34 115 32 101 110 105 117 113 32 58 11 0 do emit loop type 34 emit type ;
Also ANS Forth code. Of course, with a shorter word name, this can be quite a bit shorter:
: q s" 2dup 32 34 115 32 113 32 58 7 0 do emit loop type 34 emit type ;"2dup 32 34 115 32 113 32 58 7 0 do emit loop type 34 emit type ;

Eliminating S"

We can make it even longer by eliminating S" and constructing the string out of individual characters (by Neal Bridges <12hsoqu2lbfeg96@corp.supernews.com>):
36 base ! create d 1M c, W c, 35 c, W c, 1A c, Y c, W c, 1F c, 1I c, W c, 2Q c, 2P c, 37 c, 2T c, W c, X c, W c, 2R c, 36 c, 2T c, 2P c, 38 c, 2T c, W c, 2S c, W c, Y c, W c, 2S c, W c, 1E c, 1U c, W c, 1C c, W c, 2S c, 33 c, W c, 2S c, 39 c, 34 c, W c, 2X c, W c, 2R c, 2W c, 2P c, 36 c, 37 c, W c, 17 c, W c, 2R c, 1S c, W c, 1A c, W c, 1A c, Y c, W c, 2R c, 18 c, W c, Y c, W c, 30 c, 33 c, 33 c, 34 c, W c, 2S c, W c, 1E c, 1U c, W c, 38 c, 3D c, 34 c, 2T c, W c, 1N c, W c, 35 c, : q ." 36 base ! create d " d 2B 0 do dup i chars + c@ . ." c, " loop d 2B type ; q

Eliminating BASE

The previous solution uses BASE 36 to get a shorter quine. However, most languages do not allow changing BASE, so let's do away with that. Neal Bridges has also <12hsguqndcapg7c@corp.supernews.com> implemented a rather longish solution that satisfies that constraint.

Other ways of dealing with quotes

The more restricted solutions above deal with the quoting problem by somehow printing a prelude, then a quote, then the string, then another quote, and then the string again. The following solution puts everything in the string, but does a kind of macro-expanding printing, without needing to put the quotes in the string (by Bernd Paysan <rs53v3-vi5.ln1@vimes.paysan.nom>):
: quiche s" : quiche % 2dup bounds ?DO I c@ 37 = IF 's emit 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ; quiche" 2dup bounds ?DO I c@ 37 = IF 's emit 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ; quiche
This solution uses some common extensions. A solution in standard Forth:
: quine s" : quine s% 2dup over + swap DO I c@ 37 = IF 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ;" 2dup over + swap DO I c@ 37 = IF 34 emit space type 34 emit ELSE I c@ emit THEN LOOP ;
Instead of replacing a macro character, one can also just know the position where to insert the string and the quotes (by Bernd Paysan <0o63v3-ln5.ln1@vimes.paysan.nom>):
: quine s" : quine  over 8 type 115 emit 34 emit space 2dup type 34 emit 8 /string type ;" over 8 type 115 emit 34 emit space 2dup type 34 emit 8 /string type ;
A slightly shorter variant (by Anton Ertl):
: quine s" : quine s over 9 type 34 emit space 2dup type 34 emit 9 /string type ;" over 9 type 34 emit space 2dup type 34 emit 9 /string type ;
Instead of having one string and picking it apart, one can also have two strings:
: x 83 emit 34 emit space type 34 emit ; : quine S" : x 83 emit 34 emit space type 34 emit ; : quine "S" 2swap 2dup type x 2dup x type ;"2swap 2dup type x 2dup x type ;
It is a little shorter if we put the strings in reverse order:
: x 83 emit 34 emit space type 34 emit ; : quine S" 2dup type 2over x x type ;"S" : x 83 emit 34 emit space type 34 emit ; : quine "2dup type 2over x x type ;
A version using escaped strings (by Anton Ertl) is:
: s s\" : quine .\\\" : s s\\\\\\\" \" 0 xpos ! s c-\\type .\\\" \\\" ; \" s type ;" ; : quine .\" : s s\\\" " 0 xpos ! s c-\type .\" \" ; " s type ;
This works in Gforth (0.6.2).
Anton Ertl