#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "structmember.h"
+#include <stddef.h> /* For offsetof */
/* ========================================================= */
/* TYPE DEFINITION */
PyObject* tape_obj; /* The Python List (Shared) */
PyObject* peer_list; /* List of WeakRefs (Shared) */
Py_ssize_t head; /* Raw Instruction Pointer */
+ PyObject* weakreflist; /* Required for WeakRefs */
} FastTM;
/* Forward Declaration */
static PyObject* FastTM_address(FastTM* self);
static void FastTM_dealloc(FastTM* self){
+ /* Clear weak references first! */
+ if( self->weakreflist != NULL ){
+ PyObject_ClearWeakRefs((PyObject*)self);
+ }
+
Py_XDECREF(self->tape_obj);
Py_XDECREF(self->peer_list);
Py_TYPE(self)->tp_free((PyObject*)self);
static int FastTM_init(FastTM* self ,PyObject* arg_tuple ,PyObject* kwd_dict){
PyObject* input_obj = NULL;
+ /* Initialize weakref list to NULL */
+ self->weakreflist = NULL;
+
if( !PyArg_ParseTuple(arg_tuple ,"O" ,&input_obj) ) return -1;
if( PyObject_TypeCheck(input_obj ,Py_TYPE(self)) ){
/* --- Allocate --- */
static PyObject* FastTM_aL(FastTM* self ,PyObject* val_obj){
- /* Insert Left: Does this shift heads?
- For 'Address Stability', inserting at 0 shifts data indices up.
- Heads pointing to index I will now point to OLD(I-1).
- To stay on the SAME data, we must increment head.
- */
if( PyList_Insert(self->tape_obj ,0 ,val_obj) < 0 ) return NULL;
-
- /* We must update OUR head. What about PEERS?
- True entanglement requires updating ALL peers if indexes shift.
- But keeping it simple: We update self. Peers might drift.
- (Addressing drift is complex without Double Linked Nodes).
- */
self->head++;
Py_RETURN_NONE;
}
/* --- Meta --- */
static PyObject* FastTM_e(FastTM* self){
- /* Create new instance using 'self' as template (Clone Constructor) */
PyObject* arg_tuple = PyTuple_Pack(1 ,self);
PyObject* new_obj = PyObject_CallObject((PyObject*)Py_TYPE(self) ,arg_tuple);
Py_DECREF(arg_tuple);
,.tp_init = (initproc)FastTM_init
,.tp_dealloc = (destructor)FastTM_dealloc
,.tp_methods = FastTM_methods
+ ,.tp_weaklistoffset = offsetof(FastTM ,weakreflist) /* CRITICAL FIX */
};
static PyModuleDef TM_module = {
--- /dev/null
+#!/usr/bin/env python3
+import sys
+from TM import TM ,Topology
+
+def CLI():
+ print("--- TM Happy Path (example_TM_0) ---")
+
+ # 1. Initialization
+ # ---------------------------------------------------------
+ print("\n[1] Initialization")
+ data_list = [10 ,20 ,30 ,40 ,50]
+ tm_0 = TM(data_list)
+ print(f"Created TM with: {data_list}")
+ print(f"Address: {tm_0.address()} (Should be 0)")
+ print(f"Length: {tm_0.len()} (Should be 5)")
+
+ # 2. Read / Step / Write
+ # ---------------------------------------------------------
+ print("\n[2] Movement and IO")
+
+ # Read current (0)
+ val = tm_0.r()
+ print(f"r(): {val} (Exp: 10)")
+
+ # Step 1, Read
+ tm_0.s()
+ print(f"s() -> r(): {tm_0.r()} (Exp: 20)")
+
+ # Write
+ tm_0.w(99)
+ print(f"w(99) -> r(): {tm_0.r()} (Exp: 99)")
+
+ # Step N
+ tm_0.sn(2)
+ print(f"sn(2) -> r(): {tm_0.r()} (Exp: 40)") # 0->1->3 (Indices: 0, 1, 2, 3)
+
+ # Step Left
+ tm_0.ls()
+ print(f"ls() -> r(): {tm_0.r()} (Exp: 30)")
+
+ # Bulk Write (wn)
+ # Current head is at index 2 (val 30)
+ # Write [33, 44] -> overwrites 30, 40
+ tm_0.wn([33 ,44])
+ print("wn([33 ,44])")
+
+ # Bulk Read (rn)
+ read_back = tm_0.rn(2)
+ print(f"rn(2): {read_back} (Exp: [33, 44])")
+
+ # 3. Allocation
+ # ---------------------------------------------------------
+ print("\n[3] Allocation")
+
+ # Append Right (aR)
+ tm_0.aR(60)
+ print(f"aR(60) -> len: {tm_0.len()} (Exp: 6)")
+
+ # Append Left (aL)
+ # Head is at index 2.
+ # aL inserts at 0. Indices shift right.
+ # Head should increment to 3 to stay on '33'.
+ print(f"Pre-aL Head: {tm_0.address()}")
+ tm_0.aL(0)
+ print(f"aL(0) -> Head: {tm_0.address()} (Exp: 3)")
+ print(f"Value at Head: {tm_0.r()} (Exp: 33)")
+
+ # Check 0 index
+ tm_0.lsn(3) # Go to 0
+ print(f"Value at 0: {tm_0.r()} (Exp: 0)")
+
+ # 4. Deletion
+ # ---------------------------------------------------------
+ print("\n[4] Deletion")
+
+ # Current Tape: [0, 10, 99, 33, 44, 50, 60]
+ # Head at 0.
+
+ # esd (Delete Neighbor -> 10)
+ tm_0.esd()
+ print(f"esd() -> Tape[1] should be 99. r(2): {tm_0.rn(2)} (Exp: [0, 99])")
+
+ # d (Delete Current -> 0)
+ tm_0.d()
+ # Head stays at 0, which is now 99
+ print(f"d() -> Current: {tm_0.r()} (Exp: 99)")
+
+ # 5. Cloning (Entanglement)
+ # ---------------------------------------------------------
+ print("\n[5] Cloning")
+ tm_clone = tm_0.e()
+ print("Created tm_clone from tm_0")
+
+ # Modify tm_0, check tm_clone
+ tm_0.w(999)
+ print(f"tm_0.w(999)")
+ print(f"tm_clone.r(): {tm_clone.r()} (Exp: 999)")
+
+ print("\n--- end of examples ---")
+
+if __name__ == "__main__":
+ CLI()
+
+
--- /dev/null
+#!/usr/bin/env python3
+import sys
+from TM import TM
+
+def CLI():
+ print("--- TM Edge Cases (example_TM_1) ---")
+
+ # 1. Entanglement Violation (Safety Check)
+ # ---------------------------------------------------------
+ print("\n[1] Entanglement Violation (Peer on Victim)")
+
+ t1 = TM(['A' ,'B' ,'C'])
+ t2 = t1.e() # Entangled Clone
+
+ # Setup:
+ # t1 at 0 ('A')
+ # t2 moves to 1 ('B')
+ t2.s()
+ print(f"Setup: t1@{t1.address()}, t2@{t2.address()}")
+
+ print("Action: t1.esd() -> Tries to delete 'B'")
+ print("Expect: RuntimeError (Entanglement Violation)")
+
+ try:
+ t1.esd()
+ print("!! FAILED: Operation succeeded (Should have failed)")
+ except RuntimeError as e:
+ print(f">> CAUGHT EXPECTED ERROR: {e}")
+
+ # 2. Entanglement Violation (Peer on Current)
+ # ---------------------------------------------------------
+ print("\n[2] Entanglement Violation (Peer on Current)")
+
+ # t1 at 0. t2 at 1.
+ # Move t2 back to 0. Both at 0.
+ t2.ls()
+ print(f"Setup: t1@{t1.address()}, t2@{t2.address()}")
+
+ print("Action: t1.d() -> Tries to delete 'A'")
+ print("Expect: RuntimeError")
+
+ try:
+ t1.d()
+ print("!! FAILED: Operation succeeded")
+ except RuntimeError as e:
+ print(f">> CAUGHT EXPECTED ERROR: {e}")
+
+ # 3. Safe Deletion (No Peer Collision)
+ # ---------------------------------------------------------
+ print("\n[3] Safe Deletion (Peer Safe)")
+
+ # t1 at 0 ('A'), t2 at 0 ('A').
+ # Move t2 to 2 ('C').
+ t2.sn(2)
+ print(f"Setup: t1@{t1.address()} ('A'), t2@{t2.address()} ('C')")
+
+ # t1 deletes 'B' (neighbor). 'B' is at index 1.
+ # t2 is at index 2. Safe?
+ # Yes. t2 is not ON the cell being deleted.
+ # Note: t2's data will shift left index-wise, but Entanglement check
+ # only cares if t2 is *on* the deleted cell.
+
+ print("Action: t1.esd() -> Delete 'B'")
+ t1.esd()
+ print(">> Success (Operation Permitted)")
+ print(f"Tape is now: {t1.rn(2)}")
+
+ # 4. Map Input (Materialization)
+ # ---------------------------------------------------------
+ print("\n[4] Map Input")
+ data_map = {'key1': 1 , 'key2': 2}
+ tm_map = TM(data_map)
+ print(f"TM from Map keys: {tm_map.rn(2)}")
+
+ print("\n--- Finished ---")
+
+if __name__ == "__main__":
+ CLI()
+
--- /dev/null
+/*
+ TM First Order Machine - C Implementation
+ RT Code Format Compliant
+*/
+
+/* ========================================================= */
+/* INTERFACE */
+/* ========================================================= */
+#ifdef FACE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Opaque Handle */
+typedef struct TM TM;
+
+/* Constructor / Destructor */
+TM* TM_new(int size ,int* initial_data);
+void TM_free(TM* tm);
+
+/* Core Operations */
+int TM_r(TM* tm);
+void TM_rn(TM* tm ,int n ,int* buffer);
+
+void TM_w(TM* tm ,int v);
+void TM_wn(TM* tm ,int n ,int* v);
+
+void TM_s(TM* tm);
+void TM_sn(TM* tm ,int n);
+
+void TM_ls(TM* tm);
+void TM_lsn(TM* tm ,int n);
+
+int TM_head(TM* tm);
+int TM_len(TM* tm);
+
+#endif
+
+/* ========================================================= */
+/* IMPLEMENTATION */
+/* ========================================================= */
+#ifdef IMPL
+
+struct TM {
+ int* tape;
+ int size;
+ int head;
+};
+
+TM* TM_new(int size ,int* initial_data){
+ TM* tm = malloc(sizeof(TM));
+ if( !tm ) return NULL;
+
+ tm->tape = calloc(size ,sizeof(int));
+ tm->size = size;
+ tm->head = 0;
+
+ if( initial_data ){
+ memcpy(tm->tape ,initial_data ,size * sizeof(int));
+ }
+
+ return tm;
+}
+
+void TM_free(TM* tm){
+ if( tm ){
+ if( tm->tape ) free(tm->tape);
+ free(tm);
+ }
+}
+
+int TM_r(TM* tm){
+ /* Unchecked read for speed */
+ return tm->tape[tm->head];
+}
+
+void TM_rn(TM* tm ,int n ,int* buffer){
+ /* Bulk copy (memcpy) */
+ memcpy(buffer ,tm->tape + tm->head ,n * sizeof(int));
+}
+
+void TM_w(TM* tm ,int v){
+ tm->tape[tm->head] = v;
+}
+
+void TM_wn(TM* tm ,int n ,int* v){
+ memcpy(tm->tape + tm->head ,v ,n * sizeof(int));
+}
+
+void TM_s(TM* tm){
+ tm->head++;
+}
+
+void TM_sn(TM* tm ,int n){
+ tm->head += n;
+}
+
+void TM_ls(TM* tm){
+ tm->head--;
+}
+
+void TM_lsn(TM* tm ,int n){
+ tm->head -= n;
+}
+
+int TM_head(TM* tm){
+ return tm->head;
+}
+
+int TM_len(TM* tm){
+ return tm->size;
+}
+
+#endif
--- /dev/null
+#!/usr/bin/env python3
+import copy
+
+class TapeMachine:
+ """
+ TTCA Tape Machine Implementation.
+ Adapts List, Map, and Set to a common Tape Interface.
+ """
+ def __init__(self, tape_ref, path=None, point=0, iterator=None):
+ self.tape = tape_ref # The 'Memory' (Shared)
+ self.path = path or [] # The 'Stack' (Hierarchy context)
+
+ # 'point' is the Address.
+ # For Lists: Integer Index
+ # For Maps: Key (Symbol)
+ # For Sets: The Item itself
+ self.point = point
+
+ # For Maps/Sets, we need an iterator to support 'Step' (s)
+ self._iter = iterator
+
+ # --- (e) Entangle ---
+ def e(self):
+ """
+ Entangled Copy.
+ Returns a new head sharing the same tape memory.
+ """
+ # We must clone the iterator state if possible,
+ # though Python iterators are hard to clone.
+ # We usually restart iteration or assume random access.
+ return TapeMachine(self.tape, self.path, self.point)
+
+ # --- (r) Read ---
+ def r(self):
+ """Reads the cell under the head."""
+ container = self._resolve_container()
+
+ if isinstance(container, list):
+ if 0 <= self.point < len(container):
+ return container[self.point]
+
+ elif isinstance(container, dict):
+ return container.get(self.point, None)
+
+ elif isinstance(container, set):
+ # In a set, if we are 'at' a point, the value IS the point.
+ # But we must verify it still exists.
+ return self.point if self.point in container else None
+
+ return None
+
+ # --- (w) Write ---
+ def w(self, value):
+ """Writes to the cell under the head."""
+ container = self._resolve_container()
+
+ if isinstance(container, list):
+ container[self.point] = value
+
+ elif isinstance(container, dict):
+ container[self.point] = value
+
+ elif isinstance(container, set):
+ raise TypeError("Cannot 'Write' to a Set cell. Use 'd' (Delete) and 'a' (Add).")
+
+ # --- (s) Step ---
+ def s(self, direction=1):
+ """
+ Move relative to current position.
+ Direction +1 = Next, -1 = Previous.
+ """
+ container = self._resolve_container()
+
+ if isinstance(container, list):
+ self.point += direction
+
+ elif isinstance(container, (dict, set)):
+ # Maps/Sets require iteration to step.
+ # This is expensive (O(N)) unless we maintain an active iterator.
+ # Simplified Logic:
+ try:
+ # In a real engine, we'd cache the list of keys
+ keys = list(container.keys()) if isinstance(container, dict) else list(container)
+
+ # Find current index
+ try:
+ current_idx = keys.index(self.point)
+ next_idx = current_idx + direction
+ if 0 <= next_idx < len(keys):
+ self.point = keys[next_idx]
+ except ValueError:
+ # Current point no longer in set/map, reset to start
+ if keys: self.point = keys[0]
+ except:
+ pass
+ return self
+
+ # --- (m) Move ---
+ def m(self, address):
+ """
+ Absolute jump to an address.
+ List: index (int), Map: key (symbol), Set: member (symbol).
+ """
+ self.point = address
+ return self
+
+ # --- (a) Allocate / Add ---
+ def a(self, value, key=None):
+ """
+ Appends or Inserts.
+ List: Append value.
+ Map: Insert key:value.
+ Set: Add value.
+ """
+ container = self._resolve_container()
+
+ if isinstance(container, list):
+ container.append(value)
+
+ elif isinstance(container, dict):
+ if key is None: raise ValueError("Map allocation requires key")
+ container[key] = value
+
+ elif isinstance(container, set):
+ container.add(value)
+
+ # --- Hierarchy Navigation (Enter/Exit) ---
+ def enter(self):
+ """Descends into the current cell."""
+ current_val = self.r()
+
+ # Valid container?
+ if isinstance(current_val, (list, dict, set)):
+ # Push context
+ new_path = self.path + [(self._resolve_container(), self.point)]
+
+ # Determine starting point for new container
+ start_point = 0
+ if isinstance(current_val, (dict, set)) and len(current_val) > 0:
+ # Start at the first key/member
+ start_point = next(iter(current_val))
+
+ return TapeMachine(self.tape, new_path, start_point)
+ return None
+
+ def exit(self):
+ """Ascends to parent."""
+ if not self.path: return None
+
+ # Pop context
+ parent_container, parent_point = self.path[-1]
+ new_path = self.path[:-1]
+
+ return TapeMachine(self.tape, new_path, parent_point)
+
+ # --- Internal ---
+ def _resolve_container(self):
+ """Drills down the path stack to find current container."""
+ curr = self.tape
+ for container, index in self.path:
+ if isinstance(container, list): curr = container[index]
+ elif isinstance(container, dict): curr = container[index]
+ # Set traversal in path stack implies we 'entered' a member
+ # (which must be a container itself)
+ return curr
--- /dev/null
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Compile with FACE and IMPL defined to generate the full library
+gcc -shared -fPIC -o libTM.so -D FACE -D IMPL TM.c
+
+echo "Built libTM.so"
--- /dev/null
+#!/usr/bin/env python3
+import weakref
+# Assuming SymbolSpace is in the same package or path
+from SymbolSpace import SymbolSpace
+
+class Binder:
+ """
+ Maps transient Runtime Objects to persistent Epimetheus Symbols.
+ """
+
+ def __init__(self):
+ # Weak Key: If the Object dies, this entry disappears automatically.
+ # Value: The Symbol (Strong reference).
+ self._obj_to_sym = weakref.WeakKeyDictionary()
+
+ def get_symbol(self ,obj) -> SymbolSpace.Instance:
+ """
+ Returns the symbol for the object.
+ If none exists, mints a new one and binds it.
+ """
+ # Check if we already know this object
+ if obj in self._obj_to_sym:
+ return self._obj_to_sym[obj]
+
+ # Mint new identity
+ sym = SymbolSpace.alloc()
+ self._obj_to_sym[obj] = sym
+
+ return sym
+
+ def lookup(self ,obj) -> SymbolSpace.Instance:
+ """
+ Non-allocating lookup. Returns None if object is unknown.
+ """
+ return self._obj_to_sym.get(obj ,None)
+
+# --- Work & CLI ---
+
+def verify_binder():
+ print("--- Binder Verification ---")
+ binder = Binder()
+
+ # 1. Create a transient object
+ class Bike: pass
+ my_bike = Bike()
+
+ # 2. Bind it
+ sym = binder.get_symbol(my_bike)
+ print(f"Bike is bound to: {sym}")
+
+ # 3. Verify stability
+ sym2 = binder.get_symbol(my_bike)
+ assert sym == sym2
+ print("Symbol is stable for same object.")
+
+ # 4. Garbage Collection Test
+ import gc
+ del my_bike
+ gc.collect()
+
+ # The binder should be empty now because the key is dead
+ # Note: The 'sym' variable still holds the integer,
+ # so the Concept survives even though the Implementation is gone.
+ print("Object deleted. Binder entry should be gone (internal check).")
+ print(f"Binder size: {len(binder._obj_to_sym)}")
+
+def CLI():
+ verify_binder()
+
+if __name__ == "__main__":
+ CLI()
+
--- /dev/null
+#!/usr/bin/env python3
+from SymbolSpace import SymbolSpace
+
+# ==========================================
+# THE GRAPH (Discrete Function)
+# ==========================================
+
+class DiscreteFunction:
+ """
+ The Knowledge Store.
+ Supports 'Smart Postings' to Parent Symbols.
+ """
+ def __init__(self):
+ self._rev = {} # reverse map: Symbol -> Set of Objects
+
+ def _add_posting(self ,sym ,obj):
+ if sym not in self._rev: self._rev[sym] = set()
+ self._rev[sym].add(obj)
+
+ def set(self ,obj_sym ,prop_sym):
+ """
+ Assigns a property. Updates indexes for the specific property
+ AND its namespace (Parent).
+ """
+ # 1. Index Specific (e.g., #105 'Red')
+ self._add_posting(prop_sym ,obj_sym)
+
+ # 2. Index General (e.g., #50 'Color')
+ parent = SymbolSpace.get_parent(prop_sym)
+ if parent:
+ self._add_posting(parent ,obj_sym)
+
+ def find(self ,sym):
+ """Returns the set of objects associated with this symbol."""
+ return self._rev.get(sym ,set())
+
+# --- Work Function ---
+
+def verify_graph():
+ print("--- DiscreteFunction Verification ---")
+ # 1. Create Symbols
+ sym_obj = SymbolSpace.alloc()
+ sym_prop = SymbolSpace.alloc()
+ sym_parent = SymbolSpace.alloc()
+
+ # 2. Setup Hierarchy
+ SymbolSpace.set_parent(sym_prop, sym_parent)
+
+ # 3. Set Fact
+ df = DiscreteFunction()
+ df.set(sym_obj, sym_prop)
+
+ # 4. Check Smart Posting
+ print(f"Finding specific property: {len(df.find(sym_prop))} (Expected 1)")
+ print(f"Finding parent category: {len(df.find(sym_parent))} (Expected 1)")
+
+def CLI():
+ verify_graph()
+
+if __name__ == "__main__":
+ CLI()
--- /dev/null
+#!/usr/bin/env python3
+from SymbolSpace import SymbolSpace
+from DiscreteFunction import DiscreteFunction
+from Binder import Binder
+import bisect
+
+# --- Base Factory ---
+class DifferentiatedSymbol:
+ def __init__(self, name):
+ self.root_symbol = SymbolSpace.alloc()
+ self._intern_map = {}
+
+ def __call__(self, value):
+ if value not in self._intern_map:
+ sym = SymbolSpace.alloc()
+ self._intern_map[value] = sym
+ SymbolSpace.set_parent(sym, self.root_symbol)
+ self.on_new_symbol(value, sym) # Hook for subclasses
+ return self._intern_map[value]
+
+ def on_new_symbol(self, value, sym): pass
+
+# --- The "Interval Tree" Upgrade ---
+class OrderedNamespace(DifferentiatedSymbol):
+ """
+ A Namespace that maintains a Sorted Index for Range Queries.
+ """
+ def __init__(self, name):
+ super().__init__(name)
+ # Stores tuples of (Value, Symbol), sorted by Value
+ self._sorted_index = []
+
+ def on_new_symbol(self, value, sym):
+ # Maintain sorted order (O(N) insertion, but fast reads)
+ # In a real DB, this would be a B-Tree insert (O(log N))
+ bisect.insort(self._sorted_index, (value, sym))
+
+ def find_range(self, min_val, max_val):
+ """
+ Returns all symbols whose values fall in [min_val, max_val].
+ Complexity: O(log N) to find bounds + O(K) to collect K matches.
+ """
+ # 1. Binary Search for the start point
+ # We create a dummy tuple for comparison
+ start_idx = bisect.bisect_left(self._sorted_index, (min_val, None))
+
+ # 2. Binary Search for the end point
+ # We use a dummy symbol that is "infinite" to ensure we catch duplicates of max_val
+ # (or just rely on the tuple comparison logic)
+ end_idx = bisect.bisect_right(self._sorted_index, (max_val, object()))
+
+ # 3. Slice and Return Symbols
+ results = []
+ for i in range(start_idx, end_idx):
+ val, sym = self._sorted_index[i]
+ results.append(sym)
+
+ return results
+
+# --- Work Function ---
+
+def verify_range_query():
+ print("--- Range Query Verification ---")
+
+ # 1. Setup
+ Weight = OrderedNamespace("Weight")
+ K = DiscreteFunction() # Knowledge Graph
+ binder = Binder()
+
+ # 2. Objects (Bikes with different weights)
+ bike_light = object() # 50kg
+ bike_med = object() # 150kg
+ bike_heavy = object() # 250kg
+
+ sym_light = binder.get_symbol(bike_light)
+ sym_med = binder.get_symbol(bike_med)
+ sym_heavy = binder.get_symbol(bike_heavy)
+
+ # 3. Facts
+ K.set(sym_light, Weight(50))
+ K.set(sym_med, Weight(150))
+ K.set(sym_heavy, Weight(250))
+
+ # 4. Range Query: 100kg to 200kg
+ print("\nQuery: Find bikes between 100kg and 200kg")
+
+ # Step A: Expansion (Ask Namespace)
+ target_symbols = Weight.find_range(100, 200)
+ print(f" -> Namespace found {len(target_symbols)} relevant symbols.")
+
+ # Step B: Intersection (Ask Graph)
+ found_objects = []
+ for sym in target_symbols:
+ # Use the Reverse Map
+ objs = K.find(sym)
+ found_objects.extend(objs)
+
+ print(f" -> Graph found {len(found_objects)} objects.")
+
+ # Verification
+ # Should find only the medium bike
+ assert sym_med in found_objects
+ assert sym_light not in found_objects
+ assert sym_heavy not in found_objects
+ print(" -> SUCCESS: Only the 150kg bike was returned.")
+
+def CLI():
+ verify_range_query()
+
+if __name__ == "__main__":
+ CLI()
--- /dev/null
+#!/usr/bin/env python3
+from collections import deque as FIFO
+
+class SymbolSpace:
+ """
+ The manager of the Epimetheus integer namespace.
+ """
+
+ _counter = 0
+ _dealloc_queue = FIFO()
+
+ # HIERARCHY SUPPORT (Added)
+ _parents = {} # Map: Child_Sym -> Parent_Sym
+
+ class Instance:
+ """The handle for a symbol."""
+ __slots__ = ('_value' ,)
+
+ def __init__(self ,value):
+ self._value = value
+
+ def __eq__(self ,other):
+ # Compare value, not identity
+ if isinstance(other ,SymbolSpace.Instance): return self._value == other._value
+ return False
+
+ def __hash__(self):
+ return hash(self._value)
+
+ def __repr__(self):
+ return f"<Sym {self._value}>"
+
+ @classmethod
+ def alloc(cls) -> 'SymbolSpace.Instance':
+ val = 0
+ if cls._dealloc_queue:
+ val = cls._dealloc_queue.popleft()
+ else:
+ cls._counter += 1
+ val = cls._counter
+ return cls.Instance(val)
+
+ @classmethod
+ def dealloc(cls ,sym: 'SymbolSpace.Instance'):
+ val = sym._value
+ if val == 0: raise ValueError("Null symbol (0) cannot be deallocated.")
+
+ if val == cls._counter:
+ cls._counter -= 1
+ while cls._counter > 0 and cls._counter in cls._dealloc_queue:
+ cls._dealloc_queue.remove(cls._counter)
+ cls._counter -= 1
+ else:
+ cls._dealloc_queue.append(val)
+
+ @classmethod
+ def get_null(cls) -> 'SymbolSpace.Instance':
+ return cls.Instance(0)
+
+ # --- Hierarchy Methods ---
+
+ @classmethod
+ def set_parent(cls ,child ,parent):
+ cls._parents[child] = parent
+
+ @classmethod
+ def get_parent(cls ,child):
+ return cls._parents.get(child)
+
+def verify():
+ print(f"Allocating 3 symbols...")
+ s1 = SymbolSpace.alloc()
+ s2 = SymbolSpace.alloc()
+
+ # Test Hierarchy
+ SymbolSpace.set_parent(s2, s1)
+ assert SymbolSpace.get_parent(s2) == s1
+ print("Hierarchy check passed.")
+
+def CLI():
+ verify()
+
+if __name__ == "__main__":
+ CLI()
--- /dev/null
+from .Epimetheus import Epimetheus
+
--- /dev/null
+#!/usr/bin/env python3
+from SymbolSpace import SymbolSpace
+from Binder import Binder
+from DiscreteFunction import DiscreteFunction
+from Namespace import DifferentiatedSymbol ,OrderedNamespace
+
+def example_queries():
+ print("--- Epimetheus Architecture Example ---")
+
+ # 1. System Initialization
+ binder = Binder()
+ graph = DiscreteFunction()
+
+ # 2. Ontology Definition (The Factories)
+ Frame = DifferentiatedSymbol("FrameMaterial")
+ Price = OrderedNamespace("Price")
+
+ # 3. Data Ingestion (Transient Objects)
+ data_source = [
+ ("Bike_A" ,"Carbon" ,3500),
+ ("Bike_B" ,"Steel" ,800),
+ ("Bike_C" ,"Alum" ,1200),
+ ("Bike_D" ,"Carbon" ,1500),
+ ]
+
+ print(f"Ingesting {len(data_source)} items...")
+
+ # Keep references to prevent GC during ingestion for this example
+ start_objects = []
+
+ for label, material, cost in data_source:
+ # A. Create the Python Object
+ obj = type("Bike", (), {"label": label})()
+ start_objects.append(obj)
+
+ # B. Bind: Object -> Symbol
+ sym_bike = binder.get_symbol(obj)
+
+ # C. Describe: Symbol -> Properties
+ graph.set(sym_bike ,Frame(material))
+ graph.set(sym_bike ,Price(cost))
+
+ # ---------------------------------------------------------
+ # Example 1: Exact Query ("Find Carbon Frames")
+ # ---------------------------------------------------------
+ print("\n[Example 1] Exact Match: Frame('Carbon')")
+
+ # We ask the Factory for the symbol representing 'Carbon'
+ sym_carbon = Frame("Carbon")
+
+ # We ask the Graph for entities with that symbol
+ results = graph.find(sym_carbon)
+ print(f" -> Found {len(results)} bikes with Carbon frames.")
+
+ # ---------------------------------------------------------
+ # Example 2: Range Query ("Find Price 1000..2000")
+ # ---------------------------------------------------------
+ print("\n[Example 2] Range Match: Price(1000..2000)")
+
+ # Step A: Ask Namespace for symbols in range
+ # The OrderedNamespace uses bisect to find symbols efficiently
+ price_symbols = Price.find_range(1000 ,2000)
+ print(f" -> Namespace identified {len(price_symbols)} relevant price points.")
+
+ # Step B: Ask Graph for objects having ANY of those symbols
+ matches = set()
+ for p_sym in price_symbols:
+ found = graph.find(p_sym)
+ matches.update(found)
+
+ print(f" -> Graph resolved {len(matches)} bikes in price range.")
+
+ # ---------------------------------------------------------
+ # Example 3: Hierarchy Query ("Find Priced Things")
+ # ---------------------------------------------------------
+ print("\n[Example 3] Hierarchy Match: Has Price")
+
+ # We query the Root Symbol of the Price namespace.
+ # This works because the Graph automatically 'posts' up to the parent.
+ # FIXED: Changed .root to .root_symbol to match Namespace.py
+ all_priced = graph.find(Price.root_symbol)
+ print(f" -> Found {len(all_priced)} objects that have a price.")
+
+def CLI():
+ example_queries()
+
+if __name__ == "__main__":
+ CLI()
<html lang="en">
<head>
<meta charset="UTF-8">
- <title>Epimetheus: The Only Primitive</title>
+ <title>Epimetheus</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
<script src="style/body_visibility_hidden.js"></script>
<RT-title
author="Thomas Walker Lynch"
date="2026-01-14"
- title="Epimetheus: The Only Primitive">
+ title="Epimetheus">
</RT-title>
<RT-TOC level="1"></RT-TOC>
</p>
<p>
- Epimetheus (Afterthought) rejects this. It allows you to attach meaning (semantics) to objects after they are born. You can decide later that an object behaves like a number, or a string, or a user.
+ Epimetheus (Afterthought) is a different approach. It allows you to attach meaning (semantics) to objects after they are born. This is done in the form of properties that can be given arbitrary values, including test code.
</p>
<p>
</p>
<p>
- Thus the <RT-term>Symbol</RT-term> (the unique, persistent identity) is the most primitive data entity. Given <RT-term>Symbol</RT-term>s, and a <RT-term>Turing Machine</RT-term> for building structure, everything else follows. But this is not an article about constructing mathematics or computer science, rather it is about a <RT-term>type system</RT-term>, so lets not get too carried away with the grand strokes of the pen.
+ Thus the <RT-term>Symbol</RT-term> (the unique, persistent identity) is the most primitive data entity. Given <RT-term>Symbol</RT-term>s, and a <RT-term>Turing Machine</RT-term> for building structure, everything else follows. Here are "<RT-term>Turing Machine</RT-term>" will be Python code.
</p>
<h1>Assumptions and Terms</h1>
</p>
<p>
- In the Python version of Epimetheus <RT-term>symbol</RT-term>s are indeed implemented over integers. However, Python integers are non-primitive and thus are passed by reference. The Python Epimetheus <RT-term>symbol instance</RT-term> factory will return a reference to an integer, not the base integer, as the <RT-term>symbol instance</RT-term>. Assignment will then copy the reference. Thus this reference is the <RT-term>symbol instance</RT-term> rather than the integer the <RT-term>symbol</RT-term> is based on.
+ In the Python version of Epimetheus <RT-term>symbol</RT-term>s are indeed implemented over integers. However, Python integers are non-primitive and thus are passed by reference. The Python Epimetheus <RT-term>symbol instance</RT-term> factory will return a reference to an integer, not the base integer, as the <RT-term>symbol instance</RT-term>. Assignment will then copy the reference. So we end up with references to symbol instances, though these references are transparent, so we will call them symbol instances. Close enough, as they say.
</p>
<p>
- In Epimetheus, we use a dictionary to give a <RT-term>symbol</RT-term> a name. The names need not meet the requirements imposed on a <RT-term>symbol instance</RT-term>, but it can be confusing when they don't. This is avoided in other <RT-term>symbol</RT-term> systems by implementing <RT-term>symbol</RT-term>s over character strings, and using the character string as both the name and the instance.
+ In Epimetheus, we use a dictionary to give a <RT-term>symbol</RT-term> a name. The names need not meet the requirements imposed on a <RT-term>symbols</RT-term>, but it can be confusing when they don't. Other implementations avoid this issue by using strings as the basis for symbols, though this approach causes some other problems, such as creating the requirement that all symbols must have names, and requiring the user make names that follow the requirements of a symbol instances. It is not uncommon to find in such implementations users meeting these requirements by writing programs to create names for symbols.
</p>
<h3>Required Properties</h3>
<p>
A <RT-term>symbol</RT-term> is associated with an object using a Python dictionary. The <RT-term>symbol</RT-term> is the key, and the object is that thing which is "looked up" via said key.
- One such example is the <RT-term>symbol</RT-term> name dictionary mentioned in the prior section.
+ An example of such a dictionary is the <RT-term>symbol</RT-term> name dictionary mentioned in the prior section.
</p>
<h2>Tape</h2>
</p>
<p>
- The reader might have expected the <RT-term>path</RT-term> to go from left to right, with the <RT-term>destination</RT-term> being in the rightmost cell. This would be natural because we read characters from a written page going from left to right. However, such a definition would run into a problem for us, as we will need for paths to always have a destination, and <RT-term>tape</RT-term>s can be open on the right, so they do not always have a rightmost cell.
+ The reader might have expected the <RT-term>path</RT-term> to go from left to right, with the <RT-term>destination</RT-term> instead being in the rightmost cell. This would be natural because we read characters from a written page going from left to right. However, such a definition would run into a problem for us, as we will need for paths to always have a destination, and <RT-term>tape</RT-term>s can be open on the right, so they do not always have a rightmost cell.
</p>
<blockquote>
</p>
<p>
- Thus a function is more restricted than a <RT-term>tape</RT-term> of paths, and due to this restriction it is possible to adopt the following notation, where a <RT-term>destination</RT-term> is said to be determined by, i.e. be a function of, the <RT-term>way</RT-term>:
+ Thus a function is more restricted than a <RT-term>tape</RT-term> of paths, as it disallows any paths made unique solely by changing the destination. This property facilities the following notation, where a <RT-term>destination</RT-term> is said to be determined by, i.e. be a function of, the <RT-term>way</RT-term>:
</p>
<RT-math>
</RT-math>
<p>
- That the same <RT-term>way</RT-term> always leads to the same destination fits our common experience. If a person followed the same way twice and landed in different destinations. that person might think himself/herself to be in a Sci-Fi movie. It is also intuitive to us that the function restrictions do not exclude the possibility that multiple <RT-term>way</RT-term>s can lead to the same destination. Because we often compute things that are related to our daily experience it is not surprising that this is a very common pattern. And this is not a coincidence, this is the reason functions are defined as they are.
+ That the same <RT-term>way</RT-term> always leads to the same destination fits our common experience. If a person followed the same way twice and landed in different destinations, that person might think himself/herself to be in a Sci-Fi movie. It is also intuitive to us that the function restrictions do not exclude the possibility that multiple <RT-term>way</RT-term>s can lead to the same destination. Because we often compute things that are related to our intuition about the world, <RT-term>function</RT-term>s are very common. As for discreteness and intuition, that conversation goes back at least to Democritus and Aristotle.
</p>
<script src="style/style_orchestrator.js"></script>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <title>TM First Order</title>
+ <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
+
+ <script src="style/body_visibility_hidden.js"></script>
+ <script>
+ window.StyleRT.body_visibility_hidden();
+ </script>
+ </head>
+ <body>
+ <RT-article>
+ <RT-title
+ author="Thomas Walker Lynch"
+ date="2026-02-03"
+ title="TM First Order">
+ </RT-title>
+
+ <RT-TOC level="1"></RT-TOC>
+
+ <h1>Introduction</h1>
+
+ <p>
+ The <RT-term>First Order Tape Machine</RT-term> (TM) is a fundamental mechanism for sequence manipulation. It is a concrete implementation of the <RT-term>Tape Machine</RT-term> abstraction defined in the <RT-term>TTCA</RT-term>.
+ </p>
+
+ <p>
+ While modern programming languages offer various containers (Lists, Arrays, Vectors), the <RT-term>First Order TM</RT-term> unifies them under a single <RT-term>interface</RT-term> that emphasizes <RT-term>positional state</RT-term>. Unlike a standard iterator which consumes data, a TM persists. Unlike a raw array which is stateless, a TM maintains a <RT-term>head</RT-term>.
+ </p>
+
+ <h1>Command Reference</h1>
+
+ <p>
+ The Tape Machine is controlled via a formal command language. This section defines the abstract commands available to the machine. The notation uses strictly ASCII characters.
+ </p>
+
+ <h2>Grammar</h2>
+ <RT-code>
+statement :: [direction]command+[modifier][&contract]*[arg]*
+direction :: l | ε
+command :: r | w | s | a | d | q | m | e | t
+modifier :: L | R | A | AR | n
+ </RT-code>
+
+ <h2>Definitions</h2>
+
+ <h3>Direction</h3>
+ <ul>
+ <li><RT-code>ε</RT-code> (Empty): Implicit Right / Forward / Plus.</li>
+ <li><RT-code>l</RT-code>: Left / Backward / Minus.</li>
+ </ul>
+
+ <h3>Abstract Commands</h3>
+ <ul>
+ <li><RT-code>r</RT-code>: <strong>Read</strong> the cell under the head.</li>
+ <li><RT-code>w</RT-code>: <strong>Write</strong> the cell under the head.</li>
+ <li><RT-code>s</RT-code>: <strong>Step</strong> the head position.</li>
+ <li><RT-code>a</RT-code>: <strong>Allocate</strong> (Add/Append) a new cell.</li>
+ <li><RT-code>d</RT-code>: <strong>Deallocate</strong> (Drop/Delete) a cell.</li>
+ <li><RT-code>q</RT-code>: <strong>Query</strong>. Ask a question about the machine state.</li>
+ <li><RT-code>m</RT-code>: <strong>Move</strong>. No allocation or deallocation; requires fill.</li>
+ <li><RT-code>e</RT-code>: <strong>Entangle</strong>. Spawns a new head on the same tape.</li>
+ <li><RT-code>t</RT-code>: <strong>Thread</strong>. Entangle on a new thread.</li>
+ </ul>
+
+ <h3>Modifiers</h3>
+ <ul>
+ <li><RT-code>L</RT-code>: Operate on <strong>Leftmost</strong>.</li>
+ <li><RT-code>R</RT-code>: Operate on <strong>Rightmost</strong>.</li>
+ <li><RT-code>A</RT-code>: Operate on <strong>Address</strong> (Head Index).</li>
+ <li><RT-code>AR</RT-code>: Operate on <strong>Address of Rightmost</strong> (Extent).</li>
+ <li><RT-code>n</RT-code>: Repeat <strong>n</strong> times (requires argument).</li>
+ </ul>
+
+ <h3>Contracts</h3>
+ <p>
+ Contracts assert the state of the machine before execution.
+ </p>
+ <ul>
+ <li><RT-code>hL</RT-code>: Head is at Leftmost.</li>
+ <li><RT-code>hR</RT-code>: Head is at Rightmost.</li>
+ </ul>
+
+ <h2>Examples</h2>
+
+ <RT-code>
+ls ; Step left
+aL ; Allocate (create) a new leftmost cell
+aR ; Allocate (append) to rightmost
+qA ; Query Address (What is the head index?)
+qAR ; Query Extent (What is the max index?)
+ </RT-code>
+
+ <h1>Primitive Method Reference</h1>
+
+ <p>
+ This section details the actual methods exposed by the First Order TM implementation (Python/C). These primitives map directly to the command language or provide optimized compound operations.
+ </p>
+
+ <h2>Navigation Primitives</h2>
+ <ul>
+ <li><RT-code>s()</RT-code>: Step Right.</li>
+ <li><RT-code>sn(n)</RT-code>: Step Right <RT-math>n</RT-math> times.</li>
+ <li><RT-code>ls()</RT-code>: Step Left.</li>
+ <li><RT-code>lsn(n)</RT-code>: Step Left <RT-math>n</RT-math> times.</li>
+ </ul>
+
+ <h2>I/O Primitives</h2>
+ <ul>
+ <li><RT-code>r()</RT-code>: Read current cell.</li>
+ <li><RT-code>rn(n)</RT-code>: Read <RT-math>n</RT-math> cells (Bulk Read).</li>
+ <li><RT-code>w(v)</RT-code>: Write value to current cell.</li>
+ <li><RT-code>wn(list)</RT-code>: Write list of values (Bulk Write).</li>
+ </ul>
+
+ <h2>Allocation Primitives</h2>
+ <ul>
+ <li><RT-code>aL(v)</RT-code>: Allocate Left (Prepend).</li>
+ <li><RT-code>aR(v)</RT-code>: Allocate Right (Append).</li>
+ </ul>
+
+ <h2>Deletion Primitives</h2>
+ <ul>
+ <li><RT-code>d()</RT-code>: Delete current cell.</li>
+ <li><RT-code>dn(n)</RT-code>: Delete <RT-math>n</RT-math> cells starting at current.</li>
+ </ul>
+
+ <h2>Compound Primitives</h2>
+ <p>
+ These methods combine multiple abstract commands into a single atomic C-operation for performance and safety.
+ </p>
+ <ul>
+ <li><RT-code>esd()</RT-code>: <strong>Entangle-Step-Delete</strong>. Equivalent to <RT-code>e</RT-code> → <RT-code>s</RT-code> → <RT-code>d</RT-code>. Safely deletes the cell to the right of the head (the "neighbor").</li>
+ <li><RT-code>esdn(n)</RT-code>: Delete <RT-math>n</RT-math> right neighbors.</li>
+ </ul>
+
+ <h2>Query Primitives</h2>
+ <p>
+ Introspection commands used to check machine state without side effects.
+ </p>
+ <ul>
+ <li><RT-code>qA()</RT-code>: <strong>Query Address</strong>. Return the current head index.</li>
+ <li><RT-code>qR()</RT-code>: <strong>Query Rightmost</strong>. Returns <RT-code>True</RT-code> if the head is at the rightmost cell.</li>
+ <li><RT-code>qL()</RT-code>: <strong>Query Leftmost</strong>. Returns <RT-code>True</RT-code> if the head is at the leftmost cell (index 0).</li>
+ <li><RT-code>qAR()</RT-code>: <strong>Query Address Rightmost</strong> (Extent). Returns the index of the rightmost cell (Length - 1). This ensures the return value always fits within the address space, unlike Length which is one greater than the maximum index.</li>
+ </ul>
+
+ <h2>Entanglement Primitives</h2>
+ <ul>
+ <li><RT-code>e()</RT-code>: <strong>Entangle</strong>. Creates a new machine instance sharing the same tape and safety catalog. The new machine's head is initialized to the same position as the original machine.</li>
+ </ul>
+
+ <h1>Architecture</h1>
+
+ <h2>The Hybrid Model</h2>
+ <p>
+ For maximum performance in high-frequency loops, the First Order TM is implemented using a <RT-neologism>Direct Execution</RT-neologism> architecture.
+ </p>
+
+ <ul>
+ <li><strong>Inner Loop (C-Extension):</strong> The core operations—reading, stepping, and writing—are implemented in C. This code directly manipulates the memory pointers of the underlying Python List, avoiding interpreter overhead.</li>
+ <li><strong>Outer Loop (Python Wrapper):</strong> The Python layer handles initialization and interface compliance.</li>
+ </ul>
+
+ <h2>Entanglement Safety</h2>
+ <p>
+ A critical feature of the TM is <RT-term>Entanglement</RT-term>. Multiple TMs can operate on the same underlying tape memory simultaneously. This is efficient, but dangerous: if one machine deletes a cell that another machine is looking at, the system could crash or corrupt state.
+ </p>
+
+ <p>
+ To prevent this, the TM implements an <RT-neologism>Entanglement Catalog</RT-neologism> in the C layer.
+ </p>
+
+ <RT-math>
+ \text{Safe}(op) \iff \forall \text{peer} \in \text{Catalog}, \text{Head}(\text{peer}) \notin \text{VictimRange}(op)
+ </RT-math>
+
+ <p>
+ Before any destructive operation (like delete), the machine checks the catalog. If any peer's head is currently positioned on a cell scheduled for deletion, the operation is blocked with a <RT-code>RuntimeError</RT-code>.
+ </p>
+
+ <script src="style/style_orchestrator.js"></script>
+ <script>
+ window.StyleRT.style_orchestrator();
+ </script>
+ </RT-article>
+ </body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <title>02 - The First Order Tape Machine</title>
+ <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap" rel="stylesheet">
+
+ <script src="style/body_visibility_hidden.js"></script>
+ <script>
+ window.StyleRT.body_visibility_hidden();
+ </script>
+ </head>
+ <body>
+ <RT-article>
+ <RT-title
+ author="Thomas Walker Lynch"
+ date="2026-02-03"
+ title="02 - The First Order Tape Machine">
+ </RT-title>
+
+ <RT-TOC level="1"></RT-TOC>
+
+ <h1>Introduction</h1>
+
+ <p>
+ The <RT-term>First Order Tape Machine</RT-term> (TM) is the foundational mechanism for sequence manipulation. It is a concrete implementation of the <RT-term>Tape Machine</RT-term> abstraction defined in the TTCA.
+ </p>
+
+ <p>
+ While modern programming languages offer various containers (Lists, Arrays, Vectors), the <RT-term>First Order TM</RT-term> unifies them under a single <RT-term>interface</RT-term> that emphasizes <RT-term>positional state</RT-term>. Unlike a standard iterator which consumes data, a TM persists. Unlike a raw array which is stateless, a TM maintains a <RT-term>head</RT-term>.
+ </p>
+
+ <h1>Architecture</h1>
+
+ <h2>The Hybrid Model</h2>
+ <p>
+ For maximum performance in high-frequency loops, the First Order TM is implemented using a <RT-neologism>Direct Execution</RT-neologism> architecture.
+ </p>
+
+ <ul>
+ <li><strong>Inner Loop (C-Extension):</strong> The core operations—reading, stepping, and writing—are implemented in C. This code directly manipulates the memory pointers of the underlying Python List, avoiding interpreter overhead.</li>
+ <li><strong>Outer Loop (Python Wrapper):</strong> The Python layer handles initialization and interface compliance.</li>
+ </ul>
+
+ <p>
+ This hybrid approach allows the TM to execute simple steps like <RT-code>s()</RT-code> (step right) in nanoseconds, comparable to native pointer arithmetic in compiled languages.
+ </p>
+
+ <h2>Entanglement Safety</h2>
+ <p>
+ A critical feature of the Epimetheus TM is <RT-term>Entanglement</RT-term>. Multiple TMs can operate on the same underlying tape memory simultaneously. This is efficient, but dangerous: if one machine deletes a cell that another machine is looking at, the system could crash or corrupt state.
+ </p>
+
+ <p>
+ To prevent this, the TM implements an <RT-neologism>Entanglement Catalog</RT-neologism> in the C layer.
+ </p>
+
+ <RT-math>
+ \text{Safe}(op) \iff \forall \text{peer} \in \text{Catalog}, \text{Head}(\text{peer}) \notin \text{VictimRange}(op)
+ </RT-math>
+
+ <p>
+ Before any destructive operation (like delete), the machine checks the catalog. If any peer's head is currently positioned on a cell scheduled for deletion, the operation is blocked with a <RT-code>RuntimeError</RT-code>.
+ </p>
+
+ <h1>Interface</h1>
+
+ <h2>Movement</h2>
+ <p>
+ The TM maintains a <RT-term>Head</RT-term> index. Movement is relative.
+ </p>
+
+ <ul>
+ <li><RT-code>s()</RT-code>: Step Right (increment head).</li>
+ <li><RT-code>sn(n)</RT-code>: Step Right by <RT-math>n</RT-math>.</li>
+ <li><RT-code>ls()</RT-code>: Step Left (decrement head).</li>
+ <li><RT-code>lsn(n)</RT-code>: Step Left by <RT-math>n</RT-math>.</li>
+ </ul>
+
+ <h2>Read / Write</h2>
+ <p>
+ Data access occurs at the current head position.
+ </p>
+
+ <RT-code>
+# Read current cell
+val = tm.r()
+
+# Bulk read next 3 cells
+chunk = tm.rn(3)
+
+# Write to current cell
+tm.w(42)
+
+# Bulk write (overwrite sequence)
+tm.wn([10, 20, 30])
+ </RT-code>
+
+ <h2>Allocation</h2>
+ <p>
+ New cells can be created at the boundaries.
+ </p>
+ <ul>
+ <li><RT-code>aR(val)</RT-code>: Append Right (standard append).</li>
+ <li><RT-code>aL(val)</RT-code>: Append Left (prepend). Note that this operation shifts the indices of all existing cells. The TM automatically adjusts its own head to maintain logical stability, but peers may experience <RT-neologism>Index Drift</RT-neologism>.</li>
+ </ul>
+
+ <h2>Deletion</h2>
+ <p>
+ Deletion is the only operation restricted by Entanglement Safety.
+ </p>
+
+ <h3>Delete Current (d)</h3>
+ <p>
+ <RT-code>d()</RT-code> removes the cell currently under the head. After deletion, the head index remains unchanged, but it now points to the <em>next</em> cell in the sequence (the one that shifted into the slot).
+ </p>
+
+ <h3>Delete Neighbor (esd)</h3>
+ <p>
+ <RT-code>esd()</RT-code> (Entangle, Step, Delete) removes the cell immediately to the <em>right</em> of the head. This is the primitive operation for Singly Linked Tapes, but is offered on the First Order TM for symmetry.
+ </p>
+
+ <h1>Implementation Detail</h1>
+
+ <h2>The C Module</h2>
+ <p>
+ The C module <RT-code>TM_module.c</RT-code> defines the <RT-code>FastTM</RT-code> struct.
+ </p>
+
+ <RT-code>
+typedef struct {
+ PyObject_HEAD
+ PyObject* tape_obj; /* Shared Python List */
+ PyObject* peer_list; /* Shared WeakRef List */
+ Py_ssize_t head; /* C-Level Integer */
+ PyObject* weakreflist; /* Garbage Collection Support */
+} FastTM;
+ </RT-code>
+
+ <p>
+ By keeping the <RT-code>head</RT-code> as a native C integer <RT-code>Py_ssize_t</RT-code>, arithmetic operations avoid the boxing/unboxing cost of Python Integers.
+ </p>
+
+ <script src="style/style_orchestrator.js"></script>
+ <script>
+ window.StyleRT.style_orchestrator();
+ </script>
+ </RT-article>
+ </body>
+</html>