adding decoder logic

This commit is contained in:
Arnav Sacheti
2025-10-16 22:35:36 -07:00
parent 2937624ee7
commit 0c66453ba0
19 changed files with 354 additions and 326 deletions

View File

@@ -0,0 +1,84 @@
from __future__ import annotations
from types import EllipsisType
from typing import Self
from .body import Body, SupportsStr
class IfBody(Body):
def __init__(self, *, indent: int = 4) -> None:
super().__init__()
# (None means 'else')
self._branches: list[tuple[SupportsStr | None, Body]] = []
self._has_else = False
self._indent = " " * indent
# --- Item access: if/else-if via condition; else via Ellipsis/None ---
def __getitem__(self, condition: SupportsStr | EllipsisType | None) -> Body:
if self._has_else:
raise RuntimeError("Cannot add branches after an 'else' branch.")
if condition is Ellipsis or condition is None:
if self._has_else:
raise RuntimeError("Only one 'else' branch is allowed.")
self._has_else = True
b = Body()
self._branches.append((None, b))
return b
# conditional branch
b = Body()
self._branches.append((condition, b))
return b
# --- In-place or: if/else-if via (cond, Body); else via Body ---
def __ior__(self, other: tuple[SupportsStr, Body] | Body) -> Self:
if isinstance(other, Body):
if self._has_else:
raise RuntimeError("Only one 'else' branch is allowed.")
if self._has_else or (self._branches and self._branches[-1][0] is None):
raise RuntimeError("Cannot add branches after an 'else' branch.")
self._branches.append((None, other))
self._has_else = True
return self
cond, body = other
if self._has_else:
raise RuntimeError("Cannot add branches after an 'else' branch.")
self._branches.append((cond, body))
return self
# --- Context manager for a branch ---
class _BranchCtx:
def __init__(self, outer: IfBody, condition: SupportsStr | None) -> None:
self._outer = outer
# route through __getitem__ to reuse validation logic
self._body = outer[Ellipsis if condition is None else condition]
def __enter__(self) -> Body:
return self._body
def __exit__(
self,
exc_type: type[BaseException] | None,
exc: BaseException | None,
tb: object | None,
) -> bool:
return False
def cm(self, condition: SupportsStr | None) -> "IfBody._BranchCtx":
"""Use with: with ifb.cm('cond') as b: ... ; use None for else."""
return IfBody._BranchCtx(self, condition)
# --- Rendering ---
def __str__(self) -> str:
out: list[str] = []
for i, (cond, body) in enumerate(self._branches):
if i == 0 and cond is not None:
out.append(f"if ({cond}) begin")
elif cond is not None:
out.append(f"else if ({cond}) begin")
else:
out.append("else begin")
body_str = str(body)
if body_str:
out.extend(self._indent + ln for ln in body_str.splitlines())
out.append("end")
return "\n".join(out)