DEV Community

Ziad Mohsin
Ziad Mohsin

Posted on

Building MountX: A Self-Hosted Dynamic Language Compiling to C99

Every systems programmer eventually asks the question: what does it take to build a programming language from the ground up, make it self-hosted, and get real native performance without external runtimes?

Over the past months, I built and verified MountX—a dynamically-typed scripting language with a self-hosted tree-walking interpreter that emits pure, standard C99.

The project is fully open-source, passes a comprehensive 343-check regression suite, and runs between 5x and 20x faster than standard Python.

Here is an architectural walkthrough of how MountX works under the hood.


1. The 4-Layer Self-Hosting Architecture

MountX didn't start in C. It followed a structured bootstrap pipeline:

  1. Python Oracle (host/): An initial reference implementation written in Python to define language grammar, semantics, and standard behaviors.
  2. Self-Hosted Frontend (gate1/): The Lexer, Recursive Descent Parser, and Tree-Walking Interpreter were completely rewritten in MountX itself (lexer.mx, parser.mx, interp.mx).
  3. C99 Emitter & Substrate (gate2/g1/): The MountX-written interpreter is translated into C code (interp.emitted.c) and backed by a lightweight runtime substrate (mini.c, ~7000 lines).
  4. Native Executable: Compiled via GCC with zero external dependencies beyond libc and an embedded SQLite3 engine (sqlite3.c).
+-----------------------------------------------------------+
| 1. User Source Code (.mx)                                 |
+-----------------------------+-----------------------------+
                              |
                              v
+-----------------------------------------------------------+
| 2. Self-Hosted Frontend (MountX Lexer & Parser)          |
+-----------------------------+-----------------------------+
                              |
                              v
+-----------------------------------------------------------+
| 3. Emitted C + Native Substrate (mini.c + interp.emitted.c)|
+-----------------------------+-----------------------------+
                              |
                              v
+-----------------------------------------------------------+
| 4. Native Standalone Binary (mountx-native / mountx.exe)   |
+-----------------------------------------------------------+

2. Architectural Highlights & OptimizationsTree-walking interpreters are typically slow due to recursive calls and pointer chasing. MountX tackles this through several low-level optimizations:   A. Pre-compiled AOT Standard Library (Zero Disk I/O)Instead of reading 41 standard library files from disk on every importx statement:   An AOT generator script pre-compiles all .mx files in shared/stdlib/ into static C Abstract Syntax Tree (AST) structures inside stdlib_aot.c.   At runtime, mx_aot_get_prog(name) resolves imports directly from memory in microseconds.   If a module isn't built-in, the runtime gracefully falls back to traditional disk lookup.   B. String Interning with Direct CachingString comparisons (strcmp) across variable Lookups (env_get) and dictionary accesses add significant overhead ($O(N)$).   MountX canonicalizes all strings via an internal intern table (mx_intern) backed by a 4096-entry direct pointer cache (g_ptr_cache)[cite: 1].Once interned, string equality comparisons degrade to simple pointer equality checks (ptr_a == ptr_b) in $O(1)$ time[cite: 1].C. Smart Memory ManagementArena Allocators: Scoped memory arenas manage AST node lifecycles cleanly without fragmented heap calls[cite: 1].Local Buffer Optimization: Environments utilize small local buffers (small_b[8]) to avoid frequent malloc/free churn[cite: 1].Loop Environment Reuse: Loops (while, loop, forin) reuse environment frames across iterations, clearing pointers instead of reallocating memory[cite: 1].3. Built-in Networking & Database SupportMountX provides direct native bindings to low-level primitives:Native TCP Sockets: Core networking primitives (tcp_listen, tcp_accept, tcp_send, tcp_recv, tcp_close) allow building HTTP services without external packages[cite: 1]:



Enter fullscreen mode Exit fullscreen mode

importx socket

let server = newx socket.TcpServer(8080, "0.0.0.0")
let conn = server.accept()
let req = socket.recv(conn, 4096)
socket.send(conn, "HTTP/1.1 200 OK\r\n\r\nHello from MountX!")
socket.close(conn)
server.close()



Embedded SQLite: Fully integrated SQLite3 query building and storage out of the box[cite: 1].4. Testing & VerificationThe runtime is continuously tested against a strict regression suite (host/fbtest.mx) spanning 343 assertions:   Covers built-ins, collections, math, regex, exception handling (setjmp/longjmp), TCP networking, and SQLite queries.   The native binary passes 100% of all 343 checks cleanly[cite: 3].5. Getting StartedPre-built binaries are available for Linux and Windows, or you can build it from source with GCC[cite: 1].Quick Run (Linux):

# Clone the repository
git clone [https://github.com/mountxlang-eng/mountxlang.git](https://github.com/mountxlang-eng/mountxlang.git)
cd mountxlang

# Download pre-built native binary or build with gcc
./mountx-native host/fbtest.mx
GitHub Repository: github.com/mountxlang-eng/mountxlang

Releases & Binaries: Check the Releases tab for pre-compiled mountx-native and mountx.exe.

I would love to get thoughts, critiques, and feedback from the community regarding the C substrate design and the tree-walking execution pipeline!

Enter fullscreen mode Exit fullscreen mode

Top comments (0)