-
Notifications
You must be signed in to change notification settings - Fork 0
Why I created madc
madc was created by Derek Snider, a programmer with more than 40 years of experience writing software.
I started programming in 1982, when I was ten years old, beginning with BASIC. From there, my path moved through 6809 assembly, x86 assembly, Pascal, Turbo Pascal, Borland Pascal / Delphi, C, C++, PHP, Perl, JavaScript, TypeScript, and Python.
Of all those languages, C and C++ have been the longest and deepest part of my programming life.
That matters, because madc is not a C-flavoured scripting language created by someone looking at native code from the outside. It comes from decades of working with real C and C++ native code, pointers, memory, libc, headers, compilation, linking, performance, backend systems, and the practical realities of writing efficient, maintainable software.
It also comes from understanding why C++ and scripting languages became so important: safer types, better abstractions, standard containers, strings, references, more expressive syntax, and a gradual move away from unnecessary raw pointer work.
madc is not about freezing programming in the 1970s.
It is about keeping the native power of C and C++, while making common work safer, faster, and more convenient.
Every language gives you something.
BASIC gave me immediacy: type something, run it, see what happens.
Assembly taught me that every abstraction eventually comes down to real machine code.
Pascal, Turbo Pascal, and Delphi showed me the value of structure, clarity, and productive native tooling. Delphi in particular was an early proof that a native compiler could have the immediacy of a scripting workflow — fast compilation, a rich standard library, and a tight edit-run loop. That idea stuck with me.
C gave me direct control.
C++ gave me abstraction, stronger types, constructors, destructors, containers, references, and a safer way to write native code without fully leaving the machine behind.
PHP showed me the value of a broad, practical standard library and a fast edit-run workflow.
Perl, JavaScript, TypeScript, and Python added lessons about expressiveness, convenience, and how different language communities solve everyday problems.
After enough years, you notice the same pattern again and again: every language has features you miss when you move to another one.
Modern development often adds too much ceremony.
Too often, writing a small useful program means installing a runtime, installing a package manager, creating a project structure, configuring dependencies, choosing a build system, pulling in libraries, and fighting paths before you can do anything meaningful.
Sometimes that complexity is necessary.
But sometimes you just want to write a native program, run it, and move on.
A hello-world program should not require a ceremony. Neither should the next useful program after hello world.
C and C++ have never really gone away because they solve problems that never go away.
They are direct. They are efficient. They work with real memory, real libraries, real operating systems, and real binaries. They let you build close to the machine when that matters, while still giving you room to create safer and higher-level abstractions when the program grows.
That balance matters.
I did not create madc because I wanted to make C less real. I created madc because I wanted to make native C-family development more immediate — real C/C++-family native code at the core, extended where useful, and improving rapidly.
The practical test case for madc has been SMAUG 1.8 — a MUD (Multi-User Dungeon) engine written in C, roughly 158,000 lines of code across hundreds of source files.
SMAUG is code I know well. I wrote it in the 1990s, building on the Merc/Diku MUD lineage, and it went on to become one of the most widely used MUD codebases in the online gaming community. Decades of MUD development — real-time networking, game logic, complex data structures, thousands of simultaneous users — taught me what systems-level C code actually looks like in production.
That made SMAUG the ideal test case. It uses pointers extensively, has complex struct hierarchies, relies on libc and POSIX APIs, and exercises most of the patterns you find in real-world C: variadic functions, preprocessor macros, fixed arrays, struct-of-struct layouts, function pointers, and more.
madc now compiles and runs SMAUG end-to-end — both JIT and as a native executable. Getting there drove most of madc's C compatibility work: struct alignment, pointer arithmetic, va_list, K&R function support, and dozens of other features that only surface when you try to compile real legacy code.
If it can run SMAUG, it can handle a lot of real-world C.
I think of madc as a Swiss Army Knife for native C-family development.
It can run C-family code with script-like immediacy. It can build native executables. It can be embedded as a compiler, JIT, and runtime inside C/C++ applications. Its features can also be reused directly in native C/C++ programs.
That combination is the point.
madc brings together real native code generation, direct libc usage, object caching, embedded headers, C/C++-style conveniences, multi-language-inspired helper namespaces, and reusable C/C++ runtime features.
It is not trying to replace every specialized compiler, build system, package manager, scripting language, or standard library.
But sometimes you do not need an entire workshop.
Sometimes you need a practical tool you can reach for quickly.
That is the spirit of madc: native code, real C-family programming, script-like workflow, and modern convenience in one self-contained toolkit.
madc is open source because tools like this should be inspectable, hackable, testable, and improvable.
A compiler should not be magic.
If madc is useful, people should be able to see how it works. If it is wrong, people should be able to prove it. If it is missing something, people should be able to add it.
madc is still growing. Fuller C compatibility, broader C23 support, better diagnostics, stronger tests, deeper library coverage, and wider platform support are all part of the road ahead.
But the goal is clear:
real native code, C-family power, script-like workflow, modern convenience.
C, unbound.