/*
TM_module.c
- CPython Extension: Direct List Access + Entanglement Safety
- RT Code Format Compliant
+ CPython Extension: Tape Machine Factory
+ Implements:
+ - TM_SR_ND (Base: Step Right, Non-Destructive)
+ - TM_SR_ND_AR (Feature: Append Right)
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "structmember.h"
-#include <stddef.h> /* For offsetof */
+#include <stddef.h>
/* ========================================================= */
-/* TYPE DEFINITION */
+/* 1. DATA LAYOUT (Shared) */
/* ========================================================= */
typedef struct {
PyObject* weakreflist; /* Required for WeakRefs */
} FastTM;
-/* Forward Declaration */
-static PyObject* FastTM_address(FastTM* self);
-
static void FastTM_dealloc(FastTM* self){
- /* Clear weak references first! */
if( self->weakreflist != NULL ){
PyObject_ClearWeakRefs((PyObject*)self);
}
-
Py_XDECREF(self->tape_obj);
Py_XDECREF(self->peer_list);
Py_TYPE(self)->tp_free((PyObject*)self);
}
-/* Helper: Register self into the peer_list.
- Uses WeakRef so dead machines don't keep the list alive.
-*/
-static int register_entanglement(FastTM* self ,PyObject* existing_peer_list){
+/* Helper: Register Entanglement */
+static int register_entanglement(FastTM* self, PyObject* existing_peer_list){
PyObject* weak_ref = NULL;
-
if( existing_peer_list ){
- /* Join existing entanglement */
self->peer_list = existing_peer_list;
Py_INCREF(self->peer_list);
} else {
- /* Start new entanglement */
self->peer_list = PyList_New(0);
if( !self->peer_list ) return -1;
}
-
- /* Create WeakRef to self */
- weak_ref = PyWeakref_NewRef((PyObject*)self ,NULL);
+ weak_ref = PyWeakref_NewRef((PyObject*)self, NULL);
if( !weak_ref ) return -1;
-
- /* Add to list */
- if( PyList_Append(self->peer_list ,weak_ref) < 0 ){
+ if( PyList_Append(self->peer_list, weak_ref) < 0 ){
Py_DECREF(weak_ref);
return -1;
}
-
Py_DECREF(weak_ref);
return 0;
}
-static int FastTM_init(FastTM* self ,PyObject* arg_tuple ,PyObject* kwd_dict){
- PyObject* input_obj = NULL;
-
- /* Initialize weakref list to NULL */
- self->weakreflist = NULL;
-
- if( !PyArg_ParseTuple(arg_tuple ,"O" ,&input_obj) ) return -1;
-
- if( PyObject_TypeCheck(input_obj ,Py_TYPE(self)) ){
- /* CLONE MODE: Entangle with existing TM */
- FastTM* source_tm = (FastTM*)input_obj;
-
- /* Share Tape */
- self->tape_obj = source_tm->tape_obj;
- Py_INCREF(self->tape_obj);
-
- /* Copy Head */
- self->head = source_tm->head;
-
- /* Register in shared peer list */
- if( register_entanglement(self ,source_tm->peer_list) < 0 ) return -1;
-
- } else {
- /* NEW MODE: Create from Container */
- if( PyList_Check(input_obj) ){
- self->tape_obj = input_obj;
- Py_INCREF(self->tape_obj);
- } else {
- self->tape_obj = PySequence_List(input_obj);
- if( !self->tape_obj ) return -1;
- }
-
- self->head = 0;
-
- /* Start new peer list */
- if( register_entanglement(self ,NULL) < 0 ) return -1;
- }
-
- return 0;
-}
-
/* ========================================================= */
-/* ENTANGLEMENT SAFETY CHECK */
+/* 2. THE MIXIN LIBRARY (Static C Functions) */
/* ========================================================= */
-/*
- Checks if any PEER (other than self) is within the forbidden range.
- Range: [start, start + count)
- Returns 0 if Safe, -1 if Violation (and sets Exception).
-*/
-static int check_safety(FastTM* self ,Py_ssize_t start_idx ,Py_ssize_t count_val){
- Py_ssize_t i;
- Py_ssize_t num_peers;
- PyObject* ref_item;
- PyObject* peer_obj;
- FastTM* peer_tm;
- Py_ssize_t end_idx = start_idx + count_val;
-
- num_peers = PyList_Size(self->peer_list);
-
- for( i = 0; i < num_peers; i++ ){
- ref_item = PyList_GetItem(self->peer_list ,i); /* Borrowed */
- peer_obj = PyWeakref_GetObject(ref_item); /* Borrowed */
-
- /* Skip dead objects or self */
- if( peer_obj == Py_None || peer_obj == (PyObject*)self ) continue;
-
- peer_tm = (FastTM*)peer_obj;
-
- /* Collision Check */
- if( peer_tm->head >= start_idx && peer_tm->head < end_idx ){
- PyErr_SetString(PyExc_RuntimeError ,"Entanglement Violation: Peer is on target cell");
- return -1;
- }
- }
- return 0;
+/* --- Navigation --- */
+static PyObject* mixin_s(FastTM* self){
+ self->head++;
+ Py_RETURN_NONE;
}
-/* ========================================================= */
-/* METHODS */
-/* ========================================================= */
+static PyObject* mixin_sn(FastTM* self, PyObject* arg_tuple){
+ Py_ssize_t n_val;
+ if( !PyArg_ParseTuple(arg_tuple, "n", &n_val) ) return NULL;
+ if (n_val < 0) {
+ PyErr_SetString(PyExc_ValueError, "Machine supports positive steps only.");
+ return NULL;
+ }
+ self->head += n_val;
+ Py_RETURN_NONE;
+}
-/* --- Read --- */
-static PyObject* FastTM_r(FastTM* self){
- PyObject* item_obj = PyList_GetItem(self->tape_obj ,self->head);
+/* --- I/O --- */
+static PyObject* mixin_r(FastTM* self){
+ PyObject* item_obj = PyList_GetItem(self->tape_obj, self->head);
if( !item_obj ) return NULL;
Py_INCREF(item_obj);
return item_obj;
}
-static PyObject* FastTM_rn(FastTM* self ,PyObject* arg_tuple){
+static PyObject* mixin_rn(FastTM* self, PyObject* arg_tuple){
Py_ssize_t n_val;
- if( !PyArg_ParseTuple(arg_tuple ,"n" ,&n_val) ) return NULL;
- return PyList_GetSlice(self->tape_obj ,self->head ,self->head + n_val);
+ if( !PyArg_ParseTuple(arg_tuple, "n", &n_val) ) return NULL;
+ return PyList_GetSlice(self->tape_obj, self->head, self->head + n_val);
}
-/* --- Write --- */
-static PyObject* FastTM_w(FastTM* self ,PyObject* val_obj){
+static PyObject* mixin_w(FastTM* self, PyObject* val_obj){
Py_INCREF(val_obj);
- if( PyList_SetItem(self->tape_obj ,self->head ,val_obj) < 0 ) return NULL;
+ if( PyList_SetItem(self->tape_obj, self->head, val_obj) < 0 ) return NULL;
Py_RETURN_NONE;
}
-static PyObject* FastTM_wn(FastTM* self ,PyObject* arg_tuple){
+static PyObject* mixin_wn(FastTM* self, PyObject* arg_tuple){
PyObject* val_list;
- if( !PyArg_ParseTuple(arg_tuple ,"O" ,&val_list) ) return NULL;
+ if( !PyArg_ParseTuple(arg_tuple, "O", &val_list) ) return NULL;
Py_ssize_t len_val = PySequence_Size(val_list);
- if( PyList_SetSlice(self->tape_obj ,self->head ,self->head + len_val ,val_list) < 0 ) return NULL;
+ if( PyList_SetSlice(self->tape_obj, self->head, self->head + len_val, val_list) < 0 ) return NULL;
Py_RETURN_NONE;
}
-/* --- Step --- */
-static PyObject* FastTM_s(FastTM* self){
- self->head++;
- Py_RETURN_NONE;
-}
+/* --- Features --- */
-static PyObject* FastTM_sn(FastTM* self ,PyObject* arg_tuple){
- Py_ssize_t n_val;
- if( !PyArg_ParseTuple(arg_tuple ,"n" ,&n_val) ) return NULL;
- self->head += n_val;
+/* Feature: aR (Append Right) */
+static PyObject* mixin_aR(FastTM* self, PyObject* val_obj){
+ /* aR typically appends to the END of the tape,
+ regardless of head position, in non-destructive contexts?
+ Or at the head?
+ Standard definition: Append to end of container. */
+ if( PyList_Append(self->tape_obj, val_obj) < 0 ) return NULL;
Py_RETURN_NONE;
}
-static PyObject* FastTM_ls(FastTM* self){
- self->head--;
- Py_RETURN_NONE;
+/* --- Meta --- */
+static PyObject* mixin_e(FastTM* self){
+ /* Factory-aware Entanglement:
+ We call the type's constructor. Since Py_TYPE(self) is the specific
+ machine type (e.g. TM_SR_ND_AR), the clone will inherit the same features. */
+ PyObject* arg_tuple = PyTuple_Pack(1, self);
+ PyObject* new_obj = PyObject_CallObject((PyObject*)Py_TYPE(self), arg_tuple);
+ Py_DECREF(arg_tuple);
+ return new_obj;
}
-static PyObject* FastTM_lsn(FastTM* self ,PyObject* arg_tuple){
- Py_ssize_t n_val;
- if( !PyArg_ParseTuple(arg_tuple ,"n" ,&n_val) ) return NULL;
- self->head -= n_val;
- Py_RETURN_NONE;
+static PyObject* mixin_address(FastTM* self){
+ return PyLong_FromSsize_t(self->head);
}
-/* --- Allocate --- */
-static PyObject* FastTM_aL(FastTM* self ,PyObject* val_obj){
- if( PyList_Insert(self->tape_obj ,0 ,val_obj) < 0 ) return NULL;
- self->head++;
- Py_RETURN_NONE;
+static PyObject* mixin_len(FastTM* self){
+ return PyLong_FromSsize_t(PyList_Size(self->tape_obj));
}
-static PyObject* FastTM_aR(FastTM* self ,PyObject* val_obj){
- if( PyList_Append(self->tape_obj ,val_obj) < 0 ) return NULL;
- Py_RETURN_NONE;
+static PyObject* mixin_rightmost(FastTM* self){
+ Py_ssize_t len = PyList_Size(self->tape_obj);
+ if( self->head >= len - 1 ) Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
}
-/* --- Delete (Safe) --- */
-
-static PyObject* FastTM_d(FastTM* self){
- if( check_safety(self ,self->head ,1) < 0 ) return NULL;
- if( PyList_SetSlice(self->tape_obj ,self->head ,self->head + 1 ,NULL) < 0 ) return NULL;
- Py_RETURN_NONE;
-}
+/* ========================================================= */
+/* 3. TYPE DEFINITIONS */
+/* ========================================================= */
-static PyObject* FastTM_dn(FastTM* self ,PyObject* arg_tuple){
- Py_ssize_t n_val;
- if( !PyArg_ParseTuple(arg_tuple ,"n" ,&n_val) ) return NULL;
+/* Generic Init (Used by all types) */
+static int GenericTM_init(FastTM* self, PyObject* args, PyObject* kwds){
+ PyObject* input_obj = NULL;
+ PyObject* features_obj = NULL; /* Ignored here, consumed by Factory */
- if( check_safety(self ,self->head ,n_val) < 0 ) return NULL;
- if( PyList_SetSlice(self->tape_obj ,self->head ,self->head + n_val ,NULL) < 0 ) return NULL;
- Py_RETURN_NONE;
+ if( !PyArg_ParseTuple(args, "O|O", &input_obj, &features_obj) ) return -1;
+
+ if( PyObject_TypeCheck(input_obj, Py_TYPE(self)) ){
+ /* Clone/Entangle */
+ FastTM* source_tm = (FastTM*)input_obj;
+ self->tape_obj = source_tm->tape_obj;
+ Py_INCREF(self->tape_obj);
+ self->head = source_tm->head;
+ if( register_entanglement(self, source_tm->peer_list) < 0 ) return -1;
+ } else {
+ /* New */
+ if( PyList_Check(input_obj) ){
+ self->tape_obj = input_obj;
+ Py_INCREF(self->tape_obj);
+ } else {
+ self->tape_obj = PySequence_List(input_obj);
+ if( !self->tape_obj ) return -1;
+ }
+ if (PyList_Size(self->tape_obj) == 0) {
+ PyErr_SetString(PyExc_ValueError, "First Order TM cannot be empty.");
+ return -1;
+ }
+ self->head = 0;
+ if( register_entanglement(self, NULL) < 0 ) return -1;
+ }
+ return 0;
}
-static PyObject* FastTM_esd(FastTM* self){
- Py_ssize_t victim = self->head + 1;
- if( check_safety(self ,victim ,1) < 0 ) return NULL;
- if( PyList_SetSlice(self->tape_obj ,victim ,victim + 1 ,NULL) < 0 ) return NULL;
- Py_RETURN_NONE;
-}
+/* --- Type 1: TM_SR_ND (Base) --- */
+static PyMethodDef TM_SR_ND_methods[] = {
+ {"r", (PyCFunction)mixin_r, METH_NOARGS, ""},
+ {"rn", (PyCFunction)mixin_rn, METH_VARARGS, ""},
+ {"w", (PyCFunction)mixin_w, METH_O, ""},
+ {"wn", (PyCFunction)mixin_wn, METH_VARARGS, ""},
+ {"s", (PyCFunction)mixin_s, METH_NOARGS, ""},
+ {"sn", (PyCFunction)mixin_sn, METH_VARARGS, ""},
+ {"e", (PyCFunction)mixin_e, METH_NOARGS, ""},
+ {"address", (PyCFunction)mixin_address, METH_NOARGS, ""},
+ {"len", (PyCFunction)mixin_len, METH_NOARGS, ""},
+ {"rightmost", (PyCFunction)mixin_rightmost, METH_NOARGS, ""},
+ {NULL}
+};
-static PyObject* FastTM_esdn(FastTM* self ,PyObject* arg_tuple){
- Py_ssize_t n_val;
- Py_ssize_t start_val;
- if( !PyArg_ParseTuple(arg_tuple ,"n" ,&n_val) ) return NULL;
-
- start_val = self->head + 1;
- if( check_safety(self ,start_val ,n_val) < 0 ) return NULL;
- if( PyList_SetSlice(self->tape_obj ,start_val ,start_val + n_val ,NULL) < 0 ) return NULL;
- Py_RETURN_NONE;
-}
+static PyTypeObject TM_SR_ND_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "TM_module.TM_SR_ND",
+ .tp_doc = "Step Right, Non-Destructive",
+ .tp_basicsize = sizeof(FastTM),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_new = PyType_GenericNew,
+ .tp_init = (initproc)GenericTM_init,
+ .tp_dealloc = (destructor)FastTM_dealloc,
+ .tp_methods = TM_SR_ND_methods,
+ .tp_weaklistoffset = offsetof(FastTM, weakreflist)
+};
-/* --- Meta --- */
-static PyObject* FastTM_e(FastTM* self){
- PyObject* arg_tuple = PyTuple_Pack(1 ,self);
- PyObject* new_obj = PyObject_CallObject((PyObject*)Py_TYPE(self) ,arg_tuple);
- Py_DECREF(arg_tuple);
- return new_obj;
-}
+/* --- Type 2: TM_SR_ND_AR (Base + aR) --- */
+static PyMethodDef TM_SR_ND_AR_methods[] = {
+ /* Copy Base Methods */
+ {"r", (PyCFunction)mixin_r, METH_NOARGS, ""},
+ {"rn", (PyCFunction)mixin_rn, METH_VARARGS, ""},
+ {"w", (PyCFunction)mixin_w, METH_O, ""},
+ {"wn", (PyCFunction)mixin_wn, METH_VARARGS, ""},
+ {"s", (PyCFunction)mixin_s, METH_NOARGS, ""},
+ {"sn", (PyCFunction)mixin_sn, METH_VARARGS, ""},
+ {"e", (PyCFunction)mixin_e, METH_NOARGS, ""},
+ {"address", (PyCFunction)mixin_address, METH_NOARGS, ""},
+ {"len", (PyCFunction)mixin_len, METH_NOARGS, ""},
+ {"rightmost", (PyCFunction)mixin_rightmost, METH_NOARGS, ""},
+ /* Add Feature */
+ {"aR", (PyCFunction)mixin_aR, METH_O, "Append Right"},
+ {NULL}
+};
-static PyObject* FastTM_address(FastTM* self){
- return PyLong_FromSsize_t(self->head);
-}
+static PyTypeObject TM_SR_ND_AR_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "TM_module.TM_SR_ND_AR",
+ .tp_doc = "Step Right, Non-Destructive, Append Right",
+ .tp_basicsize = sizeof(FastTM),
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ .tp_new = PyType_GenericNew,
+ .tp_init = (initproc)GenericTM_init,
+ .tp_dealloc = (destructor)FastTM_dealloc,
+ .tp_methods = TM_SR_ND_AR_methods,
+ .tp_weaklistoffset = offsetof(FastTM, weakreflist)
+};
-static PyObject* FastTM_len(FastTM* self){
- return PyLong_FromSsize_t(PyList_Size(self->tape_obj));
-}
+/* ========================================================= */
+/* 4. THE FACTORY */
+/* ========================================================= */
-static PyObject* FastTM_rightmost(FastTM* self){
- Py_ssize_t len = PyList_Size(self->tape_obj);
- if( self->head >= len - 1 ) Py_RETURN_TRUE;
- Py_RETURN_FALSE;
-}
+static PyObject* FastTM_Factory(PyObject* self, PyObject* args, PyObject* kwds){
+ PyObject* input_obj = NULL;
+ PyObject* features_obj = NULL;
+
+ if( !PyArg_ParseTuple(args, "O|O", &input_obj, &features_obj) ) return NULL;
+
+ /* Check for "aR" in features */
+ int has_aR = 0;
+ if( features_obj && PyList_Check(features_obj) ){
+ Py_ssize_t size = PyList_Size(features_obj);
+ for( Py_ssize_t i=0; i<size; i++ ){
+ PyObject* item = PyList_GetItem(features_obj, i); /* Borrowed */
+ if( PyUnicode_Check(item) ){
+ const char* s = PyUnicode_AsUTF8(item);
+ if( s && strcmp(s, "aR") == 0 ) has_aR = 1;
+ }
+ }
+ }
-static PyObject* FastTM_leftmost(FastTM* self){
- if( self->head <= 0 ) Py_RETURN_TRUE;
- Py_RETURN_FALSE;
+ /* Select Type */
+ PyTypeObject* target_type = has_aR ? &TM_SR_ND_AR_Type : &TM_SR_ND_Type;
+
+ /* Create Instance */
+ PyObject* arg_tuple = PyTuple_Pack(2, input_obj, features_obj ? features_obj : Py_None);
+ PyObject* obj = PyObject_CallObject((PyObject*)target_type, arg_tuple);
+ Py_DECREF(arg_tuple);
+
+ return obj;
}
/* ========================================================= */
-/* REGISTRATION */
+/* 5. MODULE INIT */
/* ========================================================= */
-static PyMethodDef FastTM_methods[] = {
- {"r" ,(PyCFunction)FastTM_r ,METH_NOARGS ,""}
- ,{"rn" ,(PyCFunction)FastTM_rn ,METH_VARARGS ,""}
- ,{"w" ,(PyCFunction)FastTM_w ,METH_O ,""}
- ,{"wn" ,(PyCFunction)FastTM_wn ,METH_VARARGS ,""}
- ,{"s" ,(PyCFunction)FastTM_s ,METH_NOARGS ,""}
- ,{"sn" ,(PyCFunction)FastTM_sn ,METH_VARARGS ,""}
- ,{"ls" ,(PyCFunction)FastTM_ls ,METH_NOARGS ,""}
- ,{"lsn" ,(PyCFunction)FastTM_lsn ,METH_VARARGS ,""}
- ,{"aL" ,(PyCFunction)FastTM_aL ,METH_O ,""}
- ,{"aR" ,(PyCFunction)FastTM_aR ,METH_O ,""}
- ,{"d" ,(PyCFunction)FastTM_d ,METH_NOARGS ,""}
- ,{"dn" ,(PyCFunction)FastTM_dn ,METH_VARARGS ,""}
- ,{"esd" ,(PyCFunction)FastTM_esd ,METH_NOARGS ,""}
- ,{"esdn" ,(PyCFunction)FastTM_esdn ,METH_VARARGS ,""}
- ,{"e" ,(PyCFunction)FastTM_e ,METH_NOARGS ,""}
- ,{"address" ,(PyCFunction)FastTM_address ,METH_NOARGS ,""}
- ,{"len" ,(PyCFunction)FastTM_len ,METH_NOARGS ,""}
- ,{"rightmost" ,(PyCFunction)FastTM_rightmost ,METH_NOARGS ,""}
- ,{"leftmost" ,(PyCFunction)FastTM_leftmost ,METH_NOARGS ,""}
- ,{NULL}
-};
-
-static PyTypeObject FastTMType = {
- PyVarObject_HEAD_INIT(NULL ,0)
- .tp_name = "TM_module.FastTM"
- ,.tp_doc = "Safe Entangled Tape Machine"
- ,.tp_basicsize = sizeof(FastTM)
- ,.tp_itemsize = 0
- ,.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
- ,.tp_new = PyType_GenericNew
- ,.tp_init = (initproc)FastTM_init
- ,.tp_dealloc = (destructor)FastTM_dealloc
- ,.tp_methods = FastTM_methods
- ,.tp_weaklistoffset = offsetof(FastTM ,weakreflist) /* CRITICAL FIX */
+static PyMethodDef module_methods[] = {
+ {"FastTM", (PyCFunction)FastTM_Factory, METH_VARARGS | METH_KEYWORDS, "TM Factory"},
+ {NULL, NULL, 0, NULL}
};
static PyModuleDef TM_module = {
- PyModuleDef_HEAD_INIT
- ,"TM_module"
- ,"Fast TM Extension"
- ,-1
- ,NULL
+ PyModuleDef_HEAD_INIT, "TM_module", "Fast TM Extension", -1, module_methods
};
PyMODINIT_FUNC PyInit_TM_module(void){
PyObject* m_obj;
- if( PyType_Ready(&FastTMType) < 0 ) return NULL;
+
+ if( PyType_Ready(&TM_SR_ND_Type) < 0 ) return NULL;
+ if( PyType_Ready(&TM_SR_ND_AR_Type) < 0 ) return NULL;
m_obj = PyModule_Create(&TM_module);
if( !m_obj ) return NULL;
- Py_INCREF(&FastTMType);
- PyModule_AddObject(m_obj ,"FastTM" ,(PyObject*)&FastTMType);
+ Py_INCREF(&TM_SR_ND_Type);
+ Py_INCREF(&TM_SR_ND_AR_Type);
+
+ /* We export the Types if user wants to inspect them,
+ but primarily they use the FastTM factory. */
+ PyModule_AddObject(m_obj, "TM_SR_ND", (PyObject*)&TM_SR_ND_Type);
+ PyModule_AddObject(m_obj, "TM_SR_ND_AR", (PyObject*)&TM_SR_ND_AR_Type);
+
return m_obj;
}
</p>
<p>
- If an operation were permitted to remove the last remaining cell, 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 <RT-term>second order</RT-term> tape machine.
+ 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 <RT-term>second order</RT-term> tape machine.
</p>
<p>
- Tape machines that share a tape are said to be <RT-neologism>entangled</RT-neologism>. There will be both data and control hazards among entangled machines. Data hazards have to do with one machine writing data being read by another, either unexpectedly, or in the wrong temporal order. Data hazards can lead to incorrectly computed results, but they will not break the machines. In contrast, control hazards lead to broken machines. The principle control hazard is that of one entangled TM deleting a cell that another TM is visiting. That orphans the head of that other machine and leads to a violation of the <em>a tape machine head is always on a valid cell</em>. We leave the data hazard management to the programmer; however, we provide specific features for preventing control hazards.
+ Tape machines that share a tape are said to be <RT-neologism>entangled</RT-neologism>. 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 <em>a tape machine head is always on a valid cell</em> invariant.
</p>
<p>
- TM machines incorporate various approaches for managing entanglement and avoiding control hazards. These are chosen as features at 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 <RT-term>non-destructive</RT-term>. 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 <RT-neologism>solitary machine</RT-neologism> 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 <RT-neologism>entanglement accounting</RT-neologism>. 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.
+ 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 <RT-term>non-destructive</RT-term>. 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 <RT-neologism>solitary machine</RT-neologism> 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 <RT-neologism>entanglement accounting</RT-neologism>. 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 <RT-term>correct by construction</RT-term>.
</p>
<h1>Command language</h1>
<p>
- The command language is not used directly. It describes the letter patterns used to form TM interface function names.
- This approach began with LISP, and its extension is described in the paper "Towards a Better Understanding of CAR, CDR, CADR and the Others".
+ 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".
</p>
<p>
- The actual function names found on TM interfaces are listed in later sections of this guide. Reading the source code can also help.
- 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.
+ 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.
</p>
<p>
<p>
The query command, <RT-code>q</RT-code>, reports head state.
With no <RT-code>arg</RT-code> descriptor it returns a boolean value.
- With an <RT-code>R</RT-code> <RT-code>arg</RT-code> descriptor it returns true iff the head is on the rightmost cell.
+ With an <RT-code>R</RT-code> <RT-code>arg</RT-code> descriptor it returns true iff the head is on the rightmost cell. With an <RT-code>I</RT-code> <RT-code>arg</RT-code> descriptor it returns an index.
</p>
<p>
<h3>Examples</h3>
<p>
- The example descriptions state effects in the base view.
- Effects in the mirror view match the same command without the <RT-code>L</RT-code> prefix.
+ In these examples, the comments discuss what happens on the base machine. Effects in the mirror view match the same command without the <RT-code>L</RT-code> prefix.
</p>
<h4>Relative head movement</h4>
<RT-code>LsI(k)</RT-code> and <RT-code>sI(k)</RT-code> cue the head to the same indexed cell.
<RT-code>L</RT-code> flips direction and the meaning of <RT-code>R</RT-code>, not the index to cell correspondence.
Thus <RT-code>LsI(0)</RT-code> cues the cell with index zero, which is rightmost in the mirror view and leftmost in the base view.
- For that reason there is no primitive family for <RT-code>LsI</RT-code> distinct from <RT-code>sI</RT-code>.
</p>
<h4>Absolute head movement</h4>
</RT-code>
<p>
- In <RT-code>q</RT-code>, the <RT-code>I</RT-code> <RT-code>arg</RT-code> descriptor selects an index valued result.
+ The <RT-code>I</RT-code> <RT-code>arg</RT-code> descriptor causes <RT-code>q</RT-code> to return an index.
By default <RT-code>q</RT-code> returns a boolean value.
In other commands, an <RT-code>I</RT-code> <RT-code>arg</RT-code> descriptor indicates that an index argument is supplied.
</p>
<h2>Query primitives</h2>
<p>
- Query primitives expose the <RT-code>q</RT-code> command.
+ Query primitives are built from the <RT-code>q</RT-code> 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.
</p>
<p>
If indexing is enabled, the API also exposes index query primitives.
- These correspond to the <RT-code>A</RT-code> arg descriptor in the command language.
- (If you later rename <RT-code>A</RT-code> to <RT-code>I</RT-code>, this section becomes <RT-code>qI</RT-code> and <RT-code>qIR</RT-code> accordingly.)
+ These correspond to the <RT-code>I</RT-code> arg descriptor in the command language.
</p>
<ul>
- <li><RT-code>qA()</RT-code> returns the current head index. (Command form: <RT-code>qA</RT-code>.)</li>
- <li><RT-code>qAR()</RT-code> returns the index of the selected view rightmost cell. (Command form: <RT-code>qAR</RT-code>.)</li>
+ <li><RT-code>qI()</RT-code> returns the current head index. (Command form: <RT-code>qI</RT-code>.)</li>
+ <li><RT-code>qIR()</RT-code> returns the index of the selected view rightmost cell. (Command form: <RT-code>qIR</RT-code>.)</li>
</ul>
<p>
Mirror view query forms follow the same rule in the command language.
- For example, <RT-code>LqR</RT-code> tests the leftmost of the underlying tape, and <RT-code>LqAR</RT-code> returns its index, typically zero.
- In the API, that effect is obtained either by left primitives (for <RT-code>LqR</RT-code> this is <RT-code>lsqR()</RT-code> if such a helper exists), or by explicit equivalences such as “leftmost test” implemented via the leftmost cue or by comparing to a known bound head.
- The primitive set stays small, and higher level forms live in friend or workspace layers.
+ For example, <RT-code>LqR</RT-code> tests the leftmost of the underlying tape, and <RT-code>LqIR</RT-code> returns its index, typically zero.
</p>
<h2>Entanglement primitives</h2>
<p>
Entanglement primitives implement the <RT-code>e</RT-code> command.
- The entangled machine shares the tape with the original and starts on the same cell.
+ 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.
</p>
</ol>
<p>
- In order to maintain these properties, a TM uses inclusive bounds for intervals.
- An interval is marked by placing a head on the leftmost cell of the interval, and placing an entangled head on the rightmost cell of the interval.
+ In order to maintain these properties, a TM uses inclusive bounds for intervals, including intervals of cells, and intervals of indexes.
</p>
<h2>Contract with the programmer</h2>
</p>
<ol>
- <li>When there is a right bound, the caller guarantees they will never command the machine to step beyond the rightmost cell.</li>
- <li>When there is a left bound, the caller guarantees they will never command the machine to step left of the leftmost cell.</li>
+ <li>When there is a right bound, the caller guarantees that he will never command the machine to step beyond the rightmost cell.</li>
+ <li>When there is a left bound, the caller guarantees that he will never command the machine to step left of the leftmost cell.</li>
</ol>
<p>