sammine-lang
Jasmine's education front end compiler front end via her blog
How I pictured sammine-lang in my head
Dev
MacOS Configurations
Install llvm & catch2
Run
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug [-DSAMMINE_TEST=ON/OFF] [-DCMAKE_LINKER_TYPE=MOLD]
for configuration. We need llvm,FileCheck, and lit.
Run
and
cmake --build build -j --target unit-tests e2e-tests
in the project root folder to cycle through the development process.
Run
to erase the build folder (similar to make clean).
Language Features
# Line comments start with #
# Types: i32, i64, f64, bool, string, unit, etc
import std; # import standard library (provides printf)
extern sqrt(x: f64) -> f64; # C extern (private to this file)
let add(a: i32, b: i32) -> i32 { # function definition
a + b # implicit return (last expression)
}
let fib(x: i32) -> i32 { # recursion, if/else as expression
if x == 0 || x == 1 { # logical operators: && ||
x
} else {
fib(x - 1) + fib(x - 2) # arithmetic: + - * / %
}
}
let identity(x: T) -> T { x } # generics (monomorphized)
let apply(f: (T) -> U, x: T) -> U { # higher-order + generic
f(x) # (T) -> U is a function type
}
let main() -> i32 {
# --- Variables ---
let x: i32 = 5; # immutable, type-annotated
let y = 10; # type inference
let mut counter: i32 = 0; # mutable binding
counter = counter + 1; # assignment (mut only)
# --- Control flow ---
let sign = if x > 0 { 1 } # if/else is an expression
else if x == 0 { 0 } # comparison: < <= > >= == !=
else { -1 }; # unary negation
# --- Arrays ---
let a: [i32; 3] = [10, 20, 30]; # fixed-size array literal
let first = a[0]; # indexing
let size = len(a); # array length
# --- Pointers & memory ---
let p: ptr<i32> = alloc(42); # heap allocation
let val = *p; # dereference
*p = 100; # write through pointer
free(p); # manual deallocation
let q: ptr<i32> = &x; # address-of (stack pointer)
let pp: ptr<ptr<i32>> = &q; # nested pointers
# --- Pipe operator ---
let r1 = 5 |> add(3); # x |> f(y) becomes f(x, y)
let r2 = 5 |> identity |> add(3); # chained pipes
# --- Partial function application ---
let add5: (i32) -> i32 = add(5); # fewer args -> new function
let eight = add5(3); # call the partially applied fn
# --- Higher-order functions ---
let f: (i32) -> i32 = add5; # function as value
let res = apply(f, 42); # pass function as argument
# --- Generics (monomorphized) ---
let a_i32 = identity(42); # instantiates identity.i32
let a_f64 = identity(3.14); # instantiates identity.f64
std::printf("%d\n", fib(9));
return 0; # explicit return
}
Dev
MacOS Configurations
Install llvm & catch2
Run
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug [-DSAMMINE_TEST=ON/OFF] [-DCMAKE_LINKER_TYPE=MOLD]
for configuration. We need llvm,FileCheck, and lit.
Run
and
cmake --build build -j --target unit-tests e2e-tests
in the project root folder to cycle through the development process.
Run
to erase the build folder (similar to make clean).
Compiler CLI
./build/bin/sammine --help
Usage: sammine [--help] [--version] [[--file VAR]|[--str VAR]] [--check] [--llvm-ir] [--ast-ir] [--diagnostics VAR]
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
-f, --file An input file for compiler to scan over.
-s, --str An input string for compiler to scan over.
--check Performs compiler check only, no codegen
Diagnostics related options (detailed usage):
--llvm-ir sammine compiler spits out LLVM-IR to stdout
--ast-ir sammine compiler spits out the internal AST to stdout
--diagnostics sammine compiler spits out diagnostics for sammine-lang developers.
Use with value for logging: --diagnostics=stages;lexer;parser. Default value is none
--time Print compilation timing. Also accepts: sparse (per-phase table), coarse (per-phase + all LLVM passes)
--dev Show compiler source locations in error messages (for developers)