Skip to content

Commit 669c0ac

Browse files
committed
fix: render bridge-emitted ISC shapes the corpus actually produces
Through the Ruby bridge the engine sees generated ISC, whose shapes differ from the hand-written corpus in two ways: - any(<single alias resolving to a plain string>) is a character class — the generator inlines the unicode library's greek inside any() — while a bare alias reference stays a literal sequence (the qualified 404 pins). alalc-ell's gamma nasalization guards had compiled to the literal 300-character alphabet through the bridge. - a capture group in a result position renders as the parenthesised inner text, like Ruby's build_item (bgnpcgn-zho writes to capture("me, yao") for 么). The renderer rejected it and the whole map failed to load through the bridge. Bridge sweep (Compiler::Python over the full corpus): 8,238 examples, 0 failures.
1 parent 16e250d commit 669c0ac

1 file changed

Lines changed: 17 additions & 1 deletion

File tree

‎src/interscript/isc.py‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import re
2323
from pathlib import Path
2424

25-
from .expr import _BOUNDARY, _WORD, expr_lookbehind, expr_neg_lookbehind, expr_to_regex
25+
from .expr import _BOUNDARY, _WORD, expr_lookbehind, expr_neg_lookbehind, expr_to_regex, is_plain_string
2626

2727
# Ruby \w is ASCII-only; the same divergence the expression layer fixes.
2828
_WORD_BOUNDARY = _BOUNDARY
@@ -671,6 +671,18 @@ def _render_item(item: dict, aliases: dict[str, str]) -> str:
671671
len(sub["value"]) == 1 for sub in items
672672
):
673673
return f'any("{_escape("".join(sub["value"] for sub in items))}")'
674+
# any(<single alias resolving to a plain string>) is a character
675+
# class (measured against Ruby: the unicode library's greek);
676+
# a bare alias reference stays a literal sequence.
677+
if (
678+
len(items) == 1
679+
and items[0]["type"] == "alias_ref"
680+
and not items[0].get("map")
681+
and items[0]["name"] in aliases
682+
):
683+
resolved = aliases[items[0]["name"]]
684+
if is_plain_string(resolved):
685+
return f"any({resolved})"
674686
return "any([" + ", ".join(_render_item(sub, aliases) for sub in items) + "])"
675687
if kind == "range":
676688
return f'any("{_escape(item["lo"])}".."{_escape(item["hi"])}")'
@@ -792,6 +804,10 @@ def _repl_of(item: dict, aliases: dict[str, str]) -> str:
792804
return "".join(_repl_of(part, aliases) for part in item["parts"])
793805
if kind == "capture":
794806
return f"${item['index']}"
807+
if kind == "capture_group":
808+
# Ruby renders a capture group in a result position as the
809+
# parenthesised inner text (bgnpcgn-zho: to capture("me, yao")).
810+
return "(" + _repl_of(item["inner"], aliases) + ")"
795811
if kind == "set":
796812
# A to-position any() lists alternative spellings; the Ruby
797813
# runtime picks the first in non-iterating mode.

0 commit comments

Comments
 (0)