Skip to content

Istar-Eldritch/sooth

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

295 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sooth

A small, statically-checked concatenative language in the Forth/Factor/Kitten lineage, compiled to native code with no external runtime. A craft language: built for the pleasure of writing it and writing programs in it, not as a product. See DESIGN.md for the why and ROADMAP.md for the plan.

The one bet that makes it more than a tidy Forth: in a stack language the stack discipline already is move semantics, so linear types fall out for free. dup is the explicit copy, and drop is the explicit destructor point (use exactly once, forgetting is a compile error).

: gcd ( i64 i64 -- i64 )
  dup 0 = if
    drop
  else
    swap over mod gcd
  end ;

Status

Phases 0 and 1 complete; Phase 2 (typed core) in progress (see ROADMAP.md). The pipeline is implemented end to end: gcd/factorial/lerp and the newer examples compile to native binaries and run, and cargo run -- repl gives an interactive session where words are compiled to shared objects and dlopen'd in as you define them. Phase 2 has landed its full scalar core: a Type per stack slot, unified at branch joins; the fixed-width integer tower (i8..i64, u8..u64) with explicit target-only conversions (>i8..>u64); floating point (f32/f64) with IEEE arithmetic and comparison; bitwise operators (and/or/xor/not/shl/shr); and boolean logic with the full comparison set (= < > <= >= <>). Phase 2 has also landed structs (the type: declaration form, inline-aggregate layout, generated constructor/accessor words) and enums/ADTs (type: with |-separated variants, a tagged inline-aggregate representation, and exhaustiveness-checked clause-style word definition as the eliminator, no inline match). What remains in Phase 2 are fixed-size arrays, then the bytecode-VM exit dogfood. The compiler is a Rust bootstrap; the language will later self-host.

Pipeline: source → lex → parse → stack-effect check → backend-neutral IR → QBE IL → native binary. Backend is QBE, invoked from PATH alongside the system cc. WASM is a planned sibling lowering off the neutral IR.

Build and run

Requires qbe and a C compiler (cc) on your PATH. Needs a reasonably modern QBE: Debian's packaged qbe (1.2) predates the unsigned int/float conversion ops (uwtof/ultof/stoui/dtoui) and fails with unknown keyword on those; build from c9x.me/git/qbe.git if so.

cargo build
cargo test                            # unit tests + the Phase 0/1 goldens
cargo run -- run   examples/gcd.sth   # compile and run (prints 5)
cargo run -- build examples/gcd.sth   # just compile, to examples/gcd
cargo run -- repl                     # interactive session

A REPL session compiles each line to a shared object and dlopens it into the process, with a stack that persists across lines (no prompt is printed in Phase 1; lines below are input, other lines are the session's output):

: sq ( i64 -- i64 ) | n | n n * ;
defined sq
5 sq
stack: 25

Layout

src/lexer.rs  parser.rs  ast.rs   front end
src/check.rs                      stack-effect checker
src/ir.rs                         backend-neutral IR (Ptr[T] kept abstract)
src/backend/qbe.rs                QBE IL emission
src/driver.rs                     pipeline orchestration
src/repl.rs                       REPL session: dlopen loop, generation mangling
examples/                         target programs (gcd, factorial, lerp, rgb, mean, leap, ...)
tests/phase0.rs                   golden tests: build+run + diagnostics across the scalar core
tests/phase1.rs                   golden REPL sessions (define/redefine/recover)

About

A small, statically-checked concatenative language in the Forth lineage compiled to native code with no external runtime

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages