early development
first is a minimal interpreted language written in C99. Arithmetic, relational, equality, and boolean expressions, when for predicate-based branching, { } scoped blocks, and fn functions with closures and recursion — from source text to runtime value.
echo "let x = 1 + 2" | ./build/first
Type any first expression and watch it decompose into tokens in real time — exactly what lex_next_token() produces.
The interpreter is a tree-walk evaluator. Each AST node is a tagged union dispatched by interpreter_evaluate(). Variables live in a scope-chained Environment, backed by JMap — a custom open-addressing hash map.
Zero external runtime dependencies. Builds with CMake, tested with Criterion, runs anywhere.
Tokenizes from a FILE* without loading the full source into memory. One token per call.
let x = expr declares. x = expr reassigns. Scopes chain by parent pointer.
Arithmetic (+ − × ÷ % **), relational, equality, and boolean operators, all with correct precedence and parenthesized grouping.
The parser is hand-written and easy to follow. Each grammar rule maps to a single function.
No if/else — when evaluates predicate arms top to bottom with a mandatory _ -> catch-all, and is itself an expression.
Anonymous fn(params) -> body literals bound with let like any other value. They capture their defining scope by reference, so closures and self-recursive calls both work.
// full grammar — src/parser.c <program> ::= [ "module" <identifier> ] { <expression> } <expression> ::= <declaration> | <when> | <boolean_or> <declaration> ::= "let" <identifier> "=" <assignment> { "," <identifier> "=" <assignment> } <assignment> ::= <when> | <function> | <boolean_or> [ "=" <assignment> ] <when> ::= "when" <arm> { ("," | newline) <arm> } "_" "->" <expression> <arm> ::= <boolean_or> "->" <expression> <function> ::= "fn" "(" [ <identifier> { "," <identifier> } ] ")" "->" <expression> <boolean_or> ::= <boolean_and> { "||" <boolean_and> } <boolean_and> ::= <equality> { "&&" <equality> } <equality> ::= <relational> { ("==" | "!=") <relational> } <relational> ::= <addition> { ("<" | ">" | "<=" | ">=") <addition> } <addition> ::= <multiplication> { ("+" | "-") <multiplication> } <multiplication> ::= <exponent> { ("*" | "/" | "%") <exponent> } <exponent> ::= <unary> { "**" <unary> } <unary> ::= ("+" | "-") <unary> | <primary> <primary> ::= "(" <expression> ")" | <block> | <literal> | <identifier> [ <call> ] <call> ::= "(" [ <boolean_or> { "," <boolean_or> } ] ")" <block> ::= "{" { <expression> } "}" <literal> ::= <number> | <string> | "true" | "false"