#compiler #hash-map #performance #symbol-table #scope

ax-sym

High-performance scoped symbol table for compilers, linters, and LSP servers — backed by axhash-map

4 releases (1 stable)

Uses new Rust 2024

1.0.0 May 29, 2026
0.1.2 May 19, 2026
0.1.1 May 19, 2026
0.1.0 May 7, 2026

#1189 in Data structures

MIT license

17KB
378 lines

ax-sym

High-performance scoped symbol table for compilers, linters, and LSP servers.

Powered by axhash-map.

Crates.io Docs.rs License: MIT


Why ax-sym?

Compiler front-ends repeatedly perform symbol lookups during parsing, type checking, and name resolution.

ax-sym provides a scoped symbol table optimized for:

  • Fast nested-scope lookup
  • Efficient symbol insertion
  • Minimal hashing overhead
  • Compiler and LSP workloads

Ecosystem

Crate Description
axhash AES-accelerated hashing
axhash-map Fast HashMap/HashSet
axhash-indexmap Ordered hash maps
axhash-dashmap Concurrent DashMap
ax-sym Scoped symbol table

Installation

[dependencies]
ax-sym = "0.1"

Quick Start

use ax_sym::{
    ScopedSymbolTable,
    SymbolData,
    SymbolKind,
    SourceLocation,
};

let mut table =
    ScopedSymbolTable::new();

let loc =
    SourceLocation::new(0, 1, 1);

table.define(
    "println".to_string(),
    SymbolData::new(
        0,
        SymbolKind::Function,
        loc,
    ).public(),
);

table.push_scope();

table.define(
    "x".to_string(),
    SymbolData::new(
        1,
        SymbolKind::Variable,
        loc,
    ),
);

assert!(table.resolve("x").is_some());

table.pop_scope();

assert!(table.resolve("x").is_none());

Constructors

Method Description
new() Default global scope
with_scope_capacity(n) Pre-allocate scope
with_capacity(depth, n) Pre-allocate multiple scopes

Scope Management

Method Description
push_scope() Enter scope
pop_scope() Leave scope
depth() Current nesting depth
scope_count() Total active scopes

Symbol Operations

Method Description
define() Insert symbol
define_symbol() Auto-ID symbol insertion
resolve() Resolve symbol
resolve_mut() Mutable resolve
resolve_with_depth() Resolve with scope depth
is_defined_locally() Check local scope
total_symbols() Total active symbols

Symbol Metadata

pub struct SymbolData {
    pub id: u32,
    pub kind: SymbolKind,
    pub location: SourceLocation,
    pub is_used: bool,
    pub is_public: bool,
}

SymbolKind

pub enum SymbolKind {
    Variable,
    Function,
    Type,
    Constant,
    Module,
    Other(String),
}

Depth-aware Resolution

let result =
    table.resolve_with_depth("outer")
        .unwrap();

assert_eq!(result.depth, 2);

Useful for closure capture analysis and compiler lowering.


Mark-as-used Pattern

if let Some(sym) =
    table.resolve_mut("x")
{
    sym.mark_used();
}

Pre-allocation

use ax_sym::ScopedSymbolTable;

let table =
    ScopedSymbolTable::with_capacity(
        8,
        50,
    );

Useful for avoiding reallocations in deep compiler passes.


Benchmarks

cargo bench --bench symbol_table

Benchmarks include:

  • define
  • resolve hit
  • resolve miss
  • deep lookup
  • mixed workloads

License

MIT

Dependencies

~0.6–2MB
~34K SLoC