introduces Symbol.py
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 12 Feb 2026 15:03:16 +0000 (15:03 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Thu, 12 Feb 2026 15:03:16 +0000 (15:03 +0000)
developer/authored/Symbol.py
developer/authored/TM_Array.c
developer/authored/TM_GR.c
developer/authored/TM_NaturalNumber.c
developer/authored/TM_module.c
developer/authored/build/temp.linux-x86_64-cpython-311/TM_module.o
document/Symbol_Specification.html [new file with mode: 0644]

index 98deb40..e893c6f 100755 (executable)
-#!/usr/bin/env python3
-"""
-Symbol.py
-Epimetheus Symbol Implementation.
-Core Concept: A Symbol is a discrete, hashable set defined by its identity.
-"""
+# Symbol.py
+# RT format: 2-space indent, PascalCase type names, snake_case identifiers.
 
+from __future__ import annotations
+
+import threading
 import weakref
+from typing import Optional, Sequence, Tuple
+
+
+class SymbolSpace:
+  """
+  A SymbolSpace provides:
+  - A Null symbol (identity 0).
+  - A ContextMap from symbol context keys to Factories.
+  - Factories that issue symbols and reclaim identities on GC.
+  """
+
+  class Symbol:
+    __slots__ = (
+      "_identity"
+      ,"_factory_ref"
+      ,"_finalizer"
+      ,"_factory_id"
+      ,"__weakref__"
+    )
+
+    def __init__(self ,identity: int ,factory: Optional["SymbolSpace.Factory"]):
+      self._identity = int(identity)
+
+      if(self._identity == 0):
+        self._factory_ref = None
+        self._finalizer = None
+        self._factory_id = 0
+        return
+
+      if(factory is None):
+        raise ValueError("Non-null symbols require a factory.")
+
+      self._factory_id = factory.factory_id
+      self._factory_ref = weakref.ref(factory)
+
+      identity_copy = self._identity
+      factory_ref = self._factory_ref
+
+      def _finalize():
+        f = factory_ref()
+        if(f is None):
+          return
+        try:
+          f._reclaim_identity(identity_copy)
+        except Exception:
+          # Finalizers must never raise.
+          return
+
+      self._finalizer = weakref.finalize(self ,_finalize)
+
+    @property
+    def identity(self) -> int:
+      return self._identity
+
+    def __repr__(self) -> str:
+      if(self._identity == 0):
+        return "Symbol(0)"
+      return f"Symbol({self._identity} ,factory_id={self._factory_id})"
+
+    def __hash__(self) -> int:
+      return hash( (self._factory_id ,self._identity) )
+
+    def __eq__(self ,other: object) -> bool:
+      if( not isinstance(other ,SymbolSpace.Symbol) ):
+        return False
+      return (self._factory_id == other._factory_id) and (self._identity == other._identity)
+
+  class Factory:
+    """
+    Issues identities from a monotonically increasing counter and a free set.
+
+    Reclaim policy (from the spec):
+    - When a reclaimed identity equals counter, decrement counter.
+      Continue decrementing while counter is in the free set.
+    - Otherwise, add the identity to the free set.
+    """
+
+    __slots__ = (
+      "_lock"
+      ,"_counter"
+      ,"_free_set"
+      ,"_space"
+      ,"_context_key"
+      ,"factory_id"
+      ,"__weakref__"
+    )
+
+    def __init__(self ,space: "SymbolSpace" ,context_key: Tuple["SymbolSpace.Symbol" ,...] ,factory_id: int):
+      self._lock = threading.RLock()
+      self._counter = 0  # 0 is reserved for space.null
+      self._free_set = set()  # Set[int]
+      self._space = space
+      self._context_key = context_key
+      self.factory_id = int(factory_id)
 
-class Symbol(set):
+    @property
+    def counter(self) -> int:
+      with self._lock:
+        return self._counter
+
+    @property
+    def free_set_size(self) -> int:
+      with self._lock:
+        return len(self._free_set)
+
+    def make(self) -> "SymbolSpace.Symbol":
+      with self._lock:
+        if(self._free_set):
+          identity = min(self._free_set)
+          self._free_set.remove(identity)
+          return self._space.Symbol(identity ,self)
+
+        self._counter += 1
+        return self._space.Symbol(self._counter ,self)
+
+    def _reclaim_identity(self ,identity: int) -> None:
+      identity = int(identity)
+      if(identity == 0):
+        raise ValueError("Attempted to reclaim the null symbol identity 0.")
+
+      with self._lock:
+        if(identity > self._counter):
+          raise ValueError(f"Attempted to reclaim identity {identity} above counter {self._counter}.")
+
+        if(identity in self._free_set):
+          raise ValueError(f"Identity {identity} already reclaimed.")
+
+        if(identity == self._counter):
+          self._counter -= 1
+          while(self._counter in self._free_set):
+            self._free_set.remove(self._counter)
+            self._counter -= 1
+          return
+
+        self._free_set.add(identity)
+
+  class ContextMap:
     """
-    A persistent, unique identity that acts as a container.
-    
-    Properties:
-      - Identity: Equality and Hashing are based on memory address (id).
-      - Container: Inherits from set. Can contain other symbols (differentiation).
-      - Hierarchy: Knows its parent to support dealloc().
+    Map: context_key -> Factory
+    A context_key is an ordered list of symbols, represented as a tuple.
     """
-    
-    def __init__(self, parent=None):
-        super().__init__()
-        # We hold a strong ref to the parent? 
-        # If we hold strong, the root keeps the whole tree alive.
-        # If we hold weak, we can't dealloc if parent dies (but that's expected).
-        # Standard graph theory: Edges are usually strong.
-        self._parent = parent
-
-    def alloc(self):
-        """
-        Allocates a new differentiated symbol from this one.
-        The new symbol is added to this symbol (the set).
-        """
-        child = Symbol(parent=self)
-        self.add(child)
-        return child
-
-    def dealloc(self):
-        """
-        Removes this symbol from its parent.
-        If no other references exist, this symbol will be garbage collected.
-        """
-        if self._parent is not None:
-            self._parent.remove(self)
-            self._parent = None
-        # If parent is None (Root), dealloc does nothing.
-
-    # --- Identity Overrides (Force Set to be Hashable) ---
-
-    def __hash__(self):
-        return id(self)
-
-    def __eq__(self, other):
-        return self is other
-
-    def __repr__(self):
-        return f"<Symbol {id(self):x}>"
-
-# --- Example ---
-
-def example_symbol_lifecycle():
-    print("--- Symbol Lifecycle Example ---")
-    root = Symbol()
-
-    # 1. Root exists
-    print(f"Root: {root}")
-    
-    # 2. Alloc Features
-    nav = root.alloc()
-    print(f"Allocated 'nav' inside root: {nav}")
-    print(f"root has nav? {nav in root}")
-    
-    # 3. Alloc Leaf
-    left = nav.alloc()
-    print(f"Allocated 'left' inside nav: {left}")
-    
-    # 4. Dealloc
-    print("Deallocating 'left'...")
-    left.dealloc()
-    print(f"nav has left? {left in nav} (Expected: False)")
-
-if __name__ == "__main__":
-    example_symbol_lifecycle()
+
+    __slots__ = (
+      "_space"
+      ,"_lock"
+      ,"_factory_map"
+      ,"_factory_id_counter"
+    )
+
+    def __init__(self ,space: "SymbolSpace"):
+      self._space = space
+      self._lock = threading.RLock()
+      self._factory_map = {}  # Dict[Tuple[Symbol] ,Factory]
+      self._factory_id_counter = 0
+
+    def _normalize(self ,context_key: Optional[Sequence["SymbolSpace.Symbol"]]) -> Tuple["SymbolSpace.Symbol" ,...]:
+      if(context_key is None):
+        return tuple()
+      if( isinstance(context_key ,tuple) ):
+        ctx = context_key
+      else:
+        ctx = tuple(context_key)
+
+      for s in ctx:
+        if( not isinstance(s ,SymbolSpace.Symbol) ):
+          raise TypeError("context_key entries must be SymbolSpace.Symbol values.")
+
+      return ctx
+
+    def read(self ,context_key: Optional[Sequence["SymbolSpace.Symbol"]] = None) -> Optional["SymbolSpace.Factory"]:
+      ctx = self._normalize(context_key)
+      with self._lock:
+        return self._factory_map.get(ctx)
+
+    def make(self ,context_key: Optional[Sequence["SymbolSpace.Symbol"]] = None) -> "SymbolSpace.Factory":
+      ctx = self._normalize(context_key)
+      with self._lock:
+        if(ctx in self._factory_map):
+          raise KeyError("Factory already exists for this context_key.")
+
+        self._factory_id_counter += 1
+        f = SymbolSpace.Factory(self._space ,ctx ,self._factory_id_counter)
+        self._factory_map[ctx] = f
+        return f
+
+    def delete(self ,context_key: Optional[Sequence["SymbolSpace.Symbol"]] = None) -> None:
+      ctx = self._normalize(context_key)
+      with self._lock:
+        if(ctx not in self._factory_map):
+          raise KeyError("No factory exists for this context_key.")
+        del self._factory_map[ctx]
+
+    def __len__(self) -> int:
+      with self._lock:
+        return len(self._factory_map)
+
+  def __init__(self):
+    self.null = SymbolSpace.Symbol(0 ,None)
+    self.context_map = SymbolSpace.ContextMap(self)
+
+    # Default root factory for empty context.
+    self.root_factory = self.context_map.make(tuple())
index f0ae915..471f805 100644 (file)
@@ -4,21 +4,18 @@
   Backing: PyListObject
 */
 
-/* ALLOW CDOT IN IDENTIFIERS */
-#define · _ 
-
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include "structmember.h"
 
-/* --- 1. HEAD STRUCT (Linear Array) --- */
+/* --- 1. HEAD STRUCT --- */
 
 typedef struct {
   PyObject_HEAD
-  PyObject* tape_obj;       /* Variable: The Container */
-  PyObject** head_ptr;      /* Variable: Pointer to Current Cell */
-  PyObject** leftmost_ptr;  /* Variable: Pointer to Leftmost Cell */
-  PyObject** right_sentinel;/* Variable: Pointer to Right Sentinel */
+  PyObject* tape_obj;       /* Variable: Container */
+  PyObject** head_ptr;      /* Variable: Current Cell */
+  PyObject** leftmost_ptr;  /* Variable: Left Bound */
+  PyObject** right_sentinel;/* Variable: Right Bound */
 } TM·Arr·Head;
 
 static void TM·Arr·dealloc(TM·Arr·Head* self){
@@ -178,7 +175,6 @@ static PyObject* TM·Arr·LqnR(TM·Arr·Head* self){
 
 static PyObject* TM·Arr·dR(TM·Arr·Head* self){
   TM·Arr·lazysync(self);
-  /* Guard: Must have a left neighbor to step back to. */
   if (self->head_ptr <= self->leftmost_ptr) {
       PyErr_SetString(PyExc_RuntimeError, "Invariant Violation: Cannot dR from leftmost cell.");
       return NULL;
@@ -195,7 +191,6 @@ static PyObject* TM·Arr·dR(TM·Arr·Head* self){
 
 static PyObject* TM·Arr·LdR(TM·Arr·Head* self){
   TM·Arr·lazysync(self);
-  /* Guard: Must have a right neighbor to reset to. */
   if (self->head_ptr >= self->right_sentinel - 1) {
       PyErr_SetString(PyExc_RuntimeError, "Invariant Violation: Cannot LdR from rightmost cell.");
       return NULL;
@@ -264,3 +259,73 @@ static PyObject* TM·Arr·LaR(TM·Arr·Head* self, PyObject* val){
   TM·Arr·sync(self);
   Py_RETURN_NONE;
 }
+
+/* --- 8. METHOD TABLES --- */
+
+static PyMethodDef Table·Arr·CR·ND[] = {
+  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
+  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
+  {"e", (PyCFunction)TM·Arr·e, METH_NOARGS, ""},
+  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
+  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
+  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
+  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
+  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
+  {NULL}
+};
+
+static PyMethodDef Table·Arr·CLR·ND[] = {
+  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
+  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
+  {"e", (PyCFunction)TM·Arr·e, METH_NOARGS, ""},
+  {"Ls",(PyCFunction)TM·Arr·Ls,METH_NOARGS, ""},
+  {"Lsn",(PyCFunction)TM·Arr·Lsn,METH_VARARGS,""},
+  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
+  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
+  {"LqR",(PyCFunction)TM·Arr·LqR,METH_NOARGS, ""},
+  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
+  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
+  {"sR",(PyCFunction)TM·Arr·sR,METH_NOARGS, ""},
+  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
+  {NULL}
+};
+
+static PyMethodDef Table·Arr·CR·SO[] = {
+  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
+  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
+  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
+  {"dR",(PyCFunction)TM·Arr·dR,METH_NOARGS, ""},
+  {"esd",(PyCFunction)TM·Arr·esd,METH_NOARGS,""},
+  {"esa",(PyCFunction)TM·Arr·esa,METH_O,     ""},
+  {"aR",(PyCFunction)TM·Arr·aR,METH_O,       ""},
+  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
+  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
+  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
+  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
+  {NULL}
+};
+
+static PyMethodDef Table·Arr·CLR·SO[] = {
+  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
+  {"Ls",(PyCFunction)TM·Arr·Ls,METH_NOARGS, ""},
+  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
+  {"dR",(PyCFunction)TM·Arr·dR,METH_NOARGS, ""},
+  {"LdR",(PyCFunction)TM·Arr·LdR,METH_NOARGS,""},
+  {"esd",(PyCFunction)TM·Arr·esd,METH_NOARGS,""},
+  {"eLsd",(PyCFunction)TM·Arr·eLsd,METH_NOARGS,""},
+  {"esa",(PyCFunction)TM·Arr·esa,METH_O,     ""},
+  {"eLsa",(PyCFunction)TM·Arr·eLsa,METH_O,   ""},
+  {"aR",(PyCFunction)TM·Arr·aR,METH_O,       ""},
+  {"LaR",(PyCFunction)TM·Arr·LaR,METH_O,     ""},
+  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
+  {"LqR",(PyCFunction)TM·Arr·LqR,METH_NOARGS, ""},
+  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
+  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
+  {"sR",(PyCFunction)TM·Arr·sR,METH_NOARGS, ""},
+  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
+  {NULL}
+};
index 76b4aa4..3134744 100644 (file)
@@ -4,19 +4,14 @@
   Backing: Generic Python Object with "right" and "left" attributes.
 */
 
-/* ALLOW CDOT IN IDENTIFIERS */
-#define · _ 
-
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include "structmember.h"
 
-/* --- 1. HEAD STRUCT (Graph) --- */
-
 typedef struct {
   PyObject_HEAD
-  PyObject* leftmost_node; /* Variable: The anchor/start of the tape */
-  PyObject* head_node;     /* Variable: The current cell/node */
+  PyObject* leftmost_node; 
+  PyObject* head_node;     
 } TM·Gr·Head;
 
 static void TM·Gr·dealloc(TM·Gr·Head* self){
@@ -43,35 +38,29 @@ static int TM·Gr·init(TM·Gr·Head* self, PyObject* args, PyObject* kwds){
   return 0;
 }
 
-/* --- 2. PRIMITIVES --- */
+/* --- PRIMITIVES --- */
 
 static PyObject* TM·Gr·s(TM·Gr·Head* self){ 
-  /* Spatial: Move Right */
   PyObject* right = PyObject_GetAttrString(self->head_node, "right");
   if (!right) return NULL; 
-  
   if (right == Py_None) {
       Py_DECREF(right);
       PyErr_SetString(PyExc_RuntimeError, "Stepped off tape (right is None).");
       return NULL;
   }
-  
   Py_DECREF(self->head_node);
   self->head_node = right;
   Py_RETURN_NONE; 
 }
 
 static PyObject* TM·Gr·Ls(TM·Gr·Head* self){ 
-  /* Spatial: Move Left */
   PyObject* left = PyObject_GetAttrString(self->head_node, "left");
   if (!left) return NULL;
-  
   if (left == Py_None) {
       Py_DECREF(left);
       PyErr_SetString(PyExc_RuntimeError, "Stepped off tape (left is None).");
       return NULL;
   }
-  
   Py_DECREF(self->head_node);
   self->head_node = left;
   Py_RETURN_NONE; 
@@ -92,19 +81,16 @@ static PyObject* TM·Gr·e(TM·Gr·Head* self){
 }
 
 static PyObject* TM·Gr·r(TM·Gr·Head* self){ 
-  /* In Graph topology, the Node IS the cell. Return the node. */
   Py_INCREF(self->head_node);
   return self->head_node;
 }
 
 static PyObject* TM·Gr·w(TM·Gr·Head* self, PyObject* val){
-  /* Write payload to 'val' attribute of the node */
   if (PyObject_SetAttrString(self->head_node, "val", val) < 0) return NULL;
   Py_RETURN_NONE;
 }
 
 static PyObject* TM·Gr·qR(TM·Gr·Head* self){ 
-  /* Is Rightmost? Check if .right is None/Missing */
   PyObject* right = PyObject_GetAttrString(self->head_node, "right");
   if (!right || right == Py_None) {
       Py_XDECREF(right);
@@ -115,7 +101,6 @@ static PyObject* TM·Gr·qR(TM·Gr·Head* self){
 }
 
 static PyObject* TM·Gr·LqR(TM·Gr·Head* self){ 
-  /* Is Leftmost? Check if .left is None/Missing */
   PyObject* left = PyObject_GetAttrString(self->head_node, "left");
   if (!left || left == Py_None) {
       Py_XDECREF(left);
@@ -126,9 +111,32 @@ static PyObject* TM·Gr·LqR(TM·Gr·Head* self){
 }
 
 static PyObject* TM·Gr·LsR(TM·Gr·Head* self){ 
-  /* Cue to Leftmost */
   Py_DECREF(self->head_node);
   self->head_node = self->leftmost_node;
   Py_INCREF(self->head_node);
   Py_RETURN_NONE; 
 }
+
+/* --- METHOD TABLES --- */
+
+static PyMethodDef Table·Gr·CR·ND[] = {
+  {"s", (PyCFunction)TM·Gr·s, METH_NOARGS, ""},
+  {"e", (PyCFunction)TM·Gr·e, METH_NOARGS, ""},
+  {"r", (PyCFunction)TM·Gr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Gr·w, METH_O,      ""},
+  {"qR",(PyCFunction)TM·Gr·qR,METH_NOARGS, ""},
+  {"LsR",(PyCFunction)TM·Gr·LsR,METH_NOARGS,""},
+  {NULL}
+};
+
+static PyMethodDef Table·Gr·CLR·ND[] = {
+  {"s", (PyCFunction)TM·Gr·s, METH_NOARGS, ""},
+  {"e", (PyCFunction)TM·Gr·e, METH_NOARGS, ""},
+  {"Ls",(PyCFunction)TM·Gr·Ls,METH_NOARGS, ""},
+  {"r", (PyCFunction)TM·Gr·r, METH_NOARGS, ""},
+  {"w", (PyCFunction)TM·Gr·w, METH_O,      ""},
+  {"qR",(PyCFunction)TM·Gr·qR,METH_NOARGS, ""},
+  {"LqR",(PyCFunction)TM·Gr·LqR,METH_NOARGS, ""},
+  {"LsR",(PyCFunction)TM·Gr·LsR,METH_NOARGS,""},
+  {NULL}
+};
index 65e0c29..c782b7d 100644 (file)
@@ -3,18 +3,13 @@
   Topology: Infinite Line
 */
 
-/* ALLOW CDOT IN IDENTIFIERS */
-#define · _ 
-
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 #include "structmember.h"
 
-/* --- 1. HEAD STRUCT --- */
-
 typedef struct {
   PyObject_HEAD
-  unsigned long long state; /* Variable */
+  unsigned long long state; 
 } TM·Nat·Head;
 
 static int TM·Nat·init(TM·Nat·Head* self, PyObject* args, PyObject* kwds){
@@ -26,8 +21,6 @@ static void TM·Nat·dealloc(TM·Nat·Head* self){
   Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
-/* --- 2. PRIMITIVES --- */
-
 static PyObject* TM·Nat·s(TM·Nat·Head* self){ 
   self->state++; 
   Py_RETURN_NONE; 
@@ -60,7 +53,6 @@ static PyObject* TM·Nat·w(TM·Nat·Head* self, PyObject* val){
 }
 
 static PyObject* TM·Nat·qR(TM·Nat·Head* self){ 
-  /* Infinite tape, never at rightmost end */
   Py_RETURN_FALSE; 
 }
 
@@ -80,8 +72,6 @@ static PyObject* TM·Nat·LqnR(TM·Nat·Head* self){
   return PyLong_FromUnsignedLongLong(self->state);
 }
 
-/* --- 3. METHOD TABLE --- */
-
 static PyMethodDef TM·Nat·methods[] = {
   {"s", (PyCFunction)TM·Nat·s, METH_NOARGS, ""},
   {"sn",(PyCFunction)TM·Nat·sn,METH_VARARGS,""},
@@ -96,8 +86,6 @@ static PyMethodDef TM·Nat·methods[] = {
   {NULL}
 };
 
-/* --- 4. TYPE DEFINITION --- */
-
 static PyTypeObject TMA_NaturalNumber·Type = {
   PyVarObject_HEAD_INIT(NULL, 0)
   .tp_name = "TM_module.TMA_NaturalNumber",
index c25dff4..8d56b74 100644 (file)
@@ -4,10 +4,6 @@
   Aggregates implementations for Array, Graph, and Abstract topologies.
 */
 
-/* ALLOW CDOT IN IDENTIFIERS */
-#define · _ 
-
-/* Shared Includes */
 #include <Python.h>
 
 /* Include Implementations */
 #include "TM_GR.c"
 #include "TM_NaturalNumber.c"
 
-/* --- METHOD TABLES (Graph) --- */
-
-/* Note: Graph machines implemented here are ND (Non-Destructive) for structure.
-   They allow 'w' (write value), but not 'd' (delete node). */
-
-static PyMethodDef Table·Gr·CR·ND[] = {
-  {"s", (PyCFunction)TM·Gr·s, METH_NOARGS, ""},
-  {"e", (PyCFunction)TM·Gr·e, METH_NOARGS, ""},
-  {"r", (PyCFunction)TM·Gr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Gr·w, METH_O,      ""},
-  {"qR",(PyCFunction)TM·Gr·qR,METH_NOARGS, ""},
-  {"LsR",(PyCFunction)TM·Gr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
-static PyMethodDef Table·Gr·CLR·ND[] = {
-  {"s", (PyCFunction)TM·Gr·s, METH_NOARGS, ""},
-  {"e", (PyCFunction)TM·Gr·e, METH_NOARGS, ""},
-  {"Ls",(PyCFunction)TM·Gr·Ls,METH_NOARGS, ""},
-  {"r", (PyCFunction)TM·Gr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Gr·w, METH_O,      ""},
-  {"qR",(PyCFunction)TM·Gr·qR,METH_NOARGS, ""},
-  {"LqR",(PyCFunction)TM·Gr·LqR,METH_NOARGS, ""},
-  {"LsR",(PyCFunction)TM·Gr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
-/* --- METHOD TABLES (Array) --- */
-
-/* 1. NON-DESTRUCTIVE (ND) */
-static PyMethodDef Table·Arr·CR·ND[] = {
-  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
-  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
-  {"e", (PyCFunction)TM·Arr·e, METH_NOARGS, ""},
-  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
-  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
-  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
-  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
-  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
-static PyMethodDef Table·Arr·CLR·ND[] = {
-  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
-  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
-  {"e", (PyCFunction)TM·Arr·e, METH_NOARGS, ""},
-  {"Ls",(PyCFunction)TM·Arr·Ls,METH_NOARGS, ""},
-  {"Lsn",(PyCFunction)TM·Arr·Lsn,METH_VARARGS,""},
-  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
-  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
-  {"LqR",(PyCFunction)TM·Arr·LqR,METH_NOARGS, ""},
-  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
-  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
-  {"sR",(PyCFunction)TM·Arr·sR,METH_NOARGS, ""},
-  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
-/* 2. DESTRUCTIVE (SO) - No Entangle 'e' */
-static PyMethodDef Table·Arr·CR·SO[] = {
-  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
-  {"sn",(PyCFunction)TM·Arr·sn,METH_VARARGS,""},
-  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
-  {"dR",(PyCFunction)TM·Arr·dR,METH_NOARGS, ""},
-  {"esd",(PyCFunction)TM·Arr·esd,METH_NOARGS,""},
-  {"esa",(PyCFunction)TM·Arr·esa,METH_O,     ""},
-  {"aR",(PyCFunction)TM·Arr·aR,METH_O,       ""},
-  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
-  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
-  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
-  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
-static PyMethodDef Table·Arr·CLR·SO[] = {
-  {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""},
-  {"Ls",(PyCFunction)TM·Arr·Ls,METH_NOARGS, ""},
-  {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""},
-  {"w", (PyCFunction)TM·Arr·w, METH_O,      ""},
-  {"dR",(PyCFunction)TM·Arr·dR,METH_NOARGS, ""},
-  {"LdR",(PyCFunction)TM·Arr·LdR,METH_NOARGS,""},
-  {"esd",(PyCFunction)TM·Arr·esd,METH_NOARGS,""},
-  {"eLsd",(PyCFunction)TM·Arr·eLsd,METH_NOARGS,""},
-  {"esa",(PyCFunction)TM·Arr·esa,METH_O,     ""},
-  {"eLsa",(PyCFunction)TM·Arr·eLsa,METH_O,   ""},
-  {"aR",(PyCFunction)TM·Arr·aR,METH_O,       ""},
-  {"LaR",(PyCFunction)TM·Arr·LaR,METH_O,     ""},
-  {"qR",(PyCFunction)TM·Arr·qR,METH_NOARGS, ""},
-  {"LqR",(PyCFunction)TM·Arr·LqR,METH_NOARGS, ""},
-  {"qnR",(PyCFunction)TM·Arr·qnR,METH_NOARGS,""},
-  {"LqnR",(PyCFunction)TM·Arr·LqnR,METH_NOARGS,""},
-  {"sR",(PyCFunction)TM·Arr·sR,METH_NOARGS, ""},
-  {"LsR",(PyCFunction)TM·Arr·LsR,METH_NOARGS,""},
-  {NULL}
-};
-
 /* --- TYPE MACROS --- */
 
 #define DEFINE_ARRAY_TYPE(NAME, METHODS) \
@@ -171,8 +68,8 @@ DEFINE_ARRAY_TYPE(TM_UTF8_CR_ND,  Table·Arr·CR·ND)
 DEFINE_ARRAY_TYPE(TM_UTF8_CR_SO,  Table·Arr·CR·SO)
 DEFINE_ARRAY_TYPE(TM_UTF8_CR_EA,  Table·Arr·CR·ND)
 DEFINE_ARRAY_TYPE(TM_UTF8_CLR_ND, Table·Arr·CLR·ND)
-DEFINE_ARRAY_TYPE(TM_UTF8_CLR_SO, Table·Arr_CLR_SO)
-DEFINE_ARRAY_TYPE(TM_UTF8_CLR_EA, Table·Arr_CLR_ND)
+DEFINE_ARRAY_TYPE(TM_UTF8_CLR_SO, Table·Arr·CLR·SO)
+DEFINE_ARRAY_TYPE(TM_UTF8_CLR_EA, Table·Arr·CLR·ND)
 
 /* 2. Graph Types */
 DEFINE_GR_TYPE(TM_Gr_CR_ND,  Table·Gr·CR·ND)
@@ -181,14 +78,14 @@ DEFINE_GR_TYPE(TM_Gr_CR_EA,  Table·Gr·CR·ND)
 
 DEFINE_GR_TYPE(TM_Gr_CLR_ND, Table·Gr·CLR·ND)
 DEFINE_GR_TYPE(TM_Gr_CLR_SO, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_Gr_CLR_EA, Table·Gr_CLR_ND)
+DEFINE_GR_TYPE(TM_Gr_CLR_EA, Table·Gr·CLR·ND)
 
 DEFINE_GR_TYPE(TM_Glr_CR_ND,  Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Glr_CR_SO,  Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Glr_CR_EA,  Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Glr_CLR_ND, Table·Gr·CLR·ND)
 DEFINE_GR_TYPE(TM_Glr_CLR_SO, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_Glr_CLR_EA, Table·Gr_CLR_ND)
+DEFINE_GR_TYPE(TM_Glr_CLR_EA, Table·Gr·CLR·ND)
 
 /* ... Maps and Sets ... */
 DEFINE_GR_TYPE(TM_Set_CR_ND, Table·Gr·CR·ND)
@@ -196,28 +93,28 @@ DEFINE_GR_TYPE(TM_Set_CR_SO, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Set_CR_EA, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Set_CLR_ND, Table·Gr·CLR·ND)
 DEFINE_GR_TYPE(TM_Set_CLR_SO, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_Set_CLR_EA, Table·Gr·CLR_ND)
+DEFINE_GR_TYPE(TM_Set_CLR_EA, Table·Gr·CLR·ND)
 
 DEFINE_GR_TYPE(TM_Map_CR_ND, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Map_CR_SO, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Map_CR_EA, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_Map_CLR_ND, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_Map_CLR_SO, Table·Gr·CLR_ND)
-DEFINE_GR_TYPE(TM_Map_CLR_EA, Table·Gr_CLR_ND)
+DEFINE_GR_TYPE(TM_Map_CLR_SO, Table·Gr·CLR·ND)
+DEFINE_GR_TYPE(TM_Map_CLR_EA, Table·Gr·CLR·ND)
 
 DEFINE_GR_TYPE(TM_MapK_CR_ND, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_MapK_CR_SO, Table·Gr·CR·ND)
-DEFINE_GR_TYPE(TM_MapK_CR_EA, Table·Gr_CR_ND)
+DEFINE_GR_TYPE(TM_MapK_CR_EA, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_MapK_CLR_ND, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_MapK_CLR_SO, Table·Gr·CLR_ND)
-DEFINE_GR_TYPE(TM_MapK_CLR_EA, Table·Gr_CLR_ND)
+DEFINE_GR_TYPE(TM_MapK_CLR_SO, Table·Gr·CLR·ND)
+DEFINE_GR_TYPE(TM_MapK_CLR_EA, Table·Gr·CLR·ND)
 
 DEFINE_GR_TYPE(TM_MapV_CR_ND, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_MapV_CR_SO, Table·Gr·CR·ND)
-DEFINE_GR_TYPE(TM_MapV_CR_EA, Table·Gr_CR_ND)
+DEFINE_GR_TYPE(TM_MapV_CR_EA, Table·Gr·CR·ND)
 DEFINE_GR_TYPE(TM_MapV_CLR_ND, Table·Gr·CLR·ND)
-DEFINE_GR_TYPE(TM_MapV_CLR_SO, Table·Gr_CLR_ND)
-DEFINE_GR_TYPE(TM_MapV_CLR_EA, Table_Gr_CLR_ND)
+DEFINE_GR_TYPE(TM_MapV_CLR_SO, Table·Gr·CLR·ND)
+DEFINE_GR_TYPE(TM_MapV_CLR_EA, Table·Gr·CLR·ND)
 
 
 /* --- MODULE INIT --- */
index 0a4bc2f..ae8ada3 100644 (file)
Binary files a/developer/authored/build/temp.linux-x86_64-cpython-311/TM_module.o and b/developer/authored/build/temp.linux-x86_64-cpython-311/TM_module.o differ
diff --git a/document/Symbol_Specification.html b/document/Symbol_Specification.html
new file mode 100644 (file)
index 0000000..d9c0526
--- /dev/null
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <title>Symbol Specification</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-title 
+        author="Thomas Walker Lynch" 
+        date="2026-02-12" 
+        title="Symbol Specification">
+      </RT-title>
+
+      <h1> <RT-code>SymbolSpace</RT-code> </h1>
+      <p>
+        <RT-code>SymbolSpace</RT-code> has:
+        <ol>
+          <li>Symbol subclass</li>
+          <li>Factory subclass</li>
+          <li>Context subclass</li>
+          <li>a <RT-code>null<RT-code> symbol</li>
+        </ol>
+      </p>
+
+      <h2>Symbol</h2>
+
+      <p>
+        A Symbol instance wraps an integer known as its <RT-term>identity</RT-term>.
+      </p>
+
+      <p>
+        Symbols are made by the Factory `make` method.
+      </p>
+
+      <p>
+        When a Symbol instance is garbage collected, it contacts the Symbol.Factory, so that its <RT-term>identity</RT-term> can be added to the Symbol.Factory's free list.
+      <p>
+
+      <h2><RT-code>Factory</RT-code></h2>
+
+      <p>The <RT-code>Factory</RT-code> has:
+        <ol>
+          <li><RT-code>counter</RT-code></li>
+          <li><RT-code>free_list</RT-code></li>
+        </ol>
+      </p>
+
+      <p>
+        Factory method calls are transactional.
+      </p>
+
+      <p>
+        The <RT-code>counter</RT-code> value at any time between transactions is the highest count symbol identity that has been issued.
+      </p>
+
+      <p>
+        The lowest counter value is zero. At time of <RT-code>Factory</RT-code> initialization the zero value is given as the identity for the <RT-code>SymbolSpace.null</RT-code> symbol. This initialization strategy assures the counter value remains the highest issued symbol identity even immediately after initialization.
+      </p>
+
+      <p>
+        To add to the free list, first check the current <RT-code>counter</RT-code> value,   If the count matches the identity of the newly freed Symbol instance,  decremented the count.  If the Counter's post decrement value is on the free list,  it is removed from the free list and the count is decremented again, this repeats until the new decement count is not found on the free list.  It is an error to attempt to free the null symbol, that of 0.
+      </p>
+
+      <h2>Context</h2>
+      <p>
+        Context is a map keyed on a symbol list.  Such a symbol list is called a 'symbol context'.  Each key maps to a <RT-code>Factory</RT-code>.
+      </p>
+
+      <p>
+        A program creates a context by calling <RT-code>make</RT-code> while giving it a <RT-code>Symbol</RT-code> instance list. That list, in the order the symbols are given, is said to be a <RT-term>symbol context</RT-term>. The <RT-code>make</RT-code> routine returns a <RT-code>Factory</RT-code>. Thus the returned <RT-code>Factory</RT-code> instance is a <RT-term>context specific factory</RT-term>.
+        </p>
+
+      <p>The program should never give <RT-code>make</RT-code> a <RT-term>symbol context</RT-term> that is already a key in the table. <RT-code>make</RT-code> can be guarded using <RT-code>read</RT-code>
+      </p>
+
+      <p>The <RT-code>read</RT-code> function is given a symbol context and returns the       corresponding <RT-term>context specific factory</RT-term>, or none, if there isn't one.
+      </p>
+
+      <p>A symbol that is part of <RT-term>symbol context</RT-term> will never be garbage
+      collected.  Hence, a <RT-term>symbol context</RT-term> remains in the table even when it is not being used.
+      </p>
+
+      <p>A <RT-term>symbol context</RT-term> is deleted from the table by calling the <RT-code>delete</RT-code> interface function and giving it the <RT-term>symbol context</RT-term> to be deleted.</p>
+
+
+      <h1>Usage</h1>
+
+      <p>A programmer first creates a <RT-code>SymbolSpace</RT-code>, then in normal use, the programmer will create a top level symbol to serve as a namespace.  The programmer will then use the resulting <RT-term>context specific factory</RT-term> to create symbols within that namespace
+      </p>
+
+  <script src="style/style_orchestrator.js"></script>
+  <script>
+   window.StyleRT.style_orchestrator();
+  </script>
+
+</body>
+</html>