Skip to content

derekbsnider/madc

Repository files navigation

madc — Mad-C Programming Language

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 in docs/rules/. Cross-agent session flow lives in docs/agent-handoff.md.


Quick Start

# 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.mad

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

Multi-file Projects

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.


Language Features

  • Data types: int8_tint64_t, uint8_tuint64_t, float, double, char, std::string, array
  • Typed containers: vector<int>, map<string, int>, set<string> — also as std::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; and q, 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)
  • auto keyword: type inference for function pointer and lambda declarations
  • := short declaration: x := 42; with type inference from RHS
  • register keyword: 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 inclusion
  • using: using namespace std; or using std::cout; imports std names into the unqualified surface
  • #load: #load "libfoo.so" as foo; for dynamic library loading
  • dlopen/dlsym/dlcall: first-class dynamic linking
  • File I/O: ifstream/ofstream with open, 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)

Multi-Language Namespaces

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;
}

Available Namespaces

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.


Building

Requires:

  • g++ with C++11 support
  • asmjit v1.14 installed at /usr/local/ (see docs/build.md)
make -C src           # build bin/madc
make -C src clean     # clean objects
make -C src test      # run unit tests

Testing

# 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.mad

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


Documentation

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

Current Release

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.

Recent Releases

  • 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

Roadmap

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/

Architecture

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

About

Mad-C Programming Language (My jit-Assembled Dialect of C)

Resources

License

Stars

1 star

Watchers

1 watching

Forks

Packages

 
 
 

Contributors

Languages