Scar
A compiled, statically typed programming language, offering high-level syntax with low-level control.
what it is
Scar is a RAD-centred programming language that includes defensive programming as part of the language grammar, while still being flexible enough to iterate and prototype upon ideas.
why it exists
Existing options were either garbage collected (pauses, slowness), plagued with numerous footguns, or cryptic and unreadable due to their overly loose and flexible conventions. This language aims to strike a balance between safety and iterability.
explicit over implicit
No hidden allocations. This does not hinder readability, in fact it greatly helps to have complete explicitness under a Ruby-style, readable syntax.
interfaces & generics
Generics and interface rely on static dispatch, thus there is zero runtime overhead associated with them. This means, rich, dynamic language features, without losing runtime performance.
extern def strcmp(x ref(u8), y ref(u8)) i32 :: "strcmp" extern def strlen(x ref(u8)) usize :: "strlen" pub def eql(x ref(u8), y ref(u8)) bool guard (y != none && x != none) else return false end return strcmp(x, y) == 0 end pub def len(x ref(u8)) usize guard (x != none) else return 0 end return strlen(x) end test "equals works" assert eql("hello", "hello") assert !eql("hello", "something else") end
type Complex re i64 im i64 end def c_add(a Complex, b Complex) Complex return Complex( re: a.re + b.re, im: a.im + b.im ) end def mandelbrot_iter(c Complex, max_iter i32) i32 var z = make_complex(0, 0) for var i = 0 .. max_iter if c_mag2(z) > 4 return i end z = c_add(c_mul(z, z), c) end return max_iter end
pub interface BumpAllocator pub def alloc(a ref(BumpAllocator), size usize) ref(void)|error pub def reset(a ref(BumpAllocator)) pub def destroy(a ref(BumpAllocator)) end pub type Arena : BumpAllocator ptr ref(u8) cap usize off usize end pub def Arena.new(cap usize) Arena|error ## Create a new arena given some cap. var mem ref(u8) = @alloc(cap) as mut(ref(u8)) if mem == none return error("arena allocation failed") end return Arena(ptr: mem, cap: cap, off: 0) end test "alloc with unwrap works" var arena = Arena.new(1024 as usize)? var mem = Arena.alloc(@addr(arena), 500)? Arena.destroy(@addr(arena)) end
type Grid width i32 height i32 cells list[list[i32]] end def step(grid ref(Grid)) Grid val next = make_grid(grid.width, grid.height) for var y = 0 .. grid.height for var x = 0 .. grid.width val alive = get_cell(grid, x, y) val neighbors = count_neighbors(grid, x, y) if alive == 1 if neighbors == 2 || neighbors == 3 set_cell(@addr(next), x, y, 1) end else if neighbors == 3 set_cell(@addr(next), x, y, 1) end end end end return next end
2025
Initial design. Pythonic syntax. First compiler prototype.
early 2026
Syntax redesign. Moved from Pythonic to Ruby-style structure.
now
Looking towards making the standard library more feature complete, and the language itself more batteries included