Skip to content

Commit

Permalink
Separate HeadTape from Tape
Browse files Browse the repository at this point in the history
  • Loading branch information
nickdrozd committed Nov 17, 2023
1 parent 1a6492f commit 6f42d8f
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 29 deletions.
2 changes: 0 additions & 2 deletions test/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ def test_display(self):

print(Machine("1RB ... ... ...").run(watch_tape = True))

print(StrictLinRecMachine("1RB 0LB 1LA 0RB").run(check_rec = 0))


class TestFloss(TestCase):
def test_macro(self):
Expand Down
67 changes: 56 additions & 11 deletions test/test_tape.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import TYPE_CHECKING

from tm.tape import Tape, TagTape, EnumTape, Block
from tm.lin_rec import HeadTape
from tm.lin_rec import HeadTape, Block as HeadBlock

if TYPE_CHECKING:
from tm.tape import Color, Signature
Expand All @@ -26,7 +26,7 @@ def stringify_sig(sig: Signature) -> str:


class TestTape(TestCase):
tape: HeadTape
tape: Tape | HeadTape

def set_tape(
self,
Expand All @@ -35,24 +35,60 @@ def set_tape(
rspan: BlockSpan,
head: int | None = None,
) -> None:
self.tape = HeadTape(
[Block(color, count) for color, count in lspan],
scan,
[Block(color, count) for color, count in rspan],
head = head or 0)
block = Block if head is None else HeadBlock

lspan = [
block(color, count) # type: ignore[misc]
for color, count in lspan
]
rspan = [
block(color, count) # type: ignore[misc]
for color, count in rspan
]

self.tape = (
Tape(lspan, scan, rspan) # type: ignore[arg-type]
if head is None else
HeadTape(lspan, scan, rspan, head) # type: ignore[arg-type]
)

def assert_tape(self, tape: str):
self.assertEqual(tape, str(self.tape))
self.assertEqual(
tape,
str(tape)
if isinstance(
tape := self.tape, # type: ignore[assignment]
Tape
) else
str(Tape(
[Block(block.color, block.count)
for block in tape.lspan], # type: ignore[attr-defined]
tape.scan, # type: ignore[attr-defined]
[Block(block.color, block.count)
for block in tape.rspan] # type: ignore[attr-defined]
))
)

def assert_signature(
self,
expected: str,
tape: Tape | None = None,
tape: Tape | HeadTape | None = None,
) -> None:
if tape is None:
tape = self.tape

assert isinstance(tape, HeadTape)

self.assertEqual(
expected,
stringify_sig(
(tape or self.tape).signature))
Tape(
[Block(block.color, block.count)
for block in tape.lspan],
tape.scan,
[Block(block.color, block.count)
for block in tape.rspan]
).signature))

def test_marks(self):
self.assertFalse(
Expand All @@ -62,7 +98,8 @@ def test_copy(self):
self.set_tape(
[[1, 1], [0, 1], [1, 1]],
2,
[[2, 1], [1, 2]]
[[2, 1], [1, 2]],
0,
)

self.assert_tape(
Expand All @@ -71,6 +108,8 @@ def test_copy(self):
self.assert_signature(
'1|0|1[2]2|1')

assert isinstance(self.tape, HeadTape)

copy_1 = self.tape.copy()
copy_2 = self.tape.copy()

Expand All @@ -97,6 +136,8 @@ def test_rule_1(self):
self.assert_tape(
"2^3 1^12 [3] 4^15 5^2 6^2")

assert isinstance(self.tape, Tape)

self.tape.apply_rule({
(0, 1): 3,
(1, 0): -2,
Expand All @@ -119,6 +160,8 @@ def test_rule_2(self):
4,
[[5, 60], [2, 1], [4, 1], [5, 7], [1, 1]])

assert isinstance(self.tape, Tape)

self.assert_tape(
"4^2 [4] 5^60 2^1 4^1 5^7 1^1")

Expand All @@ -133,6 +176,8 @@ def test_rule_2(self):
def test_rule_3(self):
self.set_tape([[1, 152], [2, 655345], [3, 1]], 0, [])

assert isinstance(self.tape, Tape)

self.assert_tape(
"3^1 2^655345 1^152 [0]")

Expand Down
85 changes: 70 additions & 15 deletions tm/lin_rec.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
from collections import defaultdict
from dataclasses import dataclass, field

from tm.tape import Tape, Block
from tm.machine import BasicMachine

if TYPE_CHECKING:
from typing import Self

from tm.tape import Shift
from tm.parse import Color, State, Slot
from tm.parse import Color, Shift, State, Slot, GetInstr

RecRes = tuple[int, int]
LinRec = tuple[int | None, int]
Expand All @@ -21,19 +19,22 @@


@dataclass
class HeadTape(Tape):
head: int = 0
class Block:
color: Color
count: int

def __init__(
self,
lspan: list[Block],
scan: Color,
rspan: list[Block],
head: int = 0,
):
self.head = head

super().__init__(lspan, scan, rspan)
@dataclass
class HeadTape:
lspan: list[Block]
scan: Color
rspan: list[Block]

head: int = 0

@classmethod
def init(cls, scan: Color = 0) -> Self:
return cls([], scan, [])

@classmethod
def init_stepped(cls) -> Self: # no-cover
Expand Down Expand Up @@ -72,8 +73,62 @@ def unroll(self) -> list[Color]:
for _ in range(int(block.count))
]

@property
def blank(self) -> bool:
return self.scan == 0 and not self.lspan and not self.rspan

def at_edge(self, edge: Shift) -> bool:
return (
self.scan == 0
and not (self.rspan if edge else self.lspan)
)

def step(self, shift: Shift, color: Color, skip: bool) -> int:
stepped = int(super().step(shift, color, skip))
pull, push = (
(self.rspan, self.lspan)
if shift else
(self.lspan, self.rspan)
)

push_block = (
pull.pop(0)
if skip and pull and pull[0].color == self.scan else
None
)

stepped = 1 if push_block is None else 1 + push_block.count

next_scan: Color

if not pull:
next_scan = 0
else:
next_pull = pull[0]

if next_pull.count != 1:
next_pull.count -= 1
else:
popped = pull.pop(0)

if push_block is None:
push_block = popped
push_block.count = 0

next_scan = next_pull.color

if push and (top_block := push[0]).color == color:
top_block.count += stepped
else:
if push_block is None:
push_block = Block(color, 1)
else:
push_block.color = color
push_block.count += 1

if push or color != 0:
push.insert(0, push_block)

self.scan = next_scan

self.head += stepped if shift else -stepped

Expand Down
2 changes: 1 addition & 1 deletion tm/machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def term_results(self) -> list[tuple[str, Result]]:
try:
# pylint: disable = bad-builtin
data = getattr(self, cat)
except AttributeError:
except AttributeError: # no-cover
continue

if data is not None:
Expand Down

0 comments on commit 6f42d8f

Please sign in to comment.