Midori
A statically-typed functional language with algebraic data types, exhaustive pattern matching, typeclasses, and an explicit module system. Compiles to bytecode for the Midori Virtual Machine with mark-and-sweep garbage collection.
- 01
Static Type System
Strong static typing with bidirectional inference, generics, constraints, and exhaustive checking.
- 02
Pattern Matching
Exhaustive pattern matching on unions and Bool with compiler-enforced coverage.
- 03
Algebraic Data Types
Express complex structures with structs, unions, type aliases, and recursive definitions.
- 04
Typeclasses
Constrained generics with associated types and instance dispatch.
- 05
Modules & Packages
Explicit imports/exports, project.midori layout, third-party packages with native FFI.
- 06
Typed Prelude
MidoriPrelude exposes typed IO, system, date/time, text, and array helpers.
A complete .mdr file starts with an explicit module declaration.
module Main
import { "../MidoriPrelude/IO.mdr" }
IO::PrintLine("Hello, Midori!");// Simple function
defun square(x: Int) : Int => {
return x * x;
};
// Generic function
defun identity<T>(value: T) : T => value;
// Higher-order function
defun apply<T, R>(fn: fn(T) -> R, value: T) : R => {
return fn(value);
};// Product types (structs)
struct Point {
x: Float,
y: Float,
};
// Sum types (unions)
union Option<T> = None | Some(T);
union Result<T, E> = Ok(T) | Err(E);
def origin = new Point(0.0, 0.0);
def maybe = new Option::Some(42);union Result<T, E> = Ok(T) | Err(E);
defun handle_result<T>(result: Result<T, Text>) : Text => {
return match result with
case Result::Ok(value) => "Success: " ++ (value as Text)
case Result::Err(msg) => "Error: " ++ msg
;
};Constrained generics with associated types and instance dispatch — preserving static guarantees.
class Show<T> {
show: fn(value: T) -> Text;
};
instance Show<Int> {
defun show(value: Int) : Text => {
return value as Text;
};
};
defun display<T>(value: T) : Text where Show<T> => {
return Show::show(value);
};union Option<T> = None | Some(T);
class Iterable<Iter> {
type Item;
Next: fn(iter: Iter) -> Option<Item>;
};
defun NextValue<Iter>(iter: Iter)
: Option<Iterable::Item<Iter>>
where Iterable<Iter> => {
return Iterable::Next(iter);
};defun double(x: Int) : Int => x * 2;
union Result<T, E> = Ok(T) | Err(E);
defun transform(value: Int) : Result<Int, Text> => {
if value > 10
then new Result::Ok(value + 1)
else new Result::Err("too small")
};
def result =
5
|> double
|> fn(x) => { x + 1 }
|> transform
|> match with
case Result::Ok(value) => value
case Result::Err(_) => 0;defun make_counter() : fn() -> Int => {
def count = 0;
return fn() : Int => {
count = count + 1;
return count;
};
};
def counter = make_counter();
def first = counter(); // 1
def second = counter(); // 2MidoriPrelude wraps the runtime FFI surface in Midori-facing modules. File and process APIs prefer typed Result and Option over sentinel returns.
module ConfigDemo
import
{
"./MidoriPrelude/IO.mdr",
"./MidoriPrelude/System.mdr",
"./MidoriPrelude/Prelude/Option.mdr",
"./MidoriPrelude/Prelude/Result.mdr"
}
use Option.{Option}
use Result.{Result}
def config_text =
match IO::TryReadFile("app.conf") with
case Result::Ok(contents) => contents
case Result::Err(_) => "release=debug"
;
def cache_dir =
match System::TryGetEnv("MIDORI_CACHE_DIR") with
case Option::Some(path) => path
case Option::None() => ".midori-cache"
;- 01
IO.mdrConsole output and typed file APIs (TryReadFile, TryWriteFile, TryReadBinaryFile). - 02
System.mdrEnvironment, working-directory, process, and platform helpers using Option and Result. - 03
DateTime.mdrLocal and UTC date/time structs (LocalNow, UtcNow, FormatLocal). - 04
TextUtil.mdrText helpers — Length, Split, Replace, Trim, Reverse. - 05
ArrayUtil.mdrMutable array helpers — Append, Prepend, Extend, Slice, Reverse. - 06
Prelude/Result.mdrResult utilities built around Ok and Err with map, bind, and unwrap.
- 01FrontendLexer → Module Manager → Parser → Type Checker → Static Analyzer
- 02OptimizerConstant folding, strength reduction, closure lifting, tail-call optimization
- 03BackendBytecode generator → Linker
- 04RuntimeSingle VirtualMachine execution path with mark-and-sweep garbage collection