Repository navigation
Implementation Notes
This page is for contributors hacking on the language runtime.
The lexer skips:
- spaces, tabs, CR, LF
-
//line comments -
/* ... */block comments
Recognizes:
-
integers (decimal)
-
identifiers / keywords
-
strings (double-quoted, allows escapes)
-
operators/punctuation:
()[]{} , ; .+ - * / %! !== ==< <=> >=&&||
Tokens carry line and col which update on newline.
Statements:
N_BLOCK-
N_LET,N_ASSIGN,N_SETINDEX -
N_IF,N_WHILE,N_RETURN N_EXPR_STMTN_FNDEF
Expressions:
-
N_BINOP,N_UNOP N_CALLN_INDEXN_GETFIELDN_FUNCLITN_IDENT-
N_LIT_INT,N_LIT_STR,N_LIT_BOOL,N_LIT_NIL
Assignments are statements only:
name = expr;target[index] = expr;
Parser uses a lookahead approach:
- if a statement starts with
IDENT, it tries parsing an lvalue and checks for=. - It rewinds lexer state and then parses properly.
Semicolons are optional in many places; maybe_semi() consumes an optional ;.
cs_value carries a cs_type tag and either:
- immediate (
bool,int) - pointer to refcounted heap objects (
string,list,map,strbuf,function,native)
cs_env is a chained scope (linked list via parent), storing parallel arrays of:
-
keys[](malloc'd C strings) -
vals[](cs_value)
Lookup walks outward; assignment updates nearest existing scope, else creates in current scope.
A function value stores:
- parameter list
- body AST pointer
- closure env (refcounted)
Parser stores raw token text (including quotes) for string literals. VM unescapes at evaluation time.
-
map.field→map_get(map, "field") - If
a.b.cis used andais undefined, VM can fall back to a dotted global lookup of"a.b.c"for compatibility with "namespaced globals".
Handled as special cases in CALL when callee is GETFIELD:
-
append,str,clear,len