Skip to main content

Node

Struct Node 

Source
pub struct Node { /* private fields */ }
Expand description

A child edge in an Expr: a reference-counted subterm together with the facts about it that the kernel needs in O(1) (structural sharing, wave5 Stage E; the hash and the three flags added for 0.1.4).

  • range — the subterm’s looseBVarRange: 1 + the largest loose de Bruijn index in the subterm (0 = closed). It lets a substitution or lift decide in O(1) whether a subtree is affected — range <= depth means “no loose bvar can be touched, share it unchanged” — without traversing the subtree.
  • cost — the size of the subterm counted as a TREE (a shared subterm once per path to it), saturating at REBUILD_COST_MAX: one unit per node plus one more per leaf, so cost(leaf) = 2 and cost(internal) = 1 + Σ cost(children). The reduction and def-eq caches read it to keep giant terms out (expr_util::expr_size_within). Through 0.1.4’s first performance pass this was also what a substitution charged to the per-declaration budget for a subtree it shared instead of rebuilding; sharing a subtree now charges one unit (see crate::fuel).
  • hash — the hash of the subterm’s structure (the kernel-private structural_hash module documents it). Hash writes it instead of walking the subterm, and == uses it as a fast negative test.
  • three flags — whether the subterm contains a free variable, a universe parameter, a universe metavariable. They let the operations that only concern those (abstracting a free variable, instantiating universe parameters, the universe hygiene check of a declaration) pass over everything else without visiting it.

All of them are computed once, bottom-up, in Node::new from the subterm’s own immediate children (also Nodes), so construction stays O(nodes) and none of them ever needs a traversal.

§Layout

The facts live in the shared allocation, next to the subterm; a Node is one pointer. (Through 0.1.3 range and cost sat on the edge beside the pointer, and the allocation held the bare Expr.) An allocation is the two reference counts, 16 bytes of facts and a 40-byte Expr — 72 bytes where the old layout used 80, with the hash and the flags added (the flags share a word with cost) — and an Expr held by value, as every cache key is, is 40 bytes where it was 64. Reading a fact dereferences the edge, which costs nothing extra where it matters: a substitution that skips a subtree shares it by bumping the reference count stored right beside the facts, and one that does not skip it walks into it.

Node is a transparent wrapper: it Derefs to the inner Expr, and its PartialEq/Eq/Hash are those of the subterm (so the instances on Expr keep exactly their structural meaning). The cached facts are functions of the subterm and so never change what is equal to what.

Implementations§

Source§

impl Node

Source

pub fn new(e: Expr) -> Node

Wrap an Expr as a child edge, caching its looseBVarRange, its tree size, its content flags and the hash of its structure. O(1): each is read off the cached facts of e’s immediate children (for a Sort or a Const, off its universe levels).

In a build that tracks the depth of terms (crate::fuel::TERM_DEPTH_TRACKED) the depth is cached too, and a subterm deeper than the limit of crate::fuel::set_term_depth_limit spends the budget of the declaration being checked.

Source

pub fn range(&self) -> u32

The cached looseBVarRange of this subterm (O(1)).

Source

pub fn rebuild_cost(&self) -> u32

The cached size of this subterm counted as a tree (O(1)); see Expr::rebuild_cost.

Source

pub fn as_ptr(&self) -> *const Expr

The address of the shared subterm. Two nodes return the same address exactly when they share one allocation, for as long as either is alive — so the address can key a memo table over a term whose subterms are shared, visiting each shared subterm once.

The pointer is for comparison only. (This replaces rc(), which exposed the Rc<Expr> the edge used to hold.)

Source

pub fn ptr_eq(this: &Node, other: &Node) -> bool

Whether two nodes share one allocation (which implies they are equal; equal nodes need not share one).

Methods from Deref<Target = Expr>§

Source

pub fn range(&self) -> u32

This node’s looseBVarRange — 1 + the largest loose de Bruijn index, or 0 if closed. O(1): it reads the immediate children’s cached ranges (see Node) and combines them, accounting for the binders each child sits under.

Source

pub fn rebuild_cost(&self) -> u32

The size of this term counted as a TREE — a shared subterm once per path to it — O(1) from the children’s cached sizes: one unit per node and one more per leaf, so cost(leaf) = 2 and cost(internal) = 1 + Σ cost(children), saturating at REBUILD_COST_MAX. It is what rebuilding the term node by node, with no sharing, would cost; the caches read it to keep giant terms out.

Source

pub fn is_sort(&self) -> bool

Check if this is a Sort.

Source

pub fn is_prop(&self) -> bool

Check if this is Prop.

Source

pub fn is_bvar(&self) -> bool

Check if this is a bound variable.

Source

pub fn is_fvar(&self) -> bool

Check if this is a free variable.

Source

pub fn is_app(&self) -> bool

Check if this is an application.

Source

pub fn is_lambda(&self) -> bool

Check if this is a lambda.

Source

pub fn is_pi(&self) -> bool

Check if this is a Pi type.

Source

pub fn is_let(&self) -> bool

Check if this expression is a let binding.

Source

pub fn is_lit(&self) -> bool

Check if this expression is a literal.

Source

pub fn is_const(&self) -> bool

Check if this expression is a named constant.

Source

pub fn is_proj(&self) -> bool

Check if this expression is a projection.

Source

pub fn is_atom(&self) -> bool

Check if this expression is an “atom” (cannot be further reduced without context): Sort, BVar, FVar, Const, Lit.

Source

pub fn as_bvar(&self) -> Option<u32>

Extract the bound variable index, or None.

Source

pub fn as_fvar(&self) -> Option<FVarId>

Extract the free variable ID, or None.

Source

pub fn as_const_name(&self) -> Option<&Name>

Extract the constant name, or None.

Source

pub fn as_sort_level(&self) -> Option<&Level>

Extract the sort level, or None.

Source

pub fn app_head_args(&self) -> (&Expr, Vec<&Expr>)

Return the head and argument list of an application spine.

For f a b c, returns (&f, [&a, &b, &c]).

Source

pub fn app_arity(&self) -> usize

Return the number of arguments in an application spine.

Source

pub fn pi_arity(&self) -> usize

Count the number of leading Pi binders.

Source

pub fn lam_arity(&self) -> usize

Count the number of leading Lambda binders.

Source

pub fn size(&self) -> usize

Compute the AST size (total number of nodes).

Source

pub fn ast_depth(&self) -> usize

Compute the AST depth (longest path to a leaf).

Source

pub fn has_loose_bvar_at(&self, d: u32) -> bool

Check if this expression has any loose bound variables at depth d.

Source

pub fn count_bvar_occurrences(&self, idx: u32) -> usize

Count occurrences of bound variable BVar(idx) in this expression.

Source

pub fn is_closed(&self) -> bool

Check if this expression is closed (no loose bound variables).

Source

pub fn free_vars(&self) -> HashSet<FVarId>

Collect all free variable IDs occurring in this expression.

Source

pub fn constants(&self) -> HashSet<Name>

Collect all constant names occurring in this expression.

Trait Implementations§

Source§

impl AsRef<Expr> for Node

Source§

fn as_ref(&self) -> &Expr

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Borrow<Expr> for Node

Source§

fn borrow(&self) -> &Expr

Immutably borrows from an owned value. Read more
Source§

impl Clone for Node

Source§

fn clone(&self) -> Self

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 Node

Source§

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

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

impl Deref for Node

Source§

type Target = Expr

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Expr

Dereferences the value.
Source§

impl Display for Node

Source§

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

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

impl Eq for Node

Source§

impl Hash for Node

Source§

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

Writes the cached structural hash: what Expr’s Hash writes for the subterm (as Borrow<Expr> requires), without walking it.

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 Node

Source§

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

Structural equality of the two subterms, decided without comparing them when it can be: one allocation is equal to itself, and two subterms whose cached hashes differ are different (equal terms always hash equal). Only when the hashes agree are the subterms compared.

1.0.0 (const: unstable) · Source§

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

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl !Send for Node

§

impl !Sync for Node

§

impl Forget for Node

§

impl Freeze for Node

§

impl Move for Node

§

impl RefUnwindSafe for Node

§

impl Unpin for Node

§

impl UnsafeUnpin for Node

§

impl UnwindSafe for Node

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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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 = !

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

fn try_from(value: U) -> Result<T, !>

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.