The Myra Programming Language
C++ is always one line away.
A systems programming language in the Pascal/Oberon tradition.
Compiles to C++23 via Zig/Clang. Produces real x86-64 binaries.
The language definition ships as readable .mld files
you can inspect, patch, and extend.
module exe hello; type Color = choices(Red, Green, Blue); Point = record x: int32; y: int32; end; routine greet(const name: string); begin writeln("Hello, {}!", name); end; var p: Point; begin @ifdef TARGET_WIN64 greet("Windows"); @else greet("Linux"); @endif p.x := 42; p.y := 99; writeln("({}, {})", p.x, p.y); end.
Core strengths
Oberon-inspired minimalism. Only the constructs that earn their place.
Compiles to real x86-64 machine code via C++23. No VM, no garbage collection pauses. Decades of compiler optimisation work, for free.
#include any C++ header, use std::vector, call std::sqrt, mix new/delete with Myra's create/destroy. If it's not a Myra keyword, it's C++.
The language definition ships as readable .mld files. Fix a compiler bug. Add a keyword. Change code generation. The language is yours to shape.
Records with inheritance and bit fields. Objects with virtual dispatch. Overlays. Typed sets. Fixed and dynamic arrays. Pointer types. Routine types.
Target Windows or Linux from the same source. Conditional compilation with @ifdef TARGET_WIN64. WSL2 handles Linux testing from Windows.
test "name" begin...end; blocks live in the same source file. Typed assertions (testAssertEqualInt, testAssertTrue, etc.) with file and line reporting.
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 p.x := 10; p.y := 20; p.z := 30; writeln("({}, {}, {})", p.x, p.y, p.z); end.
type TAnimal = object Name_: string; method Init(AName: string); begin self.Name_ := AName; end; method Speak(); begin writeln("{} says: ...", self.Name_); end; end; TDog = object(TAnimal) // Override -- virtual dispatch method Speak(); begin writeln("{} says: Woof!", self.Name_); end; end; var dog: pointer to TDog; base: pointer to TAnimal; begin create(dog); dog^.Init("Buddy"); // Dispatch through base pointer base := pointer to TAnimal(dog); base^.Speak(); // calls TDog.Speak() destroy(dog); end.
routine zero(): int32; begin return 0; end; begin // Software exception guard raiseException("Something went wrong"); except writeln("Caught: {}", getExceptionMessage()); end; // With error code and finally guard raiseExceptionCode(42, "Custom error"); except writeln("Code: {}", getExceptionCode()); finally writeln("Always runs"); end; // Hardware exception (div-by-zero) guard writeln("{}", 10 div zero()); except writeln("HW exception: {}", getExceptionMessage()); end; end.
// User-defined variadic routine routine sumInts(...): int32; var i: int32; sum: int32; begin sum := 0; for i := 0 to varargs.count - 1 do sum := sum + varargs.next(int32); 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 through 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.
module exe mixed; // C++ headers pass through verbatim #include <cmath> #include <string> #include <vector> var LS: std::string; LV: std::vector<int32_t>*; begin // C++ functions in Myra expressions writeln("sqrt(16) = {}", std::sqrt(16.0)); // C++ types as Myra variables LS := "hello from C++"; writeln("len = {}", LS.length()); // C++ new/delete alongside Myra LV := new std::vector<int32_t>(); LV->push_back(42); writeln("size = {}", LV->size()); delete LV; 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.
Compiled to .lib (Windows) or .a (Linux). Use exported to expose symbols. Importable with import.
Compiled to .dll or .so. Export C-compatible APIs with exported routine "C". Ideal for plugins and FFI.
"Start with Pascal. Remove everything that is not essential."
-- The Myra design principle