TM_module.c
CPython Extension: Tape Machine Factory
Implements:
- - TM_SR_ND (Base: Step Right, Non-Destructive)
- - TM_SR_ND_AR (Feature: Append Right)
+ - TM·Array_SR_ND (Pointer-based, Solitary, Step Right, Non-Destructive)
+
+ Style Note:
+ - RT Naming Convention: TM·Class·Method
+ - Uses UTF-8 center dot '·' for namespace separation.
*/
#define PY_SSIZE_T_CLEAN
#include <stddef.h>
/* ========================================================= */
-/* 1. DATA LAYOUT (Shared) */
+/* 1. DATA LAYOUT */
/* ========================================================= */
typedef struct {
PyObject_HEAD
- 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 */
+ PyObject* tape_obj; /* The Container (List) */
+ PyObject** head_ptr; /* Current Cell */
+ PyObject** start_ptr; /* Leftmost Cell (Cache) */
+ PyObject** end_ptr; /* Rightmost Cell + 1 (Sentinel) */
} FastTM;
static void FastTM_dealloc(FastTM* self){
- 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);
}
-/* Helper: Register Entanglement */
-static int register_entanglement(FastTM* self, PyObject* existing_peer_list){
- PyObject* weak_ref = NULL;
- if( existing_peer_list ){
- self->peer_list = existing_peer_list;
- Py_INCREF(self->peer_list);
- } else {
- self->peer_list = PyList_New(0);
- if( !self->peer_list ) return -1;
- }
- weak_ref = PyWeakref_NewRef((PyObject*)self, NULL);
- if( !weak_ref ) return -1;
- if( PyList_Append(self->peer_list, weak_ref) < 0 ){
- Py_DECREF(weak_ref);
- return -1;
- }
- Py_DECREF(weak_ref);
+/* Helper: Refresh Pointers (Used on Init) */
+static int refresh_pointers(FastTM* self){
+ if (!PyList_Check(self->tape_obj)) return -1;
+
+ Py_ssize_t len = PyList_GET_SIZE(self->tape_obj);
+ PyObject** items = ((PyListObject*)self->tape_obj)->ob_item;
+
+ self->start_ptr = items;
+ self->end_ptr = items + len;
+ self->head_ptr = items; /* Initialize to start */
+
return 0;
}
/* ========================================================= */
-/* 2. THE MIXIN LIBRARY (Static C Functions) */
+/* 2. TM·Array_SR_ND Methods (Static Implementation) */
/* ========================================================= */
-/* --- Navigation --- */
-static PyObject* mixin_s(FastTM* self){
- self->head++;
+/* TM·Array_SR_ND·s: Step Right */
+static PyObject* TM·Array_SR_ND·s(FastTM* self){
+ self->head_ptr++;
Py_RETURN_NONE;
}
-static PyObject* mixin_sn(FastTM* self, PyObject* arg_tuple){
+/* TM·Array_SR_ND·sn: Step N */
+static PyObject* TM·Array_SR_ND·sn(FastTM* self, PyObject* arg_tuple){
Py_ssize_t n_val;
if( !PyArg_ParseTuple(arg_tuple, "n", &n_val) ) return NULL;
+
if (n_val < 0) {
- PyErr_SetString(PyExc_ValueError, "Machine supports positive steps only.");
+ PyErr_SetString(PyExc_ValueError, "Step Right machine supports positive steps only.");
return NULL;
}
- self->head += n_val;
+ self->head_ptr += n_val;
Py_RETURN_NONE;
}
-/* --- I/O --- */
-static PyObject* mixin_r(FastTM* self){
- PyObject* item_obj = PyList_GetItem(self->tape_obj, self->head);
- if( !item_obj ) return NULL;
- Py_INCREF(item_obj);
- return item_obj;
-}
-
-static PyObject* mixin_rn(FastTM* self, PyObject* arg_tuple){
- Py_ssize_t n_val;
- if( !PyArg_ParseTuple(arg_tuple, "n", &n_val) ) return NULL;
- return PyList_GetSlice(self->tape_obj, self->head, self->head + n_val);
-}
-
-static PyObject* mixin_w(FastTM* self, PyObject* val_obj){
- Py_INCREF(val_obj);
- if( PyList_SetItem(self->tape_obj, self->head, val_obj) < 0 ) return NULL;
+/* TM·Array_SR_ND·LsR: Rewind */
+static PyObject* TM·Array_SR_ND·LsR(FastTM* self){
+ self->head_ptr = self->start_ptr;
Py_RETURN_NONE;
}
-static PyObject* mixin_wn(FastTM* self, PyObject* arg_tuple){
- PyObject* val_list;
- if( !PyArg_ParseTuple(arg_tuple, "O", &val_list) ) return NULL;
- Py_ssize_t len_val = PySequence_Size(val_list);
- if( PyList_SetSlice(self->tape_obj, self->head, self->head + len_val, val_list) < 0 ) return NULL;
- Py_RETURN_NONE;
+/* TM·Array_SR_ND·r: Read */
+static PyObject* TM·Array_SR_ND·r(FastTM* self){
+ PyObject* item = *(self->head_ptr);
+ Py_INCREF(item);
+ return item;
}
-/* --- Features --- */
-
-/* Feature: aR (Append Right) */
-static PyObject* mixin_aR(FastTM* self, PyObject* val_obj){
- /* aR typically appends to the END of the tape,
- regardless of head position, in non-destructive contexts?
- Or at the head?
- Standard definition: Append to end of container. */
- if( PyList_Append(self->tape_obj, val_obj) < 0 ) return NULL;
+/* TM·Array_SR_ND·w: Write */
+static PyObject* TM·Array_SR_ND·w(FastTM* self, PyObject* val_obj){
+ PyObject* old_val = *(self->head_ptr);
+ Py_INCREF(val_obj);
+ *(self->head_ptr) = val_obj;
+ Py_DECREF(old_val);
Py_RETURN_NONE;
}
-/* --- Meta --- */
-static PyObject* mixin_e(FastTM* self){
- /* Factory-aware Entanglement:
- We call the type's constructor. Since Py_TYPE(self) is the specific
- machine type (e.g. TM_SR_ND_AR), the clone will inherit the same features. */
- PyObject* arg_tuple = PyTuple_Pack(1, self);
- PyObject* new_obj = PyObject_CallObject((PyObject*)Py_TYPE(self), arg_tuple);
- Py_DECREF(arg_tuple);
- return new_obj;
-}
-
-static PyObject* mixin_address(FastTM* self){
- return PyLong_FromSsize_t(self->head);
-}
-
-static PyObject* mixin_len(FastTM* self){
- return PyLong_FromSsize_t(PyList_Size(self->tape_obj));
+/* TM·Array_SR_ND·qR: Query Rightmost */
+static PyObject* TM·Array_SR_ND·qR(FastTM* self){
+ if( self->head_ptr >= (self->end_ptr - 1) ) Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
}
-static PyObject* mixin_rightmost(FastTM* self){
- Py_ssize_t len = PyList_Size(self->tape_obj);
- if( self->head >= len - 1 ) Py_RETURN_TRUE;
- Py_RETURN_FALSE;
+/* TM·Array_SR_ND·address: Get Index */
+static PyObject* TM·Array_SR_ND·address(FastTM* self){
+ Py_ssize_t idx = self->head_ptr - self->start_ptr;
+ return PyLong_FromSsize_t(idx);
}
/* ========================================================= */
-/* 3. TYPE DEFINITIONS */
+/* 3. TM·Array_SR_ND Init */
/* ========================================================= */
-/* Generic Init (Used by all types) */
-static int GenericTM_init(FastTM* self, PyObject* args, PyObject* kwds){
+static int TM·Array_SR_ND·init(FastTM* self, PyObject* args, PyObject* kwds){
PyObject* input_obj = NULL;
- PyObject* features_obj = NULL; /* Ignored here, consumed by Factory */
+ PyObject* features_obj = NULL;
if( !PyArg_ParseTuple(args, "O|O", &input_obj, &features_obj) ) return -1;
- if( PyObject_TypeCheck(input_obj, Py_TYPE(self)) ){
- /* Clone/Entangle */
- FastTM* source_tm = (FastTM*)input_obj;
- self->tape_obj = source_tm->tape_obj;
- Py_INCREF(self->tape_obj);
- self->head = source_tm->head;
- if( register_entanglement(self, source_tm->peer_list) < 0 ) return -1;
- } else {
- /* New */
- if( PyList_Check(input_obj) ){
- self->tape_obj = input_obj;
- Py_INCREF(self->tape_obj);
- } else {
- self->tape_obj = PySequence_List(input_obj);
- if( !self->tape_obj ) return -1;
- }
- if (PyList_Size(self->tape_obj) == 0) {
- PyErr_SetString(PyExc_ValueError, "First Order TM cannot be empty.");
- return -1;
- }
- self->head = 0;
- if( register_entanglement(self, NULL) < 0 ) return -1;
+ if( !PyList_Check(input_obj) ){
+ PyErr_SetString(PyExc_TypeError, "Array TM requires a list data object.");
+ return -1;
+ }
+
+ if (PyList_Size(input_obj) == 0) {
+ PyErr_SetString(PyExc_ValueError, "First Order TM cannot be empty.");
+ return -1;
}
+
+ self->tape_obj = input_obj;
+ Py_INCREF(self->tape_obj);
+
+ refresh_pointers(self);
+
return 0;
}
-/* --- Type 1: TM_SR_ND (Base) --- */
-static PyMethodDef TM_SR_ND_methods[] = {
- {"r", (PyCFunction)mixin_r, METH_NOARGS, ""},
- {"rn", (PyCFunction)mixin_rn, METH_VARARGS, ""},
- {"w", (PyCFunction)mixin_w, METH_O, ""},
- {"wn", (PyCFunction)mixin_wn, METH_VARARGS, ""},
- {"s", (PyCFunction)mixin_s, METH_NOARGS, ""},
- {"sn", (PyCFunction)mixin_sn, METH_VARARGS, ""},
- {"e", (PyCFunction)mixin_e, METH_NOARGS, ""},
- {"address", (PyCFunction)mixin_address, METH_NOARGS, ""},
- {"len", (PyCFunction)mixin_len, METH_NOARGS, ""},
- {"rightmost", (PyCFunction)mixin_rightmost, METH_NOARGS, ""},
- {NULL}
-};
-
-static PyTypeObject TM_SR_ND_Type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "TM_module.TM_SR_ND",
- .tp_doc = "Step Right, Non-Destructive",
- .tp_basicsize = sizeof(FastTM),
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
- .tp_new = PyType_GenericNew,
- .tp_init = (initproc)GenericTM_init,
- .tp_dealloc = (destructor)FastTM_dealloc,
- .tp_methods = TM_SR_ND_methods,
- .tp_weaklistoffset = offsetof(FastTM, weakreflist)
-};
+/* ========================================================= */
+/* 4. TYPE DEFINITION */
+/* ========================================================= */
-/* --- Type 2: TM_SR_ND_AR (Base + aR) --- */
-static PyMethodDef TM_SR_ND_AR_methods[] = {
- /* Copy Base Methods */
- {"r", (PyCFunction)mixin_r, METH_NOARGS, ""},
- {"rn", (PyCFunction)mixin_rn, METH_VARARGS, ""},
- {"w", (PyCFunction)mixin_w, METH_O, ""},
- {"wn", (PyCFunction)mixin_wn, METH_VARARGS, ""},
- {"s", (PyCFunction)mixin_s, METH_NOARGS, ""},
- {"sn", (PyCFunction)mixin_sn, METH_VARARGS, ""},
- {"e", (PyCFunction)mixin_e, METH_NOARGS, ""},
- {"address", (PyCFunction)mixin_address, METH_NOARGS, ""},
- {"len", (PyCFunction)mixin_len, METH_NOARGS, ""},
- {"rightmost", (PyCFunction)mixin_rightmost, METH_NOARGS, ""},
- /* Add Feature */
- {"aR", (PyCFunction)mixin_aR, METH_O, "Append Right"},
+static PyMethodDef TM·Array_SR_ND·methods[] = {
+ {"s", (PyCFunction)TM·Array_SR_ND·s, METH_NOARGS, "Step Right"},
+ {"sn", (PyCFunction)TM·Array_SR_ND·sn, METH_VARARGS, "Step N"},
+ {"r", (PyCFunction)TM·Array_SR_ND·r, METH_NOARGS, "Read"},
+ {"w", (PyCFunction)TM·Array_SR_ND·w, METH_O, "Write"},
+ {"qR", (PyCFunction)TM·Array_SR_ND·qR, METH_NOARGS, "Query Rightmost"},
+ {"LsR", (PyCFunction)TM·Array_SR_ND·LsR, METH_NOARGS, "Rewind"},
+ {"address", (PyCFunction)TM·Array_SR_ND·address, METH_NOARGS, "Get Index"},
{NULL}
};
-static PyTypeObject TM_SR_ND_AR_Type = {
+static PyTypeObject TM·Array_SR_ND·Type = {
PyVarObject_HEAD_INIT(NULL, 0)
- .tp_name = "TM_module.TM_SR_ND_AR",
- .tp_doc = "Step Right, Non-Destructive, Append Right",
+ .tp_name = "TM_module.TM_Array_SR_ND",
+ .tp_doc = "Array TM: Pointer-based, Solitary, SR, ND",
.tp_basicsize = sizeof(FastTM),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
.tp_new = PyType_GenericNew,
- .tp_init = (initproc)GenericTM_init,
+ .tp_init = (initproc)TM·Array_SR_ND·init,
.tp_dealloc = (destructor)FastTM_dealloc,
- .tp_methods = TM_SR_ND_AR_methods,
- .tp_weaklistoffset = offsetof(FastTM, weakreflist)
+ .tp_methods = TM·Array_SR_ND·methods,
};
/* ========================================================= */
-/* 4. THE FACTORY */
+/* 5. FACTORY */
/* ========================================================= */
-static PyObject* FastTM_Factory(PyObject* self, PyObject* args, PyObject* kwds){
+static PyObject* TM·Factory(PyObject* self, PyObject* args, PyObject* kwds){
PyObject* input_obj = NULL;
PyObject* features_obj = NULL;
if( !PyArg_ParseTuple(args, "O|O", &input_obj, &features_obj) ) return NULL;
- /* Check for "aR" in features */
- int has_aR = 0;
+ /* Check Features (Reject incompatible ones) */
if( features_obj && PyList_Check(features_obj) ){
Py_ssize_t size = PyList_Size(features_obj);
for( Py_ssize_t i=0; i<size; i++ ){
- PyObject* item = PyList_GetItem(features_obj, i); /* Borrowed */
+ PyObject* item = PyList_GetItem(features_obj, i);
if( PyUnicode_Check(item) ){
const char* s = PyUnicode_AsUTF8(item);
- if( s && strcmp(s, "aR") == 0 ) has_aR = 1;
+ if( s && strcmp(s, "aR") == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "Feature 'aR' is incompatible with Array TMs.");
+ return NULL;
+ }
}
}
}
- /* Select Type */
- PyTypeObject* target_type = has_aR ? &TM_SR_ND_AR_Type : &TM_SR_ND_Type;
+ /* Dispatch to TM·Array_SR_ND if input is List */
+ if (!PyList_Check(input_obj)) {
+ PyErr_SetString(PyExc_TypeError, "TM constructor requires a List container.");
+ return NULL;
+ }
- /* Create Instance */
PyObject* arg_tuple = PyTuple_Pack(2, input_obj, features_obj ? features_obj : Py_None);
- PyObject* obj = PyObject_CallObject((PyObject*)target_type, arg_tuple);
+ PyObject* obj = PyObject_CallObject((PyObject*)&TM·Array_SR_ND·Type, arg_tuple);
Py_DECREF(arg_tuple);
return obj;
}
-/* ========================================================= */
-/* 5. MODULE INIT */
-/* ========================================================= */
-
static PyMethodDef module_methods[] = {
- {"FastTM", (PyCFunction)FastTM_Factory, METH_VARARGS | METH_KEYWORDS, "TM Factory"},
+ {"TM", (PyCFunction)TM·Factory, METH_VARARGS | METH_KEYWORDS, "TM Factory"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC PyInit_TM_module(void){
PyObject* m_obj;
-
- if( PyType_Ready(&TM_SR_ND_Type) < 0 ) return NULL;
- if( PyType_Ready(&TM_SR_ND_AR_Type) < 0 ) return NULL;
+ if( PyType_Ready(&TM·Array_SR_ND·Type) < 0 ) return NULL;
m_obj = PyModule_Create(&TM_module);
if( !m_obj ) return NULL;
- Py_INCREF(&TM_SR_ND_Type);
- Py_INCREF(&TM_SR_ND_AR_Type);
-
- /* We export the Types if user wants to inspect them,
- but primarily they use the FastTM factory. */
- PyModule_AddObject(m_obj, "TM_SR_ND", (PyObject*)&TM_SR_ND_Type);
- PyModule_AddObject(m_obj, "TM_SR_ND_AR", (PyObject*)&TM_SR_ND_AR_Type);
-
+ Py_INCREF(&TM·Array_SR_ND·Type);
+ PyModule_AddObject(m_obj, "TM_Array_SR_ND", (PyObject*)&TM·Array_SR_ND·Type);
return m_obj;
}
--- /dev/null
+#!/usr/bin/env python3
+import sys
+from enum import Enum, auto
+
+try:
+ import TM_module
+except ImportError:
+ print("Error: Import failed. Run 'python3 setup.py build_ext --inplace'")
+ sys.exit(1)
+
+# ==========================================
+# 1. Enums & Features
+# ==========================================
+
+class Features:
+ APPEND_RIGHT = "aR"
+
+class Status(Enum):
+ ABANDONED = auto()
+ ACTIVE = auto()
+ EMPTY = auto()
+ PARKED = auto()
+
+class Topology(Enum):
+ CIRCLE = auto()
+ LINEAR_RIGHT = auto()
+ LINEAR_OPEN = auto()
+ NULL = auto()
+ SEGMENT = auto()
+
+# The Factory
+TM = TM_module.FastTM
+
+# ==========================================
+# 2. TM Workspace Functions
+# ==========================================
+class TM_workspace:
+ @staticmethod
+ def head_on_same_cell(tm1, tm2):
+ """
+ Predicate: Returns true if entangled machines are on the same cell.
+ Requires: tm1 and tm2 share the same tape.
+ """
+ if tm1.empty() or tm2.empty(): return False
+ # TODO: Verify entanglement identity via C-extension property if needed.
+ return tm1.address() == tm2.address()
+
+ @staticmethod
+ def step_tandem(tm1, tm2):
+ if tm1.empty() or tm2.empty(): return
+ tm1.s()
+ tm2.s()
+
+# ==========================================
+# 3. Status Wrapper (TMS)
+# ==========================================
+
+class TMS:
+ def __init__(self, data_obj, features=None):
+ """
+ TMS Constructor.
+ Args:
+ data_obj: MANDATORY. List or existing TM.
+ """
+ # 1. Wrap Existing (Entangled) TM
+ if hasattr(data_obj, '__class__') and data_obj.__class__.__module__ == 'TM_module':
+ self.tm = data_obj
+ self._stat = Status.ACTIVE
+
+ # 2. Handle Empty List (Demotion to Empty Status)
+ # The C-TM rejects empty lists, so we handle it here.
+ elif isinstance(data_obj, list) and len(data_obj) == 0:
+ self.tm = None
+ self._stat = Status.EMPTY
+
+ # 3. Create New Active TM via Factory
+ else:
+ self.tm = TM(data_obj, features)
+ self._stat = Status.ACTIVE
+
+ # --- Base Methods ---
+ def r(self):
+ if self.empty(): raise RuntimeError("Attempted to read from EMPTY machine.")
+ return self.tm.r()
+
+ def rn(self, n): return self.tm.rn(n)
+ def w(self, v): return self.tm.w(v)
+ def wn(self, v): return self.tm.wn(v)
+
+ def s(self):
+ if self.empty(): raise RuntimeError("Attempted to step EMPTY machine.")
+ return self.tm.s()
+
+ def sn(self, n): return self.tm.sn(n)
+
+ def address(self): return 0 if self.empty() else self.tm.address()
+ def len(self): return 0 if self.empty() else self.tm.len()
+
+ # --- Features ---
+ def aR(self, v):
+ if self.empty():
+ # Promotion: Empty -> Active
+ # We must assume implicit list container for now
+ self.tm = TM([v])
+ self._stat = Status.ACTIVE
+ else:
+ self.tm.aR(v)
+
+ # --- Meta ---
+ def e(self):
+ return TMS(self.tm.e()) if not self.empty() else TMS([])
+
+ def empty(self): return self._stat == Status.EMPTY
+ def rightmost(self): return True if self.empty() else self.tm.rightmost()
+
+# ==========================================
+# 4. Region Machine
+# ==========================================
+
+class RegionMachine:
+ def __init__(self, t_active):
+ """
+ Constructs a Region Machine from a single Active TM.
+ Initializes Left/Right boundaries to the current Active position.
+ """
+ self.t_active = t_active
+ self.t_left = t_active.e() # Left Boundary
+ self.t_right = t_active.e() # Right Boundary
+
+ # --- Bounds Management ---
+ def qL(self):
+ return TM_workspace.head_on_same_cell(self.t_active, self.t_left)
+
+ def qR(self):
+ return TM_workspace.head_on_same_cell(self.t_active, self.t_right)
+
+ def sR(self):
+ # Cue to Right Boundary (Simulated via address copying or step loop)
+ # Since we lack random access 'cue' in SR_ND, we might need 's' loop
+ # or direct address manipulation if supported.
+ # For now, we rely on the implementation matching the head.
+ pass # Todo: Implement cue via delta steps
+
+ # --- Navigation (Guarded) ---
+ def s(self):
+ if self.qR():
+ raise RuntimeError("Region Boundary Violation: Cannot step past Right Bound.")
+ self.t_active.s()
+
+ def r(self):
+ return self.t_active.r()