Skip to main content

StackType

Enum StackType 

Source
pub enum StackType {
    Empty,
    Cons {
        rest: Box<StackType>,
        top: Type,
    },
    RowVar(String),
}
Expand description

Stack types with row polymorphism

§Understanding Stack Type Representation

Seq uses row polymorphism to type stack operations. The stack is represented as a linked list structure using Cons cells (from Lisp terminology).

§Components

  • Cons { rest, top }: A “cons cell” pairing a value type with the rest of the stack

    • top: The type of the value at this position
    • rest: What’s underneath (another Cons, Empty, or RowVar)
  • RowVar("name"): A row variable representing “the rest of the stack we don’t care about”

    • Enables polymorphic functions like dup that work regardless of stack depth
    • Written as ..name in stack effect signatures
  • Empty: An empty stack (no values)

§Debug vs Display Format

The Debug format shows the internal structure (useful for compiler developers):

Cons { rest: Cons { rest: RowVar("a$5"), top: Int }, top: Int }

The Display format shows user-friendly notation (matches stack effect syntax):

(..a$5 Int Int)

§Reading the Debug Format

To read Cons { rest: Cons { rest: RowVar("a"), top: Int }, top: Float }:

  1. Start from the outermost Cons - its top is the stack top: Float
  2. Follow rest to the next Cons - its top is next: Int
  3. Follow rest to RowVar("a") - this is the polymorphic “rest of stack”
Cons { rest: Cons { rest: RowVar("a"), top: Int }, top: Float }
│                                           │           │
│                                           │           └── top of stack: Float
│                                           └── second from top: Int
└── rest of stack: ..a (whatever else is there)

Equivalent to: (..a Int Float)  or in signature: ( ..a Int Float -- ... )

§Fresh Variables (e.g., “a$5”)

During type checking, variables are “freshened” to avoid name collisions:

  • a becomes a$0, a$1, etc.
  • The number is just a unique counter, not semantically meaningful
  • a$5 means “the 6th fresh variable generated with prefix ‘a’”

§Example Error Message

divide: stack type mismatch. Expected (..a$0 Int Int), got (..rest Float Float)

Meaning:

  • divide expects two Int values on top of any stack (..a$0)
  • You provided two Float values on top of the stack (..rest)
  • The types don’t match: Int vs Float

Variants§

§

Empty

Empty stack - no values

§

Cons

Stack with a value on top of rest (a “cons cell”)

Named after Lisp’s cons (construct) operation that builds pairs. Think of it as: top is the head, rest is the tail.

Fields

§rest: Box<StackType>

The rest of the stack (may be Empty, another Cons, or RowVar)

§top: Type

The type on top of the stack at this position

§

RowVar(String)

Row variable representing “rest of stack” for polymorphism

Allows functions to be polymorphic over stack depth. Example: dup has effect ( ..a T -- ..a T T ) where ..a means “whatever is already on the stack stays there”.

Implementations§

Source§

impl StackType

Source

pub fn empty() -> Self

Create an empty stack type

Source

pub fn singleton(ty: Type) -> Self

Create a stack type with a single value

Source

pub fn push(self, ty: Type) -> Self

Push a type onto a stack type

Source

pub fn from_vec(types: Vec<Type>) -> Self

Create a stack type from a vector of types (bottom to top)

Source

pub fn pop(self) -> Option<(StackType, Type)>

Pop a type from a stack type, returning (rest, top) if successful

Trait Implementations§

Source§

impl Clone for StackType

Source§

fn clone(&self) -> StackType

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for StackType

Source§

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

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

impl Display for StackType

Source§

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

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

impl Eq for StackType

Source§

impl Hash for StackType

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for StackType

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · 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 StackType

Auto Trait Implementations§

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> Same for T

Source§

type Output = T

Should always be Self
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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.