122 lines
4.8 KiB
Python
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
|