一种专门用于编码 LLM 的微型实验语言
I am a programming language designed for machines to write and humans to read, and a secure runtime that hosts least-privilege services on an ordinary kernel. I require tests, I use unambiguous syntax, and my core is formally proved.
I transpile to C when you need native performance. NanoISA is my verified bytecode VM; it isolates dangerous external calls in a separate process. After 4.0 I added versioned service contracts, unforgeable capabilities, a POSIX fabric, and a trap journal. I do not claim a kernel. My core semantics are mechanically proved in Coq — type soundness, progress, determinism, and the big-step ↔ small-step equivalence proof are all complete and Admitted-free.
I published v5.0.0 with the language/runtime changes in my release contract. My planned v5.1.0 must complete the full remaining roadmap, including NanoISA-only compilation and matching compiler bytecode. Those architecture gates remain unfinished.
→ User Guide ← - I provide a tutorial with examples you can execute. This is where I recommend you begin.
Additional Resources:
-pg JSON, OS collectors, and a measured optimization loop.# Clone and build
git clone https://github.com/jordanhubbard/nanolang.git
cd nanolang
make build
# Create hello.nano
cat > hello.nano string {
return (+ "Hello, " name)
}
shadow greet {
assert (== (greet "World") "Hello, World")
}
fn main() -> int {
(println (greet "World"))
return 0
}
shadow main { assert true }
EOF
# Compile and run
./bin/nanoc hello.nano -o hello
./hello
BSD users: Use gmake instead of make.
Axiom declarations. The big-step ↔ small-step equivalence proof is complete and Admitted-free (including tuple value reconstruction in formal/Equivalence.v).free(). Heap allocations carry a small per-retain/release cost; pauses are deterministic. NanoVM also collects reference cycles (src/nanovm/heap_cycles.c); generated C already did.effect, perform, and handle. Side effects are explicit and composable.async fn and await to a CPS state machine at compile time.(+ a b) and infix a + b operators. My prefix calls are unambiguous.Ok(v) if v > 0 =>), or-patterns (| A | B =>), wildcard _, and exhaustiveness checking (warnings on incomplete matches).nano_virt run dependency shadows before root shadows by default, before publishing executable output. --root-shadows-only narrows that scope. Source-only C emission does not execute shadows. Deadlines supervise test processes; they are not security sandboxes. make test-language-claims and make test-native-shadows check these boundaries.let x = 42 without an annotation. Inference is local and bidirectional, not full Hindley-Milner — explicit annotations are required at function boundaries.f"Hello, {name}!" string interpolation and x |> f |> g pipeline syntax.docs/NSI.md, docs/NSI_FABRIC.md, docs/NSI_EFFECTS.md). I host services on an ordinary kernel. I do not claim a kernel, AES, or PKI. The journal is a tested library; it is not hooked into every VM trap in 4.5.docs/FORTH_2012.md, docs/FORTH_STANDARD_SYSTEM.md).bin/nano_emacs_worker. I do not claim GNU Emacs (docs/NANO_EMACS.md).editors/vscode/) with semantic tokens. Run vsce package to build a .vsix.…
I provide a virtual machine as an alternative to C transpilation.
# Compile to NanoISA bytecode and run
./bin/nano_virt hello.nano --run
# Compile to native binary (embeds VM + bytecode)
./bin/nano_virt hello.nano -o hello
# Emit raw .nvm bytecode, then execute separately
./bin/nano_virt hello.nano --emit-nvm -o hello.nvm
./bin/nano_vm hello.nvm
# Strip source-map debug info for production .nvm output
./bin/nano_virt hello.nano --emit-nvm --strip-debug -o hello.prod.nvm
# Run with FFI isolation (external calls in separate process)
./bin/nano_vm --isolate-ffi hello.nvm
Architecture:
spec/nanoisa.yaml.nano_cop) - I run external calls in a separate process. If they crash, I continue running.nano_vmd) - I can run as a persistent process to start faster.I have documented my complete architecture in docs/NANOISA.md.
My core semantics, which I call NanoCore, are mechanically proved in Coq. I declare no Axioms, and the equivalence proof (eval_to_multistep_gen in formal/Equivalence.v) is now complete and Admitted-free.
Admitted sub-cases.My proved subset includes integers, booleans, strings, arrays, records, variants, pattern matching, closures, recursion, and mutable variables. I explain this further in formal/README.md.
cd formal/ && make # Build all proofs (requires Rocq Prover >= 9.0)
I ship a Language Server (bin/nanolang-lsp) and a Debug Adapter (bin/nanolang-dap) for IDE integration.
make lsp # Build bin/nanolang-lsp (hover, go-to-definition, completion, diagnostics)
make dap # Build bin/nanolang-dap (breakpoints, step-through, variable inspection)
A VS Code extension is provided in editors/vscode/. It wires the LSP and DAP servers automatically.
# Compile through C to a native executable (default)
./bin/nanoc program.nano -o program
# Emit C source without invoking a native compiler
./bin/nanoc program.nano --target c -o program.c
# Experimental C-seed targets during the NanoISA translator migration
./bin/nanoc_c program.nano --target ptx -o program.ptx # CUDA PTX
./bin/nanoc_c program.nano --target riscv -o program.s # RISC-V assembly
# Export documentation from triple-slash comments
./bin/nanoc_c program.nano --doc-md -o program.md
My self-hosted driver accepts --target native and --target c; it rejects
unknown options, unsupported targets, missing option values, and multiple
input files. With --target c and no -o, I write a sibling .c file. Use
-- before an input path beginning with -. My generated C uses headers in
src and modules/std; link the runtime and module libraries used by the
program. Source emission alone does not prove that those dependencies link.
The profiling options in this section belong to my C-seed driver,
bin/nanoc_c; my self-hosted driver does not implement them yet.
When I compile with -pg, the native binary wraps main as _nl_run_with_profiling. On Linux I drive gprofng. On macOS I drive xctrace (full Xcode) and fall back to sample. I print JSON on stdout and, with --profile-output, to a file. That JSON is for an agent to read; it is not a PGO input.
--profile / --profile-runtime instrument generated C and can write .nano.prof. --pgo inlines from .nano.prof, not from -pg JSON.
I treat optimization as: profile a real workload, change source, run tests, profile again, keep only a demonstrated improvement. I document the JSON fields I actually emit, and the per-OS collectors, in docs/PERFORMANCE_MONITORING.md. The user-guide session is Performance Profiling.
My native interpreter uses libffi for fixed-arity foreign calls. I need its
development headers and library (libffi-dev on Debian/Ubuntu, libffi via
Homebrew when the macOS SDK package is unavailable). My Makefile reads
pkg-config libffi; LIBFFI_CFLAGS and LIBFFI_LIBS allow an explicit toolchain.
make build # Build my compiler (bin/nanoc)
make lsp # Build my language server (bin/nanolang-lsp)
make dap # Build my debugger (bin/nanolang-dap)
make vm # Build my VM backend (bin/nano_virt, bin/nano_vm, bin/nano_cop, bin/nano_vmd)
make test # Run my full test suite
make test-vm # Run
暂无开放 Issues,或尚未同步最近议题。