πŸ€” Why MELP?

Every language solves a problem. The problem MELP solves: safety without complexity.

1. The Scope Model β€” No GC, No Borrow Checker, Memory Safe

In MELP every variable lives inside a scope. When the scope closes, its memory is cleaned up automatically.

scope account
    numeric balance = 1000
    scope operations
        numeric function withdraw(numeric amount)
            if amount > balance then return 0 end if
            balance = balance - amount
            return 1
        end function
        return withdraw(200)
    end scope
end scope
-- balance was cleaned up automatically here

Rust: borrowing rules enforced by the borrow checker.
Go: memory managed by a GC, with pause times.
MELP: scope = lifetime. Neither a GC nor a borrow checker.

Honesty line: the mechanism is valgrind-proven on the fronts it covers today (big numbers, printed strings). General string temporaries are not yet under custody and do leak β€” a known, addressed limit. And the moment you write external, the guarantee ends: that is MELP's equivalent of Rust's unsafe.

2. Self-Hosting β€” The Compiler Is Written in MELP

# The MELP compiler can compile itself:
melp_compiler < main.mlp > stage.ll
clang stage.ll -o new_compiler
./new_compiler < main.mlp > stage2.ll
diff stage.ll stage2.ll  # β†’ empty (proof of self-hosting)

This is evidence of the language's maturity and reliability. A bootstrap test exists in every self-hosting language; MELP's difference is that this chain is a mandatory gate on every single change. If the two outputs are not bit-for-bit identical, the change is reverted β€” no exceptions.

3. Silent Wrongness β€” Software's Most Dangerous State

The most dangerous state of software is not the state where it crashes. It is the state where it quietly returns the wrong answer: the billion-dollar mistake (null), swallowed exceptions, broken pipelines that exit 0, benchmark loops that -O2 deleted.

MELP's answer is a rule applied throughout the compiler: nothing is left to runtime guesswork. Where another language would pick a plausible interpretation and continue, MELP stops with an explicit error code. Using a decimal without its import is a compile error, not a silent misreading. A missing implementation must fail loudly rather than exit 0.

This discipline is enforced against ourselves as much as against user code: a green result without evidence is treated as more dangerous than a red one.

4. Objects Without OOP β€” No Inheritance, Composition Instead

struct Point
    numeric x
    numeric y
end struct
-- point.move(1; 2) β†’ move_point(point; 1; 2)
-- MELP: composition > inheritance

No classes, no inheritance, no virtual methods. Struct + function. Simpler, and faster.

5. The debug Block β€” A Conversation With the IDE at Design Time

debug
    external ide
    ide_inspect(members_count)
    if members_count > 10000 then
        ide_warning("Critical level: " & str(members_count))
        ide_highlight(1442)
    end if
end debug

Stripped at zero cost in release builds. In debug builds, it talks to the IDE. Above all it is a letter to the future: a comment may go unread, but a debug block runs β€” when the world outgrows the assumption, the program stops and makes someone read it.

6. Performance β€” The Same League as C

MELP does not claim to be "faster than C". Its goal is C-league performance without surprises. MELP is compiled with LLVM/clang; the fairest comparison is C compiled with the same backend (clang -O2) β€” one variable, the language. The numbers follow a protocol (5 runs, best value; Intel i7-10750H).

TestMELPC (clang -O2)Status
fib(40)234 ms232 msPractically identical β€” same LLVM (gcc-C: 171 ms)
string concat 100K9 ms~1 msO(n) parity; C leads on the constant factor

fib(40): MELP is also faster than Rust (277 ms) and Go (429 ms). But the headline is not "we beat C" β€” MELP is in the same league as C compiled with its own backend, without surprises.

Note: side-effect-free loops such as "loop 100M" are folded away by LLVM at compile time (induction variable elimination) β€” that is an indicator of optimisability, not a runtime speed measurement, and it is excluded from the speed table. That MELP's IR is clean enough for LLVM to fold is a good sign, but it does not mean "we beat C".

MELP vs Other Languages

PropertyMELPRustGoZig
Memory modelScopeBorrow checkerGCManual
Self-hostingβœ…βœ…βœ…βœ…
Data racesβœ… structurally impossibleβœ… borrow checker❌❌
debug block (letter to the future)βœ…βŒβŒβŒ
Freeze / quarantineπŸ”¬ scope freezing*❌❌❌
Without OOPβœ…TraitsInterfaces❌
Learning curveLowHighMediumMedium
Supply chain β€” package ecosystemβœ… none existscargomodulesβ€”
Supply chain β€” build chain (xz class)❌ no answer❌❌❌
Toolchain maturity❌ youngβœ…βœ…πŸ”¬

* Freeze works today through a host API (freezing and thawing scopes, selectively); full integration into the language syntax is in development β€” hence the πŸ”¬ (partial) stamp.

The rows we lose stay in the table. A comparison that only lists your wins is an advertisement, not a comparison. Note the build-chain row: nobody has an answer there β€” MELP included. Having no package ecosystem removes one class of this risk and leaves the other untouched, and MELP being closed source does not help: it removes independent audit, so it lowers verifiability rather than raising it.

Where the Claim Is Aimed

Rust is an enormous competitor in the memory-safety market. But in the market of "let the intent of this code still run forty years from now" and "let a wrong answer never stay silent", there is almost no competition at all. That is where a small language's smartest positioning lies β€” and it is where MELP aims.

What we have not solved stays on the front page: the honest map lists supply-chain security and toolchain comfort as ❌, because a claim without an honesty line does not get published.

MELP β€” Safety without complexity. πŸš€