The Myra Programming Language
Native binaries. Zero friction.
Myra is a statically-typed, compiled language in the Pascal/Oberon tradition. It transpiles to C++23 and uses Zig as a build backend — producing real x86-64 executables and libraries for Windows and Linux. The backend is invisible. You write Myra. You get binaries.
module exe hello; type Color = (Red, Green, Blue); Point = record x: int32; y: int32; end; routine greet(const name: string); begin writeln("Hello, {}! 🌍", name); end; var p: Point; c: Color; begin $ifdef TARGET_WIN64 greet("Windows"); $else greet("Linux"); $endif p := Point{ x: 42, y: 99 }; c := Green; writeln("({}, {})", p.x, p.y); end.
Core strengths
Myra is designed around a principle: the language should get out of your way.
Compiles to real x86-64 machine code. No VM, no garbage collection pauses, no interpreter. The C++23 backend means you get decades of compiler optimisation work for free.
Call any C library with external declarations and "C" linkage. Full varargs support for printf-style APIs. No wrapper generators, no binding glue.
Records with inheritance and bit fields. Classes with virtual dispatch. Unions. Typed sets. Fixed and dynamic arrays. Pointer types. Routine types. All first-class citizens.
Reference-counted UTF-8 string and UTF-16 wstring. Emoji, CJK, accented characters — all work natively. Freed automatically, no leaks.
Target Windows or Linux from the same source. Conditional compilation with $ifdef TARGET_WIN64 and platform predefined symbols. WSL2 handles Linux testing from Windows.
test "name" begin...end blocks live in the same source file as your code. The test runner compiles and executes them, comparing output against EXPECT comments.
Language tour
Every example below compiles and runs. No hand-waving.
// Overloading — same name, different signatures routine max(const a: int32; const b: int32): int32; begin if a > b then return a; end; return b; end; routine max(const a: float64; const b: float64): float64; begin if a > b then return a; end; return b; end; // var parameter — modified in place routine swap(var a: int32; var b: int32); var tmp: int32; begin tmp := a; a := b; b := tmp; end; // Recursion routine fib(const n: int32): int32; begin if n <= 1 then return n; end; return fib(n - 1) + fib(n - 2); end;
type Point = record x: int32; y: int32; end; // Record inheritance Point3D = record(Point) z: int32; end; // Packed — no padding between fields Header = record packed magic: uint32; version: uint16; flags: uint8; end; // Bit fields Flags = record active: int32 : 1; mode: int32 : 3; level: int32 : 4; end; var p: Point3D; begin // Record literal syntax p.x := 10; p.y := 20; p.z := 30; writeln("({}, {}, {})", p.x, p.y, p.z); end.
type TAnimal = class Name_: string; method Init(AName: string); begin Self.Name_ := AName; end; method Speak(); begin writeln("{} says: ...", Self.Name_); end; end; TDog = class(TAnimal) // Override — virtual dispatch method Speak(); begin writeln("{} says: Woof!", Self.Name_); end; end; var dog: pointer to TDog; base: pointer to TAnimal; begin new(dog); dog^.Init("Buddy"); // Dispatch through base pointer base := pointer to TAnimal(dog); base^.Speak(); // calls TDog.Speak() dispose(dog); end.
routine zero(): int32; begin return 0; end; begin // Raise and catch a message exception try raiseexception("Something went wrong"); except writeln("Caught: {}", getexceptionmessage()); end; // Raise with a numeric code try raiseexceptioncode(42, "Custom error"); except writeln("Code: {}", getexceptioncode()); finally writeln("Always runs"); end; // Hardware exception (div-by-zero) try writeln("{}", 10 div zero()); except writeln("HW exception: {}", getexceptionmessage()); end; end.
// User-defined variadic routine routine sumInts(...): int32; var i: int32; sum: int32; arg: int32; begin sum := 0; for i := 0 to varargs.count - 1 do arg := varargs.next(int32); sum := sum + arg; end; return sum; end; begin writeln("sum = {}", sumInts(10, 20, 30)); // 60 writeln("sum = {}", sumInts(1, 2, 3, 4, 5)); // 15 writeln("sum = {}", sumInts()); // 0 end.
var s1: set; s2: set; s3: set; begin s1 := {1, 3, 5}; // bit positions 1, 3, 5 s2 := {3, 5, 10}; // Set arithmetic s3 := s1 + s2; // union: {1,3,5,10} s3 := s1 * s2; // intersection: {3,5} s3 := s1 - s2; // difference: {1} // Membership test if 1 in s1 then writeln("1 is in s1"); end; // Range literal s1 := {1..5}; // bits 1, 2, 3, 4, 5 end.
module exe ffi_demo; $ifdef TARGET_WIN64 // Call Windows API directly routine "C" MessageBoxA( const hwnd: pointer; const text: pointer to char; const caption: pointer to char; const utype: uint32 ): int32; external "user32.dll"; $endif // Link a third-party library $linklibrary "mylib.lib" $librarypath "libs/" routine "C" compute(const x: float64): float64; external "mylib.dll" name "compute_v2"; begin writeln("result = {}", compute(3.14)); end.
Cross-platform
The same Myra source compiles to Windows and Linux. Conditional compilation with predefined symbols handles the differences. WSL2 lets you build and test Linux binaries without leaving Windows.
Module system
Every Myra source file is a module. The kind declaration determines the output artifact.
A program with a begin..end. entry point. Produces a native executable. The most common module kind — start here for tools, CLIs, and applications.
Compiled to a .lib (Windows) or .a (Linux) archive. Use public to export symbols. Importable with the import statement.
Compiled to a .dll or .so shared object. Export C-compatible APIs with public routine "C". Ideal for plugin systems and FFI targets.
"The best tool is the one that disappears."
— The Myra design principle