From: Thomas Walker Lynch Date: Wed, 2 Apr 2025 11:45:15 +0000 (+0000) Subject: changing out type guards for #define lists X-Git-Url: https://git.reasoningtechnology.com/style/static/git-logo.png?a=commitdiff_plain;h=1a71e9990c908b636b0b4fe8338bf3827c38119a;p=N changing out type guards for #define lists --- diff --git "a/developer/cc\360\237\226\211/#Binding.lib.c#" "b/developer/cc\360\237\226\211/#Binding.lib.c#" deleted file mode 100644 index 0ca7be7..0000000 --- "a/developer/cc\360\237\226\211/#Binding.lib.c#" +++ /dev/null @@ -1,86 +0,0 @@ -/* -Template parameters: - - Binding·TYPE - Type used to name the binding struct. Binding struct instances get passed as arguments to functions etc. - -*/ - -//-------------------------------------------------------------------------------- -// Interface - -// once per translation unit -#ifndef Binding·TYPE_LIST -#define Binding·TYPE_LIST - - #define Binding·DEBUG - #ifdef Binding·DEBUG - #include - #endif - - #include "cpp_ext.c" - #include "Core.lib.c" - -#endif - -// once per Binding·TYPE value -#ifdef Binding·TYPE -#if NOT( FIND_ITEM(Binding·TYPE ,Binding·TYPE_LIST) ) -#pragma message( STR_VAL(Binding·TYPE) ) - - //this is what it takes to append to a list in cpp ... - #undef TEMP - #define TEMP Binding·TYPE_LIST ,Binding·TYPE - #undef Binding·TYPE_LIST - #define Binding·TYPE_LIST TEMP - - // a simplifying naming convention - #define Binding Ξ(Binding·TYPE) - #define Binding·FG Ξ(Binding·TYPE ,FG) - #define Binding·Tableau Ξ(Binding·TYPE ,Tableau) - - // binds a tableau and Binding table instance together - // as a convention, we name the binding after the Type - typedef struct Binding·FG Binding·FG; - typedef struct Binding·Tableau Binding·Tableau; - typedef struct{ - Binding·FG *fg; - Binding·Tableau *tableau; - } Binding; - - Local inline void Binding·wellformed_binding(Binding b){ - #ifdef Binding·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk, 1, b.fg, "NULL fg table"); - Core·Guard·fg.check(&chk, 1, b.tableau, "NULL tableau"); - Core·Guard·assert(chk); - #endif - } - - /* - usage e.g.: Binding·call(tm, function_name, arg1, arg2, ...) - Expands to: (tm.fg->function_name)(tm ,arg1 ,arg2, ...) - - note the use of the comma operator to return the result from the b.fg->fn call - */ - #define Binding·call(b, fn, ...) \ - ( Binding·wellformed_binding(b) ,b.fg->fn(b, ##__VA_ARGS__) ) - -#endif -#endif - -//-------------------------------------------------------------------------------- -// Implementation -// Binding has no implementation - -#ifdef LOCAL - -#endif - -#ifdef LIBRARY - -#endif - -//-------------------------------------------------------------------------------- -// template variables work once - -#undef Binding·TYPE diff --git "a/developer/cc\360\237\226\211/Binding.lib.c" "b/developer/cc\360\237\226\211/Binding.lib.c" index 4296c2e..da7a380 100644 --- "a/developer/cc\360\237\226\211/Binding.lib.c" +++ "b/developer/cc\360\237\226\211/Binding.lib.c" @@ -1,4 +1,10 @@ /* +This files declares a binding struct named [Binding·TYPE]. It also provides +the macro `call` that uses the binding. + +Note this file does not make an instance of the binding, and does not intialize +fields in an instance. + Template parameters: Binding·TYPE - Type used to name the binding struct. Binding struct instances get passed as arguments to functions etc. @@ -7,48 +13,58 @@ Template parameters: //-------------------------------------------------------------------------------- // Interface +//-------------------------------------------------------------------------------- // once per translation unit -#ifndef Binding·TYPE_LIST -#define Binding·TYPE_LIST +#ifndef Binding·FACE +#define Binding·FACE #define Binding·DEBUG #ifdef Binding·DEBUG #include + #pragma message( "in #ifndef Binding·TYPE_LIST section" ) #endif #include "cpp_ext.c" #include "Core.lib.c" + #define Binding·NO_BINDING_FOR(x) BOOLEAN(NOT(CAT2(Binding·TYPE· ,x))) + + /* + usage e.g.: Binding·call(tm, function_name, arg1, arg2, ...) + Expands to: (tm.fg->function_name)(tm ,arg1 ,arg2, ...) + + note the use of the comma operator to return the result from the b.fg->fn call + */ + #define Binding·call(b, fn, ...) \ + ( \ + Binding·wellformed_binding(b) , \ + b.fg->fn(b.tableau __VA_OPT__(,) __VA_ARGS__) \ + ) + #endif + // once per Binding·TYPE value #ifdef Binding·TYPE -#if NOT_CONTAINS(Binding·TYPE ,Binding·TYPE_LIST) ) -#pragma message( STR_VAL(Binding·TYPE) ) - - //this is what it takes to append to a list in cpp ... - #undef TEMP - #define TEMP Binding·TYPE_LIST ,Binding·TYPE - #undef Binding·TYPE_LIST - #define Binding·TYPE_LIST TEMP - - // a simplifying naming convention - #define Binding Ξ(Binding·TYPE) - #define Binding·FG Ξ(Binding·TYPE ,FG) - #define Binding·Tableau Ξ(Binding·TYPE ,Tableau) - - // binds a tableau and Binding table instance together - // as a convention, we name the binding after the Type - typedef struct Binding·FG Binding·FG; - typedef struct Binding·Tableau Binding·Tableau; - typedef struct{ - Binding·FG *fg; - Binding·Tableau *tableau; - } Binding; - - Local inline void Binding·wellformed_binding(Binding b){ +#if Binding·NO_BINDING_FOR(Binding·TYPE) +#ifdef Binding·DEBUG + #pragma message( "adding binding for:" STR_VAL(Binding·TYPE) ) +#endif + + struct Ξ(Binding·TYPE ,FG); + typedef struct Ξ(Binding·TYPE ,FG) Ξ(Binding·TYPE ,FG); + + struct Ξ(Binding·TYPE ,Tableau); + typedef struct Ξ(Binding·TYPE ,Tableau) Ξ(Binding·TYPE ,Tableau); + + typedef struct Ξ(Binding·TYPE){ + Ξ(Binding·TYPE ,Tableau) *tableau; + Ξ(Binding·TYPE ,FG) *fg; + } Ξ(Binding·TYPE); + + static void Binding·wellformed_binding(Ξ(Binding·TYPE) b){ #ifdef Binding·DEBUG Core·Guard·init_count(chk); Core·Guard·fg.check(&chk, 1, b.fg, "NULL fg table"); @@ -57,31 +73,29 @@ Template parameters: #endif } - /* - usage e.g.: Binding·call(tm, function_name, arg1, arg2, ...) - Expands to: (tm.fg->function_name)(tm ,arg1 ,arg2, ...) +#endif +#endif - note the use of the comma operator to return the result from the b.fg->fn call - */ - #define Binding·call(b, fn, ...) \ - ( Binding·wellformed_binding(b) ,b.fg->fn(b, ##__VA_ARGS__) ) - -#endif -#endif //-------------------------------------------------------------------------------- -// Implementation -// Binding has no implementation +// Local - at bottom of translation unit, to keep some functions private +// Binding currently has no local component +//-------------------------------------------------------------------------------- #ifdef LOCAL #endif +//-------------------------------------------------------------------------------- +// Library - compiled into a lib.a file by the current make +// Binding has no library component +//-------------------------------------------------------------------------------- #ifdef LIBRARY #endif //-------------------------------------------------------------------------------- -// template variables work once - +// undef the template parameters +//-------------------------------------------------------------------------------- #undef Binding·TYPE + diff --git "a/developer/cc\360\237\226\211/Core.lib.c" "b/developer/cc\360\237\226\211/Core.lib.c" index c3bed46..162b278 100644 --- "a/developer/cc\360\237\226\211/Core.lib.c" +++ "b/developer/cc\360\237\226\211/Core.lib.c" @@ -1,4 +1,4 @@ - /* +/* Core - core memory operations. Abbreviations used in comments: @@ -6,19 +6,19 @@ '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. + 'AToW' - At Time of Writing ,also used in comments. Abbreviations used in identifiers: `AU` `Addressable Unit for the machine`. The C standard leaves this open to definition by the architecture and calls it `char`. On most all machines today it is uint8_t; - We use structs to group functions into a namespace. When all the functions that have a specific type of given argument are group together, we call the table a 'Functions Given Type X table', or 'FG table' for short. A specific instance of an FG table is an `fg` table. + We use structs to group functions into a namespace. When all the functions that have a specific type of given argument are group together ,we call the table a 'Functions Given Type X table' ,or 'FG table' for short. A specific instance of an FG table is an `fg` table. */ //-------------------------------------------------------------------------------- // Interface - +//-------------------------------------------------------------------------------- #ifndef Core·FACE #define Core·FACE @@ -35,14 +35,13 @@ //---------------------------------------- // memory interface - //---------------------------------------- - // extent is the maximum index in an address space, tape or area, the doted + // extent is the maximum index in an address space ,tape or area ,the doted // unit is the cell type. typedef size_t extent_t·AU; #define extent_of·AU(x) (sizeof(x) - 1) - // Funny, we seldom check for this, perhaps that matters on some tiny machine. - #define extent·AU_address_space ~(uintptr)0; + // Funny ,we seldom check for this ,perhaps that matters on some tiny machine. + #define extent_of·AU_address_space ~(uintptr)0; // addressable unit for the machine // C language standard left this undefined. AToW industry uses uint8_t. @@ -62,8 +61,7 @@ const WU WU_MAX = (~(WU)0); //---------------------------------------- - // flag facility, argument guard facility - //---------------------------------------- + // flag facility ,argument guard facility typedef enum{ Core·Status·mu = 0 @@ -87,7 +85,7 @@ } typedef struct { - char *name; + const char *name; Core·Flag·Fn flag_function; WU flag; } Core·Guard; @@ -123,9 +121,8 @@ //---------------------------------------- // functions interface - //---------------------------------------- - // no state, this is merely a namespace + // no state ,this is merely a namespace typedef struct{ Core·Status (*on_track)(); @@ -140,101 +137,105 @@ //-------------------------------------------------------------------------------- -// Implementation +// Local - at bottom of translation unit, to keep some functions private +//-------------------------------------------------------------------------------- +#ifdef LOCAL -#ifdef IMPLEMENTATION +// once per translation unit +#ifndef Core·LOCAL +#define Core·LOCAL - //-------------------------------------------------------------------------------- - // implementation to go into the lib.a file - // - #ifndef LOCAL - #endif + //---------------------------------------- + // argument guard implementation - //-------------------------------------------------------------------------------- - #ifdef LOCAL + Local void Core·Guard·init(Core·Guard *chk ,const char *name ,Core·Flag·Fn af){ + if(!chk) return; + chk->name = name; + chk->flag_function = af; + chk->flag = 0; + } - //---------------------------------------- - // argument guard implementation - //---------------------------------------- + Local void Core·Guard·reset(Core·Guard *chk){ + if( !chk ) return; + chk->flag = 0; + } - Local void Core·Guard·init(Core·Guard *chk, const char *name, Core·Flag·Fn af){ - if(!chk) return; - chk->name = name; - chk->flag_function = af; - chk->flag = 0; - } + Local void Core·Guard·check( + Core·Guard *chk + ,WU err + ,bool condition + ,char *message + ){ + if( !chk || !chk->flag_function ) return; + if( condition ) return; + fprintf(stderr ,"%s\n" ,message); + chk->flag_function(&chk->flag ,err); + } - Local void Core·Guard·reset(Core·Guard *chk){ - if( !chk ) return; - chk->flag = 0; - } + Local Core·Guard·FG Core·Guard·fg = { + .init = Core·Guard·init + ,.reset = Core·Guard·reset + ,.check = Core·Guard·check + }; - Local void Core·Guard·check( - Core·Guard *chk - ,WU 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 - }; - - //---------------------------------------- - // Functions implementation - //---------------------------------------- - - 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 = Core·round_down // Add `Core` - ,.round_up = Core·round_up // Add `Core` - }; - - #endif // LOCAL - -#endif // IMPLEMENTATION + //---------------------------------------- + // Functions implementation + + 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_t·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_t·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_t·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 = Core·round_down // Add `Core` + ,.round_up = Core·round_up // Add `Core` + }; + +#endif // Core·LOCAL +#endif // LOCAL + +//-------------------------------------------------------------------------------- +// Library - compiled into a lib.a file by the current make +// Core currently has no library components +//-------------------------------------------------------------------------------- +#ifdef LIBRARY +#endif + +//-------------------------------------------------------------------------------- +// undef the template parameters +// Core currently has not template parameters +//-------------------------------------------------------------------------------- diff --git "a/developer/cc\360\237\226\211/TM.lib.c" "b/developer/cc\360\237\226\211/TM.lib.c" index 3300f37..0f93de3 100644 --- "a/developer/cc\360\237\226\211/TM.lib.c" +++ "b/developer/cc\360\237\226\211/TM.lib.c" @@ -1,7 +1,13 @@ /* TM - Tape Machine Model - Template parameters + User must define the equivalence template: + + EQ_TM·__oo__TM· + + While filling in the CVT values of course. For pointers, struct, arrays, etc. use a typedef to reduce the type to an identifier. + + Template parameters `TM·CVT` Cell Value Type`. @@ -9,10 +15,11 @@ //-------------------------------------------------------------------------------- // Interface +//-------------------------------------------------------------------------------- // once per translation unit -#ifndef TM·TYPE_LIST -#define TM·TYPE_LIST +#ifndef TM·CVT_LIST +#define TM·CVT_LIST #include #include @@ -59,18 +66,33 @@ // once per TM·CVT value #ifdef TM·CVT -#if NOT_CONTAINS( TM·CVT ,TM·TYPE_LIST ) -#define TM·TYPE_LIST APPEND(TM·TYPE_LIST ,TM·TYPE) +#if NOT_CONTAINS( TM·CVT ,TM·CVT_LIST ) +#ifdef Binding·DEBUG + #pragma message( STR_VAL(TM·CVT_LIST) ) +#endif - // declare 'TM' as a type - #define EQ__TM__oo__TM - #define Binding·Type TM + //this is what it takes to append to a list in cpp ... + #undef TEMP + #define TEMP TM·CVT_LIST ,TM·CVT + #undef TM·CVT_LIST + #define TM·CVT_LIST TEMP + + // some synonyms to make this section easier to read + #undef TM + #define TM Ξ(TM ,TM·CVT) + #undef EXTENT_T + #define EXTENT_T Ξ(extent_t ,TM·CVT) + + // declare 'TM·CVT' as a type + // (or more specifically, make a struct for binding the FG table to the tableau) + #undef Binding·Type + #define Binding·Type TM #include "Binding.lib.c" - - // `extent_t` is an index, so element size matters, so TM·CVT matters + + // `extent_t` is an index, so element size matters, so I associate it with TM·CVT typedef Ξ(extent_t ,TM·CVT) size_t; - - typedef struct{ + + typedef struct Ξ(TM ,FG){ TM·Tape·Topo (*Tape·topo)(TM tm); bool (*Tape·bounded)(TM tm); @@ -88,537 +110,198 @@ void (*step_left) (TM tm); void (*rewind) (TM tm); - TM·Binding TM·fg; // points to TM·Binding instance - Ξ(extent_t ,TM·CVT) (*extent)(TM tm); - TM·CVT (*read) (TM tm); - void (*write)(TM tm ,TM·CVT *remote_pt); + EXTENT_T (*extent)(TM tm); + TM·CVT (*read) (TM tm); + void (*write) (TM tm ,TM·CVT *remote_pt); } Ξ(TM ,FG); //---------------------------------------- // Array interface - //---------------------------------------- - typedef struct Ξ(TM ,Array)·Tableau; - - TM Ξ(TM ,Array)·init_pe( - Ξ(TM ,Array)·Tableau *t - ,TM·CVT position[] - ,Ξ(extent_t ,TM·CVT) extent - ); + #undef TM·ARRAY + #define TM·ARRAY Ξ(TM ,ARRAY) - TM Ξ(TM ,Array)·init_pp( - Ξ(TM ,Array)·Tableau *t - ,TM·CVT *position_left - ,TM·CVT *position_right - ); + struct Ξ(TM·ARRAY ,Tableau); + + /* + We assume that the binding produced by init is valid. Thus it does not have null pointers to the tableau or the fg table; it points to an initialized tableau; it points to a valid array fg table; and, that the fg table and tableau go together. + + Calling init is the only time the user/programmer will need to know the implementation name. + + The resulting binding object returned is what the user will call an instance of the + type. + */ + TM Ξ(TM·ARRAY ,init_pe)( + struct Ξ(TM·ARRAY ,Tableau) *t + ,TM·CVT position[] + ,EXTENT_T extent + ); + + TM Ξ(TM·ARRAY ,init_pp)( + Ξ(TM·ARRAY ,Tableau) *t + ,TM·CVT *position_left + ,TM·CVT *position_right + ); -#endif #endif + //-------------------------------------------------------------------------------- -// Implementation - -#ifdef IMPLEMENTATION - - // implementation to go into the lib.a file - // - #ifndef LOCAL - #endif - - #ifdef LOCAL - - //---------------------------------------- - // included first without defining TM·CVT - //---------------------------------------- - - #ifndef TM·CVT - - //----------------------------------- - // common error messages - - const char *TM·Msg·tm="given NULL tm"; - const char *TM·Msg·position= - "Null position.This is only possible when the tape machine has not been initialized."; - const char *TM·Msg·flag="given NULL flag pointer"; - const char *TM·Msg·result="given NULL result pointer"; - const char *TM·Msg·head="head not on tape"; - - //----------------------------------- - // generic call wrappers - - Local TM·Tape·Topo TM·Tape·topo(TM *tm){ - return tm->fg.Tape·topo(tm); - } - Local TM·Tape·Topo TM·Tape·bounded(TM *tm){ - return TM·tape_top(tm) & TM·Tape·Topo·bounded); - } - - Local TM·Head·Status TM·head_status(TM *tm){ - return tm->fg.status(tm ,result); - } - Local TM·Head·Status TM·head_on_tape(TM *tm){ - return TM·status(tm) & TM·Head·Status·on_tape; - } - - // does nothing if the head is already mounted - Local Core·Status TM·mount(TM *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk, 1, tm, TM·Msg·tm); - Core·Guard·if_return(chk); - #endif - if( !TM·head_on_tape(tm) ) return Core·Status·on_track; - return tm->fg.mount(tm); - } - - // does nothing if the head is already dismounted - Local Core·Status TM·dismount(TM *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk, 1, tm, TM·Msg·tm); - Core·Guard·if_return(chk); - #endif - if( TM·head_status(TM *tm) & TM·Head·Status·dismounted) ) return Core·Status·on_track; - return tm->fg.dismount(tm); - } - - #define TM·macro·bool_tm(name) - Local bool name(TM *tm){ \ - #ifdef TM·DEBUG \ - Core·Guard·init_count(chk); \ - Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); \ - Core·Guard·assert(chk); \ - #endif \ - return tm->fg.name(tm); \ - } - - Local bool TM·macro·bool_tm(on_leftmost); - Local bool TM·macro·bool_tm(on_rightmost); - Local bool TM·macro·bool_tm(step); - Local bool TM·macro·bool_tm(step_left); - Local bool TM·macro·bool_tm(rewind); - - //---------------------------------------- - // Initialization for TM·fg - - Local TM·Binding TM·fg = { - .Tape·topo = TM·Tape·topo - ,.Tape·bounded = TM·Tape·bounded - ,.Head·status = TM·Head·status - ,.Head·on_tape = TM·Head·on_tape - - ,.Head·on_leftmost = TM·Head·on_leftmost - ,.Head·on_rightmost = TM·Head·on_rightmost - - ,.mount = TM·mount - ,.dismount = TM·dismount - - ,.step = TM·step - ,.step_left = TM·step_left - ,.step_right = TM·step // Synonym - ,.rewind = TM·rewind - - }; - - #endif // ifndef TM·CVT - - //----------------------------------- - // TM·CVT dependent functions - - #ifdef TM·CVT - - Local Ξ(extent_t ,TM·CVT) Ξ(TM ,TM·CVT)·extent(TM *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,TM·Tape·bounded(tm) ,"Tape is not bounded."); - Core·Guard·assert(chk); - #endif - return tm->fg.extent(tm); - } - - Local TM·CVT TM·read(TM *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); - Core·Guard·assert(chk); - #endif - return tm->fg.read(tm); - } - - Local void TM·write(TM *tm ,TM·CVT *write_pt){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); - Core·Guard·fg.check( &chk ,1 ,write_pt ,"Given NULL write_pt"); - Core·Guard·assert(chk); - #endif - return tm->fg.write(tm ,write_pt); - } - - Local Ξ(TM ,TM·CVT)·Binding Ξ(TM ,TM·CVT)·fg = { - .parent = TM·fg - ,.extent = Ξ(TM ,TM·CVT)·extent - ,.read = Ξ(TM ,TM·CVT)·read - ,.write = Ξ(TM ,TM·CVT)·write - }; - - #endif // ifdef TM·CVT - - - //---------------------------------------- - // TM·Array implementation - //---------------------------------------- - - /* - 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 - and remounted. - - 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. - - Re-initializing a TM·Array while in use can lead to unspecified badness. Use `rewind` instead. - */ - - //---------------------------------------- - // TM·Array implementation - //---------------------------------------- - - #ifndef TM·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·status="bad head status"; - - - #endif // #ifndef TM·CVT - - #ifdef TM·CVT - - typedef struct Ξ(TM ,TM·CVT)·Tableau; - - typedef struct{ - TM·CVT *hd; - TM·CVT *position; - Ξ(extent_t ,TM·CVT) extent; - }Ξ(TM·Array ,TM·CVT)·Tableau; - - //----------------------------------- - - // TM·Array.tape implementation - - //---------------------------------------- - // TM Array implementation, not TM·CVT differentiated - - Local TM·Tape·Topo TM·Array·Tape·topo( Ξ(TM ,TM·CVT)·Tableau *tableau ){ - Ξ(TM·Array ,TM·CVT)·Tableau *t = (Ξ(TM·Array ,TM·CVT)·Tableau *)tableau; - if(!t || !t->position) return T·Tape·Topo·mu; - if(t->extent == 0) TM·Tape·Topo·singleton; - return TM·Tape·Topo·segment; - } - Local TM·Tape·Topo TM·Tape·bounded(TM·Tableau *t){ - return TM·tape_top(t) & TM·Tape·Topo·bounded; - } - - TM·Tape·Topo TM·Array·Tape·mount(TM·Tableau *t){ - if(!t || !t->position) return T·Tape·Topo·mu; - if(t->extent == 0) TM·Tape·Topo·singleton; - return TM·Tape·Topo·segment; - } - - // For an Array Tape Machine ,a bound tape will be singleton or segment. - TM·Tape·Topo Ξ(TM·Array ,TM·CVT)·Tape·topo(Ξ(TM·Array ,TM·CVT) *tm){ - if(!tm || !tm->position) return TM·Tape·Topo·mu; - if(tm->extent == 0) TM·Tape·Topo·singleton; - return TM·Tape·Topo·segment; - } - - // check the Tape·topo to make sure tape has extent before calling this - // `extent·TM·CVT` returns the index to the rightmost cell in the array. - Local Ξ(extent_t ,TM·CVT) Ξ(TM·Array ,TM·CVT)·extent(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Tape·Topo Tape·topo = Core·Tape·Topo·mu; - Core·Status status = Ξ(TM·Array ,TM·CVT)·Tape·topo(tm ,&Tape·topo); - bool good_Tape·topo = - (status == Core·Status·on_track) && (Tape·topo & Core·Tape·Topo·finite_nz) - ; - Core·Guard·fg.check(&chk ,1 ,good_Tape·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 ,TM·CVT)·mount_pe( - Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *position ,Ξ(extent_t ,TM·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 TM·CVT is not a power of two this can perform a divide - Local Core·Status Ξ(TM·Array ,TM·CVT)·mount_pp( - Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *pos_leftmost ,TM·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 ,TM·CVT) extent = pos_rightmost - pos_leftmost); - return Ξ(TM·Array ,TM·CVT)·mount_pe(tm ,pos_leftmost ,extent); - } - - //----------------------------------- - // base Tape Machine operations - - Local Core·Status Ξ(TM·Array ,TM·CVT)·mount(Ξ(TM·Array ,TM·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 ,TM·CVT)·dismount(Ξ(TM·Array ,TM·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 ,TM·CVT)·head_status(TM *tm){ - if(!tm || !tm->position) return TM·Head·Status·mu; - if(!tm->hd) return TM·Head·Status·dismounted; - if(tm->hd == tm->position) return TM·Head·Status·leftmost; - - TM·CVT *rightmost_pt = tm->position + tm->extent; - if(tm->hd == rightmost_pt) TM·Head·Status·rightmost; - if(tm->hd < tm->position || tm->hd > rightmost_pt) - return TM·Head·Status·out_of_area; - - return TM·Head·Status·interim; - } - - bool Ξ(TM·Array ,TM·CVT)·can_read(Ξ(TM·Array ,TM·CVT) *tm){ - return tm && tm->position && tm->hd; - } - - // can_read was true - bool Ξ(TM·Array ,TM·CVT)·on_origin(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·CVT)·on_rightmost(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·CVT)·step(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·CVT)·step_left(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·CVT)·rewind(Ξ(TM·Array ,TM·CVT) *tm){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·CVT)·copy_datum(Ξ(TM·Array ,TM·CVT) *tm_read ,Ξ(TM·Array ,TM·CVT) *tm_write){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 ,TM·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 ,TM·CVT)·read(Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *read_pt){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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); - } - - - // step_right is a synonym for step - - - //---------------------------------------- - // Initialization for Ξ(TM·Array ,TM·CVT)·fg - - Local Ξ(TM·Array ,TM·CVT)·Binding Ξ(TM·Array ,TM·CVT)·fg = { - .tape = { - .Tape·topo = Ξ(TM·Array ,TM·CVT)·Tape·topo - .extent = Ξ(TM·Array ,TM·CVT)·extent - } - - ,.area = { - .mount_pe = Ξ(TM·Array ,TM·CVT)·mount_pe - ,.mount_pp = Ξ(TM·Array ,TM·CVT)·mount_pp - } - - ,.mount = Ξ(TM·Array ,TM·CVT)·mount - ,.dismount = Ξ(TM·Array ,TM·CVT)·dismount - - ,.status = Ξ(TM·Array ,TM·CVT)·status - ,.head_on_format = Ξ(TM·Array ,TM·CVT)·head_on_format - - ,.can_read = Ξ(TM·Array ,TM·CVT)·can_read - ,.on_origin = Ξ(TM·Array ,TM·CVT)·on_origin - ,.on_rightmost = Ξ(TM·Array ,TM·CVT)·on_rightmost - - ,.step = Ξ(TM·Array ,TM·CVT)·step - ,.step_left = Ξ(TM·Array ,TM·CVT)·step_left - ,.step_right = Ξ(TM·Array ,TM·CVT)·step_right // Synonym for step - ,.rewind = Ξ(TM·Array ,TM·CVT)·rewind - - ,.copy_datum = Ξ(TM·Array ,TM·CVT)·copy_datum - ,.read = Ξ(TM·Array ,TM·CVT)·read - ,.write = Ξ(TM·Array ,TM·CVT)·write - - }; - - #endif // ifdef TM·CVT - - #endif // LOCAL - -#endif // IMPLEMENTATION - - -void Ξ(TM·Array ,TM·CVT)·write(Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *write_pt){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - bool flag = true ,s; - s = Ξ(TM·Array ,TM·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 +// Local - at bottom of translation unit, to keep some functions private +//-------------------------------------------------------------------------------- +#ifdef LOCAL + +// once per translation unit +#ifndef TM·LOCAL·TYPE_LIST +#define TM·LOCAL·TYPE_LIST - *(tm->hd) = *write_pt; -} - - //----------------------------------- - // TM struct initializers - - Local Core·Status TM·mount_pe( - TM *tm ,TM·CVT *position ,Ξ(extent_t ,TM·CVT) extent - ){ - #ifdef TM·DEBUG - Core·Guard·init_count(chk); - Core·Guard·fg.check(&chk ,1 ,tm ,TM·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 TM·CVT is not a power of two this can perform a divide - Local Core·Status TM·mount_pp( - TM *tm ,TM·CVT *pos_leftmost ,TM·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 ,TM·CVT) extent = pos_rightmost - pos_leftmost); - return TM·mount_pe(tm ,pos_leftmost ,extent); - } + const char *TM·Msg·tm="given NULL tm"; + const char *TM·Msg·flag="given NULL flag pointer"; + const char *TM·Msg·result="given NULL result pointer"; + const char *TM·Msg·status="bad head status"; +#endif + +// once per TM·CVT value +#ifdef TM·CVT +#if NOT_CONTAINS( TM·CVT ,TM·LOCAL·TYPE_LIST ) +#ifdef Binding·DEBUG + #pragma message( STR_VAL(TM·LOCAL·TYPE_LIST) ) +#endif + + //this is what it takes to append to a list in cpp ... + #undef TEMP + #define TEMP TM·LOCAL·TYPE_LIST ,TM·CVT + #undef TM·LOCAL·TYPE_LIST + #define TM·LOCAL·TYPE_LIST TEMP + + // some aliases to make things a little easier to read + #undef TM + #define TM Ξ(TM ,TM·CVT) + #undef EXTENT_T + #define EXTENT_T Ξ(extent_t ,TM·CVT) + + //---------------------------------------- + // TM Array implementation, not TM·CVT differentiated + + // some aliases + #undef TM·ARRAY + #define TM·ARRAY Ξ(TM ,ARRAY) + + typedef struct Ξ(TM·ARRAY ,Tableau){ + TM·CVT *hd; + TM·CVT position[]; + EXTENT_T extent; + } Ξ(TM·ARRAY ,Tableau); + + + typedef struct Ξ(TM·ARRAY ,Tableau){ + TM·CVT *hd; + TM·CVT *position; + Ξ(extent_t ,TM·CVT) extent; + } Ξ(TM·Array ,TM·CVT)·Tableau; + + // with a direct interface, an array can implement three among the possible tape topologies + Local TM·Tape·Topo Ξ(TM·ARRAY ,Tape·topo)(TM tm){ + Ξ(TM·ARRAY ,Tableau) *t = (Ξ(TM·ARRAY ,Tableau) *) tm.tableau; + if(t->extent == 0) return TM·Tape·Topo·singleton; + return TM·Tape·Topo·segment; + } + Local bool Ξ(TM·ARRAY ,bounded)(TM tm){ + Ξ(TM·ARRAY ,Tableau) *t = (Ξ(TM·ARRAY ,Tableau) *) tm.tableau; + return Ξ(TM·ARRAY ,Tape·topo)(tm) & TM·Tape·Topo·bounded; + } + + Local TM·Head·Status Ξ(TM·ARRAY ,Head·status)(TM tm){ + Ξ(TM·ARRAY ,Tableau) *t = (Ξ(TM·ARRAY ,Tableau) *) tm.tableau; + if(!t->hd) return TM·Head·Status·dismounted; + if(t->hd == tm->position) return TM·Head·Status·leftmost; + + TM·CVT *rightmost_pt = t->position + t->extent; + if(t->hd == rightmost_pt) TM·Head·Status·rightmost; + if(t->hd < tm->position || tm->hd > rightmost_pt) + return TM·Head·Status·out_of_area; + + return TM·Head·Status·interim; + } + Local bool Ξ(TM·ARRAY ,Head·on_tape)(TM tm){ + Ξ(TM·ARRAY ,Tableau) *t = (Ξ(TM·ARRAY ,Tableau) *) tm.tableau; + return Ξ(TM·ARRAY ,Head·status)(tm) & TM·Head·Status·on_tape; + } + + + Ξ(TM ,FG) TM·ARRAY·fg = { + + } + + + TM Ξ(TM·ARRAY ,init_pe)( + struct Ξ(TM·ARRAY ,Tableau) *t + ,TM·CVT position[] + ,EXTENT_T extent + ); + + TM Ξ(TM·ARRAY ,init_pp)( + Ξ(TM·ARRAY ,Tableau) *t + ,TM·CVT *position_left + ,TM·CVT *position_right + ); + +-- + TM·Tape·Topo TM·Array·Tape·mount(TM·Tableau *t){ + if(!t || !t->position) return T·Tape·Topo·mu; + if(t->extent == 0) TM·Tape·Topo·singleton; + return TM·Tape·Topo·segment; + } + + Local Ξ(extent_t ,TM·CVT) Ξ(TM ,TM·CVT)·extent(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,TM·Tape·bounded(tm) ,"Tape is not bounded."); + Core·Guard·assert(chk); + #endif + return tm->fg.extent(tm); + } + + Local TM·CVT TM·read(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); + Core·Guard·assert(chk); + #endif + return tm->fg.read(tm); + } + + Local void TM·write(TM *tm ,TM·CVT *write_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); + Core·Guard·fg.check( &chk ,1 ,write_pt ,"Given NULL write_pt"); + Core·Guard·assert(chk); + #endif + return tm->fg.write(tm ,write_pt); + } + + Local Ξ(TM ,TM·CVT)·Binding Ξ(TM ,TM·CVT)·fg = { + .parent = TM·fg + ,.extent = Ξ(TM ,TM·CVT)·extent + ,.read = Ξ(TM ,TM·CVT)·read + ,.write = Ξ(TM ,TM·CVT)·write + }; + +#endif // ifdef TM·CVT +#undef TM·CVT + + +//-------------------------------------------------------------------------------- +// Library - compiled into a lib.a file by the current make +// Core currently has no library components +//-------------------------------------------------------------------------------- +#ifdef LIBRARY +#endif + +//-------------------------------------------------------------------------------- +// undef the template parameters +//-------------------------------------------------------------------------------- +#undef TM·CVT diff --git "a/developer/cc\360\237\226\211/cpp_ext.c" "b/developer/cc\360\237\226\211/cpp_ext.c" index b1bb1d1..8f0cacd 100644 --- "a/developer/cc\360\237\226\211/cpp_ext.c" +++ "b/developer/cc\360\237\226\211/cpp_ext.c" @@ -15,8 +15,6 @@ */ - #define NOT_CONTAINS(item ,list) BOOL( NOT(CONTAINS(item ,list)) ) - #define Ξ(...) CAT(· ,__VA_ARGS__) #endif diff --git "a/developer/cc\360\237\226\211/cpp_ext_0.c" "b/developer/cc\360\237\226\211/cpp_ext_0.c" index 635bab9..2c2a661 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_0.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_0.c" @@ -13,6 +13,7 @@ - cpp_ext as separate project - make the try into tests +- cpp_ext macros put into a namespace to prevent aliasing */ @@ -40,6 +41,8 @@ DEBUG Constants ===========================================================================*/ +#define NOTHING + #define COMMA , #define SEMICOLON ; diff --git "a/developer/cc\360\237\226\211/cpp_ext_1.c" "b/developer/cc\360\237\226\211/cpp_ext_1.c" index 63d63f7..ee69a22 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_1.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_1.c" @@ -15,6 +15,15 @@ DROPE_EMPTY_RIGHT #define CAT(sep,first,...) \ +Instead of comma separated lists consider instead to make a list with #define: +``` +#define LIST_1 +#define LIST_2 + +#ifdef LIST_2 + ... +`` + */ #ifndef CPP_EXT_1 @@ -124,7 +133,7 @@ DROPE_EMPTY_RIGHT #define CAT(sep ,...) \ IF \ (__VA_ARGS__) \ - (_CAT_s(sep ,__VA_ARGS__)) \ + (_CAT_s( sep ,__VA_ARGS__)) \ () #define _CAT_s(sep ,a ,...)\ @@ -141,6 +150,28 @@ DROPE_EMPTY_RIGHT #define _CAT_ss_CONFEDERATE() _CAT_ss + // comma does not work with CAT so use this, though perhaps list ,a would be faster? + #define APPEND(...) \ + IF \ + (__VA_ARGS__) \ + (_APPEND_s(__VA_ARGS__)) \ + () + + #define _APPEND_s(a ,...)\ + IF \ + (__VA_ARGS__) \ + ( EVAL(_APPEND_ss(a ,__VA_ARGS__)) ) \ + (a) + + #define _APPEND_ss(accumulator ,a ,...) \ + IF \ + (__VA_ARGS__) \ + ( DEFER2(_APPEND_ss_CONFEDERATE)()(accumulator, a, ,__VA_ARGS__) ) \ + (accumulator,a) + + #define _APPEND_ss_CONFEDERATE() _APPEND_ss + + /*=========================================================================== Quantifiers ===========================================================================*/ diff --git "a/developer/cc\360\237\226\211/scatch.c" "b/developer/cc\360\237\226\211/scatch.c" new file mode 100644 index 0000000..98ab003 --- /dev/null +++ "b/developer/cc\360\237\226\211/scatch.c" @@ -0,0 +1,470 @@ + + + + + + + + + + + //----------------------------------- + // generic call wrappers + + Local TM·Tape·Topo TM·Tape·topo(TM *tm){ + return tm->fg.Tape·topo(tm); + } + Local TM·Tape·Topo TM·Tape·bounded(TM *tm){ + return TM·tape_top(tm) & TM·Tape·Topo·bounded); + } + + Local TM·Head·Status TM·head_status(TM *tm){ + return tm->fg.status(tm ,result); + } + Local TM·Head·Status TM·head_on_tape(TM *tm){ + return TM·status(tm) & TM·Head·Status·on_tape; + } + + // does nothing if the head is already mounted + Local Core·Status TM·mount(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk, 1, tm, TM·Msg·tm); + Core·Guard·if_return(chk); + #endif + if( !TM·head_on_tape(tm) ) return Core·Status·on_track; + return tm->fg.mount(tm); + } + + // does nothing if the head is already dismounted + Local Core·Status TM·dismount(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk, 1, tm, TM·Msg·tm); + Core·Guard·if_return(chk); + #endif + if( TM·head_status(TM *tm) & TM·Head·Status·dismounted) ) return Core·Status·on_track; + return tm->fg.dismount(tm); + } + + #define TM·macro·bool_tm(name) + Local bool name(TM *tm){ \ + #ifdef TM·DEBUG \ + Core·Guard·init_count(chk); \ + Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); \ + Core·Guard·assert(chk); \ + #endif \ + return tm->fg.name(tm); \ + } + + Local bool TM·macro·bool_tm(on_leftmost); + Local bool TM·macro·bool_tm(on_rightmost); + Local bool TM·macro·bool_tm(step); + Local bool TM·macro·bool_tm(step_left); + Local bool TM·macro·bool_tm(rewind); + + //---------------------------------------- + // Initialization for TM·fg + + Local TM·Binding TM·fg = { + .Tape·topo = TM·Tape·topo + ,.Tape·bounded = TM·Tape·bounded + ,.Head·status = TM·Head·status + ,.Head·on_tape = TM·Head·on_tape + + ,.Head·on_leftmost = TM·Head·on_leftmost + ,.Head·on_rightmost = TM·Head·on_rightmost + + ,.mount = TM·mount + ,.dismount = TM·dismount + + ,.step = TM·step + ,.step_left = TM·step_left + ,.step_right = TM·step // Synonym + ,.rewind = TM·rewind + + }; + + #endif // ifndef TM·CVT + + //----------------------------------- + // TM·CVT dependent functions + + #ifdef TM·CVT + + Local Ξ(extent_t ,TM·CVT) Ξ(TM ,TM·CVT)·extent(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,TM·Tape·bounded(tm) ,"Tape is not bounded."); + Core·Guard·assert(chk); + #endif + return tm->fg.extent(tm); + } + + Local TM·CVT TM·read(TM *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); + Core·Guard·assert(chk); + #endif + return tm->fg.read(tm); + } + + Local void TM·write(TM *tm ,TM·CVT *write_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check( &chk ,1 ,TM·head_on_tape(tm) ,TM·Msg·head); + Core·Guard·fg.check( &chk ,1 ,write_pt ,"Given NULL write_pt"); + Core·Guard·assert(chk); + #endif + return tm->fg.write(tm ,write_pt); + } + + Local Ξ(TM ,TM·CVT)·Binding Ξ(TM ,TM·CVT)·fg = { + .parent = TM·fg + ,.extent = Ξ(TM ,TM·CVT)·extent + ,.read = Ξ(TM ,TM·CVT)·read + ,.write = Ξ(TM ,TM·CVT)·write + }; + + #endif // ifdef TM·CVT + + + + #endif // ifdef TM·CVT + +#endif // LOCAL + +//-------------------------------------------------------------------------------- +// Library - compiled into a lib.a file by the current make +// TM currently has no library components +//-------------------------------------------------------------------------------- +#ifdef LIBRARY +#endif + +//-------------------------------------------------------------------------------- +// undef the template parameters +//-------------------------------------------------------------------------------- +#undef TM·CVT + + //---------------------------------------- + // TM·Array implementation + //---------------------------------------- + + /* + 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 + and remounted. + + 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. + + Re-initializing a TM·Array while in use can lead to unspecified badness. Use `rewind` instead. + */ + + //---------------------------------------- + // TM·Array implementation + //---------------------------------------- + + #ifndef TM·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·status="bad head status"; + + + #endif // #ifndef TM·CVT + + #ifdef TM·CVT + + + + + + // check the Tape·topo to make sure tape has extent before calling this + // `extent·TM·CVT` returns the index to the rightmost cell in the array. + Local Ξ(extent_t ,TM·CVT) Ξ(TM·Array ,TM·CVT)·extent(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Tape·Topo Tape·topo = Core·Tape·Topo·mu; + Core·Status status = Ξ(TM·Array ,TM·CVT)·Tape·topo(tm ,&Tape·topo); + bool good_Tape·topo = + (status == Core·Status·on_track) && (Tape·topo & Core·Tape·Topo·finite_nz) + ; + Core·Guard·fg.check(&chk ,1 ,good_Tape·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 ,TM·CVT)·mount_pe( + Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *position ,Ξ(extent_t ,TM·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 TM·CVT is not a power of two this can perform a divide + Local Core·Status Ξ(TM·Array ,TM·CVT)·mount_pp( + Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *pos_leftmost ,TM·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 ,TM·CVT) extent = pos_rightmost - pos_leftmost); + return Ξ(TM·Array ,TM·CVT)·mount_pe(tm ,pos_leftmost ,extent); + } + + //----------------------------------- + // base Tape Machine operations + + Local Core·Status Ξ(TM·Array ,TM·CVT)·mount(Ξ(TM·Array ,TM·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 ,TM·CVT)·dismount(Ξ(TM·Array ,TM·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 ,TM·CVT)·head_status(TM *tm){ + if(!tm || !tm->position) return TM·Head·Status·mu; + if(!tm->hd) return TM·Head·Status·dismounted; + if(tm->hd == tm->position) return TM·Head·Status·leftmost; + + TM·CVT *rightmost_pt = tm->position + tm->extent; + if(tm->hd == rightmost_pt) TM·Head·Status·rightmost; + if(tm->hd < tm->position || tm->hd > rightmost_pt) + return TM·Head·Status·out_of_area; + + return TM·Head·Status·interim; + } + + bool Ξ(TM·Array ,TM·CVT)·can_read(Ξ(TM·Array ,TM·CVT) *tm){ + return tm && tm->position && tm->hd; + } + + // can_read was true + bool Ξ(TM·Array ,TM·CVT)·on_origin(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·CVT)·on_rightmost(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·CVT)·step(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·CVT)·step_left(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·CVT)·rewind(Ξ(TM·Array ,TM·CVT) *tm){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·CVT)·copy_datum(Ξ(TM·Array ,TM·CVT) *tm_read ,Ξ(TM·Array ,TM·CVT) *tm_write){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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 ,TM·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 ,TM·CVT)·read(Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *read_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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); + } + + + // step_right is a synonym for step + + + //---------------------------------------- + // Initialization for Ξ(TM·Array ,TM·CVT)·fg + + Local Ξ(TM·Array ,TM·CVT)·Binding Ξ(TM·Array ,TM·CVT)·fg = { + .tape = { + .Tape·topo = Ξ(TM·Array ,TM·CVT)·Tape·topo + .extent = Ξ(TM·Array ,TM·CVT)·extent + } + + ,.area = { + .mount_pe = Ξ(TM·Array ,TM·CVT)·mount_pe + ,.mount_pp = Ξ(TM·Array ,TM·CVT)·mount_pp + } + + ,.mount = Ξ(TM·Array ,TM·CVT)·mount + ,.dismount = Ξ(TM·Array ,TM·CVT)·dismount + + ,.status = Ξ(TM·Array ,TM·CVT)·status + ,.head_on_format = Ξ(TM·Array ,TM·CVT)·head_on_format + + ,.can_read = Ξ(TM·Array ,TM·CVT)·can_read + ,.on_origin = Ξ(TM·Array ,TM·CVT)·on_origin + ,.on_rightmost = Ξ(TM·Array ,TM·CVT)·on_rightmost + + ,.step = Ξ(TM·Array ,TM·CVT)·step + ,.step_left = Ξ(TM·Array ,TM·CVT)·step_left + ,.step_right = Ξ(TM·Array ,TM·CVT)·step_right // Synonym for step + ,.rewind = Ξ(TM·Array ,TM·CVT)·rewind + + ,.copy_datum = Ξ(TM·Array ,TM·CVT)·copy_datum + ,.read = Ξ(TM·Array ,TM·CVT)·read + ,.write = Ξ(TM·Array ,TM·CVT)·write + + }; + + +//-------------------------------------------------------------------------------- + +// scrat + + +void Ξ(TM·Array ,TM·CVT)·write(Ξ(TM·Array ,TM·CVT) *tm ,TM·CVT *write_pt){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + bool flag = true ,s; + s = Ξ(TM·Array ,TM·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; +} + + //----------------------------------- + // TM struct initializers + + Local Core·Status TM·mount_pe( + TM *tm ,TM·CVT *position ,Ξ(extent_t ,TM·CVT) extent + ){ + #ifdef TM·DEBUG + Core·Guard·init_count(chk); + Core·Guard·fg.check(&chk ,1 ,tm ,TM·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 TM·CVT is not a power of two this can perform a divide + Local Core·Status TM·mount_pp( + TM *tm ,TM·CVT *pos_leftmost ,TM·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 ,TM·CVT) extent = pos_rightmost - pos_leftmost); + return TM·mount_pe(tm ,pos_leftmost ,extent); + } + diff --git "a/developer/deprecated\360\237\226\211/About_Python_templates.org" "b/developer/deprecated\360\237\226\211/About_Python_templates.org" new file mode 100644 index 0000000..414366f --- /dev/null +++ "b/developer/deprecated\360\237\226\211/About_Python_templates.org" @@ -0,0 +1,232 @@ +#+TITLE: Python-Based Template Generation (Multi-Module Approach) +#+AUTHOR: Chat GPT + +Below is a single Org-mode document containing **four** separate Python modules +(or scripts). Each code block is top-level (not nested), ensuring they render +correctly. Together, they demonstrate how to generate a parametric `.lib.c` file +for an RT code format library. + +1. **get_template.py**: Returns a base template with `{named_blank}` placeholders. +2. **make_constants.py**: Creates the compile-time constants block for zero, one, etc. +3. **fill_template.py**: Combines the template and constants block, substituting parameters. +4. **A "Main" generator script** (for instance, `gen_n64_lib.py`) that writes out a final file (like `N64.lib.c`). + +You can create additional “main” scripts to produce different `.lib.c` files (e.g., `N128.lib.c`). + +--- + +*1. `get_template.py`* + +#+BEGIN_SRC python +#!/usr/bin/env python3 + +def get_template(): + """ + Returns the base RT C code template, with placeholders like: + {NAMESPACE}, {DIGIT_EXTENT}, {DIGIT_TYPE}, {EXTENT_TYPE}, {CONSTANTS_BLOCK}. + + The final generated .lib.c will replace these with user-specified values. + """ + return r'''#define {NAMESPACE}DEBUG + +#ifndef FACE + #define {NAMESPACE}IMPLEMENTATION + #define FACE +#endif + +#ifndef {NAMESPACE}FACE +#define {NAMESPACE}FACE + + #include + #include + #include + #include + + typedef {EXTENT_TYPE} ExtentType; + typedef {DIGIT_TYPE} Digit; + + // Digit count is (DIGIT_EXTENT + 1) + #define {NAMESPACE}DIGIT_COUNT ( {DIGIT_EXTENT} + 1 ) + + typedef struct {NAMESPACE}T{{ + Digit d[{NAMESPACE}DIGIT_COUNT]; + }} {NAMESPACE}T; + + // forward declarations for constants + extern {NAMESPACE}T *{NAMESPACE}zero; + extern {NAMESPACE}T *{NAMESPACE}one; + extern {NAMESPACE}T *{NAMESPACE}all_one_bit; + extern {NAMESPACE}T *{NAMESPACE}msb; + + // forward declarations for allocations, etc. + +#endif // {NAMESPACE}FACE + +#ifdef {NAMESPACE}IMPLEMENTATION + +#ifndef LOCAL + #include + #include + + // compile-time constants + {CONSTANTS_BLOCK} + + {NAMESPACE}T *{NAMESPACE}zero = &{NAMESPACE}constant[0]; + {NAMESPACE}T *{NAMESPACE}one = &{NAMESPACE}constant[1]; + {NAMESPACE}T *{NAMESPACE}all_one_bit = &{NAMESPACE}constant[2]; + {NAMESPACE}T *{NAMESPACE}msb = &{NAMESPACE}constant[3]; + + // memory allocation prototypes, etc. + +#endif // not LOCAL + +#ifdef LOCAL + // local code: actual function bodies, add, subtract, etc. +#endif // LOCAL + +#endif // {NAMESPACE}IMPLEMENTATION +''' +#+END_SRC + +--- + +*2. `make_constants.py`* + +#+BEGIN_SRC python +#!/usr/bin/env python3 + +def make_constants_block(namespace: str, + digit_type: str, + digit_extent: int) -> str: + """ + Returns a block of code defining static compile-time constants: + static {namespace}T {namespace}constant[4] = { + { { ...zero... } }, + { { ...one... } }, + { { ...allbits... } }, + { { ...msb... } } + }; + + The total digit count is digit_extent + 1. + """ + digit_count = digit_extent + 1 + + def digits_zero(): + return ", ".join("0" for _ in range(digit_count)) + + def digits_one(): + # index 0 => 1, rest => 0 + return ", ".join("1" if i == 0 else "0" for i in range(digit_count)) + + def digits_allbits(): + # each digit => (digit_type)(-1) + return ", ".join(f"( {digit_type} )( -1 )" for _ in range(digit_count)) + + def digits_msb(): + # top index => (digit_type)1 << ((sizeof(digit_type)*8)-1) + items = [] + for i in range(digit_count): + if i == digit_count - 1: + items.append(f"( {digit_type} )1 << ((sizeof({digit_type})*8) - 1)") + else: + items.append("0") + return ", ".join(items) + + return f'''\ +static {namespace}T {namespace}constant[4] = {{ + {{ + // zero + {{ {digits_zero()} }} + }}, + {{ + // one + {{ {digits_one()} }} + }}, + {{ + // all bits + {{ {digits_allbits()} }} + }}, + {{ + // msb + {{ {digits_msb()} }} + }} +}};''' + +#+END_SRC + +--- + +*3. `fill_template.py`* + +#+BEGIN_SRC python +#!/usr/bin/env python3 + +from get_template import get_template +from make_constants import make_constants_block + +def fill_template(namespace: str, + digit_extent: int, + digit_type: str, + extent_type: str) -> str: + """ + Renders the final .lib.c code by merging: + - the base template from get_template() + - the compile-time constants block from make_constants_block() + - placeholders for namespace, digit_extent, digit_type, extent_type + """ + template = get_template() + constants_block = make_constants_block(namespace, digit_type, digit_extent) + + # Substitute placeholders + code = template.format( + NAMESPACE = namespace, + DIGIT_EXTENT = digit_extent, + DIGIT_TYPE = digit_type, + EXTENT_TYPE = extent_type, + CONSTANTS_BLOCK = constants_block + ) + return code +#+END_SRC + +--- + +*4. An Example “Main” Script, `gen_n64_lib.py`* + +#+BEGIN_SRC python +#!/usr/bin/env python3 + +import sys +from fill_template import fill_template + +def main(): + """ + Example: generate a .lib.c with an 'N64·' namespace, + digit_extent=0 => 1 digit total, + digit_type='uint32_t', + extent_type='uint64_t'. + """ + code = fill_template( + namespace = "N64·", + digit_extent = 0, # => digit_count = 1 => 32-bit + digit_type = "uint32_t", + extent_type = "uint64_t" + ) + + with open("N64.lib.c", "w") as f: + f.write(code) + print("Generated N64.lib.c") + +if __name__ == "__main__": + main() +#+END_SRC + +--- + +### Usage + +1. **Place** these four files side-by-side in your project (e.g., a `scripts/` directory). +2. **Mark** them as executable (`chmod +x`). +3. **Run** `./gen_n64_lib.py` to produce `N64.lib.c`. This file will appear in the same directory (or wherever you prefer). +4. **Compile** `N64.lib.c` using your RT C build system (`make -f tool🖉/makefile`, etc.). + +You can then create similar scripts like `gen_n128_lib.py` or unify them into a single driver that takes parameters for namespace, digit_extent, etc. The main advantage is that **Python code** for generating constants is much more readable than M4 macros, and you keep the RT code format in your template exactly as it should appear. diff --git "a/developer/deprecated\360\237\226\211/adding_new_N_types.org" "b/developer/deprecated\360\237\226\211/adding_new_N_types.org" new file mode 100644 index 0000000..efb018b --- /dev/null +++ "b/developer/deprecated\360\237\226\211/adding_new_N_types.org" @@ -0,0 +1,23 @@ +#+TITLE: Adding new N types +#+AUTHOR: Thomas + +* Project Name + +N == Natural Number, aka 'unsigned int'. + +* Pencil directories / pencil suffix. + +The files in the pencil directory, e.g. cc🖉, are 'authored files'. The program 'rm_na' will not delete them. Use 'rm_na" in scripts. + +* Parameterized types + +The templated N type allows a user to specify a digit type, and number of digits. To generate a new multiple digit type, go into the `Python🖉/` directory, add a new write section to the `fill_template` file, and fill in the digit type and number of digits the new type will have. Run `fill_template` and the synthesized file will be written to the `cc/` directory. + + +* Custom types + +Some processors will have processor native types that the templating scheme does not take advantage of. + +Put custom `N_.lib.cc` files in the `cc🖉/` directory. Or new templates in the `Python🖉` directory. Be sure the file name is distinct from existing types, because the testing setup installs all the files. + + diff --git "a/developer/document\360\237\226\211/About_Python_templates.org" "b/developer/document\360\237\226\211/About_Python_templates.org" deleted file mode 100644 index 414366f..0000000 --- "a/developer/document\360\237\226\211/About_Python_templates.org" +++ /dev/null @@ -1,232 +0,0 @@ -#+TITLE: Python-Based Template Generation (Multi-Module Approach) -#+AUTHOR: Chat GPT - -Below is a single Org-mode document containing **four** separate Python modules -(or scripts). Each code block is top-level (not nested), ensuring they render -correctly. Together, they demonstrate how to generate a parametric `.lib.c` file -for an RT code format library. - -1. **get_template.py**: Returns a base template with `{named_blank}` placeholders. -2. **make_constants.py**: Creates the compile-time constants block for zero, one, etc. -3. **fill_template.py**: Combines the template and constants block, substituting parameters. -4. **A "Main" generator script** (for instance, `gen_n64_lib.py`) that writes out a final file (like `N64.lib.c`). - -You can create additional “main” scripts to produce different `.lib.c` files (e.g., `N128.lib.c`). - ---- - -*1. `get_template.py`* - -#+BEGIN_SRC python -#!/usr/bin/env python3 - -def get_template(): - """ - Returns the base RT C code template, with placeholders like: - {NAMESPACE}, {DIGIT_EXTENT}, {DIGIT_TYPE}, {EXTENT_TYPE}, {CONSTANTS_BLOCK}. - - The final generated .lib.c will replace these with user-specified values. - """ - return r'''#define {NAMESPACE}DEBUG - -#ifndef FACE - #define {NAMESPACE}IMPLEMENTATION - #define FACE -#endif - -#ifndef {NAMESPACE}FACE -#define {NAMESPACE}FACE - - #include - #include - #include - #include - - typedef {EXTENT_TYPE} ExtentType; - typedef {DIGIT_TYPE} Digit; - - // Digit count is (DIGIT_EXTENT + 1) - #define {NAMESPACE}DIGIT_COUNT ( {DIGIT_EXTENT} + 1 ) - - typedef struct {NAMESPACE}T{{ - Digit d[{NAMESPACE}DIGIT_COUNT]; - }} {NAMESPACE}T; - - // forward declarations for constants - extern {NAMESPACE}T *{NAMESPACE}zero; - extern {NAMESPACE}T *{NAMESPACE}one; - extern {NAMESPACE}T *{NAMESPACE}all_one_bit; - extern {NAMESPACE}T *{NAMESPACE}msb; - - // forward declarations for allocations, etc. - -#endif // {NAMESPACE}FACE - -#ifdef {NAMESPACE}IMPLEMENTATION - -#ifndef LOCAL - #include - #include - - // compile-time constants - {CONSTANTS_BLOCK} - - {NAMESPACE}T *{NAMESPACE}zero = &{NAMESPACE}constant[0]; - {NAMESPACE}T *{NAMESPACE}one = &{NAMESPACE}constant[1]; - {NAMESPACE}T *{NAMESPACE}all_one_bit = &{NAMESPACE}constant[2]; - {NAMESPACE}T *{NAMESPACE}msb = &{NAMESPACE}constant[3]; - - // memory allocation prototypes, etc. - -#endif // not LOCAL - -#ifdef LOCAL - // local code: actual function bodies, add, subtract, etc. -#endif // LOCAL - -#endif // {NAMESPACE}IMPLEMENTATION -''' -#+END_SRC - ---- - -*2. `make_constants.py`* - -#+BEGIN_SRC python -#!/usr/bin/env python3 - -def make_constants_block(namespace: str, - digit_type: str, - digit_extent: int) -> str: - """ - Returns a block of code defining static compile-time constants: - static {namespace}T {namespace}constant[4] = { - { { ...zero... } }, - { { ...one... } }, - { { ...allbits... } }, - { { ...msb... } } - }; - - The total digit count is digit_extent + 1. - """ - digit_count = digit_extent + 1 - - def digits_zero(): - return ", ".join("0" for _ in range(digit_count)) - - def digits_one(): - # index 0 => 1, rest => 0 - return ", ".join("1" if i == 0 else "0" for i in range(digit_count)) - - def digits_allbits(): - # each digit => (digit_type)(-1) - return ", ".join(f"( {digit_type} )( -1 )" for _ in range(digit_count)) - - def digits_msb(): - # top index => (digit_type)1 << ((sizeof(digit_type)*8)-1) - items = [] - for i in range(digit_count): - if i == digit_count - 1: - items.append(f"( {digit_type} )1 << ((sizeof({digit_type})*8) - 1)") - else: - items.append("0") - return ", ".join(items) - - return f'''\ -static {namespace}T {namespace}constant[4] = {{ - {{ - // zero - {{ {digits_zero()} }} - }}, - {{ - // one - {{ {digits_one()} }} - }}, - {{ - // all bits - {{ {digits_allbits()} }} - }}, - {{ - // msb - {{ {digits_msb()} }} - }} -}};''' - -#+END_SRC - ---- - -*3. `fill_template.py`* - -#+BEGIN_SRC python -#!/usr/bin/env python3 - -from get_template import get_template -from make_constants import make_constants_block - -def fill_template(namespace: str, - digit_extent: int, - digit_type: str, - extent_type: str) -> str: - """ - Renders the final .lib.c code by merging: - - the base template from get_template() - - the compile-time constants block from make_constants_block() - - placeholders for namespace, digit_extent, digit_type, extent_type - """ - template = get_template() - constants_block = make_constants_block(namespace, digit_type, digit_extent) - - # Substitute placeholders - code = template.format( - NAMESPACE = namespace, - DIGIT_EXTENT = digit_extent, - DIGIT_TYPE = digit_type, - EXTENT_TYPE = extent_type, - CONSTANTS_BLOCK = constants_block - ) - return code -#+END_SRC - ---- - -*4. An Example “Main” Script, `gen_n64_lib.py`* - -#+BEGIN_SRC python -#!/usr/bin/env python3 - -import sys -from fill_template import fill_template - -def main(): - """ - Example: generate a .lib.c with an 'N64·' namespace, - digit_extent=0 => 1 digit total, - digit_type='uint32_t', - extent_type='uint64_t'. - """ - code = fill_template( - namespace = "N64·", - digit_extent = 0, # => digit_count = 1 => 32-bit - digit_type = "uint32_t", - extent_type = "uint64_t" - ) - - with open("N64.lib.c", "w") as f: - f.write(code) - print("Generated N64.lib.c") - -if __name__ == "__main__": - main() -#+END_SRC - ---- - -### Usage - -1. **Place** these four files side-by-side in your project (e.g., a `scripts/` directory). -2. **Mark** them as executable (`chmod +x`). -3. **Run** `./gen_n64_lib.py` to produce `N64.lib.c`. This file will appear in the same directory (or wherever you prefer). -4. **Compile** `N64.lib.c` using your RT C build system (`make -f tool🖉/makefile`, etc.). - -You can then create similar scripts like `gen_n128_lib.py` or unify them into a single driver that takes parameters for namespace, digit_extent, etc. The main advantage is that **Python code** for generating constants is much more readable than M4 macros, and you keep the RT code format in your template exactly as it should appear. diff --git "a/developer/document\360\237\226\211/Needed_in_C.org" "b/developer/document\360\237\226\211/Needed_in_C.org" new file mode 100644 index 0000000..d82aa95 --- /dev/null +++ "b/developer/document\360\237\226\211/Needed_in_C.org" @@ -0,0 +1,27 @@ + +1. C needs namespaces. The '·' notation seems to accomplish most of what is needed, and I'm doing this in existing C. Scoped 'using' would be nice for shortening the identifiers. + This can be done without changing the tool chain. + +2. control of evaluation in definitions + + Currently definitions remain literal text. + + Also #redefine delayed assignment to macro_name, with evaluation of the body. + + Without namespaces I can see the problem with developers stepping on each others's macro ames. However, with namespaces it seems that #redefine, or #redef is tractable. + +3. Something should be done about macros having to be on one line and having to account for, format, all those \. Perhaps an emacs mode similar as used for paragraphs? Anyway something should be done. + +4. ability to declare a type hierarchy based on struct types having the same field + names and format, or extensions thereof. + + typehier pair -> vector-2d -> complex + + Something like that. + +5. compiler switch to put the struct etc. types into the same space with the others. of course. + + +6. ability to use a macro to define a macro name. first create a value, then + call a function to enter it into the symbol table. + diff --git "a/developer/document\360\237\226\211/adding_new_N_types.org" "b/developer/document\360\237\226\211/adding_new_N_types.org" deleted file mode 100644 index efb018b..0000000 --- "a/developer/document\360\237\226\211/adding_new_N_types.org" +++ /dev/null @@ -1,23 +0,0 @@ -#+TITLE: Adding new N types -#+AUTHOR: Thomas - -* Project Name - -N == Natural Number, aka 'unsigned int'. - -* Pencil directories / pencil suffix. - -The files in the pencil directory, e.g. cc🖉, are 'authored files'. The program 'rm_na' will not delete them. Use 'rm_na" in scripts. - -* Parameterized types - -The templated N type allows a user to specify a digit type, and number of digits. To generate a new multiple digit type, go into the `Python🖉/` directory, add a new write section to the `fill_template` file, and fill in the digit type and number of digits the new type will have. Run `fill_template` and the synthesized file will be written to the `cc/` directory. - - -* Custom types - -Some processors will have processor native types that the templating scheme does not take advantage of. - -Put custom `N_.lib.cc` files in the `cc🖉/` directory. Or new templates in the `Python🖉` directory. Be sure the file name is distinct from existing types, because the testing setup installs all the files. - - diff --git "a/developer/document\360\237\226\211/build.org" "b/developer/document\360\237\226\211/build.org" new file mode 100644 index 0000000..a499421 --- /dev/null +++ "b/developer/document\360\237\226\211/build.org" @@ -0,0 +1,8 @@ + + +> make clean +> make dependency +> make library +> make cli + +I manually edit the make file to turn on and off the making of the main program or the example directories. See notes in ` tool🖉/makefile`. diff --git "a/developer/document\360\237\226\211/coffee.txt" "b/developer/document\360\237\226\211/coffee.txt" new file mode 100644 index 0000000..daf4508 --- /dev/null +++ "b/developer/document\360\237\226\211/coffee.txt" @@ -0,0 +1,20 @@ +/* + Coffee Species Reference + + | Species | Origin(s) | Flavor Notes | Notes | + |-----------|----------------------------|----------------------------|------------------------------- | + | Arabica | Vietnam (Da Lat), Malawi | Floral, bright, acidic | High elevation, lower caffeine | + | Robusta | Vietnam (Dak Lak, Gia Lai) | Bitter, strong, earthy | Common in Vietnamese blends | + | Excelsa | Vietnam (Central Highlands)| Tart, fruity, smoky | Adds depth, low production | + | Liberica | Vietnam (rare farms) | Woody, floral, full-bodied | Very large beans, low yield | + + Likely Blend (CASA Blue Mountain): + - Arabica (Malawi or Da Lat) + - Robusta (Vietnam) + - Possibly Excelsa (depth/complexity) + + Notes: + - "Made in Taiwan" likely refers to roasting/packaging. + - Shelf life: 2 years (cool, dry, or frozen recommended). + - Freezing whole beans is safe *if sealed airtight* and thawed only once. +*/ diff --git "a/developer/document\360\237\226\211/cpp_CAT_and_comma.org" "b/developer/document\360\237\226\211/cpp_CAT_and_comma.org" deleted file mode 100644 index 1507b5c..0000000 --- "a/developer/document\360\237\226\211/cpp_CAT_and_comma.org" +++ /dev/null @@ -1,44 +0,0 @@ -* CATSEP Separator Expansion Notes -:PROPERTIES: -:CREATED: [2025-04-01] -:END: - -** Problem - -When using `CATSEP` (or `CAT`) to join tokens with a separator, we encountered an issue where passing a macro-defined separator (e.g. `COMMA`) leads to incorrect behavior: - -- The macro expands too early. -- The result is malformed token pasting like `,A` instead of proper separation. -- This happens because `##` prevents further expansion, so any `sep` macro used in a `##` must already be fully resolved. - -** Attempts - -We tried multiple versions: -- Using `DEFER`, `DEFER2`, `DEFER3` to hide expansion. -- Wrapping the separator in a macro (e.g. `DEFER_SEP()`). -- Recursive accumulation models with delayed evaluation. - -** Findings - -- The separator **must not be a macro** when passed as an argument to a `##` operation. -- Macro arguments are always expanded before `##` is applied, unless blocked (e.g., by an extra layer of indirection). -- `##` prevents further expansion, so once the macro has been expanded into a literal comma (`,`) or semicolon (`;`), it can no longer be deferred. - -** Recommendation - -Use raw characters or tokens as separators, not macros. For example: - -#+begin_src c -CAT(, A ,B ,C) // OK makes a token ABC -CAT(;, A ,B ,C) // OK - [I don't think this works either] -CAT(__oo__, A ,B ,C) // OK A__oo__B__oo__C -CAT(COMMA, A ,B ,C) // ❌ COMMA expands too early -#+end_src - -If you must use a macro-defined separator, redesign may be required. For now: - -** Conclusion - -⛔ **Do not use macro-defined separators in `CAT` or `CATSEP`.** - -Leave this as a known limitation and revisit if/when it becomes essential. Better to avoid the rabbit hole for now. diff --git "a/developer/document\360\237\226\211/cpp_evaluation.org" "b/developer/document\360\237\226\211/cpp_evaluation.org" index 5c6a493..4529a7a 100644 --- "a/developer/document\360\237\226\211/cpp_evaluation.org" +++ "b/developer/document\360\237\226\211/cpp_evaluation.org" @@ -4,8 +4,8 @@ 1. Macro function definition - Macro function definitions are not evaluated, so macro calls in them remain - literal. + Macro function definitions are not evaluated, so the body (the definition) of the macro remains literal until the time it is called. Thus macro calls in macro defintion remain + literal, unevaluated. A macro function has three parts, 1) a name 2) a parameter list 3) body @@ -21,8 +21,18 @@ #define name(x ,...) #+END_SRC +2. directives + + #ifdef and #ifndef to not evaluate what follows. They expect a full formed + macro name. + + #if does evaluate, but expects existence as true, and 0 as false (though zero + also exists). Non-existence is an error. Wrap cpp_ext_0 logic in BOOLEAN to get 1 or 0. (cpp_ext_0 logic is true for existence, and false for nonexistence.) + 2. Macro Call + A macro call that was colored blue will not be expanded. + A macro call can occur anywhere in the source code. It takes the form of a macro name followed by an argument list: @@ -36,73 +46,67 @@ cpp scans the tokens in the translation unit, upon finding a macro call it replaces it with the body from the macro definition using the following steps: -** 1. Argument Substitution Phase + ** 1. Argument Substitution Phase - When the macro is invoked: + When the macro is invoked: - 1. Each parameter in the macro body is replaced *verbatim* with the - corresponding argument. No evaluation is performed at this stage. + 1. Each parameter in the macro body is replaced *verbatim* with the + corresponding argument. No evaluation is performed at this stage. - 2. The new macro body is a new token stream: the old macro body with arguments pasted in. + 2. The new macro body is a new token stream: the old macro body with arguments pasted in. -** 2. Evaluation Phase + ** 2. Evaluation Phase - The preprocessor then scans the argument substituted macro body *from left to right*, - evaluating macro calls *as it encounters them*. + The preprocessor then scans the argument substituted macro body *from left to right*, + evaluating macro calls *as it encounters them*. - - If a token is **not** a macro call (see below), it is included as-is. - - If a token **is** a macro call, it is expanded immediately, using the same two-phase process. + - If a token is **not** a macro call (see below), it is included as-is. + - If a token **is** a macro call, it is expanded immediately, using the same two-phase process. - This produces a depth-first, left-to-right expansion strategy. + This produces a depth-first, left-to-right expansion strategy. - Non-macro-call tokens include: + Non-macro-call tokens include: - 1. Any non-identifier (e.g. `+`, `123`, `"text"`) + 1. Any non-identifier (e.g. `+`, `123`, `"text"`) - 2. Any identifier **not followed by `(`** + 2. Any identifier **not followed by `(`** - 3. Any parameter or token used with `#` + 3. Any parameter or token used with `#` - - `#param` turns the *original* argument text into a string. - - Because it stringifies, *the argument is never evaluated*. + - `#param` turns the *original* argument text into a string. + - Because it stringifies, *the argument is never evaluated*. - 4. Any parameter or token used with `##` + 4. Any parameter or token used with `##` - - `##` concatenates tokens without evaluating them. - - The pasted result is *not* scanned recursively for macro calls. + - `##` concatenates tokens without evaluating them. + - The pasted result is *not* scanned recursively for macro calls. - 5. any macro call token that has been "colored blue" by the evaluator. + 5. any macro call token that has been "colored blue" by the evaluator. - It is common that macros containing a `#` or a `##` will have an extra call - layer above them to cause the argument to be first substituted into a macro - where it will get evaluated. Large number of Eval calls are typically not needed - for this, rather what is needed is one layer above the layer with the `#` or `##`. + It is common that macros containing a `#` or a `##` will have an extra call + layer above them to cause the argument to be first substituted into a macro + where it will get evaluated. Large number of Eval calls are typically not needed + for this, rather what is needed is one layer above the layer with the `#` or `##`. -** 3. Colored blue macro call tokens are taken as literal text. + ** 3. Colored blue macro call tokens are taken as literal text. - A macro color token is the text of a macro call considered as a single token. The following is an example macro call token: + During evaluation cpp keeps a list of macros that are actively being expanded. This includes the macro that has been called, of course, and all the calls that it found during its depth traversal to get to the current point of evaluation. If it sees any calls to the macros on the active expand list, it marks the macro call token itself as unexpandable, and thus to be treated as literal text. It is said that the macro call token "has been colored blue". - #+BEGIN_SRC c - name(1 ,a ,b) - #+END_SRC - - During evaluation cpp keeps a list of macros that are actively being expanded. This includes the macro that has been called, of course, and all the calls that it found during its depth traversal to get to the current point of evaluation. If it sees any calls to the macros on the active expand list, it marks the macro call token itself as unexpandable, and thus to be treated as literal text. It is said that the macro call token "has been colored blue". + Any subsequent appearance of a colored blue macro call token will be treated as literal text, no matter the context. This includes if the macro result was assigned to a variable, then that variable is evaluated later. It includes if the macro call token or the expression it is in is sent to another macro, etc. - Any subsequent appearance of a colored blue macro call token will be treated as literal text, no matter the context. This includes if the macro result was assigned to a variable, then that variable is evaluated later. It includes if the macro call token or the expression it is in is sent to another macro, etc. + Example: - Example: + #+BEGIN_SRC c + #define GROW(x) 1029 * GROW(x) + #define RESULT GROW(5) - #+BEGIN_SRC c - #define GROW(x) 1029 * GROW(x) - #define RESULT GROW(5) - - SHOW(RESULT); // → 1029 * GROW(5) - SHOW(EVAL(RESULT)); // → 1029 * GROW(5) again, never expands - #+END_SRC + SHOW(RESULT); // → 1029 * GROW(5) + SHOW(EVAL(RESULT)); // → 1029 * GROW(5) again, never expands + #+END_SRC - The macro call token `GROW(x)` which occurs in the body of a macro definition of the same name, gets colored blue, and thus is always treated as literal text. This happens even though an expression containing it is assigned to a variable, then that variable is evaluated in a totally different evaluation context. + The macro call token `GROW(x)` which occurs in the body of a macro definition of the same name, gets colored blue, and thus is always treated as literal text. This happens even though an expression containing it is assigned to a variable, then that variable is evaluated in a totally different evaluation context. - Apparently the designers of cpp do not want people to design recursive structures with cpp. However, there is a trick for getting around it using a confederate in place of the recursive call, then putting back the original call later, as shown in section 6. + Apparently the designers of cpp do not want people to design recursive structures with cpp. However, there is a trick for getting around it using a confederate in place of the recursive call, then putting back the original call later, as shown in section 6. 3. Example macros @@ -121,8 +125,7 @@ 5. Cascading evaluation - A macro can also fail to evaluate all possible macros, because during - the left to right scan, it did not see the new macro call. + A macro can also fail to evaluate all possible macros, because during the left to right scan, it created a macro call, but during the scan it did not see it. #+BEGIN_SRC c #define NULL_FN() // expands to nothing @@ -140,7 +143,9 @@ 3. ~(x)~ is not a macro so there is nothing to recur into, so it becomes ~(5)~. - 4. Thus the final result of the left to right pass is → ~NEGATE (5)~ + 4. Thus the final result of the left to right pass is → ~NEGATE (5)~ The evaluator + recursively expands calls, but it never saw ~NEGATE (5)~, so it remains unexpanded. + This is the second reason a literal macro call might occur in an expansion. #+BEGIN_SRC bash cat >test.c < macro calls in macro defintions remain literal, i.e. unevaluated. + +4. + Macros can be called with empty arguments. #+BEGIN_SRC c @@ -24,8 +31,54 @@ Macros can be called with empty arguments. int a_macro (a,,b) // -> a + + c #+END_SRC -4. +5. The COMMA macro, though defined, can't be used in any two level or more deep macro calls, because it will expand to a comma on the first level. It perhaps could be wrapped in a function that is given a deferred call, and then have eval expand it, dunno. +4o has written a little doc about this: + + * CATSEP Separator Expansion Notes + :PROPERTIES: + :CREATED: [2025-04-01] + :END: + + ** Problem + + When using `CATSEP` (or `CAT`) to join tokens with a separator, we encountered an issue where passing a macro-defined separator (e.g. `COMMA`) leads to incorrect behavior: + + - The macro expands too early. + - The result is malformed token pasting like `,A` instead of proper separation. + - This happens because `##` prevents further expansion, so any `sep` macro used in a `##` must already be fully resolved. + + ** Attempts + + We tried multiple versions: + - Using `DEFER`, `DEFER2`, `DEFER3` to hide expansion. + - Wrapping the separator in a macro (e.g. `DEFER_SEP()`). + - Recursive accumulation models with delayed evaluation. + + ** Findings + + - The separator **must not be a macro** when passed as an argument to a `##` operation. + - Macro arguments are always expanded before `##` is applied, unless blocked (e.g., by an extra layer of indirection). + - `##` prevents further expansion, so once the macro has been expanded into a literal comma (`,`) or semicolon (`;`), it can no longer be deferred. + + ** Recommendation + + Use raw characters or tokens as separators, not macros. For example: + + #+begin_src c + CAT(, A ,B ,C) // OK makes a token ABC + CAT(;, A ,B ,C) // OK - [I don't think this works either] + CAT(__oo__, A ,B ,C) // OK A__oo__B__oo__C + CAT(COMMA, A ,B ,C) // ❌ COMMA expands too early + #+end_src + + If you must use a macro-defined separator, redesign may be required. For now: + + ** Conclusion + + ⛔ **Do not use macro-defined separators in `CAT` or `CATSEP`.** + + Leave this as a known limitation and revisit if/when it becomes essential. Better to avoid the rabbit hole for now. diff --git "a/developer/document\360\237\226\211/general_notes.org" "b/developer/document\360\237\226\211/general_notes.org" deleted file mode 100644 index 9090e71..0000000 --- "a/developer/document\360\237\226\211/general_notes.org" +++ /dev/null @@ -1,10 +0,0 @@ -#+TITLE: General notes -#+AUTHOR: Thomas - -* Files in the `cc/` directory are .gitignore and can be deleted by clean scripts. This directory is for the output of template generation. - -* There is a stylistic form for using these files. The `FACE` section include goes at the top and the `LOCAL` include at the bottom of the user's source files. Then link with `N.lib.a`. - -* Most of the work is done in the `LOCAL` section. - -* Compile with optimization to make the calls to the `LOCAL` functions compile out, leaving clean inline code. (That is the intention anyway, as of this writing development is still ongoing.) diff --git "a/developer/document\360\237\226\211/todo.org" "b/developer/document\360\237\226\211/todo.org" index 984f156..139597f 100644 --- "a/developer/document\360\237\226\211/todo.org" +++ "b/developer/document\360\237\226\211/todo.org" @@ -1,31 +1,2 @@ -* 2025-02-14T16:12:47Z new namespace names for the current `.lib_std` files. -done -* 2025-02-14T16:20:52Z consider adding macros to replace multi-digit sequences with native types when available in some situations. - - -* 2025-02-21T09:43:26Z Copy.lib.c should be templated with the block copy type, currently uint64_t templated, and the alginment mask templated. Also need macro gates to - turn off expansion when there is no uint64_t support. Also need a naive byte - copy version that works when there is not even a unint32_t type. - - -* 2025-02-24T08:09:57Z Copy.lib.c forced alginment machine might have issues with the block copy. - - The block copy aligns the read pointer by copying some initial - bytes. It ignores the alignment on the write pointer. Then at the end it does a byte - by byte copy of the ragged tail (less than a full word number of bytes). - - For a system that forces alignment, the initial alignment of the read pointer will get skipped. The write pointer will be aligned, so there is no problem in not checking it. - - However, the ragged tail loop can fire on a forced aligned - system. This will happen if the bounding read pointer passed in to - the block copy is not pointing to the first byte of a word. This can - happen if it is created adding `sizeof` of an object with that is not an even number - of bytes in a word long. - - The solution is probably to set a 'force align' macro based on the - architecture macro and gating the ragged tail code to do a word - copy, or affecting the bulk section to do one more loop -- or having - a differnt block copy an bytes_reversed block copy that loops on - words. diff --git a/developer/example/bespoke_type.cli.c b/developer/example/bespoke_type.cli.c index b8de24b..c307dbf 100644 --- a/developer/example/bespoke_type.cli.c +++ b/developer/example/bespoke_type.cli.c @@ -19,56 +19,86 @@ Here by 'type' we mean a Tableau to FG table binding. */ - #define EQ__Bespoke__oo__Bespoke #undef Binding·TYPE #define Binding·TYPE Bespoke - #include "../cc🖉/Binding.lib.c" - -#if 0 + #define Binding·TYPE·Bespoke + #include "Binding.lib.c" // This defines the FG table type for Bespoke (aka vtable). Each instance is a different implementation of the type sharing the same interface. - typedef struct{ - void (*version)(Bespoke c); - void (*report)(Bespoke c ,*mess); + typedef struct Bespoke·FG{ + void (*version)(Bespoke·Tableau *t); + void (*report)(Bespoke·Tableau *t ,char *mess); }Bespoke·FG; // This defines the Tableau, the data that is given as a first argument of each FG table entry. - typedef struct{ - void (*version)(Bespoke c); - void (*report)(Bespoke c ,*mess); + typedef struct Bespoke·Tableau{ + }Bespoke·Tableau; // This creates a FG table to Tableau binding type. We will use this to represent the type. // The EQ pattern is required for `FIND_ITEM` to recognize the type: // these functions will be used for making an instance of the abstract Bespoke type - void Bespoke·version(Bespoke c){ printf("A Bespoke instance") }; - void Bespoke·report(Bespoke c ,*mess){ printf("A Bespoke instance says %s" ,mess)}; -#endif + void Bespoke·version(Bespoke·Tableau *t){ printf("version 1.0\n"); }; + void Bespoke·report(Bespoke·Tableau *t ,char *mess){ printf("The report: %s\n" ,mess);}; + int main(){ + printf("running example binding.cli.c on %s at %s\n", __DATE__, __TIME__); + SHOW(Ξ(Binding·TYPE ,FG)); + #define A 5 SHOW(A); #define B Ξ(X,Y) SHOW(B); -#if 0 - Bespoke·FG = { + // one FG table will be shared by many instances of Bespoke, maybe all of them + Bespoke·FG fg = { .version = Bespoke·version ,.report = Bespoke·report }; -#endif + // The Bespoke·Tableau carries the instance data', often is one to one to a binding. + Bespoke·Tableau t; + + // allocate a binding + Bespoke spoke; + + // Initialize the binding, this the job of a type specific init function. + // in C we don't know where the user is allocating the data, otherwise we would + // have a factory instead of an initializer. + spoke.fg = &fg; + spoke.tableau = &t; + + // direct use of the fg table, the user/programmer should not do this + fg.version(spoke.tableau); + fg.report(spoke.tableau ,"fg.report"); + + // does the binding have null pointers? + printf("fg: %p, tableau: %p\n", (void*)spoke.fg, (void*)spoke.tableau); + + // calling though the binding + spoke.fg->version(spoke.tableau); + spoke.fg->report(spoke.tableau ,"spoke.fg->report"); + + printf("and version again\n"); + spoke.fg->version(spoke.tableau); + printf("before Binding·call to version\n"); + Binding·call(spoke ,version); + printf("after Binding·call to version.\n"); + + printf("before Binding·call to report\n"); + Binding·call(spoke ,report ,"Binding·call to report"); + printf("after Binding·call to report\n"); return 0; } -#define IMPLEMENTATION #define LOCAL +#include "Core.lib.c" + -//#include "../cc🖉/Core.lib.c" -//#include "../cc🖉/Binding.lib.c" diff --git a/developer/example/holder/try_TM_1.cli.c b/developer/example/holder/try_TM_1.cli.c new file mode 100644 index 0000000..1851978 --- /dev/null +++ b/developer/example/holder/try_TM_1.cli.c @@ -0,0 +1,61 @@ +/* + try_TM.cli.c - Example use of TM·AU type with array backend. +*/ + +#include "cpp_ext.c" +#include "Core.lib.c" +#include "Binding.lib.c" +#include "TM.lib.c" + +#define EQ__TM·AU__oo__TM·AU +#define TM·CVT AU +#include "TM.lib.c" + +int main(){ + + printf("running try_TM.cli.c on %s at %s\n", __DATE__, __TIME__); + + SHOW(Ξ(TM·CVT ,FG)); // TM·AU·FG + SHOW(Ξ(TM·CVT ,Tableau)); // TM·AU·Tableau + + // Create a tape with 5 AU values + AU tape[] = {1 ,2 ,3 ,4 ,5}; + extent_t·AU extent = sizeof(tape) - 1; + + // Init the tableau + Ξ(TM ,AU)·Tableau t; + Ξ(TM ,AU)·init_pe(&t ,tape ,extent); + + // Allocate a binding + TM·AU tm; + tm.fg = &Ξ(TM ,AU)·fg; + tm.tableau = &t; + + // Call version of the TM status + printf("Before any operations:\n"); + Binding·call(tm ,rewind); + + AU datum = Binding·call(tm ,read); + printf("Initial datum: %u\n", datum); + + // Step and read again + Binding·call(tm ,step); + datum = Binding·call(tm ,read); + printf("After step, datum: %u\n", datum); + + // Write a new value + AU value = 99; + Binding·call(tm ,write ,&value); + + // Rewind and read again + Binding·call(tm ,rewind); + datum = Binding·call(tm ,read); + printf("After rewind, datum: %u\n", datum); + + return 0; +} + +#define LOCAL +#include "Core.lib.c" +#include "Binding.lib.c" +#include "TM.lib.c" diff --git "a/developer/tool\360\237\226\211/makefile" "b/developer/tool\360\237\226\211/makefile" index 8dfa07c..41932ad 100644 --- "a/developer/tool\360\237\226\211/makefile" +++ "b/developer/tool\360\237\226\211/makefile" @@ -5,8 +5,11 @@ include $(RT-INCOMMON)/make/environment_RT_0 # to compile only the example directory # comment these out for a normal compile +# SRCDIR_List=example +# # if the .lib.c interfaces are needed: +# CFLAGS+=-Icc🖉 CFLAGS+= -include "$(RT-INCOMMON)/make/RT_0.h"