We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.
SubtextLang
SubtextLang (Chinese: 潛文) is a steganographic esoteric programming language inspired by the minimalist philosophy of languages like Whitespace. It operates exclusively with a set of seven carefully selected characters, grouped into three semantic categories. Despite this extreme constraint, SubtextLang enables the creation of well-structured, expressive, and Turing-complete programs, showcasing the creative potential of minimal syntax design.
A unique property of SubtextLang is its support for Bistability—a single source file can simultaneously contain both invisible code and visible semantic camouflage code, yielding entirely distinct execution results depending on which parsing layer is targeted.
Dialects and Representation
SubtextLang is designed to be utilized in two distinct concealment variants:
- Invisible Subtext (
.istx) — This variant uses zero-width and formatting control characters (e.g., U+180B, U+202D). Programs written in this version are effectively hidden within ordinary text and are virtually invisible under standard text viewers. - Semantic Camouflage (
.cstx) — This variant employs common, innocuous Chinese characters (e.g., "也", "之", "是"). These characters can be seamlessly woven into natural language prose, masking both the existence and intent of the code.
Character Substitution Table
To maintain readability during development, human-readable placeholder characters (.stx) are used. The following table defines the mapping between placeholders, Unicode characters, and suggested Chinese characters for camouflage:
| Placeholder | Invisible Subtext | Semantic Camouflage | Substitution Options | Description |
|---|---|---|---|---|
| 一 | U+180B | 也 | 亦, 仍, 還 | Instruction Type A (Stack, Math, Control) |
| 二 | U+180C | 如 | 像, 似 | Instruction Type A (Stack, Math, Control) |
| 三 | U+180D | 是 | 即, 乃, 為 | Instruction Type A (Stack, Math, Control) |
| 子 | U+180E | 其 | 那個, 該 | Type B: Modifier / Terminating Delimiter |
| 丑 | U+202C | 言 | 說, 語, 講 | Type B: Modifier / Terminating Delimiter |
| 甲 | U+202A / U+202B | 之 | 的, 所 | Type C: Data Encoding (Bit 0) |
| 乙 | U+202D / U+202E | 與 | 和, 以及, 跟 | Type C: Data Encoding (Bit 1) |
Instruction Format
All instructions follow a strict structural pattern:
<Type A> <Type B/Type C> [<Type B>] [Data/Label using 甲/乙 <子/丑>]
- Example (Push Value 5):
一 子 乙甲乙子(Equivalent to:Push (101)_2) - Example (Label Definition):
三 甲 子 乙乙甲乙子(Defines Label 13)
Data Encoding
SubtextLang encodes numbers using binary representation of 甲 (0) and 乙 (1).
- Sign Bit: If a number starts with
甲, it represents a negative number (e.g.甲乙甲乙子is -5). If it starts with乙, it is positive. - Literal Delimiter: Literal values are terminated with
子. - Dynamic Heap Reference Delimiter: To dynamically load a value from a heap address, terminate the binary with
丑instead of子.
| Code | Binary Representation | Meaning |
|---|---|---|
乙甲子 |
10 (Literal) |
Decimal 2 |
甲乙甲乙子 |
0101 (Literal) |
Decimal -5 |
乙乙丑 |
11 (Heap Reference) |
Read from heap at address 2 (binary 10) |
甲乙甲丑 |
01 (Heap Reference) |
Read from heap at address -1 |
Instruction Set
Memory Manipulation (Type A: 一)
| Code | Operation | Description |
|---|---|---|
一 子 [n] |
push VALUE | Push number n onto the stack.
|
一 丑 [n] |
copy N | Copy the N-th item of the stack to the top. |
一 子 子 |
swap | Swap the top two items on the stack. |
一 子 丑 |
drop | Discard the top item on the stack. |
一 丑 子 |
save | Store value into heap (Address: second item, Value: top item). |
一 丑 丑 |
get | Retrieve value from heap (Address: top item). |
I/O Operations (Type A: 一)
| Code | Operation | Description |
|---|---|---|
一 甲 子 |
printN | Output the top stack item as a number. |
一 甲 丑 |
printC | Output the top stack item as a character. |
一 乙 子 |
readN | Read a number and store it at the heap address specified by the top stack item. |
一 乙 丑 |
readC | Read a character and store it at the heap address specified by the top stack item. |
Arithmetic (Type A: 二)
Note: For operations, the stack top is b, and the second item is a.
| Code | Operation | Description |
|---|---|---|
二 甲 子 |
add | Compute a + b.
|
二 甲 丑 |
sub | Compute a - b.
|
二 乙 子 |
mul | Compute a * b.
|
二 乙 丑 |
div | Compute floor of a / b.
|
二 子 子 |
root | Compute floor of a¹ᐟᵇ.
|
二 子 丑 |
and | Compute bitwise a ⋀ b.
|
二 丑 子 |
or | Compute bitwise a ⋁ b.
|
二 丑 丑 |
not | Compute bitwise ¬ b.
|
Flow Control (Type A: 三)
| Code | Operation | Description |
|---|---|---|
三 甲 子 [label] |
label LABEL | Define a label. |
三 甲 丑 [label] |
jump LABEL | Unconditional jump to LABEL. |
三 乙 子 [label] |
ifz LABEL | Jump to LABEL if top of stack is 0. |
三 乙 丑 [label] |
ifl LABEL | Jump to LABEL if top of stack < 0. |
三 子 子 [label] |
func LABEL | Call function at LABEL (pushes return address to call stack). |
三 子 丑 |
funcEnd | Return from function (pops return address). |
三 丑 丑 |
end | Terminate the program. |
Computational Model
- Stack: Standard LIFO stack for data operations.
- Heap: Global key-value memory mapping integers to integers.
- Call Stack: Implicit return address stack allowing nested function calls.
- Error Handling: Programs terminate with a Runtime Error upon division by zero, stack underflow, or memory access violations.
- Ignored Characters: Any character outside the seven core symbols (
一,二,三,子,丑,甲,乙) is treated as a comment and ignored. - Encoding: It is recommended to save programs in
UTF-8format. This ensures that the Invisible Subtext characters are correctly preserved and interpreted across different platforms and text viewers.
Sample Program
This sample calculates the modulus (remainder) of the top two stack items (stack: [a, b] -> [a % b]):
三 甲 子 乙子 # function start (e.g. stack has [7, 3]) 一 丑 乙甲子 # Duplicate 2nd item (stack: [7, 3, 7]) 一 丑 乙甲子 # Duplicate 2nd item (stack: [7, 3, 7, 3]) 二 乙 丑 # Floor Division (stack: [7, 3, 2]) 二 乙 子 # Multiplication (stack: [7, 6]) 二 甲 丑 # Subtraction (stack: [7 - 6] -> [1]) 三 子 丑 # Return from function
See Also
External resources
- Interpreters and Examples(GitHub)
- Online interpreter with a debugger(GitHub Pages)