From 030b5fefb95512dddf829570ae2a75d3374e504c Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Thu, 20 Mar 2025 11:17:43 +0000 Subject: [PATCH] simplified, comging down to read and write type matching, is it possible? --- "developer/cc\360\237\226\211/Core.lib.c" | 7 +- "developer/cc\360\237\226\211/Map.lib.c" | 1540 ++--------------- "developer/cc\360\237\226\211/Map2.lib.c" | 500 ++++++ "developer/cc\360\237\226\211/TM.lib.c" | 391 ++++- "developer/cc\360\237\226\211/xi.c" | 66 + .../document\360\237\226\211/alignment.org" | 15 + .../generalizing_type.org" | 109 ++ developer/experiment/xi.c | 68 + developer/experiment/xi2_test.c | 62 + developer/experiment/xi_test.c | 39 + 10 files changed, 1329 insertions(+), 1468 deletions(-) create mode 100644 "developer/cc\360\237\226\211/Map2.lib.c" create mode 100644 "developer/cc\360\237\226\211/xi.c" create mode 100644 "developer/document\360\237\226\211/generalizing_type.org" create mode 100644 developer/experiment/xi.c create mode 100644 developer/experiment/xi2_test.c create mode 100644 developer/experiment/xi_test.c diff --git "a/developer/cc\360\237\226\211/Core.lib.c" "b/developer/cc\360\237\226\211/Core.lib.c" index 53e0632..f70d7ea 100644 --- "a/developer/cc\360\237\226\211/Core.lib.c" +++ "b/developer/cc\360\237\226\211/Core.lib.c" @@ -32,12 +32,13 @@ #include #include + // the template filling macro + #include + //---------------------------------------- // memory interface //---------------------------------------- - #ifndef CVT - // Expand namespace with a macro parameter given value. // The namespace and the extended value will be evaluated for macros. // Greek capital letter 'Xi' for eXtend. @@ -79,8 +80,6 @@ ,Core·Status·derailed }Core·Status; - #endif - //---------------------------------------- // flag facility, argument guard facility //---------------------------------------- diff --git "a/developer/cc\360\237\226\211/Map.lib.c" "b/developer/cc\360\237\226\211/Map.lib.c" index 26297b8..2fd90cf 100644 --- "a/developer/cc\360\237\226\211/Map.lib.c" +++ "b/developer/cc\360\237\226\211/Map.lib.c" @@ -1,1486 +1,154 @@ - /* - Core - core memory operations. +/* Map - mapping functions between tape machines. - This file has the template parameter: `CVT` + This file has two template parameters: + `CVT_read` Cell Value Type for the source/read tape machine + `CVT_write` Cell Value Type for the destination/write tape machine - `CVT` Cell Value Type`. It is the type of the datum placed in a cell. By default (when the macro CVT has no definition) the cell value type is taken as AUM. This file must - be included with CVT undefined, before inclusions with it defined. - - `AU` `Addressable Unit for the machine`, on most all machines today this is uint8_t, - though the C standard has never required this. - - 'ATP' `At This Point' in the code. Acronym used in comments usually before pointing - out certain values variables must have. - - 'AToW' - At Time of Writing, also used in comments. - - 'Tape' is operated on by the Tape Machine. - - 'Area' is subset of an address space that is used as a virtual Tape by a machine. - - An Area with zero elements has 'length == 0' or is 'empty'. In contrast, and - area located (position specified) with a null pointer is said not to exist. - - When all the functions that have a specific type of operand given are group together - in a table, we call the table a 'Function Given Type X', table. In general we call - these FG (Function Given) tables. A specific instance of an FG table is an `fg` table. + By default (when the macros have no definition) the cell value types are taken as AU. + This file must be included with CVT_read and CVT_write undefined, before inclusions with them defined. + 'Tape' is operated on by the Tape Machine. + 'Area' is subset of an address space that is used as a virtual Tape by a machine. + An Area with zero elements has 'length == 0' or is 'empty'. + In contrast, and area located (position specified) with a null pointer is said not to exist. */ -#define Core·DEBUG +#define Map·DEBUG #ifndef FACE -#define Core·IMPLEMENTATION -#define FAC -#endif + #define Map·IMPLEMENTATION + #define FACE +#endif //-------------------------------------------------------------------------------- // Interface -#ifndef Core·FACE -#define Core·FACE +#ifndef Map·FACE + #define Map·FACE #include #include + #include "Core.lib.c" + #include "TM.lib.c" - //---------------------------------------- - // memory interface - //---------------------------------------- - - #ifndef CVT - - // Expand namespace with a macro parameter given value. - // The namespace and the extended value will be evaluated for macros. - // Greek capital letter 'Xi' for eXtend. - #define _Ξ(a ,b) a##·##b - #define Ξ(a ,b) _Ξ(a ,b) - - // ask the machine what this is - // C language standard left this undefined, probably why unicode uses 'octet' - // AToW industry uses uint8_t - // reminds me of FORTRAN star types - #define AU uint8_t - #define AU2 uint16_t - #define UA4 uint32_t - #define UA8 uint64_t - - #define AU_MAX ~(AU)0 - #define AU2_MAX ~(AU2)0 - #define UA4_MAX ~(AU4)0 - #define UA8_MAX ~(AU8)0 - - // ask the compiler what this is - // when using enums we get this whether we want it or not - #define WU unsigned int - #define WU ~(WU)0 - - // extent is an address or an index. It is not a length. - // The index scaling CVT type is appended to the end of the extent related identifiers.. - // E.g. exent_of·AU(uint64_t) == 7 while exent_of·uint16_t(uint64_t) == 3; - // exent_of·AU of the address space is ~(uintptr)0; - #define extent_of·AU(x)(sizeof(x) - 1) - #define extent_t·AU size_t - - // Funny, we seldom check for this, but maybe someone is running a microcontroller or something, so we will here. Also, too bad that address 0 can't be used. - #define extent_address_space·AU ~(uintptr)0; - - typedef enum{ - Core·Status·mu = 0 - ,Core·Status·on_track - ,Core·Status·derailed - }Core·Status; + // if only one template parameter is given, we will assume both are the same + #if defined(CVT_read) && !defined(CVT_write) + #warning "Given CVT_read template value. Missing CVT_write template value, so setting it to CVT_read" + #define CVT_write CVT_read #endif - #ifdef CVT - #define Ξ(extent_t ,CVT) size_t - #endif - - //---------------------------------------- - // argument guard interface - //---------------------------------------- - - #ifndef CVT - - typedef void (*Core·Flag·Fn)(WU *flag ,WU err); - - void Core·Flag·count(WU *flag ,WU err){ - if(err == WU_MAX){ *flag = WU_MAX; return;} - - //*flag + err > WU_MAX - if(*flag > WU_MAX - err){ *flag = WU_MAX; return;} - - (*flag) += err; - } - - void Core·Flag·collect(WU *flag ,WU err){ - (*flag) |= err; - } - - typedef struct { - char *name; - Core·Flag·Fn flag_function; - WU flag; - } Core·Guard; - - typedef struct { - void (*init)(Core·Guard *chk ,const char *name ,Core·Flag·Fn af); - void (*reset)(Core·Guard *chk); - void (*check)( - Core·Guard *chk - ,WU err - ,bool condition - ,char *message - ); - } Core·Guard·FG; - - // Default guard function table - // initialized in the implementation section below - Local Core·Guard·FG Core·Guard·fg; - - #define Core·Guard·init_count(chk) \ - Core·Guard chk; \ - Core·Guard·fg.init(&chk ,__func__ ,Core·Flag·count); - - #define Core·Guard·init_collect(chk) \ - Core·Guard chk; \ - Core·Guard·fg.init(&chk ,__func__ ,Core·Flag·collect); - - #define Core·Guard·if_return(chk) if( chk.flag ) return Core·Status·derailed; - #define Core·Guard·return(chk)\ - if( chk.flag ) return Core·Status·derailed;\ - else return Core·Status·on_track; - - #endif - - //---------------------------------------- - // functions interface - //---------------------------------------- - - // no state, this is merely a namespace - - #ifndef CVT - typedef struct{ - Core·Status (*on_track)(); - Core·Status (*derailed)(); - Core·Status (*is_aligned)(AU *p ,extent·AU alignment ,bool *flag); - Core·Status (*round_down)(AU *p ,extent·AU alignment ,AU **result); - Core·Status (*round_up)(AU *p ,extent·AU alignment ,AU **result); - } Core·F; - Local Core·F Core·f; - #endif - - #ifdef CVT - typedef struct{ - // nothing here right now - } Ξ(Core·F ,CVT); - Local Ξ(Core·F ,CVT) Ξ(Core·F ,CVT)·f; + #if !defined(CVT_read) && defined(CVT_write) + #warning "Given CVT_write template value. Missing CVT_read template value, so setting it to CVT_write" + #define CVT_read CVT_write #endif //---------------------------------------- - // Tape Machine interface + // Map status and completion enums //---------------------------------------- - #ifndef CVT - - typedef struct Core·TM_NX; - - /* - For an CVT machine tape, a mounted tape will be singleton or segment. - */ - typedef enum{ - Core·Tape·Topo·mu = 0 - ,Core·Tape·Topo·nonexistent = 1 - ,Core·Tape·Topo·empty = 1 << 1 - ,Core·Tape·Topo·singleton = 1 << 2 - ,Core·Tape·Topo·segment = 1 << 3 - ,Core·Tape·Topo·circle = 1 << 4 - ,Core·Tape·Topo·tail_cyclic = 1 << 5 - ,Core·Tape·Topo·infinite = 1 << 6 - }Core·Tape·Topo; - - const Core·Tape·Topo Core·Tape·Topo·finite_nz = - Core·Tape·Topo·singleton | Core·Tape·Topo·segment - ; - - // 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·not_on_tape = 1 - ,Core·TM·Head·Status·origin = 1 << 1 - ,Core·TM·Head·Status·interim = 1 << 2 - ,Core·TM·Head·Status·rightmost = 1 << 3 - } Core·TM·Head·Status; - - const Core·TM·Head·Status Core·TM·Head·Status·on_tape = - Core·TM·Head·Status·origin - | Core·TM·Head·Status·interim - | Core·TM·Head·Status·rightmost + #if !defined(CVT_read) && !defined(CVT_write) + + typedef enum { + Map·Completion·mu = 0 + ,Map·Completion·failed = 1 + ,Map·Completion·null_fn = 1 << 1 + ,Map·Completion·no_tape_access = 1 << 2 + ,Map·Completion·rightmost_read = 1 << 3 + ,Map·Completion·rightmost_write = 1 << 4 + } Map·Completion; + + // Masks for combinations + const uint Map·Completion·rightmost_both = + Map·Completion·rightmost_read + | Map·Completion·rightmost_write ; - // tape and area are included with Tape Machine to facilitate abstract interfaces. - typedef struct{ - - struct { - Core·Status (*topo)(Core·TM_NX *tm ,Core·Tape·Topo *topo); - Core·Status (*extent)(Core·TM_NX *tm ,extent_t·AU *result); - } tape; - - struct { - // Initialize tm - Core·Status (*mount_pe)(Core·TM_NX *tm ,AU position[] ,extent_t·AU extent·AU); - Core·Status (*mount_pp)(Core·TM_NX *tm ,AU *position_left ,AU *position_right); - - // predicates - Core·Status (*encloses_pt)(Core·TM_NX *tm ,AU *pt ,bool *result); - Core·Status (*encloses_pt_strictly)(Core·TM_NX *tm ,AU *pt ,bool *result); - Core·Status (*encloses_area)(Core·TM_NX *outer ,Core·TM_NX *inner ,bool *flag); - Core·Status (*encloses_area_strictly)( - Core·TM_NX *outer ,Core·TM_NX *inner ,bool *flag - ); - Core·Status (*overlap)(Core·TM_NX *a ,Core·TM_NX *b ,bool *result); - } area; - - // tape machine functions - Core·Status (*mount)(Core·TM_NX *tm); - Core·Status (*dismount)(Core·TM_NX *tm); - - Core·Status (*status)(Core·TM_NX *tm ,Core·TM·Head·Status *status); - Core·Status (*can_read)(Core·TM_NX *tm ,bool *flag); - Core·Status (*on_origin)(Core·TM_NX *tm ,bool *flag); - Core·Status (*on_rightmost)(Core·TM_NX *tm ,bool *flag); - - Core·Status (*copy_datum)(Core·TM_NX *tm_read ,Core·TM_NX *tm_write); - Core·Status (*read)(Core·TM_NX *tm ,AU *read_pt); - Core·Status (*write)(Core·TM_NX *tm ,AU *write_pt); - Core·Status (*head_pt)(Core·TM_NX *tm ,AU *head_pt); - - Core·Status (*rewind)(Core·TM_NX *tm); - Core·Status (*step)(Core·TM_NX *tm); - Core·Status (*step_left)(Core·TM_NX *tm); - Core·Status (*step_right)(Core·TM_NX *tm); // Synonym for step - - } Core·TM_NX·FG; - - Core·TM_NX·FG Core·TM_NX·fg; - - #endif // #ifndef CVT - - #ifndef CVT - typedef struct Ξ(Core·TM_NX ,CVT); - - typedef struct{ - - struct { - Core·Status (*extent)(Ξ(Core·TM_NX ,CVT) *tm ,Ξ(extent_t ,CVT) *result); - } tape; - - struct { - - // Initialize tm - Core·Status (*mount_pe)(Core·TM_NX tm ,CVT position[] ,Ξ(extent_t ,CVT) extent); - Core·Status (*mount_pp)(Core·TM_NX *tm ,CVT *position_left ,CVT *position_right); - - // initializes inner - Core·Status (*largest_aligned)(Core·TM_NX_uint8_t *outer ,Ξ(Core·TM_NX ,CVT) *inner); - - Core·Status (*encloses_pt)(Ξ(Core·TM_NX ,CVT) *tm ,CVT *pt ,bool *result); - Core·Status (*encloses_pt_strictly)(Ξ(Core·TM_NX ,CVT) *tm ,CVT *pt ,bool *result); - - Core·Status (*encloses_area)( - Ξ(Core·TM_NX ,CVT) *outer ,Ξ(Core·TM_NX ,CVT) *inner ,bool *flag - ); - Core·Status (*encloses_area_strictly)( - Ξ(Core·TM_NX ,CVT) *outer ,Ξ(Core·TM_NX ,CVT) *inner ,bool *flag - ); - Core·Status (*overlap)( - Ξ(Core·TM_NX ,CVT) *a ,Ξ(Core·TM_NX ,CVT) *b ,bool *result - ); - } area; - - Core·Status (*copy_datum)( Ξ(Core·TM_NX ,CVT) *tm_read ,Ξ(Core·TM_NX ,CVT) *tm_write ); - Core·Status (*read)( Ξ(Core·TM_NX ,CVT) *tm ,CVT *remote_pt ); - Core·Status (*write)( Ξ(Core·TM_NX ,CVT) *tm ,CVT *remote_pt ); - Core·Status (*head_pt)( Ξ(Core·TM_NX ,CVT) *tm ,CVT *head_pt ); - - - } Ξ(Core·TM_NX ,CVT)·FG; - - Ξ(Core·TM_NX ,CVT)·FG Ξ(Core·TM_NX ,CVT)·fg; - - #endif // #ifdef CVT - - //---------------------------------------- - // Map interface - //---------------------------------------- - - #ifndef CVT - - typedef enum{ - Core·Map·Status·mu = 0 - ,Core·Map·Status·no_tape - ,Core·Map·Status·not_computable - ,Core·Map·Status·complete - } Core·Map·Status; - - typedef enum{ - Core·Map·Completion·mu = 0 - ,Core·Map·Completion·null_fn = 1 - ,Core·Map·Completion·no_tape_access = 1 << 1 - ,Core·Map·Completion·failed = 1 << 2 - ,Core·Map·Completion·perfect_fit = 1 << 3 - ,Core·Map·Completion·read_surplus = 1 << 4 - ,Core·Map·Completion·read_surplus_write_gap = 1 << 5 - ,Core·Map·Completion·write_available = 1 << 6 - ,Core·Map·Completion·write_gap = 1 << 7 - } Core·Map·Completion; - - const uint Core·Map·Completion·derailed = - Core·Map·Completion·no_tape - | Core·Map·Completion·not_computable - | Core·Map·Completion·failed + const uint Map·Completion·derailed = + Map·Completion·failed + | Map·Completion·null_fn + | Map·Completion·no_tape_access ; - const uint Core·Map·Completion·on_track = - Core·Map·Completion·perfect_fit - | Core·Map·Completion·read_surplus - | Core·Map·Completion·read_surplus_write_gap - | Core·Map·Completion·write_available - | Core·Map·Completion·write_gap + const uint Map·Completion·on_track = + Map·Completion·rightmost_read + | Map·Completion·rightmost_write + | Map·Completion·rightmost_both ; - typedef Core·Map·Fn (*Core·Map·Fn)(AU *x ,AU *fx); - - #endif // #ifndef CVT - - #ifdef CVT - typedef Ξ(Core·Map ,CVT)·Fn (*Core·Map·Fn)(CVT *x ,CVT *fx); - - #endif CVT - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef Core·IMPLEMENTATION - // declarations available to all of the IMPLEMENTATION go here - // - #ifdef Core·DEBUG - #include - #endif - - // implementation to go into the lib.a file - // - #ifndef LOCAL - #endif - - #ifdef LOCAL - - //---------------------------------------- - // argument guard implementation - //---------------------------------------- - - #ifndef CVT - Local void Core·Guard·init(Core·Guard *chk ,Core·Flag·Fn af){ - if( !chk ) return; - chk->flag_function = af; - chk->flag = 0; - } - - Local void Core·Guard·reset(Core·Guard *chk){ - if( !chk ) return; - chk->flag = 0; - } - - Local void Core·Guard·check( - Core·Guard *chk - ,uint err - ,bool condition - ,const char *message - ){ - if( !chk || !chk->flag_function ) return; - if( condition ) return; - fprintf(stderr ,"%s\n" ,message); - chk->flag_function(&chk->flag ,err); - } - - Local Core·Guard·FG Core·Guard·fg = { - .init = Core·Guard·init - ,.reset = Core·Guard·reset - ,.check = Core·Guard·check - }; - #endif // *ifndef CVG - - //---------------------------------------- - // Functions implementation - //---------------------------------------- - - #ifndef CVT - - Core·Status Core·on_track(){ return Core·Status·on_track; } - Core·Status Core·derailed(){ return Core·Status·derailed; } - - Local Core·Status Core·is_aligned(AU *p ,extent·AU alignment ,bool *flag){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,p ,"given NULL p"); - Core·Guard·fg.check(&chk ,1 ,flag ,"flag is NULL, so nowhere to write result"); - Core·Guard·if_return(chk); - #endif - *flag = ( (uintptr_t)p & alignment ) == 0; - return Core·Status·on_track; - } - - Local Core·Status Core·round_down(AU *p ,extent·AU alignment ,AU **result){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,p ,"given NULL p to round"); - Core·Guard·fg.check(&chk ,1 ,result ,"result is NULL, so nowhere to write result"); - Core·Guard·if_return(chk); - #endif - *result = (AU *)( (uintptr_t)p & ~(uintptr_t)alignment ); - return Core·Status·on_track; - } - - Local Core·Status Core·round_up(AU *p ,extent·AU alignment ,AU **result){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,p ,"given NULL p to round"); - Core·Guard·fg.check(&chk ,1 ,result ,"result is NULL, so nowhere to write result"); - Core·Guard·if_return(chk); - #endif - *result = (AU *)( ( (uintptr_t)p + alignment ) & ~(uintptr_t)alignment ); - return Core·Status·on_track; - } - - Local Core·F Core·f = { - .on_track = Core·on_track - ,.derailed = Core·derailed - ,.is_aligned = Core·is_aligned - ,.round_down = round_down - ,.round_up = round_up - }; - - #endif // #ifndef CVT - - #ifdef CVT - - // Struct instance initialization - Ξ(Core·F ,CVT) Ξ(Core·F ,CVT)·f = { - }; - - #endif - - //---------------------------------------- - // TM_NX implementation - //---------------------------------------- - - /* - TM_NX are initialized with calls to 'mount_pe' or 'mount_pp'. These both bind the machine to a tape, and mount the tape. Hence, there is no such thing as an initialized which is not bound to a tape. (It is possible to dismount the tm->hd, then remount tm->hd, but the tape remains bound through that process.) - - Because the TM_NX has no destructive operations, Once it is initialized the tape will never get shorter. With TM_MX it is not possible to mount an empty tape, because the minimum value of extent·AU is zero. Therefore the tape can never be empty. - - For an initialized TM_NX, TM_NX.array.hd == NULL means the tape is currently not mounted. - - C has no means of binding an operation to allocation apart from the initializer syntax, but the user might not initialize a tape machine after allocating one. There is no deterministic method available to a TM_NX to detect if a machine is uninitialized. However, if it happens that TM_NX.array.position == NULL, the only explanations are 1) a bug 2) the machine was not initialized - and the initialized data in TM_NX.array.position happened to be zero. - - It is an error to re-initialize the machine while it is being used, unfortunately this is a contract with the user, because the TM_NX has no way to detect if the machine was initialized in the first place. - - */ - - #ifndef CVT - struct{ - AU *position; - extent·AU extent·AU; - AU *hd; - }Core·TM_NX; - #endif - - #ifdef CVT - struct{ - CVT *position; - extent·AU extent·AU; - CVT *hd; - }Ξ(Core·TM_NX ,CVT); #endif //---------------------------------------- - // TM_NX implementation + // Map interface //---------------------------------------- - //----------------------------------- - // common error messages - - const char *Ξ(Core·TM_NX ,CVT)·Msg·tm="given NULL tm"; - const char *Ξ(Core·TM_NX ,CVT)·Msg·flag="given NULL flag pointer"; - const char *Ξ(Core·TM_NX ,CVT)·Msg·address= - "given NULL address pointer ,or address struct holds NULL address"; - const char *Ξ(Core·TM_NX ,CVT)·Msg·address_on_tape= - "given address is not on the tape"; - const char *Ξ(Core·TM_NX ,CVT)·Msg·extent·AU="given NULL extent·AU pointer"; - const char *Ξ(Core·TM_NX ,CVT)·Msg·position= - "Null position.This is only possible when the tape machine has not been initialized."; - - #ifndef CVT - Core·Status Core·TM_NX·topo(Core·TM_NX *tm ,Core·Tape·Topo *topo){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,topo ,"topo ptr is NULL, so nowhere to put result"); - Core·Guard·if_return(chk); - #endif - if(tm->extent·AU == 0){ - *topo = Core·Tape·Topo·singleton; - }else{ - *topo = Core·Tape·Topo·segment; - } - return Core·Status·on_track; - } - - // extent·AU is an AU index - Local Core·Status Core·TM_NX·extent·AU(Core·TM_NX *tm ,extent·AU *extent·AU){ - Core·Tape·Topo topo; - Core·Status status = Core·TM_NX_##CVT·topo(tm ,&topo); - boolean good_topo = - (status == Core·Status·on_track) && (topo & Core·Tape·Topo·finite_nz) - ; - - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,extent·AU ,Core·TM_NX·Msg·extent·AU); - Core·Guard·fg.check( - &chk ,0 ,good_topo - ,"Tape does not exist or topology does not have an extent·AU." - ); - Core·Guard·if_return(chk); - #endif - - if(!good_topo) return Core·Status·derailed; - *extent·AU = tm->array.extent·AU; - return Core·Status·on_track; - } - - #endif - - #ifdef CVT - - //----------------------------------- - // Area functions within Core·TM_NX_##CVT - - Core·Status Core·TM_NX_##CVT·topo(Core·TM_NX *tm ,Core·Tape·Topo *topo){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,topo ,"topo ptr is NULL, so nowhere to put result"); - Core·Guard·if_return(chk); - #endif - if(tm->extent·AU == 0){ - *topo = Core·Tape·Topo·singleton; - }else{ - *topo = Core·Tape·Topo·segment; - } - return Core·Status·on_track; - } - - - Local Core·Status Core·TM_NX_##CVT·mount_pe( - Core·TM_NX *tm ,void *position ,extent·AU extent·AU - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,position ,"given NULL position"); - Core·Guard·if_return(chk); - #endif - tm->array.position = position->array.address; - tm->array.extent·AU = extent·AU; - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·mount_pp( - Core·TM_NX *tm ,void *position_left ,void *position_right - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - bool good_address = position_left && position_left->address; - Core·Guard·fg.check(&chk ,1 ,good_address ,Core·TM_NX_##CVT·Msg·address); - good_address = position_right && position_right->address; - Core·Guard·fg.check(&chk ,1 ,good_address ,Core·TM_NX_##CVT·Msg·address); - if(position_left && position_right){ - Core·Guard·fg.check( - &chk ,1 ,position_right->array.address >= position_left->array.address - ,"position_right < position_left" - ); - } - Core·Guard·if_return(chk); - #endif - - extent·AU computed_extent·AU = - (extent·AU)( - (uintptr_t)position_right->array.address - (uintptr_t)position_left->array.address - ); - - return Core·TM_NX_##CVT·mount_pe(tm ,position_left ,computed_extent·AU); - } - - Local Core·Status Core·TM_NX_##CVT·largest_aligned_64( - Core·TM_NX *outer ,Core·TM_NX *inner_64 - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,outer ,"given NULL outer TM"); - if(outer){ - Core·Guard·fg.check(&chk ,1 ,outer->array.position ,"NULL outer->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,inner_64 ,"given NULL inner TM"); - Core·Guard·fg.check(&chk ,1 ,outer->array.position ,"outer TM has NULL position"); - Core·Guard·if_return(chk); - #endif - - uintptr_t p0 = (uintptr_t)outer->array.position; - uintptr_t p1 = (uintptr_t)outer->array.position + outer->array.extent·AU; - - CVT *p0_64 = (CVT *)( (p0 + 0x7) & ~(uintptr_t)0x7 ); - CVT *p1_64 = (CVT *)( (p1 - 0x7) & ~(uintptr_t)0x7 ); - - if(p1_64 < p0_64){ - inner_64->array.position = NULL; - inner_64->array.extent·AU = 0; - return Core·Status·derailed; - } - - inner_64->array.position = p0_64; - inner_64->array.extent·AU = (extent·AU)(p1_64 - p0_64); - return Core·Status·on_track; - } + #if !defined(CVT_read) || !defined(CVT_write) + typedef struct { + Map·Completion (*copy_byte_to_byte)( + Ξ(TM·Array ,AU) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ); - Local Core·Status Core·TM_NX_##CVT·encloses_pt( - Core·TM_NX *tm ,void *a ,bool *result - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - bool good_address = a && a->address; - Core·Guard·fg.check(&chk ,1 ,good_address ,Core·TM_NX_##CVT·Msg·address); - Core·Guard·fg.check(&chk ,1 ,result ,"given NULL result pointer"); - Core·Guard·if_return(chk); - #endif - - *result = - (a->array.address >= tm->array.position) - && (a->array.address <= tm->array.position + tm->array.extent·AU); - - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·encloses_pt_strictly( - Core·TM_NX *tm ,void *a ,bool *result - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - bool good_address = a && a->address; - Core·Guard·fg.check(&chk ,1 ,good_address ,Core·TM_NX_##CVT·Msg·address); - Core·Guard·fg.check(&chk ,1 ,result ,"given NULL result pointer"); - Core·Guard·if_return(chk); - #endif - - *result = - (a->array.address > tm->array.position) - && (a->array.address < tm->array.position + tm->array.extent·AU); - - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·encloses_tm( - Core·TM_NX *outer ,Core·TM_NX *inner ,bool *flag - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,outer ,"given NULL outer TM"); - if(outer){ - Core·Guard·fg.check(&chk ,1 ,outer->array.position ,"NULL outer->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,inner ,"given NULL inner TM"); - if(inner){ - Core·Guard·fg.check(&chk ,1 ,inner->array.position ,"NULL inner->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,flag ,"given NULL flag pointer"); - Core·Guard·if_return(chk); - #endif - - *flag = - (inner->array.position >= outer->array.position) - && (inner->array.position + inner->array.extent·AU <= outer->array.position + outer->array.extent·AU); - - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·encloses_tm_strictly( - Core·TM_NX *outer ,Core·TM_NX *inner ,bool *flag - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,outer ,"given NULL outer TM"); - if(outer){ - Core·Guard·fg.check(&chk ,1 ,outer->array.position ,"NULL outer->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,inner ,"given NULL inner TM"); - if(inner){ - Core·Guard·fg.check(&chk ,1 ,inner->array.position ,"NULL inner->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,flag ,"given NULL flag pointer"); - Core·Guard·if_return(chk); - #endif - - *flag = - (inner->array.position > outer->array.position) - && (inner->array.position + inner->array.extent·AU < outer->array.position + outer->array.extent·AU); - - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·overlap( - Core·TM_NX *a ,Core·TM_NX *b ,bool *result - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,a ,"given NULL TM A"); - if(a){ - Core·Guard·fg.check(&chk ,1 ,a->array.position ,"NULL a->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,b ,"given NULL TM B"); - if(b){ - Core·Guard·fg.check(&chk ,1 ,b->array.position ,"NULL b->array.position"); - } - Core·Guard·fg.check(&chk ,1 ,result ,"given NULL result pointer"); - Core·Guard·if_return(chk); - #endif - - *result = - (a->array.position < b->array.position + b->array.extent·AU) - && (b->array.position < a->array.position + a->array.extent·AU); - - return Core·Status·on_track; - } - - - //----------------------------------- - // base Tape Machine operations - - Local Core·Status Core·TM_NX_##CVT·mount(Core·TM_NX *tm){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,tm->array.position ,Core·TM_NX_##CVT·Msg·position); - Core·Guard·if_return(chk); - #endif - - tm->array.hd = tm->array.position; - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·dismount(Core·TM_NX *tm){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·if_return(chk); - #endif - - // Reset head position upon dismount - tm->array.hd = NULL; - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·status( - Core·TM_NX *tm ,Core·TM·Head·Status *status - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,status ,"given NULL status pointer"); - Core·Guard·if_return(chk); - #endif - - if(tm->array.hd == NULL){ - *status = Core·TM·Head·Status·not_on_tape; - }else if(tm->array.hd == tm->array.position){ - *status = Core·TM·Head·Status·origin; - }else if(tm->array.hd == tm->array.position + tm->array.extent·AU){ - *status = Core·TM·Head·Status·rightmost; - }else{ - *status = Core·TM·Head·Status·interim; - } - - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·can_read(Core·TM_NX *tm ,bool *flag){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - if(tm){ - // All initialized TM_NX_##CVT have an initialized position - // Maybe this catches that the machine is uninitialized? - Core·Guard·fg.check(&chk ,1 ,tm->array.position ,Core·TM_NX_##CVT·Msg·position); - } - Core·Guard·fg.check(&chk ,1 ,flag ,Core·TM_NX_##CVT·Msg·flag); - Core·Guard·if_return(chk); - #endif - *flag = tm && tm->array.hd != NULL; - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·on_origin( - Core·TM_NX *tm ,bool *flag - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,tm && tm->array.position ,Core·TM_NX_##CVT·Msg·position); - Core·Guard·fg.check(&chk ,1 ,flag ,Core·TM_NX_##CVT·Msg·flag); - Core·Guard·if_return(chk); - #endif - - *flag = (tm->array.hd == tm->array.position); - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·on_rightmost( - Core·TM_NX *tm ,bool *flag - ){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,flag ,Core·TM_NX_##CVT·Msg·flag); - Core·Guard·fg.check(&chk ,1 ,tm && tm->array.position ,Core·TM_NX_##CVT·Msg·position); - Core·Guard·if_return(chk); - #endif - - *flag = tm->array.hd == (tm->array.position + tm->array.extent·AU); - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·copy_datum(Core·TM_NX *tm_read ,Core·TM_NX *tm_write){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm_read ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,tm_write ,Core·TM_NX_##CVT·Msg·tm); - if(tm_read && tm_write){ - Core·Guard·fg.check( - &chk ,1 ,Core·TM_NX_##CVT·area.encloses_pt(tm_read ,tm_read->array.hd) - ,"Source address is outside tape bounds" - ); - Core·Guard·fg.check( - &chk ,1 ,Core·TM_NX_##CVT·area.encloses_pt(tm_write ,tm_write->array.hd) - ,"Destination address is outside tape bounds" - ); - } - Core·Guard·if_return(chk); - #endif - - *(tm_write->array.hd) = *(tm_read->array.hd); - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·read(Core·TM_NX *tm ,void *read_pt){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - if(tm) Core·Guard·fg.check(&chk ,1 ,tm->array.hd ,Core·TM_NX_##CVT·Msg·address); - if(tm && tm->array.hd){ - Core·Guard·fg.check( - &chk ,1 ,Core·TM_NX_##CVT·area.encloses_pt(tm ,tm->array.hd) - ,"Given address is outside tape bounds" - ); - } - Core·Guard·if_return(chk); - #endif - - *(CVT *)read_pt = *(tm_array.hd); - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·write(Core·TM_NX *tm ,void *write_pt){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - if(tm) Core·Guard·fg.check(&chk ,1 ,tm->array.hd ,Core·TM_NX_##CVT·Msg·address); - if(tm && tm->array.hd){ - Core·Guard·fg.check( - &chk ,1 ,Core·TM_NX_##CVT·area.encloses_pt(tm ,tm->array.hd) - ,"Given address is outside tape bounds" - ); - } - Core·Guard·if_return(chk); - #endif - - *(tm->array.hd) = *(CVT *)write_pt; - return Core·Status·on_track; - } - - Local Core·Status Core·TM_NX_##CVT·rewind(Core·TM_NX *tm){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - if(tm){ - Core·Guard·fg.check(&chk ,1 ,tm->array.position ,Core·TM_NX_##CVT·Msg·position); - } - Core·Guard·if_return(chk); - #endif - tm->array.hd = tm->array.position; - return Core·Status·on_track; - } - - Core·Status Core·TM_NX_##CVT·step(Core·TM_NX *tm){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,tm->array.position ,"step requested on unbound machine"); - Core·Guard·fg.check(&chk ,1 ,tm->array.hd ,"step requested but tape not mounted"); - Core·Guard·if_return(chk); - #endif - if( tm->array.hd < tm->array.position + tm->array.extent·AU ){ - tm->array.hd++; - return Core·Status·on_track; - } - return Core·Status·derailed; // Stepping beyond tape bounds - } - - Core·Status Core·TM_NX_##CVT·step_left(Core·TM_NX *tm){ - #ifdef Core·Debug - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,Core·TM_NX_##CVT·Msg·tm); - Core·Guard·fg.check(&chk ,1 ,tm->array.position - ,"step_left requested on unbound machine" - ); - Core·Guard·fg.check(&chk ,1 ,tm->array.hd - ,"step_left requested with no mounted head" - ); - Core·Guard·if_return(chk); - #endif - if( tm->array.hd > tm->array.position ){ - tm->array.hd--; - return Core·Status·on_track; - } - return Core·Status·derailed; // Stepping beyond left boundary - } - - // step_right is a synonym for step - - - //---------------------------------------- - // Initialization for Core·TM_NX_##CVT·fg - - Local Core·TM_NX·FG Core·TM_NX_##CVT·fg = { - .mount = Core·TM_NX_##CVT·mount - ,.dismount = Core·TM_NX_##CVT·dismount - - ,.status = Core·TM_NX_##CVT·status - ,.can_read = Core·TM_NX_##CVT·can_read - ,.on_origin = Core·TM_NX_##CVT·on_origin - ,.on_rightmost = Core·TM_NX_##CVT·on_rightmost - - ,.read = Core·TM_NX_##CVT·read - ,.write = Core·TM_NX_##CVT·write - - ,.rewind = Core·TM_NX_##CVT·rewind - ,.step = Core·TM_NX_##CVT·step - ,.step_left = Core·TM_NX_##CVT·step_left - ,.step_right = Core·TM_NX_##CVT·step_right // Synonym for step - - ,.area = { - .topo = Core·TM_NX_##CVT·topo - ,.extent·AU = Core·TM_NX_##CVT·extent·AU - - ,.mount_pe = Core·TM_NX_##CVT·mount_pe - ,.mount_pp = Core·TM_NX_##CVT·mount_pp - ,.largest_aligned_64 = Core·TM_NX_##CVT·largest_aligned_64 - - ,.encloses_pt = Core·TM_NX_##CVT·encloses_pt - ,.encloses_pt_strictly = Core·TM_NX_##CVT·encloses_pt_strictly - ,.encloses_tm = Core·TM_NX_##CVT·encloses_tm - ,.encloses_tm_strictly = Core·TM_NX_##CVT·encloses_tm_strictly - ,.overlap = Core·TM_NX_##CVT·overlap - } - }; - - #endif - - //---------------------------------------- - // Map implementation - //---------------------------------------- - - -Core·Map·Completion Core·map(TM_MX *tm_read ,TM_MX *tm_write ,Core·Map·Fn fn){ - - Core·Guard·init_collect(chk); - if(!fn) chk.flag |= Core·Map·Completion·null_fn; - bool tm_read_can_read=false ,tm_write_can_read=false; - Core·TM·Head·Status tm_read_status ,tm_write_status; - if( - tm_read->can_read(tm_read ,&tm_read_can_read) == Core·Status·derailed - || tm_write->can_read(tm_write ,&tm_write_can_read) == Core·Status·derailed - || !tm_read_can_read - || !tm_write_can_read - ){ - chk.flag |= Core·Map·Completion·no_tape_access; - } - Core·Guard·return(chk); - - do{ - TM_MX·Remote d_remote; - if( tm_read->read(tm_read ,&d_addr ,&d_remote) != Core·Status·on_track ){ - chk.flag |= Core·Map·Completion·failed; - break; - } - - TM_MX·Remote r_remote; - if(map->fn(&d_remote ,&r_remote) != Core·Status·on_track){ - chk.flag |= Core·Map·Completion·not_computable; - break; - } - - Core·TM_NX·Address r_addr; - if( tm_write->write(tm_write ,&r_addr ,&r_remote) != Core·Status·on_track ){ - chk.flag |= Core·Map·Completion·failed; - break; - } - - if( - tm_read->step(tm_read) != Core·Status·on_track - || tm_write->step(tm_write) != Core·Status·on_track - ){ - chk.flag |= Core·Map·Completion·failed; - break; - } - - tm_read->status(tm_read ,&tm_read_status); - tm_write->status(tm_write ,&tm_write_status); - - if( - tm_read_status & Core·TM·Head·Status·rightmost - && tm_write_status & Core·TM·Head·Status·rightmost - ){ - chk.flag |= Core·Map·Completion·perfect_fit; - break; - } - - if(tm_read_status & Core·TM·Head·Status·rightmost){ - chk.flag |= Core·Map·Completion·read_surplus; - break; - } - - if(tm_write_status & Core·TM·Head·Status·rightmost){ - chk.flag |= Core·Map·Completion·write_available; - break; - } - - }while(true); - - Core·Guard·return(chk); -} - - - // Map function using trampoline execution model - Local Core·Map·Status Core·map(Core·Map·Fn fn){ - #ifdef Core·Debug - if(!fn){ - fprintf(stderr,"Core·map:: given null function"); - return Core·Map·argument_guard; - } - if( - true - && fn != Core·Map·by_##CVT - && fn != Core·Map·##CVT_by_##CVT - && fn != Core·write_hex - && fn != Core·read_hex - ){ - fprintf(stderr,"Core·map:: unrecognized copy function\n"); - return Core·Map·argument_guard; - ) - #endif - - while(fn) fn = fn(); - return tf.copy.status; - } - - - - //---------------------------------------- - // copy byte_by_byte - //---------------------------------------- - - Core·Map·Fn Core·Map·Map·ByteByByte·perfect_fit; - Core·Map·Fn Core·Map·Map·ByteByByte·read_surplus; - Core·Map·Fn Core·Map·Map·ByteByByte·write_available; - - Local Core·Map·Fn Core·Map·##CVT_by_##CVT(){ - if(Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) == Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)) - return Core·Map·ByteByByte·perfect_fit; - - if(Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) > Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)) - return Core·Map·ByteByByte·read_surplus; - - return Core·Map·ByteByByte·write_available; - } - - Local Core·Map·Fn Core·Map·ByteByByte·perfect_fit(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - - do{ - **w = Core·tf.copy.read_fn_8(Core·tf.copy.read ,*r); - if(*r == r1) break; - (*r)++; - (*w)++; - }while(true); - - Core·tf.copy.status = Core·Map·Status·perfect_fit; - return NULL; - } - - Local Core·Map·Fn Core·Map·ByteByByte·read_surplus(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - CVT *w1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - - do{ - **w = Core·tf.copy.read_fn_8(Core·tf.copy.read ,*r); - if(*w == w1) break; - (*r)++; - (*w)++; - }while(true); - - Core·tf.copy.status = Core·Map·Status·write_available; - return NULL; - } - - Local Core·Map·Fn Core·Map·ByteByByte·write_avalable(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - - do{ - **w = Core·tf.copy.read_fn_8(Core·tf.copy.read ,*r); - if(*r == r1) break; - (*r)++; - (*w)++; - }while(true); - - Core·tf.copy.status = Core·Map·Status·read_surplus; - return NULL; - } - - //---------------------------------------- - // copy copy_64 - - // 64-bit copy function with updated TableauFace terminology - Core·Map·Fn Core·Map·by_##CVT; - Core·Map·Fn Core·Map·ByWord64·leadin; - Core·Map·Fn Core·Map·ByWord64·bulk; - Core·Map·Fn Core·Map·ByWord64·tail; - - // Initialize the copy_64 process - Local Core·Map·Fn Core·Map·by_##CVT(){ - // Determine the largest 64-bit aligned region within the read area - Core·TM_NX_##CVT·largest_aligned_64(Core·tf.copy.read ,&Core·tl.copy_64.area_64); - - // Choose the correct function based on alignment - if(Core·TM_NX_##CVT·empty(&Core·tl.copy_64.area_64)) return Core·Map·ByWord64·tail; - if(Core·is_aligned_on_64(Core·TM_NX_##CVT·position(Core·tf.copy.read))) return Core·Map·ByWord64·bulk; - return Core·Map·ByWord64·leadin; - } - - // Lead-in byte copy (until alignment) - Local Core·Map·Fn Core·Map·ByWord64·leadin(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r0_64 = Core·TM_NX_##CVT·position(&Core·tl.copy_64.area_64); - CVT **w = &Core·tf.copy.write_pt; - - do{ - **w = Core·tf.copy.read_fn_8(Core·tf.copy.read ,r0_64 ,*r); - if(*r == r0_64) break; - (*r)++; - (*w)++; - }while(true); - - return Core·Map·ByWord64·bulk; - } - - // Bulk word copy - Local Core·Map·Fn Core·Map·ByWord64·bulk(){ - uint64_t **r = (uint64_t **)&Core·tf.copy.read_pt; - uint64_t **w = (uint64_t **)&Core·tf.copy.write_pt; - uint64_t *r1_64 = Core·TM_NX_##CVT·position_right(&Core·tl.copy_64.area_64); - - do{ - **w = Core·tf.copy.read_fn_64(Core·tf.copy.read ,r1_64 ,*r); - if(*r == r1_64) break; - (*r)++; - (*w)++; - }while(true); - - return Core·Map·ByWord64·tail; - } - - // Tail byte copy (unaligned trailing bytes) - Local Core·Map·Fn Core·Map·ByWord64·tail(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(&Core·tl.copy_64.area_64); - CVT **w = &Core·tf.copy.write_pt; - - do{ - **w = Core·tf.copy.read_fn_8(Core·tf.copy.read ,r1 ,*r); - if(*r == r1) break; - (*r)++; - (*w)++; - }while(true); - - Core·tf.copy.status = Core·Map·Status·perfect_fit; - return NULL; - } - - //---------------------------------------- - // copy write hex - - Local uint16_t Core·byte_to_hex(CVT byte){ - static const char hex_digits[] = "0123456789ABCDEF"; - return - (hex_digits[byte >> 4] << 8) - | hex_digits[byte & 0x0F]; - } - - // Forward Declarations - Core·Map·Fn Core·Map·write_hex; - Core·Map·Fn Core·Map·WriteHex·perfect_fit; - Core·Map·Fn Core·Map·WriteHex·read_surplus; - Core·Map·Fn Core·Map·WriteHex·write_available; - - // Hex Encoding: Initialize Map - Local Core·Map·Fn Core·Map·write_hex(){ - if(Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) == (Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write) >> 1)){ - return Core·Map·WriteHex·perfect_fit; - } - if(Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) > (Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write) >> 1)){ - return Core·Map·WriteHex·read_surplus; - } - return Core·Map·WriteHex·write_available; - } - - Local Core·Map·Fn Core·Map·WriteHex·perfect_fit(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - - do { - *(uint16_t *)*w = Core·hex.byte_to_hex(**r); - if(*r == r1) break; - (*r)++; - (*w) += 2; - } while(true); - - Core·tf.copy.status = Core·Map·Status·perfect_fit; - return NULL; - } - - // Hex Encoding: Read Surplus - Local Core·Map·Fn Core·Map·WriteHex·read_surplus(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - CVT **w = &Core·tf.copy.write_pt; - - do { - *(uint16_t *)*w = Core·write_hex.byte_to_hex(**r); - if(*r == r1) break; - (*r)++; - (*w) += 2; - } while(true); - - Core·tf.copy.status = Core·Map·Status·read_surplus; - return NULL; - } - - // Hex Encoding: Write Available - Local Core·Map·Fn Core·Map·WriteHex·write_available(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - CVT *w1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - - do { - *(uint16_t *)*w = Core·write_hex.byte_to_hex(**r); - if(*w == w1) break; - (*r)++; - (*w) += 2; - } while(true); - - Core·tf.copy.status = Core·Map·Status·write_available; - return NULL; - } - - //---------------------------------------- - // copy read hex - - Local CVT Core·hex_to_byte(uint16_t hex){ - CVT high = hex >> 8; - CVT low = hex & 0xFF; - - high = - (high >= '0' && high <= '9') ? (high - '0') - : (high >= 'A' && high <= 'F') ? (high - 'A' + 10) - : (high >= 'a' && high <= 'f') ? (high - 'a' + 10) - : 0; - - low = - (low >= '0' && low <= '9') ? (low - '0') - : (low >= 'A' && low <= 'F') ? (low - 'A' + 10) - : (low >= 'a' && low <= 'f') ? (low - 'a' + 10) - : 0; - - return (high << 4) | low; - } - - Core·Map·Fn Core·Map·read_hex; - Core·Map·Fn Core·Map·ReadHex·perfect_fit; - Core·Map·Fn Core·Map·ReadHex·read_surplus; - Core·Map·Fn Core·Map·ReadHex·write_available; - - Local Core·Map·Fn Core·Map·read_hex(){ - if((Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) >> 1) == Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)){ - return Core·Map·ReadHex·perfect_fit; - } - if((Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) >> 1) > Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)){ - return Core·Map·ReadHex·read_surplus; - } - return Core·Map·ReadHex·write_available; - } - - Local Core·Map·Fn Core·Map·ReadHex·perfect_fit(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - - do { - **w = Core·hex_to_byte(*(uint16_t *)*r); - if(*r == r1) break; - (*r) += 2; - (*w)++; - } while(true); - - Core·tf.copy.status = Core·Map·Status·perfect_fit; - return NULL; - } - - Local Core·Map·Fn Core·Map·ReadHex·read_surplus(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - CVT **w = &Core·tf.copy.write_pt; - - do { - **w = Core·tf.read_hex.hex_to_byte(*(uint16_t *)*r); - if(*r == r1) break; - (*r) += 2; - (*w)++; - } while(true); - - Core·tf.copy.status = Core·Map·Status·read_surplus; - return NULL; - } - - Local Core·Map·Fn Core·Map·ReadHex·write_available(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - CVT *w1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - - do { - **w = Core·tf.read_hex.hex_to_byte(*(uint16_t *)*r); - if(*w == w1) break; - (*r) += 2; - (*w)++; - } while(true); - - Core·tf.copy.status = Core·Map·Status·write_available; - return NULL; - } - - //---------------------------------------- - // copy read hex - - Core·Map·Fn Core·Map·read_hex; - Core·Map·Fn Core·Map·ReadHex·perfect_fit; - Core·Map·Fn Core·Map·ReadHex·read_surplus; - Core·Map·Fn Core·Map·ReadHex·write_available; + Map·Completion (*copy_hex_to_byte)( + Ξ(TM·Array ,uint16_t) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ); - Local Core·Map·Fn Core·Map·read_hex(){ - if((Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) >> 1) == Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)){ - return Core·Map·ReadHex·perfect_fit; - } - if((Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.read) >> 1) > Core·TM_NX_##CVT·extent_by·AU(Core·tf.copy.write)){ - return Core·Map·ReadHex·read_surplus; - } - return Core·Map·ReadHex·write_available; - } + Map·Completion (*copy_byte_to_hex)( + Ξ(TM·Array ,AU) *read_tm + ,Ξ(TM·Array ,uint16_t) *write_tm + ); - Local Core·Map·Fn Core·Map·ReadHex·perfect_fit(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; + // Terminate string function + Map·Completion (*terminate_string)( + Ξ(TM·Array ,AU) *write_tm + ); + } Map·FG; - do { - **w = Core·hex_to_byte(*(uint16_t *)*r); - if(*r == r1) break; - (*r) += 2; - (*w)++; - } while(true); + // a default function given table + Map·FG Map·fg; - Core·tf.copy.status = Core·Map·Status·perfect_fit; - return NULL; - } + #endif - Local Core·Map·Fn Core·Map·ReadHex·read_surplus(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); - CVT **w = &Core·tf.copy.write_pt; - do { - **w = Core·hex_to_byte(*(uint16_t *)*r); - if(*r == r1) break; - (*r) += 2; - (*w)++; - } while(true); + #if defined(CVT_read) && defined(CVT_write) - Core·tf.copy.status = Core·Map·Status·read_surplus; - return NULL; - } + // Function passed to map type signature must be this: + typedef Core·Status (*Ξ(Map·fn ,CVT_read ,CVT_write))( + CVT_read *read_value + ,CVT_write *write_value + ); - Local Core·Map·Fn Core·Map·ReadHex·write_available(){ - CVT **r = &Core·tf.copy.read_pt; - CVT *r1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.read); - CVT **w = &Core·tf.copy.write_pt; - CVT *w1 = Core·TM_NX_##CVT·position_right(Core·tf.copy.write); + typedef struct { + // Map a function over all elements from read_tm to write_tm + Map·Completion (*map)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ); - do { - **w = Core·hex_to_byte(*(uint16_t *)*r); - if(*w == w1) break; - (*r) += 2; - (*w)++; - } while(true); + // Map a function over elements from read_tm to write_tm until a condition is met + Map·Completion (*map_while)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,bool (*condition)(Ξ(TM·Array ,CVT_read) *read_tm) + ); - Core·tf.copy.status = Core·Map·Status·write_available; - return NULL; - } + // Map a function over n elements from read_tm to write_tm + Map·Completion (*map_extent)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,Ξ(extent_t ,CVT_read) extent + ); + } Ξ(Map·FG ,CVT_read ,CVT_write); + // Default function given table + Ξ(Map·FG ,CVT_read ,CVT_write) Ξ(Map·fg ,CVT_read ,CVT_write); - #endif // LOCAL + #endif -#endif // IMPLEMENTATION +#endif // #ifndef Map·FACE diff --git "a/developer/cc\360\237\226\211/Map2.lib.c" "b/developer/cc\360\237\226\211/Map2.lib.c" new file mode 100644 index 0000000..931c0c2 --- /dev/null +++ "b/developer/cc\360\237\226\211/Map2.lib.c" @@ -0,0 +1,500 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* Map - mapping functions between tape machines. + + This file has two template parameters: + `CVT_read` Cell Value Type for the source/read tape machine + `CVT_write` Cell Value Type for the destination/write tape machine + + By default (when the macros have no definition) the cell value types are taken as AU. + This file must be included with CVT_read and CVT_write undefined, before inclusions with them defined. + + 'Tape' is operated on by the Tape Machine. + 'Area' is subset of an address space that is used as a virtual Tape by a machine. + An Area with zero elements has 'length == 0' or is 'empty'. + In contrast, and area located (position specified) with a null pointer is said not to exist. +*/ + +#define Map·DEBUG + +#ifndef FACE + #define Map·IMPLEMENTATION + #define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef Map·FACE + #define Map·FACE + + #include + #include + #include "Core.lib.c" + #include "TM.lib.c" + + // if only one template parameter is given, we will assume both are the same + + #if defined(CVT_read) && !defined(CVT_write) + #warning "Given CVT_read template value. Missing CVT_write template value, so setting it to CVT_read" + #define CVT_write CVT_read + #endif + + #if !defined(CVT_read) && defined(CVT_write) + #warning "Given CVT_write template value. Missing CVT_read template value, so setting it to CVT_write" + #define CVT_read CVT_write + #endif + + //---------------------------------------- + // Map status and completion enums + //---------------------------------------- + + #if !defined(CVT_read) && !defined(CVT_write) + + typedef enum { + Map·Completion·mu = 0 + ,Map·Completion·failed = 1 + ,Map·Completion·null_fn = 1 << 1 + ,Map·Completion·no_tape_access = 1 << 2 + ,Map·Completion·rightmost_read = 1 << 3 + ,Map·Completion·rightmost_write = 1 << 4 + } Map·Completion; + + // Masks for combinations + const uint Map·Completion·rightmost_both = + Map·Completion·rightmost_read + | Map·Completion·rightmost_write + ; + + const uint Map·Completion·derailed = + Map·Completion·failed + | Map·Completion·null_fn + | Map·Completion·no_tape_access + ; + + const uint Map·Completion·on_track = + Map·Completion·rightmost_read + | Map·Completion·rightmost_write + | Map·Completion·rightmost_both + ; + + #endif + + //---------------------------------------- + // Map interface + //---------------------------------------- + + #if !defined(CVT_read) || !defined(CVT_write) + typedef struct { + Map·Completion (*copy_byte_to_byte)( + Ξ(TM·Array ,AU) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ); + + Map·Completion (*copy_hex_to_byte)( + Ξ(TM·Array ,uint16_t) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ); + + Map·Completion (*copy_byte_to_hex)( + Ξ(TM·Array ,AU) *read_tm + ,Ξ(TM·Array ,uint16_t) *write_tm + ); + + // Terminate string function + Map·Completion (*terminate_string)( + Ξ(TM·Array ,AU) *write_tm + ); + } + #endif + + + #if defined(CVT_read) && defined(CVT_write) + + // Function passed to map type signature must be this: + typedef Core·Status (*Ξ(Map·fn ,CVT_read ,CVT_write))( + CVT_read *read_value + ,CVT_write *write_value + ); + + typedef struct { + // Map a function over all elements from read_tm to write_tm + Map·Completion (*map)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ); + + // Map a function over elements from read_tm to write_tm until a condition is met + Map·Completion (*map_while)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,bool (*condition)(Ξ(TM·Array ,CVT_read) *read_tm) + ); + + // Map a function over n elements from read_tm to write_tm + Map·Completion (*map_extent)( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,Ξ(extent_t ,CVT_read) extent + ); + + } Ξ(Map·FG ,CVT_read ,CVT_write); + + // Default function given table + Ξ(Map·FG ,CVT_read ,CVT_write) Ξ(Map·fg ,CVT_read ,CVT_write); + #endif // !defined(CVT_read) && !defined(CVT_write) + +#endif // #ifndef Map·FACE + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef Map·IMPLEMENTATION + + // declarations available to all of the IMPLEMENTATION go here + #ifdef Map·DEBUG + #include + #endif + + // implementation to go into the lib.a file + #ifndef LOCAL + #endif + + #ifdef LOCAL + //---------------------------------------- + // Map implementation + //---------------------------------------- + + #if !defined(CVT_read) && !defined(CVT_write) + //----------------------------------- + // common error messages + const char *Map·Msg·read_tm = "given NULL read_tm"; + const char *Map·Msg·write_tm = "given NULL write_tm"; + const char *Map·Msg·map_fn = "given NULL map_fn"; + const char *Map·Msg·condition = "given NULL condition function"; + + //----------------------------------- + // Helper functions for copy operations + + // Byte to byte copy function + Local Core·Status Map·byte_to_byte_fn(AU *read_value, AU *write_value) { + *write_value = *read_value; + return Core·Status·on_track; + } + + // Hex to byte conversion function + Local Core·Status Map·hex_to_byte_fn(uint16_t *read_value, AU *write_value) { + // Convert hex value to byte + *write_value = (AU)(*read_value & 0xFF); + return Core·Status·on_track; + } + + // Byte to hex conversion function + Local Core·Status Map·byte_to_hex_fn(AU *read_value, uint16_t *write_value) { + // Convert byte to lowercase hex representation (no prefix) + static const char hex_chars[] = "0123456789abcdef"; + *write_value = hex_chars[(*read_value >> 4) & 0x0F]; + return Core·Status·on_track; + } + #endif // !defined(CVT_read) && !defined(CVT_write) + + #if defined(CVT_read) && defined(CVT_write) + //----------------------------------- + // Map implementation with specific types + + // Map a function over all elements from read_tm to write_tm + Local Core·Status Ξ(Map ,CVT_read ,CVT_write)·map( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ){ + #ifdef Map·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,read_tm ,Map·Msg·read_tm); + Core·Guard·fg.check(&chk ,1 ,write_tm ,Map·Msg·write_tm); + Core·Guard·fg.check(&chk ,1 ,map_fn ,Map·Msg·map_fn); + Core·Guard·if_return(chk); + #endif + + // Rewind both tape machines to ensure we start at the beginning + Ξ(TM·Array ,CVT_read)·fg.rewind(read_tm); + Ξ(TM·Array ,CVT_write)·fg.rewind(write_tm); + + // Initial check if can_read (not part of the loop) + if(!Ξ(TM·Array ,CVT_read)·fg.can_read(read_tm)) return Core·Status·on_track; + + // Track completion status + uint completion = 0; + + // Following the first-rest pattern described in TTCA + while(1){ + // Read value from source + CVT_read read_value; + Ξ(TM·Array ,CVT_read)·fg.read(read_tm ,&read_value); + + // Apply mapping function to get write value + CVT_write write_value; + Core·Status status = map_fn(&read_value ,&write_value); + if(status != Core·gStatus·on_track) { + completion |= Core·Map·Completion·failed; + return status; + } + + // Write result to destination + Ξ(TM·Array ,CVT_write)·fg.write(write_tm ,&write_value); + + // Check if we're at the rightmost position for read + bool read_rightmost = Ξ(TM·Array ,CVT_read)·fg.on_rightmost(read_tm); + if(read_rightmost) { + completion |= Core·Map·Completion·rightmost_read; + } + + // Check if we're at the rightmost position for write + bool write_rightmost = Ξ(TM·Array ,CVT_write)·fg.on_rightmost(write_tm); + if(write_rightmost) { + completion |= Core·Map·Completion·rightmost_write; + } + + // Break if either machine is at rightmost + if(read_rightmost || write_rightmost) break; + + // Step both machines + Ξ(TM·Array ,CVT_read)·fg.step(read_tm); + Ξ(TM·Array ,CVT_write)·fg.step(write_tm); + } + + return Core·Status·on_track; + } + + // Map a function over elements from read_tm to write_tm until a condition is met + Local Core·Status Ξ(Map ,CVT_read ,CVT_write)·map_while( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,bool (*condition)(CVT_read *value) + ){ + #ifdef Map·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,read_tm ,Map·Msg·read_tm); + Core·Guard·fg.check(&chk ,1 ,write_tm ,Map·Msg·write_tm); + Core·Guard·fg.check(&chk ,1 ,map_fn ,Map·Msg·map_fn); + Core·Guard·fg.check(&chk ,1 ,condition ,Map·Msg·condition); + Core·Guard·if_return(chk); + #endif + + // Rewind both tape machines to ensure we start at the beginning + Ξ(TM·Array ,CVT_read)·fg.rewind(read_tm); + Ξ(TM·Array ,CVT_write)·fg.rewind(write_tm); + + // Initial check if can_read (not part of the loop) + if(!Ξ(TM·Array ,CVT_read)·fg.can_read(read_tm)) return Core·Status·on_track; + + // Track completion status + uint completion = 0; + + // Following the first-rest pattern described in TTCA + while(1){ + // Read value from source + CVT_read read_value; + Ξ(TM·Array ,CVT_read)·fg.read(read_tm ,&read_value); + + // Check condition + if(!condition(&read_value)) break; + + // Apply mapping function to get write value + CVT_write write_value; + Core·Status status = map_fn(&read_value ,&write_value); + if(status != Core·Status·on_track) { + completion |= Core·Map·Completion·failed; + return status; + } + + // Write result to destination + Ξ(TM·Array ,CVT_write)·fg.write(write_tm ,&write_value); + + // Check if we're at the rightmost position for read + bool read_rightmost = Ξ(TM·Array ,CVT_read)·fg.on_rightmost(read_tm); + if(read_rightmost) { + completion |= Core·Map·Completion·rightmost_read; + } + + // Check if we're at the rightmost position for write + bool write_rightmost = Ξ(TM·Array ,CVT_write)·fg.on_rightmost(write_tm); + if(write_rightmost) { + completion |= Core·Map·Completion·rightmost_write; + } + + // Break if either machine is at rightmost + if(read_rightmost || write_rightmost) break; + + // Step both machines + Ξ(TM·Array ,CVT_read)·fg.step(read_tm); + Ξ(TM·Array ,CVT_write)·fg.step(write_tm); + } + + return Core·Status·on_track; + } + + // Map a function over n elements from read_tm to write_tm + Local Core·Status Ξ(Map ,CVT_read ,CVT_write)·map_n( + Ξ(TM·Array ,CVT_read) *read_tm + ,Ξ(TM·Array ,CVT_write) *write_tm + ,Ξ(Map·fn ,CVT_read ,CVT_write) map_fn + ,size_t n + ){ + #ifdef Map·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,read_tm ,Map·Msg·read_tm); + Core·Guard·fg.check(&chk ,1 ,write_tm ,Map·Msg·write_tm); + Core·Guard·fg.check(&chk ,1 ,map_fn ,Map·Msg·map_fn); + Core·Guard·if_return(chk); + #endif + + // Rewind both tape machines to ensure we start at the beginning + Ξ(TM·Array ,CVT_read)·fg.rewind(read_tm); + Ξ(TM·Array ,CVT_write)·fg.rewind(write_tm); + + // Initial check if can_read (not part of the loop) + if(!Ξ(TM·Array ,CVT_read)·fg.can_read(read_tm)) return Core·Status·on_track; + + // Track completion status + uint completion = 0; + + // Following the first-rest pattern described in TTCA + size_t count = 0; + while(count < n){ + // Read value from source + CVT_read read_value; + Ξ(TM·Array ,CVT_read)·fg.read(read_tm ,&read_value); + + // Apply mapping function to get write value + CVT_write write_value; + Core·Status status = map_fn(&read_value ,&write_value); + if(status != Core·Status·on_track) { + completion |= Core·Map·Completion·failed; + return status; + } + + // Write result to destination + Ξ(TM·Array ,CVT_write)·fg.write(write_tm ,&write_value); + + // Increment count + count++; + + // Check if we're at the rightmost position for read + bool read_rightmost = Ξ(TM·Array ,CVT_read)·fg.on_rightmost(read_tm); + if(read_rightmost) { + completion |= Core·Map·Completion·rightmost_read; + } + + // Check if we're at the rightmost position for write + bool write_rightmost = Ξ(TM·Array ,CVT_write)·fg.on_rightmost(write_tm); + if(write_rightmost) { + completion |= Core·Map·Completion·rightmost_write; + } + + // Break if either machine is at rightmost + if(read_rightmost || write_rightmost) break; + + // Step both machines + Ξ(TM·Array ,CVT_read)·fg.step(read_tm); + Ξ(TM·Array ,CVT_write)·fg.step(write_tm); + } + + return Core·Status·on_track; + } + + // Initialize the function given table + Ξ(Map·FG ,CVT_read ,CVT_write) Ξ(Map·fg ,CVT_read ,CVT_write) = { + .map = Ξ(Map ,CVT_read ,CVT_write)·map + ,.map_while = Ξ(Map ,CVT_read ,CVT_write)·map_while + ,.map_n = Ξ(Map ,CVT_read ,CVT_write)·map_n + }; + #endif // defined(CVT_read) && defined(CVT_write) + + //---------------------------------------- + // Copy functions implementation + //---------------------------------------- + + // Byte to byte copy + Local Core·Status Map·copy_byte_to_byte( + Ξ(TM·Array ,AU) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ){ + #ifdef Map·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,read_tm ,Map·Msg·read_tm); + Core·Guard·fg.check(&chk ,1 ,write_tm ,Map·Msg·write_tm); + Core·Guard·if_return(chk); + #endif + + return Ξ(Map ,AU ,AU)·fg.map(read_tm, write_tm, Map·byte_to_byte_fn); + } + + // Hex to byte copy + Local Core·Status Map·copy_hex_to_byte( + Ξ(TM·Array ,uint16_t) *read_tm + ,Ξ(TM·Array ,AU) *write_tm + ){ + #ifdef Map·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,read_tm ,Map·Msg·read_tm); + Core·Guard·fg.check(&chk ,1 ,write_tm ,Map·Msg·write_tm); + Core·Guard·if_return(chk); + #endif + + return To save on context only part of this file has been shown to you. You should retry this tool after you have searched inside the file with `grep -n` in order to find the line numbers of what you are looking for. diff --git "a/developer/cc\360\237\226\211/TM.lib.c" "b/developer/cc\360\237\226\211/TM.lib.c" index 947bbed..9936426 100644 --- "a/developer/cc\360\237\226\211/TM.lib.c" +++ "b/developer/cc\360\237\226\211/TM.lib.c" @@ -13,6 +13,8 @@ An Area with zero elements has 'length == 0' or is 'empty'. In contrast ,and area located (position specified) with a null pointer is said not to exist. + Template variable: CVT + */ #define TM·DEBUG @@ -22,11 +24,16 @@ #define FACE #endif +#if defined(Array) && !defined(CVT) + #error "Array implementation requires CVT to be defined" +#endif + + //-------------------------------------------------------------------------------- // Interface -#ifndef TM·FACE -#define TM·FACE +#ifndef Ξ(TM·FACE ,CVT) +#define Ξ(TM·FACE ,CVT) #include #include @@ -68,48 +75,61 @@ | TM·Head·Status·interim | TM·Head·Status·rightmost ; - #endif // #ifndef CVT - #ifndef CVT - typedef struct Ξ(TM·Array ,CVT); + typedef struct TM; // tape and area are included with Tape Machine to facilitate abstract interfaces. typedef struct{ struct { - Core·Status (*topo) ( Ξ(TM·Array ,CVT) *tm ,TM·Tape·Topo *result ); - Ξ(extent_t ,CVT) (*extent)( Ξ(TM·Array ,CVT) *tm ); + Core·Status (*topo) ( TM *tm ,TM·Tape·Topo *result ); + Ξ(extent_t ,CVT) (*extent)( TM *tm ); } tape; struct { // Initialize tm - Core·Status (*mount_pe)(Ξ(TM·Array ,CVT) *tm ,CVT position[] ,Ξ(extent_t ,CVT) extent); - Core·Status (*mount_pp)(Ξ(TM·Array ,CVT) *tm ,CVT *position_left ,CVT *position_right); + Core·Status (*mount_pe)(TM *tm ,CVT position[] ,Ξ(extent_t ,CVT) extent); + Core·Status (*mount_pp)(TM *tm ,CVT *position_left ,CVT *position_right); } area; // tape machine functions - Core·Status (*mount) (Ξ(TM·Array ,CVT) *tm); - Core·Status (*dismount)(Ξ(TM·Array ,CVT) *tm); + Core·Status (*mount) (TM *tm); + Core·Status (*dismount)(TM *tm); - TM·Head·Status (*status) (Ξ(TM·Array ,CVT) *tm ,TM·Head·Status *status); - Core·Status (*head_on_format)(Ξ(TM·Array ,CVT) *tm ,bool *flag); + TM·Head·Status (*status) (TM *tm ,TM·Head·Status *status); + Core·Status (*head_on_format)(TM *tm ,bool *flag); - bool (*can_read) (Ξ(TM·Array ,CVT) *tm); - bool (*on_origin) (Ξ(TM·Array ,CVT) *tm); - bool (*on_rightmost)(Ξ(TM·Array ,CVT) *tm); + bool (*can_read) (TM *tm); + bool (*on_leftmost) (TM *tm); + bool (*on_rightmost)(TM *tm); - void (*step) (Ξ(TM·Array ,CVT) *tm); - void (*step_left) (Ξ(TM·Array ,CVT) *tm); - void (*step_right)(Ξ(TM·Array ,CVT) *tm); // Synonym for step - void (*rewind) (Ξ(TM·Array ,CVT) *tm); + void (*step) (TM *tm); + void (*step_left) (TM *tm); + void (*step_right)(TM *tm); // Synonym for step + void (*rewind) (TM *tm); - void (*copy_datum)( Ξ(TM·Array ,CVT) *tm_read ,Ξ(TM·Array ,CVT) *tm_write ); - void (*read) ( Ξ(TM·Array ,CVT) *tm ,CVT *remote_pt ); - void (*write) ( Ξ(TM·Array ,CVT) *tm ,CVT *remote_pt ); + void (*copy_datum)( TM *tm_read ,TM *tm_write ); + void (*apply)( TM *tm_read , TM·FN); - } Ξ(TM·Array ,CVT)·FG; + } TM·FG; - Ξ(TM·Array ,CVT)·FG Ξ(TM·Array ,CVT)·fg; + + #endif // #ifndef CVT + + #ifdef CVT + + + typedef struct{ + + void (*read) ( TM *tm ,CVT *remote_pt ); + void (*write) ( TM *tm ,CVT *remote_pt ); + + } Ξ(TM ,CVT); + + // default table for TM implemented by an Array + #ifdef Array + Ξ(TM ,CVT)·FG Ξ(TM·Array ,CVT)·fg; + #endif #endif // #ifdef CVT @@ -132,6 +152,321 @@ #ifdef LOCAL + //---------------------------------------- + // Dispatch wrapper + //---------------------------------------- + + #ifndef CVT + + //----------------------------------- + // common error messages + + const char *TM·Array·Msg·tm="given NULL tm"; + const char *TM·Array·Msg·flag="given NULL flag pointer"; + const char *TM·Array·Msg·result="given NULL result pointer"; + const char *TM·Array·Msg·position= + "Null position.This is only possible when the tape machine has not been initialized."; + + #endif // #ifndef CVT + + #ifdef CVT + + struct{ + Ξ(TM ,CVT)·FG *fg + }Ξ(TM ,CVT); + + //----------------------------------- + // TM·Array.tape implementation + + /* + For an Array Tape Machine ,a bound tape will be singleton or segment. + An initialized Array Tape Machine always has a bound tape. + */ + Core·Status Ξ(TM ,CVT)·topo(Ξ(TM·Array ,CVT) *tm ,TM·Tape·Topo *result){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + Core·Guard·fg.check(&chk ,1 ,result ,TM·Array·Msg·result); + Core·Guard·if_return(chk); + #endif + if(tm->extent == 0){ + *result = TM·Tape·Topo·singleton; + }else{ + *result = TM·Tape·Topo·segment; + } + return Core·Status·on_track; + } + + // check the topo to make sure tape has extent before calling this + // `extent·CVT` returns the index to the rightmost cell in the array. + Local Ξ(extent_t ,CVT) Ξ(TM·Array ,CVT)·extent(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Tape·Topo topo = Core·Tape·Topo·mu; + Core·Status status = Ξ(TM·Array ,CVT)·topo(tm ,&topo); + bool good_topo = + (status == Core·Status·on_track) && (topo & Core·Tape·Topo·finite_nz) + ; + Core·Guard·fg.check(&chk ,1 ,good_topo ,"Tape does not have an extent."); + Core·Guard·assert(chk); + #endif + + *result = tm->extent; + return Core·Status·on_track; + } + + //----------------------------------- + // TM·Array.area implementation + + Local Core·Status Ξ(TM·Array ,CVT)·mount_pe( + Ξ(TM·Array ,CVT) *tm ,CVT *position ,Ξ(extent_t ,CVT) extent + ){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + Core·Guard·fg.check(&chk ,1 ,position ,"Given NULL position."); + Core·Guard·if_return(chk); + #endif + tm->position = position; + tm->extent = extent; + tm->hd = position; // mount the head on the origin cell + return Core·Status·on_track; + } + + // If size of CVT is not a power of two this can perform a divide + Local Core·Status Ξ(TM·Array ,CVT)·mount_pp( + Ξ(TM·Array ,CVT) *tm ,CVT *pos_leftmost ,CVT *pos_rightmost + ){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,pos_leftmost ,"Null pos_leftmost."); + Core·Guard·fg.check(&chk ,1 ,pos_rightmost ,"Null pos_rightmost."); + if(pos_leftmost && pos_rightmost){ + Core·Guard·fg.check(&chk ,1 ,pos_rightmost >= pos_leftmost + ,"pos_rightmost < pos_leftmost" + ); + } + Core·Guard·if_return(chk); + #endif + + Ξ(extent_t ,CVT) extent = pos_rightmost - pos_leftmost); + return Ξ(TM·Array ,CVT)·mount_pe(tm ,pos_leftmost ,extent); + } + + //----------------------------------- + // base Tape Machine operations + + Local Core·Status Ξ(TM·Array ,CVT)·mount(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + if(tm) Core·Guard·fg.check(&chk ,1 ,tm->position ,TM·Array·Msg·position); + Core·Guard·if_return(chk); + #endif + + // mounting an already mounted head does nothing ,perhaps you meant `rewind`? + if(!tm->hd) tm->hd = tm->position; + return Core·Status·on_track; + } + + Local Core·Status Ξ(TM·Array ,CVT)·dismount(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + Core·Guard·if_return(chk); + #endif + + tm->hd = NULL; + return Core·Status·on_track; + } + + Local TM·Head·Status Ξ(TM·Array ,CVT)·status( + Ξ(TM·Array ,CVT) *tm ,TM·Head·Status *status + ){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + Core·Guard·fg.check(&chk ,1 ,status ,"given NULL status pointer"); + Core·Guard·if_return(chk); + #endif + + if(tm->hd == NULL){ + *status = TM·Head·Status·not_on_tape; + }else if(tm->hd == tm->position){ + *status = TM·Head·Status·origin; + }else if(tm->hd == tm->position + tm->extent){ + *status = TM·Head·Status·rightmost; + }else{ + *status = TM·Head·Status·interim; + } + + return Core·Status·on_track; + } + + // Stronger than `can_read`. Used mostly for debugging. + // as it checks for a legal head position. + Local Core·Status Ξ(TM·Array ,CVT)·head_on_format( + Ξ(TM·Array ,CVT) *tm ,bool *flag + ){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·Array·Msg·tm); + if(tm) Core·Guard·fg.check(&chk ,1 ,tm->position ,TM·Array·Msg·position); + Core·Guard·fg.check(&chk ,1 ,flag ,TM·Array·Msg·flag); + Core·Guard·if_return(chk); + #endif + + *flag = + tm->hd + && tm->hd >= tm->position + && tm->hd - tm->position <= tm->extent + && ( (AU *)tm->hd - (AU *)tm->position ) % sizeof(CVT) == 0 // '%' expensive + ; + return Core·Status·on_track; + } + + bool Ξ(TM·Array ,CVT)·can_read(Ξ(TM·Array ,CVT) *tm){ + return tm && tm->position && tm->hd; + } + + // can_read was true + bool Ξ(TM·Array ,CVT)·on_origin(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + return tm->hd == tm->position; + } + + // can_read was true + bool Ξ(TM·Array ,CVT)·on_rightmost(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + return tm->hd == tm->position; + } + + void Ξ(TM·Array ,CVT)·step(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + tm->hd++; + } + + void Ξ(TM·Array ,CVT)·step_left(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + tm->hd--; + } + + void Ξ(TM·Array ,CVT)·rewind(Ξ(TM·Array ,CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + tm->hd = tm->position; + } + + // tm_can_read must be true for both machines. + void Ξ(TM·Array ,CVT)·copy_datum(Ξ(TM·Array ,CVT) *tm_read ,Ξ(TM·Array ,CVT) *tm_write){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm_read ,flag) == Control·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"tm_read head off track"); + s = Ξ(TM·Array ,CVT)·head_on_format(tm_write ,flag) == Control·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"tm_write head off track"); + Core·Guard·assert(chk); + #endif + + *(tm_write->hd) = *(tm_read->hd); + return Core·Status·on_track; + } + + void Ξ(TM·Array ,CVT)·read(Ξ(TM·Array ,CVT) *tm ,CVT *read_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + + *read_pt = *(tm->hd); + } + + void Ξ(TM·Array ,CVT)·write(Ξ(TM·Array ,CVT) *tm ,CVT *write_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,CVT)·head_on_format(tm ,flag) == Core·Status·on_track; + Core·Guard·fg.check(&chk ,1 ,s && flag ,"head off format"); + Core·Guard·assert(chk); + #endif + + *(tm->hd) = *write_pt; + } + + // step_right is a synonym for step + + + //---------------------------------------- + // Initialization for Ξ(TM·Array ,CVT)·fg + + Local Ξ(TM·Array ,CVT)·FG Ξ(TM·Array ,CVT)·fg = { + .tape = { + .topo = Ξ(TM·Array ,CVT)·topo + .extent = Ξ(TM·Array ,CVT)·extent + } + + ,.area = { + .mount_pe = Ξ(TM·Array ,CVT)·mount_pe + ,.mount_pp = Ξ(TM·Array ,CVT)·mount_pp + } + + ,.mount = Ξ(TM·Array ,CVT)·mount + ,.dismount = Ξ(TM·Array ,CVT)·dismount + + ,.status = Ξ(TM·Array ,CVT)·status + ,.head_on_format = Ξ(TM·Array ,CVT)·head_on_format + + ,.can_read = Ξ(TM·Array ,CVT)·can_read + ,.on_origin = Ξ(TM·Array ,CVT)·on_origin + ,.on_rightmost = Ξ(TM·Array ,CVT)·on_rightmost + + ,.step = Ξ(TM·Array ,CVT)·step + ,.step_left = Ξ(TM·Array ,CVT)·step_left + ,.step_right = Ξ(TM·Array ,CVT)·step_right // Synonym for step + ,.rewind = Ξ(TM·Array ,CVT)·rewind + + ,.copy_datum = Ξ(TM·Array ,CVT)·copy_datum + ,.read = Ξ(TM·Array ,CVT)·read + ,.write = Ξ(TM·Array ,CVT)·write + + }; + + #endif // ifdef CVT + + //---------------------------------------- // TM·Array implementation //---------------------------------------- @@ -139,13 +474,13 @@ /* TM·Array is bound to a tape with head on the tape via mount_pe or mount_pp. - Once a tape is bound ,it remains so ,though the head can be dismounted + Once a tape is bound, it remains so, though the head can be dismounted and remounted. - C lacks an allocation-bound initialization feature ,so the library user is responsible + C lacks an allocation-bound initialization feature, so the library user is responsible to make sure a TM·Array has been initialized before use. - The TM·Array has no locking facility ,so it is not possible to know if it is in use. + The TM·Array has no locking facility, so it is not possible to know if it is in use. Re-initializing a TM·Array while in use can lead to unspecified badness. Use `rewind` instead. */ diff --git "a/developer/cc\360\237\226\211/xi.c" "b/developer/cc\360\237\226\211/xi.c" new file mode 100644 index 0000000..ae2b85c --- /dev/null +++ "b/developer/cc\360\237\226\211/xi.c" @@ -0,0 +1,66 @@ +/* Xi (Ξ) macro implementation with variable argument support + * + * This file provides macros from Ξ0 through Ξ10 along with a selector + * that automatically chooses the right macro based on argument count. + * + * Usage: + * Ξ(a) -> a + * Ξ(a ,b) -> a·b + * Ξ(a ,b ,c) -> a·b·c + * ... + * Ξ(a ,b ,c ,d ,e ,f) -> a·b·c·d·e·f + * + * For Map with two template parameters: + * Ξ(Map ,CVT_read ,CVT_write) -> Map·CVT_read·CVT_write + */ + +#ifndef XI_C +#define XI_C + +// Individual macros for specific argument counts +#define _Ξ0() +#define Ξ0() _Ξ0() + +#define _Ξ1(a) a +#define Ξ1(a) _Ξ1(a) + +#define _Ξ2(a ,b) a##·##b +#define Ξ2(a ,b) _Ξ2(a ,b) + +#define _Ξ3(a ,b ,c) a##·##b##·##c +#define Ξ3(a ,b ,c) _Ξ3(a ,b ,c) + +#define _Ξ4(a ,b ,c ,d) a##·##b##·##c##·##d +#define Ξ4(a ,b ,c ,d) _Ξ4(a ,b ,c ,d) + +#define _Ξ5(a ,b ,c ,d ,e) a##·##b##·##c##·##d##·##e +#define Ξ5(a ,b ,c ,d ,e) _Ξ5(a ,b ,c ,d ,e) + +#define _Ξ6(a ,b ,c ,d ,e ,f) a##·##b##·##c##·##d##·##e##·##f +#define Ξ6(a ,b ,c ,d ,e ,f) _Ξ6(a ,b ,c ,d ,e ,f) + +#define _Ξ7(a ,b ,c ,d ,e ,f ,g) a##·##b##·##c##·##d##·##e##·##f##·##g +#define Ξ7(a ,b ,c ,d ,e ,f ,g) _Ξ7(a ,b ,c ,d ,e ,f ,g) + +#define _Ξ8(a ,b ,c ,d ,e ,f ,g ,h) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h +#define Ξ8(a ,b ,c ,d ,e ,f ,g ,h) _Ξ8(a ,b ,c ,d ,e ,f ,g ,h) + +#define _Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h##·##i +#define Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) _Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) + +#define _Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h##·##i##·##j +#define Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) _Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) + +// Argument counting mechanism +#define _ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define COUNT_ARGS(...) _ARG_N(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +// Macro name concatenation +#define _CONCAT(a, b) a##b +#define CONCAT(a, b) _CONCAT(a, b) + +// Selector that chooses the right macro based on argument count +#define Ξ_EXPAND(count, ...) CONCAT(Ξ, count)(__VA_ARGS__) +#define Ξ(...) Ξ_EXPAND(COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) + +#endif /* XI_C */ diff --git "a/developer/document\360\237\226\211/alignment.org" "b/developer/document\360\237\226\211/alignment.org" index aa9ee34..c77db25 100644 --- "a/developer/document\360\237\226\211/alignment.org" +++ "b/developer/document\360\237\226\211/alignment.org" @@ -1,13 +1,28 @@ +*recovering alignment of pointers that point to array cells (elements) Interesting observation, recovering alignment for a pointer into an array is expensive. It requires modulus against the element size to find how far off the pointer is. +*converving alignment + If one starts aligned, say on zero, then only increments by the element size, alignment is not ever lost. However, if an element pointer is computed by a imprecise process, and rounding is recovered to get it back again, then the modulus is required. +*power of radix boundaries + However, modulus is not hard on powers of the radix boundaries. So either a) in the first place make elements a power of the radix in size, perhaps even using padding, b) change the radix of the number system so the native element size if the radix, or a power there of c) never do a computation that loses alignment. As a consequence it is expensive to compute the extent of an object with arbitrary CVT (Cell Value Type). Given the two bounding pointers, one must subtract and divide by the sizeof(CVT) to recover the extent, and divide is expensive. In contrast when given the position and extent, the address of the rightmost cell can be recovered with an addition. +*store base and extent, rather than two pointers + It follows that if the extent is needed that it makes more sense to store the position and extent for an interval than it does to store two bounding pointers. + +*unaligned bound + +`on_rightmost` is a precise predicate. If the head pointer were advanced by a value other than sizeof(CVT) then it could step right over the base pointer to the rightmost cell. If this was part of looping, the loop would continue. + +A situation where this could happen, suppose we want to copy a block of memory. We walk AU by AU (byte by byte) up to an aligned on AU8 address. Then we copy AU8 by AU8. Here is the problem, the actual data being copied ends on an AU pointer boundary, not an AU8 pointer boundary. It is not difficult to round down to an AU8 because 8 is a power of two. This round down is required, to the point of the last full AU8 that can be copied, to stop the AU8 copy. This is not a problem for AU8 because 8 is a power of two. + +However, if the increment were by the size of CVT, and the boundary was given given by an AU pointer, then rounding down requires a modulus operation to know where the last CVT fits in. It is not clear what use case exists for this. diff --git "a/developer/document\360\237\226\211/generalizing_type.org" "b/developer/document\360\237\226\211/generalizing_type.org" new file mode 100644 index 0000000..73bba86 --- /dev/null +++ "b/developer/document\360\237\226\211/generalizing_type.org" @@ -0,0 +1,109 @@ +* Generalizing type + +** Passing an TM FG table instance + +1. Suppose we have a generic TM FG table with the declared functions constituting the architecture (user's view, interface) of a tape machine. + +2. Instances of this TM FG table to represent different implementations of the architecture. Say TM·Array·fg for a TM implemented as an array, and TM·Function·fg for a function implementation (for example the Natural_Number in the Java implementation). + +3. Now suppose we have a function `map` that is given a TM_read, a TM_write, and a function. + The map does not care how the TM is implemented. + + If these first two arguments are declared as TM FG type, then they can accept any fg table whether it be an Array implementation, a Function implementation, etc. The map can then pick the functions it needs, such as step, and rightmost, from the + table, and thus get tape behavior. + + This achieves what we wanted, a map function that can use a tape machine and does not care what the implementation of that tape machine is. + + However, the TM functions that map calls require to be given a first argument of that holds the TM instance data. Without this it can not know which machine is being operated on. + Furthermore, the instance data type must match the TM fg table type. + + Given steps 1 through 3 we never passed in instance data to map, only a TM FG table insance. So map has a type, but not the data. + + +** Passing TM instance data, compile in the fg table. + +1. As noted, `map` is given a TM_read, a TM_write, and a function. For these first two + arguments, suppose we pass in the instance data, i.e. struct pointers. + +2. The TM·Array struct will hold a base pointer to the array, and the head location. The TM·Function struct would hold a handle recognized by the functions, or some state used by them. + +3. Then we have a map function for each architecture type, and we compile into each of these a call to the correct default TM·fg table. The map·Array will have compiled into it, TM·Array·fg, and the map·Function will have compiled into it TM·Function·fg etc. + +4. This approach works, but we duplicate the map code many times just to get the types to match the calls. + + +** Passing in both, the TM instance data, and corresponding TM FG tables instances. + +1. Say we have one generic `map` that given 5 arguments: TM_read (an instance), TM_read_fg, a TM_write (an instance), and TM_write_fg. + +2. The instance parameters must be declared `void *` to prevent argument checking on them, otherwise it will be necessary to implement many map functions for each instance type combination. + +3. This works, though we have no way to know if the correct type of instance data, that matches the fg table, was actually passed in. + +4. We could create many wrapper functions to accomplish the instance data type check, then to call a central map function with `void *` instance data pointers. With any luck the optimizer would make this extra layer go away, so it will be efficient. Still map now has 5 arguments instead the three that are natural for the problem. + + +** Using a "vtable" + +1. All TM instance types are structs with a first field that points to the fg table, + no matter the implementation type. This is not a serious requirement because + each implementation type already has an struct for its implementation data. However it does make an instance bigger, and it is not clear that the optimizer will be able to + discombobulation it all. + +2. Then a generic fg table is created, where the functions have the signatures as specified + in the FG table. However, each of these functions follows the fg table pointer in the + the instance data given to it as a first argument, and then calls that function. + +3. It works, and it is a tried and true method. + +** Using a pointer pair .. + +1. Instead of the instance data being called the 'TM type', a pair is the 'TM type', + the first member of the pair points to an instance, the second to a corresponding + fg table. + +2. Again there are some generic TM functions, each accepts a pair as a first argument, and then calls the corresponding fg table function while giving it the instance pointer + from the pair as the first argument. + +3. This approach packs the same information as the vtable approach. If there is a + one to one correspondence between instances and pairs, then it is larger by one pointer. + +4. This is a type of 'link' from our continuations, but the tableau pointer is gone due + to using a stack frame, and the continuation table pointer is gone due to flow through sequencing. Thus it is two pointers instead of 4. + +5. Hopefully the optimizer would recognize that the pair pointers are redundant. They are only needed to ensure that the instance and fg table go together. + +** Instance curried dispatch function + +1. In this case a pointer to a function is the 'TM type'. There is an enum that gives numeric tags to each of the functions in the FG struct instance. + +2. The tag for the desired fg function to be called is passed as the first argument to the dispatch function, and the remaining arguments are for the fg function. + +3. The dispatch function has the instance data and fg table pointer curried into it, so it then calls the correct fg function while handing it the correct instance data. + +4. In C it is not immediately obvious how to create a function on the fly each time an + instance is created, to curry the instance data into it, and then later how to call + the newly created function. + +** Self-typed Instance and dispatch function + +1. With this method, an extra field is added to the instance data that identifies its type. Then a globally available TM specific dispatch function is called to run the desired fg function on the data. It is similar to the dispatch function from above, but the instance data is an additional argument. + +2. The dispatch function uses the type information to know which fg table to call. This type information could be a pointer to the appropriate fg table. + +3. This approach differs from the vtable method in that all the arguments are given to the one TM dispatch function, and it figures out how to do the dispatch. There is not a wrapper-per-function. + +** Which approach? + +We want to be able to declare an instance as a local variable, where it will end up being on the stack frame. We want to avoid heap allocation for performance reasons, but not exclude use of heap memory. + +Dynamically created functions are out of the question. Dispatch approaches require the enum table so as to have tags. This is not show stopper. However, having one dispatch function means the argument types are not checked. That is a problem. + +Doubled up argument, one for the instance, the other for the table, either require wrappers, or not checking that an instance really goes with the data. Besides it is a lot of typing. + +The pointer pair approach requires the separate maintenance of the pair. When these are local variables, then the pair has to be tied to the instance. This would require the user to be aware of the existence of both the instance data and the pair, so as to pass them to an initializer. This could be avoided if the pair would combined with the instance, but that +is identical to the vtable approach (the instance pointer no longer being needed). + +So we are lead to the vtable. Though we are still hoping for the curried dispatch function - lol. + + diff --git a/developer/experiment/xi.c b/developer/experiment/xi.c new file mode 100644 index 0000000..3a13ea5 --- /dev/null +++ b/developer/experiment/xi.c @@ -0,0 +1,68 @@ +/* Xi (Ξ) macro implementation with variable argument support + * + * This file provides macros from Ξ0 through Ξ10 along with a selector + * that automatically chooses the right macro based on argument count. + * + * Usage: + * Ξ(a) -> a + * Ξ(a ,b) -> a·b + * Ξ(a ,b ,c) -> a·b·c + * ... + * Ξ(a ,b ,c ,d ,e ,f) -> a·b·c·d·e·f + * + * For Map with two template parameters: + * Ξ(Map ,CVT_read ,CVT_write) -> Map·CVT_read·CVT_write + */ + +#warning "beware all those who traverse here" + +#ifndef XI_C +#define XI_C + +// Individual macros for specific argument counts +#define _Ξ0() +#define Ξ0() _Ξ0() + +#define _Ξ1(a) a +#define Ξ1(a) _Ξ1(a) + +#define _Ξ2(a ,b) a##·##b +#define Ξ2(a ,b) _Ξ2(a ,b) + +#define _Ξ3(a ,b ,c) a##·##b##·##c +#define Ξ3(a ,b ,c) _Ξ3(a ,b ,c) + +#define _Ξ4(a ,b ,c ,d) a##·##b##·##c##·##d +#define Ξ4(a ,b ,c ,d) _Ξ4(a ,b ,c ,d) + +#define _Ξ5(a ,b ,c ,d ,e) a##·##b##·##c##·##d##·##e +#define Ξ5(a ,b ,c ,d ,e) _Ξ5(a ,b ,c ,d ,e) + +#define _Ξ6(a ,b ,c ,d ,e ,f) a##·##b##·##c##·##d##·##e##·##f +#define Ξ6(a ,b ,c ,d ,e ,f) _Ξ6(a ,b ,c ,d ,e ,f) + +#define _Ξ7(a ,b ,c ,d ,e ,f ,g) a##·##b##·##c##·##d##·##e##·##f##·##g +#define Ξ7(a ,b ,c ,d ,e ,f ,g) _Ξ7(a ,b ,c ,d ,e ,f ,g) + +#define _Ξ8(a ,b ,c ,d ,e ,f ,g ,h) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h +#define Ξ8(a ,b ,c ,d ,e ,f ,g ,h) _Ξ8(a ,b ,c ,d ,e ,f ,g ,h) + +#define _Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h##·##i +#define Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) _Ξ9(a ,b ,c ,d ,e ,f ,g ,h ,i) + +#define _Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) a##·##b##·##c##·##d##·##e##·##f##·##g##·##h##·##i##·##j +#define Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) _Ξ10(a ,b ,c ,d ,e ,f ,g ,h ,i ,j) + +// Argument counting mechanism +#define _ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define COUNT_ARGS(...) _ARG_N(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +// Macro name concatenation +#define _CONCAT(a, b) a##b +#define CONCAT(a, b) _CONCAT(a, b) + +// Selector that chooses the right macro based on argument count +#define Ξ_EXPAND(count, ...) CONCAT(Ξ, count)(__VA_ARGS__) +#define Ξ(...) Ξ_EXPAND(COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) + +#endif /* XI_C */ diff --git a/developer/experiment/xi2_test.c b/developer/experiment/xi2_test.c new file mode 100644 index 0000000..b00205e --- /dev/null +++ b/developer/experiment/xi2_test.c @@ -0,0 +1,62 @@ +#warning "beware all those who traverse here" + +// Individual macros for specific argument counts +#define _Ξ0() "" +#define Ξ0() _Ξ0() + +#define _Ξ1(a) #a +#define Ξ1(a) _Ξ1(a) + +#define _Ξ2(a, b) #a "·" #b +#define Ξ2(a, b) _Ξ2(a, b) + +#define _Ξ3(a, b, c) #a "·" #b "·" #c +#define Ξ3(a, b, c) _Ξ3(a, b, c) + +#define _Ξ4(a, b, c, d) #a "·" #b "·" #c "·" #d +#define Ξ4(a, b, c, d) _Ξ4(a, b, c, d) + +#define _Ξ5(a, b, c, d, e) #a "·" #b "·" #c "·" #d "·" #e +#define Ξ5(a, b, c, d, e) _Ξ5(a, b, c, d, e) + +#define _Ξ6(a, b, c, d, e, f) #a "·" #b "·" #c "·" #d "·" #e "·" #f +#define Ξ6(a, b, c, d, e, f) _Ξ6(a, b, c, d, e, f) + +#define _Ξ7(a, b, c, d, e, f, g) #a "·" #b "·" #c "·" #d "·" #e "·" #f "·" #g +#define Ξ7(a, b, c, d, e, f, g) _Ξ7(a, b, c, d, e, f, g) + +#define _Ξ8(a, b, c, d, e, f, g, h) #a "·" #b "·" #c "·" #d "·" #e "·" #f "·" #g "·" #h +#define Ξ8(a, b, c, d, e, f, g, h) _Ξ8(a, b, c, d, e, f, g, h) + +#define _Ξ9(a, b, c, d, e, f, g, h, i) #a "·" #b "·" #c "·" #d "·" #e "·" #f "·" #g "·" #h "·" #i +#define Ξ9(a, b, c, d, e, f, g, h, i) _Ξ9(a, b, c, d, e, f, g, h, i) + +#define _Ξ10(a, b, c, d, e, f, g, h, i, j) #a "·" #b "·" #c "·" #d "·" #e "·" #f "·" #g "·" #h "·" #i "·" #j +#define Ξ10(a, b, c, d, e, f, g, h, i, j) _Ξ10(a, b, c, d, e, f, g, h, i, j) + +// Argument counting mechanism +#define _ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define COUNT_ARGS(...) _ARG_N(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +// Macro name concatenation +#define _CONCAT(a, b) a##b +#define CONCAT(a, b) _CONCAT(a, b) + +// Selector that chooses the right macro based on argument count +#define Ξ_EXPAND(count, ...) CONCAT(Ξ, count)(__VA_ARGS__) +#define Ξ(...) Ξ_EXPAND(COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) + +// Test cases +#include + +int main() { + printf("Testing macros:\n"); + + // Test with different argument counts + printf("Ξ0(): %s\n", Ξ()); + printf("Ξ1(hello): %s\n", Ξ(hello)); + printf("Ξ2(hello, world): %s\n", Ξ(hello, world)); + printf("Ξ3(a, b, c): %s\n", Ξ(a, b, c)); + + return 0; +} diff --git a/developer/experiment/xi_test.c b/developer/experiment/xi_test.c new file mode 100644 index 0000000..d9e435f --- /dev/null +++ b/developer/experiment/xi_test.c @@ -0,0 +1,39 @@ +#include + +#include "xi.c" + +struct a{ + int x; +} Ξ(X) ,Ξ(Y ,Y) ,Ξ(Z ,Z ,Z); + + +int main(){ + + X.x = 3; + Y·Y.x = 5; + Z·Z·Z.x = 7; + + Ξ(); // should do nothing, as it expands to nothing. + + printf("%x" ,X.x); // notice no cdot, just 'X' + printf("%x" ,Y·Y.x); + printf("%x" ,Z·Z·Z.x); + +} + + +/* +2025-03-20T08:20:34Z[developer] +Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/experiment§ +> gcc xi_test.c +In file included from xi_test.c:3: +xi.c:17:2: warning: #warning "beware all those who traverse here" [-Wcpp] + 17 | #warning "beware all those who traverse here" + | ^~~~~~~ + +2025-03-20T08:21:28Z[developer] +Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/experiment§ +> ./a.out +357 +2025-03-20T08:21:34Z[developer] +*/ -- 2.20.1