Skip to content

Commit 8ba63ba

Browse files
authored
fix(json-ir): serialise to the production corpus shape (#772)
JsonIR merged every library's aliases into every document and wrapped ISC any()-sets in group nodes. The production corpus carries only the document's own aliases and serialises any()-sets as {kind: "any", "of": [...]} — consumers resolve dependency and library aliases at runtime via the loader, matching interscript-ts's converter. Also renders string_case/compose/decompose stage items as Funcall rules in the NodeAdapter (4fdf15b never reached main): bare Symbols raise 'Cannot serialise rule of type Symbol' in JsonIR.
1 parent 0c7b5fc commit 8ba63ba

3 files changed

Lines changed: 45 additions & 34 deletions

File tree

‎lib/interscript/compiler/json_ir.rb‎

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,37 +38,9 @@ def serialise_document(doc)
3838
# without re-implementing the Ruby dep_aliases indirection.
3939
all_aliases = {}
4040

41-
# Walk dependencies and merge their alias definitions.
42-
# posix defines :upper, :lower; unicode defines :combining marks; etc.
43-
doc.dependencies.each do |dep|
44-
next unless dep.document
45-
dep.document.aliases.each do |aname, defn|
46-
all_aliases[aname.to_s] ||= serialise_item(defn.data)
47-
end
48-
end
49-
50-
# Also walk dep_aliases (for run-rule dependency resolution paths).
51-
doc.dep_aliases.each_value do |dep|
52-
next unless dep.document
53-
dep.document.aliases.each do |aname, defn|
54-
all_aliases[aname.to_s] ||= serialise_item(defn.data)
55-
end
56-
end
57-
58-
# Also merge ALL library aliases unconditionally. Libraries (posix,
59-
# unicode, var-Cyrl, var-kor) define character classes that maps
60-
# reference via alias() without listing the library as an explicit
61-
# dependency in the dependency list.
62-
Interscript.maps(libraries: true).each do |lib|
63-
libdoc = Interscript.parse(lib)
64-
libdoc.aliases.each do |aname, defn|
65-
all_aliases[aname.to_s] ||= serialise_item(defn.data)
66-
end
67-
rescue
68-
# skip unparseable libraries
69-
end
70-
71-
# Document's own aliases override everything.
41+
# Only the document's own aliases are serialised. Library and
42+
# dependency aliases resolve at runtime via the alias `map:` qualifier,
43+
# matching the production corpus shape.
7244
doc.aliases.each do |name, defn|
7345
all_aliases[name.to_s] = serialise_item(defn.data)
7446
end
@@ -180,6 +152,7 @@ def serialise_to(to)
180152
end
181153

182154
def serialise_item(item)
155+
return {kind: "any", of: item.map { |i| i.is_a?(String) ? {kind: "string", value: i} : serialise_item(i) }} if item.is_a?(::Array)
183156
case item
184157
when Interscript::Node::Item::String
185158
{kind: "string", value: item.data}

‎lib/interscript/isc/node_adapter.rb‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,11 @@ def build_stage(stage_def)
113113
Interscript::Node::Item::String.new(item[:separator]&.value || "-")
114114
)
115115
when :string_case
116-
sym = (item[:op] == "title_case") ? :title_case : item[:op].to_sym
117-
stage.children << sym
116+
stage.children << Interscript::Node::Rule::Funcall.new(item[:op].to_sym)
118117
when :compose
119-
stage.children << :compose
118+
stage.children << Interscript::Node::Rule::Funcall.new(:compose)
119+
when :decompose
120+
stage.children << Interscript::Node::Rule::Funcall.new(:decompose)
120121
when :funcall
121122
stage.children << Interscript::Node::Rule::Funcall.new(
122123
item[:name].to_sym,

‎spec/json_ir_serialisation_spec.rb‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# frozen_string_literal: true
2+
3+
# JsonIR must serialise to the production corpus shape: a document
4+
# carries only its own aliases (dependency and library aliases resolve
5+
# at runtime via the alias `map:` qualifier), and any()-sets serialise
6+
# as {kind: "any", of: [...]} — never as merged library dumps or
7+
# char-class rewrites.
8+
require "interscript"
9+
require "json"
10+
11+
MAPS = ENV.fetch("INTERSCRIPT_MAPS_PATH", "../maps/maps")
12+
13+
RSpec.describe "Interscript::Compiler::JsonIR serialisation form" do
14+
before(:all) do
15+
Interscript.load_path.unshift(MAPS) unless Interscript.load_path.first == MAPS
16+
end
17+
18+
it "serialises only the document's own aliases" do
19+
skip "maps checkout not present" unless File.file?(File.expand_path("un-tam-Taml-Latn-1972.isc", MAPS))
20+
21+
doc = Interscript::Compiler.parse_isc(File.expand_path("un-tam-Taml-Latn-1972.isc", MAPS))
22+
ir = JSON.parse(Interscript::Compiler::JsonIR.new.compile(doc).code)
23+
24+
expect(ir["aliases"].keys).to eq(["taml_chars_1"])
25+
end
26+
27+
it "serialises any()-sets as any/of string alternatives" do
28+
skip "maps checkout not present" unless File.file?(File.expand_path("un-tam-Taml-Latn-1972.isc", MAPS))
29+
30+
doc = Interscript::Compiler.parse_isc(File.expand_path("un-tam-Taml-Latn-1972.isc", MAPS))
31+
ir = JSON.parse(Interscript::Compiler::JsonIR.new.compile(doc).code)
32+
alias_def = ir["aliases"]["taml_chars_1"]
33+
34+
expect(alias_def["kind"]).to eq("any")
35+
expect(alias_def["of"]).to all(include("kind" => "string"))
36+
end
37+
end

0 commit comments

Comments
 (0)