From 4923e8ec3a648652f4f83bc99e2863b6b1d38c23 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Tue, 29 Sep 2026 21:52:33 +0800 Subject: [PATCH 1/4] spec: ISC_SWEEP gate for the corpus sweep measurement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The per-example timeouts already bound the sweep (16,262 examples, 16k pass, 6 fail — all iso-mal-Mlym-Latn-15919-2001 on the Ruby compiler; the Interpreter passes the same map, so it is a codegen divergence, not a corpus gap). The gate keeps CI on the legacy scope while the conformance tail closes. --- spec/interscript_spec.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/spec/interscript_spec.rb b/spec/interscript_spec.rb index 62564564..6dc98eeb 100644 --- a/spec/interscript_spec.rb +++ b/spec/interscript_spec.rb @@ -2,8 +2,16 @@ cache = {} mask = ENV["TRANSLIT_SYSTEM"] || "*" -# The legacy .imp sweep only (see legacy_maps in spec_helper). -maps = legacy_maps(select: mask) +# The ISC corpus sweep runs behind ISC_SWEEP=1: each example is +# timeout-guarded (at least one map hangs the interpreter) and +# per-map failures are expected until the ISC-era conformance work +# completes — the sweep exists to MEASURE that gap, gated so CI stays +# green while it closes. +if ENV["ISC_SWEEP"] + maps = Interscript.maps(basename: false, select: mask) +else + maps = legacy_maps(select: mask) +end # Precache can be used to compare interpreter to compiler performance if ENV.include? "PRECACHE" From 765810f0daaeda92b6f83a757df2e92928693fcc Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Tue, 29 Sep 2026 22:04:52 +0800 Subject: [PATCH 2/4] fix: NodeAdapter carries the system code into Document#name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The adapter read isc_doc[:system_code] but DocumentBuilder emits :systemCode — every ISC-parsed document got name: nil, and the Ruby compiler (which registers compiled maps under Document#name) compiled every ISC map under the empty string. Transliterate then crashed with 'undefined method call for nil' — the same crash the detector's full-corpus walk hit. Interp-vs-compiled divergence on iso-mal-Mlym-Latn-15919-2001 is also gone for the direct paths; the remaining sweep failures there are a separate codegen bug (an object inspect-string interpolated into a lookahead character class). --- lib/interscript/isc/node_adapter.rb | 2 +- spec/interscript/isc/node_adapter_spec.rb | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/interscript/isc/node_adapter.rb b/lib/interscript/isc/node_adapter.rb index 4229bcbb..c19d43cc 100644 --- a/lib/interscript/isc/node_adapter.rb +++ b/lib/interscript/isc/node_adapter.rb @@ -29,7 +29,7 @@ def build doc.aliases = build_aliases build_stages.each { |name, stage| doc.stages[name] = stage } build_dependencies(doc) - doc.name = @isc_doc[:system_code] + doc.name = @isc_doc[:systemCode] end end diff --git a/spec/interscript/isc/node_adapter_spec.rb b/spec/interscript/isc/node_adapter_spec.rb index aae5423b..301e8a83 100644 --- a/spec/interscript/isc/node_adapter_spec.rb +++ b/spec/interscript/isc/node_adapter_spec.rb @@ -249,3 +249,17 @@ def parse_and_adapt(src) end end end + +RSpec.describe "NodeAdapter document identity" do + it "carries the system code into the document name" do + tree = Interscript::Isc::Parser.parse( + 'system "X:a-b:C-D:1" { stage main { sub { from "a" to "b" } } }' + ) + doc = Interscript::Isc::DocumentBuilder.build(tree) + node = Interscript::Isc::NodeAdapter.to_interscript_node(doc) + # The Ruby compiler registers compiled maps under Document#name; a + # nil name registered them under "" and every transliterate call + # crashed on nil.call. + expect(node.name).to eq("X:a-b:C-D:1") + end +end From 30bf057bfd47af4689942fd82d2b612d216268d0 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Tue, 29 Sep 2026 22:08:10 +0800 Subject: [PATCH 3/4] style: standardrb clean on the sweep gate --- spec/interscript_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/interscript_spec.rb b/spec/interscript_spec.rb index 6dc98eeb..1f022067 100644 --- a/spec/interscript_spec.rb +++ b/spec/interscript_spec.rb @@ -7,10 +7,10 @@ # per-map failures are expected until the ISC-era conformance work # completes — the sweep exists to MEASURE that gap, gated so CI stays # green while it closes. -if ENV["ISC_SWEEP"] - maps = Interscript.maps(basename: false, select: mask) +maps = if ENV["ISC_SWEEP"] + Interscript.maps(basename: false, select: mask) else - maps = legacy_maps(select: mask) + legacy_maps(select: mask) end # Precache can be used to compare interpreter to compiler performance From 5d2ad9273d6c57022f6441bd4f3da903d663b07f Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Tue, 29 Sep 2026 22:14:10 +0800 Subject: [PATCH 4/4] fix: convert_set converts non-string entries any([boundary, ZWNJ, ZWJ]) leaked the boundary primitive as a raw Isc::Items::Primitive into Any's value; the Ruby compiler then baked the object's inspect string into the compiled character class character-by-character, and the rule's lookahead matched positions it must not. Set entries now convert through the alias/primitive paths. --- lib/interscript/isc/node_adapter.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/interscript/isc/node_adapter.rb b/lib/interscript/isc/node_adapter.rb index c19d43cc..c2cca5eb 100644 --- a/lib/interscript/isc/node_adapter.rb +++ b/lib/interscript/isc/node_adapter.rb @@ -202,7 +202,21 @@ def convert_concat(concat) def convert_set(set) Interscript::Node::Item::Any.new( - set.chars.map { |c| Interscript::Node::Item::String.new(c) } + set.chars.map do |c| + # Entries may be primitives/alias refs (e.g. any([boundary, + # "\u200c", "\u200d"])) — stringifying them baked an object + # inspect into the compiled character class. + case c + when ::String + Interscript::Node::Item::String.new(c) + when Items::Primitive + convert_primitive(c) + when Items::AliasRef + convert_alias_ref(c) + else + convert_item(c) + end + end ) end end