A statically-typed language with a native compiler, hand-written in Go. Source → three-address IR → LLVM IR → real native binaries for Linux & Windows.
● SYSTEM ONLINE · LLVM BACKEND · NATIVE BINARY
▶ Launch the Playground · Features · Syntax · Install · Pipeline
BidhuScript is a small, statically-typed programming language — and a complete,
from-scratch native compiler for it, written in Go with no parser generators,
no LLVM bindings, no shortcuts. It takes a .bidhu source file all the way down
to a real machine-code executable.
It is a genuine compiler, not a transpiler. Your program is lexed, parsed,
type-checked, and lowered to a three-address intermediate representation, which
is then emitted as textual LLVM IR and handed to clang/llc for instruction
selection and register allocation. The only C anywhere is libc, used as the
runtime — exactly as every native compiler links one. A second, legacy C
backend is kept alongside for side-by-side study.
The result: the same IR retargets to a Linux ELF and a Windows PE32+ .exe,
and -O2's mem2reg turns the compiler's alloca/load/store output into clean
SSA — the way Clang's own frontend works.
bidhu@playground:~/src$ ./bidhu run examples/functions.bidhu
▸ lexing...
▸ parsing...
▸ sema ok
▸ ir lowered
▸ llvm ir emitted
▸ clang link ok
▸ exec ▸ ▸ ▸
====================
BidhuScript functions
====================
9
120
snap and skip:
0 1 2 4 5 6
done| 6 phases | lexer → parser → semantic analysis → IR → codegen → link |
| 2 backends | LLVM (native, default) · C (legacy, for comparison) |
| 2 targets | linux (ELF) · windows (PE32+, cross-compiled) |
| Real IR | three-address code, printable and inspectable |
| Optimizer | run the LLVM opt pass pipeline with a single flag |
| Static typing | full type checking with line/column diagnostics |
| Live playground | run it in your browser — bidhuscript.onrender.com |
Language features: typed variables, a unified while loop (with a do-while mode),
if/else, functions with recursion, fixed-size arrays, and classes — each with a
bit of unique syntax that gives BidhuScript its own character.
BidhuScript keeps a distinctive, memorable keyword set. Here's the whole language at a glance.
let int x = 5; // int, float, string, char, bool
let float y = 10.9;
let string s = "Hello, " + "World"; // '+' concatenates
if (x > 3) { print(x); } else { print(0); }
// unified loop: init ; condition ; increment ; inverse
// inverse = true -> do-while semantics
while(let int i = 0; i < 5; i = i + 1; false) {
print(i);
}
forge add(int a, int b) ~> int { // 'forge' defines; '~>' gives return type
return a + b;
}
forge banner(string title) { // no '~>' => void routine
print(title);
}
let int s = add(4, 5); // calls are standard
while(let int i = 0; i < 10; i = i + 1; false) {
if (i == 3) { skip; } // skip = continue (increment still runs)
if (i == 7) { snap; } // snap = break
print(i);
}
let int[4] nums = [10, 20, 30, 40]; // declared size + literal
let int[] auto = [1, 2, 3]; // size inferred from the literal
let float[3] zeros; // zero-filled
nums[2] = 99; // index assignment
print(nums[i]); // index read
print(span(nums)); // 'span' = length (compile-time constant)
blueprint Point { // 'blueprint' defines a class
int x;
int y;
forge sum() ~> int { // methods reuse forge syntax
return my.x + my.y; // 'my' is the current instance
}
forge scale(int k) { // methods mutate through 'my'
my.x = my.x * k; // (a hidden reference — the caller sees it)
my.y = my.y * k;
}
}
let Point p = spawn Point(3, 4); // 'spawn' constructs (one arg per field)
let Point q = spawn Point; // zero-filled
p.x = 10; // field write
print(p.sum()); // method call
Keyword cheat sheet —
forge= function ·~>= returns ·snap= break ·skip= continue ·span= array length ·blueprint= class ·spawn= new ·my= self · plusletwhileifelsereturn.
Arrays and objects are stack-allocated value types and deliberately second-class: no whole-value use, assignment, parameters, or returns — index or access them instead. Every violation is a precise compile error.
The compiler needs only Go 1.22+ to build. To emit executables it drives a few
external tools, which it finds on your PATH (or via the CLANG, LLC,
MINGW_CC, OPT, CC environment variables):
| Task | Needs |
|---|---|
| Native build (default) | clang |
C backend (-backend c) |
cc / gcc |
Optimizer (-opt) |
opt |
| Windows cross-compile (from Linux) | llc + x86_64-w64-mingw32-gcc |
Tip: the
ir,llvm, anddebugcommands are pure Go and need no external toolchain — handy for verifying your setup before installing LLVM.
# 1. Go (skip if 'go version' already reports >= 1.22)
sudo apt update && sudo apt install golang-go
# 2. LLVM toolchain
sudo apt install clang llvm lld
# On Ubuntu, llc/opt may install version-suffixed only. If so, expose them:
sudo ln -sf "$(which llc-18)" /usr/local/bin/llc
sudo ln -sf "$(which opt-18)" /usr/local/bin/opt
# 3. (optional) mingw — only to cross-compile Windows .exe files from Linux
sudo apt install gcc-mingw-w64-x86-64
# 4. Build the compiler
cd bidhuscript
go build -o bidhu ./cmd/bidhu
# 5. Run something
./bidhu run examples/classes.bidhuIf your distro's Go is too old, grab the official tarball:
curl -LO https://go.dev/dl/go1.22.5.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin # add to ~/.bashrcOption A — build & run natively on Windows (the real "run it on Windows" story):
# 1. Install Go from https://go.dev/dl (the .msi adds Go to PATH).
# Open a NEW terminal, then:
go version
# 2. Install LLVM (choose "Add LLVM to PATH" in the installer):
winget install LLVM.LLVM
# ...or download LLVM-<version>-win64.exe from the LLVM releases page.
clang --version
# 3. Build
cd bidhuscript
go build -o bidhu.exe ./cmd/bidhu
# 4. Run (native is the default target on Windows — no -target flag needed)
.\bidhu.exe run examples\classes.bidhu
.\bidhu.exe build examples\loops.bidhu # -> loops.exeThe C backend on Windows needs a
gcc/cconPATH(install MSYS2 or MinGW-w64 and set$env:CC = "gcc"). The default LLVM path is smoother on Windows — stick with it.
Option B — cross-compile a .exe from Linux (no Windows machine needed to build):
./bidhu build -target windows examples/classes.bidhu
file classes.exe # -> PE32+ executable (console) x86-64, MS WindowsIt links statically — copy the .exe to any 64-bit Windows box and run it.
bidhu build [flags] <file.bidhu> compile to an executable
bidhu run [flags] <file.bidhu> compile and immediately execute
bidhu ir <file.bidhu> print the three-address IR
bidhu llvm [flags] <file.bidhu> print the LLVM IR
bidhu debug <file.bidhu> print tokens, AST, and the semantic report
Flags for build / run:
-o <path> output path (default: source name without extension)
-target <t> native | windows (default native)
-backend <b> llvm | c (default llvm)
-opt run the 'opt' pass pipeline over the LLVM IR before codegen
-passes <p> opt pipeline (default "default<O2>")
-v verbose
./bidhu run examples/functions.bidhu # compile + execute
./bidhu build -opt -v examples/functions.bidhu # opt pipeline, keeps .opt.ll
./bidhu build -backend c examples/loops.bidhu # legacy C backend
./bidhu llvm examples/classes.bidhu # inspect the generated LLVM IRTry this: build with
-optand read the.opt.ll. Recursivefactorialgets turned into a loop with an accumulator phi-node by LLVM's tail-call elimination — running on IR the compiler emitted.
Don't want to install anything? bidhuscript.onrender.com runs BidhuScript live in your browser — edit, run, and inspect every stage of the pipeline (tokens, AST, IR, LLVM IR) with output streamed to a console.
source ─▶ lexer ─▶ parser ─▶ semantic analysis ─▶ IR (three-address code) ─▶ codegen
The IR is the pivot: one front-end feeds two backends, and the LLVM backend feeds two targets.
codegen_llvm— native backend (default). Emits opaque-pointer LLVM IR;clangbuilds the Linux ELF,llc+mingwcross-builds the Windows.exe.codegen_c— legacy backend, kept for comparison; renders the same IR as C and compiles it withcc.
bidhuscript/
├── cmd/bidhu/main.go CLI: build / run / ir / llvm / debug
├── internal/compiler/ the compiler — one package, split by phase
│ ├── token.go lexer.go source -> tokens
│ ├── ast*.go AST nodes (core · func · array · class)
│ ├── parser*.go Pratt parser (core · func · array · class)
│ ├── sema*.go scopes & type checking (core · func · array · class)
│ ├── ir.go irgen*.go three-address IR + lowering
│ ├── codegen_llvm.go IR -> LLVM IR (native backend)
│ ├── codegen_c.go IR -> C (legacy backend)
│ ├── build.go drivers: opt pipeline, clang, llc+mingw, cc
│ └── compiler.go debug.go orchestration + inspection helpers
└── examples/ loops · functions · arrays · classes
Around 6,000 lines of Go, no external dependencies. The per-phase file split
(*_func, *_array, *_class) means each language feature lives in a focused
handful of files rather than swelling the core.
BidhuScript — built from scratch in Go. Lex. Parse. Sema. IR. LLVM. Native.
SNAP · SKIP · SPAN · MY · ~> · LET · WHILE · IF / ELSE · PRINT · FORGE · BLUEPRINT


