integrating Link into Core
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 12 Mar 2025 11:13:36 +0000 (11:13 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 12 Mar 2025 11:13:36 +0000 (11:13 +0000)
developer/cc馃枆/Core.lib.c
document馃枆/Model.org [new file with mode: 0644]

index 244894f..c98747a 100644 (file)
@@ -22,7 +22,7 @@
 
 #ifndef FACE
 #define Core路IMPLEMENTATION
-#define FACE
+#define FAC
 #endif 
 
 //--------------------------------------------------------------------------------
@@ -35,7 +35,7 @@
   #include <stddef.h>
 
   //----------------------------------------
-  // fundamental
+  // memory
 
     #define extentof(x)(sizeof(x) - 1)
     #define extent_t size_t
     // given an AU is an 8 bit byte, 4AU is 32 bits, and 8 AU is 64 bits.
     #define AU uint8_t;
 
-    // latent link call convention
+  //----------------------------------------
+  // model
+
+    typedef enum{
+      Core路Status路mu = 0
+      ,Core路Status路good
+      ,Core路Status路bad
+    }Core路Status;
+
+    typedef struct{
+    }Core路Tableau;
+
+    typedef struct{
+      Core路Tableau tableau;
+      unint status;
+    }Core路Tableau路Face;
+
+    typedef struct Core路Action;
     typedef struct Core路Link;
 
-    // as this is a macro the fields are not typed, so no casts are needed
-    #define Core路call(fn ,link) (link->action.##fn##(link->tableau))
+    typedef Core路Link *(*Core路Fn)(Core路Link *);
+
+    typedef struct{
+      Core路Fn good;
+      Core-Fn bad;
+    }Core路Action;
+
+    typedef struct{
+      Core路Tableau *face;
+      Core路Tableau *State;
+      Core路Action *act;
+    }Core路Link;
+
+    // Then define the functions separately
+    Local Core路Link *Core路Action路good_function(Core路Link *lnk){
+      lnk->face->status = Core路Status路good;
+      return NULL;
+    }
+
+    Local void call(Core路Link *lnk){
+      while(lnk) lnk = lnk->act(lnk);
+    }
+
+    Local Core路Link *Core路Action路bad_function(Core路Link *lnk){
+      lnk->face->status = Core路Status路bad;
+      return NULL;
+    }
+
+    // Assign the function pointers to a struct
+    Local Core路Action action = {
+      .good = Core路Action路good_function,
+      .bad = Core路Action路bad_function
+    };
+
+
+    // -----implementation
+
+    typedef struct{
+      Core路Tableau tableau;
+    }Core路Tableau路State;
+
+
+
+  //----------------------------------------
+  // utility
 
     struct{
       void *offset(void *p ,size_t 螖);
       bool is_aligned_on_8AU(void *p);
       void *floor_within_aligned_8AU(void *p);
       void *ceiling_within_aligned_8AU(void *p);
-    } Core;
+    }Core;
 
   //----------------------------------------
-  // Area
+  // Area model
 
     typedef struct Core路Tape;
 
+    typedef struct{
+      Core路Tableau路Face;
+      Core路Tape *tape;
+      extent_t extent;
+      Core路Link extent_mu;
+      Core路Link extent_next;
+    }Core路Tape路Tableau路Face;
+
     typedef enum{
       Core路Area路Topology路mu
-      ,Core路Area路Topology路nonexistent // pointer to area is NULL
-      ,Core路Area路Topology路empty      // pointer to are is non-null but position pointer is NULL
+      ,Core路Area路Topology路nonexistent // pointer to tape is NULL
+      ,Core路Area路Topology路empty      // tape has no cells
       ,Core路Area路Topology路singleton  // extent is zero
-      ,Core路Area路Topology路segment    // none of the above
-      ,Core路Area路Topology路circle     // could be forced by a special read function
-      ,Core路Area路Topology路cyclic     // cycle does not include leftmost
-      ,Core路Area路Topology路infinite   // could happen for a function abstraction of the interface
+      ,Core路Area路Topology路segment    // finite non-singleton tape
+      ,Core路Area路Topology路circle     // initial location recurs
+      ,Core路Area路Topology路cyclic     // a location recurs
+      ,Core路Area路Topology路infinite   // exists, not empty, no cycle, no rightmost
     }Core路Tape路Topology;
 
     typedef struct{
+      Core路Fn
       Core路Tape路Topology (*topology)(Core路Tape *tape);
-    }Core路Tape路Face;
+      extent_t extent(Core路Area *area); 
+
+    }Core路Tape路Action;
 
     typedef struct Core路Area; // extends Tape
 
     typedef struct{
-      Core路Tape路Face tape;
+      Core路Tape路Tableau路Face tape_tableau;
+      Core路Area *area;
+      void *position_left;
+      void *position_right;
+
+    }Core路Area路Tableau路Face;
+
+
+
+    typedef struct{
+      Core路Tape路Action tape;
 
       void init_pe(Core路Area *area ,void *position ,extent_t extent);
       void init_pp(Core路Area *area ,void *position_left ,void *position_right);
       AU *position(Core路Area *area);
       AU *position_left(Core路Area *area); // synonym
       AU *position_right(Core路Area *area);
-      extent_t extent(Core路Area *area); 
 
       AU *complement(Core路Area *area ,AU *r);
 
       bool overlap(Core路Area *a ,Core路Area *b);
       void largest_aligned_64(Core路Area *outer ,Core路Area *inner_64);
 
-    } Core路Area路Face;
+    } Core路Area路Action;
 
 
   //----------------------------------------
 
     // if tape machine does not support step left, then Status路leftmost will be reported as Status路interim
     typedef enum{
-      Core路TM路Head路Status路mu = 0
+      Core路TM路Head路Status路mu
       ,Core路TM路Head路Status路not_on_tape = 1
-      ,Core路TM路Head路Status路leftmost    = 1 << 1
-      ,Core路TM路Head路Status路interim     = 1 << 2
-      ,Core路TM路Head路Status路rightmost   = 1 << 3
+      ,Core路TM路Head路Status路on_leftmost    = 1 << 1
+      ,Core路TM路Head路Status路in_interim     = 1 << 2
+      ,Core路TM路Head路Status路on_rightmost   = 1 << 3
     }Core路TM路Head路Status;
 
     const uint Core路TM路Head路Status路bad =
       ;
 
     typedef struct{
-      Core路Tableau tableau;
-      Core路TM *tm;
+      Core路Tableau路Face
       Core路Area路M *a;
-      Core路TM路Head路Status status;
+      Core路TM路Head路Status status; // perhaps integrate this with Core路tableau status
       Core路Tape路Topology topology;
-    }Core路TM_NX路Tableau;
+    }Core路TM_NX路Tableau路Face;
 
     // default Tableau
     Local Core路TM_NX路Tableau Core路TM_NX路t;
diff --git a/document馃枆/Model.org b/document馃枆/Model.org
new file mode 100644 (file)
index 0000000..6e10dbe
--- /dev/null
@@ -0,0 +1,165 @@
+#+TITLE: Model and related
+#+AUTHOR: Thomas
+#+STARTUP: content
+
+* Tableau
+
+A Tableau is a type definition for a work area, typically implemented as a typedef struct in C.
+
+An instance of a Tableau is a tableau. There can be many instances of a given Tableau. 
+
+There are multiple kinds of Tableau:
+
+- interface (also called a Face)
+- state
+
+* ActionTable
+
+An action is a function that operates on a tableau.
+
+Each action is an instance of an Action. An Action is a typedef for a function pointer.
+
+An ActionTable is a typedef of a struct,  and instance of is said to be an action_table.
+A given ActionTable can 
+
+An instance of an ActionTable is an action_table.  There can be many isntances of a given ActionTable.
+
+Each function in an action_table is an action.
+
+
+* Model
+
+A Model is a  TableauFace, a TableauState, and an ActionTable.
+
+An instance of a Model is a model.
+
+
+* Status bits or continuations?
+
+The problem I found with continuations is that when the library is
+limited to a single status function for a model, there will necessarily
+be many continuations from the status function, one for each shade of meaning that it can discern. To endow it with fewer would limit its usefulness for some scenario, perhaps rare, but still supported. 
+
+In addition, not all status's are independent. Thus there must be a priority scheme and then a choice of continuation, but the status function might not know the caller's
+priorities. An alternative would be to take both continuations and break into multithreaded execuation. However, many programs are designed to be single threaded.
+
+When status is used as an argument guard this often comes down to, "Is the passed in
+status baring model operable or not?" Thus the tableau for the many-continuations status function will have many duplicate next pointers.
+
+If rather than returning continuations, a highly discerning status function were to  return status bits, The caller could mask the bits and then chose among continuations.  In the cause of an argument guard, choosing among two paths.
+
+It is also a little funny when using a status function as an argument guard that the guard continues into the very function it is guarding. The tableau facilitates this
+design pattern in that the input operands need not be written again. Though this
+requires managing the tableau for the model who's status is being checked.
+
+An alternative to using status bits is to have more than one status function. One implementation is to embed the many-continuations status function inside the few-continuations status function, to perform the mask, and then pick the continuation.  This might be convenient function to have, but where a second status function really makes sense is where it reduces the amount of computation that need be done.
+
+* A Single Tableau per Model
+
+Inputs for actions are written to a tableau. A link currently holds an actions table pointer, and a tableau pointer, hence there is one tableau that holds both action inputs and model state variables.
+
+If this tableau is declared as part of the FACE then the user can access the model state variables. This would follow a philosophy of, "if they are useful, then so bit it"; however exposing state variables limits both the number of models that can be made that provide the user with the same interface, and limits what can be done with maintenance edits without risking breaking the user's code.  Recall that Model is an abstract type, and there can be many implementations for said type, i.e. many models for a given Model.
+
+C does not allow for public and private sections of a struct, or we could make the state variables private.
+
+However, we can accomplish the same thing as public and private, perhaps in even a better way, by including the interface tableau in the full tableau, and have the code know it was given the full tableau:
+
+#+BEGIN_SRC c
+typedef struct{
+  ...
+}X路TableaFace;
+
+// in the implementation
+
+typedef struct{
+  X路TableaFace face;
+  ...
+}X路Tablea;
+
+#+END_SRC
+
+The details of the TableauFace type are shown to the user.  The actions are
+declared to be given a TableauFace, so any directly calls will work.  Inside each action the tableau is converted from TableauFace to Tableau.
+
+
+** Tableau structure
+
+The TableauFace has:
+- all possible inputs
+- results
+- continuations
+
+Then the Tableau extension
+
+- state variables
+
+
+* Continuation Link
+
+There are two dimensions of variation. 1) Multiple action_tables from a given ActionTable, and 2) multiple tableau from a given Tableau.
+
+Each action_table instance of a given ActionTable can have very different function implementations, as only the function type signatures are specified in the ActionTable definition. 
+
+The interface tableau, TableauFace, is designed against the ActionTable. Both deal with the user's view of the Model. In contrast each state tableau, TableauState is designed against a specific action_table.
+
+Hence, for each ActionTable declaration there will be corresponding to a TableauFace declaration, unless by coincidence, an existing one can be recycled, though even then programmers would appreciate having matching names. This begs the question if the two structures can be combined into one. So doing would constrain our ability to make instances from them independently.
+
+A given action table can be used with multiple state tableaux. In other words, there can be multiple instances of the same type.
+
+Conversely a given tableau can be used with multiple action tables. This happens in
+polymorphism, where a child tableau can be passed to a parent action. The child
+parts are in an extended portion of the tableau, and thus not seen by the parent
+action.
+
+In the one Tableau per model approach, each tableau instance is both state and inputs, hence each instance will have its own inputs. We would lose the ability to make independent state and interface instances. The interface tableau is playing the role
+that is typically played by the stack frame. Hence there is a copy per call, now this the one tableau per model, there would be a copy per instance. If left independent, there would be as many or few copies as the user determines is necessary, with the network of interface tableaux being connected by pointers tending to look like a circuit.
+
+**proposal 1
+
+Place an action_table pointer in each single tableau per model tableau, then there would be many copies of the action_table pointer, one per tableau. This is the virtual table pointer approach from C++ or the delegate pointer from JavaScript.
+
+With this approach the action table can be reached through the tableau, so only the tableau, or references to it, need to be passed around as an instance of the model. This is appealing.
+
+However, such a link to such a tableau is not sufficient for knowing which action on the action table should be called.  Hence a link to such an overloaded tableau can not function as a continuation link.
+
+Suppose if instead of an action_table link, a function link were embedded in the tableau, perhaps as a first member. Then the first member could be called and given the tableau as its only argument. This could function as a link, but then the state of the model is owned by a single function call. This looks problematic.
+
+**proposal 2
+
+A link is a two pointer bundle. The first pointer to an action table, the second to single tableau. Then there is a macro called `call` that is used for calling functions in the action table. ``call(extent ,&tape_tableau)`
+
+The problem here is that such a link can not appear as a continuation because the link itself  does not say which action is being invoked. That information is in the call.
+
+Attempts to save this proposal by including a 'field pointer' in the link, that would be applied to the action table are rather awkward in C, though it can be done by creating an enumeration of the struct offsets, and using those tags.
+
+**proposal 3
+
+A three pointer bundle, the first pointer to the function being called, the second pointer to an interface tableau, the third pointer to the state tableau shared by the functions in the action_table the function comes from.
+
+In this approach there is not action_table pointer, though that is not a problem because if that information is needed it can be curried into the called function when it is written, though chances are if a given action needs to call another action function in the table, it will do so through a function pointer. The purposes of the action_table struct is then to document which actions share the corresponding tableau state, and to provide a namespace to put the actions in, which makes it conceptually nicer for the programmer.  It would be even nicer if C supported Pascal's 'with' statement.
+
+Such a link could be reduced to two pointers if the single tableau variation is used.
+
+* Mixing continuations with fall through execution.
+
+#+BEGIN_SRC c
+    Local void call(Core路Link *lnk){
+      while(lnk) lnk = lnk->act(lnk);
+    }
+#+END_SRC
+
+This implementation of call falls through when a null `lnk` pointer is returned. However the caller can not know anything about the status of the call.
+
+**proposal 1
+
+Each continuation function that can return a NULL link, where the caller wants to know the status, also sets a `status` value at the top of the base tableau, that all FACE tableau's extend from.
+
+Disadvantage, all code must set status, so why have continuations?  The optimizer will drop unused status setting code, so perhaps this is not serious.  Though, on the other hand, for Local functions would the optimizer skip the status return and condition testing, and put the continuation in - thus making status setting the way to go as it must be coded anyway?
+
+
+**proposal 2
+
+Have actions that set status, link to them when status is desired.
+
+Actually we need default continuations anyway. In many cases these could
+be generic. Argument guard continuations could be 'good' or 'bad'.