pub enum Exp {
Show 35 variants
Lit(i64),
Nil,
Sym(SmolStr),
Var(usize),
Lam(RcExp),
App(RcExp, RcExp),
Cons(RcExp, RcExp),
Let(RcExp, RcExp),
If(RcExp, RcExp, RcExp),
IsNum(RcExp),
IsSym(RcExp),
IsNil(RcExp),
IsPair(RcExp),
IsCode(RcExp, RcExp),
Car(RcExp),
Cdr(RcExp),
Plus(RcExp, RcExp),
Minus(RcExp, RcExp),
Times(RcExp, RcExp),
Eq(RcExp, RcExp),
Lift(RcExp),
Run(RcExp, RcExp),
LiftRef(RcExp, RcExp),
Log(RcExp, RcExp),
Proc(RcVal),
Read(RcExp),
ReadFile(RcExp),
Print(RcExp),
Catch(RcExp),
Throw(RcExp),
Evalms(RcExp, RcExp),
Trans(RcExp, RcExp),
CellNew(RcExp),
CellRead(RcExp),
CellSet(RcExp, RcExp),
}Expand description
A floor expression, after parsing and sugar expansion.
Each variant’s doc gives the surface syntax it corresponds to;
variants with no surface syntax (Exp::Proc, Exp::Catch) say
so. A common pattern throughout: primitives dispatch on whether
their operands are plain values or staged Val::Code — the value
case computes now, the code case emits a copy of the operation into
the residual program being built (see crate::eval::machine).
Variants§
Lit(i64)
Integer literal. Booleans share this encoding: the reader takes
#t to Lit(1) and #f to Lit(0), and predicates answer 1 or 0.
Nil
Nil literal — the empty list / false sentinel.
Sym(SmolStr)
Symbol literal. SmolStr stores strings ≤22 bytes inline (no heap).
Var(usize)
Variable — an index into the environment, counted from its base
(a de Bruijn level, matching list position in base.scm’s env).
The parser resolves surface names to these indices.
Lam(RcExp)
(lambda f x body): unary, self-naming lambda. Application
extends the closure’s environment with the closure itself and
then the argument, so body reaches f at the first new slot
(recursion without a fixpoint combinator) and x at the second.
Body as Rc<Exp>: all closures from the same Lam site share
one allocation, making find_fun’s ptr_eq fast path fire reliably.
App(RcExp, RcExp)
(f a): unary application. A code operand pair residualizes an
application instead of β-reducing.
Cons(RcExp, RcExp)
(cons a b): pair construction.
Let(RcExp, RcExp)
(let x e body): evaluate e, bind it as the next environment
slot, evaluate body. The name is resolved away by the parser.
If(RcExp, RcExp, RcExp)
(if c t f): the condition must produce a number — 0 is false,
anything else true — or code, in which case both branches are
reified and the if residualizes.
IsNum(RcExp)
(number? e): 1 if the value is a number, else 0.
IsSym(RcExp)
(symbol? e): 1 if the value is a symbol, else 0.
IsNil(RcExp)
(null? e): 1 if the value is nil, else 0.
IsPair(RcExp)
(pair? e): 1 if the value is a pair, else 0.
IsCode(RcExp, RcExp)
(code? d e): 1 if e’s value is staged code, else 0. The
first operand is a stage dispatch: when it evaluates to code,
the test itself residualizes (strict — a non-code e under a
staged dispatch is an error, never an implicit lift).
Car(RcExp)
(car p): first component of a pair.
Cdr(RcExp)
(cdr p): second component of a pair.
Plus(RcExp, RcExp)
(+ a b): integer addition.
Minus(RcExp, RcExp)
(- a b): integer subtraction.
Times(RcExp, RcExp)
(* a b): integer multiplication.
Eq(RcExp, RcExp)
(eq? a b): structural equality, answering 1 or 0. Closures and
code compare by pointer first, then structurally; cells compare
by identity.
Lift(RcExp)
(lift e): reify a value into next-stage code — numbers and
symbols become literals, pairs of code become cons nodes,
closures are η-expanded into staged lambdas (memoized per
closure, so recursive functions lift to a single residual
definition).
Run(RcExp, RcExp)
(run b e): stage dispatch on b. Non-code b compiles e
(evaluates it in a fresh reify scope, expecting code) and
immediately executes the result; code b reifies e and
residualizes the run itself.
LiftRef(RcExp, RcExp)
(lift-ref name v): cross-stage persistence. With a non-code
first operand, v is evaluated and embedded in code as
Exp::Proc — the residual program references the live value
rather than a syntactic copy. With a code first operand, the
lift-ref residualizes.
Log(RcExp, RcExp)
(log b v): stage-aware debug print. Non-code b: print v
(as [log] …) and return it. Code b: residualize the log,
persisting a non-code v via Exp::Proc.
Proc(RcVal)
Cross-stage persisted value — the reference’s (proc _ <thunk>)
(see base.scm’s lift-ref wrapper). Evaluates to the embedded
Val. Not reachable from the parser; only constructed by staged
log, which persists a non-code logged value into residual code
rather than coercing it to syntax.
Read(RcExp)
(read prompt): print the prompt, read one line from the
evaluator’s NarjuIo, parse it as a datum.
End-of-input and blank lines read as nil. Like read-file, this
has no Pink-source representation, so trans never emits it.
ReadFile(RcExp)
(read-file 'path): parse a source file into a list of forms-as-data
(each pre-sugged — read-file reads source, and sug is a read-time
source transform). Floor primitive for Pink-level load; like Read,
it has no Pink-source representation, so trans never emits it.
Print(RcExp)
(print e): write the value to the evaluator’s
NarjuIo; returns nil (log is the
variant that returns its value).
Catch(RcExp)
Single restricted floor primitive for error handling in the Purple REPL loop — not reachable from the user-facing parser.
Throw(RcExp)
(throw v): evaluate v, then raise it as a first-class error
payload. Unwinds to the nearest Catch, arriving as
(error <payload> ()); uncaught, it propagates as a top-level
error. This is how a base env reports unbound variables loudly
instead of returning a silent zero.
Evalms(RcExp, RcExp)
(evalms env-list expr): evaluate a code value under an
explicit environment given as a list of values. base.scm’s
evalms exposed as a primitive — the back half of the
trans + evalms pipeline that lets floor programs animate
source-as-data (this is how lib/purple.naj boots Pink).
Trans(RcExp, RcExp)
(trans e env): translate an s-expression value into a code
value, resolving names positionally against env — a list
whose entries are symbols (plain names) or (name . code)
pairs (splices: the name resolves to the given code rather
than a variable). base.scm’s trans as a primitive.
CellNew(RcExp)
(cell-new v): allocate a fresh mutable cell holding v.
CellRead(RcExp)
(cell-read c): current contents of a cell.
CellSet(RcExp, RcExp)
(cell-set! c v): write v into the cell; returns v.
Implementations§
Source§impl Exp
Constructor helpers that hide Box::new and rc_exp at call sites.
impl Exp
Constructor helpers that hide Box::new and rc_exp at call sites.
Using these everywhere means changing an Exp variant’s storage type
(e.g. Box → Rc) only requires updating the constructor, not every
call site in tests and the evaluator.
Sourcepub fn minus(a: Exp, b: Exp) -> Self
pub fn minus(a: Exp, b: Exp) -> Self
Construct Exp::Minus.
Sourcepub fn times(a: Exp, b: Exp) -> Self
pub fn times(a: Exp, b: Exp) -> Self
Construct Exp::Times.
Sourcepub fn is_num(e: Exp) -> Self
pub fn is_num(e: Exp) -> Self
Construct Exp::IsNum.
Sourcepub fn is_sym(e: Exp) -> Self
pub fn is_sym(e: Exp) -> Self
Construct Exp::IsSym.
Sourcepub fn is_nil(e: Exp) -> Self
pub fn is_nil(e: Exp) -> Self
Construct Exp::IsNil.
Sourcepub fn is_pair(e: Exp) -> Self
pub fn is_pair(e: Exp) -> Self
Construct Exp::IsPair.
Sourcepub fn is_code(dispatch: Exp, tested: Exp) -> Self
pub fn is_code(dispatch: Exp, tested: Exp) -> Self
Construct Exp::IsCode.
Sourcepub fn lift_ref(a: Exp, b: Exp) -> Self
pub fn lift_ref(a: Exp, b: Exp) -> Self
Construct Exp::LiftRef.
Sourcepub fn read_file(path: Exp) -> Self
pub fn read_file(path: Exp) -> Self
Construct Exp::ReadFile.
Sourcepub fn print(e: Exp) -> Self
pub fn print(e: Exp) -> Self
Construct Exp::Print.
Sourcepub fn catch(e: Exp) -> Self
pub fn catch(e: Exp) -> Self
Construct Exp::Catch.
Sourcepub fn throw(e: Exp) -> Self
pub fn throw(e: Exp) -> Self
Construct Exp::Throw.
Sourcepub fn evalms(env_list: Exp, expr: Exp) -> Self
pub fn evalms(env_list: Exp, expr: Exp) -> Self
Construct Exp::Evalms.
Sourcepub fn trans(e: Exp, env: Exp) -> Self
pub fn trans(e: Exp, env: Exp) -> Self
Construct Exp::Trans.
Sourcepub fn cell_new(v: Exp) -> Self
pub fn cell_new(v: Exp) -> Self
Construct Exp::CellNew.
Sourcepub fn cell_read(c: Exp) -> Self
pub fn cell_read(c: Exp) -> Self
Construct Exp::CellRead.
Sourcepub fn cell_set(c: Exp, v: Exp) -> Self
pub fn cell_set(c: Exp, v: Exp) -> Self
Construct Exp::CellSet.