v0.92.0 — std::format built in, zero-include cout << value, UFCS, print_r over any type
madc v0.92.0
Binaries: download the packages for this feature line from v0.92.1 — the binary-shipping patch (Linux deb/rpm, Windows zip, macOS tarballs).
Everything since v0.82.0 — ten releases of language features, with the
madc dialect growing a modern, zero-ceremony surface.
Features
std::format, std::print, std::println — built into madc
The C++23 formatting library works in any madc script with zero
includes and zero header parsing — no <format>, no <print>,
nothing to set up:
std::println("x={} y={:.3f} hex={:#x}", x, y, 255);
std::string s = std::format("{:>8}|{:08.2f}", name, price);The compiler itself is the implementation: format strings are checked
at compile time (a bad {:q} or a missing argument is a compile
error, exactly as C++23 requires), and the output is byte-for-byte
identical to real libstdc++ std::format — verified against 1,430
generated oracle cases covering shortest-round-trip floats, hex floats,
alignment, fill, precision, and every presentation type. madc's own
var/value arguments format as whatever they currently hold.
Streaming madc values: cout << value, no includes needed
A var streams exactly as its contained type would — std::hex,
setprecision, boolalpha all apply as if you had written the plain
int / double / bool:
var test = "hello";
cout << test << endl; // just works — no #include at allThe <iomanip> manipulators (setprecision, setw, setfill) work
too, on plain types and streamed values alike.
UFCS — uniform function call syntax
In the madc dialect, x.f(y) and f(x, y) are interchangeable
spellings, in both directions: a free function can be called like a
method, and a method like a free function. Calls chain naturally
(n.twice().inc().twice()), any receiver type participates, and the
fallback only fires where the code was already an error — strict
--std=c* / --std=c++* modes are byte-identical to before.
FILE *fp = fopen("data.txt", "r");
fp->fclose(); // fclose(fp) — the same operator
count(m, key); // m.count(key)php::print_r and php::var_dump over ANY type
Dump anything — structs, nested aggregates, pointers (cycle-safe, with
PHP's *RECURSION* marker), fixed arrays, std::vector, std::map,
std::set, std::list, std::string, enums, and madc values — and
the output matches php-cli to the byte. The compiler generates the
dumper for each concrete type, so a program that never dumps pays
nothing.
Range-for, grown up
for (auto &kv : m) over a std::map, for (auto x : v) over vectors
and raw arrays — the element type is deduced at parse time from the
container itself. Over a madc array, for (value v : a) gives you the
raw carrier element, kind and all, while for (string s : a) keeps the
string view.
The value carrier matured
- Real constructors:
value v(7);,value(3.5)temporaries — every
kind, correctly typed. .count()/.size()answer the owner semantics: containers count
elements, text counts length, and a non-countable kind throws a real,
catchable madc exception instead of silently answering 0.php::array_pushis one overloaded name matching PHP exactly —
push a string, int, float, bool, or another array, and get PHP's
new-element-count return.
Headerless C that behaves like gcc
An undeclared C library call now gets its real signature: strcmp
returns a real int (comparisons work), floor returns through the
right register, floorf(3.9f) is 3.0 — with the full C99 math family's
argument and return shapes carried in one signature table, measured
against gcc -O0. Legal C89 without includes no longer returns garbage
with exit 0.
madc --version
madc --version / -V, kept in lockstep with the MADC_VERSION macro
and madc::sys.version.
Fixes and internals
- Front end: a cast binds a paren-less sizeof operand
((long long)sizeof buf— valid C89, previously rejected);for (string s("ab"); ...)parses; range-for binds its range before
declaring the element (a silent shadowing divergence from g++, one
shape of which compiled and read garbage). - Overload resolution: numeric ranking is graded by type domain, so a
floatargument selects thedoubleoverload instead of truncating;
plain structs (the<iomanip>manipulator kind) resolve through free
operator templates like classes do. - Codegen/runtime: loop-header temporaries are constructed and
destroyed per iteration in their own scope; external-constructor
prototypes type scalar parameters correctly (adoubleno longer
marshalled through an integer register); one generic c2mir fix — a
statement expression's value is its last statement as written, not
a scope-exit cleanup call appended after it (MIR's own C test suite
at exact baseline). - The forest pack (madc's pre-parsed standard-library store) is gated
against silent degradation across all three platform packs; the
gate's first run found and fixed along doublemember vanishing at
bind time. - One libstdc++ 13 defect found while pinning the format oracle, and
excluded with evidence:std::format("{:#.0f}", DBL_MAX)returns a
corrupt buffer (leading NUL, shifted digits). madc keeps the correct
output.
Validation
One merge-wave battery on the release commit: 1104/0 integration tests
(9 skipped), 1,113 tests compiled with zero warnings, native EXE and
OBJ lanes 1063/0, packed suite 1104/0, headerless (no headers on disk
anywhere) 1077/0, plus 4,334 formatting-engine assertions against the
generated libstdc++ oracle.