Something went wrong. Try again.
Jam Programming Language jamlang.org
compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178// Payload-less enums (M2 E1). Variants are sequential u8// discriminants; the type compiles to `i8` in LLVM IR. Match patterns// support `EnumName.Variant` arms.const { assert } = import("test");
// -------------------- Basic dispatch --------------------
const Color = enum { Red, Green, Blue };
fn classifyColor(c: Color) u8 { match (c) { Color.Red { return 100; } Color.Green { return 200; } Color.Blue { return 50; } _ { return 0; } } return 99;}
tfn colorRed() { assert(classifyColor(Color.Red), 100); }tfn colorGreen() { assert(classifyColor(Color.Green), 200); }tfn colorBlue() { assert(classifyColor(Color.Blue), 50); }
// -------------------- Discriminant values are stable --------------------
fn colorAsByte(c: Color) u8 { match (c) { Color.Red { return 0; } Color.Green { return 1; } Color.Blue { return 2; } _ { return 255; } } return 99;}
tfn discriminantRed() { assert(colorAsByte(Color.Red), 0); }tfn discriminantGreen() { assert(colorAsByte(Color.Green), 1); }tfn discriminantBlue() { assert(colorAsByte(Color.Blue), 2); }
// -------------------- More variants --------------------
const Direction = enum { North, South, East, West };
fn opposite(d: Direction) Direction { match (d) { Direction.North { return Direction.South; } Direction.South { return Direction.North; } Direction.East { return Direction.West; } Direction.West { return Direction.East; } _ { return Direction.North; } } return Direction.North;}
fn isOppositePair(d: Direction) u8 { const opp: Direction = opposite(d); match (opp) { Direction.North { return 1; } Direction.South { return 2; } Direction.East { return 3; } Direction.West { return 4; } _ { return 99; } } return 0;}
tfn oppositeOfNorth() { assert(isOppositePair(Direction.North), 2); } // Southtfn oppositeOfSouth() { assert(isOppositePair(Direction.South), 1); } // Northtfn oppositeOfEast() { assert(isOppositePair(Direction.East), 4); } // Westtfn oppositeOfWest() { assert(isOppositePair(Direction.West), 3); } // East
// -------------------- Variant in or-pattern --------------------
fn isHorizontal(d: Direction) u8 { match (d) { Direction.East | Direction.West { return 1; } _ { return 0; } } return 0;}
tfn horizontalEast() { assert(isHorizontal(Direction.East), 1); }tfn horizontalWest() { assert(isHorizontal(Direction.West), 1); }tfn horizontalNorth() { assert(isHorizontal(Direction.North), 0); }tfn horizontalSouth() { assert(isHorizontal(Direction.South), 0); }
// -------------------- Returning enums --------------------
fn defaultColor() Color { return Color.Red;}
fn colorEqualsRed() u8 { const c: Color = defaultColor(); match (c) { Color.Red { return 1; } _ { return 0; } } return 0;}
tfn defaultIsRed() { assert(colorEqualsRed(), 1); }
// -------------------- State machine --------------------
const State = enum { Idle, Running, Paused, Stopped };
fn step(s: State) State { match (s) { State.Idle { return State.Running; } State.Running { return State.Paused; } State.Paused { return State.Running; } State.Stopped { return State.Stopped; } _ { return State.Stopped; } } return State.Stopped;}
fn stepN(start: State, n: u8) State { var s: State = start; var i: u8 = 0; while (i < n) { s = step(s); i = i + 1; } return s;}
fn stateAsByte(s: State) u8 { match (s) { State.Idle { return 0; } State.Running { return 1; } State.Paused { return 2; } State.Stopped { return 3; } _ { return 99; } } return 0;}
tfn stateMachineStart() { assert(stateAsByte(stepN(State.Idle, 0)), 0); } // Idletfn stateMachine1Step() { assert(stateAsByte(stepN(State.Idle, 1)), 1); } // Runningtfn stateMachine2Step() { assert(stateAsByte(stepN(State.Idle, 2)), 2); } // Pausedtfn stateMachine3Step() { assert(stateAsByte(stepN(State.Idle, 3)), 1); } // Runningtfn stateMachine4Step() { assert(stateAsByte(stepN(State.Idle, 4)), 2); } // Paused
// -------------------- Many variants (Game-Boy-style) --------------------
const Tetromino = enum { I, O, T, S, Z, J, L };
fn cellsForShape(t: Tetromino) u8 { // Each tetromino has 4 cells; this is just a smoke test that // dispatch over 7 variants compiles and runs correctly. match (t) { Tetromino.I | Tetromino.O | Tetromino.T | Tetromino.S | Tetromino.Z | Tetromino.J | Tetromino.L { return 4; } _ { return 0; } } return 0;}
fn tetrominoIsBalanced(t: Tetromino) u8 { // I and O are symmetric; the others are not. match (t) { Tetromino.I | Tetromino.O { return 1; } _ { return 0; } } return 0;}
tfn allTetrominoesHave4Cells_I() { assert(cellsForShape(Tetromino.I), 4); }tfn allTetrominoesHave4Cells_T() { assert(cellsForShape(Tetromino.T), 4); }tfn allTetrominoesHave4Cells_L() { assert(cellsForShape(Tetromino.L), 4); }tfn iIsBalanced() { assert(tetrominoIsBalanced(Tetromino.I), 1); }tfn oIsBalanced() { assert(tetrominoIsBalanced(Tetromino.O), 1); }tfn sIsNotBalanced() { assert(tetrominoIsBalanced(Tetromino.S), 0); }tfn jIsNotBalanced() { assert(tetrominoIsBalanced(Tetromino.J), 0); }