The Myra Programming Language

Minimal.
Native. Hackable.

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.

hello.myra
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.
Minimal by design Compiles to C++23 Seamless C++ interop Hackable .mld definition Windows & Linux Managed strings Record inheritance Objects with virtual dispatch FFI / C interop Variadic routines Structured exceptions Pascal-style sets Built-in test blocks DAP debugger Minimal by design Compiles to C++23 Seamless C++ interop Hackable .mld definition Windows & Linux Managed strings Record inheritance Objects with virtual dispatch FFI / C interop Variadic routines Structured exceptions Pascal-style sets Built-in test blocks DAP debugger

Everything you need.
Nothing you don't.

Oberon-inspired minimalism. Only the constructs that earn their place.

Native Performance

Compiles to real x86-64 machine code via C++23. No VM, no garbage collection pauses. Decades of compiler optimisation work, for free.

🔗
Seamless C++ Interop

#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++.

🔧
Hackable Compiler

The language definition ships as readable .mld files. Fix a compiler bug. Add a keyword. Change code generation. The language is yours to shape.

🧬
Rich Type System

Records with inheritance and bit fields. Objects with virtual dispatch. Overlays. Typed sets. Fixed and dynamic arrays. Pointer types. Routine types.

🌐
Cross-Platform

Target Windows or Linux from the same source. Conditional compilation with @ifdef TARGET_WIN64. WSL2 handles Linux testing from Windows.

Built-in Tests

test "name" begin...end; blocks live in the same source file. Typed assertions (testAssertEqualInt, testAssertTrue, etc.) with file and line reporting.

The language, in code.

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.

One source.
Two platforms.

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.

  • Identical language semantics across platforms
  • Platform symbols injected automatically
  • WSL2 integration for Linux testing from Windows
  • Zig handles all cross-compilation internals
  • macOS, ARM64 targets on the roadmap
win64 -- Windows x86-64 Supported
linux64 -- Linux x86-64 Supported
macos64 -- macOS x86-64 Planned
winarm64 -- Windows ARM64 Planned
linuxarm64 -- Linux ARM64 Planned

Three kinds.
One language.

Every Myra source file is a module. The kind declaration determines the output artifact.

exe
Executable

A program with a begin..end. entry point. Produces a native executable. The most common module kind.

lib
Static Library

Compiled to .lib (Windows) or .a (Linux). Use exported to expose symbols. Importable with import.

dll
Shared Library

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