Skip to content

refactor: split Stdlib::Functions into autoloaded adapters - #759

Open
ronaldtse wants to merge 7 commits into
mainfrom
feat/stdlib-functions-autoload
Open

refactor: split Stdlib::Functions into autoloaded adapters#759
ronaldtse wants to merge 7 commits into
mainfrom
feat/stdlib-functions-autoload

Conversation

@ronaldtse

Copy link
Copy Markdown
Contributor

Summary

  • Extract RababaAdapter and SecrystAdapter from the monolithic Interscript::Stdlib::Functions module into their own files.
  • Simple text-transform functions (title_case, downcase, compose, decompose, separate, unseparate) stay inline.
  • Parent namespace file (lib/interscript/stdlib/functions.rb) autoloads the two heavy adapters.
  • Public API (Interscript::Stdlib::Functions.<name>) is unchanged. All callers in interpreter.rb and compiler/ruby.rb work without edits.

Design

  • OCP: adding a new ML adapter = one new file + one autoload entry. No framework edits.
  • MECE: parent namespace owns the public surface; each adapter owns its model lifecycle (lazy load, mutex-protected cache, lazy require of external gem).
  • DRY: RababaAdapter.reverse (strip harakat) works without the gem loaded, since it's pure regex.
  • No require_relative. No internal require "interscript/...". Only autoload entries.

Test plan

  • spec/stdlib_functions_spec.rb (14 examples, all green)
  • Smoke test: ruby -Ilib -e "require 'interscript'; puts Interscript::Stdlib::Functions.title_case('hello world')"
  • Smoke test: Interscript::Stdlib::Functions.rababa_reverse('كَتَبَ') returns 'كتب' without loading the rababa gem
  • Interscript::Stdlib.available_functions unchanged
  • No require_relative added (grep clean)

Note: existing specs in this repo can't be run in my dev env because spec/spec_helper.rb does require "bundler/setup" and the local bundler install is broken (vendored thor references the removed DidYoumean::SPELL_CHECKERS constant under Ruby 3.4). The new spec bypasses spec_helper and runs cleanly under ruby -Ilib -S rspec --no-profile.

Adds a new compiler that walks the AST and emits JSON IR consumed by
interscript-ts. Mirrors the structure of Compiler::Javascript but
produces data, not code.

## IR schema (v1)
- schemaVersion: 1
- systemCode, dependencies[], metadata, stages[], aliases, functions

## Stage serialisation
- Each Stage becomes { kind: 'stage', name, rules: [...] }
- Group::Parallel -> { kind: 'parallel', rules: [...] }
- Group::Sequential -> { kind: 'sequential', rules: [...] }

## Rule serialisation
- Sub: from/to/before/after/notBefore/notAfter/priority (omitted if nil)
- Run: stage name + resolved docName (dependency alias -> system code)
- Funcall: name + kwargs

## Item serialisation
- String, CaptureGroup, CaptureRef, Alias, Any, Group, Repeat, Stage

## Resolution
- Run rule's docName resolves via dep_aliases so consumers don't need
  the Ruby dep_aliases indirection

## Rakefile
- New task compile:json_ir (parallel to existing compile:javascript)

Refs: interscript/interscript#3
posix library defines :upper, :lower; unicode defines combining marks.
These aliases were missing from the IR output, causing interscript-ts
to fail on maps that reference them (German β, Belarusian Е, etc.).
posix/unicode/var-Cyrl/var-kor define character classes (upper, jamo,
etc.) that maps reference via alias() without listing the library as a
direct dependency. Now merged unconditionally into every map's IR.
Ruby's Node::Item::Any compiles differently depending on the payload:
Array → alternation `(?:a|b|c)`, String → char class `[abc]`, Range →
char class `[a-z]`. The IR serialiser was treating all three the same
(Array form), which expanded Ranges via String#succ into nonsense
like "zzz" and missed most of the BMP. Maps that used
`any("\\u0061".."\\uFFFF")` for post-rule upcase failed because the
expanded list didn't include extended-Latin characters like ā.

Emit {kind: "any_char_class", range: [first, last]} for Range payloads
and {kind: "any_char_class", chars: [...]} for String payloads. The
interscript-ts runtime handles both forms via the AnyCharClassItem
variant introduced in the parallel-mode parity work.

Companion PR: interscript/interscript-ts#5
Every internal library require replaced with autoload entries defined
in the immediate parent namespace file. Zero require_relative calls.

Files changed:
- lib/interscript.rb: autoload for Stdlib, Compiler, Interpreter,
  DSL, Node, Detector, VERSION (was 6 explicit requires)
- lib/interscript/node.rb: autoload for all Node subtypes
- lib/interscript/node/item.rb: autoload for all Item subtypes
  including Maybe/MaybeSome/Some (subclasses in repeat.rb)
- lib/interscript/node/group.rb: autoload for Parallel, Sequential
- lib/interscript/node/rule.rb: autoload for Sub, Run, Funcall
- lib/interscript/dsl.rb: autoload for all DSL modules
- lib/interscript/dsl/group.rb: autoload for Parallel
- lib/interscript/compiler.rb: autoload for Javascript, Python,
  Ruby, JsonIR
- lib/interscript/visualize.rb: autoload for Nodes, JSON

Verified: transliterate works with lazy autoload.
Extract RababaAdapter and SecrystAdapter from the monolithic Functions
module into their own files, autoloaded from the parent namespace.
Simple text-transform functions (title_case, downcase, compose, etc.)
stay inline since they have no heavy dependencies.

- lib/interscript/stdlib.rb: add autoload :Functions entry
- lib/interscript/stdlib/functions.rb: parent namespace file with
  autoload for RababaAdapter and SecrystAdapter
- lib/interscript/stdlib/functions/rababa_adapter.rb: mutex-protected
  diacritizer cache; reverse() works without the gem loaded
- lib/interscript/stdlib/functions/secryst_adapter.rb: per-model
  translator cache

Public API (Interscript::Stdlib::Functions.<name>) is unchanged.
Callers in interpreter.rb and compiler/ruby.rb work without edits.

Zero require_relative added. Zero internal require added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant