From: Thomas Walker Lynch Date: Wed, 12 Mar 2025 11:13:36 +0000 (+0000) Subject: integrating Link into Core X-Git-Url: https://git.reasoningtechnology.com/style/static/git-favicon.png?a=commitdiff_plain;h=9bb1d11b5796b1636f64c8fb80b9d88b7131bf02;p=N integrating Link into Core --- diff --git "a/developer/cc\360\237\226\211/Core.lib.c" "b/developer/cc\360\237\226\211/Core.lib.c" index 244894f..c98747a 100644 --- "a/developer/cc\360\237\226\211/Core.lib.c" +++ "b/developer/cc\360\237\226\211/Core.lib.c" @@ -22,7 +22,7 @@ #ifndef FACE #define Core·IMPLEMENTATION -#define FACE +#define FAC #endif //-------------------------------------------------------------------------------- @@ -35,7 +35,7 @@ #include //---------------------------------------- - // fundamental + // memory #define extentof(x)(sizeof(x) - 1) #define extent_t size_t @@ -44,11 +44,71 @@ // 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 Δ); @@ -58,32 +118,53 @@ 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); @@ -96,7 +177,6 @@ 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); @@ -108,7 +188,7 @@ 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; //---------------------------------------- @@ -118,11 +198,11 @@ // 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 = @@ -137,12 +217,11 @@ ; 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\360\237\226\211/Model.org" "b/document\360\237\226\211/Model.org" new file mode 100644 index 0000000..6e10dbe --- /dev/null +++ "b/document\360\237\226\211/Model.org" @@ -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'.