Sike
Created 11/10/2025, 6:56:20 PM; Last modified 11/11/2025, 11:49:22 AM
- Sike* [ˈsi.ke] (/SEE-kay/) is a deque[a]-based esoteric programming language, based on the idea of both /code/ and and /data/ sharing the same collection. Instructions are shifted (i.e. dequeued) from the front of the deque, and data is popped from the back of the deque.
The name is from toki pona[b] and means something like /circle/ or /cycle/.
[ Table of Contents ]
+ 1. Syntax and Types
+ 1.1. Numbers
+ 1.2. Characters
+ 1.3. Words
+ 1.4. Packs
+ 1.5. Keep tokens
+ 1.6. Comments
+ 2. Execution
+ 3. Words
+ 4. Example Programs
+ 4.1. Hello, World!
+ 4.2. Cat
+ 4.3. Truth Machine
+ 4.4. Counter
+ 4.5. Limited Counter
+ 4.6. FizzBuzz
+ 5. Computational class
+ 6. Interpreter
+ 6.1. Debugging
+ Links
1. Syntax and Types
Sike has fairly traditional syntax similar to many stack-based languages. The program is a sequence of whitespace-delimited tokens. Tokens can be either a /number/, a /character/, or a /word/.
All tokens, once parsed, become the program's initial deque.
1.1. Numbers
Numbers are 64-bit signed integers. They optionally begin with a minus `-`, and then contain a sequence of digits. Examples:
0 20 -1234
1.2. Characters
Characters represent a single unicode codepoint. They start with quote `'` followed optionally by any character (encoded in UTF-8). If no character is specified, the character represents space (U+0020). Alternatively, after the quote a character may contain `u` followed by a hexadecimal number specifying a unicode codepoint. Examples:
'A # LATIN CAPITAL LETTER A U+0041 ' # SPACE U+0020 'u0A # LINE FEED U+000A
1.3. Words
Tokens that do not start with quote and can not be parsed as a number are parsed as words. There is a limited number of valid words, and new words can not be defined. Examples:
dup swap unpack
1.4. Packs
In addition, there are /packs/ which are groups of tokens surrounded by brackets `[]`. There does not need to be whitespace between brackets and surrounding tokens. Examples:
# Pack containing 1, 2, and 3 [ 1 2 3 ] [1 2 3] # Empty pack [] [ ] # Packs may be nested [ 1 2 [ 3 4 ] ]
1.5. Keep tokens
A token may also be marked /keep/, meaning that after evaluation it is to be pushed to the back of the deque. Keep tokens begin with a dot `.`:
# Keep tokens of different types .1 .[ 1 2 3 ] .'A .swap
1.6. Comments
Comments start with `#` and end at the end of the line. Examples:
# hello pack unpack # do nothing
2. Execution
The program continuously runs cycles until the deque is empty. Each cycle, a value is shifted from the front of the deque and executed. The action that takes place depends on the type of the value:
- /Words/: The corresponding word action is executed.
- /Numbers, Characters/: The number or character is printed to `stdout`.
- /Packs/: The pack is /unpacked/, i.e. all values inside the pack are pushed to the back of the deque.
If the value is marked keep, it is pushed to the end only after its execution finishes.
3. Words
The following list contains all words. The effect of each word is written in Forth-like stack notation.[c]
Conditional operators output either the integer zero or one.
- `dup`: x -- x x
- `drop`: x --
- `swap`: x y -- y x
- `over`: x y -- x y x
- `dupd`: x y -- x x y
- `swapd`: x y z -- y x z
- `nip`: x y -- y
- `rotl`: x y z -- y z x
- `rotr`: x y z -- z x y
- `swapn`: x ...[n-1 items] y n -- y ... x (when /n/ is zero, this is no-op)
- `+`: x y -- x+y
- `-`: x y -- x-y
- `*`: x y -- x*y
- `/`: x y -- x/y
- `%`: x y -- x%y
- `=`: x y -- x=y
- `!=`: x y -- x!=y
- `<`: x y -- x<y
- `>`: x y -- x>y
- `<=`: x y -- x<=y
- `>=`: x y -- x>=y
- `and` x y - x&&y
- `or` x y -- x||y
- `not` x -- !x
- `neg` x -- -x
- `keep`: x -- .x
- `unkeep`: .x -- x
- `toggle-keep`: x -- .x ; .x -- x
- `if`: cond true false -- true|false (/true/ is outputted when /cond/ ≠ 0, otherwise /false/ is outputted.)
- `pack`: x -- [ x ]
- `packn`: ...[n items] n -- [ ... ]
- `unpack`: [ ... ] - ...
- `input`: -- c (reads a single character from `stdin`)
- `ord`: c -- n (converts a character to a number representing its unicode codepoint)
- `chr`: n -- c (converts a number representing a unicode codepoint to the corresponding character)
4. Example Programs
4.1. Hello, World!
Prints `Hello, World!` to `stdout`.
'H 'e 'l 'l 'o ', ' 'W 'o 'r 'l 'd '! 'u0A
4.2. Cat
This program outputs its input.
.input
4.3. Truth Machine
Takes a single character as input. When that character is `0`, prints `0` and returns immediately. Otherwise, prints `1` forever.
input ord [ 48 ] - [ 0 .1 ] if
4.4. Counter
Counts up forever, outputting numbers delimited by space.
.[ dup [ 1 ] + pack [ ' ] ] [ 0 ]
4.5. Limited Counter
Same as the previous, but only counts up to 10.
.[ # increase n dup [ 1 ] + pack # compare n to 10 and drop everything if greater over [ 10 ] < [ [ drop drop drop drop drop drop drop drop drop drop drop drop drop drop 'u0A ] [] ] if unpack # add space to print [ ' ] ] [ 0 ]
4.6. FizzBuzz
Does the classic FizzBuzz problem. This program does not halt.
[[ 0 ]] .[ [1] + # select "Fizz" if n%3==0 dup [3] % [ ['F 'i 'z 'z] [] ] if # select "Buzz" if n%5==0 swap dup [5] % [ ['B 'u 'z 'z] [] ] if # push `[drop]` when n%3==0||n%5==0, empty pack otherwise swap dup [5] % over [3] % or [ drop [] ] if # create two packs of the number # one is for output, the other is for preserving the state of the counter swap pack dup rotl # note: above two instructions make sure that the number is only # printed when we haven't pushed either Fizz or Buzz # print newline (deferred) # swap necessary to keep number on top of stack [ ['u0A] swap ] ]
5. Computational class
Sike is Turing complete.[d] This can be shown by a translation argument; the following python code (written by Moja[e]) translates cyclic tag[f] (a turing complete system) to Sike:
def step(n):
return ["[[]]", f"[{2*n}]", "swapn"]*2
def convert_bit(bit, n):
if bit=="0":
return step(n)
else:
return [f"[{2*n}]", "packn", "dup", "unpack",
f"[{2*n-1}]", "packn", "drop",
"unpack", "unpack", "swapn", "unpack"] + step(n)
def convert_block(b, n):
res=[]
for bit in b:
res+=convert_bit(bit, n)
res+=["[]", f"{len(res)+1}"]
return f"[[{' '.join(res)}]] drop"
def convert_prog(table, input):
n=len(table)
return (" ".join(" ".join(convert_bit(bit, n)) for bit in input)+" "+
" ".join(convert_block(b, n) for b in table))
# The following two lines can be replaced to generate any cyclic tag
# system
# Input bitstring
input="100"*1
# Productions
table=["010001","100","100100100","","",""]
print(convert_prog(table,input))
6. Interpreter
6.1. Debugging
The official interpreter supports extra debugging features. When run with the `-d` flag, the interpreter starts in /debug mode/. When in debug node, the program can be stepped through cycle-by-cycle by pressing enter. `continue` or `c` can be typed to continue execution from the current position without stepping.
Breakpoints may also be inserted. For example:
1 2 breakpoint 3
Will trigger a breakpoint when `2` is executed. Breakpoints are not words; instead they simply mark the previous token as having a breakpoint. When a breakpoint is triggered, stepping is reactivated.