Skip to content
J2k-studioPublic

About

J2K, a small systems language, and Jcmp, its self-hosting compiler: native Linux ARM64 and ARM32 programs, no libc, written in J2K itself and built on a phone

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

J2K and Jcmp

J2K & Jcmp

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.

Why it exists

  • 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).

What is done

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

Where it is going

  1. Speed: match clang -O2 (division by constants, vector loops, better registers).
  2. More targets: x86-64, then WebAssembly or Windows.
  3. Languages that meet: J2K libraries that Java, C and Python call; tools that build Android apps from J2K.
  4. 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!

ภาษาไทย → README.th.md


Status

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.


Tools, games and the Jaric app

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 system

Many 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).

Install

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.

1. install.sh (recommended)

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.

2. One command with tar (keeps the executable bit)

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

3. By hand, into ../bin

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.

Use it

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            # hi

Without PATH you can call it by its path: ../bin/jcmp hi.jk -o hi.

From the source repository

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 itself

If 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).


The language in one screen

#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]).


Repository layout

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

How it was built (bootstrapping)

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.


License

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).

Author

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.

About

J2K, a small systems language, and Jcmp, its self-hosting compiler: native Linux ARM64 and ARM32 programs, no libc, written in J2K itself and built on a phone

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages