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.
Unicodinido
Unicodinido is designed by PSTF, and is mostly inspired from Unicoding.
The name of Unicodinido combines Unicoding and Ido (which means successor in Esperanto).
Overview
Unicodinido currently supports these scripts:
- ASCII
- Pan-Latin
- Greek
- Cyrillic
- Armenian
- Hiragana
- Katakana
- Hanzi/Kanji/Hanja
- Hangul Jamo
In future, it will support more scripts.
EBNF Definition
(* ─── ASCII BASIC (0–127) ─────────────────────────────────────────── *)
ASCII_BF_OP = '>' | '<' | '+' | '-' | '[' | ']' | '.' | ',' ;
ASCII_PUNCT = ';' | '{' | '}' | '(' | ')' | '=' | ':' | '?' | '!'
| '~' | '/' | '*' | '%' | '#' ;
ASCII_KW = 'import' | 'as' | 'implements' | 'fn' | 'return'
| 'if' | 'else' | 'loop' | 'while' | 'match'
| 'true' | 'false' | 'null' ;
(* ─── LATIN-1 SUPPLEMENT (U+0080–U+00FF) ───────────────────────────── *)
LATIN1_OP = '×' | '÷' | '±' | 'µ' ;
LATIN1_FRACTION= '¼' | '½' | '¾' ;
(* ─── LATIN EXTENDED-A & B (U+0100–U+024F) ──────────────────────────── *)
LATIN_EXT_IO = 'ā' | 'ē' | 'ī' | 'ō' ; (* print_str, read_line, print_int, print_float *)
(* ─── IPA EXTENSIONS (U+0250–U+02AF) ────────────────────────────────── *)
IPA_CONC = 'ʃ' | 'ʒ' | 'æ' | 'ð' ; (* spawn, join, atomic_xchg, memory_fence *)
(* ─── GREEK (U+0370–U+03FF) ─────────────────────────────────────────── *)
GREEK_LAMBDA = 'λ' ;
GREEK_MATH_ID = 'α' | 'β' | 'δ' | 'ε' | 'ζ' | 'π' | 'σ' | 'τ' ; (* used as identifiers *)
(* ─── BASIC CYRILLIC (U+0400–U+04FF) ────────────────────────────────── *)
CYRILLIC_TYPE = 'А' | 'Б' | 'В' | 'Г' | 'Д' | 'Ж' | 'З' ; (* int, long, string, bool, float, list, dict *)
(* ─── ARMENIAN (U+0530–U+058F) ──────────────────────────────────────── *)
ARMENIAN_OO = 'ա' | 'բ' | 'գ' | 'դ' | 'զ' ; (* class, method, property, extends, implements *)
(* ─── HIRAGANA (U+3040–U+309F) ──────────────────────────────────────── *)
HIRAGANA_ASYNC = 'か' | 'あ' | 'ら' | 'り' ; (* async, await, emit, listen *)
(* ─── KATAKANA (U+30A0–U+30FF) ──────────────────────────────────────── *)
KATAKANA_FFI = 'カ' | 'チ' | 'ラ' | 'タ' ; (* ffi_import, unsafe, abi_call, extern *)
(* ─── CJK UNIFIED IDEOGRAPHS / HANZI (U+4E00–U+9FFF) ───────────────── *)
HANZI_MACRO = '宏' ; (* macro definition *)
HANZI_COLL = '集' | '列' | '映' ; (* set, list, map literals *)
HANZI_REFLECT = '反' ; (* compile‑time reflection *)
HANZI_ID = Any Hanzi ideograph EXCEPT the above reserved ones ;
(* ─── HANGUL JAMOS & SYLLABLES (U+1100–U+11FF, U+AC00–U+D7AF) ────── *)
HANGUL_GENERIC = 'ㄱ' | 'ㄴ' | 'ㄷ' | 'ㅂ' ; (* type parameters T, U, V, bounded *)
INTERFACE_KW = '정의' ; (* interface keyword – composed syllable *)
HANGUL_CTOR = '글' | '한' ; (* Result<T,E> and Option<T> type constructors *)
HANGUL_ID = Any Hangul syllable EXCEPT the reserved ones above ;
(* ─── GENERIC LEXICAL RULES ─────────────────────────────────────────── *)
Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ;
StringChar = ? any UTF‑8 character except double‑quote or backslash ?
| '\"' | '\\' | '\n' | '\t' ;
StringLiteral = '"' { StringChar } '"' ;
NumericLiteral = Digit { Digit } [ '.' Digit { Digit } ] | LATIN1_FRACTION ;
(* Identifier: any letter from the supported blocks, minus the fixed keywords.
The lexer resolves this by matching the longest keyword first. *)
Identifier = ( ASCII_Letter | LATIN_EXT_IO | GREEK_MATH_ID | CYRILLIC_TYPE
| ARMENIAN_OO | HIRAGANA_ASYNC | KATAKANA_FFI | HANZI_ID
| HANGUL_GENERIC | HANGUL_ID | IPA_CONC )
{ Identifier | Digit | '_' } ;
(* ─── ROOT ───────────────────────────────────────────────────────────── *)
Program = { Import | TopLevelDecl | BrainfuckBlock } ;
Import = 'import' Identifier [ 'as' Identifier ] ';' ;
TopLevelDecl = ClassDecl | InterfaceDecl | FunctionDecl
| MacroDecl | FfiBlock ;
(* ─── ARMENIAN OOP ──────────────────────────────────────────────────── *)
ClassDecl = ARMENIAN_OO.ա Identifier [ GenericParams ]
[ 'implements' Identifier [ GenericArgs ] ]
'{' { ClassMember } '}' ;
InterfaceDecl = INTERFACE_KW [ GenericParams ]
'{' { MethodSignature } '}' ;
ClassMember = PropertyDecl | MethodDecl ;
PropertyDecl = ARMENIAN_OO.գ Identifier ':' Type [ '=' Expression ] ';' ;
MethodDecl = [ HIRAGANA_ASYNC.か ] ARMENIAN_OO.բ Identifier
'(' [ ParamList ] ')' [ '->' Type ] Block ;
MethodSignature = ARMENIAN_OO.բ Identifier
'(' [ ParamList ] ')' [ '->' Type ] ';' ;
(* ─── HANZI MACROS ──────────────────────────────────────────────────── *)
MacroDecl = HANZI_MACRO Identifier '(' [ ParamList ] ')' Block ;
(* ─── KATAKANA FFI ──────────────────────────────────────────────────── *)
FfiBlock = KATAKANA_FFI.カ '(' StringLiteral ')'
'{' { FfiDecl } '}' ;
FfiDecl = Identifier '=' StringLiteral ';' | FunctionDecl ;
(* ─── GENERIC FUNCTIONS ────────────────────────────────────────────── *)
FunctionDecl = [ HIRAGANA_ASYNC.か ] 'fn' Identifier
'(' [ ParamList ] ')' [ '->' Type ] Block ;
ParamList = Param { ',' Param } ;
Param = Identifier ':' Type ;
(* ─── TYPE SYSTEM (CYRILLIC + HANGUL CONSTRUCTORS) ────────────────── *)
Type = CYRILLIC_TYPE
| HANGUL_CTOR '<' Type [ ',' Type ] '>' (* 글<A,B> , 한<T> *)
| Identifier [ GenericArgs ] ;
GenericParams = '<' HANGUL_GENERIC { ',' HANGUL_GENERIC } '>' ;
GenericArgs = '<' Type { ',' Type } '>' ;
(* ─── BLOCKS & STATEMENTS ──────────────────────────────────────────── *)
Block = '{' { Statement } '}' ;
Statement = DeclarationStmt | AssignmentStmt | EmitStmt
| ListenStmt | AwaitStmt | ReflectStmt | UnsafeStmt
| IfStmt | LoopStmt | ReturnStmt | MatchStmt
| ExpressionStmt | BrainfuckBlock ;
DeclarationStmt = Type Identifier [ '=' Expression ] ';' ;
AssignmentStmt = Identifier '=' Expression ';' ;
(* ─── HIRAGANA ASYNC / EVENT ──────────────────────────────────────── *)
EmitStmt = HIRAGANA_ASYNC.ら Expression ';' ; (* event_emit *)
ListenStmt = HIRAGANA_ASYNC.り '(' Expression ',' Expression ')' ';' ;
AwaitStmt = HIRAGANA_ASYNC.あ Expression ';' ; (* can also appear as AwaitExpr *)
(* ─── HANZI REFLECTION ────────────────────────────────────────────── *)
ReflectStmt = HANZI_REFLECT '(' Expression ')' ';' ;
(* ─── KATAKANA UNSAFE ─────────────────────────────────────────────── *)
UnsafeStmt = KATAKANA_FFI.チ Block ; (* inline assembly / raw pointers *)
(* ─── CONTROL FLOW ────────────────────────────────────────────────── *)
IfStmt = 'if' '(' Expression ')' Block [ 'else' Block ] ;
LoopStmt = 'loop' Block | 'while' '(' Expression ')' Block ;
ReturnStmt = 'return' [ Expression ] ';' ;
MatchStmt = 'match' '(' Expression ')' '{' { MatchArm } '}' ;
MatchArm = Identifier '(' [ Identifier ] ')' '->' Block ;
(* ─── EXPRESSIONS ──────────────────────────────────────────────────── *)
Expression = AwaitExpr | LambdaExpr | TernaryExpr
| ArithmeticExpr | CallExpr | CollectionLiteral
| Identifier | Literal | '(' Expression ')' ;
AwaitExpr = HIRAGANA_ASYNC.あ Expression ;
LambdaExpr = GREEK_LAMBDA '(' [ ParamList ] ')' Block ;
TernaryExpr = Expression '?' Expression ':' Expression ;
ArithmeticExpr = Expression ( '+' | '-' | LATIN1_OP | '/' | '*' ) Expression ;
(* LATIN1_OP includes × and ÷ *)
CallExpr = Identifier '(' [ Expression { ',' Expression } ] ')' ;
(* ─── HANZI COLLECTION LITERALS ────────────────────────────────────── *)
CollectionLiteral = HANZI_COLL.集 '{' [ Expression { ',' Expression } ] '}' (* set *)
| HANZI_COLL.列 '[' [ Expression { ',' Expression } ] ']' (* list *)
| HANZI_COLL.映 '{' [ MapEntry { ',' MapEntry } ] '}' ; (* map *)
MapEntry = Expression '=>' Expression ;
Literal = NumericLiteral | StringLiteral | 'true' | 'false' | 'null' ;
(* ─── BRAINFUCK EMBEDDING (TURING‑COMPLETENESS PROOF) ────────────── *)
BrainfuckBlock = "BF{" { ASCII_BF_OP } "}FB" ; (* any sequence of > < + - [ ] . , enclosed in BF{}FB *)
Textual Definition
As you see, a program is consist of several statements or brainfuck codes (this language is strict superset of brainfuck).
Instead of wasteful 1:1 glyph→instruction mapping, Unicodinido assigns entire Unicode blocks to distinct language categories. Currently, scripts plays these roles:
- ASCII stands as the BF code block and some symbols, along with some keywords.
- Pan-Latin stands as some extended expressions.
- Greek stands as a part of identifiers.
- Cyrillic stands as types.
- Armenian stands as Object Oriented things.
- Hiragana stands as Async and Await programming.
- Katakana stands as FFI programming.
- Hanzi/Kanji/Hanja stands as extended literals.
- Hangul Jamo stands as type generics.
Now, let's see what these operations do.
Most Basic Syntax
- Statements end with ; (ASCII semicolon).
- Blocks are delimited by { } (ASCII braces).
- Comments use // (line) and /* */ (block).
- Identifiers can be composed of any letter from Greek, Cyrillic, Armenian, Latin Ext, IPA sets, Hiragana, Katakana, Hanzi, and Jamo (plus ASCII letters).
- Whitespace (space, tab, newline) is ignored except inside string literals.
- Brainfuck instructions can be freely mixed with high-level code, but should be enclosed in BF{}FB—they operate on a separate, dedicated tape.
Examples
If you don't mind, you can learn how to use the language by some examples.
Hello, World!
// A pure Brainfuck program that prints "Hello, World!"
// This proves Turing-completeness without any high-level sugar.
BF{ +++++++++++[>++++++>+++++++++>++++++++>++++>+++>+<<<<<<-]>++++++.>++.+++++++..+++.>>.>-.<<-.<.+++.------.--------.>>>+.>-. }FB
// We can mix in a single Latin-Ext I/O call to flush the buffer:
ā("BF execution done.\n");
Bank Account Simulator
// A simple Bank Account class using Armenian OOP keywords
// and Cyrillic type annotations.
արմ.ա BankAccount {
արմ.գ balance: Д = 0.0; // `Д` = float (Cyrillic)
արմ.գ owner: В; // `В` = string
արմ.բ init(ownerName: В, initial: Д) -> В {
this.owner = ownerName;
this.balance = initial;
return "Account created.";
}
արմ.բ deposit(amount: Д) -> Д {
this.balance = this.balance + amount;
return this.balance;
}
արմ.բ withdraw(amount: Д) -> Д {
if (amount > this.balance) {
return -1.0; // Insufficient funds
} else {
this.balance = this.balance - amount;
return this.balance;
}
}
}
main() -> А { // `А` = int return code
В name = "Alice";
BankAccount acc = new BankAccount();
acc.init(name, 100.0);
Д newBalance = acc.deposit(25.5);
// `ī` = print_float (Latin Extended-A)
ī(newBalance); // prints 125.5
return 0;
}
Fibonacci Numbers
// Compute the nth Fibonacci number using a recursive lambda.
// Uses `×` (multiplication) and `÷` (integer division) from Latin-1.
fn fib(n: А) -> А {
// Greek `λ` creates an anonymous recursive function.
λ (self, x) {
(x <= 1) ? x : self(self, x - 1) + self(self, x - 2);
}(fib, n) // Immediately invoked with `fib` as self-reference
}
main() -> А {
А result = fib(10); // 55
// Demonstrate Latin-1 arithmetic:
А squared = result × result; // 3025 (using `×`)
А halved = squared ÷ 2; // 1512 (using `÷`)
// `ī` = print_int (Latin Extended-A)
ī(halved); // outputs 1512
return 0;
}
Hiragana and Katakana
// Simulate an async HTTP fetch using Hiragana,
// and call a C math library using Katakana.
// Import external C standard math library (Katakana FFI)
カ("libm.so.6") {
// `チ` marks unsafe FFI bindings
チ {
double pow(double, double); // C function declaration
};
}
// Hiragana `か` marks an asynchronous function
か fn fetch_and_compute(url: В) -> Д {
// `あ` = await a hypothetical asynchronous HTTP GET
Д raw_value = あ http_get(url); // assume http_get returns a float
// Call imported C pow() to compute x^2.5
Д computed = pow(raw_value, 2.5);
return computed;
}
main() -> А {
// Spawn the async task (does not block)
Д future = fetch_and_compute("https://api.example.com/sensor");
// `あ` = await the result
Д final = あ future;
ā("Computed value: ");
ī(final); // print float
return 0;
}
Usage of Hanzi Macro
// A compile‑time macro (`宏`) that logs expressions before evaluation.
// Uses Hanzi collection literals: `列` (list) and `映` (map).
宏 log_and_eval(expr) {
// `反` = compile‑time reflection: convert AST to string
В exprStr = 反(expr);
ā("Evaluating: " + exprStr);
return expr; // macro returns the original expression unmodified
}
main() -> А {
// `列` is the Hanzi list literal.
列<А> numbers = 列[10, 20, 30, 40];
// `映` is the Hanzi map literal.
映<В, А> scores = 映{"Alice" => 95, "Bob" => 87, "Charlie" => 92};
// Use the macro:
А x = 5;
А y = log_and_eval(x × 3 + 2); // At compile‑time, prints "Evaluating: x × 3 + 2"
// Access collections:
А first = numbers[0]; // 10
А aliceScore = scores["Alice"]; // 95
return first + aliceScore; // returns 105
}
Usage of Jamo
// `정의` = interface keyword (Hangul).
// `글` = Result<T, E> type constructor, `한` = Option<T>.
정의<ㄱ, ㄴ> { // Generic interface with Jamos: <T, U>
取(값: ㄱ) -> 글<ㄴ, В>; // Method returns Result<U, string>
};
// Armenian class implementing the generic interface.
արմ.ա Parser implements 정의<В, А> {
արմ.բ 取(input: В) -> 글<А, В> {
// Try to parse integer from string.
if (input.length == 0) {
return 글::실패("Empty string"); // `실패` = "failure"
}
А parsed = parse_int(input);
return 글::성공(parsed); // `성공` = "success"
}
}
main() -> А {
Parser p = new Parser();
// Test with valid input.
글<А, В> result1 = p.取("123");
// Use Greek `λ` for pattern matching on the Result.
λ(result1) {
성공(val) -> ī(val); // prints 123
실패(err) -> ā("Error: " + err);
};
// Test with invalid input.
글<А, В> result2 = p.取("");
λ(result2) {
성공(val) -> ī(val);
실패(err) -> ā("Error: " + err); // prints "Error: Empty string"
};
return 0;
}
Concurrency programming by IPA
// Demonstrate thread spawning (`ʃ`), joining (`ʒ`),
// and atomic exchange (`æ`) using Latin-1 fractional constants.
main() -> А {
// Atomic shared counter (address returned by `æ`).
atomic_ptr counter = æ(0); // `æ` = atomic_xchg, initializes atomic int
// Spawn 5 threads using `ʃ` (IPA).
loop (А i = 0; i < 5; i = i + 1) {
ʃ {
// Each thread increments the atomic counter.
// We use Latin-1 fractional constants as loop control.
Д waitTime = ¼; // 0.25 seconds (compile‑time constant)
sleep(waitTime × 1000); // `×` is Latin-1 multiplication
atomic_add(counter, 1);
};
}
// `ʒ` = join all threads (wait for completion).
ʒ();
// Read the final atomic value.
А finalCount = atomic_read(counter);
ā("All threads finished. Counter = ");
ī(finalCount); // should print 5
// Use Latin-1 fraction in an expression:
Д progress = ½; // 0.5
if (finalCount == 5) {
progress = ¾; // 0.75
}
ī(progress);
return 0;
}
Real Description
Due to lack of detail, I couldn't provide it here. Use can add it by themselves.