Home

Awesome

GS2 documentation

What is GS2?

GS2 is a stack-based, concatenative programming language with functional influences, inspired by GolfScript and J. Its primary purpose is doing well at code golf contests; it achieves this by supplying many built-in commands and syntactical shortcuts that are each only one byte long.

Programming in GS2 is conceptually similar to programming in GolfScript or similar languages: the stack initially contains a string representing standard input, and its contents are printed to standard output when the program is finished.

The original author (@nooodl/@maurisvh) is no longer maintaining this language.

Values

GS2 values are integers, blocks, or lists. Blocks contain unevaluated code, representing "functions", like in GolfScript. There is no dedicated string type: strings are just lists of integers.

Tokens

Throughout this document mnemonics are listed next to some token names; these are compatible with the included gs2c utility.

Special tokens are:

TokenMeaning
$01 $xxPush unsigned byte $xx to stack.
$02 $yy $xxPush signed short $xxyy to stack.
$03 $zz $yy $xx $wwPush signed short $wwxxyyzz to stack.
$04 ss* $zzPush string(s) to stack. ss is separated by $07; the action performed is decided by the string end byte $zz, see below.
$07 $ccPush single-character string "\xcc" to stack.
$08Opens a block.
$09Closes a block.
%111xxyyy (hex values $e0 through $fb)Wraps last y + 1 values into a block. x is the final token (what do we do with this block?): 0=nop, 1=map ($34), 2=filter ($35), 3=apply on both of top 2 elements ($38)
$xx $fc (dm1, dump-map1)Map single token inside lists. Short for $08 $90 $xx $09 $34.
$xx $fd (df1, dump-filter1)Filter single token inside lists. Short for $08 $90 $xx $09 $35.
$fe (m:)Open rest-of-program map block.
$ff (f:)Open rest-of-program filter block.

The end bytes for $04 mean the following:

End byteMeaning
$05push strings to stack, sequentially
$06push strings to stack in array
$9bsprintf (pops format from ss, pops fitting number of items from stack, pushes formatted string)
$9cregex match (pops regex from ss, pops string from stack, pushes 1 on match, else 0)
$9dregex replace (pops replacement string from ss, pops regex from ss, pops string from stack and pushes re.sub result)
$9eregex find (like $9c, but calls re.findall)
$9fregex split (like $9c, but calls re.split)

The regexes used by these operations may be prefixed by special characters to set a special variable c: by default it is 0, prefixing the regex by $5D sets it to 1, prefixing it by $7D $xx sets it to $xx. c affects the operations as follows:

The following single-byte tokens have special meaning at the start of a program:

ModeMeaning
$30 (line-mode)Line mode: [program] -> [lines, map program, unlines]
$31 (word-mode)Word mode: [program] -> [words, map program, unwords]
$32 (line-mode-skip-first)Like $30, but ignore first line.

All other tokens are simple operations that pop values from the stack and push results back.

Constants

The following single-byte tokens push constants to the stack:

ByteConstant
$0a (new-line)[$0a]
$0b (empty-list)[]
$0c (empty-block){}
$0d (space)[$20]
$10 - $1a0 - 10
$1b100
$1c1000
$1d16
$1e64
$1f256

Functions

OpcodeMeaning
$0e (make-array, extract-array)Pop number n, then pop n elements and push them back into an array; pop array and push each element.
$20 (negate, reverse, eval)Negate numbers; reverse lists; evaluate blocks.
$21 (bnot, head)Bitwise-negates numbers; extract first element from lists.
$22 (not, tail)Boolean negation for numbers; drop first element from lists.
$23 (abs, init)Absolute value for numbers; drop last element from lists.
$24 (digits, last)Push array of base 10 digits for numbers; extract last element from lists.
$25 (random)Push random.randint(0, x-1) for numbers x; choose random element for lists.
$26 (dec, left-uncons)Subtract 1 from numbers; pushes tail and then head for lists.
$27 (inc, right-uncons)Add 1 to numbers; pushes init and then last for lists.
$28 (sign, min)Push sign for numbers; minimum for lists.
$29 (thousand, max)Multiply numbers by 1000; maximum for lists.
$2a (double, lines)Multiply numbers by 2; split list into lines.
$2b (half, unlines)Divide numbers by 2; join with newlines for lists.
$2c (square, words)Square numbers; split list into words.
$2d (sqrt, unwords)Integer square root for numbers, join with space for lists.
$2e (range, length)Push [0..n-1] for numbers n, length for lists.
$2f (range1, sort)Push [1..n] for numbers n; sorts lists; sortBy for blocks.
$30 (add, cat, +)Add numbers, catenate lists/blocks.
$31 (sub, diff, -)Subtract numbers, set difference for lists.
$32 (mul, join, times, fold, \*)Multiply numbers; repeats a list n times; join list of lists with another; fold block over list.
$33 (div, chunks, split, each, /)Divide numbers; splits a list in chunks of size n; split two lists; call block with each element of list.
$34 (mod, step, clean-split, map, %)Modulo numbers; each nth element for list+number; split two lists removing empty lists; maps block over list.
$35 (and, get, when, filter, &)Bitwise and numbers; index list; eval block only when number on top of stack is non-zero, filter list by block.
Et cetera. You can see the full list of mnemonics in gs2.py and play around with them to get a feel for what they do.

Example usage and gs2c

The included gs2c.py script is an "assembler" that compiles a more readable representation of gs2 opcodes and constants. It reads mnemonics for gs2 functions from the source code of gs2.py itself! Let's write a simple program, compile it using gs2c.py, and run it.

A very simple golf challenge is the following: given a positive integer n on standard input, print a triangle of asterisks of size n:

*
**
***
****
*****

We read the number, then map a block over [1..n], turning each number into asterisks followed by a newline:

read-num range1 m: "*" times new-line

Then gs2c can compile this, and gs2 can run the resulting file:

$ python gs2c.py < stars > compiled && echo 7 | python gs2.py compiled
*
**
***
****
*****
******
*******

Our solution is 7 bytes long: 56 2f fe 07 2a 32 0a. This is pretty good compared to GolfScript's 11.