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: }

Examples:

Register tree-sitter grammar

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

Register Citrus grammar

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

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!


125
126
127
128
# File 'lib/tree_haver/language_registry.rb', line 125

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



109
110
111
112
113
114
115
# File 'lib/tree_haver/language_registry.rb', line 109

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)



56
57
58
59
60
61
62
63
64
65
# File 'lib/tree_haver/language_registry.rb', line 56

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



83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/tree_haver/language_registry.rb', line 83

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