gdscript-transpiler/tests/test_assembler.py
Claude Code 27396acf47 release(forgejo-.forgejo/): 🔖 Publish new release with updated metadata, README, and source code + tests
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-03-25 22:43:42 -07:00

122 lines
4.8 KiB
Python

"""Tests for the GDScript to TypeScript coordinate bridge (assembler)."""
from lilith_gdscript_transpiler.assembler import transform_method_body
def _body(*lines: str) -> str:
"""Build a tab-indented GDScript body from lines."""
return "\n".join(f"\t{line}" for line in lines) + "\n"
def _tile_loop_body(*inner_lines: str) -> str:
"""Build a body with a proper tile loop so ctx.in_tile_loop is set."""
lines = [
"var old_temp: Dictionary = {} # axial -> float",
"for axial: Vector2i in tiles:",
"\tvar tile = tiles[axial]",
] + [f"\t{l}" for l in inner_lines]
return _body(*lines)
class TestBufferDicts:
"""Buffer dict: `var x: Dictionary = {} # axial -> float`"""
def test_declaration_becomes_float32array(self) -> None:
body = _body("var old_temp: Dictionary = {} # axial -> float")
result = transform_method_body(body, "test")
assert "oldTemp" in result
assert "Float32Array" in result
def test_set_uses_idx(self) -> None:
body = _tile_loop_body("old_temp[axial] = tile.temperature")
result = transform_method_body(body, "test")
assert "oldTemp[i] =" in result
assert "old_temp[axial]" not in result
def test_read_uses_idx(self) -> None:
# Buffer dict read: `old_temp[axial]` in an expression → `oldTemp[i]`
body = _tile_loop_body("var delta: float = tile.temperature - old_temp[axial]")
result = transform_method_body(body, "test")
assert "oldTemp[i]" in result
assert "old_temp[axial]" not in result
class TestHopPos:
"""hop_pos tracking: init → hopCol/hopRow, access → idx(hopCol, hopRow, w)."""
def test_init_expands_to_tracking_vars(self) -> None:
body = _body("var hop_pos = axial")
result = transform_method_body(body, "test")
assert "let hopCol = col" in result
assert "let hopRow = row" in result
def test_tiles_get_hop_pos_uses_tracking_vars(self) -> None:
body = _body(
"var hop_pos = axial",
"var hop_tile = tiles.get(hop_pos)",
)
result = transform_method_body(body, "test")
assert "tiles[idx(hopCol, hopRow, w)]" in result
# No residual hop_pos references as an identifier
assert "hop_pos.col" not in result
assert "hop_pos.row" not in result
def test_hop_advance_uses_tracking_vars(self) -> None:
body = _body(
"var hop_pos = axial",
"hop_pos = neighborInDir(hop_pos.col, hop_pos.row, wind_dir, w, h)",
)
result = transform_method_body(body, "test")
assert "neighborInDir(hopCol, hopRow" in result
assert "hopCol = _hop.col" in result
assert "hopRow = _hop.row" in result
class TestTileLoop:
"""In-tile-loop context: row redeclaration suppression."""
def test_row_redecl_suppressed_inside_tile_loop(self) -> None:
# `var row = tile.row` inside a tile loop is a redeclaration — already
# destructured by `const { col, row } = tile` — must be suppressed
body = _tile_loop_body("var row: int = tile.row")
result = transform_method_body(body, "test")
row_decl_lines = [l for l in result.splitlines() if "let row =" in l or "const row =" in l]
assert len(row_decl_lines) == 0
class TestNeighborLookup:
"""tiles.get(pos) and tiles.get(expr) patterns."""
def test_simple_pos_var(self) -> None:
body = _body("var nb = tiles.get(nb_pos)")
result = transform_method_body(body, "test")
assert "tiles[idx(nb_pos.col, nb_pos.row, w)]" in result
def test_complex_expr_emits_temp_var(self) -> None:
body = _body("var nb = tiles.get(neighborInDir(col, row, d, w, h))")
result = transform_method_body(body, "test")
# Two-liner: temp coord + conditional access
assert "_nbCoord" in result
assert "neighborInDir(col, row, d, w, h)" in result
class TestUpwindVar:
"""upwind_pos tracking: `.has(upwind_pos)` → `upwind_pos !== null`."""
def test_has_replaced_with_null_check(self) -> None:
# Inside a tile loop, `_upwind_pos(axial, dir)` → `upwindPos(col, row, dir, w, h)`,
# then the upwind var is tracked so `.has(upwind_pos)` → `upwind_pos !== null`
body = _tile_loop_body(
"var upwind_pos: Vector2i = _upwind_pos(axial, wind_dir)",
"if old_temp.has(upwind_pos):",
"\tpass",
)
result = transform_method_body(body, "test")
assert "upwind_pos !== null" in result
def test_upwind_pos_converted_to_hex_call(self) -> None:
body = _tile_loop_body(
"var upwind_pos: Vector2i = _upwind_pos(axial, wind_dir)",
)
result = transform_method_body(body, "test")
assert "upwindPos(col, row, wind_dir, w, h)" in result