Module: TreeHaver::LanguageRegistry Private

Defined in:
lib/tree_haver/language_registry.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Thread-safe language registrations and cache for loaded Language handles

The LanguageRegistry provides two main functions:

  1. Registrations: Store mappings from language names to backend-specific configurations

  2. Cache: Memoize loaded Language objects to avoid repeated dlopen calls

The registry supports multiple backends for the same language, allowing runtime switching, benchmarking, and fallback scenarios.

Registration structure: “‘ruby } “`

“‘ruby

TreeHaver::LanguageRegistry.register(:toml, :tree_sitter,
  path: "/path/to/lib.so", symbol: "tree_sitter_toml")

“‘

“‘ruby

TreeHaver::LanguageRegistry.register(:toml, :citrus,
  grammar_module: TomlRB::Document, gem_name: "toml-rb")

“‘

Examples:

Register tree-sitter grammar


Register Citrus grammar


Class Method Summary collapse

Class Method Details

.clear_cache!void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Clear the language cache

Removes all cached Language objects. The next call to fetch for any key will recompute the value. Does not clear registrations.

Examples:

LanguageRegistry.clear_cache!


131
132
133
134
# File 'lib/tree_haver/language_registry.rb', line 131

def clear_cache!
  @mutex.synchronize { @cache.clear }
  nil
end

.fetch(key) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Fetch a cached language by key or compute and store it

This method provides thread-safe memoization for loaded Language objects. If the key exists in the cache, the cached value is returned immediately. Otherwise, the block is called to compute the value, which is then cached.

Examples:

language = LanguageRegistry.fetch(["/path/lib.so", "symbol", "toml"]) do
  expensive_language_load_operation
end

Parameters:

  • key (Array)

    cache key, typically [path, symbol, name]

Yield Returns:

  • (Object)

    the computed language handle (called only on cache miss)

Returns:

  • (Object)

    the cached or computed language handle



115
116
117
118
119
120
121
# File 'lib/tree_haver/language_registry.rb', line 115

def fetch(key)
  @mutex.synchronize do
    return @cache[key] if @cache.key?(key)
    value = yield
    @cache[key] = value
  end
end

.register(name, backend_type, **config) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Register a language for a specific backend

Stores backend-specific configuration for a language. Multiple backends can be registered for the same language without conflict.

Examples:

Register tree-sitter grammar

LanguageRegistry.register(:toml, :tree_sitter,
  path: "/usr/local/lib/libtree-sitter-toml.so", symbol: "tree_sitter_toml")

Register Citrus grammar

LanguageRegistry.register(:toml, :citrus,
  grammar_module: TomlRB::Document, gem_name: "toml-rb")

Parameters:

  • name (Symbol, String)

    language identifier (e.g., :toml, :json)

  • backend_type (Symbol)

    backend type (:tree_sitter, :citrus, :mri, :rust, :ffi, :java)

  • config (Hash)

    backend-specific configuration

Options Hash (**config):

  • :path (String)

    tree-sitter library path (for tree-sitter backends)

  • :symbol (String)

    exported symbol name (for tree-sitter backends)

  • :grammar_module (Module)

    Citrus grammar module (for Citrus backend)

  • :gem_name (String)

    gem name for error messages (for Citrus backend)



62
63
64
65
66
67
68
69
70
71
# File 'lib/tree_haver/language_registry.rb', line 62

def register(name, backend_type, **config)
  key = name.to_sym
  backend_key = backend_type.to_sym

  @mutex.synchronize do
    @registrations[key] ||= {}
    @registrations[key][backend_key] = config.compact
  end
  nil
end

.registered(name, backend_type = nil) ⇒ Hash{Symbol => Hash}, ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Fetch registration entries for a language

Returns all backend-specific configurations for a language.

Examples:

Get all backends

entries = LanguageRegistry.registered(:toml)
# => {
#   tree_sitter: { path: "/usr/local/lib/libtree-sitter-toml.so", symbol: "tree_sitter_toml" },
#   citrus: { grammar_module: TomlRB::Document, gem_name: "toml-rb" }
# }

Get specific backend

entry = LanguageRegistry.registered(:toml, :citrus)
# => { grammar_module: TomlRB::Document, gem_name: "toml-rb" }

Parameters:

  • name (Symbol, String)

    language identifier

  • backend_type (Symbol, nil) (defaults to: nil)

    optional backend type to filter by

Returns:

  • (Hash{Symbol => Hash}, Hash, nil)

    all backends or specific backend config



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/tree_haver/language_registry.rb', line 89

def registered(name, backend_type = nil)
  @mutex.synchronize do
    lang_config = @registrations[name.to_sym]
    return unless lang_config

    if backend_type
      lang_config[backend_type.to_sym]
    else
      lang_config
    end
  end
end