Skip to main content

Context

Struct Context 

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

A hash-consed expression arena.

A context owns every node it creates. Nodes are immutable and appended in creation order, and every child index is lower than its parent’s, so ascending index order is a topological order. Structurally equal expressions are the same node (“equal handle implies equal value”; the converse does not hold). Every node is in canonical form: constants are folded, commutative operands are ordered (constants last) independently of construction order, and a fixed set of O(1) identities and cast collapses is applied (see docs/design.md §4.3).

use bitwright::{Context, Width};
let mut cx = Context::new();
let x = cx.symbol("x", Width::W32)?;
let one = cx.one(Width::W32)?;
let a = cx.add(one, x)?;
let b = cx.add(x, one)?;
assert_eq!(a, b);
let z = cx.xor(a, b)?;
assert_eq!(cx.as_const(z)?.map(|v| v.is_zero()), Some(true));

Implementations§

Source§

impl Context

Source

pub fn ext(&mut self, op: ExtId, args: &[Expr]) -> Result<Vec<Expr>, Error>

Every output of the extension call op(args) (1 to 3 arguments), in order. Needs a context built with a registry holding op (with_registry); outputs of calls on constants are constants.

Source

pub fn ext_output( &mut self, op: ExtId, k: usize, args: &[Expr], ) -> Result<Expr, Error>

Output k of the extension call op(args).

Source

pub fn constant(&mut self, v: &BitVec) -> Result<Expr, Error>

A constant.

Source

pub fn constant_u64(&mut self, width: Width, v: u64) -> Result<Expr, Error>

The constant v, which must fit in width bits.

Source

pub fn constant_u128(&mut self, width: Width, v: u128) -> Result<Expr, Error>

The constant v, which must fit in width bits.

Source

pub fn constant_i128(&mut self, width: Width, v: i128) -> Result<Expr, Error>

The constant v, which must be representable as a signed width-bit value.

Source

pub fn zero(&mut self, width: Width) -> Result<Expr, Error>

Zero.

Source

pub fn one(&mut self, width: Width) -> Result<Expr, Error>

One.

Source

pub fn ones(&mut self, width: Width) -> Result<Expr, Error>

All ones.

Source

pub fn bool(&mut self, b: bool) -> Result<Expr, Error>

A 1-bit constant.

Source

pub fn un(&mut self, op: UnOp, a: Expr) -> Result<Expr, Error>

A unary operator.

Source

pub fn bin(&mut self, op: BinOp, a: Expr, b: Expr) -> Result<Expr, Error>

A binary operator; the operands must have the same width.

Source

pub fn cmp( &mut self, op: impl Into<CmpOpExt>, a: Expr, b: Expr, ) -> Result<Expr, Error>

A comparison (1-bit result); the operands must have the same width.

Source

pub fn zext(&mut self, a: Expr, to: Width) -> Result<Expr, Error>

Zero extension to to (at least the operand’s width; equal width is the identity).

Source

pub fn sext(&mut self, a: Expr, to: Width) -> Result<Expr, Error>

Sign extension to to (at least the operand’s width; equal width is the identity).

Source

pub fn trunc(&mut self, a: Expr, to: Width) -> Result<Expr, Error>

The low to bits.

Source

pub fn extract(&mut self, a: Expr, lo: u16, len: Width) -> Result<Expr, Error>

Bits [lo, lo + len).

Source

pub fn concat(&mut self, hi: Expr, lo: Expr) -> Result<Expr, Error>

hi in the high bits, lo in the low bits.

Source

pub fn select( &mut self, cond: Expr, then: Expr, els: Expr, ) -> Result<Expr, Error>

cond ? then : els; the condition must be 1 bit wide.

Source§

impl Context

Source

pub fn not(&mut self, a: Expr) -> Result<Expr, Error>

Bitwise complement.

Source

pub fn neg(&mut self, a: Expr) -> Result<Expr, Error>

Two’s-complement negation.

Source

pub fn popcnt(&mut self, a: Expr) -> Result<Expr, Error>

Number of set bits.

Source

pub fn clz(&mut self, a: Expr) -> Result<Expr, Error>

Leading zeros (clz(0) = W).

Source

pub fn ctz(&mut self, a: Expr) -> Result<Expr, Error>

Trailing zeros (ctz(0) = W).

Source

pub fn bswap(&mut self, a: Expr) -> Result<Expr, Error>

Byte reversal (W % 8 == 0).

Source

pub fn bitrev(&mut self, a: Expr) -> Result<Expr, Error>

Bit reversal.

Source§

impl Context

Source

pub fn add(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Addition.

Source

pub fn sub(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Subtraction.

Source

pub fn mul(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Multiplication.

Source

pub fn umulhi(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

High half of the unsigned double-width product.

Source

pub fn smulhi(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

High half of the signed double-width product.

Source

pub fn udiv(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned division (udiv(x, 0) = ones).

Source

pub fn urem(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned remainder (urem(x, 0) = x).

Source

pub fn sdiv(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed division (bvsdiv).

Source

pub fn srem(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed remainder (bvsrem).

Source

pub fn and(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Bitwise and.

Source

pub fn or(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Bitwise or.

Source

pub fn xor(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Bitwise exclusive or.

Source

pub fn shl(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Left shift (a count >= W gives 0).

Source

pub fn lshr(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Logical right shift (a count >= W gives 0).

Source

pub fn ashr(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Arithmetic right shift (a count >= W gives the sign fill).

Source

pub fn rotl(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Rotate left by count mod W.

Source

pub fn rotr(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Rotate right by count mod W.

Source

pub fn pdep(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Parallel bit deposit.

Source

pub fn pext(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Parallel bit extract.

Source§

impl Context

Source

pub fn eq(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a == b.

Source

pub fn ne(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a != b.

Source

pub fn ult(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned a < b.

Source

pub fn ule(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned a <= b.

Source

pub fn ugt(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned a > b.

Source

pub fn uge(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned a >= b.

Source

pub fn slt(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed a < b.

Source

pub fn sle(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed a <= b.

Source

pub fn sgt(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed a > b.

Source

pub fn sge(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed a >= b.

Source§

impl Context

Derived constructors: they build existing node kinds.

Source

pub fn umin(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned minimum.

Source

pub fn umax(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Unsigned maximum.

Source

pub fn smin(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed minimum.

Source

pub fn smax(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed maximum.

Source

pub fn andn(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a & ~b.

Source

pub fn orn(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a | ~b.

Source

pub fn xnor(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

~(a ^ b).

Source

pub fn bit(&mut self, a: Expr, i: u16) -> Result<Expr, Error>

Bit i as a 1-bit value.

Source

pub fn abs(&mut self, a: Expr) -> Result<Expr, Error>

Absolute value (abs(smin) = smin).

Source

pub fn add_carry(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

The carry out of a + b (1 bit).

Source

pub fn sub_borrow(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

The borrow out of a - b (1 bit).

Source

pub fn sadd_overflow(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed overflow of a + b (1 bit).

Source

pub fn ssub_overflow(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

Signed overflow of a - b (1 bit).

Source

pub fn add_sat_u(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a + b clamped to the unsigned range: all ones when the sum carries out.

Source

pub fn sub_sat_u(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a - b clamped to the unsigned range: 0 when b exceeds a.

Source

pub fn add_sat_s(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a + b clamped to the signed range: the signed minimum or maximum on overflow.

Source

pub fn sub_sat_s(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

a - b clamped to the signed range: the signed minimum or maximum on overflow.

Source

pub fn mul_wide_u(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

The full 2W-bit unsigned product (2W <= 512).

Source

pub fn mul_wide_s(&mut self, a: Expr, b: Expr) -> Result<Expr, Error>

The full 2W-bit signed product (2W <= 512).

Source§

impl Context

Source

pub fn eval( &mut self, roots: &[Expr], env: &(impl Env + ?Sized), ) -> Result<Vec<BitVec>, Error>

Evaluates roots under env. Iterative and memoized per call: a shared node is evaluated once.

Source

pub fn substitute( &mut self, roots: &[Expr], map: &[(Expr, Expr)], ) -> Result<Vec<Expr>, Error>

Simultaneously replaces every occurrence of each from by its to in roots (replacements are not substituted again), rebuilding through the canonicalizing constructors. Each pair must have equal widths.

Source

pub fn substitute_bounded( &mut self, roots: &[Expr], s: &mut Substitution, max_visits: u64, ) -> Result<Option<Vec<Expr>>, Error>

Applies the substitution s to roots, working on at most max_visits nodes not already in its memo. Ok(None) when that limit stops it first: the progress is kept in s, so a later call continues where this one stopped. The walk never descends below a replaced node or a node the memo already answers.

Source§

impl Context

Source

pub fn new() -> Self

An empty context with the default configuration. Allocates nothing until the first node.

Source

pub fn with_config(config: ContextConfig) -> Self

An empty context.

Source

pub fn with_registry(config: ContextConfig, registry: Arc<Registry>) -> Self

An empty context that can build the extension operations of registry.

Source

pub fn registry(&self) -> Option<&Registry>

The extension operations this context can build.

Source

pub fn extend_registry(&mut self, registry: Arc<Registry>) -> Result<(), Error>

Replaces the registry by one that extends it: every operation of the current registry is at the same position in registry (same name, revision and traits), so every existing node keeps its meaning and canonical form. Otherwise an error, and nothing changes.

Source

pub fn config(&self) -> &ContextConfig

The configuration.

Source

pub fn set_max_nodes(&mut self, n: u32)

Changes the node limit (ContextConfig::max_nodes). Existing nodes stay; a limit below the current size only stops new nodes from being created (lookups of existing structure still succeed).

Source

pub fn len(&self) -> usize

The number of nodes.

Source

pub fn is_empty(&self) -> bool

Whether the context has no nodes.

Source

pub fn clear(&mut self)

Removes every node and symbol, keeping allocations. Handles created before the call become stale and are rejected with Error::StaleExpr.

Source

pub fn counters(&self) -> ArenaCounters

Node creation counters.

Source

pub fn mark(&self) -> Mark

The current position of the caller-growth counter.

Source

pub fn caller_growth_since(&self, mark: Mark) -> u64

New nodes created by the caller since mark (all of them, if the mark is from another context or from before a clear()). Nodes created by the library itself are not counted.

Source

pub fn width(&self, e: Expr) -> Result<Width, Error>

The width of an expression.

Source

pub fn view(&self, e: Expr) -> Result<View, Error>

A read-only view of an expression’s top node.

Source

pub fn children( &self, e: Expr, ) -> Result<impl Iterator<Item = Expr> + '_, Error>

The expression’s direct operands, in order.

Source

pub fn as_const(&self, e: Expr) -> Result<Option<BitVec>, Error>

The value, if the expression is a constant node.

Source

pub fn is_leaf(&self, e: Expr) -> Result<bool, Error>

Whether the expression is a constant or a symbol.

Source

pub fn height(&self, e: Expr) -> Result<u32, Error>

Structural depth (leaves are 0), saturating at u32::MAX. O(1).

Source

pub fn tree_size(&self, e: Expr) -> Result<u32, Error>

The size of the expression unfolded as a tree, saturating at u32::MAX. O(1).

Source

pub fn symbol( &mut self, key: impl Into<SymbolKey>, width: Width, ) -> Result<Expr, Error>

The symbol for key, created at width width on first use. A key has exactly one width per context.

Source

pub fn fresh_symbol(&mut self, width: Width) -> Result<Expr, Error>

A new symbol with a key that is not yet used in this context.

Source

pub fn find_symbol(&self, key: &SymbolKey) -> Option<Expr>

The symbol for key, if it exists. Never creates.

Source

pub fn symbol_id(&self, e: Expr) -> Result<Option<SymbolId>, Error>

The symbol id, if the expression is a symbol node.

Source

pub fn symbol_key(&self, id: SymbolId) -> Option<&SymbolKey>

A symbol’s key.

Source

pub fn symbol_width(&self, id: SymbolId) -> Option<Width>

A symbol’s width.

Source

pub fn symbol_count(&self) -> usize

The number of symbols.

Source

pub fn post_order(&mut self, roots: &[Expr]) -> Result<Vec<Expr>, Error>

Every node reachable from roots, each once, children before parents. Iterative.

Source

pub fn symbols_in(&mut self, roots: &[Expr]) -> Result<Vec<SymbolId>, Error>

The symbols reachable from roots, sorted by key.

Source

pub fn dag_size(&mut self, roots: &[Expr], cap: u32) -> Result<Bounded, Error>

The number of distinct nodes reachable from roots, walking at most cap + 1 nodes. Exact single-root results are cached.

Source§

impl Context

Source

pub fn facts(&mut self, e: Expr) -> Result<Facts, Error>

Facts about e. If the per-query work cap (ContextConfig::fact_work) is reached, the answer is Facts::top (sound, just imprecise); see Context::try_facts.

Source

pub fn try_facts(&mut self, e: Expr) -> Result<Option<Facts>, Error>

Facts about e, or None if the per-query work cap was reached first. Progress is kept: repeating the call for the same expression continues where it stopped.

Source

pub fn exact(&mut self, e: Expr) -> Result<Option<BitVec>, Error>

The value of e if its facts pin exactly one.

Source

pub fn enumerate_values( &mut self, e: Expr, limit: u32, ) -> Result<Option<Vec<BitVec>>, Error>

The values e’s facts allow, if there are at most limit of them (and at most 2^20 candidates to examine). Every value e can take is included; some included values may be impossible, since facts over-approximate.

Source

pub fn facts_with( &mut self, e: Expr, assumptions: &Assumptions, ) -> Result<Option<Facts>, Error>

Facts about e under assumptions, or None if the assumptions are infeasible for the part of the expression that e depends on. Never pollutes the base cache.

Source

pub fn facts_under( &mut self, e: Expr, assumptions: &Assumptions, ) -> Result<Option<(Facts, Reliance)>, Error>

Facts about e under assumptions, with the constraints they rely on; None if the assumptions are infeasible. Never pollutes the base cache.

Source

pub fn prove(&mut self, q: Query<'_>) -> Result<Truth, Error>

Answers a question from facts. Every True/False is proved; Unknown otherwise.

Source

pub fn prove_with( &mut self, q: Query<'_>, assumptions: &Assumptions, ) -> Result<Truth, Error>

Answers a question from facts under assumptions. Infeasible assumptions prove anything: every well-formed question is answered True.

Source

pub fn prove_under( &mut self, q: Query<'_>, assumptions: &Assumptions, ) -> Result<Proof, Error>

Context::prove_with, also reporting the constraints the answer relies on.

Source§

impl Context

Source

pub fn parse(&mut self, src: &str, opts: &ParseOptions) -> Result<Expr, Error>

Parses an expression in the text syntax (see docs/design.md §7.1), creating symbols as needed, and builds it through the canonicalizing constructors.

use bitwright::{Context, ParseOptions, Width};
let mut cx = Context::new();
let e = cx.parse("(y | x) + (y & x)", &ParseOptions::width(Width::W64))?;
// Built canonically: operands of commutative operators in one order.
assert_eq!(cx.display(e).to_string(), "(x & y) + (x | y)");
Source§

impl Context

Source

pub fn display(&self, e: Expr) -> Display<'_>

The expression in the text syntax, with the default PrintOptions.

Source

pub fn display_with(&self, e: Expr, opts: PrintOptions) -> Display<'_>

The expression in the text syntax.

Trait Implementations§

Source§

impl Debug for Context

Source§

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

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

impl Default for Context

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

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