SkillAgentSearch skills...

Gs2

code-golf-oriented esoteric programming language

Install / Use

/learn @nooodl/Gs2
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

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:

Token | Meaning ----- | ------- $01 $xx | Push unsigned byte $xx to stack. $02 $yy $xx | Push signed short $xxyy to stack. $03 $zz $yy $xx $ww | Push signed short $wwxxyyzz to stack. $04 ss* $zz | Push string(s) to stack. ss is separated by $07; the action performed is decided by the string end byte $zz, see below. $07 $cc | Push single-character string "\xcc" to stack. $08 | Opens a block. $09 | Closes 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 byte | Meaning -------- | ------- $05 | push strings to stack, sequentially $06 | push strings to stack in array $9b | sprintf (pops format from ss, pops fitting number of items from stack, pushes formatted string) $9c | regex match (pops regex from ss, pops string from stack, pushes 1 on match, else 0) $9d | regex replace (pops replacement string from ss, pops regex from ss, pops string from stack and pushes re.sub result) $9e | regex find (like $9c, but calls re.findall) $9f | regex 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:

  • $9c: match whole string if c > 0
  • $9d: perform at most c substitutions (unlimited if c = 0)
  • $9e: find first matching substring only if c > 0 (else array of matching substrings)
  • $9f: perform at most c splits (unlimited if c = 0) Furthermore, if the first character of a program is $04, it may be omitted; an unmatched string closing token will automatically be paired up. (gs2c will automatically perform this optimization.)

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

Mode | Meaning ---- | ------- $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:

Byte | Constant ---- | -------- $0a (new-line) | [$0a] $0b (empty-list) | [] $0c (empty-block) | {} $0d (space) | [$20] $10 - $1a | 0 - 10 $1b | 100 $1c | 1000 $1d | 16 $1e | 64 $1f | 256

Functions

Opcode | Meaning ------ | ------- $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.

View on GitHub
GitHub Stars45
CategoryDevelopment
Updated1y ago
Forks5

Languages

Python

Security Score

60/100

Audited on Dec 5, 2024

No findings