Exp

Enum Exp 

Source
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.

Using these everywhere means changing an Exp variant’s storage type (e.g. BoxRc) only requires updating the constructor, not every call site in tests and the evaluator.

Source

pub fn lam(body: Exp) -> Self

Construct Exp::Lam.

Source

pub fn app(f: Exp, a: Exp) -> Self

Construct Exp::App.

Source

pub fn let_(init: Exp, body: Exp) -> Self

Construct Exp::Let.

Source

pub fn if_(c: Exp, t: Exp, f: Exp) -> Self

Construct Exp::If.

Source

pub fn cons(a: Exp, b: Exp) -> Self

Construct Exp::Cons.

Source

pub fn car(e: Exp) -> Self

Construct Exp::Car.

Source

pub fn cdr(e: Exp) -> Self

Construct Exp::Cdr.

Source

pub fn plus(a: Exp, b: Exp) -> Self

Construct Exp::Plus.

Source

pub fn minus(a: Exp, b: Exp) -> Self

Construct Exp::Minus.

Source

pub fn times(a: Exp, b: Exp) -> Self

Construct Exp::Times.

Source

pub fn eq(a: Exp, b: Exp) -> Self

Construct Exp::Eq.

Source

pub fn is_num(e: Exp) -> Self

Construct Exp::IsNum.

Source

pub fn is_sym(e: Exp) -> Self

Construct Exp::IsSym.

Source

pub fn is_nil(e: Exp) -> Self

Construct Exp::IsNil.

Source

pub fn is_pair(e: Exp) -> Self

Construct Exp::IsPair.

Source

pub fn is_code(dispatch: Exp, tested: Exp) -> Self

Construct Exp::IsCode.

Source

pub fn lift(e: Exp) -> Self

Construct Exp::Lift.

Source

pub fn run(b: Exp, e: Exp) -> Self

Construct Exp::Run.

Source

pub fn lift_ref(a: Exp, b: Exp) -> Self

Construct Exp::LiftRef.

Source

pub fn log(b: Exp, v: Exp) -> Self

Construct Exp::Log.

Source

pub fn read(prompt: Exp) -> Self

Construct Exp::Read.

Source

pub fn read_file(path: Exp) -> Self

Construct Exp::ReadFile.

Source

pub fn print(e: Exp) -> Self

Construct Exp::Print.

Source

pub fn catch(e: Exp) -> Self

Construct Exp::Catch.

Source

pub fn throw(e: Exp) -> Self

Construct Exp::Throw.

Source

pub fn evalms(env_list: Exp, expr: Exp) -> Self

Construct Exp::Evalms.

Source

pub fn trans(e: Exp, env: Exp) -> Self

Construct Exp::Trans.

Source

pub fn cell_new(v: Exp) -> Self

Construct Exp::CellNew.

Source

pub fn cell_read(c: Exp) -> Self

Construct Exp::CellRead.

Source

pub fn cell_set(c: Exp, v: Exp) -> Self

Construct Exp::CellSet.

Trait Implementations§

Source§

impl Clone for Exp

Source§

fn clone(&self) -> Exp

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Exp

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for Exp

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl PartialEq for Exp

Source§

fn eq(&self, other: &Exp) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for Exp

Auto Trait Implementations§

§

impl Freeze for Exp

§

impl RefUnwindSafe for Exp

§

impl !Send for Exp

§

impl !Sync for Exp

§

impl Unpin for Exp

§

impl UnwindSafe for Exp

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.