SNAPKITTYWEST's picture
October 2026 main drop: mirror from GitHub
fc3e70a verified
Raw History Blame Contribute Delete
3.16 kB
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
"""Phase 11: Rosetta mapping β€” Latin semantic IDs β†’ SUBLEQ IR.
Only canonical vocabulary reaches this layer.
Direct arbitrary Latin→machine mapping is prohibited.
"""
from __future__ import annotations
import json
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
from .latin import LatinCanonicalForm, LatinToken
from .lexer import LexResult, LexedToken
from .types import FSMState, RosettaError
@dataclass(frozen=True)
class RosettaEntry:
semantic_id: str
subleq_op: str
template: str
args: tuple[str, ...]
@dataclass
class RosettaMapping:
"""Result of mapping a LatinCanonicalForm to SUBLEQ operations."""
entries: list[tuple[LatinToken, RosettaEntry]] = field(default_factory=list)
unmapped: list[LatinToken] = field(default_factory=list)
@property
def complete(self) -> bool:
return len(self.unmapped) == 0
# ── Table loader ──────────────────────────────────────────────────────────────
def _load_table() -> dict[str, RosettaEntry]:
path = Path(__file__).parent.parent.parent / "mappings" / "rosetta_table.json"
if not path.exists():
return {}
data = json.loads(path.read_text())
return {
sem_id: RosettaEntry(
semantic_id=sem_id,
subleq_op=entry["subleq_op"],
template=entry["template"],
args=tuple(entry.get("args", [])),
)
for sem_id, entry in data.get("mappings", {}).items()
}
_TABLE: dict[str, RosettaEntry] = {}
def table() -> dict[str, RosettaEntry]:
global _TABLE
if not _TABLE:
_TABLE = _load_table()
return _TABLE
# ── Mapper ────────────────────────────────────────────────────────────────────
class RosettaMapper:
"""Map LatinCanonicalForm tokens to SUBLEQ operations via the Rosetta table."""
def map(self, form: LatinCanonicalForm) -> RosettaMapping:
tbl = table()
mapping = RosettaMapping()
for tok in form.tokens:
entry = tbl.get(tok.semantic_id)
if entry is None:
mapping.unmapped.append(tok)
else:
mapping.entries.append((tok, entry))
if not mapping.complete:
unmapped_ids = [t.semantic_id for t in mapping.unmapped]
raise RosettaError(
FSMState.ROSETTA_MAPPING,
f"Unmapped semantic IDs: {unmapped_ids}",
)
return mapping
def map_lex_result(self, result: LexResult, form: LatinCanonicalForm) -> RosettaMapping:
"""Map from a lexed result, cross-referencing the canonical form for semantic IDs."""
return self.map(form)