.
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Tue, 2 Dec 2025 12:56:27 +0000 (12:56 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Tue, 2 Dec 2025 12:56:27 +0000 (12:56 +0000)
shared/authored/dir-walk/TM_ND_A.py
shared/authored/dir-walk/TM_ND_A_DB.py

index 0dbccef..05facdc 100644 (file)
@@ -5,6 +5,129 @@ from __future__ import annotations
 from typing import Any
 import duck
 
+
+class TM_ND_A:
+  """
+  TM_ND_A
+
+    TM  Tape Machine
+    ND  Non-destructive (no cell deletion)
+    A   Addressed head
+
+  Contract:
+    - Head always on a valid cell.
+    - User must check can_step(n) before step(n).
+  """
+
+  # ----------------------------------------------------------------------
+  def __init__(self ,tape: Any):
+    # minimal requirement: length, getitem, setitem
+    duck.require(duck.class_of(tape) ,"__len__" ,"__getitem__" ,"__setitem__")
+
+    # synthetic extent() if tape lacks it
+    if not duck.has(tape ,"extent"):
+      tape.extent = lambda: len(tape) - 1
+
+    # synthetic clone() if tape lacks it
+    if not duck.has(tape ,"clone"):
+      def _default_clone(src=tape):
+        return src.__class__(src[:])
+      tape.clone = _default_clone
+
+    self._tape = tape
+    self._head: int = 0
+
+  # ----------------------------------------------------------------------
+  # topology
+  def extent(self) -> int: return self._tape.extent()
+  def tape(self) -> Any:   return self._tape
+  def where(self) -> int:  return self._head
+
+  # ----------------------------------------------------------------------
+  # absolute-position tests
+  def on_leftmost(self ,k: int = 0) -> bool:
+    return self._head == 0 + k
+
+  def on_rightmost(self ,k: int = 0) -> bool:
+    return self._head == self.extent() - k
+
+  # ----------------------------------------------------------------------
+  # motion
+  def can_step(self ,n: int = 1) -> bool:
+    nxt = self._head + n
+    return 0 <= nxt <= self.extent()
+
+  def step(self ,n: int = 1) -> None:
+    self._head += n
+
+  # ----------------------------------------------------------------------
+  # data transfer
+  def copy_from(self ,n: int = 0) -> Any:
+    return self._tape[self._head + n]
+
+  def copy_to(self ,value: Any ,n: int = 0) -> None:
+    self._tape[self._head + n] = value
+
+  # ----------------------------------------------------------------------
+  # structural changes (append, no drop)
+  def append(self ,value: Any ,n: int = 1) -> None:
+    """
+    Append cells left or right without deletion.
+    n > 0 -> append right n times
+    n < 0 -> append left  |n| times
+    """
+    if n > 0:
+      for _ in range(n):
+        idx = self.extent() + 1
+        self._tape.append(value)
+    elif n < 0:
+      for _ in range(-n):
+        self._tape.insert(0 ,value)
+        self._head += 1  # head shifts right because new 0 inserted
+
+  # ----------------------------------------------------------------------
+  # entanglement: share tape, copy head only
+  def entangle(self) -> "TM_ND_A":
+    tm = object.__new__(TM_ND_A)
+    tm._tape = self._tape
+    tm._head = self._head
+    return tm
+
+  # ----------------------------------------------------------------------
+  # clone: duplicate tape and head
+  def clone(self) -> "TM_ND_A":
+    new = object.__new__(TM_ND_A)
+    new._tape = self._tape.clone()
+    new._head = self._head
+    return new
+
+
+# ----------------------------------------------------------------------
+if __name__ == "__main__":
+  # simple smoke test
+  tape = [1 ,2 ,3]
+  tm = TM_ND_A(tape)
+  print("extent =", tm.extent())
+  print("copy_from =", tm.copy_from())
+  tm.step(1)
+  tm.copy_to(99)
+  print("tape =", tm.tape())
+  tm.append(7 ,1)
+  print("after append right =", tm.tape())
+  tm.append(8 ,-1)
+  print("after append left =", tm.tape(), "head =", tm.where())
+  ent = tm.entangle()
+  clo = tm.clone()
+  print("entangle tape is tm.tape?", ent.tape() is tm.tape())
+  print("clone   tape is tm.tape?", clo.tape() is tm.tape())
+
+#!/usr/bin/env python3
+# -*- mode: python; coding: utf-8; python-indent-offset: 2; indent-tabs-mode: nil -*-
+
+from __future__ import annotations
+from typing import Any
+import duck
+
 class TM_ND_A:
   """
   TM_ND_A
index 33d9ae9..758dc06 100755 (executable)
@@ -8,6 +8,7 @@ import TM_ND_A
 import JSON
 import meta
 
+_INSTANCE_COUNTER = 0
 
 # ----------------------------------------------------------------------
 _STACK_DEPTH = 0
@@ -38,7 +39,11 @@ class TM_ND_A_DB:
     global _STACK_DEPTH
     _STACK_DEPTH += 1
     self._tm = TM_ND_A.TM_ND_A(tape)
-    self._id = f"{id(self)}" 
+
+    global _INSTANCE_COUNTER
+    _INSTANCE_COUNTER += 1
+    self._id = f"TM_ND_A_DB_{_INSTANCE_COUNTER}"
+
     JSON.debug(f"{self._id} __init__({tape})" ,value="<init>" ,indent=_indent())
     _STACK_DEPTH -= 1