Skip to main content

CompilerContext

Struct CompilerContext 

Source
pub struct CompilerContext {
    pub domains: HashMap<String, DomainInfo>,
    pub var_to_domain: HashMap<String, String>,
    pub var_to_axis: HashMap<String, char>,
    pub config: CompilationConfig,
    pub let_bindings: HashMap<String, usize>,
    /* private fields */
}
Expand description

Compiler context for managing compilation state.

The CompilerContext tracks all stateful information needed during compilation:

  • Domain definitions and their cardinalities
  • Variable-to-domain bindings
  • Variable-to-axis assignments (for einsum notation)
  • Temporary tensor name generation
  • Compilation configuration (logic-to-tensor mapping strategies)
  • Optional SymbolTable integration for schema-driven compilation

§Lifecycle

  1. Create a new context with CompilerContext::new(), CompilerContext::with_config(), or CompilerContext::from_symbol_table()
  2. Register domains with add_domain
  3. Optionally bind variables to domains with bind_var
  4. Pass the context to compile_to_einsum_with_context
  5. Axes are automatically assigned during compilation

§Examples

§Basic Usage

use tensorlogic_compiler::{CompilerContext, CompilationConfig};

// Use default soft_differentiable strategy
let mut ctx = CompilerContext::new();

// Or use a specific strategy
let mut ctx_fuzzy = CompilerContext::with_config(
    CompilationConfig::fuzzy_lukasiewicz()
);

// Register domains
ctx.add_domain("Person", 100);
ctx.add_domain("City", 50);

// Optionally bind variables (or let the compiler infer)
ctx.bind_var("x", "Person").unwrap();

§Schema-Driven Compilation

use tensorlogic_compiler::CompilerContext;
use tensorlogic_adapters::{SymbolTable, DomainInfo};

// Create a symbol table with schema
let mut table = SymbolTable::new();
table.add_domain(DomainInfo::new("Person", 100)).unwrap();

// Create context from symbol table
let ctx = CompilerContext::from_symbol_table(&table);

// Domains are automatically imported
assert!(ctx.domains.contains_key("Person"));

Fields§

§domains: HashMap<String, DomainInfo>

Registered domains with their metadata

§var_to_domain: HashMap<String, String>

Variable-to-domain bindings

§var_to_axis: HashMap<String, char>

Variable-to-axis assignments (e.g., ‘x’ → ‘a’, ‘y’ → ‘b’)

§config: CompilationConfig

Compilation configuration (strategies for logic operations)

§let_bindings: HashMap<String, usize>

Let bindings: variable name to tensor index

Implementations§

Source§

impl CompilerContext

Source

pub fn new() -> Self

Creates a new, empty compiler context with default configuration.

The context starts with no domains, no variable bindings, axis assignment beginning at ‘a’, and uses the default soft_differentiable compilation strategy.

§Examples
use tensorlogic_compiler::CompilerContext;

let ctx = CompilerContext::new();
assert!(ctx.domains.is_empty());
Source

pub fn with_config(config: CompilationConfig) -> Self

Creates a new compiler context with a specific configuration.

Use this to control how logical operations are compiled to tensor operations.

§Examples
use tensorlogic_compiler::{CompilerContext, CompilationConfig};

// Use Łukasiewicz fuzzy logic (satisfies De Morgan's laws)
let ctx = CompilerContext::with_config(
    CompilationConfig::fuzzy_lukasiewicz()
);

// Use hard Boolean logic
let ctx_bool = CompilerContext::with_config(
    CompilationConfig::hard_boolean()
);
Source

pub fn from_symbol_table(table: &SymbolTable) -> Self

Creates a compiler context from a SymbolTable for schema-driven compilation.

This constructor automatically imports all domains from the symbol table and validates the schema. It enables type-safe compilation with rich predicate signatures and domain hierarchies.

§Arguments
  • table - The symbol table containing domain and predicate definitions
§Examples
use tensorlogic_compiler::CompilerContext;
use tensorlogic_adapters::{SymbolTable, DomainInfo, PredicateInfo};

let mut table = SymbolTable::new();
table.add_domain(DomainInfo::new("Person", 100)).unwrap();
table.add_predicate(PredicateInfo::new(
    "knows",
    vec!["Person".to_string(), "Person".to_string()]
)).unwrap();

let ctx = CompilerContext::from_symbol_table(&table);

assert_eq!(ctx.domains.len(), 1);
assert!(ctx.domains.contains_key("Person"));
Source

pub fn from_symbol_table_with_config( table: &SymbolTable, config: CompilationConfig, ) -> Self

Creates a compiler context from a SymbolTable with a specific configuration.

Combines schema-driven compilation with custom compilation strategies.

§Examples
use tensorlogic_compiler::{CompilerContext, CompilationConfig};
use tensorlogic_adapters::{SymbolTable, DomainInfo};

let mut table = SymbolTable::new();
table.add_domain(DomainInfo::new("Person", 100)).unwrap();

let ctx = CompilerContext::from_symbol_table_with_config(
    &table,
    CompilationConfig::fuzzy_lukasiewicz()
);
Source

pub fn add_domain(&mut self, name: impl Into<String>, cardinality: usize)

Registers a new domain with its cardinality.

Domains must be registered before they can be used for variable bindings or quantifiers. The cardinality determines the size of the tensor dimension for variables in this domain.

§Arguments
  • name - The domain name (e.g., “Person”, “City”)
  • cardinality - The number of possible values in this domain
§Examples
use tensorlogic_compiler::CompilerContext;

let mut ctx = CompilerContext::new();
ctx.add_domain("Person", 100);
ctx.add_domain("City", 50);

assert_eq!(ctx.domains.len(), 2);
assert_eq!(ctx.domains.get("Person").unwrap().cardinality, 100);
Source

pub fn add_domain_info(&mut self, domain: DomainInfo)

Registers a domain with full metadata.

Use this method when you have a complete DomainInfo instance with metadata, descriptions, or parametric types.

§Examples
use tensorlogic_compiler::CompilerContext;
use tensorlogic_adapters::DomainInfo;

let mut ctx = CompilerContext::new();
let domain = DomainInfo::new("Person", 100)
    .with_description("All persons in the system");

ctx.add_domain_info(domain);

assert!(ctx.domains.get("Person").unwrap().description.is_some());
Source

pub fn bind_var(&mut self, var: &str, domain: &str) -> Result<()>

Binds a variable to a specific domain.

This is optional - the compiler can often infer domains from quantifiers. However, explicit bindings can be useful for type checking and validation.

§Arguments
  • var - The variable name (e.g., “x”, “y”)
  • domain - The domain name (must be already registered)
§Errors

Returns an error if the specified domain has not been registered.

§Examples
use tensorlogic_compiler::CompilerContext;

let mut ctx = CompilerContext::new();
ctx.add_domain("Person", 100);

ctx.bind_var("x", "Person").unwrap();
assert_eq!(ctx.var_to_domain.get("x"), Some(&"Person".to_string()));

// Error: domain not registered
assert!(ctx.bind_var("y", "Unknown").is_err());
Source

pub fn assign_axis(&mut self, var: &str) -> char

Assigns an einsum axis to a variable.

Axes are assigned in lexicographic order (‘a’, ‘b’, ‘c’, …). If a variable already has an assigned axis, that axis is returned. Otherwise, a new axis is assigned and the counter is incremented.

§Arguments
  • var - The variable name
§Returns

The axis character assigned to this variable.

§Examples
use tensorlogic_compiler::CompilerContext;

let mut ctx = CompilerContext::new();

let axis_x = ctx.assign_axis("x");
assert_eq!(axis_x, 'a');

let axis_y = ctx.assign_axis("y");
assert_eq!(axis_y, 'b');

// Re-assigning returns the same axis
let axis_x_again = ctx.assign_axis("x");
assert_eq!(axis_x_again, 'a');
Source

pub fn fresh_temp(&mut self) -> String

Generates a fresh temporary tensor name.

Temporary tensors are used for intermediate results during compilation. Names are generated as “temp_0”, “temp_1”, etc.

§Returns

A unique temporary tensor name.

§Examples
use tensorlogic_compiler::CompilerContext;

let mut ctx = CompilerContext::new();

let temp1 = ctx.fresh_temp();
assert_eq!(temp1, "temp_0");

let temp2 = ctx.fresh_temp();
assert_eq!(temp2, "temp_1");
Source

pub fn get_axes(&self, terms: &[Term]) -> Result<String>

Gets the einsum axes string for a list of terms.

This is used internally during predicate compilation to determine the axes string for a predicate’s arguments.

§Arguments
  • terms - The list of terms (usually predicate arguments)
§Returns

A string of axis characters (e.g., “ab” for two variables)

§Errors

Returns an error if a variable term has not been assigned an axis.

§Examples
use tensorlogic_compiler::CompilerContext;
use tensorlogic_ir::Term;

let mut ctx = CompilerContext::new();
ctx.assign_axis("x");
ctx.assign_axis("y");

let terms = vec![Term::var("x"), Term::var("y")];
let axes = ctx.get_axes(&terms).unwrap();
assert_eq!(axes, "ab");

Trait Implementations§

Source§

impl Clone for CompilerContext

Source§

fn clone(&self) -> CompilerContext

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 CompilerContext

Source§

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

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

impl Default for CompilerContext

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