A language that talks straight to the CPU. Written in itself, built on a phone.
J2K is a small systems language, designed from scratch and close to the machine.
Jcmp is its native compiler: it reads .jk / .j source and writes a Linux ARM64 executable
directly (its own assembler and ELF writer: no LLVM, no GCC, no as, no ld).
It is self-hosting: the compiler is written in J2K and rebuilds itself, byte for byte.
- One person, one phone, no borrowed toolchain. Every layer is ours: language, compiler, assembler, linker, standard library, the tools, the terminal app and the start of an operating system.
- Close to the machine, with the comforts of a modern language: pointers and raw registers when you want them; strings, generics,
Option/Result,defer, lambdas, inheritance, default arguments and"x = {x}"text when you do not. - Fast by design: the goal is output as fast as
clang -O2(today about 1.5 to 4 times slower on loops and recursion, faster on some, and getting closer each release).
| Compiler | self-hosting, Linux ARM64 and ARM32, -j N many cores, native GPU (-dyn), shared libraries for C / Java / Python (export, -l), 600+ tests |
| Language | structs, methods and operator methods, enums with data, generics, try/throw, threads, inheritance (virtual / override), default arguments, text with values inside |
| Tools (Jcmp-Tools) | shell, package manager, editor, build tool, git, music player, small AI, an emulator that runs ARM64 programs and kernels |
| Jaric | an Android terminal app that is the first mode of Jaric OS; a kernel with processes, a file system, pipes and a real shell, started in the emulator, with its own boot screen |
- Speed: match
clang -O2(division by constants, vector loops, better registers). - More targets: x86-64, then WebAssembly or Windows.
- Languages that meet: J2K libraries that Java, C and Python call; tools that build Android apps from J2K.
- Jaric OS with a real screen: phone mode (portrait) and desktop mode (landscape), apps for graphics, video and sound on the Jaric Engine.
// hello.jk
void main() {
jout << "Hello from J2K!\n";
}
$ bin/jcmp examples/hello.jk -o hello
$ ./hello
Hello from J2K!| Component | State |
|---|---|
Compiler written in J2K (jcmp/) |
Working, self-hosting (two generations are identical, byte for byte) |
Assembler written in J2K (jcmp/jc_asm.j) |
Working, built into the compiler |
| Language | Integers (i8 i32 int char bool, unsigned u8 u32 u64), floats (float double), arrays (up to 3 dimensions, with lists int a[3] = {1, 2, 3};), pointers (T^, T^^), function pointers and lambdas (int(int a) { ... }), structs with methods and operator methods (operator vec3 add(self, vec3 o) makes a + b, -a, 2.0 * a work), enums (also with data: Shape::Circle(r)), switch that takes a value apart, Option<T> / Result<T, E> and ?, defer, try/catch/throw, panics with a stack trace, sizeof, dynamic arrays (T[]), String (UTF-8, +, ==, <), generics with inference (T max<T>(T a, T b), struct Stack<T>), #define, imports |
| Standard library | #import <stdlib>: Sys, Mem, Str, Math (complete), File, Fs, Dir, Env, Time, Random, Num (parse), Term (size, key), List / Map / Set, Json, Sha256, Proc (run programs), Path, Hex, Base64 |
| Math and graphics | #import <math> then using math::vector; (vec2 vec3 vec4, swizzle v.xy, c.rgb), matrix (mat3 mat4: rotate, perspective, look_at), quat, complex, stats; #import <gfx> then using gfx::canvas; (characters with a depth buffer) or using gfx::screen; (colour dots: lines, circles, gradients, glow, vignette) |
| Diagnostics | file:line:col: error/warning: with the source line and ^; -st makes warnings errors |
Debug build (-d) |
array bounds checks, a report of memory that was not freed |
| Memory | alloc/free, dynamic arrays, automatic freeing of owned memory at the end of a block, structs that free themselves and move |
| Input | jin (type decides what is read; bad input throws) |
| Threads | #import <cpu>: Thread (create, join, detach), Mutex (futex based), #multithread loops |
| Speed | about 1.5 to 4 times slower than clang -O2 on loops and recursion (a peephole pass, operands in registers, division by a literal without sdiv); more is planned |
| Target | Linux ARM64; Linux ARM32 with -target arm32 (first version, see docs/USAGE.md) |
Release history: CHANGELOG.md.
Around the compiler there are tools written in J2K: Jcmp-Tools (jget, makej, the shell jsh, jbox, the editor coderin, zipj, tarj, the player mujic, the task manager jamanager, the settings tool jash, the small AI tool neuron with the assistant xr, and Python 3.14 with pip and yt-dlp for Android; the compiler itself is jc install jcmp) and the Jaric app for Android, a terminal that is the first mode of Jaric OS.
$ makej init -pro mytool # a project with the right structure: src/, tests/, docs/, manifest.toml ...
$ makej init -game # a game with Jaric Engine (jc lib install gamej) and five lessons
$ makej apk # the game as an Android app; makej pack = a .jc; makej dist = every systemMany cores: makej -j 8 builds several programs at once; #multithread before a for loop splits it over the cores; the compiler itself uses one core today (-cache DIR makes a second build fast). Loops get their test at the bottom (-norot switches it off while looking for a fault).
You need a Linux ARM64 machine (a phone with Termux works) and curl or wget
(Termux: pkg install curl wget). The compiler jcmp and its library (the folder Library) are a pair and are published together as a
release.
It downloads the latest release, checks its SHA-256 and puts jcmp and the library (Library, next to the program folder) in place.
curl -fsSL https://raw.githubusercontent.com/J2k-studio/Jcmp/main/install.sh | sh
Or, with wget:
wget -qO- https://raw.githubusercontent.com/J2k-studio/Jcmp/main/install.sh | sh
The default folder is $PREFIX/bin on Termux and ~/.local/bin elsewhere. To choose the folder, for example a
bin folder next to your project (../bin):
curl -fsSL https://raw.githubusercontent.com/J2k-studio/Jcmp/main/install.sh | sh -s -- --dir ../bin
wget -qO- https://raw.githubusercontent.com/J2k-studio/Jcmp/main/install.sh | sh -s -- --dir ../bin
| Option | Meaning |
|---|---|
--dir DIR |
install into DIR (created if needed) |
--version 0.9.158 |
a specific release instead of the latest |
--with-assembler |
also install j2k_asm, the stand-alone assembler |
Run it again to update (or run jcmp -update). To uninstall, delete the files.
A plain file downloaded from a release is not executable (GitHub does not keep the permission bit; that is why a
plain download needs chmod +x). The file jcmp.tar.gz of every release holds the program jcmp, already executable, and the folder Library that belongs to it (keep them side by side):
mkdir -p ../bin
curl -fL https://github.com/J2k-studio/Jcmp/releases/latest/download/jcmp.tar.gz | tar xz -C ../bin
Or with wget:
wget -qO- https://github.com/J2k-studio/Jcmp/releases/latest/download/jcmp.tar.gz | tar xz -C ../bin
../bin/jcmp -version
The same thing step by step with the plain file (the folder ../bin is only an example; use any folder):
mkdir -p ../bin && cd ../bin
With curl:
curl -fLO https://github.com/J2k-studio/Jcmp/releases/latest/download/jcmp
curl -fLO https://github.com/J2k-studio/Jcmp/releases/latest/download/SHA256SUMS
Or with wget:
wget https://github.com/J2k-studio/Jcmp/releases/latest/download/jcmp
wget https://github.com/J2k-studio/Jcmp/releases/latest/download/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS # must print: jcmp: OK
chmod +x jcmp && rm SHA256SUMS
A specific version: replace latest/download with download/v0.9.158 (also a good idea right after a new release, when the latest links can lag behind for a minute). The bundle
jcmp-<version>-linux-arm64.tar.gz of the same release holds the compiler, the assembler, the examples and the docs.
Put the folder on your PATH (once per shell, or add the line to ~/.bashrc), then check:
export PATH="$PWD:$PATH" # inside the folder; or the full path of your folder
jcmp -version # jcmp 0.9.158 (J2K compiler, Linux ARM64)
printf '#import <stdlib>\nusing stdlib\nvoid main() { jout << "hi\\n"; }\n' > hi.jk
jcmp hi.jk -o hi && ./hi # hiWithout PATH you can call it by its path: ../bin/jcmp hi.jk -o hi.
To read the compiler or rebuild it (the repository contains a ready bin/jcmp):
git clone https://github.com/J2k-studio/Jcmp.git
cd Jcmp
bin/jcmp examples/fib.jk -o fib && ./fib
./bootstrap.sh # rebuild the compiler with itselfIf the repository or its releases are private, curl/wget need a token
(curl -fL -H "Authorization: Bearer $TOKEN" ...) or use gh release download.
New to J2K? Start with the tutorial: docs/TUTORIAL.md. More: docs/USAGE.md (command line, building, testing) and docs/LANGUAGE.md (a tour of the language), docs/LIBRARIES.md (how to use each part of the library, by category), docs/LIMITS.md (what it does not do yet) and docs/API.md (every library function).
#import <stdlib> // the standard library: Sys, Mem, Str, Math, File (and jout, jin)
using stdlib; // use its names without the prefix (jout needs both lines)
enum class Color { Red, Green, Blue };
struct Point {
double x;
double y;
double length(self) { return sqrt(self.x * self.x + self.y * self.y); }
}
int sum(int a[]) { // arrays arrive with their length: a.len
int total = 0;
for i in 0..a.len { total += a[i]; }
return total;
}
void main() {
int numbers[4];
for i in 0..4 { numbers[i] = i * 10; }
jout << "sum = " << sum(numbers) << "\n";
Point p = {3.0, 4.0};
jout << "length = " << p.length() << "\n"; // 5.000000
Color c = Color::Green;
switch c {
Color::Red: jout << "red\n";
Color::Green: jout << "green\n";
_: jout << "other\n";
}
}
Design goals: fast and close to the CPU (values live in registers, struct layout like C,
arithmetic at register width), strict where it prevents bugs (a bool is not an int,
an enum is not a number, int and float do not mix without a cast), no hidden magic
(no garbage collector, no pointer arithmetic — use p[i]).
Jcmp/
├── README.md, README.th.md, LICENSE, VERSION, CHANGELOG.md
├── install.sh download + check + install the latest release
├── bin/ the compiler and assembler binaries (built by themselves)
│ ├── jcmp the compiler (J2K -> ARM64 ELF)
│ └── j2k_asm_j2k the stand-alone assembler (.jasm -> ELF)
├── jcmp/ the compiler's own source, in J2K
│ ├── jcmp.jk entry point (main, command line)
│ ├── jc_base.j jc_lex.j jc_expr.j jc_stmt.j the four parts
│ ├── jc_asm.j the assembler (a library)
│ └── jc_std.j generated from std/ by gen_std.sh
├── std/ the standard library (J2K): sys, mem, str, math, fs
├── examples/ small programs
├── docs/ language specification and guides
│ ├── syntax-design.md the language specification (decisions are recorded here)
│ └── TUTORIAL.md TUTORIAL.th.md LANGUAGE.md USAGE.md
├── j2k_asm.jk command-line wrapper of the assembler
├── bootstrap.sh rebuild the compiler with itself and compare
├── bootstrap-from-binary.sh the short version of the same check
└── gen_std.sh std/*.j -> jcmp/jc_std.j
The first assembler and compiler were hand-written in ARM64 assembly. The assembler was then
rewritten in J2K, then the compiler, in four parts. Today the compiler compiles itself:
bootstrap.sh starts from the committed bin/jcmp, builds three generations and checks that
the last two are byte-for-byte identical. The assembly versions are no longer part of this
repository.
This project is source-available under its own license (version 1.2):
- Programs you write in J2K and build with jcmp are yours. You may distribute them, sell them and use them commercially, without asking and without paying; no credit line is needed.
- Every update of jcmp 1.x is free of charge. A new release never needs a new payment.
- You may read the compiler, run it, and study it. You may not modify it and redistribute it, redistribute the compiler or the library as such, or sell or offer the compiler itself as a product or a service. (A private copy may be changed for your own use if you never share it.)
See LICENSE for the full terms (English + Thai summary).
Jao (J2k-studio) — Thailand. Contact for permission requests: the GitHub profile J2k-studio. The project is developed by a single author; outside contributions are not accepted at this stage.