gs2
gs2 is a a concatenative language designed by User:nooodl, inspired by GolfScript and J, designed to be as efficient as possible at code golf. gs2 code uses a binary format in which most bytes represent a single high-level stack operation. The code is run over stdin token by token, just like GolfScript.
The documentation that used to be here is mostly out of date now, and until the author gets around to writing up something more thorough, careful reading of the source code is your best bet, as with FlogScript. An old revision can be found here: [1]
Syntax
Code is tokenized as follows:
# string hack: programs can omit starting \x04 and save a byte if re.match('^[^\x04]*[\x05\x06]', prog): prog = '\x04' + prog token_re = [ '\x01.', # unsigned byte '\x02..', # signed short '\x03....', # signed long '\x04[^\x05\x06]*[\x05\x06]', # string (array) '\x07.', # 1 char string '.', # regular token ] tokens = re.findall('|'.join(token_re), prog, re.DOTALL)
Tokens starting with \x01 through \x03 push little-endian binary integers to the stack. Sequences of strings are delimited by \x04 and \x05, and split by \x07. The final \x05 byte can be replaced by \x06 in which case the strings are wrapped in an array. Some examples:
04 'a' 'b' 'c' 05 => "abc" 04 'a' 'b' 'c' 07 'd' 'e' 'f' 05 => "abc" "def" 04 'a' 'b' 'c' 06 => ["abc"] 04 'a' 'b' 'c' 07 'd' 'e' 'f' 06 => ["abc" "def"]
The following tokens are all "special" syntactically, i.e. not just a stack operation:
- \x08 opens a block, \x09 closes it. (These function like GolfScript's curly braces.) The mnemonics are { and }.
- \x4d __ pushes a 1-byte block. Mnemonic: ' (as in a Lisp quote.)
- \x4e __ maps a 1-byte block over the top of the stack. Mnemonic: m.
- \x4f __ filters a 1-byte block over the top of the stack. Mnemonic: f.
- \x5c __ maps a 2-byte block over the top of the stack. Mnemonic: mm.
- \x5d __ filters a 2-byte block over the top of the stack. Mnemonic: ff.
- \x5e opens a map block that lasts until the end of the program (or the next }). Mnemonic: m:.
- \x5f opens a filter block that lasts until the end of the program (or the next }). Mnemonic: f:.
Commands
In the "from" and "to" columns, following variables are used:
- α, β, γ represent any stack value, κ represents a constant
- f, g, h represent blocks
- a through z otherwise represent integers
- [α], [β] represent lists.
Dec | Hex | Mnemonic | From | To | Description |
---|---|---|---|---|---|
10 | \x0a | new-line | κ | Push a string containing a newline ([10]) to the stack. | |
11 | \x0b | empty-list | κ | Push an empty list ([]) to the stack. | |
12 | \x0c | empty-block | κ | Push an empty block ({}) to the stack. | |
13 | \x0d | space | κ | Push a string containing a space ([32]) to the stack. | |
14 | \x0e | make-array | α1 α2 ... αn n | [α] | Wrap top n elements in an array. |
15 | \x0f | exit | Stop program execution. | ||
32 | \x20 | negate | x | -x | Negate a number. |
32 | \x20 | reverse | [α] | [α] | Reverse a list. |
33 | \x21 | bnot | x | ~x | One's complement. |
33 | \x21 | head | [α] | α | Extract first element from a list. |
34 | \x22 | not | α | x | Return 1 if α is zero or empty. 0 otherwise. |
34 | \x22 | tail | [α] | [α] | Drop the first element from a list. |
35 | \x23 | abs | x | |x| | Absolute value. |
35 | \x23 | init | [α] | [α] | Drop the last element from a list. |
36 | \x24 | digits | x | [x] | Return a list of digits in x, e.g. 123 → [1 2 3] |
36 | \x24 | last | [α] | α | Extract the last element of a list. |
37 | \x25 | random | [α] or x | α or x' | Pick a random element from a list or [0 1 ... x-1]. |
38 | \x26 | dec | x | x-1 | Subtract one. |
38 | \x26 | left-uncons | [α] | [α] α | Cut the first element off a list and place it on top of the stack. |
39 | \x27 | inc | x | x+1 | Add one. |
39 | \x27 | right-uncons | [α] | [α] α | Cut the last element off a list and place it on top of the stack. |
40 | \x28 | sign | x | sgn(x) | Signum. |
40 | \x28 | min | [α] | α | Minimum value of list. |
41 | \x29 | thousand | x | 1000x | Multiply by 1000. |
41 | \x29 | max | [α] | α | Maximum value of list. |
42 | \x2a | double | x | 2x | Multiply by 2. |
42 | \x2a | lines | [c] | [[c]] | Split over newlines. |
43 | \x2b | half | x | x/2 | Divide by 2. |
43 | \x2b | unlines | [[c]] | [c] | Join with newlines. |
44 | \x2c | square | x | x2 | Square. |
44 | \x2c | words | [c] | [[c]] | Split over spaces. |
45 | \x2d | sqrt | x | sqrt(x) | Calculate square root (rounded down.) |
45 | \x2d | unwords | [[c]] | [c] | Join by spaces. |
46 | \x2e | range | x | [x] | Push list of [0 1 ... x-1]. |
46 | \x2e | length | [α] | x | Push length of list |
47 | \x2f | range1 | x | [x] | Push list of [1 2 ... x]. |
47 | \x2f | sort | [α] | [α] | Sort list. |
48 | \x30 | add, + | x y | x+y | Add the top two numbers on the stack. |
48 | \x30 | cat | [α] [β] | [α β] | Concatenate top two lists on stack. |
49 | \x31 | sub, - | x y | x-y | Subtract the top two numbers on the stack. |
49 | \x31 | diff | [α] [β] | [γ] | Collect elements in [α] that are not in [β]. |
50 | \x32 | mul, * | x y | x*y | Multiply the top two numbers on the stack. |
50 | \x32 | join | [[α]] [β] | [γ] | Joins the lists in [[α]], splicing [β] between them. |
50 | \x32 | times | f n | Pops a number, then runs the block on top of the stack that many times. | |
50 | \x32 | fold | [α] f | β | Push the first element of [α], then alternate between pushing the next element of the list and running f. |
51 | \x33 | div, / | x y | x/y | Divide the top two numbers on the stack. |
51 | \x33 | group | [α] n | [[α]] | Group [α] into chunks of size n. |
51 | \x33 | split | [α] [β] | [[α]] | Split [α] over occurrences of sublist [β]. |
51 | \x33 | each | [α] f | Alternate between pushing elements of the list (from left to right) and running f. | |
52 | \x34 | mod, % | x y | x mod y | Modulo. |
52 | \x34 | step | [α] n | [α] | Take every nth element of [α] (like Python's a[::n].) |
52 | \x34 | clean-split | [α] [β] | [[α]] | Like split but remove empty results. |
52 | \x34 | map | [α] f | [β] | Apply f to each element in the list. |
53 | \x35 | and, & | x y | x AND y | Bitwise AND. |
53 | \x35 | get | [α] i | α | Get the i'th element of a list. |
53 | \x35 | when | f p | Run f only if p is true. | |
53 | \x35 | filter | [α] f | [α] | Collect elements in [α] for which evaluating f returns a truth value. |
54 | \x36 | or, | | x y | x OR y | Bitwise OR. |
54 | \x36 | unless | f p | Run f only if p is false. | description |
55 | \x37 | xor, ^ | x y | x XOR y | Binary XOR. |
55 | \x37 | concatmap | [α] f | [β] | Equivalent to map empty-list join. |
56 | \x38 | smallest | x y | min(x,y) | Smallest of x and y. |
57 | \x39 | biggest | x y | max(x,y) | Biggest of x and y. |
58 | \x3a | clamp | l h x | clamp(x,l,h) | Clamp x between l and h. |
60 | \x3c | gcd | x y | gcd(x,y) | Greatest common divisor. |
60 | \x3c | take | [α] i | [α] | First i elements. |
61 | \x3d | lcm | x y | lcm(x,y) | Least common multiple. |
61 | \x3d | drop | [α] i | [α] | All but first i elements. |
62 | \x3e | pow | x y | xy | Exponentiation. |
62 | \x3e | index | [α] β | i | Return first index of β in the list (-1 if not found.) |
63 | \x3f | log | x y | floor(log(x,y)) | Floor of logarithm to base y. |
63 | \x3f | member | [α] β | p | Return 1 if β is in the list, else 0. |
64 | \x40 | dup | α | α | Duplicate stack top. |
65 | \x41 | dup2 | α | α α α | Duplicate stack top twice. |
66 | \x42 | swap | α β | β α | Swap top two stack elements. |
67 | \x43 | rot | α β γ | β γ α | Rotate top three stack elements leftwards. |
68 | \x44 | rrot | α β γ | γ α β | Rotate top three stack elements rightwards. |
69 | \x45 | over | α β | α β α | Copy penultimate stack element. |
70 | \x46 | nip | α β | β | Pop penultimate stack element. |
71 | \x47 | tuck | α β | β α β | Copy stack top before penultimate. |
72 | \x48 | 2dup | α β | α β α β | Duplicate top two stack elements. |
73 | \x49 | pick | αn ... α1 n | αn ... α1 αn | Copy the n'th stack element counting from the top. |
74 | \x4a | roll | αn ... α1 n | αn-1 ... α1 αn | Move the n'th stack element counting from the top. |
75 | \x4b | get-stack | [σ] | Push the current stack as a list. | |
76 | \x4c | leave-top | α β ... ω | ω | Remove all but the top element from the stack. |
80 | \x50 | printf | [c] x or x [c] | [c] | Format x according to a printf specifier. |
81 | \x51 | lprintf | [c] [x] | [c] | Format [x] according to a printf specifier. |
82 | \x52 | show | α | [c] | Convert to string. |
83 | \x53 | map-show | [α] | [[c]] | Equivalent to m show. |
84 | \x54 | show-lines | [α] | [c] | Equivalent to m show unlines. |
85 | \x55 | show-words | [α] | [c] | Equivalent to m show unwords. |
86 | \x56 | read-num | [c] | x | Find first number (/-?\d+/) in string. |
87 | \x57 | read-nums | [c] | [x] | Find all numbers in string. |
88 | \x58 | show-line | α | [c] | Equivalent to show new-line cat |
96 | \x60 | logical-and | α β | x | Return 1 if both α and β are truthy, else 0. |
97 | \x61 | logical-or | α β | x | Return 1 if both α or β (or both) are truthy, else 0. |
98 | \x62 | divides | x y | p | Return 1 if x is a multiple of y, else 0. |
99 | \x63 | divmod | x y | q r | Return int(x/y) and (x mod y). |
100 | \x64 | sum | [x] | sum([x]) | Sum of list |
100 | \x64 | even | x | p | Is x even? |
101 | \x65 | product | [x] | product([x]) | Product of list |
101 | \x65 | odd | x | p | Is x odd? |
102 | \x66 | fizzbuzz | κ | Push "1\n2\nFizz\n4\nBuzz..." | |
103 | \x67 | popcnt | x | popcnt(x) | Count number of 1 bits in binary repr. of x |
104 | \x68 | base | α b | β | Convert α to/from base b |
105 | \x69 | binary | α | β | 2 base |
106 | \x6a | is-prime | x | p | |
107 | \x6b | nth-prime | n | p | |
108 | \x6c | n-primes | n | [p] | |
109 | \x6d | primes-below | n | [p] | |
110 | \x6e | next-prime | n | p | |
111 | \x6f | totient | n | p | Euler's totient function |
112 | \x70 | lt | α β | α < β | |
113 | \x71 | eq | α β | α = β | |
114 | \x72 | gt | α β | α > β | |
115 | \x73 | ge | α β | α ≥ β | |
116 | \x74 | ne | α β | α ≠ β | |
117 | \x75 | le | α β | α ≤ β | |
118 | \x76 | cmp | α β | cmp(α,β) | -1 if α<β, 0 if α=β, 1 if α>β |
119 | \x77 | sorted | [α] | b | 1 if [α] is sorted, else 0 |
Examples
(TODO)