Everything is data by default. Prefix a name with , to evaluate it — that's the whole rule.
Read, learn, and run the dialect right here. The interpreter ships with the app.
LISCT is a tiny dialect designed to embed into the set-based data model of this app. The whole language fits in your head — these four visuals are the load-bearing concepts.
Imagine the entire program is wrapped in an invisible Scheme `(…). Bare lists are data. They self-evaluate.
The only thing that "happens" is when you puncture the data layer with ,name — that's Scheme's unquote, hoisted to the language baseline. Quote ' is mostly noise here; data is already the default.
Three AST shapes do everything: Lit (literal), Ref (a ,name lookup), and Cons (the pair).
Evaluation is one function that walks the cons cells. If the head of a list evaluates to a procedure, call it; otherwise the list passes through as data unchanged.
,if, ,cond, and lambda bodies return a Tail thunk instead of recursing.
The eval loop trampolines: it unwinds the thunk and continues in place. Canonical tail recursion runs in constant JS stack — try a 100 000-step loop in the playground below.
Each lambda call frame is a fresh Map whose parent points at the lexical environment of the function's definition site — closures fall out for free.
A reference walks up the chain until it finds a binding; if it falls off the root, you get undefined reference.
The interpreter runs in your browser. Pick an example or write your own — bindings persist across runs in this session, so a ,define from one run is visible in the next.
⌘/Ctrl+Enter to run · 19 chars
ready