-
Notifications
You must be signed in to change notification settings - Fork 0
Home
(My Advanced Dialect of C)
Validated on x86-64 Linux today. The MIR backend also targets aarch64 (including Apple Silicon), ppc64le, s390x, and riscv64 — more platforms are on the roadmap as ports, not rewrites.
madc is real C with the workflow of a scripting language.
Write C. Run it like a script. Ship it as a native Linux ELF executable. Embed it as a runtime. Or bring madc's built-in features directly into your own C/C++ programs.
No Makefile. No toolchain ceremony. No VM. No bytecode. No fake runtime.
madc compiles C-family source directly to native machine code, uses libc directly, caches compiled objects, and can produce real Linux binaries.
| Use madc to... | Command / API | What happens |
|---|---|---|
| Run it | madc program.mad |
JIT-compiles directly to native machine code and runs immediately. No bytecode, no interpreter. |
| Ship it | madc -o program program.mad |
Generates a native Linux ELF executable. Real binaries, real performance. |
| Embed it | libmadc |
Host madc as a compiler, JIT, and runtime inside your own C/C++ application. |
| Reuse it | madc headers, namespaces, and runtime helpers | Bring madc features directly into your own native C/C++ programs. |
Compiled objects are cached, so the first run is fast and repeat runs can skip unnecessary recompilation.
Getting Started →
Native Executables →
Embedding Guide →
madc is not a C-flavoured scripting language, bytecode VM, or toy interpreter.
It compiles to real native machine code. It uses libc directly. It supports ordinary C-style programs, pointers, structs, functions, headers, preprocessor directives, and native linking.
madc compiles real C. It supports ordinary C-style programs end-to-end — pointers, structs, functions, headers, preprocessor directives, native linking — and tracks the GCC torture suite closely. C23 coverage is rolling in and expanding.
K&R C was real C. ANSI C was real C. Embedded C compilers are real C. TinyCC is real C.
madc belongs on that spectrum:
real C at the core, extended where useful, and improving rapidly.
No Makefile. No include paths to configure. No separate compile step.
madc file.mad
One file. One command. Native execution.
madc starts with familiar C syntax and real native code generation, then adds practical conveniences where they help:
-
cout,cin,cerr -
string,stringstream -
vector<T>,map<K,V>,set<T> - classes with methods
- lambdas
defer- multiple return values
-
:=type inference - range-based
for - function pointers
- embedded standard headers
Use ordinary C when you want it. Reach for modern conveniences when they make the program clearer.
madc is not only a command-line compiler. You can embed libmadc inside your own C/C++ applications — host a full C-family compiler, JIT, and runtime, or evaluate expressions on the fly — each one compiled to native code, not interpreted:
#include <libmadc/api.h>
madc::program pgm;
pgm.exec_file("script.mad");
int64_t result;
pgm.eval("2 + 2", result);
madc is aimed at real C compatibility, native execution, and practical systems-level use.
It is not pretending to be C. It is a real compiler that emits native machine code, uses libc directly, and can compile real C codebases end-to-end.
Your C code just works:
#include <stdio.h>
int main() {
printf("hello, world\n");
return 0;
}
Run it directly:
$ madc hello.mad
hello, world
Or build a native executable:
$ madc -o hello hello.mad
$ ./hello
hello, world
Use modern conveniences alongside ordinary C:
#include <stdio.h>
int main() {
FILE *f = fopen("data.txt", "r");
defer { fclose(f); };
auto count := 0;
char line[256];
while (fgets(line, sizeof line, f)) {
count++;
}
printf("read %d lines\n", count);
return 0;
}
No Makefile. No project setup. madc count.mad and you're done.
- JIT compilation to native machine code via MIR — runs at native speed (x86-64 today; the backend also targets aarch64, ppc64le, s390x, riscv64)
- Native executable generation — produce standalone Linux ELF binaries (with
-gDWARF debug info), directly — no external assembler or linker - Standard C output —
--emit=c11renders any madc/C++ program as portable C11 source for any C toolchain -
Script mode — no
main()needed; top-level statements run like a script (#!/usr/bin/env madcshebang supported) - OBJ caching — compiled objects are cached; repeat runs skip recompilation
- Direct libc usage
- 40+ embedded headers —
<stdio.h>,<stdlib.h>,<math.h>,<string.h>,<unistd.h>, and more — with auto-header inclusion: common symbols likeprintfresolve without any#include -
C++ support — classes with multiple/virtual inheritance (Itanium ABI, RTTI,
dynamic_cast), virtual functions, operator overloading (incl.<=>), templates with real instantiation, exceptions, lambdas, references, RAII — plus real libstdc++ interop:cout/cin/cerr,string,stringstream,vector<T>,map<K,V>,set<T> - Modern features — lambdas,
defer, multiple return values,:=inference, range-basedfor, function pointers - C23 early coverage —
_Bool,0bbinary literals,static_assert,typeof,nullptr, digit separators - Preprocessor —
#define,#ifdef,#include,#pragma, plus#load "libfoo.so"for dynamic libraries - Multi-language namespaces — 100+ helper functions inspired by PHP, Perl, Python, Ruby, JavaScript, and Rust (see below)
- Embeddable
libmadcAPI with C++ support and C shims - Reusable runtime helpers for native C/C++ programs
- Self-contained — no external dependencies at runtime beyond libc
madc also ships with something less conventional: a set of helper namespaces that bring familiar functions from other languages into native C/C++ code. These are entirely optional — ignore them and you have a plain C compiler. Reach for them when they make a program clearer.
Examples:
-
php::explode(),php::implode(),php::sort() -
perl::grep(),perl::chomp(),perl::split() -
python::title(),python::ljust(),python::format() -
ruby::squeeze(),ruby::tr(),ruby::chars() -
js::btoa(),js::encodeURIComponent() -
rust::trim(),rust::contains(),rust::split()
All 100+ helpers compile to native code like the rest of madc — no scripting layer, no runtime cost beyond the function call itself.
#include <iostream>
int main()
{
std::string csv = "alice,bob,charlie";
std::string delim = ",";
madc::array names;
php::explode(names, delim, csv);
php::sort(names);
std::string sorted;
php::implode(sorted, delim, names);
std::cout << sorted << std::endl;
std::string title = "hello world";
python::title(title);
std::cout << title << std::endl;
madc::array matches;
std::string pat = "^a";
perl::grep(matches, pat, names);
std::string s = "aabbccdd";
ruby::squeeze(s);
std::cout << s << std::endl;
std::string encoded;
js::btoa(encoded, s);
std::cout << encoded << std::endl;
return 0;
}
No imports to install. No package manager. It is all built in.
The same helpers are available outside the madc compiler. Link against libmadc and use php::explode(), perl::grep(), python::title(), and the rest directly in any C++ program:
#include <libmadc/namespaces.h>
std::string csv = "alice,bob,charlie";
madc::array names;
php::explode(names, ",", csv);
php::sort(names);
That makes madc both a compiler and a native C/C++ toolkit.
madc is for developers who like C, but want a faster workflow.
Use it when you want to:
- write small native utilities without setting up a project
- prototype systems code quickly
- build C programs that run with script-like immediacy
- ship a native Linux executable
- embed a C-family compiler, JIT, and runtime inside a C/C++ application
- reuse madc's helper namespaces and runtime features directly in native C/C++ programs
- use familiar helpers from PHP, Python, Perl, Ruby, JavaScript, and Rust
- experiment with modern C extensions without leaving native code behind
madc is not trying to replace GCC, Clang, or every production C toolchain.
Use GCC or Clang when you need mature, battle-tested, fully standards-focused compilation across large production codebases and many platforms.
Use madc when you want C with immediacy:
madc program.mad
madc is also not cross-platform yet — it is validated only on x86-64 Linux so far. Windows, macOS, and ARM64 are not currently supported, though the MIR backend already targets aarch64, ppc64le, s390x, and riscv64 — new architectures are ports, not rewrites.
And madc is not Python, Lua, JavaScript, or a scripting VM. It borrows the convenience of scripting workflows, but the result is native code.
- Installation — build from source, dependencies, verifying your setup
- Getting Started — overview of the basic workflow
- Your First Program — from hello world to something real
-
Multi-file Projects —
--projectbuilds fromcompile_commands.json;#includecomposition for small projects -
Script Mode — main-less scripts, shebang,
madc::sys
- Data Types — integers, floats, strings, arrays, containers
-
Control Flow — if/else, for, while, switch,
rust::match - Functions — declarations, multiple returns, function pointers, lambdas
- Structs & Classes — user-defined types, methods, member access
- C++ Support — inheritance, templates, exceptions, operator overloading, libstdc++ interop
- Strings & I/O — string operations, cout/cin, file streams
- Pointers & Arrays — C-style pointers, fixed arrays, subscripts
-
Modern Features — defer, range-for,
:=, auto, ternary
- Language-namespaces — how multi-language namespaces work
| Namespace | Focus |
|---|---|
| php:: | String manipulation, array operations |
| perl:: | chop/chomp, regex grep, split/join |
| python:: | Title case, alignment, format |
| ruby:: | squeeze, tr, chars, rotate |
| js:: | Base64, URL encoding, JSON |
| rust:: | trim, contains, replace, split/join |
-
Preprocessor —
#define,#ifdef,#include,#load,#pragma - Embedded Headers — built-in standard and POSIX headers
- C23 Features — early C23 standard coverage
- Regex — match, search, replace
- GCC Compatibility — torture test parity, what works, what's next
- Native Executables — ELF generation, AOT compilation
- Embedding Guide — libmadc API, hosting madc in your programs
- CLI Reference — command-line flags and usage
- Namespace Reference — consolidated function lookup
- Changelog — release history and notable changes
madc is under active development, with GCC torture test parity approaching 100% on the development branch. See the Changelog for the latest release and the GCC Compatibility page for current test status.
The goal is simple:
real C, native code, script-like workflow, modern convenience.
C, unbound.
madc's code generation is built on MIR by Vladimir Makarov — a lightweight JIT compiler infrastructure whose c2mir C front end madc's IR feeds directly. madc uses its own MIR fork, released in lockstep with madc (see the repo's MIR_VERSION).
madc's original backend was built on asmjit by Petr Kobalicek — an outstanding JIT assembler library that carried the project through its first year.
madc's unit tests are written with doctest by Viktor Kirilov — a fast single-header C++ testing framework, shipped in-tree.
GitHub Repository · Report an Issue · License: MPL 2.0