From 5d7158f09c35413df50ff8fa60d0ed6661ac3390 Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Wed, 11 Feb 2026 09:56:16 +0000 Subject: [PATCH] TM_tutorial.py running, a first array based full TM implementation for Python --- developer/authored/TM.py | 176 +++-- developer/authored/TM_module.c | 409 ++++++----- developer/authored/TM_tutorial.py | 124 ++-- .../temp.linux-x86_64-cpython-311/TM_module.o | Bin 141256 -> 173856 bytes document/TM.html | 253 +++---- document/TM_reference.html | 283 -------- document/TM_sav.html | 681 ------------------ document/TM_user.html | 226 ------ 8 files changed, 525 insertions(+), 1627 deletions(-) delete mode 100644 document/TM_reference.html delete mode 100644 document/TM_sav.html delete mode 100644 document/TM_user.html diff --git a/developer/authored/TM.py b/developer/authored/TM.py index 24a262e..693b77b 100755 --- a/developer/authored/TM.py +++ b/developer/authored/TM.py @@ -1,56 +1,120 @@ -#!/usr/bin/env python3 -import sys - -try: - import TM_module -except ImportError: - print("Error: Import failed. Run 'python3 setup.py build_ext --inplace'") - sys.exit(1) - -# ========================================== -# TM Command Language (Explicit Types) -# ========================================== - -# Import all C-defined types into this namespace -_this_module = sys.modules[__name__] -for name in dir(TM_module): - if name.startswith("TM_") or name.startswith("TMA_"): - setattr(_this_module, name, getattr(TM_module, name)) - -# ========================================== -# Defaults (Aliasing) -# ========================================== - -# Pattern: TM_[Container]_[Direction]_[Entanglement] -# Default Container: Arr -# Default Entanglement: ND -# Default Direction: SR - -# --- Global Default --- -TM = TM_module.TM_Arr_SR_ND - -# --- Container Defaults (Dir=SR, Ent=ND) --- -TM_Arr = TM_module.TM_Arr_SR_ND -TM_ArrV = TM_module.TM_ArrV_SR_ND -TM_Gr = TM_module.TM_Gr_SR_ND -TM_Glr = TM_module.TM_Glr_SR_ND -TM_Set = TM_module.TM_Set_SR_ND -TM_Map = TM_module.TM_Map_SR_ND -TM_MapK = TM_module.TM_MapK_SR_ND -TM_MapV = TM_module.TM_MapV_SR_ND -TM_ASCII= TM_module.TM_ASCII_SR_ND -TM_UTF8 = TM_module.TM_UTF8_SR_ND -TM_BCD = TM_module.TM_BCD_SR_ND - -# --- Direction Defaults (Cont=Arr, Ent=ND) --- -TM_SR = TM_module.TM_Arr_SR_ND -TM_SL = TM_module.TM_Arr_SL_ND - -# --- Entanglement Defaults (Cont=Arr, Dir=SR) --- -TM_ND = TM_module.TM_Arr_SR_ND -TM_SO = TM_module.TM_Arr_SR_SO -TM_EA = TM_module.TM_Arr_SR_EA - -# --- Common Partials --- -TM_Arr_SL = TM_module.TM_Arr_SL_ND -TM_ASCII_SL = TM_module.TM_ASCII_SL_ND +""" +TM.py +Wrapper for the C extension TM_module. +""" +import TM_module + +# ----------------------------------------------------------------------------- +# 1. Arr (Fixed Array) +# ----------------------------------------------------------------------------- +TM_Arr_CR_ND = TM_module.TM_Arr_CR_ND +TM_Arr_CR_SO = TM_module.TM_Arr_CR_SO +TM_Arr_CR_EA = TM_module.TM_Arr_CR_EA + +TM_Arr_CLR_ND = TM_module.TM_Arr_CLR_ND +TM_Arr_CLR_SO = TM_module.TM_Arr_CLR_SO +TM_Arr_CLR_EA = TM_module.TM_Arr_CLR_EA + +# ----------------------------------------------------------------------------- +# 2. ArrV (Variable Array / Vector) +# ----------------------------------------------------------------------------- +TM_ArrV_CR_ND = TM_module.TM_ArrV_CR_ND +TM_ArrV_CR_SO = TM_module.TM_ArrV_CR_SO +TM_ArrV_CR_EA = TM_module.TM_ArrV_CR_EA + +TM_ArrV_CLR_ND = TM_module.TM_ArrV_CLR_ND +TM_ArrV_CLR_SO = TM_module.TM_ArrV_CLR_SO +TM_ArrV_CLR_EA = TM_module.TM_ArrV_CLR_EA + +# ----------------------------------------------------------------------------- +# 3. Gr (Graph Right / Linked List) +# ----------------------------------------------------------------------------- +TM_Gr_CR_ND = TM_module.TM_Gr_CR_ND +TM_Gr_CR_SO = TM_module.TM_Gr_CR_SO +TM_Gr_CR_EA = TM_module.TM_Gr_CR_EA + +TM_Gr_CLR_ND = TM_module.TM_Gr_CLR_ND +TM_Gr_CLR_SO = TM_module.TM_Gr_CLR_SO +TM_Gr_CLR_EA = TM_module.TM_Gr_CLR_EA + +# ----------------------------------------------------------------------------- +# 4. Glr (Graph Left Right / Doubly Linked List) +# ----------------------------------------------------------------------------- +TM_Glr_CR_ND = TM_module.TM_Glr_CR_ND +TM_Glr_CR_SO = TM_module.TM_Glr_CR_SO +TM_Glr_CR_EA = TM_module.TM_Glr_CR_EA + +TM_Glr_CLR_ND = TM_module.TM_Glr_CLR_ND +TM_Glr_CLR_SO = TM_module.TM_Glr_CLR_SO +TM_Glr_CLR_EA = TM_module.TM_Glr_CLR_EA + +# ----------------------------------------------------------------------------- +# 5. Set (Unordered) +# ----------------------------------------------------------------------------- +TM_Set_CR_ND = TM_module.TM_Set_CR_ND +TM_Set_CR_SO = TM_module.TM_Set_CR_SO +TM_Set_CR_EA = TM_module.TM_Set_CR_EA + +TM_Set_CLR_ND = TM_module.TM_Set_CLR_ND +TM_Set_CLR_SO = TM_module.TM_Set_CLR_SO +TM_Set_CLR_EA = TM_module.TM_Set_CLR_EA + +# ----------------------------------------------------------------------------- +# 6. Map (Items) +# ----------------------------------------------------------------------------- +TM_Map_CR_ND = TM_module.TM_Map_CR_ND +TM_Map_CR_SO = TM_module.TM_Map_CR_SO +TM_Map_CR_EA = TM_module.TM_Map_CR_EA + +TM_Map_CLR_ND = TM_module.TM_Map_CLR_ND +TM_Map_CLR_SO = TM_module.TM_Map_CLR_SO +TM_Map_CLR_EA = TM_module.TM_Map_CLR_EA + +# ----------------------------------------------------------------------------- +# 7. MapK (Keys) +# ----------------------------------------------------------------------------- +TM_MapK_CR_ND = TM_module.TM_MapK_CR_ND +TM_MapK_CR_SO = TM_module.TM_MapK_CR_SO +TM_MapK_CR_EA = TM_module.TM_MapK_CR_EA + +TM_MapK_CLR_ND = TM_module.TM_MapK_CLR_ND +TM_MapK_CLR_SO = TM_module.TM_MapK_CLR_SO +TM_MapK_CLR_EA = TM_module.TM_MapK_CLR_EA + +# ----------------------------------------------------------------------------- +# 8. MapV (Values) +# ----------------------------------------------------------------------------- +TM_MapV_CR_ND = TM_module.TM_MapV_CR_ND +TM_MapV_CR_SO = TM_module.TM_MapV_CR_SO +TM_MapV_CR_EA = TM_module.TM_MapV_CR_EA + +TM_MapV_CLR_ND = TM_module.TM_MapV_CLR_ND +TM_MapV_CLR_SO = TM_module.TM_MapV_CLR_SO +TM_MapV_CLR_EA = TM_module.TM_MapV_CLR_EA + +# ----------------------------------------------------------------------------- +# 9. ASCII (String) +# ----------------------------------------------------------------------------- +TM_ASCII_CR_ND = TM_module.TM_ASCII_CR_ND +TM_ASCII_CR_SO = TM_module.TM_ASCII_CR_SO +TM_ASCII_CR_EA = TM_module.TM_ASCII_CR_EA + +TM_ASCII_CLR_ND = TM_module.TM_ASCII_CLR_ND +TM_ASCII_CLR_SO = TM_module.TM_ASCII_CLR_SO +TM_ASCII_CLR_EA = TM_module.TM_ASCII_CLR_EA + +# ----------------------------------------------------------------------------- +# 10. UTF8 (String) +# ----------------------------------------------------------------------------- +TM_UTF8_CR_ND = TM_module.TM_UTF8_CR_ND +TM_UTF8_CR_SO = TM_module.TM_UTF8_CR_SO +TM_UTF8_CR_EA = TM_module.TM_UTF8_CR_EA + +TM_UTF8_CLR_ND = TM_module.TM_UTF8_CLR_ND +TM_UTF8_CLR_SO = TM_module.TM_UTF8_CLR_SO +TM_UTF8_CLR_EA = TM_module.TM_UTF8_CLR_EA + +# ----------------------------------------------------------------------------- +# 11. Abstract +# ----------------------------------------------------------------------------- +TMA_NaturalNumber = TM_module.TMA_NaturalNumber diff --git a/developer/authored/TM_module.c b/developer/authored/TM_module.c index abf3a9a..10c0f2a 100644 --- a/developer/authored/TM_module.c +++ b/developer/authored/TM_module.c @@ -3,7 +3,7 @@ CPython Extension: Tape Machine Factory Implements: - - 66 Concrete Machine Types + - 60 Concrete Machine Types (Chiral naming: CR/CLR) - TMA_NaturalNumber (Abstract Machine) Namespaces: @@ -23,25 +23,6 @@ /* UNIVERSAL HEAD STATE */ /* ========================================================= */ -/* LIMITATION OF C VOID POINTERS: - - In Standard ISO C, there is no way to "bind" a type to a void* pointer - temporarily to perform arithmetic. A cast expression like '(Type*)ptr' - yields a value (r-value), not a storage location (l-value), so we - cannot perform operations like '((Type*)ptr)++'. - - To remain strictly ISO C compliant, we would have to define multiple - structs (one for PyObject**, one for char*, etc.), which breaks our - generic "Universal Head" architecture. - - DECISION: THE GCC/CLANG WAY - We utilize the common GCC/Clang extension that treats arithmetic on - void* as byte-level arithmetic (i.e., sizeof(void) == 1). - - This allows us to write clean, polymorphic code: - self->head_ptr += sizeof(Element); -*/ - typedef struct{ PyObject_HEAD PyObject* tape_obj; /* The Container */ @@ -88,53 +69,59 @@ static int TM·Arr·init(TM·Head* self, PyObject* args, PyObject* kwds){ return 0; } -/* Sync: Re-bases pointers after a List Reallocation */ static void TM·Arr·sync(TM·Head* self){ - /* 1. Calculate Logical Offset (Byte Distance) */ Py_ssize_t byte_offset = self->head_ptr - self->start_ptr; - - /* 2. Get NEW pointers */ Py_ssize_t len = PyList_GET_SIZE(self->tape_obj); PyObject** new_items = ((PyListObject*)self->tape_obj)->ob_item; - - /* 3. Rebase */ self->start_ptr = (void*)new_items; self->end_ptr = (void*)(new_items + len); - - /* 4. Restore Head (Byte Arithmetic) */ self->head_ptr = self->start_ptr + byte_offset; } -/* --- PRIMITIVES: NAVIGATION (The GCC Way) --- */ +static inline void TM·Arr·lazysync(TM·Head* self){ + Py_ssize_t known_len = (self->end_ptr - self->start_ptr) / sizeof(PyObject*); + Py_ssize_t actual_len = PyList_GET_SIZE(self->tape_obj); + if (known_len != actual_len) { + TM·Arr·sync(self); + } +} + +/* --- PRIMITIVES: NAVIGATION --- */ static PyObject* TM·Arr·s(TM·Head* self){ + TM·Arr·lazysync(self); self->head_ptr += sizeof(PyObject*); Py_RETURN_NONE; } -static PyObject* TM·Arr·ls(TM·Head* self){ +static PyObject* TM·Arr·Ls(TM·Head* self){ + TM·Arr·lazysync(self); self->head_ptr -= sizeof(PyObject*); Py_RETURN_NONE; } static PyObject* TM·Arr·sn(TM·Head* self, PyObject* args){ + TM·Arr·lazysync(self); Py_ssize_t n; if(!PyArg_ParseTuple(args, "n", &n)) return NULL; self->head_ptr += n * sizeof(PyObject*); Py_RETURN_NONE; } -static PyObject* TM·Arr·lsn(TM·Head* self, PyObject* args){ +static PyObject* TM·Arr·Lsn(TM·Head* self, PyObject* args){ + TM·Arr·lazysync(self); Py_ssize_t n; if(!PyArg_ParseTuple(args, "n", &n)) return NULL; self->head_ptr -= n * sizeof(PyObject*); Py_RETURN_NONE; } static PyObject* TM·Arr·sR(TM·Head* self){ + TM·Arr·lazysync(self); self->head_ptr = self->end_ptr - sizeof(PyObject*); Py_RETURN_NONE; } static PyObject* TM·Arr·LsR(TM·Head* self){ + TM·Arr·lazysync(self); self->head_ptr = self->start_ptr; Py_RETURN_NONE; } @@ -142,16 +129,14 @@ static PyObject* TM·Arr·LsR(TM·Head* self){ /* --- PRIMITIVES: ENTANGLEMENT --- */ static PyObject* TM·Arr·e(TM·Head* self){ - /* Create a new object of the same type */ + TM·Arr·lazysync(self); PyTypeObject* type = Py_TYPE(self); TM·Head* new_tm = (TM·Head*)type->tp_alloc(type, 0); if (!new_tm) return NULL; - /* Share the tape */ new_tm->tape_obj = self->tape_obj; Py_INCREF(new_tm->tape_obj); - /* Copy the pointers (Entangled start at same position) */ new_tm->start_ptr = self->start_ptr; new_tm->end_ptr = self->end_ptr; new_tm->head_ptr = self->head_ptr; @@ -162,13 +147,14 @@ static PyObject* TM·Arr·e(TM·Head* self){ /* --- PRIMITIVES: I/O --- */ static PyObject* TM·Arr·r(TM·Head* self){ - /* Must cast to dereference the data */ + TM·Arr·lazysync(self); PyObject* item = *(PyObject**)self->head_ptr; Py_INCREF(item); return item; } static PyObject* TM·Arr·w(TM·Head* self, PyObject* val){ + TM·Arr·lazysync(self); PyObject** p = (PyObject**)self->head_ptr; PyObject* old = *p; Py_INCREF(val); @@ -180,78 +166,133 @@ static PyObject* TM·Arr·w(TM·Head* self, PyObject* val){ /* --- PRIMITIVES: QUERY --- */ static PyObject* TM·Arr·qR(TM·Head* self){ - /* GCC Extension: void* comparison and arithmetic */ + TM·Arr·lazysync(self); if(self->head_ptr >= self->end_ptr - sizeof(PyObject*)){ Py_RETURN_TRUE; } Py_RETURN_FALSE; } -static PyObject* TM·Arr·qL(TM·Head* self){ +static PyObject* TM·Arr·LqR(TM·Head* self){ + TM·Arr·lazysync(self); if(self->head_ptr <= self->start_ptr){ Py_RETURN_TRUE; } Py_RETURN_FALSE; } +static PyObject* TM·Arr·qnR(TM·Head* self){ + TM·Arr·lazysync(self); + Py_ssize_t byte_diff = self->end_ptr - self->head_ptr; + /* If at Rightmost, diff is 1 item size. Result 0. */ + Py_ssize_t count = (byte_diff / sizeof(PyObject*)) - 1; + return PyLong_FromSsize_t(count); +} -/* --- PRIMITIVES: DESTRUCTIVE (Variable Array Only) --- */ +static PyObject* TM·Arr·LqnR(TM·Head* self){ + TM·Arr·lazysync(self); + Py_ssize_t byte_diff = self->head_ptr - self->start_ptr; + /* If at Leftmost, diff is 0. Result 0. */ + Py_ssize_t count = byte_diff / sizeof(PyObject*); + return PyLong_FromSsize_t(count); +} -static PyObject* TM·Arr·d(TM·Head* self){ - /* 1. Calc Index (Byte Diff / Element Size) */ - Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); +/* --- PRIMITIVES: DESTRUCTIVE (SO Only) --- */ - /* 2. API Call */ - if (PyList_SetSlice(self->tape_obj, idx, idx+1, NULL) < 0) return NULL; - - /* 3. SYNC */ - TM·Arr·sync(self); - - /* 4. Safety */ - if (self->head_ptr >= self->end_ptr && self->start_ptr != self->end_ptr) { - self->head_ptr -= sizeof(PyObject*); - } else if (self->start_ptr == self->end_ptr) { - PyErr_SetString(PyExc_RuntimeError, "TM Empty: First Order Invariant Broken."); +static PyObject* TM·Arr·dR(TM·Head* self){ + TM·Arr·lazysync(self); + /* Delete from Current to Rightmost (inclusive) */ + /* Guard: Must have a left neighbor to step back to. */ + if (self->head_ptr <= self->start_ptr) { + PyErr_SetString(PyExc_RuntimeError, "Invariant Violation: Cannot dR from leftmost cell (tape would empty)."); return NULL; } + Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); + Py_ssize_t len = PyList_GET_SIZE(self->tape_obj); + + if (PyList_SetSlice(self->tape_obj, idx, len, NULL) < 0) return NULL; + + /* Current cell is gone. Step Left to valid neighbor. */ + self->head_ptr -= sizeof(PyObject*); + TM·Arr·sync(self); Py_RETURN_NONE; } -static PyObject* TM·Arr·a(TM·Head* self, PyObject* val){ +static PyObject* TM·Arr·LdR(TM·Head* self){ + TM·Arr·lazysync(self); + /* Delete from Current to Leftmost (inclusive) */ + /* Guard: Must have a right neighbor to step 'right' (reset) to. */ + if (self->head_ptr >= self->end_ptr - sizeof(PyObject*)) { + PyErr_SetString(PyExc_RuntimeError, "Invariant Violation: Cannot LdR from rightmost cell (tape would empty)."); + return NULL; + } Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); - - if (PyList_Insert(self->tape_obj, idx, val) < 0) return NULL; + if (PyList_SetSlice(self->tape_obj, 0, idx+1, NULL) < 0) return NULL; + + /* Head resets to 0 (the element that was to the right of deleted chunk) */ + self->head_ptr = self->start_ptr; TM·Arr·sync(self); Py_RETURN_NONE; } static PyObject* TM·Arr·esd(TM·Head* self){ + TM·Arr·lazysync(self); if (self->head_ptr >= self->end_ptr - sizeof(PyObject*)) { PyErr_SetString(PyExc_IndexError, "esd: No right neighbor."); return NULL; } - Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); - if (PyList_SetSlice(self->tape_obj, idx+1, idx+2, NULL) < 0) return NULL; - TM·Arr·sync(self); Py_RETURN_NONE; } -static PyObject* TM·Arr·Lesd(TM·Head* self){ +static PyObject* TM·Arr·eLsd(TM·Head* self){ + TM·Arr·lazysync(self); if (self->head_ptr <= self->start_ptr) { - PyErr_SetString(PyExc_IndexError, "Lesd: No left neighbor."); + PyErr_SetString(PyExc_IndexError, "eLsd: No left neighbor."); return NULL; } - Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); if (PyList_SetSlice(self->tape_obj, idx-1, idx, NULL) < 0) return NULL; - /* Adjustment: Shift Left */ + /* We removed item at idx-1. The item at idx is now at idx-1. */ self->head_ptr -= sizeof(PyObject*); + TM·Arr·sync(self); + Py_RETURN_NONE; +} + +static PyObject* TM·Arr·esa(TM·Head* self, PyObject* val){ + TM·Arr·lazysync(self); + /* Insert after current (at idx+1) */ + Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); + if (PyList_Insert(self->tape_obj, idx+1, val) < 0) return NULL; + TM·Arr·sync(self); + Py_RETURN_NONE; +} +static PyObject* TM·Arr·eLsa(TM·Head* self, PyObject* val){ + TM·Arr·lazysync(self); + /* Insert before current (at idx) */ + Py_ssize_t idx = (self->head_ptr - self->start_ptr) / sizeof(PyObject*); + if (PyList_Insert(self->tape_obj, idx, val) < 0) return NULL; + + /* Current item shifts right to idx+1. Increment head to track it. */ + self->head_ptr += sizeof(PyObject*); + TM·Arr·sync(self); + Py_RETURN_NONE; +} + +static PyObject* TM·Arr·aR(TM·Head* self, PyObject* val){ + if (PyList_Append(self->tape_obj, val) < 0) return NULL; + TM·Arr·sync(self); + Py_RETURN_NONE; +} + +static PyObject* TM·Arr·LaR(TM·Head* self, PyObject* val){ + if (PyList_Insert(self->tape_obj, 0, val) < 0) return NULL; + self->head_ptr += sizeof(PyObject*); TM·Arr·sync(self); Py_RETURN_NONE; } @@ -262,59 +303,70 @@ static PyObject* TM·Arr·Lesd(TM·Head* self){ /* ========================================================= */ /* 1. NON-DESTRUCTIVE (ND) */ -static PyMethodDef Table·SR·ND[] = { +static PyMethodDef Table·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·SL·ND[] = { +static PyMethodDef Table·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,""}, + {"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, ""}, - {"qL",(PyCFunction)TM·Arr·qL,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) - For ArrV */ -static PyMethodDef Table·SR·SO[] = { +/* 2. DESTRUCTIVE (SO) - No Entangle 'e' */ +static PyMethodDef Table·CR·SO[] = { {"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, ""}, - {"d", (PyCFunction)TM·Arr·d, METH_NOARGS, ""}, - {"a", (PyCFunction)TM·Arr·a, 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·SL·SO[] = { +static PyMethodDef Table·CLR·SO[] = { {"s", (PyCFunction)TM·Arr·s, METH_NOARGS, ""}, - {"ls",(PyCFunction)TM·Arr·ls,METH_NOARGS, ""}, - {"e", (PyCFunction)TM·Arr·e, METH_NOARGS, ""}, + {"Ls",(PyCFunction)TM·Arr·Ls,METH_NOARGS, ""}, {"r", (PyCFunction)TM·Arr·r, METH_NOARGS, ""}, {"w", (PyCFunction)TM·Arr·w, METH_O, ""}, - {"d", (PyCFunction)TM·Arr·d, METH_NOARGS, ""}, - {"a", (PyCFunction)TM·Arr·a, METH_O, ""}, + {"dR",(PyCFunction)TM·Arr·dR,METH_NOARGS, ""}, + {"LdR",(PyCFunction)TM·Arr·LdR,METH_NOARGS,""}, {"esd",(PyCFunction)TM·Arr·esd,METH_NOARGS,""}, - {"Lesd",(PyCFunction)TM·Arr·Lesd,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, ""}, - {"qL",(PyCFunction)TM·Arr·qL,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} @@ -341,7 +393,7 @@ static PyObject* TM·Nat·sn(TM·Nat* self, PyObject* args){ self->state += n; Py_RETURN_NONE; } -static PyObject* TM·Nat·ls(TM·Nat* self){ +static PyObject* TM·Nat·Ls(TM·Nat* self){ if(self->state > 0) self->state--; Py_RETURN_NONE; } @@ -354,21 +406,36 @@ static PyObject* TM·Nat·w(TM·Nat* self, PyObject* val){ } static PyObject* TM·Nat·qR(TM·Nat* self){ Py_RETURN_FALSE; } -static PyObject* TM·Nat·qL(TM·Nat* self){ +static PyObject* TM·Nat·LqR(TM·Nat* self){ if(self->state == 0){ Py_RETURN_TRUE; } Py_RETURN_FALSE; } +/* Nat Query N: + qnR -> Infinite? Or not supported. For now, max int? + LqnR -> Distance from 0. Equal to state. +*/ +static PyObject* TM·Nat·qnR(TM·Nat* self){ + /* Abstract number line is infinite. */ + PyErr_SetString(PyExc_RuntimeError, "Natural Number tape is infinite to the right."); + return NULL; +} +static PyObject* TM·Nat·LqnR(TM·Nat* self){ + return PyLong_FromUnsignedLongLong(self->state); +} + static PyMethodDef TM·Nat·methods[] = { {"s", (PyCFunction)TM·Nat·s, METH_NOARGS, ""}, {"sn",(PyCFunction)TM·Nat·sn,METH_VARARGS,""}, - {"ls",(PyCFunction)TM·Nat·ls,METH_NOARGS, ""}, + {"Ls",(PyCFunction)TM·Nat·Ls,METH_NOARGS, ""}, {"r", (PyCFunction)TM·Nat·r, METH_NOARGS, ""}, {"w", (PyCFunction)TM·Nat·w, METH_O, ""}, {"qR",(PyCFunction)TM·Nat·qR,METH_NOARGS, ""}, - {"qL",(PyCFunction)TM·Nat·qL,METH_NOARGS, ""}, + {"LqR",(PyCFunction)TM·Nat·LqR,METH_NOARGS, ""}, + {"qnR",(PyCFunction)TM·Nat·qnR,METH_NOARGS, ""}, + {"LqnR",(PyCFunction)TM·Nat·LqnR,METH_NOARGS, ""}, {"LsR",(PyCFunction)TM·Nat·LsR,METH_NOARGS, ""}, {NULL} }; @@ -386,7 +453,7 @@ static PyTypeObject TMA_NaturalNumber·Type = { /* ========================================================= */ -/* TYPE DEFINITIONS (The 66 Concrete Types) */ +/* TYPE DEFINITIONS (The 60 Concrete Types) */ /* ========================================================= */ #define DEFINE_TYPE(NAME, METHODS) \ @@ -404,114 +471,104 @@ static PyTypeObject NAME##·Type = { \ /* --------------------------------------------------------- 1. Arr (Fixed Array) --------------------------------------------------------- */ -DEFINE_TYPE(TM_Arr_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_Arr_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_Arr_SR_EA, Table·SR·ND) +DEFINE_TYPE(TM_Arr_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_Arr_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_Arr_CR_EA, Table·CR·ND) -DEFINE_TYPE(TM_Arr_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_Arr_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_Arr_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_Arr_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_Arr_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_Arr_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 2. ArrV (Variable Array / Vector) --------------------------------------------------------- */ -DEFINE_TYPE(TM_ArrV_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_ArrV_SR_SO, Table·SR·SO) /* Destructive */ -DEFINE_TYPE(TM_ArrV_SR_EA, Table·SR·ND) +DEFINE_TYPE(TM_ArrV_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_ArrV_CR_SO, Table·CR·SO) /* Destructive */ +DEFINE_TYPE(TM_ArrV_CR_EA, Table·CR·ND) -DEFINE_TYPE(TM_ArrV_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_ArrV_SL_SO, Table·SL·SO) /* Destructive */ -DEFINE_TYPE(TM_ArrV_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_ArrV_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_ArrV_CLR_SO, Table·CLR·SO) /* Destructive */ +DEFINE_TYPE(TM_ArrV_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 3. Gr (Graph Right / Linked List) --------------------------------------------------------- */ -DEFINE_TYPE(TM_Gr_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_Gr_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_Gr_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_Gr_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_Gr_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_Gr_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_Gr_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_Gr_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_Gr_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_Gr_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_Gr_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_Gr_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 4. Glr (Graph Left Right / Doubly Linked List) --------------------------------------------------------- */ -DEFINE_TYPE(TM_Glr_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_Glr_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_Glr_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_Glr_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_Glr_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_Glr_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_Glr_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_Glr_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_Glr_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_Glr_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_Glr_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_Glr_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 5. Set (Unordered) --------------------------------------------------------- */ -DEFINE_TYPE(TM_Set_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_Set_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_Set_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_Set_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_Set_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_Set_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_Set_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_Set_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_Set_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_Set_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_Set_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_Set_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 6. Map (Items) --------------------------------------------------------- */ -DEFINE_TYPE(TM_Map_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_Map_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_Map_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_Map_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_Map_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_Map_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_Map_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_Map_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_Map_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_Map_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_Map_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_Map_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 7. MapK (Keys) --------------------------------------------------------- */ -DEFINE_TYPE(TM_MapK_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_MapK_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_MapK_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_MapK_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_MapK_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_MapK_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_MapK_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_MapK_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_MapK_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_MapK_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_MapK_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_MapK_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 8. MapV (Values) --------------------------------------------------------- */ -DEFINE_TYPE(TM_MapV_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_MapV_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_MapV_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_MapV_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_MapV_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_MapV_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_MapV_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_MapV_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_MapV_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_MapV_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_MapV_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_MapV_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 9. ASCII (String) --------------------------------------------------------- */ -DEFINE_TYPE(TM_ASCII_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_ASCII_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_ASCII_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_ASCII_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_ASCII_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_ASCII_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_ASCII_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_ASCII_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_ASCII_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_ASCII_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_ASCII_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_ASCII_CLR_EA, Table·CLR·ND) /* --------------------------------------------------------- 10. UTF8 (String) --------------------------------------------------------- */ -DEFINE_TYPE(TM_UTF8_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_UTF8_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_UTF8_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_UTF8_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_UTF8_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_UTF8_SL_EA, Table·SL·ND) - -/* --------------------------------------------------------- - 11. BCD (String/Array) - --------------------------------------------------------- */ -DEFINE_TYPE(TM_BCD_SR_ND, Table·SR·ND) -DEFINE_TYPE(TM_BCD_SR_SO, Table·SR·ND) -DEFINE_TYPE(TM_BCD_SR_EA, Table·SR·ND) -DEFINE_TYPE(TM_BCD_SL_ND, Table·SL·ND) -DEFINE_TYPE(TM_BCD_SL_SO, Table·SL·ND) -DEFINE_TYPE(TM_BCD_SL_EA, Table·SL·ND) +DEFINE_TYPE(TM_UTF8_CR_ND, Table·CR·ND) +DEFINE_TYPE(TM_UTF8_CR_SO, Table·CR·ND) +DEFINE_TYPE(TM_UTF8_CR_EA, Table·CR·ND) +DEFINE_TYPE(TM_UTF8_CLR_ND, Table·CLR·ND) +DEFINE_TYPE(TM_UTF8_CLR_SO, Table·CLR·ND) +DEFINE_TYPE(TM_UTF8_CLR_EA, Table·CLR·ND) /* ========================================================= */ @@ -532,48 +589,44 @@ PyMODINIT_FUNC PyInit_TM_module(void){ if(!m) return NULL; /* Arr */ - ADD_TYPE(TM_Arr_SR_ND) ADD_TYPE(TM_Arr_SR_SO) ADD_TYPE(TM_Arr_SR_EA) - ADD_TYPE(TM_Arr_SL_ND) ADD_TYPE(TM_Arr_SL_SO) ADD_TYPE(TM_Arr_SL_EA) + ADD_TYPE(TM_Arr_CR_ND) ADD_TYPE(TM_Arr_CR_SO) ADD_TYPE(TM_Arr_CR_EA) + ADD_TYPE(TM_Arr_CLR_ND) ADD_TYPE(TM_Arr_CLR_SO) ADD_TYPE(TM_Arr_CLR_EA) /* ArrV */ - ADD_TYPE(TM_ArrV_SR_ND) ADD_TYPE(TM_ArrV_SR_SO) ADD_TYPE(TM_ArrV_SR_EA) - ADD_TYPE(TM_ArrV_SL_ND) ADD_TYPE(TM_ArrV_SL_SO) ADD_TYPE(TM_ArrV_SL_EA) + ADD_TYPE(TM_ArrV_CR_ND) ADD_TYPE(TM_ArrV_CR_SO) ADD_TYPE(TM_ArrV_CR_EA) + ADD_TYPE(TM_ArrV_CLR_ND) ADD_TYPE(TM_ArrV_CLR_SO) ADD_TYPE(TM_ArrV_CLR_EA) /* Gr */ - ADD_TYPE(TM_Gr_SR_ND) ADD_TYPE(TM_Gr_SR_SO) ADD_TYPE(TM_Gr_SR_EA) - ADD_TYPE(TM_Gr_SL_ND) ADD_TYPE(TM_Gr_SL_SO) ADD_TYPE(TM_Gr_SL_EA) + ADD_TYPE(TM_Gr_CR_ND) ADD_TYPE(TM_Gr_CR_SO) ADD_TYPE(TM_Gr_CR_EA) + ADD_TYPE(TM_Gr_CLR_ND) ADD_TYPE(TM_Gr_CLR_SO) ADD_TYPE(TM_Gr_CLR_EA) /* Glr */ - ADD_TYPE(TM_Glr_SR_ND) ADD_TYPE(TM_Glr_SR_SO) ADD_TYPE(TM_Glr_SR_EA) - ADD_TYPE(TM_Glr_SL_ND) ADD_TYPE(TM_Glr_SL_SO) ADD_TYPE(TM_Glr_SL_EA) + ADD_TYPE(TM_Glr_CR_ND) ADD_TYPE(TM_Glr_CR_SO) ADD_TYPE(TM_Glr_CR_EA) + ADD_TYPE(TM_Glr_CLR_ND) ADD_TYPE(TM_Glr_CLR_SO) ADD_TYPE(TM_Glr_CLR_EA) /* Set */ - ADD_TYPE(TM_Set_SR_ND) ADD_TYPE(TM_Set_SR_SO) ADD_TYPE(TM_Set_SR_EA) - ADD_TYPE(TM_Set_SL_ND) ADD_TYPE(TM_Set_SL_SO) ADD_TYPE(TM_Set_SL_EA) + ADD_TYPE(TM_Set_CR_ND) ADD_TYPE(TM_Set_CR_SO) ADD_TYPE(TM_Set_CR_EA) + ADD_TYPE(TM_Set_CLR_ND) ADD_TYPE(TM_Set_CLR_SO) ADD_TYPE(TM_Set_CLR_EA) /* Map */ - ADD_TYPE(TM_Map_SR_ND) ADD_TYPE(TM_Map_SR_SO) ADD_TYPE(TM_Map_SR_EA) - ADD_TYPE(TM_Map_SL_ND) ADD_TYPE(TM_Map_SL_SO) ADD_TYPE(TM_Map_SL_EA) + ADD_TYPE(TM_Map_CR_ND) ADD_TYPE(TM_Map_CR_SO) ADD_TYPE(TM_Map_CR_EA) + ADD_TYPE(TM_Map_CLR_ND) ADD_TYPE(TM_Map_CLR_SO) ADD_TYPE(TM_Map_CLR_EA) /* MapK */ - ADD_TYPE(TM_MapK_SR_ND) ADD_TYPE(TM_MapK_SR_SO) ADD_TYPE(TM_MapK_SR_EA) - ADD_TYPE(TM_MapK_SL_ND) ADD_TYPE(TM_MapK_SL_SO) ADD_TYPE(TM_MapK_SL_EA) + ADD_TYPE(TM_MapK_CR_ND) ADD_TYPE(TM_MapK_CR_SO) ADD_TYPE(TM_MapK_CR_EA) + ADD_TYPE(TM_MapK_CLR_ND) ADD_TYPE(TM_MapK_CLR_SO) ADD_TYPE(TM_MapK_CLR_EA) /* MapV */ - ADD_TYPE(TM_MapV_SR_ND) ADD_TYPE(TM_MapV_SR_SO) ADD_TYPE(TM_MapV_SR_EA) - ADD_TYPE(TM_MapV_SL_ND) ADD_TYPE(TM_MapV_SL_SO) ADD_TYPE(TM_MapV_SL_EA) + ADD_TYPE(TM_MapV_CR_ND) ADD_TYPE(TM_MapV_CR_SO) ADD_TYPE(TM_MapV_CR_EA) + ADD_TYPE(TM_MapV_CLR_ND) ADD_TYPE(TM_MapV_CLR_SO) ADD_TYPE(TM_MapV_CLR_EA) /* ASCII */ - ADD_TYPE(TM_ASCII_SR_ND) ADD_TYPE(TM_ASCII_SR_SO) ADD_TYPE(TM_ASCII_SR_EA) - ADD_TYPE(TM_ASCII_SL_ND) ADD_TYPE(TM_ASCII_SL_SO) ADD_TYPE(TM_ASCII_SL_EA) + ADD_TYPE(TM_ASCII_CR_ND) ADD_TYPE(TM_ASCII_CR_SO) ADD_TYPE(TM_ASCII_CR_EA) + ADD_TYPE(TM_ASCII_CLR_ND) ADD_TYPE(TM_ASCII_CLR_SO) ADD_TYPE(TM_ASCII_CLR_EA) /* UTF8 */ - ADD_TYPE(TM_UTF8_SR_ND) ADD_TYPE(TM_UTF8_SR_SO) ADD_TYPE(TM_UTF8_SR_EA) - ADD_TYPE(TM_UTF8_SL_ND) ADD_TYPE(TM_UTF8_SL_SO) ADD_TYPE(TM_UTF8_SL_EA) - - /* BCD */ - ADD_TYPE(TM_BCD_SR_ND) ADD_TYPE(TM_BCD_SR_SO) ADD_TYPE(TM_BCD_SR_EA) - ADD_TYPE(TM_BCD_SL_ND) ADD_TYPE(TM_BCD_SL_SO) ADD_TYPE(TM_BCD_SL_EA) + ADD_TYPE(TM_UTF8_CR_ND) ADD_TYPE(TM_UTF8_CR_SO) ADD_TYPE(TM_UTF8_CR_EA) + ADD_TYPE(TM_UTF8_CLR_ND) ADD_TYPE(TM_UTF8_CLR_SO) ADD_TYPE(TM_UTF8_CLR_EA) /* Abstract */ if (PyType_Ready(&TMA_NaturalNumber·Type) < 0) return NULL; diff --git a/developer/authored/TM_tutorial.py b/developer/authored/TM_tutorial.py index 3af9f14..6ce3a0d 100755 --- a/developer/authored/TM_tutorial.py +++ b/developer/authored/TM_tutorial.py @@ -4,17 +4,17 @@ import sys def print_tape(tm): """ - Prints tape contents using the First/Rest pattern and vertical comma format. + Prints tape contents using the First/Rest pattern. + + WARNING: This function moves the head! + It rewinds to the start (LsR) and traverses to the end. + To preserve head state on ND machines, pass 'tm.e()'. """ - # Reset head to start + # Reset head to start (Leftmost) tm.LsR() - if tm.qR() and tm.qL(): - # Handle single element or empty case (qL returns true at start) - # Check if we have at least one element by trying to read? - # Actually qL and qR being true means 1 element or 0? - # qL=True (at start). qR=True (at end). => 1 element. - # We rely on 'r' to throw/work. + # Handle single element case + if tm.qR() and tm.LqR(): try: print(tm.r()) except: @@ -33,7 +33,7 @@ def print_tape(tm): def tm_loops_tutorial(): print("--- 1. The Standard Traversal (Read -> Process -> Step) ---") data = [10, 20, 30, 40, 50] - tm = TM.TM_Arr_SR_ND(data) + tm = TM.TM_Arr_CR_ND(data) while True: val = tm.r() @@ -42,7 +42,7 @@ def tm_loops_tutorial(): tm.s() print("\n--- 2. The Accumulator (Initialized First) ---") - tm = TM.TM_Arr_SR_ND([1, 2, 3, 4, 5]) + tm = TM.TM_Arr_CR_ND([1, 2, 3, 4, 5]) total = tm.r() # Process First while not tm.qR(): # Guard @@ -51,51 +51,77 @@ def tm_loops_tutorial(): print(f"Total: {total}") - print("\n--- 3. Destructive Filter (Entangled Copy) ---") - # We use TM_ArrV_SR_SO because we need 'd' (delete). - # We added 'e' (entangle) to the SO table to support this specific workflow. + print("\n--- 3. Destructive Filter (Variable Tape) ---") + # We use TM_ArrV_CLR_SO (Chiral Left Right, Solitary). + # We need CLR to support 'eLsd' (Delete Left Neighbor). original_data = [1, 2, 3, 4, 5, 6, 7] - tm_master = TM.TM_ArrV_SR_SO(original_data) + tm = TM.TM_ArrV_CLR_SO(original_data) + + # 1. Process First (Index 0) - Special Case + # We check the start. If odd, we must delete it. + # Since we are at the start, we cannot use eLsd (no left neighbor). + # We must Step then eLsd? No, that deletes 0. + # If we Step, 0 becomes the left neighbor. + + tm.LsR() # Ensure start - # Create an entangled copy for the deletion work - tm_worker = tm_master.e() + first_val = tm.r() + if first_val % 2 != 0: + print(f"Deleting odd start: {first_val}") + if tm.qR(): + # Single element list. Cannot step. + print("(Cannot delete last remaining element)") + else: + tm.s() # Step to 1 + tm.eLsd() # Delete Left Neighbor (Index 0) + # Head is now at Index 0 (the element that shifted down). + # We must NOT step in the loop immediately, or we skip the new First. + # To handle this cleanly in a loop, we align the head to "Previous" logic? + # Easier: Just restart logic from the new current. + + # Since we deleted 0, the loop below starts at the *new* 0. + # We just need to make sure we don't double step. + # The simplest way is to handle the deletion, then let the loop + # run normally from the current head position. - # Work on the worker + # Main Loop + # Invariant: Head is on a valid cell we want to inspect. while True: - val = tm_worker.r() - - if val % 2 != 0: - print(f"Deleting odd: {val}") - # Unguarded delete: We must guarantee we don't delete the final cell - # in a way that breaks the invariant for the *other* machine if it were - # elsewhere. But here they are entangled. - # Note: If we delete the last element, the C logic steps back. - tm_worker.d() - - # Since d() is in-place, the 'next' element slides into the current spot. - # We do NOT step. But we must check if we hit the end of the tape - # (i.e. we deleted the tail and stepped back, or the tape is empty). - - # Safety check for end of tape after delete - if tm_worker.qR(): - # We are at the right edge. Check if the current (last) element - # also needs deleting. - val = tm_worker.r() - if val % 2 != 0: - print(f"Deleting last odd: {val}") - try: - tm_worker.d() - except RuntimeError: - print("(Tape became empty)") - break - break - else: - print(f"Keeping even: {val}") - if tm_worker.qR(): break - tm_worker.s() + val = tm.r() + if val % 2 != 0: + # Found odd. Delete it. + print(f"Deleting odd: {val}") + + if not tm.qR(): + # Case: Not at end. + # Step Right, then delete the item to our Left (which is 'val'). + tm.s() + tm.eLsd() + # Head is now on the next item (shifted left into current slot). + # We continue loop to inspect *this* item. + else: + # Case: At End (Tail). + # Cannot use eLsd strategy because we can't step right. + # Must use esd strategy: Step Left, delete Right Neighbor. + if tm.LqR(): + print("(Last item, cannot empty tape)") + break + + tm.Ls() # Step Left + tm.esd() # Delete Right Neighbor (Tail) + # Tail deleted. We are at new tail. + # We inspected this even number already (presumably), so we break? + # Actually, if we stepped left, we are on a number we already kept. + break + else: + print(f"Keeping even: {val}") + if tm.qR(): break + tm.s() print("Final Tape Content:") - print_tape(tm_master) + # Pass the SO machine directly. + # This will consume/rewind the head, but that is acceptable here. + print_tape(tm) if __name__ == "__main__": tm_loops_tutorial() diff --git a/developer/authored/build/temp.linux-x86_64-cpython-311/TM_module.o b/developer/authored/build/temp.linux-x86_64-cpython-311/TM_module.o index d4993d1742833a4d73f3656487b6bee2a88e0cb8..0a4bc2fe5d420314622d74be8ffde9211b3563c1 100644 GIT binary patch literal 173856 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�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 diff --git a/document/TM.html b/document/TM.html index 13555e3..d6e2a40 100644 --- a/document/TM.html +++ b/document/TM.html @@ -14,7 +14,7 @@ @@ -42,10 +42,6 @@ A defining invariant of all Tape Machines is that cell contents are cargo. The TM reads and writes cell payload, but it does not interpret that payload as control. The decisions are made above the TM, by the programmer’s algorithm.

-

- A TM is constructed with a set of feature symbols that select which parts of the interface are available. When no feature symbols are supplied, the result is a non-destructive step right machine with no indexing. Feature symbols can enable step left behavior (via the mirror view), enable random access indexing functions, and accounting for a shared tape, among other things. -

-

A first order TM is defined by a single invariant: the head is always on a valid cell. This invariant makes the primitive interface total: every move, read, write, and query has a clean, well defined meaning, and caller code stays free of scattered end case tests.

@@ -63,6 +59,68 @@ These are selected at TM construction time. In one approach, no methods are placed on the interface that can destroy tape cells. This supports a non-destructive programming paradigm, so such machines are said to be non-destructive. Without destructive operations, entangled machines simply do not have the ability to break each other. In a second approach, the interface is configured so there are no functions for entangling machines in the first place. Each solitary machine can safely perform destructive operations because no other machine shares its tape. As a third approach, each group of entangled machines shares a catalog listing all machines in the group. Caller code can guard operations by querying whether a planned operation is safe before attempting it. This third strategy is called entanglement accounting. During the time of execution of the guard and operation, each tape machine must be able to lockout others from access to the catalog. Yet another approach is for the programmer, compiler, or external function to prove code is safe, which is the same as proving that guard code is not needed. An alternative is to use a compiler that only produces correct code in the first place. This is the approach of correct by construction.

+

Machine Naming Convention

+ +

+ Concrete Tape Machine classes follow a strict naming grammar. This grammar acts as a feature descriptor, allowing the programmer to select a machine by constructing its name. +

+ +

+ The name is composed of three feature segments: the Container Type, the Chirality, and the Entanglement Approach. +

+ +

grammar

+ + class_name :: TM [ _container ] [ _chirality ] [ _entanglement ] + container :: ARR | ARRV | GR | GLR | SET | MAP | MAPK | MAPV + | ASCII | UTF8 + chirality :: CR | CLR + entanglement :: ND | SO | EA + + +

+ Segments are separated by underscores. The default configuration for a segment is used if that segment is omitted. + The default machine is TM_ARR_CR_ND (Fixed Array, Chiral Right, Non-Destructive). +

+ +

container

+
    +
  • ARR Array Fixed (Default). A contiguous sequence of fixed length (e.g., Python List, C Array).
  • +
  • ARRV Array Variable. A contiguous sequence that may resize (e.g., Vector).
  • +
  • GR Graph Right. A node-based sequence with a single right neighbor (Singly Linked List).
  • +
  • GLR Graph Left Right. A node-based sequence with left and right neighbors (Doubly Linked List).
  • +
  • SET Set. Iteration over the elements of a Set.
  • +
  • MAP Map. Iteration over the items (Key-Value pairs) of a Map.
  • +
  • MAPK Map Keys. Iteration over the keys of a Map.
  • +
  • MAPV Map Values. Iteration over the values of a Map.
  • +
  • ASCII Ascii. A sequence of 1-byte characters.
  • +
  • UTF8 Utf8. A sequence of variable-width Unicode characters.
  • +
+ +

chirality

+
    +
  • CR Chiral Right (Default). The machine head can only be moved to the right.
  • +
  • CLR Chiral Left Right. The machine is bidirectional, supports stepping either right or left.
  • +
+ +

entanglement

+
    +
  • ND Non-Destructive (Default). Safe for entanglement.
  • +
  • SO Solitary. Exclusive ownership; supports destructive ops.
  • +
  • EA Entanglement Accounting. Shared access guarded by a catalog.
  • +
+ +

Abstract and Traversal Machines

+

+ The naming convention extends to Abstract and Traversal machines using specific prefixes. +

+
    +
  • TMA TM Abstract. Virtual tapes computed over state. +
    Example: TMA_Natural_Number (Iterates 0, 1, 2...).
  • +
  • TMT TM Traversal. Algorithmic traversals over non-linear structures. +
    Example: TMT_Tree_DepthFirst (Linearizes a tree via stack/recursion).
  • +
+

Command language

@@ -75,12 +133,9 @@

- A TM is constructed with a set of feature symbols that select which parts of the language are available. - When no feature symbols are supplied, the result is a non-destructive step right machine with no indexing. - Feature symbols can enable step left behavior (via the mirror view) and can independently enable indexing commands. + The grammar selects which parts of the language are available based on the machine's configuration (CR or CLR).

-

For the non-destructive step right machine

grammar

@@ -119,7 +174,7 @@

The query command, q, reports head state. With no arg descriptor it returns a boolean value. - With an R arg descriptor it returns true iff the head is on the rightmost cell. With an I arg descriptor it returns an index. + With an R arg descriptor it returns true iff the head is on the rightmost cell.

@@ -145,7 +200,7 @@

- The n arg descriptor supplies a repetition count. + The n arg descriptor supplies a repetition count or implies a distance query.

@@ -171,6 +226,7 @@

Query

qR ; true iff head is on rightmost + qnR ; returns number of steps to rightmost

Copying to and from tape cells and python variables

@@ -195,9 +251,6 @@

- Step left support does not imply index space. - A machine can support L while still omitting index operations. - When index space is enabled as an additional feature, the I arg descriptor becomes available and index based cue and query forms become legal. When L is available, n can also be negative, with the sign selecting the direction in the base view.

@@ -206,15 +259,13 @@ statement :: ( [machine] command [arg]* )+ machine :: L command :: e | q | r | s | w - arg :: R | I | n + arg :: R | n

- Index space, as defined in the TTCA book, is a natural number sequence machine that walks the tape of a base machine and establishes a one to one correspondence between natural numbers and tape cells. - That correspondence belongs to the tape and stays fixed when we change the view. - For example, consider a tape with cells [c_0 ,c_1 ,c_2 ,c_3 ,c_4], where c_4 is rightmost and has index 4. + Consider a tape with cells [c_0 ,c_1 ,c_2 ,c_3 ,c_4], where c_4 is rightmost. In the mirror view we write the same cells as [c_4 ,c_3 ,c_2 ,c_1 ,c_0]. - In the mirror view c_4 sits at the left edge, and it still has index 4. + In the mirror view c_4 sits at the left edge. A right step from c_4 in the mirror view lands on c_3, which matches a left step from c_4 in the base view.

@@ -232,48 +283,24 @@ sn(2) ; step to right neighbor twice -

Head movement relative to leftmost

- - sI(0) ; cue the head to the leftmost cell by index - sI(3) ; cue the head to tape[3] - - -

- LsI(k) and sI(k) cue the head to the same indexed cell. - L flips direction and the meaning of R, not the index to cell correspondence. - Thus LsI(0) cues the cell with index zero, which is rightmost in the mirror view and leftmost in the base view. -

-

Absolute head movement

LsR ; cue the head to leftmost sR ; cue the head to rightmost -

- Without code optimization LsR will be faster than sI(0), because sI requires passing and processing an argument. -

-

Query

LqR ; head is on leftmost qR ; head is on rightmost - qI ; index of the head - qIR ; index of rightmost - LqIR ; index of leftmost, typically zero + qnR ; steps to rightmost + LqnR ; steps to leftmost -

- The I arg descriptor causes q to return an index. - By default q returns a boolean value. - In other commands, an I arg descriptor indicates that an index argument is supplied. -

-

The R arg descriptor focuses the command on the selected view rightmost cell. For qR, the result is true iff the head is on rightmost. - For qIR, the result is the index of rightmost. - Under L, that rightmost cell is the base view leftmost cell, so LqIR returns the index of leftmost, typically zero. + Under L, that rightmost cell is the base view leftmost cell, so LqR returns true iff the head is on the leftmost cell.

Copying to and from tape cells and python variables

@@ -299,16 +326,7 @@

The L prefix is not implemented as a distinct family of primitives. In the command language it selects the mirror view. - In the API the same effect is provided by explicit left primitives such as ls() and lsn(n), or by allowing a signed n on machines that support step left. -

- -

Feature symbols and primitive availability

- -

- A TM is constructed with feature symbols that select which primitive families are present. - With no feature symbols, the result is a non-destructive step right machine with no indexing. - Enabling step left adds left motion primitives (or signed n support) and mirror view semantics in the command language. - Indexing is an independent feature: when enabled, index based query and cue forms become legal and corresponding primitives become available. + In the API the same effect is provided by explicit left primitives such as Ls() and Lsn(n), or by allowing a signed n on machines that support step left.

Navigation primitives

@@ -331,14 +349,14 @@

    -
  • ls() steps to the left neighbor. (Command form: Ls.)
  • -
  • lsn(n) steps left n times. (Command form: Lsn(n).)
  • -
  • lsR() cues the head to leftmost. (Command form: LsR.)
  • +
  • Ls() steps to the left neighbor. (Command form: Ls.)
  • +
  • Lsn(n) steps left n times. (Command form: Lsn(n).)
  • +
  • LsR() cues the head to leftmost. (Command form: LsR.)

Note the correspondence: sR cues rightmost in the base view, and LsR cues leftmost of that same underlying tape. - The primitives sR() and lsR() are optimized cues. + The primitives sR() and LsR() are optimized cues.

Input and output primitives

@@ -365,7 +383,7 @@
  • wn(list) writes a list of values.
  • -

    Destructive Primitives

    +

    Destructive Primitives

    Machines configured with the SO (Solitary) entanglement approach may expose primitives that modify the tape structure. @@ -376,17 +394,6 @@ Note: Not all container types support all destructive operations. For example, ARR (Fixed Array) does not support deletion or insertion, whereas ARRV (Variable Array) does.

    -

    Delete (d)

    -

    - Removes cells from the tape. The head typically lands on the right neighbor of the deleted segment. -

    -
      -
    • d(): Deletes the current cell.
    • -
    • dn(n): Deletes n cells starting from current.
    • -
    • dR(): Deletes from current to Rightmost (inclusive).
    • -
    • dL(): Deletes from current to Leftmost (inclusive).
    • -
    -

    Delete Neighbor (esd)

    A compound-style primitive that deletes a neighbor without moving the active head. @@ -394,14 +401,21 @@

    • esd(): Deletes the immediate right neighbor. Guard: Requires not qR().
    • -
    • esdn(n): Deletes n right neighbors.
    • -
    • Lesd(): Deletes the immediate left neighbor. Guard: Requires not qL().
    • +
    • eLsd(): Deletes the immediate left neighbor. Guard: Requires not LqR().
    • +
    + +

    Delete to Bound (dR)

    +
      +
    • dR(): Deletes from current to Rightmost (inclusive). Head steps left. Guard: Requires not LqR().
    • +
    • LdR(): Deletes from current to Leftmost (inclusive). Head lands on right neighbor. Guard: Requires not qR().
    -

    Insert/Append (a)

    +

    Insert/Append (esa)

      -
    • a(v): Inserts value v at the current head position. The old current cell shifts right.
    • -
    • an(list): Splices a list of values at the current position.
    • +
    • esa(v): Appends value v after the current head position.
    • +
    • eLsa(v): Appends value v before the current head position.
    • +
    • aR(v): Appends value v to the Rightmost end of the tape.
    • +
    • LaR(v): Appends value v to the Leftmost end of the tape.

    Query primitives

    @@ -409,28 +423,23 @@

    Query primitives are built from the q command. On the step right only machine, the primitive set covers the boolean query forms. - When indexing is enabled as an additional feature, index valued query forms become available.

    • qR() returns whether the head is on the selected view rightmost cell. (Command form: qR.)
    • +
    • qnR() returns number of steps to rightmost cell. (Command form: qnR.)

    - If indexing is enabled, the API also exposes index query primitives. - These correspond to the I arg descriptor in the command language. + Mirror view query forms follow the same rule in the command language. + For example, LqR tests the leftmost of the underlying tape.

    - +
      -
    • qI() returns the current head index. (Command form: qI.)
    • -
    • qIR() returns the index of the selected view rightmost cell. (Command form: qIR.)
    • +
    • LqR() returns whether the head is on the leftmost cell. (Command form: LqR.)
    • +
    • LqnR() returns number of steps to leftmost cell. (Command form: LqnR.)
    -

    - Mirror view query forms follow the same rule in the command language. - For example, LqR tests the leftmost of the underlying tape, and LqIR returns its index, typically zero. -

    -

    Entanglement primitives

    @@ -463,7 +472,7 @@

    - In order to maintain these properties, a TM uses inclusive bounds for intervals, including intervals of cells, and intervals of indexes. + In order to maintain these properties, a TM uses inclusive bounds for intervals, including intervals of cells.

    Contract with the programmer

    @@ -550,7 +559,7 @@

    The Region Machine implements the standard TM interface but constrains movement based on the boundary heads.

    -
    • Step (s): The Active Head performs a step only if it is not currently on the Right Boundary cell.
      • s() requires not qR().
    • Step Left (ls): The Active Head performs a left step only if it is not currently on the Left Boundary cell.
      • ls() requires not qL().
    • Query Bounds (qR, qL):
      • qR() returns true if the Active Head is on the same cell as the Right Boundary Head.
      • qL() returns true if the Active Head is on the same cell as the Left Boundary Head.
    • Cue Bounds (sR, lsR):
      • sR() moves the Active Head to the cell occupied by the Right Boundary Head.
      • lsR() moves the Active Head to the cell occupied by the Left Boundary Head.
    +
    • Step (s): The Active Head performs a step only if it is not currently on the Right Boundary cell.
      • s() requires not qR().
    • Step Left (Ls): The Active Head performs a left step only if it is not currently on the Left Boundary cell.
      • Ls() requires not LqR().
    • Query Bounds (qR, LqR):
      • qR() returns true if the Active Head is on the same cell as the Right Boundary Head.
      • LqR() returns true if the Active Head is on the same cell as the Left Boundary Head.
    • Cue Bounds (sR, LsR):
      • sR() moves the Active Head to the cell occupied by the Right Boundary Head.
      • LsR() moves the Active Head to the cell occupied by the Left Boundary Head.

    Boundary Management

    @@ -612,70 +621,6 @@

    Because the TMS implements the TM interface, it can be passed directly to these algorithms. However, if the status is Empty, the first operation attempted by the algorithm (usually r()) will trigger a "second order" error, alerting the programmer that they neglected the guard.

    -

    Machine Naming Convention

    - -

    - Concrete Tape Machine classes follow a strict naming grammar. This grammar acts as a feature descriptor, allowing the programmer to select a machine by constructing its name. -

    - -

    - The name is composed of three feature segments: the Container Type, the Step Direction, and the Entanglement Approach. -

    - -

    grammar

    - - class_name :: TM [ _container ] [ _direction ] [ _entanglement ] - container :: ARR | ARRV | GR | GLR | SET | MAP | MAPK | MAPV - | ASCII | UTF8 | BCD - direction :: SR | SL - entanglement :: ND | SO | EA - - -

    - Segments are separated by underscores. The default configuration for a segment is used if that segment is omitted. - The default machine is TM_ARR_SR_ND (Fixed Array, Step Right, Non-Destructive). -

    - -

    container

    -
      -
    • ARR Array Fixed (Default). A contiguous sequence of fixed length (e.g., Python List, C Array).
    • -
    • ARRV Array Variable. A contiguous sequence that may resize (e.g., Vector).
    • -
    • GR Graph Right. A node-based sequence with a single right neighbor (Singly Linked List).
    • -
    • GLR Graph Left Right. A node-based sequence with left and right neighbors (Doubly Linked List).
    • -
    • SET Set. Iteration over the elements of a Set.
    • -
    • MAP Map. Iteration over the items (Key-Value pairs) of a Map.
    • -
    • MAPK Map Keys. Iteration over the keys of a Map.
    • -
    • MAPV Map Values. Iteration over the values of a Map.
    • -
    • ASCII Ascii. A sequence of 1-byte characters.
    • -
    • UTF8 Utf8. A sequence of variable-width Unicode characters.
    • -
    • BCD Bcd. A sequence of Binary Coded Decimal values.
    • -
    - -

    direction

    -
      -
    • SR Step Right (Default). The machine head can only be moved to the right.
    • -
    • SL Step Left. The machine is bidirectional, supports stepping either right or left.
    • -
    - -

    entanglement

    -
      -
    • ND Non-Destructive (Default). Safe for entanglement.
    • -
    • SO Solitary. Exclusive ownership; supports destructive ops.
    • -
    • EA Entanglement Accounting. Shared access guarded by a catalog.
    • -
    - -

    Abstract and Traversal Machines

    -

    - The naming convention extends to Abstract and Traversal machines using specific prefixes. -

    -
      -
    • TMA TM Abstract. Virtual tapes computed over state. -
      Example: TMA_Natural_Number (Iterates 0, 1, 2...).
    • -
    • TMT TM Traversal. Algorithmic traversals over non-linear structures. -
      Example: TMT_Tree_DepthFirst (Linearizes a tree via stack/recursion).
    • -
    - - diff --git a/document/TM_reference.html b/document/TM_reference.html deleted file mode 100644 index 83b3073..0000000 --- a/document/TM_reference.html +++ /dev/null @@ -1,283 +0,0 @@ - - - - - TM Reference - - - - - - - - - - - - - - - - - - - - -

    Machine names

    - -

    Concrete first order machines

    - - - TM_<CONTAINER>_<TRAVERSAL>_<ENTANGLEMENT> - - -

    CONTAINER

    - -
      -
    • ARRAY Python array of cell payload pointers (default)
    • -
    • BCD reserved. Planned view over a bit vector that groups bits into 4 bit digits
    • -
    - -

    TRAVERSAL

    - -
      -
    • SR step right only
    • -
    • SL step left and right, via mirror view operations
    • -
    - -

    ENTANGLEMENT

    - -
      -
    • ND non destructive
    • -
    • SO solitary
    • -
    • EA entanglement accounting
    • -
    - -

    Abstract machines

    - - - TMA_<ABSTRACT_NAME> - - -

    - Abstract machines do not bind to a data object. - They are placeholders for virtual tapes and for higher order machinery. -

    - -

    Command language grammar

    - -

    Command groups

    - - - command_group := [view] command {arg} - view := "L" - command := "e" | "q" | "r" | "s" | "w" | "d" | "a" - arg := "R" | n - - -

    - A method name is a sequence of command groups. - Each command letter begins a new group. - Argument descriptors attach to the command group that precedes them. -

    - -

    Mirror view mapping

    - -

    - The command language uses L to select mirror view. - The Python API uses explicit left method names. - The mapping is: -

    - -
      -
    • Ls becomes ls()
    • -
    • Lsn(n) becomes lsn(n)
    • -
    • LsR becomes lsR()
    • -
    • Ld becomes ld()
    • -
    • Lesd becomes lesd()
    • -
    - -

    Traversal and repetition

    - -

    - On SR machines, sn(n) expects a non negative integer. - On SL machines, sn(n) accepts a signed integer, where negative counts step left. -

    - -

    Primitive method availability

    - -

    - The second column uses machine name patterns. - The wildcard * stands for any container. -

    - -

    Navigation

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    MethodAvailable on
    s()TM_*_SR_* ,TM_*_SL_*
    sn(n)TM_*_SR_* ,TM_*_SL_*
    sR()TM_*_SR_* ,TM_*_SL_*
    ls()TM_*_SL_*
    lsn(n)TM_*_SL_*
    lsR()TM_*_SL_*
    - -

    Read and write

    - - - - - - - - - - - - - - - - - - -
    MethodAvailable on
    r()TM_*_SR_* ,TM_*_SL_*
    w(v)TM_*_SR_* ,TM_*_SL_*
    - -

    Queries

    - - - - - - - - - - - - - - - - - - -
    MethodAvailable on
    qR()TM_*_SR_* ,TM_*_SL_*
    lqR() mirror rightmostTM_*_SL_*
    - -

    Entanglement

    - - - - - - - - - - - - - - -
    MethodAvailable on
    e()TM_*_*_ND ,TM_*_*_EA
    - -

    Structural mutation

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    MethodAvailable on
    d() delete currentTM_*_*_SO ,TM_*_*_EA
    dn(n) delete current repeatedTM_*_*_SO ,TM_*_*_EA
    dR() cue delete to rightmostTM_*_*_SO ,TM_*_*_EA
    ld() mirror delete currentTM_*_SL_SO ,TM_*_SL_EA
    ldn(n) mirror delete repeatedTM_*_SL_SO ,TM_*_SL_EA
    ldR() cue delete to leftmostTM_*_SL_SO ,TM_*_SL_EA
    esd() entangle, step, delete neighborTM_*_*_EA
    esdn(n) repeated neighbor deleteTM_*_*_EA
    esdR() cue neighbor delete to rightmostTM_*_*_EA
    lesd() mirror neighbor deleteTM_*_SL_EA
    a(v) insert one valueTM_*_*_SO ,TM_*_*_EA
    an(list) insert list valuesTM_*_*_SO ,TM_*_*_EA
    - - - - -
    - - diff --git a/document/TM_sav.html b/document/TM_sav.html deleted file mode 100644 index 13555e3..0000000 --- a/document/TM_sav.html +++ /dev/null @@ -1,681 +0,0 @@ - - - - - Tape Machine - - - - - - - - - - - - -

    Introduction

    - -

    - A Tape Machine (TM) is an abstract mechanism for manipulating data found in sequences. Such sequences include lists, arrays, sets (given an ordering function), and maps (also given an ordering function). Also included are linear traversals of more complex structures. The theory underpinning the TM is discussed in the TTCA book. -

    - -

    - Unlike standard arrays (which are stateless) or iterators (which are transient), a TM combines a data substrate with a persistent head. The head maintains positional state, allowing the programmer to navigate, read, and write tape cells. -

    - -

    - Thus a TM packages both data, and all pointers into that data, within one structure. -

    - -

    - A TM can have a concrete tape or a virtual tape. A concrete tape is backed by a container. A virtual tape presents the same TM interface, but its cells and motion are implemented by functions over some internal state. For example, an abstract Counting Number tape machine can use a big integer as its state and implement stepping and reading over that state, instead of traversing an array of numbers. -

    - -

    - A defining invariant of all Tape Machines is that cell contents are cargo. The TM reads and writes cell payload, but it does not interpret that payload as control. The decisions are made above the TM, by the programmer’s algorithm. -

    - -

    - A TM is constructed with a set of feature symbols that select which parts of the interface are available. When no feature symbols are supplied, the result is a non-destructive step right machine with no indexing. Feature symbols can enable step left behavior (via the mirror view), enable random access indexing functions, and accounting for a shared tape, among other things. -

    - -

    - A first order TM is defined by a single invariant: the head is always on a valid cell. This invariant makes the primitive interface total: every move, read, write, and query has a clean, well defined meaning, and caller code stays free of scattered end case tests. -

    - -

    - If an operation were permitted to remove the last remaining cell of a tape, said first order invariant would be broken and the interface would stop being total. A working TM that supported such a deletion would need status logic that represents the empty state. That status logic would either be embedded inside the TM operations as edge handling, or be represented explicitly as a separate status machine layered above the base TM. Either choice represents a shift in level of analysis being done, and therefore would lead to the construction of a distinct second order tape machine. -

    - -

    - Tape machines that share a tape are said to be entangled. There will be both data and structure hazards among entangled machines. Data hazards have to do with the misuse of locks or other mistakes in cooperation between machines that cause a machine to read the wrong data. Data hazards can lead to incorrectly computed results, but they will not break the machines. In contrast, structure hazards lead to broken machines. The principle structure hazard is that of one entangled TM deleting a cell that another TM has its head on. That orphans the head of that other machine and leads to a violation of the a tape machine head is always on a valid cell invariant. -

    - -

    - We leave the data hazard management to the programmer; however, we provide specific features for avoiding structure hazards. - These are selected at TM construction time. In one approach, no methods are placed on the interface that can destroy tape cells. This supports a non-destructive programming paradigm, so such machines are said to be non-destructive. Without destructive operations, entangled machines simply do not have the ability to break each other. In a second approach, the interface is configured so there are no functions for entangling machines in the first place. Each solitary machine can safely perform destructive operations because no other machine shares its tape. As a third approach, each group of entangled machines shares a catalog listing all machines in the group. Caller code can guard operations by querying whether a planned operation is safe before attempting it. This third strategy is called entanglement accounting. During the time of execution of the guard and operation, each tape machine must be able to lockout others from access to the catalog. Yet another approach is for the programmer, compiler, or external function to prove code is safe, which is the same as proving that guard code is not needed. An alternative is to use a compiler that only produces correct code in the first place. This is the approach of correct by construction. -

    - -

    Command language

    - -

    - The command language is not used directly, rather it describes the letter patterns used to form TM interface function names. - Such an approach can be found in LISP language list access function names, and its extension is described in the paper "Towards a Better Understanding of CAR, CDR, CADR and the Others". -

    - -

    - The actual function names found on TM interfaces are listed in later sections of this guide. The ultimate authority is the source code itself. Later we can add a compiler for creating new functions based on this language. Such a compiler would be a function that adds functions to a TM interface. -

    - -

    - A TM is constructed with a set of feature symbols that select which parts of the language are available. - When no feature symbols are supplied, the result is a non-destructive step right machine with no indexing. - Feature symbols can enable step left behavior (via the mirror view) and can independently enable indexing commands. -

    - - -

    For the non-destructive step right machine

    - -

    grammar

    - - statement :: ( command [arg]* )+ - command :: e | q | r | s | w - arg :: R | n - - -

    statement

    -

    - A statement is parsed left to right. Each command letter begins a new command group. All following arg descriptors attach to that command until the next command letter appears. There are no spaces. Arguments are given to the resulting function in the order that the command and its descriptors require them. -

    - -

    - Accordingly, a function name such as snr(i) denotes two command groups: - sn(i) steps right i times, then r copies out the current cell. -

    - -

    command

    -
      -
    • e entangle
    • -
    • q query
    • -
    • r read
    • -
    • s step
    • -
    • w write
    • -
    - -

    - Two or more machines are entangled when they share one tape. - Entangle differs from clone because the tape is shared rather than copied. - What is duplicated is the head state, so entangled heads move independently. - A machine produced by e begins with its head on the same cell as the machine it was created from. -

    - -

    - The query command, q, reports head state. - With no arg descriptor it returns a boolean value. - With an R arg descriptor it returns true iff the head is on the rightmost cell. With an I arg descriptor it returns an index. -

    - -

    - TM uses a guard approach for end cases. Query commands appear in control flow so caller code can select the guards it needs and handle end cases explicitly. - When guards are unnecessary, caller code can omit them. -

    - -

    - The r and w commands copy values to and from the current cell. - As of the time of this writing they are cell local operations, so direction does not enter. -

    - -

    - The s step command moves the head to the right neighbor cell. - When s is given an n arg descriptor, it performs n right steps. - On a step right only machine, n must be positive. -

    - -

    arg

    -
      -
    • n n
    • -
    • R Rightmost
    • -
    - -

    - The n arg descriptor supplies a repetition count. -

    - -

    - The R arg descriptor focuses the command on the rightmost cell. - For qR, the result is true iff the head is on rightmost. - For sR, the effect is to cue the head to rightmost. -

    - -

    Examples

    - -

    Relative head movement

    - - s ; step to right neighbor - sn(1) ; step to right neighbor - sn(2) ; step to right neighbor twice - - -

    Absolute head movement

    - - sR ; cue the head to rightmost - - -

    Query

    - - qR ; true iff head is on rightmost - - -

    Copying to and from tape cells and python variables

    - - r ; copies cell contents to the LHS of an assignment - w(v) ; copies v into the cell - - - -

    For the non-destructive machine that has step left

    - -

    - The step right grammar extends to left going behavior by introducing a mirror view of a machine. - In the mirror view, every rightward operation corresponds to the base machine’s leftward operation, so new command letters are unnecessary. - What is rightmost in the base view becomes leftmost in the mirror view, and vice versa. -

    - -

    - In this extended grammar, the L prefix selects the mirror view for the command group that follows it. - L affects direction sensitive operations such as stepping, moving to rightmost, and scans. - Today r and w are cell local, so L does not change their behavior. -

    - -

    - Step left support does not imply index space. - A machine can support L while still omitting index operations. - When index space is enabled as an additional feature, the I arg descriptor becomes available and index based cue and query forms become legal. - When L is available, n can also be negative, with the sign selecting the direction in the base view. -

    - -

    grammar

    - - statement :: ( [machine] command [arg]* )+ - machine :: L - command :: e | q | r | s | w - arg :: R | I | n - - -

    - Index space, as defined in the TTCA book, is a natural number sequence machine that walks the tape of a base machine and establishes a one to one correspondence between natural numbers and tape cells. - That correspondence belongs to the tape and stays fixed when we change the view. - For example, consider a tape with cells [c_0 ,c_1 ,c_2 ,c_3 ,c_4], where c_4 is rightmost and has index 4. - In the mirror view we write the same cells as [c_4 ,c_3 ,c_2 ,c_1 ,c_0]. - In the mirror view c_4 sits at the left edge, and it still has index 4. - A right step from c_4 in the mirror view lands on c_3, which matches a left step from c_4 in the base view. -

    - -

    Examples

    - -

    - In these examples, the comments discuss what happens on the base machine. Effects in the mirror view match the same command without the L prefix. -

    - -

    Relative head movement

    - - Ls ; step to left neighbor - Lsn(2) ; step to left neighbor twice - sn(-2) ; step to left neighbor twice - sn(2) ; step to right neighbor twice - - -

    Head movement relative to leftmost

    - - sI(0) ; cue the head to the leftmost cell by index - sI(3) ; cue the head to tape[3] - - -

    - LsI(k) and sI(k) cue the head to the same indexed cell. - L flips direction and the meaning of R, not the index to cell correspondence. - Thus LsI(0) cues the cell with index zero, which is rightmost in the mirror view and leftmost in the base view. -

    - -

    Absolute head movement

    - - LsR ; cue the head to leftmost - sR ; cue the head to rightmost - - -

    - Without code optimization LsR will be faster than sI(0), because sI requires passing and processing an argument. -

    - -

    Query

    - - LqR ; head is on leftmost - qR ; head is on rightmost - qI ; index of the head - qIR ; index of rightmost - LqIR ; index of leftmost, typically zero - - -

    - The I arg descriptor causes q to return an index. - By default q returns a boolean value. - In other commands, an I arg descriptor indicates that an index argument is supplied. -

    - -

    - The R arg descriptor focuses the command on the selected view rightmost cell. - For qR, the result is true iff the head is on rightmost. - For qIR, the result is the index of rightmost. - Under L, that rightmost cell is the base view leftmost cell, so LqIR returns the index of leftmost, typically zero. -

    - -

    Copying to and from tape cells and python variables

    - - r ; copies cell contents to the LHS of an assignment - w(v) ; copies v into the cell - - -

    - The current r and w are cell local and are unaffected by L. - If we later support list forms or repetition forms for copy, L will affect the scan direction for those operations. -

    - -

    TM interface functions

    - -

    - This section lists the concrete methods exposed by the Python/C implementation. - These methods implement a selected subset of the command grammar. - The grammar defines a command language, while the primitive set defines the operations the library exposes directly. - Later sections can introduce a compile layer that accepts additional command combinations. -

    - -

    - The L prefix is not implemented as a distinct family of primitives. - In the command language it selects the mirror view. - In the API the same effect is provided by explicit left primitives such as ls() and lsn(n), or by allowing a signed n on machines that support step left. -

    - -

    Feature symbols and primitive availability

    - -

    - A TM is constructed with feature symbols that select which primitive families are present. - With no feature symbols, the result is a non-destructive step right machine with no indexing. - Enabling step left adds left motion primitives (or signed n support) and mirror view semantics in the command language. - Indexing is an independent feature: when enabled, index based query and cue forms become legal and corresponding primitives become available. -

    - -

    Navigation primitives

    - -

    - Navigation primitives implement the s command with the argument forms ε, n, and R. - On a step right only machine, n is constrained to positive values. - On a machine that supports step left, n can be negative, with the sign selecting direction in the base view. -

    - -
      -
    • s() steps to the right neighbor. (Command form: s.)
    • -
    • sn(n) steps by n cells. On a step right only machine, n must be positive. (Command form: sn(n).)
    • -
    • sR() cues the head to the selected view rightmost cell. (Command form: sR.)
    • -
    - -

    - If step left is enabled, left motion is available either as explicit primitives, or via negative n on sn(n), depending on the configured interface. - When explicit left primitives exist, they correspond to the mirror view command forms. -

    - -
      -
    • ls() steps to the left neighbor. (Command form: Ls.)
    • -
    • lsn(n) steps left n times. (Command form: Lsn(n).)
    • -
    • lsR() cues the head to leftmost. (Command form: LsR.)
    • -
    - -

    - Note the correspondence: sR cues rightmost in the base view, and LsR cues leftmost of that same underlying tape. - The primitives sR() and lsR() are optimized cues. -

    - -

    Input and output primitives

    - -

    - The I/O primitives implement r and w(value). - In the command language, r reads the current cell payload, and w(v) writes a payload to the current cell. - As of the time of this writing, these operations are cell local, so mirror view does not change their behavior. -

    - -
      -
    • r() reads the current cell.
    • -
    • w(v) writes v to the current cell.
    • -
    - -

    - Bulk forms can exist in the API, but they are not represented in the current command grammar. - They are library level conveniences built on top of repeated primitive behavior. - If bulk copy forms become part of the command grammar later, mirror view will affect scan direction for those operations. -

    - -
      -
    • rn(n) reads n cells.
    • -
    • wn(list) writes a list of values.
    • -
    - -

    Destructive Primitives

    - -

    - Machines configured with the SO (Solitary) entanglement approach may expose primitives that modify the tape structure. - These are distinct from w (which modifies cell content) because they change the cell count or sequence. -

    - -

    - Note: Not all container types support all destructive operations. For example, ARR (Fixed Array) does not support deletion or insertion, whereas ARRV (Variable Array) does. -

    - -

    Delete (d)

    -

    - Removes cells from the tape. The head typically lands on the right neighbor of the deleted segment. -

    -
      -
    • d(): Deletes the current cell.
    • -
    • dn(n): Deletes n cells starting from current.
    • -
    • dR(): Deletes from current to Rightmost (inclusive).
    • -
    • dL(): Deletes from current to Leftmost (inclusive).
    • -
    - -

    Delete Neighbor (esd)

    -

    - A compound-style primitive that deletes a neighbor without moving the active head. - Mnemonic: Entangle-Step-Delete (conceptually acts on the neighbor). -

    -
      -
    • esd(): Deletes the immediate right neighbor. Guard: Requires not qR().
    • -
    • esdn(n): Deletes n right neighbors.
    • -
    • Lesd(): Deletes the immediate left neighbor. Guard: Requires not qL().
    • -
    - -

    Insert/Append (a)

    -
      -
    • a(v): Inserts value v at the current head position. The old current cell shifts right.
    • -
    • an(list): Splices a list of values at the current position.
    • -
    - -

    Query primitives

    - -

    - Query primitives are built from the q command. - On the step right only machine, the primitive set covers the boolean query forms. - When indexing is enabled as an additional feature, index valued query forms become available. -

    - -
      -
    • qR() returns whether the head is on the selected view rightmost cell. (Command form: qR.)
    • -
    - -

    - If indexing is enabled, the API also exposes index query primitives. - These correspond to the I arg descriptor in the command language. -

    - -
      -
    • qI() returns the current head index. (Command form: qI.)
    • -
    • qIR() returns the index of the selected view rightmost cell. (Command form: qIR.)
    • -
    - -

    - Mirror view query forms follow the same rule in the command language. - For example, LqR tests the leftmost of the underlying tape, and LqIR returns its index, typically zero. -

    - -

    Entanglement primitives

    - -

    - Entanglement primitives implement the e command. - The entangled machine shares the tape with the original machine and and initially have their head on the same cell. - In entanglement accounting configurations, entangled machines also share the group catalog used by guard predicates. -

    - -
      -
    • e() returns a new entangled machine sharing the same tape. (Command form: e.)
    • -
    - -

    - Combined command forms such as es are legal in the grammar, but they are not required as primitives. - The library can expose such combinations as convenience calls, or generate them through a compile layer. - The core model remains that a statement is a sequence of commands applied to a selected view. -

    - -

    Usage

    - -

    First order TM properties

    - -

    - For a first order TM these properties are always true. -

    - -
      -
    1. The head is always on a valid cell.
    2. -
    3. All cells return a value when read.
    4. -
    - -

    - In order to maintain these properties, a TM uses inclusive bounds for intervals, including intervals of cells, and intervals of indexes. -

    - -

    Contract with the programmer

    - -

    - Some first order TM types rely upon the caller to maintain a contract. - Such machines typically have debug variants that add contract checks. - For some machines, breaking the contract limits compiler optimization. - For other machines, breaking the contract causes program bugs. -

    - -

    - Contract: -

    - -
      -
    1. When there is a right bound, the caller guarantees that he will never command the machine to step beyond the rightmost cell.
    2. -
    3. When there is a left bound, the caller guarantees that he will never command the machine to step left of the leftmost cell.
    4. -
    - -

    - When traversing a tape, the contract is fulfilled by a First Rest pattern. -

    - -

    First Rest pattern with initialization

    - - - # Pattern 1: First Rest (Initialize with First) - # Useful when the accumulator starts with the first value. - total = tm.r() # Process First - while not tm.qR(): # Guard: Is there a Rest? - tm.s() # Step (Protected) - total += tm.r() # Process Next - - -

    - Here tm.qR() queries whether the head is on the selected view rightmost cell. - It guards the step in the loop. - No redundant tests are done, and the loop ends without stepping off the tape. -

    - -

    First Rest pattern without initialization

    - -

    - Sometimes the accumulator is initialized to an identity value (such as zero) before the loop starts. - In that form, the loop and a half structure is natural. -

    - - - # Conceptual "do" loop - do: - total += tm.r() # Always process the current cell - if tm.qR() break # protects increment from spilling over - tm.s() # Step only when not at the end - - -

    - Python has no do statement, so the same logic is written explicitly: -

    - - - # Python implementation - while True: - total += tm.r() - if tm.qR(): break - tm.s() - - -

    - The middle test tm.qR() guards tm.s(), so the machine never steps beyond rightmost. -

    - -

    Region Machine

    - -

    A Region Machine is a composite structure built from three entangled tape machines. It enforces the invariant that the active head remains within a specified closed interval of the tape.

    - -

    Structure

    - -

    The Region Machine consists of:

    • Left Boundary Machine: A TM marking the leftmost valid cell of the region.
    • Right Boundary Machine: A TM marking the rightmost valid cell of the region.
    • Active Machine: The TM interface exposed to the user for navigation and I/O.
    - -

    Because the Region Machine relies on the First Order invariant (head always on a valid cell), a region cannot be empty. The minimum region size is one cell, where the Left Boundary, Right Boundary, and Active Head all occupy the same cell.

    - -

    Behavior

    - -

    The Region Machine implements the standard TM interface but constrains movement based on the boundary heads.

    - -
    • Step (s): The Active Head performs a step only if it is not currently on the Right Boundary cell.
      • s() requires not qR().
    • Step Left (ls): The Active Head performs a left step only if it is not currently on the Left Boundary cell.
      • ls() requires not qL().
    • Query Bounds (qR, qL):
      • qR() returns true if the Active Head is on the same cell as the Right Boundary Head.
      • qL() returns true if the Active Head is on the same cell as the Left Boundary Head.
    • Cue Bounds (sR, lsR):
      • sR() moves the Active Head to the cell occupied by the Right Boundary Head.
      • lsR() moves the Active Head to the cell occupied by the Left Boundary Head.
    - -

    Boundary Management

    - -

    The boundaries of a region are themselves Tape Machines. This allows the region to expand or contract dynamically. Moving a boundary head changes the effective range of the Active Machine immediately.

    - -

    Safety Constraint: A boundary head cannot step past the other boundary head. The Left Boundary must always be to the left of or on the same cell as the Right Boundary. Furthermore, the Active Head must not be orphaned by boundary movement. If the Right Boundary steps left past the Active Head, the Active Head is no longer valid. Therefore, boundary contraction requires checking or moving the Active Head to maintain the invariant.

    - -

    TM Workspace functions

    - -

    The TM_workspace namespace contains higher-level functions that coordinate multiple machines. These functions are not part of the core TM interface but operate on TMs to implement common algorithms.

    - -

    Tandem operations

    - -

    Tandem operations drive multiple machines simultaneously. They are useful for copying, comparing, or parallel processing.

    - -
    • step_tandem(tm1, tm2): Steps both machines to their respective right neighbors. Requires that neither machine is at its rightmost bound.
    • zip_apply(f, tm1, tm2): Applies function f to the values read from tm1 and tm2, then steps both.
    - -

    Predicates

    - -

    Predicates test relationships between entangled machines.

    - -
    • head_on_same_cell(tm1, tm2): Returns true if the heads of two entangled machines are on the same cell. This is the fundamental primitive used to implement qR in Region Machines.
    - - - - - -

    Second Order Machine (TMS)

    - -

    A Second Order Machine, or TMS (Tape Machine Status), is a wrapper that manages the lifecycle of a First Order Tape Machine. It introduces the concept of status to handle conditions that violate First Order invariants, specifically the absence of valid cells (emptiness).

    - -

    Status definitions

    - -

    The TMS manages a state machine where the states are called statuses to distinguish them from the internal state of the tape or head. The current status determines which interface functions are available to the programmer.

    - -
    • Active: The machine contains cells. The underlying First Order TM is valid. All standard TM navigation and I/O commands function normally.
    • Empty: The machine contains no cells. There is no tape and no head position. First Order operations like r or s are invalid and will raise errors if called. Only status-query and insertion operations are available.
    • Parked: The machine contains cells, but the head is effectively "lifted" from the tape. The head is not on any valid cell. This status is often used during initialization or after a search fails to find a target.
    - -

    Dynamic interface dispatch

    - -

    The TMS implementation uses dynamic dispatch (or mixin replacement) to enforce status constraints. When the status changes, the interface functions are swapped.

    - -

    For example, in the Empty status, the r() function is mapped to an error handler: Error: Attempted to read from an empty machine. This prevents the programmer from accidentally running First Order logic on a machine that does not satisfy the First Order invariant.

    - -

    Transitions

    - -

    Status changes occur when operations alter the cell count to or from zero, or when the head is explicitly parked or unparked.

    - -

    Promotion (Empty to Active)

    When a TMS is Empty, calling an insertion function (e.g., append(v)) creates the first cell. The status transitions to Active. The interface is updated to expose standard TM behaviors. The head is placed on the newly created cell.

    - -

    Demotion (Active to Empty)

    If a deletion operation removes the last remaining cell of an Active machine, the First Order invariant is broken. The TMS detects this event, destroys the underlying First Order TM, and transitions the status to Empty. The interface is updated to the restricted Empty set.

    - -

    Usage with algorithms

    - -

    Algorithms requiring a First Order TM (such as foreach loops or First Rest patterns) must effectively be guarded by a status check.

    - - if tms.is_active(): # Safe to treat as a First Order TM run_algorithm(tms) else: # Handle empty case pass - -

    Because the TMS implements the TM interface, it can be passed directly to these algorithms. However, if the status is Empty, the first operation attempted by the algorithm (usually r()) will trigger a "second order" error, alerting the programmer that they neglected the guard.

    - -

    Machine Naming Convention

    - -

    - Concrete Tape Machine classes follow a strict naming grammar. This grammar acts as a feature descriptor, allowing the programmer to select a machine by constructing its name. -

    - -

    - The name is composed of three feature segments: the Container Type, the Step Direction, and the Entanglement Approach. -

    - -

    grammar

    - - class_name :: TM [ _container ] [ _direction ] [ _entanglement ] - container :: ARR | ARRV | GR | GLR | SET | MAP | MAPK | MAPV - | ASCII | UTF8 | BCD - direction :: SR | SL - entanglement :: ND | SO | EA - - -

    - Segments are separated by underscores. The default configuration for a segment is used if that segment is omitted. - The default machine is TM_ARR_SR_ND (Fixed Array, Step Right, Non-Destructive). -

    - -

    container

    -
      -
    • ARR Array Fixed (Default). A contiguous sequence of fixed length (e.g., Python List, C Array).
    • -
    • ARRV Array Variable. A contiguous sequence that may resize (e.g., Vector).
    • -
    • GR Graph Right. A node-based sequence with a single right neighbor (Singly Linked List).
    • -
    • GLR Graph Left Right. A node-based sequence with left and right neighbors (Doubly Linked List).
    • -
    • SET Set. Iteration over the elements of a Set.
    • -
    • MAP Map. Iteration over the items (Key-Value pairs) of a Map.
    • -
    • MAPK Map Keys. Iteration over the keys of a Map.
    • -
    • MAPV Map Values. Iteration over the values of a Map.
    • -
    • ASCII Ascii. A sequence of 1-byte characters.
    • -
    • UTF8 Utf8. A sequence of variable-width Unicode characters.
    • -
    • BCD Bcd. A sequence of Binary Coded Decimal values.
    • -
    - -

    direction

    -
      -
    • SR Step Right (Default). The machine head can only be moved to the right.
    • -
    • SL Step Left. The machine is bidirectional, supports stepping either right or left.
    • -
    - -

    entanglement

    -
      -
    • ND Non-Destructive (Default). Safe for entanglement.
    • -
    • SO Solitary. Exclusive ownership; supports destructive ops.
    • -
    • EA Entanglement Accounting. Shared access guarded by a catalog.
    • -
    - -

    Abstract and Traversal Machines

    -

    - The naming convention extends to Abstract and Traversal machines using specific prefixes. -

    -
      -
    • TMA TM Abstract. Virtual tapes computed over state. -
      Example: TMA_Natural_Number (Iterates 0, 1, 2...).
    • -
    • TMT TM Traversal. Algorithmic traversals over non-linear structures. -
      Example: TMT_Tree_DepthFirst (Linearizes a tree via stack/recursion).
    • -
    - - -
    - - diff --git a/document/TM_user.html b/document/TM_user.html deleted file mode 100644 index 62993d5..0000000 --- a/document/TM_user.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - TM User Guide - - - - - - - - - - - - - - - - - - - - -

    Introduction

    - -

    - A Tape Machine (TM) is an abstract mechanism for manipulating data found in sequences. - Such sequences include lists, arrays, sets (given an ordering function), maps (given an ordering function), and linear traversals of more complex structures. - The theory underpinning the TM is discussed in the TTCA book. -

    - -

    - Unlike standard arrays (which are stateless) or iterators (which are transient), a TM combines a data substrate with a persistent head. - The head maintains positional state, allowing the programmer to navigate, read, and write tape cells. -

    - -

    - A defining invariant of a first order TM is: - the head is always on a valid cell. - This invariant makes the primitive interface total. - Every move, read, write, and query has a clean, well defined meaning, and caller code stays free of scattered end case tests. -

    - -

    Choosing a machine

    - -

    - In the current implementation, you choose a TM by choosing a concrete TM class. - Machine capabilities are encoded in the class name. - Concrete machines require a data object at construction time. - Abstract machines do not require a data object, but they come later. -

    - -

    - The default concrete machine is TM_ARRAY_SR_ND(data_obj). - It treats the data object as a Python array of cell payload pointers. -

    - -

    Machine naming convention

    - -

    - First order concrete machines use this name form: -

    - - - TM_<CONTAINER>_<TRAVERSAL>_<ENTANGLEMENT> - - -

    - Abstract machines (virtual tapes) use: -

    - - - TMA_<ABSTRACT_NAME> - - -

    Field meanings

    - -
      -
    • CONTAINER: the backing data substrate.
    • -
    • TRAVERSAL: which directions the head can move.
    • -
    • ENTANGLEMENT: what sharing and structural mutation rules apply.
    • -
    - -

    Command language

    - -

    - The command language is not used directly. - It describes the letter patterns used to form TM interface method names. - The approach began with LISP, and its extension is described in the paper - "Towards a Better Understanding of CAR, CDR, CADR and the Others". -

    - -

    - A method name is a sequence of command groups. - Parsing is left to right. - Each command letter begins a new group. - Any argument descriptors that follow attach to that group until the next command letter appears. -

    - -

    - Example: snr(i) denotes two groups. - sn(i) steps right i times, then r() reads the current cell. -

    - -

    Core commands

    - -
      -
    • e entangle
    • -
    • q query
    • -
    • r read
    • -
    • s step
    • -
    • w write
    • -
    - -

    Argument descriptors

    - -
      -
    • n repetition count
    • -
    • R selected view rightmost
    • -
    - -

    Mirror view

    - -

    - Some machines support stepping left as well as right. - In the command language, the L prefix selects the mirror view for the command group that follows it. - In the mirror view, rightward operations correspond to leftward operations in the base view. - What is rightmost in the base view becomes leftmost in the mirror view, and vice versa. -

    - -

    - In the Python API, mirror view forms are exposed as explicit left methods, such as ls() for Ls and lsR() for LsR. -

    - -

    Entanglement and safety

    - -

    - Tape machines that share a tape are said to be entangled. - There are both data hazards and control hazards among entangled machines. - Data hazards relate to unexpected writes and reads and can lead to incorrect results. - Control hazards can break machines. - The primary control hazard is one machine deleting a cell that another machine is visiting, which violates - a tape machine head is always on a valid cell. -

    - -

    - Entanglement policy is encoded in the machine name: -

    - -
      -
    • ND non destructive. No structural deletion or insertion exists on the interface, so entangled machines cannot break each other.
    • -
    • SO solitary. The interface has structural mutation, but no entanglement operations exist, so machines do not share tapes.
    • -
    • EA entanglement accounting. Structural mutation and entanglement exist, and caller code uses guard predicates to avoid control hazards.
    • -
    - -

    Usage patterns

    - -

    First Rest pattern with initialization

    - - - # Pattern 1: First Rest (Initialize with First) - # Useful when the accumulator starts with the first value. - total = tm.r() # Process First - while not tm.qR(): # Guard: Is there a Rest? - tm.s() # Step (Protected) - total += tm.r() # Process Next - - -

    First Rest pattern without initialization

    - - - while True: - total += tm.r() - if tm.qR(): break - tm.s() - - -

    Composite machines

    - -

    Region Machine

    - -

    - A Region Machine is a composite built from three entangled tape machines. - It enforces the invariant that the active head stays within a specified closed interval of the tape. -

    - -
      -
    • Left boundary machine: marks the leftmost valid cell of the region.
    • -
    • Right boundary machine: marks the rightmost valid cell of the region.
    • -
    • Active machine: the interface exposed to caller code.
    • -
    - -

    - In the command language, the active head is on the left boundary iff LqR is true in the active view. - In the Python API, that corresponds to an explicit left query helper, or to a predicate that tests whether two entangled heads are on the same cell. -

    - -

    TM workspace functions

    - -

    - The TM_workspace namespace contains higher level functions that coordinate multiple machines. - These functions are not part of the core TM interface. -

    - -

    Second order machine

    - -

    - A second order TM, TMS (Tape Machine Status), is a wrapper that manages the lifecycle of a first order TM. - It introduces explicit status values to represent conditions that violate first order invariants, such as emptiness. -

    - - - - -
    - - -- 2.20.1