My jit-Assembled Dialect of C — a C-like scripting language that JIT-compiles directly to x86-64 machine code using asmjit. No bytecode, no interpreter, no separate compilation step.
The "Mad" in Mad-C: mix functions from multiple programming languages in a single program.
Contributing / using an AI agent? Start with
AGENTS.md— it's the canonical briefing for every agent (Claude Code, Codex CLI, Gemini CLI, Copilot, Cursor, Aider, Windsurf). Rules are in.claude/rules/, with reasoning indocs/rules/. Cross-agent session flow lives indocs/agent-handoff.md.
# Build
make -C src
# Run a program
bin/madc tests/testint.mad
# Run with debug trace
bin/madc -v tests/testint.mad
# Build first, then run a command against the fresh binary
scripts/build_then.sh bin/madc tests/testint.madOptional storage backends are now being wired for configure-time feature detection. When Autotools is installed, the intended flow is:
autoreconf -fi
./configure --with-bdb --with-gdbm --with-qdbm --with-sqlite3
make--with-qdbm is intended for the Villa API layer, and each backend is
optional rather than required for a core madc build.
Single-file programs are the default. For larger projects, the convention is
a top-level file named after the application (e.g. smaug.mad, mygame.mad)
that #includes the rest in the right order, with int main() last:
// smaug.mad
#include "config.mad"
#include "mud.mad"
#include "tables.mad"
#include "comm.mad"
// ... other source files ...
#include "main.mad" // contains int main()Run the whole project with bin/madc smaug.mad. #include "file.mad" works
at the lexer level — filenames resolve relative to the including file, nested
includes are supported, and repeated includes are skipped within the same
compile.
- Data types:
int8_t–int64_t,uint8_t–uint64_t,float,double,char,std::string,array - Typed containers:
vector<int>,map<string, int>,set<string>— also asstd::vector<int>etc. - Streams:
std::cout,std::cerr,std::cin,std::stringstream,std::ifstream,std::ofstream,std::fstream - Control flow:
if/else,for,while,do/while,switch/case/default,rust::match - Range-based for:
for (string name : names) { ... }— works with array and vector - Ternary operator:
condition ? true_expr : false_expr - Functions: user-defined with return values and parameters
- Multiple return values:
return q, r;andq, r := divide(17, 5);(Go-style) - Function pointers:
auto fn = my_func; fn(args); - Lambdas:
[](int a, int b) { return a + b; }with[&]capture by reference defer: Go-style deferred execution at scope exit (LIFO order)autokeyword: type inference for function pointer and lambda declarations:=short declaration:x := 42;with type inference from RHSregisterkeyword: explicitly register-only variables (never written to memory)- User-defined structs:
struct Point { int x; int y; }; - Classes with methods:
class Counter { int count; void inc() { count = count + 1; } }; - Namespaces:
std::cout,madc::regex_match(),php::explode(),perl::grep(),python::title(),ruby::tr(),js::btoa(),rust::trim() - Dialect precedence:
prefer rust, php, c;or#pragma prefer rust, php, c - Regex:
madc::regex_match(),madc::regex_search(),madc::regex_replace() - Input:
std::cin >> name >> age;reads from stdin #include:#include "file.mad"for source inclusionusing:using namespace std;orusing std::cout;imports std names into the unqualified surface#load:#load "libfoo.so" as foo;for dynamic library loadingdlopen/dlsym/dlcall: first-class dynamic linking- File I/O:
ifstream/ofstreamwithopen,close,good,eof,getline - Subscript operator:
a[0],nums[i],ages["key"] - Escape sequences:
\n,\t,\r,\\,\",\0 - C23 coverage (early wave):
_Bool,0b...,_Static_assert/static_assert,alignof/_Alignof,typeof/typeof_unqual,nullptr, digit separators (1'000'000)
The signature feature of madc — use the best functions from each language:
#!/usr/bin/env madc
#include <iostream>
#include <string>
using namespace std;
int main()
{
// PHP-style string splitting and joining
string csv = "alice,bob,charlie";
string delim = ",";
array names;
php::explode(names, delim, csv);
php::sort(names);
string sorted;
php::implode(sorted, delim, names);
cout << sorted << endl; // alice,bob,charlie
// Perl-style regex grep
array matches;
string pat = "^a";
perl::grep(matches, pat, names); // apple, avocado
// Python-style string formatting
string title = "hello world";
python::title(title);
cout << title << endl; // Hello World
// Ruby-style string transforms
string s = "aabbccdd";
ruby::squeeze(s); // "abcd"
// JavaScript base64
string encoded;
js::btoa(encoded, s);
cout << encoded << endl; // YWJjZA==
// Regex
int m = madc::regex_match(s, "[a-d]+");
cout << m << endl; // 1
return 0;
}| Namespace | Functions | Focus |
|---|---|---|
php:: |
36 | String manipulation, array operations (explode, implode, sort) |
perl:: |
21 | chop/chomp, grep (regex), glob, split (regex)/join, array ops |
python:: |
16 | Title case, alignment (center/ljust/rjust/zfill), format |
ruby:: |
12 | squeeze, tr (transliterate), chars, rotate, compact |
js:: |
6 | Base64 (btoa/atob), URL encoding, parseInt, JSON stringify |
rust:: |
18 | trim/contains/replace, split/join, first/last/get, push/pop |
std:: |
9 + types | cin, cout, cerr, endl, getline, string conversions, for_each, stream/string types |
madc:: |
4 | array, regex_match, regex_search, regex_replace |
Plus #load for any shared library via dlopen.
Requires:
g++with C++11 support- asmjit v1.14 installed at
/usr/local/(seedocs/build.md)
make -C src # build bin/madc
make -C src clean # clean objects
make -C src test # run unit tests# Run unit + integration tests
make -C src fulltest
# Build first, then run one integration test through the batch runner
scripts/build_then.sh bash scripts/run_tests.sh tests/testint.madCurrent status: 452 integration tests pass (0 failing). 261 unit tests pass (80 datadef + 24 IR + 5 libmadc_error + 133 libmadc_program + 19 libmadc_value). GCC torture test parity: 1649/1685 (97.9%). (make -C src fulltest, scripts/run_gcc_testsuite.py)
(testcin.mad and testargv.mad are driven by scripts/run_tests.sh — it
feeds them stdin and argv respectively and asserts on their output.)
| Doc | Contents |
|---|---|
docs/usage.md |
Language reference, CLI flags |
docs/language/ns-php.md |
php:: namespace reference |
docs/language/ns-perl.md |
perl:: namespace reference |
docs/language/ns-python.md |
python:: namespace reference |
docs/language/ns-ruby.md |
ruby:: namespace reference |
docs/language/ns-js.md |
js:: namespace reference |
docs/language/ns-rust.md |
rust:: namespace reference |
docs/language/prefer.md |
Namespace precedence directive |
docs/language/modern/ |
Range-for, function pointers, lambdas, defer |
docs/language/switch.md |
Switch/case/default statement |
docs/language/rust-match.md |
rust::match (integer patterns, OR-arms, _ wildcard) |
docs/language/input-operator.md |
cin >> input operator |
docs/language/class-methods.md |
Class methods with this pointer |
docs/language/regex.md |
Regex functions |
docs/language/multiple-returns.md |
Go-style multiple return values |
docs/language/ternary-operator.md |
Ternary operator |
docs/build.md |
Build requirements, asmjit setup |
docs/plans/data-storage-federation.md |
Exploratory madcdat storage/federation design (madc::DataSource stays core, DataSet<T>, Relation<A,B>, automatic mapping, SQL/GQL front-ends, current --enable-madcdat build gate, future separate libmadcdat boundary) |
docs/architecture.md |
Compiler internals |
docs/testing.md |
Test guide |
docs/test-status.md |
Per-test results |
docs/agent-handoff.md |
Cross-agent hand-off workflow and source-of-truth rules |
AGENTS.md |
Agent briefing — project rules, architecture, multi-tool setup |
docs/rules/ |
Reasoning behind each rule in .claude/rules/ |
CHANGELOG.md |
Change history |
v0.21.1 (2026-05-25) — Const enforcement, access control, MIR backend plan. Top-level const and const ref enforcement, public/private/protected access control, automatic token position inheritance, and JIT IR architecture research leading to the decision to adopt MIR as the optimizing backend (replacing asmjit). 475 tests, 0 failures.
- v0.21.1 — Const enforcement, access control, token position, MIR backend architecture decision
- v0.21.0 — C++ class model: ctors/dtors, operators, refs, new/delete, inheritance, vtables, exceptions + unwinding
- v0.20.1 — Code cleanup Phase A: compiler file split, builtin dispatch table, --emit-function tool
- v0.20.0 — GCC parity 91.2% (1536/1685); std namespace cleanup, std::vector, overflow_p builtins
- v0.19.0 — GCC parity 89.3% (1505/1685); frame_address, stdio/string builtins
| Phase | Goal | Status |
|---|---|---|
| Phase 1 | Foundation: verbose flag, char literals, struct fix, register, doctest | Complete |
| Phase 2 | User-defined structs/classes, namespaces, #include, using | Complete |
| Phase 3 | php::/perl::/python::/ruby::/js:: namespaces, dlopen, MadArray | Complete |
| Phase 3.5 | Modern language features: range-for, function pointers, lambdas, defer, STL containers | Complete |
| Phase 3.5+ | switch, cin, class methods, regex, multi-return, ternary, namespace scoping | Complete |
| Phase 4 prep | C preprocessor, 40 embedded headers, struct alignment, sizeof, argc/argv | Complete |
| SMAUG A/B/C | Pointers, ->, casts, &, macros, unsigned/enum/static/typedef |
Complete |
| SMAUG D | va_list/<stdarg.h>, variadic helpers, for-loop fix |
Complete |
| SMAUG E | Fixed arrays, brace init, struct/array-of-struct init, chained member access, struct tm/timeval/fd_set, select() | Complete (v0.8.0) |
| SMAUG F | Language gaps surfaced by porting SMAUG 1.8. Port itself lives in MadSMAUG | Complete (v0.13.0 — playable end-to-end) |
| GCC Parity | GCC torture test suite compatibility | v0.20.0 — 1536/1685 (91.2%); std namespace cleanup, std::vector |
| C++ Model | Classes, inheritance, vtables, exceptions | v0.21.0 — ctors/dtors, operators, refs, new/delete, inheritance, vtables, SJLJ exceptions + unwinding |
| Phase 4 | libmadc.so embedding API |
In progress — §4.1 state split + structured diagnostics + engine-owned IO + full logging stack landed; §4.2 now ships madc::value and madc::error at include/libmadc/ |
Source (.mad file)
|
v src/lexer.cpp — tokenize source (#include, #load handled here)
|
v src/parser.cpp — build AST, namespace resolution, type registration
|
v src/compiler.cpp — walk AST, emit x86-64 via asmjit
|
v JIT execute — run machine code in-process
Namespace implementations: src/ns_php.cpp, src/ns_perl.cpp, src/ns_python.cpp, src/ns_ruby.cpp, src/ns_js.cpp, src/ns_stl.cpp