myr the compiler
Build, run, cross-compile, or launch the debugger in one command. Pass the source name without the extension: myr hello -r -t linux64 -opt full.
Myrissa is a Pascal-family systems language whose compiler owns the whole stack. It parses, optimizes, encodes x86_64, writes PE and ELF images, links archives and injects its own runtime. One executable. No LLVM, no Clang, no external linker.
module exe hello; begin println("Hello, Myrissa!"); end. > myr hello -r Hello, Myrissa!
00000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 00000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00000030 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00000080 50 45 00 00 64 86 05 00 00 00 00 00 00 00 00 00
Exact-width types, records that lay out like C structs, managed strings, sets as bitmasks, real exceptions, and a module system that keeps every symbol qualified. Calling C is a declaration, not a binding layer.
module exe shapes; type Color = choices(red, green, blue = 5, alpha); Point = record x: float64; y: float64; end; Shape = record origin: Point; color: Color; name: string; end; routine hsv_to_rgb(const h: float32; var r: uint8; var g: uint8; var b: uint8); begin r := uint8(h * 255.0); g := uint8((1.0 - h) * 255.0); b := 128; end; begin var s: Shape = Shape(origin: Point(x: 10.0, y: 20.0), color: Color.blue, name: "box"); var r: uint8; var g: uint8; var b: uint8; hsv_to_rgb(0.25, r, g, b); println("%s at (%f, %f) rgb(%d, %d, %d)", s.name, s.origin.x, s.origin.y, r, g, b); end.
module exe interop; // the same routine, bound to the C runtime of each target @ifdef TARGET_WIN64 routine clink myabs(const n: int32): int32; external "msvcrt.dll" name "abs"; @elseif TARGET_LINUX64 routine clink myabs(const n: int32): int32; external "libc.so.6" name "abs"; @endif // a Windows-only system DLL @ifdef TARGET_WIN64 routine clink GetTick(): uint64; external "kernel32" name "GetTickCount64"; @endif // a generated binding: import SDL3 and call it qualified import SDL3; begin println("abs(-42) = %d", myabs(-42)); @ifdef TARGET_WIN64 println("tick = %llu", GetTick()); @endif SDL3.SDL_Init(SDL3.SDL_INIT_VIDEO); SDL3.SDL_Quit(); end.
module dll mathlib; public var call_count: int32 = 0; public routine clink fast_add(const a: int32; const b: int32): int32; begin call_count += 1; return a + b; end; initialize println("mathlib loaded"); end; finalize println("mathlib unloaded after %d calls", call_count); end; end.
module lib and the same source becomes a static library. Both build for win64 and linux64.routine safe_div(const a: int32; const b: int32): int32; begin guard return a div b; // hardware divide-by-zero is caught except println("caught %s (code %lld)", cstr(excmsg()), exccode()); return -1; finally println("always runs"); end; end; routine load(const path: string); begin if len(path) = 0 then throwcode(404, "empty path"); // propagates across routines, modules and static libs end; end;
module exe mathlib; @unittestmode on; routine add(const a: int32; const b: int32): int32; begin return a + b; end; end. test "add returns the sum" begin asserteq(5, add(2, 3)); asserteq(-2, add(-5, 3)); end; test "float tolerance" begin asserteqf(3.14, 22.0 / 7.0, 0.01); end;
Every stage is Delphi code in the same repository. The output of the last one is the binary.
Tokenizes .myr source. Keywords and the sixteen primitive types are registered, not hardcoded.
Recursive descent for declarations and statements, Pratt for expressions. Produces a complete AST.
Resolves every type, symbol, cross-module reference and directive once, and records it on the AST. Later stages read; they never reconstruct.
Walks the enriched AST and drives the backend's fluent IR builder. All language-specific lowering lives here.
Constant propagation and folding, copy propagation, common subexpression elimination, dead code elimination, unreferenced-function removal. Level-gated: none, basic, full.
Linear-scan register allocation and direct byte encoding, REX, ModRM, SIB, SSE2. Win64 and System V ABIs chosen per target. No assembler pass.
PE with .pdata unwind info, version resources and icons. ELF. COFF and ELF object and archive writers. A linker that reads foreign archives.
Injected into every module through the same IR API a frontend uses. Strings, arrays, exceptions, heap tracking, tests.
or hello, hello.dll, libhello.so, hello.lib, libhello.a
int8 to uint64, float32, float64, char, wchar, boolean, pointer. Every one maps to a C type with no conversion.
string is UTF-8 and wstring is UTF-16, both refcounted. cstr() and wstr() borrow a raw pointer for C calls without a copy.
Inheritance, packed, align(n), overlays (unions), anonymous overlays for tagged unions, bit fields, and named record literals.
One keyword for functions and procedures. const and var parameters, local sections, first-class routine types, overloading via cpplink, forward declarations, variadics with varargs.
if, while, for and downto, repeat, match with ranges and lists, break, continue, compound assignment.
Stack bitmasks of up to 64 elements. Union, intersection, difference and membership are single instructions.
exe, dll, lib, unit. Private by default, public to export, always qualified on import, initialize and finalize on every kind.
@target, @optimize, @subsystem, @addverinfo, @exeicon, @copydll, @ifdef family with MYRISSA, TARGET_WIN64, TARGET_LINUX64, DEBUG, RELEASE.
Cross-target parity is a hard invariant. The compliance gate runs each suite on both targets at all three levels and requires zero assertion failures and zero heap leaks before anything ships.
| Module | win64 | linux64 | Proven by |
|---|---|---|---|
| exe | name.exe | name | EXE and UNITTEST suites |
| dll | name.dll | name.so | DLL suite, two DLLs in one process |
| lib | name.lib | name.a | LIB and LINK suites, lib to lib, SEH across libs, foreign MSVC and MinGW archives |
| unit | compiled inline into the importer | UNIT suite, cross-module symbols and exceptions | |
myr the compilerBuild, run, cross-compile, or launch the debugger in one command. Pass the source name without the extension: myr hello -r -t linux64 -opt full.
myr cimport bindings from C headersA .mys script names the header, include paths, exclusions, renames and per-target DLLs; CImporter writes a complete unit module. raylib and SDL3 ship this way.
myrlsp language serverDiagnostics as you type, completions, hover, go-to-definition and document symbols for any LSP-capable editor. The same service runs in-process.
A debug build writes a compact .mdbg sidecar with functions, lines, variable locations and every @breakpoint;. No PDB, no DWARF. Breakpoints, stepping, variables, call stacks, in VS Code or any DAP client.
myrtester the gateRuns every compliance suite across both targets and all three optimization levels. Rebuilds DLL and lib producers before their consumers at each level.
The -ds flag writes the optimizer's view of every function. When something looks wrong there is no IR from someone else to decode; it is all right there.

myr.exe on your PATH. That is the install.hello.myr.myr hello -r. Add -t linux64 for a Linux binary; with WSL installed it runs immediately.> myr hello -r Hello, Myrissa! > myr hello -r -t linux64 Hello, Myrissa! > myr hello -r -opt full Hello, Myrissa! > myr hello -d debugger attached, waiting at @breakpoint