From: Thomas Walker Lynch Date: Sat, 29 Mar 2025 15:12:11 +0000 (+0000) Subject: put cpp examples in example_cpp, debugged `FIND`, making example for type X-Git-Url: https://git.reasoningtechnology.com/style/static/git-favicon.png?a=commitdiff_plain;h=e6f0ac5a88130bd5f8b79a5261283c9a543622ce;p=N put cpp examples in example_cpp, debugged `FIND`, making example for type --- diff --git "a/developer/cc\360\237\226\211/Binding.lib.c" "b/developer/cc\360\237\226\211/Binding.lib.c" new file mode 100644 index 0000000..67e7082 --- /dev/null +++ "b/developer/cc\360\237\226\211/Binding.lib.c" @@ -0,0 +1,103 @@ +/* +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 +#pragma message( "before gate" ) +#pragma message( STR_VAL(Binding·TYPE) ) +#ifdef Binding·TYPE +#if ! FIND_ITEM( Binding·TYPE ,Binding·TYPE_LIST ) +#pragma message( "after gate" ) +#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) +#if 0 + + // 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; + + 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 +#endif + +//-------------------------------------------------------------------------------- +// Implementation +// Binding has no implementation + +#ifdef IMPLEMENTATION + + //---------------------------------------- + // implementation to go into the lib.a file + //---------------------------------------- + #ifndef LOCAL + #endif //#ifndef LOCAL + + //---------------------------------------- + // implementation to go at the bottom of the translation unit + //---------------------------------------- + #ifdef LOCAL + #endif // #ifdef LOCAL + +#endif // IMPLEMENTATION + +//-------------------------------------------------------------------------------- +// template variables work once + +#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 3e78126..031fd69 100644 --- "a/developer/cc\360\237\226\211/Core.lib.c" +++ "b/developer/cc\360\237\226\211/Core.lib.c" @@ -16,58 +16,49 @@ */ -#define Core·DEBUG -#ifdef FG·DEBUG - #include -#endif - -#ifndef FACE -#define Core·IMPLEMENTATION -#define FACE -#endif - //-------------------------------------------------------------------------------- -// Interface +// Interface #ifndef Core·FACE #define Core·FACE + #define Core·DEBUG + #ifdef FG·DEBUG + #include + #endif + #include + #include #include + #include "cpp_ext.c" //---------------------------------------- // memory interface //---------------------------------------- - // Define a namespace. - // #define _Ξ(a ,b) a##·##b - /// #define Ξ(a ,b) _Ξ(a ,b) - #include - // extent is the maximum index in an address space, tape or area, the doted // unit is the cell type. - typedef extent_t·AU size_t + 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; // addressable unit for the machine // C language standard left this undefined. AToW industry uses uint8_t. - typedef AU uint8_t; - typedef AU2 uint16_t; - typedef AU4 uint32_t; - typedef AU8 uint64_t; + typedef uint8_t AU ; + typedef uint16_t AU2; + typedef uint32_t AU4; + typedef uint64_t AU8; - const AU AU_max = (~(AU)0); - const AU2 AU2_max = (~(AU2)0); - const AU4 AU4_max = (~(AU4)0); - const AU8 AU8_max = (~(AU8)0); + const AU AU_MAX = (~(AU)0); + const AU2 AU2_MAX = (~(AU2)0); + const AU4 AU4_MAX = (~(AU4)0); + const AU8 AU8_MAX = (~(AU8)0); // ask the compiler what this is // when using enums we get this whether we want it or not - typedef WU unsigned int; - const WU WU_max = (~(WU)0); + typedef unsigned int WU; + const WU WU_MAX = (~(WU)0); //---------------------------------------- // flag facility, argument guard facility @@ -129,38 +120,6 @@ else return Core·Status·on_track; #define Core·Guard·assert(chk) assert(!chk.flag); - //---------------------------------------- - // Macro to call a function in the FG table with debug checks - // Usage: FG·call(tm, function_name, arg1, arg2, ...) - // Expands to: ((tm)->fg->function_name)((tm)->t, arg1, arg2, ...) - // With debug checks for NULL pointers when FG·DEBUG is defined - //---------------------------------------- - - typedef struct FG·FG; - typedef struct FG·Tableau; - - typedef struct{ - FG·FG *fg; - FG·Tableau *tableau; - } FG·Binding; - - inline void FG·wellformed_binding(FG·Binding b) { - #ifdef FG·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 - } - - // note the use of the comma operator to return the result from b.fg->fn - #define FG·call(b, fn, ...) \ - ( \ - FG·wellformed_binding(b) \ - ,b.fg->fn(b.tableau, ##__VA_ARGS__ ) \ - ) - - //---------------------------------------- // functions interface //---------------------------------------- @@ -170,25 +129,25 @@ typedef struct{ Core·Status (*on_track)(); Core·Status (*derailed)(); - Core·Status (*is_aligned)(AU *p ,extent·AU alignment ,bool *flag); - Core·Status (*round_down)(AU *p ,extent·AU alignment ,AU **result); - Core·Status (*round_up)(AU *p ,extent·AU alignment ,AU **result); + Core·Status (*is_aligned)(AU *p ,extent_t·AU alignment ,bool *flag); + Core·Status (*round_down)(AU *p ,extent_t·AU alignment ,AU **result); + Core·Status (*round_up)(AU *p ,extent_t·AU alignment ,AU **result); } Core·F; Local Core·F Core·f; -#endif // FACE +#endif // #if CORE·FACE //-------------------------------------------------------------------------------- // Implementation -#ifdef Core·IMPLEMENTATION +#ifdef IMPLEMENTATION //-------------------------------------------------------------------------------- // implementation to go into the lib.a file // - #ifndef LOCAL - #endif + #ifndef LOCAL + #endif //-------------------------------------------------------------------------------- #ifdef LOCAL diff --git "a/developer/cc\360\237\226\211/FG.lib.c" "b/developer/cc\360\237\226\211/FG.lib.c" deleted file mode 100644 index 6d659fa..0000000 --- "a/developer/cc\360\237\226\211/FG.lib.c" +++ /dev/null @@ -1,88 +0,0 @@ -/* -Template parameters: - - FG·Type - Type used to name the binding struct. Binding struct instances get passed as arguments to functions etc. - -Template variables are _use once_ per #include. (They are #undef at the bottom of this file.) - -*/ - -#include "cpp_ext.c" - -#ifndef FACE -#define FG·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -// once per translation unit -#ifndef FG·TYPE_LIST -#define FG·TYPE_LIST - - #define FG·DEBUG - #ifdef FG·DEBUG - #include - #endif - -#endif - -// once per FG·TYPE value -#if ! FIND_ITEM( FG·TYPE ,FG·TYPE_LIST ) -#define FG·TYPE_LIST APPEND(FG·TYPE_LIST ,FG·TYPE) - - // a simplifying naming convention - #define FG·Binding Ξ(FG·Type) - #define FG·FG Ξ(FG·Type ,FG) - #define FG·Tableau Ξ(FG·Type ,Tableau) - - // as a convention, we name the binding after the type - typedef struct{ - FG·FG *fg; - FG·Tableau *tableau; - } FG·Binding; - - // binds a tableau and FG tabel instance together - inline void FG·wellformed_binding(FG·Binding b){ - #ifdef FG·DEBUG - FG·Guard·init_count(chk); - FG·Guard·fg.check(&chk, 1, b.fg, "NULL fg table"); - FG·Guard·fg.check(&chk, 1, b.tableau, "NULL tableau"); - FG·Guard·assert(chk); - #endif - } - - /* - usage e.g.: FG·call(tm, function_name, arg1, arg2, ...) - Expands to: (tm.fg->function_name)((tm)->t, arg1, arg2, ...) - - note the use of the comma operator to return the result from the b.fg->fn call - */ - #define FG·call(b, fn, ...) \ - ( FG·wellformed_binding(b) ,b.fg->fn(b.tableau, ##__VA_ARGS__) ) - -#endif // FACE - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef FG·IMPLEMENTATION - - //---------------------------------------- - // implementation to go into the lib.a file - //---------------------------------------- - #ifndef LOCAL - #endif //#ifndef LOCAL - - //---------------------------------------- - // implementation to go at the bottom of the source file - //---------------------------------------- - #ifdef LOCAL - #endif // #ifdef LOCAL - -#endif // IMPLEMENTATION - -// template variables are use once -#undef FG·Type - diff --git "a/developer/cc\360\237\226\211/N16.lib.c" "b/developer/cc\360\237\226\211/N16.lib.c" deleted file mode 100644 index 561b43d..0000000 --- "a/developer/cc\360\237\226\211/N16.lib.c" +++ /dev/null @@ -1,433 +0,0 @@ -/* - N16 - a processor native type - - For binary operations: a op b -> c - - See the document on the proper use of the Natural types. - - On the subject of multiple pointers indicating the same location in memory: - - When a routine has multiple results, and one or more of the result location - pointers point to the same storage, the routine will either return an error - status, or have defined behavior. - - When a routine has multiple operands, in any combination, those - pointers can point to the same location, and the routine will - function as advertised. - - When an operand functions as both an input and a result, perhaps due - to a result pointer pointing to the same place as an operand - pointer, the routine will function as advertised. (Internally the - routine might make a temporary copy of the operand to accomplish - this.) -*/ - -#define N16·DEBUG - -#ifndef FACE -#define N16·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef N16·FACE -#define N16·FACE - - #include - #include - #include - #include - - //---------------------------------------- - // Instance Data (Declaration Only) - - typedef uint16_t Extent; - typedef uint16_t Digit; - - typedef struct N16·T N16·T; - - extern N16·T *N16·zero; - extern N16·T *N16·one; - extern N16·T *N16·all_one_bit; - extern N16·T *N16·lsb; - extern N16·T *N16·msb; - - //---------------------------------------- - // Return/Error Status and handlers - - typedef enum{ - N16·Status·ok = 0 - ,N16·Status·overflow = 1 - ,N16·Status·accumulator1_overflow = 2 - ,N16·Status·carry = 3 - ,N16·Status·borrow = 4 - ,N16·Status·undefined_divide_by_zero = 5 - ,N16·Status·undefined_modulus_zero = 6 - ,N16·Status·gt_max_shift_count = 7 - ,N16·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value - ,N16·Status·one_word_product = 9 - ,N16·Status·two_word_product = 10 - } N16·Status; - - typedef enum{ - N16·Order_lt = -1 - ,N16·Order_eq = 0 - ,N16·Order_gt = 1 - } N16·Order; - - typedef N16·T *( *N16·Allocate_MemoryFault )(Extent); - - //---------------------------------------- - // Interface - - typedef struct{ - - N16·T *(*allocate_array_zero)(Extent, N16·Allocate_MemoryFault); - N16·T *(*allocate_array)(Extent, N16·Allocate_MemoryFault); - void (*deallocate)(N16·T*); - - void (*copy)(N16·T*, N16·T*); - void (*bit_and)(N16·T*, N16·T*, N16·T*); - void (*bit_or)(N16·T*, N16·T*, N16·T*); - void (*bit_complement)(N16·T*, N16·T*); - void (*bit_twos_complement)(N16·T*, N16·T*); - N16·Order (*compare)(N16·T*, N16·T*); - bool (*lt)(N16·T*, N16·T*); - bool (*gt)(N16·T*, N16·T*); - bool (*eq)(N16·T*, N16·T*); - bool (*eq_zero)(N16·T*); - N16·Status (*accumulate)(N16·T *accumulator1 ,N16·T *accumulator0 ,...); - N16·Status (*add)(N16·T*, N16·T*, N16·T*); - bool (*increment)(N16·T *a); - N16·Status (*subtract)(N16·T*, N16·T*, N16·T*); - N16·Status (*multiply)(N16·T*, N16·T*, N16·T*, N16·T*); - N16·Status (*divide)(N16·T*, N16·T*, N16·T*, N16·T*); - N16·Status (*modulus)(N16·T*, N16·T*, N16·T*); - N16·Status (*shift_left)(Extent, N16·T*, N16·T*, N16·T*); - N16·Status (*shift_right)(Extent, N16·T*, N16·T*, N16·T*); - N16·Status (*arithmetic_shift_right)(Extent, N16·T*, N16·T*); - - N16·T* (*access)(N16·T*, Extent); - void (*from_uint32)(N16·T *destination ,uint32_t value); - } N16·M; - - Local const N16·M N16·m; // initialized in the LOCAL section - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef N16·IMPLEMENTATION - - // this part goes into the library - #ifndef LOCAL - - #include - #include - - struct N16·T{ - Digit d0; - }; - - N16·T N16·constant[4] = { - {.d0 = 0}, - {.d0 = 1}, - {.d0 = ~(uint16_t)0}, - {.d0 = 1 << 15} - }; - - N16·T *N16·zero = &N16·constant[0]; - N16·T *N16·one = &N16·constant[1]; - N16·T *N16·all_one_bit = &N16·constant[2]; - N16·T *N16·msb = &N16·constant[3]; - N16·T *N16·lsb = &N16·constant[1]; - - // the allocate an array of N16 - N16·T *N16·allocate_array(Extent extent ,N16·Allocate_MemoryFault memory_fault){ - N16·T *instance = malloc((extent + 1) * sizeof(N16·T)); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - N16·T *N16·allocate_array_zero(Extent extent ,N16·Allocate_MemoryFault memory_fault){ - N16·T *instance = calloc(extent + 1, sizeof(N16·T)); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - void N16·deallocate(N16·T *unencumbered){ - free(unencumbered); - } - - - #endif - - // This part is included after the library user's code - #ifdef LOCAL - - // instance - - struct N16·T{ - Digit d0; - }; - - // temporary variables - Local N16·T N16·t[4]; - - // allocation - - extern N16·T *N16·allocate_array(Extent, N16·Allocate_MemoryFault); - extern N16·T *N16·allocate_array_zero(Extent, N16·Allocate_MemoryFault); - extern void N16·deallocate(N16·T *); - - // so the user can access numbers in an array allocation - Local N16·T* N16·access(N16·T *array ,Extent index){ - return &array[index]; - } - - Local void N16·from_uint32(N16·T *destination ,uint32_t value){ - if(destination == NULL) return; - destination->d0 = (uint16_t)(value & 0xFFFF); - } - - // copy, convenience copy - - Local void N16·copy(N16·T *destination ,N16·T *source){ - if(source == destination) return; - *destination = *source; - } - - Local void N16·set_to_zero(N16·T *instance){ - instance->d0 = 0; - } - - Local void N16·set_to_one(N16·T *instance){ - instance->d0 = 1; - } - - // bit operations - - Local void N16·bit_and(N16·T *result, N16·T *a, N16·T *b){ - result->d0 = a->d0 & b->d0; - } - - Local void N16·bit_or(N16·T *result, N16·T *a, N16·T *b){ - result->d0 = a->d0 | b->d0; - } - - Local void N16·bit_complement(N16·T *result, N16·T *a){ - result->d0 = ~a->d0; - } - - Local void N16·bit_twos_complement(N16·T *result ,N16·T *a){ - result->d0 = (uint16_t)(~a->d0 + 1); - } - - // test functions - - Local N16·Order N16·compare(N16·T *a, N16·T *b){ - if(a->d0 < b->d0) return N16·Order_lt; - if(a->d0 > b->d0) return N16·Order_gt; - return N16·Order_eq; - } - - Local bool N16·lt(N16·T *a ,N16·T *b){ - return a->d0 < b->d0; - } - - Local bool N16·gt(N16·T *a ,N16·T *b){ - return a->d0 > b->d0; - } - - Local bool N16·eq(N16·T *a ,N16·T *b){ - return a->d0 == b->d0; - } - - Local bool N16·eq_zero(N16·T *a){ - return a->d0 == 0; - } - - // arithmetic operations - - Local N16·Status N16·accumulate(N16·T *accumulator1 ,N16·T *accumulator0 ,...){ - - va_list args; - va_start(args ,accumulator0); - uint32_t sum = accumulator0->d0; - uint32_t carry = 0; - N16·T *current; - - while( (current = va_arg(args ,N16·T*)) ){ - sum += current->d0; - if(sum < current->d0){ - (carry)++; - if(carry == 0){ - va_end(args); - return N16·Status·accumulator1_overflow; - } - } - } - va_end(args); - - accumulator1->d0 = (uint16_t)carry; - return N16·Status·ok; - } - - Local N16·Status N16·add(N16·T *sum ,N16·T *a ,N16·T *b){ - uint32_t result = (uint32_t)a->d0 + (uint32_t)b->d0; - sum->d0 = (uint16_t)(result & 0xFFFF); - return (result >> 16) ? N16·Status·carry : N16·Status·ok; - } - - Local bool N16·increment(N16·T *a){ - a->d0++; - return (a->d0 == 0); - } - - Local N16·Status N16·subtract(N16·T *difference ,N16·T *a ,N16·T *b){ - uint32_t diff = (uint32_t)a->d0 - (uint32_t)b->d0; - difference->d0 = (uint16_t)(diff & 0xFFFF); - return (diff > a->d0) ? N16·Status·borrow : N16·Status·ok; - } - - Local N16·Status N16·multiply(N16·T *product1 ,N16·T *product0 ,N16·T *a ,N16·T *b){ - uint32_t product = (uint32_t)a->d0 * (uint32_t)b->d0; - product0->d0 = (uint16_t)(product & 0xFFFF); - product1->d0 = (uint16_t)((product >> 16) & 0xFFFF); - - if(product1->d0 == 0) return N16·Status·one_word_product; - return N16·Status·two_word_product; - } - - Local N16·Status N16·divide(N16·T *remainder ,N16·T *quotient ,N16·T *a ,N16·T *b){ - if(b->d0 == 0) return N16·Status·undefined_divide_by_zero; - - uint32_t dividend = a->d0; - uint32_t divisor = b->d0; - quotient->d0 = (uint16_t)(dividend / divisor); - remainder->d0 = (uint16_t)(dividend - (quotient->d0 * divisor)); - - return N16·Status·ok; - } - - Local N16·Status N16·modulus(N16·T *remainder ,N16·T *a ,N16·T *b){ - if(b->d0 == 0) return N16·Status·undefined_modulus_zero; - uint32_t dividend = a->d0; - uint32_t divisor = b->d0; - uint32_t q = dividend / divisor; - remainder->d0 = (uint16_t)(dividend - (q * divisor)); - return N16·Status·ok; - } - - // bit motion - - typedef uint16_t (*ShiftOp)(uint16_t, uint16_t); - - Local uint16_t shift_left_op(uint16_t value, uint16_t amount){ - return value << amount; - } - - Local uint16_t shift_right_op(uint16_t value, uint16_t amount){ - return (uint16_t)(value >> amount); - } - - Local N16·Status N16·shift - ( - uint16_t shift_count - ,N16·T *spill - ,N16·T *operand - ,N16·T *fill - ,ShiftOp shift_op - ,ShiftOp complement_shift_op - ){ - - if(operand == NULL && spill == NULL) return N16·Status·ok; - - if(operand == NULL){ - operand = &N16·t[0]; - N16·copy(operand, N16·zero); - } - - if(shift_count > 15) return N16·Status·gt_max_shift_count; - - N16·T *given_operand = &N16·t[1]; - N16·copy(given_operand, operand); - - operand->d0 = shift_op(given_operand->d0, shift_count); - if(fill != NULL){ - fill->d0 = complement_shift_op(fill->d0, (16 - shift_count)); - N16·bit_or(operand, operand, fill); - } - if(spill != NULL){ - spill->d0 = shift_op(spill->d0, shift_count); - spill->d0 += complement_shift_op(given_operand->d0, (16 - shift_count)); - } - - return N16·Status·ok; - } - - Local N16·Status - N16·shift_left(uint16_t shift_count, N16·T *spill, N16·T *operand, N16·T *fill){ - return N16·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); - } - - Local N16·Status - N16·shift_right(uint16_t shift_count, N16·T *spill, N16·T *operand, N16·T *fill){ - return N16·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); - } - - Local N16·Status - N16·arithmetic_shift_right(uint16_t shift_count, N16·T *operand, N16·T *spill){ - - if(shift_count > 15) return N16·Status·gt_max_shift_count; - - if(operand == NULL){ - operand = &N16·t[0]; - N16·copy(operand, N16·zero); - } - - N16·T *fill = (operand->d0 & 0x8000) ? N16·all_one_bit : N16·zero; - return N16·shift_right(shift_count, spill, operand, fill); - } - - Local const N16·M N16·m = { - - .allocate_array = N16·allocate_array - ,.allocate_array_zero = N16·allocate_array_zero - ,.deallocate = N16·deallocate - - ,.copy = N16·copy - ,.bit_and = N16·bit_and - ,.bit_or = N16·bit_or - ,.bit_complement = N16·bit_complement - ,.bit_twos_complement = N16·bit_twos_complement - ,.compare = N16·compare - ,.lt = N16·lt - ,.gt = N16·gt - ,.eq = N16·eq - ,.eq_zero = N16·eq_zero - ,.accumulate = N16·accumulate - ,.add = N16·add - ,.increment = N16·increment - ,.subtract = N16·subtract - ,.multiply = N16·multiply - ,.divide = N16·divide - ,.modulus = N16·modulus - ,.shift_left = N16·shift_left - ,.shift_right = N16·shift_right - ,.arithmetic_shift_right = N16·arithmetic_shift_right - - ,.access = N16·access - ,.from_uint32 = N16·from_uint32 - }; - - #endif - -#endif diff --git "a/developer/cc\360\237\226\211/N32.lib.c" "b/developer/cc\360\237\226\211/N32.lib.c" deleted file mode 100644 index ccb3411..0000000 --- "a/developer/cc\360\237\226\211/N32.lib.c" +++ /dev/null @@ -1,457 +0,0 @@ -/* - N32 - a processor native type - - For binary operations: a op b -> c - - See the document on the proper use of the Natural types. - - On the subject of multiple pointers indicating the same location in memory: - - When a routine has multiple results, and one or more of the result location - pointers point to the same storage, the routine will either return an error - status, or have defined behavior. - - When a routine has multiple operands, in any combination, those - pointers can point to the same location, and the routine will - function as advertised. - - When an operand functions as both an input and a result, perhaps due - to a result pointer pointing to the same place as an operand - pointer, the routine will function as advertised. (Internally the - routine might make a temporary copy of the operand to accomplish - this.) - -*/ - -#define N32·DEBUG - -#ifndef FACE -#define N32·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef N32·FACE -#define N32·FACE - - #include - #include - #include - #include - - //---------------------------------------- - // Instance Data (Declaration Only) - - typedef uint32_t Extent; - typedef uint32_t Digit; - - typedef struct N32·T N32·T; - - extern N32·T *N32·zero; - extern N32·T *N32·one; - extern N32·T *N32·all_one_bit; - extern N32·T *N32·lsb; - extern N32·T *N32·msb; - - //---------------------------------------- - // Return/Error Status and handlers - - typedef enum{ - N32·Status·ok = 0 - ,N32·Status·overflow = 1 - ,N32·Status·accumulator1_overflow = 2 - ,N32·Status·carry = 3 - ,N32·Status·borrow = 4 - ,N32·Status·undefined_divide_by_zero = 5 - ,N32·Status·undefined_modulus_zero = 6 - ,N32·Status·gt_max_shift_count = 7 - ,N32·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value - ,N32·Status·one_word_product = 9 - ,N32·Status·two_word_product = 10 - } N32·Status; - - typedef enum{ - N32·Order_lt = -1 - ,N32·Order_eq = 0 - ,N32·Order_gt = 1 - } N32·Order; - - typedef N32·T *( *N32·Allocate_MemoryFault )(Extent); - - //---------------------------------------- - // Interface - - typedef struct{ - - N32·T *(*allocate_array_zero)(Extent, N32·Allocate_MemoryFault); - N32·T *(*allocate_array)(Extent, N32·Allocate_MemoryFault); - void (*deallocate)(N32·T*); - - void (*copy)(N32·T*, N32·T*); - void (*bit_and)(N32·T*, N32·T*, N32·T*); - void (*bit_or)(N32·T*, N32·T*, N32·T*); - void (*bit_complement)(N32·T*, N32·T*); - void (*bit_twos_complement)(N32·T*, N32·T*); - N32·Order (*compare)(N32·T*, N32·T*); - bool (*lt)(N32·T*, N32·T*); - bool (*gt)(N32·T*, N32·T*); - bool (*eq)(N32·T*, N32·T*); - bool (*eq_zero)(N32·T*); - N32·Status (*accumulate)(N32·T *accumulator1 ,N32·T *accumulator0 ,...); - N32·Status (*add)(N32·T*, N32·T*, N32·T*); - bool (*increment)(N32·T *a); - N32·Status (*subtract)(N32·T*, N32·T*, N32·T*); - N32·Status (*multiply)(N32·T*, N32·T*, N32·T*, N32·T*); - N32·Status (*divide)(N32·T*, N32·T*, N32·T*, N32·T*); - N32·Status (*modulus)(N32·T*, N32·T*, N32·T*); - N32·Status (*shift_left)(Extent, N32·T*, N32·T*, N32·T*); - N32·Status (*shift_right)(Extent, N32·T*, N32·T*, N32·T*); - N32·Status (*arithmetic_shift_right)(Extent, N32·T*, N32·T*); - - N32·T* (*access)(N32·T*, Extent); - void (*from_uint32)(N32·T *destination ,uint32_t value); - } N32·M; - - Local const N32·M N32·m; // initialized in the LOCAL section - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef N32·IMPLEMENTATION - - // this part goes into the library - #ifndef LOCAL - - #include - #include - - struct N32·T{ - Digit d0; - }; - - N32·T N32·constant[4] = { - {.d0 = 0}, - {.d0 = 1}, - {.d0 = ~(uint32_t)0}, - {.d0 = 1 << 31} - }; - - N32·T *N32·zero = &N32·constant[0]; - N32·T *N32·one = &N32·constant[1]; - N32·T *N32·all_one_bit = &N32·constant[2]; - N32·T *N32·msb = &N32·constant[3]; - N32·T *N32·lsb = &N32·constant[1]; - - // the allocate an array of N32 - N32·T *N32·allocate_array(Extent extent ,N32·Allocate_MemoryFault memory_fault){ - N32·T *instance = malloc((extent + 1) * sizeof(N32·T) ); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - N32·T *N32·allocate_array_zero(Extent extent ,N32·Allocate_MemoryFault memory_fault){ - N32·T *instance = calloc( extent + 1 ,sizeof(N32·T) ); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - void N32·deallocate(N32·T *unencumbered){ - free(unencumbered); - } - - #endif - - // This part is included after the library user's code - #ifdef LOCAL - - // instance - - struct N32·T{ - Digit d0; - }; - - // temporary variables - // making these LOCAL rather than reserving one block in the library is thread safe - // allocating a block once is more efficient - // library code writes these, they are not on the interface - - Local N32·T N32·t[4]; - - - // allocation - - extern N32·T *N32·allocate_array(Extent, N32·Allocate_MemoryFault); - extern N32·T *N32·allocate_array_zero(Extent, N32·Allocate_MemoryFault); - extern void N32·deallocate(N32·T *); - - // so the user can access numbers in an array allocation - Local N32·T* N32·access(N32·T *array ,Extent index){ - return &array[index]; - } - - Local void N32·from_uint32(N32·T *destination ,uint32_t value){ - if(destination == NULL) return; - destination->d0 = value; - } - - // copy, convenience copy - - Local void N32·copy(N32·T *destination ,N32·T *source){ - if(source == destination) return; // that was easy! - *destination = *source; - } - - Local void N32·set_to_zero(N32·T *instance){ - instance->d0 = 0; - } - - Local void N32·set_to_one(N32·T *instance){ - instance->d0 = 1; - } - - // bit operations - - Local void N32·bit_and(N32·T *result, N32·T *a, N32·T *b){ - result->d0 = a->d0 & b->d0; - } - - // result can be one of the operands - Local void N32·bit_or(N32·T *result, N32·T *a, N32·T *b){ - result->d0 = a->d0 | b->d0; - } - - // result can the same as the operand - Local void N32·bit_complement(N32·T *result, N32·T *a){ - result->d0 = ~a->d0; - } - - // result can the same as the operand - Local void N32·bit_twos_complement(N32·T *result ,N32·T *a){ - result->d0 = ~a->d0 + 1; - } - - // test functions - - Local N32·Order N32·compare(N32·T *a, N32·T *b){ - if(a->d0 < b->d0) return N32·Order_lt; - if(a->d0 > b->d0) return N32·Order_gt; - return N32·Order_eq; - } - - Local bool N32·lt(N32·T *a ,N32·T *b){ - return a->d0 < b->d0; - } - - Local bool N32·gt(N32·T *a ,N32·T *b){ - return a->d0 > b->d0; - } - - Local bool N32·eq(N32·T *a ,N32·T *b){ - return a->d0 == b->d0; - } - - Local bool N32·eq_zero(N32·T *a){ - return a->d0 == 0; - } - - - // arithmetic operations - - // For a large number of summands for the lower precision Natural implementations, for accumulate/add/sub, the 'overflow' operand could overflow and thus this routine will halt and return N32·Status·accumulator1_overflow - // - // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value. - Local N32·Status N32·accumulate(N32·T *accumulator1 ,N32·T *accumulator0 ,...){ - - va_list args; - va_start(args ,accumulator0); - uint32_t sum = accumulator0->d0; - uint32_t carry = 0; - N32·T *current; - - while( (current = va_arg(args ,N32·T *)) ){ - sum += current->d0; - if(sum < current->d0){ // Accumulator1 into carry - (carry)++; - if(carry == 0){ - va_end(args); - return N32·Status·accumulator1_overflow; - } - } - } - va_end(args); - - // wipes out prior value of accumulator1 - accumulator1->d0 = carry; - - return N32·Status·ok; - } - - Local N32·Status N32·add(N32·T *sum ,N32·T *a ,N32·T *b){ - uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0; - sum->d0 = (uint32_t)result; - return (result >> 32) ? N32·Status·carry : N32·Status·ok; - } - - Local bool N32·increment(N32·T *a){ - a->d0++; - return a->d0 == 0; - } - - Local N32·Status N32·subtract(N32·T *difference ,N32·T *a ,N32·T *b){ - uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0; - difference->d0 = (uint32_t)diff; - return (diff > a->d0) ? N32·Status·borrow : N32·Status·ok; - } - - - Local N32·Status N32·multiply(N32·T *product1 ,N32·T *product0 ,N32·T *a ,N32·T *b){ - uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0; - product0->d0 = (uint32_t)product; - product1->d0 = (uint32_t)(product >> 32); - - if(product1->d0 == 0) return N32·Status·one_word_product; - return N32·Status·two_word_product; - } - - Local N32·Status N32·divide(N32·T *remainder ,N32·T *quotient ,N32·T *a ,N32·T *b){ - if(b->d0 == 0) return N32·Status·undefined_divide_by_zero; - - quotient->d0 = a->d0 / b->d0; - remainder->d0 = a->d0 - (quotient->d0 * b->d0); - - return N32·Status·ok; - } - - Local N32·Status N32·modulus(N32·T *remainder ,N32·T *a ,N32·T *b){ - if(b->d0 == 0) return N32·Status·undefined_modulus_zero; - uint32_t quotient = a->d0 / b->d0; - remainder->d0 = a->d0 - (quotient * b->d0); - return N32·Status·ok; - } - - // bit motion - - typedef uint32_t (*ShiftOp)(uint32_t, uint32_t); - - Local uint32_t shift_left_op(uint32_t value, uint32_t amount){ - return value << amount; - } - - Local uint32_t shift_right_op(uint32_t value, uint32_t amount){ - return value >> amount; - } - - // modifies all three of its operands - // in the case of duplicate operands this is the order: first modifies operand, then fill, then spill, - Local N32·Status N32·shift - ( - uint32_t shift_count - ,N32·T *spill - ,N32·T *operand - ,N32·T *fill - ,ShiftOp shift_op - ,ShiftOp complement_shift_op - ){ - - // If no result is needed, return immediately. - if(operand == NULL && spill == NULL) return N32·Status·ok; - - // Treat NULL operand as zero. - if(operand == NULL){ - operand = &N32·t[0]; - N32·copy(operand, N32·zero); - } - - // Shifting more than one word breaks our fill/spill model. - if(shift_count > 31) return N32·Status·gt_max_shift_count; - - // The given operand is still required after it is modified, so we copy it. - N32·T *given_operand = &N32·t[1]; - N32·copy(given_operand, operand); - - // Perform the shift - operand->d0 = shift_op(given_operand->d0, shift_count); - if(fill != NULL){ - fill->d0 = complement_shift_op(fill->d0, (32 - shift_count)); - N32·bit_or(operand, operand, fill); - } - if(spill != NULL){ - spill->d0 = shift_op(spill->d0, shift_count); - spill->d0 += complement_shift_op(given_operand->d0, (32 - shift_count)); - } - - return N32·Status·ok; - } - - // Define concrete shift functions using valid C function pointers - Local N32·Status - N32·shift_left(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ - return N32·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); - } - - Local N32·Status - N32·shift_right(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ - return N32·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); - } - - Local N32·Status - N32·arithmetic_shift_right(uint32_t shift_count, N32·T *operand, N32·T *spill){ - - // Guard against excessive shift counts - if(shift_count > 31) return N32·Status·gt_max_shift_count; - - // A NULL operand is treated as zero - if(operand == NULL){ - operand = &N32·t[0]; - N32·copy(operand, N32·zero); - } - - // Pick the fill value based on the sign bit - N32·T *fill = (operand->d0 & 0x80000000) ? N32·all_one_bit : N32·zero; - - // Call shift_right with the appropriate fill - return N32·shift_right(shift_count, spill, operand, fill); - } - - Local const N32·M N32·m = { - - .allocate_array = N32·allocate_array - ,.allocate_array_zero = N32·allocate_array_zero - ,.deallocate = N32·deallocate - - ,.copy = N32·copy - ,.bit_and = N32·bit_and - ,.bit_or = N32·bit_or - ,.bit_complement = N32·bit_complement - ,.bit_twos_complement = N32·bit_twos_complement - ,.compare = N32·compare - ,.lt = N32·lt - ,.gt = N32·gt - ,.eq = N32·eq - ,.eq_zero = N32·eq_zero - ,.accumulate = N32·accumulate - ,.add = N32·add - ,.increment = N32·increment - ,.subtract = N32·subtract - ,.multiply = N32·multiply - ,.divide = N32·divide - ,.modulus = N32·modulus - ,.shift_left = N32·shift_left - ,.shift_right = N32·shift_right - ,.arithmetic_shift_right = N32·arithmetic_shift_right - - ,.access = N32·access - ,.from_uint32 = N32·from_uint32 - }; - - #endif - -#endif diff --git "a/developer/cc\360\237\226\211/N64.lib.c" "b/developer/cc\360\237\226\211/N64.lib.c" deleted file mode 100644 index 6058e9b..0000000 --- "a/developer/cc\360\237\226\211/N64.lib.c" +++ /dev/null @@ -1,477 +0,0 @@ -/* - N64 - a 64-bit native type - - For binary operations: a op b -> c - - Similar to N32, but now each Digit is 64 bits. Where a 128-bit - intermediate is necessary (e.g. multiplication), we handle it - manually using two 64-bit parts. - - On the subject of multiple pointers indicating the same location in memory: - - When a routine has multiple results, and one or more of the result location - pointers point to the same storage, the routine will either return an error - status, or have defined behavior. - - When a routine has multiple operands, in any combination, those - pointers can point to the same location, and the routine will - function as advertised. - - When an operand functions as both an input and a result, perhaps due - to a result pointer pointing to the same place as an operand - pointer, the routine will function as advertised. (Internally the - routine might make a temporary copy of the operand to accomplish - this.) -*/ - -#define N64·DEBUG - -#ifndef FACE -#define N64·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef N64·FACE -#define N64·FACE - - #include - #include - #include - #include - - //---------------------------------------- - // Instance Data (Declaration Only) - - typedef uint64_t Extent; - typedef uint64_t Digit; - - typedef struct N64·T N64·T; - - extern N64·T *N64·zero; - extern N64·T *N64·one; - extern N64·T *N64·all_one_bit; - extern N64·T *N64·lsb; - extern N64·T *N64·msb; - - //---------------------------------------- - // Return/Error Status and handlers - - typedef enum { - N64·Status·ok = 0 - ,N64·Status·overflow = 1 - ,N64·Status·accumulator1_overflow = 2 - ,N64·Status·carry = 3 - ,N64·Status·borrow = 4 - ,N64·Status·undefined_divide_by_zero = 5 - ,N64·Status·undefined_modulus_zero = 6 - ,N64·Status·gt_max_shift_count = 7 - ,N64·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value - ,N64·Status·one_word_product = 9 - ,N64·Status·two_word_product = 10 - } N64·Status; - - typedef enum { - N64·Order_lt = -1 - ,N64·Order_eq = 0 - ,N64·Order_gt = 1 - } N64·Order; - - typedef N64·T *(*N64·Allocate_MemoryFault)(Extent); - - //---------------------------------------- - // Interface - - typedef struct { - - N64·T *(*allocate_array_zero)(Extent, N64·Allocate_MemoryFault); - N64·T *(*allocate_array)(Extent, N64·Allocate_MemoryFault); - void (*deallocate)(N64·T*); - - void (*copy)(N64·T*, N64·T*); - void (*bit_and)(N64·T*, N64·T*, N64·T*); - void (*bit_or)(N64·T*, N64·T*, N64·T*); - void (*bit_complement)(N64·T*, N64·T*); - void (*bit_twos_complement)(N64·T*, N64·T*); - N64·Order (*compare)(N64·T*, N64·T*); - bool (*lt)(N64·T*, N64·T*); - bool (*gt)(N64·T*, N64·T*); - bool (*eq)(N64·T*, N64·T*); - bool (*eq_zero)(N64·T*); - N64·Status (*accumulate)(N64·T *accumulator1, N64·T *accumulator0, ...); - N64·Status (*add)(N64·T*, N64·T*, N64·T*); - bool (*increment)(N64·T *a); - N64·Status (*subtract)(N64·T*, N64·T*, N64·T*); - N64·Status (*multiply)(N64·T*, N64·T*, N64·T*, N64·T*); - N64·Status (*divide)(N64·T*, N64·T*, N64·T*, N64·T*); - N64·Status (*modulus)(N64·T*, N64·T*, N64·T*); - N64·Status (*shift_left)(Extent, N64·T*, N64·T*, N64·T*); - N64·Status (*shift_right)(Extent, N64·T*, N64·T*, N64·T*); - N64·Status (*arithmetic_shift_right)(Extent, N64·T*, N64·T*); - - N64·T* (*access)(N64·T*, Extent); - void (*from_uint64)(N64·T *destination, uint64_t value); - - } N64·M; - - Local const N64·M N64·m; // initialized in the LOCAL section - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef N64·IMPLEMENTATION - - // this part goes into the library - #ifndef LOCAL - - #include - #include - - struct N64·T { - Digit d0; - }; - - // For constants, we store them in an array for convenience - // 0, 1, all bits set (~0ULL), and MSB set (1ULL<<63) - N64·T N64·constant[4] = { - {.d0 = 0ULL}, - {.d0 = 1ULL}, - {.d0 = ~(uint64_t)0ULL}, - {.d0 = 1ULL << 63} - }; - - N64·T *N64·zero = &N64·constant[0]; - N64·T *N64·one = &N64·constant[1]; - N64·T *N64·all_one_bit = &N64·constant[2]; - N64·T *N64·msb = &N64·constant[3]; - N64·T *N64·lsb = &N64·constant[1]; - - // allocate an array of N64 - N64·T *N64·allocate_array(Extent extent, N64·Allocate_MemoryFault memory_fault){ - N64·T *instance = malloc( (extent + 1) * sizeof(N64·T) ); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - N64·T *N64·allocate_array_zero(Extent extent, N64·Allocate_MemoryFault memory_fault){ - N64·T *instance = calloc(extent + 1, sizeof(N64·T)); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - void N64·deallocate(N64·T *unencumbered){ - free(unencumbered); - } - - #endif - - // This part is included after the library user's code - #ifdef LOCAL - - // instance - - struct N64·T { - Digit d0; - }; - - // local temporary variables - Local N64·T N64·t[4]; - - // allocation references - extern N64·T *N64·allocate_array(Extent, N64·Allocate_MemoryFault); - extern N64·T *N64·allocate_array_zero(Extent, N64·Allocate_MemoryFault); - extern void N64·deallocate(N64·T *); - - // Access array - Local N64·T* N64·access(N64·T *array, Extent index){ - return &array[index]; - } - - Local void N64·from_uint64(N64·T *destination, uint64_t value){ - if(destination == NULL) return; - destination->d0 = value; - } - - // copy - Local void N64·copy(N64·T *destination, N64·T *source){ - if(source == destination) return; - *destination = *source; - } - - // bit operations - - Local void N64·bit_and(N64·T *result, N64·T *a, N64·T *b){ - result->d0 = a->d0 & b->d0; - } - - Local void N64·bit_or(N64·T *result, N64·T *a, N64·T *b){ - result->d0 = a->d0 | b->d0; - } - - Local void N64·bit_complement(N64·T *result, N64·T *a){ - result->d0 = ~a->d0; - } - - Local void N64·bit_twos_complement(N64·T *result, N64·T *a){ - result->d0 = ~a->d0 + 1ULL; - } - - // compare & test functions - - Local N64·Order N64·compare(N64·T *a, N64·T *b){ - if(a->d0 < b->d0) return N64·Order_lt; - if(a->d0 > b->d0) return N64·Order_gt; - return N64·Order_eq; - } - - Local bool N64·lt(N64·T *a, N64·T *b){ - return (a->d0 < b->d0); - } - - Local bool N64·gt(N64·T *a, N64·T *b){ - return (a->d0 > b->d0); - } - - Local bool N64·eq(N64·T *a, N64·T *b){ - return (a->d0 == b->d0); - } - - Local bool N64·eq_zero(N64·T *a){ - return (a->d0 == 0ULL); - } - - // arithmetic operations - - // accumulate - Local N64·Status N64·accumulate(N64·T *accumulator1, N64·T *accumulator0, ...){ - va_list args; - va_start(args, accumulator0); - - uint64_t sum = accumulator0->d0; - uint64_t carry = 0; - N64·T *current; - - while( (current = va_arg(args, N64·T*)) ){ - uint64_t prior = sum; - sum += current->d0; - if(sum < prior){ // indicates carry - carry++; - // if carry overflowed a 64-bit, that's an accumulator1 overflow - if(carry == 0ULL){ - va_end(args); - return N64·Status·accumulator1_overflow; - } - } - } - va_end(args); - - accumulator1->d0 = carry; - return N64·Status·ok; - } - - // add - Local N64·Status N64·add(N64·T *sum, N64·T *a, N64·T *b){ - __uint128_t result = ( __uint128_t )a->d0 + ( __uint128_t )b->d0; - // But to avoid using a GNU extension, we can do the simpler approach: - // Actually let's do it directly with 64-bit since we only need to detect carry out of 64 bits: - uint64_t temp = a->d0 + b->d0; - sum->d0 = temp; - if(temp < a->d0) return N64·Status·carry; // means we overflowed - return N64·Status·ok; - } - - Local bool N64·increment(N64·T *a){ - uint64_t old = a->d0; - a->d0++; - // if it wrapped around to 0, then it was 0xFFFFFFFFFFFFFFFF - return (a->d0 < old); - } - - // subtract - Local N64·Status N64·subtract(N64·T *difference, N64·T *a, N64·T *b){ - uint64_t tmpA = a->d0; - uint64_t tmpB = b->d0; - uint64_t diff = tmpA - tmpB; - difference->d0 = diff; - if(diff > tmpA) return N64·Status·borrow; // indicates we borrowed - return N64·Status·ok; - } - - // multiply - // We'll do a 64x64->128 using two 64-bit accumulators - Local N64·Status N64·multiply(N64·T *product1, N64·T *product0, N64·T *a, N64·T *b){ - uint64_t A = a->d0; - uint64_t B = b->d0; - - // Break each operand into high & low 32 bits - uint64_t a_lo = (uint32_t)(A & 0xffffffffULL); - uint64_t a_hi = A >> 32; - uint64_t b_lo = (uint32_t)(B & 0xffffffffULL); - uint64_t b_hi = B >> 32; - - // partial products - uint64_t low = a_lo * b_lo; // 64-bit - uint64_t cross = (a_lo * b_hi) + (a_hi * b_lo); // potentially up to 2 * 32 bits => 64 bits - uint64_t high = a_hi * b_hi; // up to 64 bits - - // incorporate cross into low, high - // cross is effectively the middle bits, so shift cross by 32 and add to low - uint64_t cross_low = (cross & 0xffffffffULL) << 32; // lower part - uint64_t cross_high = cross >> 32; // upper part - - // add cross_low to low, capture carry - uint64_t old_low = low; - low += cross_low; - if(low < old_low) cross_high++; - - // final high - high += cross_high; - - // store results - product0->d0 = low; - product1->d0 = high; - - if(high == 0ULL) return N64·Status·one_word_product; - return N64·Status·two_word_product; - } - - // divide - Local N64·Status N64·divide(N64·T *remainder, N64·T *quotient, N64·T *a, N64·T *b){ - // we do not handle a > 64-bit, just the single 64-bit - if(b->d0 == 0ULL) return N64·Status·undefined_divide_by_zero; - - uint64_t divd = a->d0; // dividend - uint64_t divs = b->d0; // divisor - - quotient->d0 = divd / divs; - remainder->d0 = divd - (quotient->d0 * divs); - - return N64·Status·ok; - } - - // modulus - Local N64·Status N64·modulus(N64·T *remainder, N64·T *a, N64·T *b){ - if(b->d0 == 0ULL) return N64·Status·undefined_modulus_zero; - - uint64_t divd = a->d0; - uint64_t divs = b->d0; - uint64_t q = divd / divs; - remainder->d0 = divd - (q * divs); - - return N64·Status·ok; - } - - // bit motion - - typedef uint64_t (*ShiftOp)(uint64_t, uint64_t); - - Local uint64_t shift_left_op(uint64_t value, uint64_t amount){ - return (value << amount); - } - - Local uint64_t shift_right_op(uint64_t value, uint64_t amount){ - return (value >> amount); - } - - // modifies all three of its operands - // in the case of duplicate operands this is the order: first modifies operand, then fill, then spill - Local N64·Status N64·shift - ( - uint64_t shift_count, - N64·T *spill, - N64·T *operand, - N64·T *fill, - ShiftOp shift_op, - ShiftOp complement_shift_op - ){ - if(operand == NULL && spill == NULL) return N64·Status·ok; - - // Treat NULL operand as zero - if(operand == NULL){ - operand = &N64·t[0]; - N64·copy(operand, N64·zero); - } - - // Shifting more than 63 bits breaks fill/spill logic - if(shift_count > 63ULL) return N64·Status·gt_max_shift_count; - - N64·T *given_operand = &N64·t[1]; - N64·copy(given_operand, operand); - - // Perform the shift - operand->d0 = shift_op(given_operand->d0, shift_count); - if(fill != NULL){ - fill->d0 = complement_shift_op(fill->d0, (64ULL - shift_count)); - N64·bit_or(operand, operand, fill); - } - if(spill != NULL){ - spill->d0 = shift_op(spill->d0, shift_count); - spill->d0 += complement_shift_op(given_operand->d0, (64ULL - shift_count)); - } - - return N64·Status·ok; - } - - Local N64·Status N64·shift_left(uint64_t shift_count, N64·T *spill, N64·T *operand, N64·T *fill){ - return N64·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); - } - - Local N64·Status N64·shift_right(uint64_t shift_count, N64·T *spill, N64·T *operand, N64·T *fill){ - return N64·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); - } - - Local N64·Status N64·arithmetic_shift_right(uint64_t shift_count, N64·T *operand, N64·T *spill){ - if(shift_count > 63ULL) return N64·Status·gt_max_shift_count; - - // A NULL operand is treated as zero - if(operand == NULL){ - operand = &N64·t[0]; - N64·copy(operand, N64·zero); - } - - // sign bit check - N64·T *fill = (operand->d0 & (1ULL << 63)) ? N64·all_one_bit : N64·zero; - return N64·shift_right(shift_count, spill, operand, fill); - } - - Local const N64·M N64·m = { - .allocate_array = N64·allocate_array - ,.allocate_array_zero = N64·allocate_array_zero - ,.deallocate = N64·deallocate - - ,.copy = N64·copy - ,.bit_and = N64·bit_and - ,.bit_or = N64·bit_or - ,.bit_complement = N64·bit_complement - ,.bit_twos_complement = N64·bit_twos_complement - ,.compare = N64·compare - ,.lt = N64·lt - ,.gt = N64·gt - ,.eq = N64·eq - ,.eq_zero = N64·eq_zero - ,.accumulate = N64·accumulate - ,.add = N64·add - ,.increment = N64·increment - ,.subtract = N64·subtract - ,.multiply = N64·multiply - ,.divide = N64·divide - ,.modulus = N64·modulus - ,.shift_left = N64·shift_left - ,.shift_right = N64·shift_right - ,.arithmetic_shift_right = N64·arithmetic_shift_right - - ,.access = N64·access - ,.from_uint64 = N64·from_uint64 - }; - - #endif - -#endif diff --git "a/developer/cc\360\237\226\211/N8.lib.c" "b/developer/cc\360\237\226\211/N8.lib.c" deleted file mode 100644 index df6e01c..0000000 --- "a/developer/cc\360\237\226\211/N8.lib.c" +++ /dev/null @@ -1,433 +0,0 @@ -/* - N8 - PN = refers to the use of processor native accumulator - - For binary operations: a op b -> c - - See the document on the proper use of the Natural types. - - On the subject of multiple pointers indicating the same location in memory: - - When a routine has multiple results, and one or more of the result location - pointers point to the same storage, the routine will either return an error - status, or have defined behavior. - - When a routine has multiple operands, in any combination, those - pointers can point to the same location, and the routine will - function as advertised. - - When an operand functions as both an input and a result, perhaps due - to a result pointer pointing to the same place as an operand - pointer, the routine will function as advertised. (Internally the - routine might make a temporary copy of the operand to accomplish - this.) -*/ - -#define N8·DEBUG - -#ifndef FACE -#define N8·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef N8·FACE -#define N8·FACE - - #include - #include - #include - #include - - //---------------------------------------- - // Instance Data (Declaration Only) - - typedef uint8_t Extent; - typedef uint8_t Digit; - - typedef struct N8·T N8·T; - - extern N8·T *N8·zero; - extern N8·T *N8·one; - extern N8·T *N8·all_one_bit; - extern N8·T *N8·lsb; - extern N8·T *N8·msb; - - //---------------------------------------- - // Return/Error Status and handlers - - typedef enum{ - N8·Status·ok = 0 - ,N8·Status·overflow = 1 - ,N8·Status·accumulator1_overflow = 2 - ,N8·Status·carry = 3 - ,N8·Status·borrow = 4 - ,N8·Status·undefined_divide_by_zero = 5 - ,N8·Status·undefined_modulus_zero = 6 - ,N8·Status·gt_max_shift_count = 7 - ,N8·Status·spill_eq_operand = 8 - ,N8·Status·one_word_product = 9 - ,N8·Status·two_word_product = 10 - } N8·Status; - - typedef enum{ - N8·Order_lt = -1 - ,N8·Order_eq = 0 - ,N8·Order_gt = 1 - } N8·Order; - - typedef N8·T *( *N8·Allocate_MemoryFault )(Extent); - - //---------------------------------------- - // Interface - - typedef struct{ - - N8·T *(*allocate_array_zero)(Extent, N8·Allocate_MemoryFault); - N8·T *(*allocate_array)(Extent, N8·Allocate_MemoryFault); - void (*deallocate)(N8·T*); - - void (*copy)(N8·T*, N8·T*); - void (*bit_and)(N8·T*, N8·T*, N8·T*); - void (*bit_or)(N8·T*, N8·T*, N8·T*); - void (*bit_complement)(N8·T*, N8·T*); - void (*bit_twos_complement)(N8·T*, N8·T*); - N8·Order (*compare)(N8·T*, N8·T*); - bool (*lt)(N8·T*, N8·T*); - bool (*gt)(N8·T*, N8·T*); - bool (*eq)(N8·T*, N8·T*); - bool (*eq_zero)(N8·T*); - N8·Status (*accumulate)(N8·T *accumulator1 ,N8·T *accumulator0 ,...); - N8·Status (*add)(N8·T*, N8·T*, N8·T*); - bool (*increment)(N8·T *a); - N8·Status (*subtract)(N8·T*, N8·T*, N8·T*); - N8·Status (*multiply)(N8·T*, N8·T*, N8·T*, N8·T*); - N8·Status (*divide)(N8·T*, N8·T*, N8·T*, N8·T*); - N8·Status (*modulus)(N8·T*, N8·T*, N8·T*); - N8·Status (*shift_left)(Extent, N8·T*, N8·T*, N8·T*); - N8·Status (*shift_right)(Extent, N8·T*, N8·T*, N8·T*); - N8·Status (*arithmetic_shift_right)(Extent, N8·T*, N8·T*); - - N8·T* (*access)(N8·T*, Extent); - void (*from_uint32)(N8·T *destination ,uint32_t value); - } N8·M; - - Local const N8·M N8·m; // initialized in the LOCAL section - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef N8·IMPLEMENTATION - - // this part goes into the library - #ifndef LOCAL - - #include - #include - - struct N8·T{ - Digit d0; - }; - - N8·T N8·constant[4] = { - {.d0 = 0}, - {.d0 = 1}, - {.d0 = ~(uint8_t)0}, - {.d0 = 1 << 7} - }; - - N8·T *N8·zero = &N8·constant[0]; - N8·T *N8·one = &N8·constant[1]; - N8·T *N8·all_one_bit = &N8·constant[2]; - N8·T *N8·msb = &N8·constant[3]; - N8·T *N8·lsb = &N8·constant[1]; - - // the allocate an array of N8 - N8·T *N8·allocate_array(Extent extent ,N8·Allocate_MemoryFault memory_fault){ - N8·T *instance = malloc((extent + 1) * sizeof(N8·T)); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - N8·T *N8·allocate_array_zero(Extent extent ,N8·Allocate_MemoryFault memory_fault){ - N8·T *instance = calloc(extent + 1, sizeof(N8·T)); - if(!instance){ - return memory_fault ? memory_fault(extent) : NULL; - } - return instance; - } - - void N8·deallocate(N8·T *unencumbered){ - free(unencumbered); - } - - - #endif - - // This part is included after the library user's code - #ifdef LOCAL - - // instance - - struct N8·T{ - Digit d0; - }; - - // temporary variables - Local N8·T N8·t[4]; - - // allocation - - extern N8·T *N8·allocate_array(Extent, N8·Allocate_MemoryFault); - extern N8·T *N8·allocate_array_zero(Extent, N8·Allocate_MemoryFault); - extern void N8·deallocate(N8·T *); - - // so the user can access numbers in an array allocation - Local N8·T* N8·access(N8·T *array ,Extent index){ - return &array[index]; - } - - Local void N8·from_uint32(N8·T *destination ,uint32_t value){ - if(destination == NULL) return; - destination->d0 = (uint8_t)(value & 0xFF); - } - - // copy, convenience copy - - Local void N8·copy(N8·T *destination ,N8·T *source){ - if(source == destination) return; - *destination = *source; - } - - Local void N8·set_to_zero(N8·T *instance){ - instance->d0 = 0; - } - - Local void N8·set_to_one(N8·T *instance){ - instance->d0 = 1; - } - - // bit operations - - Local void N8·bit_and(N8·T *result, N8·T *a, N8·T *b){ - result->d0 = a->d0 & b->d0; - } - - Local void N8·bit_or(N8·T *result, N8·T *a, N8·T *b){ - result->d0 = a->d0 | b->d0; - } - - Local void N8·bit_complement(N8·T *result, N8·T *a){ - result->d0 = ~a->d0; - } - - Local void N8·bit_twos_complement(N8·T *result ,N8·T *a){ - result->d0 = (uint8_t)(~a->d0 + 1); - } - - // test functions - - Local N8·Order N8·compare(N8·T *a, N8·T *b){ - if(a->d0 < b->d0) return N8·Order_lt; - if(a->d0 > b->d0) return N8·Order_gt; - return N8·Order_eq; - } - - Local bool N8·lt(N8·T *a ,N8·T *b){ - return a->d0 < b->d0; - } - - Local bool N8·gt(N8·T *a ,N8·T *b){ - return a->d0 > b->d0; - } - - Local bool N8·eq(N8·T *a ,N8·T *b){ - return a->d0 == b->d0; - } - - Local bool N8·eq_zero(N8·T *a){ - return a->d0 == 0; - } - - // arithmetic operations - - Local N8·Status N8·accumulate(N8·T *accumulator1 ,N8·T *accumulator0 ,...){ - - va_list args; - va_start(args ,accumulator0); - uint32_t sum = accumulator0->d0; - uint32_t carry = 0; - N8·T *current; - - while( (current = va_arg(args ,N8·T*)) ){ - sum += current->d0; - if(sum < current->d0){ - (carry)++; - if(carry == 0){ - va_end(args); - return N8·Status·accumulator1_overflow; - } - } - } - va_end(args); - - accumulator1->d0 = (uint8_t)carry; - return N8·Status·ok; - } - - Local N8·Status N8·add(N8·T *sum ,N8·T *a ,N8·T *b){ - uint32_t result = (uint32_t)a->d0 + (uint32_t)b->d0; - sum->d0 = (uint8_t)(result & 0xFF); - return (result >> 8) ? N8·Status·carry : N8·Status·ok; - } - - Local bool N8·increment(N8·T *a){ - a->d0++; - return (a->d0 == 0); - } - - Local N8·Status N8·subtract(N8·T *difference ,N8·T *a ,N8·T *b){ - uint32_t diff = (uint32_t)a->d0 - (uint32_t)b->d0; - difference->d0 = (uint8_t)(diff & 0xFF); - return (diff > a->d0) ? N8·Status·borrow : N8·Status·ok; - } - - Local N8·Status N8·multiply(N8·T *product1 ,N8·T *product0 ,N8·T *a ,N8·T *b){ - uint32_t product = (uint32_t)a->d0 * (uint32_t)b->d0; - product0->d0 = (uint8_t)(product & 0xFF); - product1->d0 = (uint8_t)((product >> 8) & 0xFF); - - if(product1->d0 == 0) return N8·Status·one_word_product; - return N8·Status·two_word_product; - } - - Local N8·Status N8·divide(N8·T *remainder ,N8·T *quotient ,N8·T *a ,N8·T *b){ - if(b->d0 == 0) return N8·Status·undefined_divide_by_zero; - - uint32_t dividend = a->d0; - uint32_t divisor = b->d0; - quotient->d0 = (uint8_t)(dividend / divisor); - remainder->d0 = (uint8_t)(dividend - (quotient->d0 * divisor)); - - return N8·Status·ok; - } - - Local N8·Status N8·modulus(N8·T *remainder ,N8·T *a ,N8·T *b){ - if(b->d0 == 0) return N8·Status·undefined_modulus_zero; - uint32_t dividend = a->d0; - uint32_t divisor = b->d0; - uint32_t q = dividend / divisor; - remainder->d0 = (uint8_t)(dividend - (q * divisor)); - return N8·Status·ok; - } - - // bit motion - - typedef uint8_t (*ShiftOp)(uint8_t, uint8_t); - - Local uint8_t shift_left_op(uint8_t value, uint8_t amount){ - return (uint8_t)(value << amount); - } - - Local uint8_t shift_right_op(uint8_t value, uint8_t amount){ - return (uint8_t)(value >> amount); - } - - Local N8·Status N8·shift - ( - uint8_t shift_count - ,N8·T *spill - ,N8·T *operand - ,N8·T *fill - ,ShiftOp shift_op - ,ShiftOp complement_shift_op - ){ - - if(operand == NULL && spill == NULL) return N8·Status·ok; - - if(operand == NULL){ - operand = &N8·t[0]; - N8·copy(operand, N8·zero); - } - - if(shift_count > 7) return N8·Status·gt_max_shift_count; - - N8·T *given_operand = &N8·t[1]; - N8·copy(given_operand, operand); - - operand->d0 = shift_op(given_operand->d0, shift_count); - if(fill != NULL){ - fill->d0 = complement_shift_op(fill->d0, (8 - shift_count)); - N8·bit_or(operand, operand, fill); - } - if(spill != NULL){ - spill->d0 = shift_op(spill->d0, shift_count); - spill->d0 += complement_shift_op(given_operand->d0, (8 - shift_count)); - } - - return N8·Status·ok; - } - - Local N8·Status - N8·shift_left(uint8_t shift_count, N8·T *spill, N8·T *operand, N8·T *fill){ - return N8·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); - } - - Local N8·Status - N8·shift_right(uint8_t shift_count, N8·T *spill, N8·T *operand, N8·T *fill){ - return N8·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); - } - - Local N8·Status - N8·arithmetic_shift_right(uint8_t shift_count, N8·T *operand, N8·T *spill){ - - if(shift_count > 7) return N8·Status·gt_max_shift_count; - - if(operand == NULL){ - operand = &N8·t[0]; - N8·copy(operand, N8·zero); - } - - N8·T *fill = (operand->d0 & 0x80) ? N8·all_one_bit : N8·zero; - return N8·shift_right(shift_count, spill, operand, fill); - } - - Local const N8·M N8·m = { - - .allocate_array = N8·allocate_array - ,.allocate_array_zero = N8·allocate_array_zero - ,.deallocate = N8·deallocate - - ,.copy = N8·copy - ,.bit_and = N8·bit_and - ,.bit_or = N8·bit_or - ,.bit_complement = N8·bit_complement - ,.bit_twos_complement = N8·bit_twos_complement - ,.compare = N8·compare - ,.lt = N8·lt - ,.gt = N8·gt - ,.eq = N8·eq - ,.eq_zero = N8·eq_zero - ,.accumulate = N8·accumulate - ,.add = N8·add - ,.increment = N8·increment - ,.subtract = N8·subtract - ,.multiply = N8·multiply - ,.divide = N8·divide - ,.modulus = N8·modulus - ,.shift_left = N8·shift_left - ,.shift_right = N8·shift_right - ,.arithmetic_shift_right = N8·arithmetic_shift_right - - ,.access = N8·access - ,.from_uint32 = N8·from_uint32 - }; - - #endif - -#endif diff --git "a/developer/cc\360\237\226\211/TM.lib.c" "b/developer/cc\360\237\226\211/TM.lib.c" index 3c49c35..75d54af 100644 --- "a/developer/cc\360\237\226\211/TM.lib.c" +++ "b/developer/cc\360\237\226\211/TM.lib.c" @@ -1,14 +1,11 @@ /* - TM - Tape Machine + TM - Tape Machine Model - `TM·CVT` Cell Value Type`. + Template parameters -*/ + `TM·CVT` Cell Value Type`. -#ifndef FACE -#define TM·IMPLEMENTATION -#define FACE -#endif +*/ //-------------------------------------------------------------------------------- // Interface @@ -22,7 +19,7 @@ #include "cpp_ext.c" #include "Core.lib.c" - #include "FG.lib.c" + #include "Binding.lib.c" #define TM·DEBUG #ifdef TM·DEBUG @@ -58,23 +55,19 @@ | TM·Head·Status·rightmost ; - // set type equality pattern - #define EQ__TM__oo__TM - #endif // once per TM·CVT value +#ifdef TM·CVT #if ! FIND_ITEM( TM·CVT ,TM·TYPE_LIST ) #define TM·TYPE_LIST APPEND(TM·TYPE_LIST ,TM·TYPE) - // TM··Tableau - typedef struct Ξ(TM ,Tableau); + // declare 'TM' as a type + #define EQ__TM__oo__TM + #define Binding·Type TM + #include "Binding.lib.c" - // bind the tableau to an FG table, call the binding a 'TM' type - #define FG·Type TM - #include "FG.lib.c" - - // extent is an index, hence its effect is a function of TM·CVT + // `extent_t` is an index, so element size matters, so TM·CVT matters typedef Ξ(extent_t ,TM·CVT) size_t; typedef struct{ @@ -95,7 +88,7 @@ void (*step_left) (TM tm); void (*rewind) (TM tm); - TM·FG TM·fg; // points to TM·FG instance + 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); @@ -121,11 +114,12 @@ ); #endif +#endif //-------------------------------------------------------------------------------- // Implementation -#ifdef TM·IMPLEMENTATION +#ifdef IMPLEMENTATION // implementation to go into the lib.a file // @@ -135,7 +129,7 @@ #ifdef LOCAL //---------------------------------------- - // Dispatch wrapper + // included first without defining TM·CVT //---------------------------------------- #ifndef TM·CVT @@ -208,7 +202,7 @@ //---------------------------------------- // Initialization for TM·fg - Local TM·FG TM·fg = { + Local TM·Binding TM·fg = { .Tape·topo = TM·Tape·topo ,.Tape·bounded = TM·Tape·bounded ,.Head·status = TM·Head·status @@ -262,7 +256,7 @@ return tm->fg.write(tm ,write_pt); } - Local Ξ(TM ,TM·CVT)·FG Ξ(TM ,TM·CVT)·fg = { + Local Ξ(TM ,TM·CVT)·Binding Ξ(TM ,TM·CVT)·fg = { .parent = TM·fg ,.extent = Ξ(TM ,TM·CVT)·extent ,.read = Ξ(TM ,TM·CVT)·read @@ -539,7 +533,7 @@ //---------------------------------------- // Initialization for Ξ(TM·Array ,TM·CVT)·fg - Local Ξ(TM·Array ,TM·CVT)·FG Ξ(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 diff --git "a/developer/cc\360\237\226\211/TM_scratch.c" "b/developer/cc\360\237\226\211/TM_scratch.c" deleted file mode 100644 index 13b2240..0000000 --- "a/developer/cc\360\237\226\211/TM_scratch.c" +++ /dev/null @@ -1,65 +0,0 @@ - // This initializes 'inner'. - // `alignment` is an extent, e.g. extent_of·AU(uint64_t) = 0x7 - Local TM·Status Ξ(TM·NX ,CVT)·largest_aligned( - TM·NX·AU *outer ,Ξ(TM·NX ,CVT) *inner ,extent·AU alignment - ){ - uintptr_t p0 = (uintptr_t)outer->position; - uintptr_t p1 = (uintptr_t)outer->position + outer->extent; - - CVT *p0_aligned = (CVT *)( - (p0 + alignment) & ~( (uintptr_t)alignment ) - ); - CVT *p1_aligned = (CVT *)( - ( p1 - extent_of·AU(CVT) ) & ~( (uintptr_t)alignment ) - ); - - if( p1_aligned < p0_aligned ) return TM·Status·derailed; - - inner->position = p0_aligned; - inner->extent = (Ξ(extent_t ,CVT))(p1_aligned - p0_aligned}; - return TM·Status·on_track; - } - - - - - Local TM·Status TM·NX·topo(TM·NX *tm ,TM·Tape·Topo *topo){ - #ifdef TM·Debug - TM·Guard·init_count(chk); - TM·Guard·fg.check(&chk ,1 ,tm ,TM·NX_##CVT·Msg·tm); - TM·Guard·fg.check(&chk ,1 ,topo ,"topo ptr is NULL, so nowhere to put result"); - TM·Guard·if_return(chk); - #endif - if(tm->extent·AU == 0){ - *topo = TM·Tape·Topo·singleton; - }else{ - *topo = TM·Tape·Topo·segment; - } - return TM·Status·on_track; - } - - // extent·AU is an AU index - Local TM·Status TM·NX·extent·AU(TM·NX *tm ,extent·AU *extent·AU){ - TM·Tape·Topo topo; - TM·Status status = TM·NX_##CVT·topo(tm ,&topo); - boolean good_topo = - (status == TM·Status·on_track) && (topo & TM·Tape·Topo·finite_nz) - ; - - #ifdef TM·Debug - TM·Guard·init_count(chk); - TM·Guard·fg.check(&chk ,1 ,tm ,TM·NX·Msg·tm); - TM·Guard·fg.check(&chk ,1 ,extent·AU ,TM·NX·Msg·extent·AU); - TM·Guard·fg.check( - &chk ,0 ,good_topo - ,"Tape does not exist or topology does not have an extent·AU." - ); - TM·Guard·if_return(chk); - #endif - - if(!good_topo) return TM·Status·derailed; - *extent·AU = tm->array.extent·AU; - return TM·Status·on_track; - } - - #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 573c27c..dd89cd9 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_0.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_0.c" @@ -65,9 +65,15 @@ DEBUG #include #define DEBUG_CPP + +// print the macro and the evaluation of the macro at compile time: +// #pragma message( STR_VAL() ) + #define STR(...) #__VA_ARGS__ +#define VAL(...) STR(__VA_ARGS__) +#define STR_VAL(...) #__VA_ARGS__ " -> " VAL(__VA_ARGS__) -// print the macro and the evaluation of the macro +// print the macro and the evaluation of the macro at run time: #define SHOW(expr) printf("%s -> %s\n", #expr, STR(expr)) /*=========================================================================== 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 bc241d7..a188507 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_1.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_1.c" @@ -62,8 +62,8 @@ DROPE_NOT_EXISTS_RIGHT ( NOT_EXISTS(__VA_ARGS__) ) \ () \ (IF \ - ( predicate(FIRST(__VA_ARGS__)) ) \ - ( FIRST( ,__VA_ARGS__) ) \ + ( predicate(FIRST(,__VA_ARGS__)) ) \ + ( FIRST(,__VA_ARGS__) ) \ ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ ) #define _FIND_CONFEDERATE() _FIND @@ -76,9 +76,9 @@ DROPE_NOT_EXISTS_RIGHT ( NOT_EXISTS(__VA_ARGS__) ) \ () \ (IF \ - ( EQ(item ,FIRST(__VA_ARGS__)) ) \ - ( FIRST( ,__VA_ARGS__) ) \ - ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ + ( EQ(item ,FIRST(,__VA_ARGS__)) ) \ + ( item ) \ + ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(item ,REST(__VA_ARGS__)) ) \ ) #define _FIND_ITEM_CONFEDERATE() _FIND_ITEM diff --git "a/developer/cc\360\237\226\211/environment.h" "b/developer/cc\360\237\226\211/environment.h" deleted file mode 100644 index cdea83c..0000000 --- "a/developer/cc\360\237\226\211/environment.h" +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef Mpblock·ENVIRONMENT_H -#define Mpblock·ENVIRONMENT_H - - -#endif diff --git "a/developer/cc\360\237\226\211/test_setup.cli.c" "b/developer/cc\360\237\226\211/test_setup.cli.c" deleted file mode 100644 index f1c6e68..0000000 --- "a/developer/cc\360\237\226\211/test_setup.cli.c" +++ /dev/null @@ -1,22 +0,0 @@ -/* - - A placeholder to see if make etc. is working. - -*/ - -#define IFACE -#include -#include - -// No need to define IMPLEMENTATION as `main` is one and done. - -int main(int argc ,char *argv[] ,char *envp[]){ - if(argc != 1){ - fprintf(stderr, "Usage: %s\n", argv[0]); - return EXIT_FAILURE; - } - - fprintf(stderr, "%s done\n", argv[0]); - - return 0; -} diff --git "a/developer/cc\360\237\226\211/update.lib.c" "b/developer/cc\360\237\226\211/update.lib.c" deleted file mode 100644 index 61c5cf4..0000000 --- "a/developer/cc\360\237\226\211/update.lib.c" +++ /dev/null @@ -1,107 +0,0 @@ -/* - Copy - Memory copy operations with attention to alignment. - Provides optimized copy and byte order reversal functions. -*/ - -#define Copy·DEBUG - -#ifndef FACE -#define Copy·IMPLEMENTATION -#define FACE -#endif - -//-------------------------------------------------------------------------------- -// Interface - -#ifndef Copy·FACE -#define Copy·FACE - - #include - #include - - typedef struct{ - void *read0 - ,size_t read_size - ,void *write0 - ,size_t write_size; - } Copy·it; - - typedef enum{ - Copy·Status·perfect_fit = 0 - ,Copy·Status·argument_guard - ,Copy·Status·read_surplus - ,Copy·Status·read_surplus_write_gap - ,Copy·Status·write_available - ,Copy·Status·write_gap; - } Copy·Status; - - typedef enum{ - Copy·WFIt·Mode·none = 0 - ,Copy·WFIt·Mode·bytes - ,Copy·WFIt·Mode·bytes_reverse - ,Copy·WFIt·Mode·write_hex - ,Copy·WFIt·Mode·read_hex; - } Copy·WFIt·Mode; - - typedef enum{ - Copy·WFIt·Status·valid = 0 - ,Copy·WFIt·Status·null_read - ,Copy·WFIt·Status·null_write - ,Copy·WFIt·Status·zero_buffer - ,Copy·WFIt·Status·overlap - ,Copy·WFIt·Status·write_too_small; - } Copy·WFIt·Status; - - typedef struct{ - void *region( void *read0 ,void *read1 ,void *write0 ) - ,void *reverse_byte_order( void *read0 ,void *read1 ,void *write0 ); - } Copy·M; - -#endif - -//-------------------------------------------------------------------------------- -// Implementation - -#ifdef Copy·IMPLEMENTATION - - // this part goes into Nlib.a - #ifndef LOCAL - #endif - - #ifdef LOCAL - - Local Copy·WFIt·Status Copy·wellformed_it(Copy·it *it){ - char *this_name = "Copy·wellformed_it"; - Copy·WFIt·Status status = Copy·WFIt·Status·valid; - - if(it->read0 == NULL){ - fprintf( stderr ,"%s: NULL read pointer\n" ,this_name ); - status |= Copy·WFIt·Status·null_read; - } - - if(it->write0 == NULL){ - fprintf( stderr ,"%s: NULL write pointer\n" ,this_name ); - status |= Copy·WFIt·Status·null_write; - } - - if(it->read_size == 0){ - fprintf( stderr ,"%s: Zero-sized read buffer\n" ,this_name ); - status |= Copy·WFIt·Status·zero_read_buffer; - } - - if(it->write_size == 0){ - fprintf( stderr ,"%s: Zero-sized write buffer\n" ,this_name ); - status |= Copy·WFIt·Status·zero_write_buffer; - } - - if( Copy·overlap_size_interval(it->read0 ,it->read_size ,it->write0 ,it->write_size) ){ - fprintf( stderr ,"%s: Read and write buffers overlap!\n" ,this_name ); - status |= Copy·WFIt·Status·overlap; - } - - return status; - } - - #endif // LOCAL - -#endif // IMPLEMENTATION diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/N16.lib.c" "b/developer/deprecated\360\237\226\211/2025-03-29/N16.lib.c" new file mode 100644 index 0000000..561b43d --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/N16.lib.c" @@ -0,0 +1,433 @@ +/* + N16 - a processor native type + + For binary operations: a op b -> c + + See the document on the proper use of the Natural types. + + On the subject of multiple pointers indicating the same location in memory: + + When a routine has multiple results, and one or more of the result location + pointers point to the same storage, the routine will either return an error + status, or have defined behavior. + + When a routine has multiple operands, in any combination, those + pointers can point to the same location, and the routine will + function as advertised. + + When an operand functions as both an input and a result, perhaps due + to a result pointer pointing to the same place as an operand + pointer, the routine will function as advertised. (Internally the + routine might make a temporary copy of the operand to accomplish + this.) +*/ + +#define N16·DEBUG + +#ifndef FACE +#define N16·IMPLEMENTATION +#define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef N16·FACE +#define N16·FACE + + #include + #include + #include + #include + + //---------------------------------------- + // Instance Data (Declaration Only) + + typedef uint16_t Extent; + typedef uint16_t Digit; + + typedef struct N16·T N16·T; + + extern N16·T *N16·zero; + extern N16·T *N16·one; + extern N16·T *N16·all_one_bit; + extern N16·T *N16·lsb; + extern N16·T *N16·msb; + + //---------------------------------------- + // Return/Error Status and handlers + + typedef enum{ + N16·Status·ok = 0 + ,N16·Status·overflow = 1 + ,N16·Status·accumulator1_overflow = 2 + ,N16·Status·carry = 3 + ,N16·Status·borrow = 4 + ,N16·Status·undefined_divide_by_zero = 5 + ,N16·Status·undefined_modulus_zero = 6 + ,N16·Status·gt_max_shift_count = 7 + ,N16·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value + ,N16·Status·one_word_product = 9 + ,N16·Status·two_word_product = 10 + } N16·Status; + + typedef enum{ + N16·Order_lt = -1 + ,N16·Order_eq = 0 + ,N16·Order_gt = 1 + } N16·Order; + + typedef N16·T *( *N16·Allocate_MemoryFault )(Extent); + + //---------------------------------------- + // Interface + + typedef struct{ + + N16·T *(*allocate_array_zero)(Extent, N16·Allocate_MemoryFault); + N16·T *(*allocate_array)(Extent, N16·Allocate_MemoryFault); + void (*deallocate)(N16·T*); + + void (*copy)(N16·T*, N16·T*); + void (*bit_and)(N16·T*, N16·T*, N16·T*); + void (*bit_or)(N16·T*, N16·T*, N16·T*); + void (*bit_complement)(N16·T*, N16·T*); + void (*bit_twos_complement)(N16·T*, N16·T*); + N16·Order (*compare)(N16·T*, N16·T*); + bool (*lt)(N16·T*, N16·T*); + bool (*gt)(N16·T*, N16·T*); + bool (*eq)(N16·T*, N16·T*); + bool (*eq_zero)(N16·T*); + N16·Status (*accumulate)(N16·T *accumulator1 ,N16·T *accumulator0 ,...); + N16·Status (*add)(N16·T*, N16·T*, N16·T*); + bool (*increment)(N16·T *a); + N16·Status (*subtract)(N16·T*, N16·T*, N16·T*); + N16·Status (*multiply)(N16·T*, N16·T*, N16·T*, N16·T*); + N16·Status (*divide)(N16·T*, N16·T*, N16·T*, N16·T*); + N16·Status (*modulus)(N16·T*, N16·T*, N16·T*); + N16·Status (*shift_left)(Extent, N16·T*, N16·T*, N16·T*); + N16·Status (*shift_right)(Extent, N16·T*, N16·T*, N16·T*); + N16·Status (*arithmetic_shift_right)(Extent, N16·T*, N16·T*); + + N16·T* (*access)(N16·T*, Extent); + void (*from_uint32)(N16·T *destination ,uint32_t value); + } N16·M; + + Local const N16·M N16·m; // initialized in the LOCAL section + +#endif + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef N16·IMPLEMENTATION + + // this part goes into the library + #ifndef LOCAL + + #include + #include + + struct N16·T{ + Digit d0; + }; + + N16·T N16·constant[4] = { + {.d0 = 0}, + {.d0 = 1}, + {.d0 = ~(uint16_t)0}, + {.d0 = 1 << 15} + }; + + N16·T *N16·zero = &N16·constant[0]; + N16·T *N16·one = &N16·constant[1]; + N16·T *N16·all_one_bit = &N16·constant[2]; + N16·T *N16·msb = &N16·constant[3]; + N16·T *N16·lsb = &N16·constant[1]; + + // the allocate an array of N16 + N16·T *N16·allocate_array(Extent extent ,N16·Allocate_MemoryFault memory_fault){ + N16·T *instance = malloc((extent + 1) * sizeof(N16·T)); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + N16·T *N16·allocate_array_zero(Extent extent ,N16·Allocate_MemoryFault memory_fault){ + N16·T *instance = calloc(extent + 1, sizeof(N16·T)); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + void N16·deallocate(N16·T *unencumbered){ + free(unencumbered); + } + + + #endif + + // This part is included after the library user's code + #ifdef LOCAL + + // instance + + struct N16·T{ + Digit d0; + }; + + // temporary variables + Local N16·T N16·t[4]; + + // allocation + + extern N16·T *N16·allocate_array(Extent, N16·Allocate_MemoryFault); + extern N16·T *N16·allocate_array_zero(Extent, N16·Allocate_MemoryFault); + extern void N16·deallocate(N16·T *); + + // so the user can access numbers in an array allocation + Local N16·T* N16·access(N16·T *array ,Extent index){ + return &array[index]; + } + + Local void N16·from_uint32(N16·T *destination ,uint32_t value){ + if(destination == NULL) return; + destination->d0 = (uint16_t)(value & 0xFFFF); + } + + // copy, convenience copy + + Local void N16·copy(N16·T *destination ,N16·T *source){ + if(source == destination) return; + *destination = *source; + } + + Local void N16·set_to_zero(N16·T *instance){ + instance->d0 = 0; + } + + Local void N16·set_to_one(N16·T *instance){ + instance->d0 = 1; + } + + // bit operations + + Local void N16·bit_and(N16·T *result, N16·T *a, N16·T *b){ + result->d0 = a->d0 & b->d0; + } + + Local void N16·bit_or(N16·T *result, N16·T *a, N16·T *b){ + result->d0 = a->d0 | b->d0; + } + + Local void N16·bit_complement(N16·T *result, N16·T *a){ + result->d0 = ~a->d0; + } + + Local void N16·bit_twos_complement(N16·T *result ,N16·T *a){ + result->d0 = (uint16_t)(~a->d0 + 1); + } + + // test functions + + Local N16·Order N16·compare(N16·T *a, N16·T *b){ + if(a->d0 < b->d0) return N16·Order_lt; + if(a->d0 > b->d0) return N16·Order_gt; + return N16·Order_eq; + } + + Local bool N16·lt(N16·T *a ,N16·T *b){ + return a->d0 < b->d0; + } + + Local bool N16·gt(N16·T *a ,N16·T *b){ + return a->d0 > b->d0; + } + + Local bool N16·eq(N16·T *a ,N16·T *b){ + return a->d0 == b->d0; + } + + Local bool N16·eq_zero(N16·T *a){ + return a->d0 == 0; + } + + // arithmetic operations + + Local N16·Status N16·accumulate(N16·T *accumulator1 ,N16·T *accumulator0 ,...){ + + va_list args; + va_start(args ,accumulator0); + uint32_t sum = accumulator0->d0; + uint32_t carry = 0; + N16·T *current; + + while( (current = va_arg(args ,N16·T*)) ){ + sum += current->d0; + if(sum < current->d0){ + (carry)++; + if(carry == 0){ + va_end(args); + return N16·Status·accumulator1_overflow; + } + } + } + va_end(args); + + accumulator1->d0 = (uint16_t)carry; + return N16·Status·ok; + } + + Local N16·Status N16·add(N16·T *sum ,N16·T *a ,N16·T *b){ + uint32_t result = (uint32_t)a->d0 + (uint32_t)b->d0; + sum->d0 = (uint16_t)(result & 0xFFFF); + return (result >> 16) ? N16·Status·carry : N16·Status·ok; + } + + Local bool N16·increment(N16·T *a){ + a->d0++; + return (a->d0 == 0); + } + + Local N16·Status N16·subtract(N16·T *difference ,N16·T *a ,N16·T *b){ + uint32_t diff = (uint32_t)a->d0 - (uint32_t)b->d0; + difference->d0 = (uint16_t)(diff & 0xFFFF); + return (diff > a->d0) ? N16·Status·borrow : N16·Status·ok; + } + + Local N16·Status N16·multiply(N16·T *product1 ,N16·T *product0 ,N16·T *a ,N16·T *b){ + uint32_t product = (uint32_t)a->d0 * (uint32_t)b->d0; + product0->d0 = (uint16_t)(product & 0xFFFF); + product1->d0 = (uint16_t)((product >> 16) & 0xFFFF); + + if(product1->d0 == 0) return N16·Status·one_word_product; + return N16·Status·two_word_product; + } + + Local N16·Status N16·divide(N16·T *remainder ,N16·T *quotient ,N16·T *a ,N16·T *b){ + if(b->d0 == 0) return N16·Status·undefined_divide_by_zero; + + uint32_t dividend = a->d0; + uint32_t divisor = b->d0; + quotient->d0 = (uint16_t)(dividend / divisor); + remainder->d0 = (uint16_t)(dividend - (quotient->d0 * divisor)); + + return N16·Status·ok; + } + + Local N16·Status N16·modulus(N16·T *remainder ,N16·T *a ,N16·T *b){ + if(b->d0 == 0) return N16·Status·undefined_modulus_zero; + uint32_t dividend = a->d0; + uint32_t divisor = b->d0; + uint32_t q = dividend / divisor; + remainder->d0 = (uint16_t)(dividend - (q * divisor)); + return N16·Status·ok; + } + + // bit motion + + typedef uint16_t (*ShiftOp)(uint16_t, uint16_t); + + Local uint16_t shift_left_op(uint16_t value, uint16_t amount){ + return value << amount; + } + + Local uint16_t shift_right_op(uint16_t value, uint16_t amount){ + return (uint16_t)(value >> amount); + } + + Local N16·Status N16·shift + ( + uint16_t shift_count + ,N16·T *spill + ,N16·T *operand + ,N16·T *fill + ,ShiftOp shift_op + ,ShiftOp complement_shift_op + ){ + + if(operand == NULL && spill == NULL) return N16·Status·ok; + + if(operand == NULL){ + operand = &N16·t[0]; + N16·copy(operand, N16·zero); + } + + if(shift_count > 15) return N16·Status·gt_max_shift_count; + + N16·T *given_operand = &N16·t[1]; + N16·copy(given_operand, operand); + + operand->d0 = shift_op(given_operand->d0, shift_count); + if(fill != NULL){ + fill->d0 = complement_shift_op(fill->d0, (16 - shift_count)); + N16·bit_or(operand, operand, fill); + } + if(spill != NULL){ + spill->d0 = shift_op(spill->d0, shift_count); + spill->d0 += complement_shift_op(given_operand->d0, (16 - shift_count)); + } + + return N16·Status·ok; + } + + Local N16·Status + N16·shift_left(uint16_t shift_count, N16·T *spill, N16·T *operand, N16·T *fill){ + return N16·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); + } + + Local N16·Status + N16·shift_right(uint16_t shift_count, N16·T *spill, N16·T *operand, N16·T *fill){ + return N16·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); + } + + Local N16·Status + N16·arithmetic_shift_right(uint16_t shift_count, N16·T *operand, N16·T *spill){ + + if(shift_count > 15) return N16·Status·gt_max_shift_count; + + if(operand == NULL){ + operand = &N16·t[0]; + N16·copy(operand, N16·zero); + } + + N16·T *fill = (operand->d0 & 0x8000) ? N16·all_one_bit : N16·zero; + return N16·shift_right(shift_count, spill, operand, fill); + } + + Local const N16·M N16·m = { + + .allocate_array = N16·allocate_array + ,.allocate_array_zero = N16·allocate_array_zero + ,.deallocate = N16·deallocate + + ,.copy = N16·copy + ,.bit_and = N16·bit_and + ,.bit_or = N16·bit_or + ,.bit_complement = N16·bit_complement + ,.bit_twos_complement = N16·bit_twos_complement + ,.compare = N16·compare + ,.lt = N16·lt + ,.gt = N16·gt + ,.eq = N16·eq + ,.eq_zero = N16·eq_zero + ,.accumulate = N16·accumulate + ,.add = N16·add + ,.increment = N16·increment + ,.subtract = N16·subtract + ,.multiply = N16·multiply + ,.divide = N16·divide + ,.modulus = N16·modulus + ,.shift_left = N16·shift_left + ,.shift_right = N16·shift_right + ,.arithmetic_shift_right = N16·arithmetic_shift_right + + ,.access = N16·access + ,.from_uint32 = N16·from_uint32 + }; + + #endif + +#endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/N32.lib.c" "b/developer/deprecated\360\237\226\211/2025-03-29/N32.lib.c" new file mode 100644 index 0000000..ccb3411 --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/N32.lib.c" @@ -0,0 +1,457 @@ +/* + N32 - a processor native type + + For binary operations: a op b -> c + + See the document on the proper use of the Natural types. + + On the subject of multiple pointers indicating the same location in memory: + + When a routine has multiple results, and one or more of the result location + pointers point to the same storage, the routine will either return an error + status, or have defined behavior. + + When a routine has multiple operands, in any combination, those + pointers can point to the same location, and the routine will + function as advertised. + + When an operand functions as both an input and a result, perhaps due + to a result pointer pointing to the same place as an operand + pointer, the routine will function as advertised. (Internally the + routine might make a temporary copy of the operand to accomplish + this.) + +*/ + +#define N32·DEBUG + +#ifndef FACE +#define N32·IMPLEMENTATION +#define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef N32·FACE +#define N32·FACE + + #include + #include + #include + #include + + //---------------------------------------- + // Instance Data (Declaration Only) + + typedef uint32_t Extent; + typedef uint32_t Digit; + + typedef struct N32·T N32·T; + + extern N32·T *N32·zero; + extern N32·T *N32·one; + extern N32·T *N32·all_one_bit; + extern N32·T *N32·lsb; + extern N32·T *N32·msb; + + //---------------------------------------- + // Return/Error Status and handlers + + typedef enum{ + N32·Status·ok = 0 + ,N32·Status·overflow = 1 + ,N32·Status·accumulator1_overflow = 2 + ,N32·Status·carry = 3 + ,N32·Status·borrow = 4 + ,N32·Status·undefined_divide_by_zero = 5 + ,N32·Status·undefined_modulus_zero = 6 + ,N32·Status·gt_max_shift_count = 7 + ,N32·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value + ,N32·Status·one_word_product = 9 + ,N32·Status·two_word_product = 10 + } N32·Status; + + typedef enum{ + N32·Order_lt = -1 + ,N32·Order_eq = 0 + ,N32·Order_gt = 1 + } N32·Order; + + typedef N32·T *( *N32·Allocate_MemoryFault )(Extent); + + //---------------------------------------- + // Interface + + typedef struct{ + + N32·T *(*allocate_array_zero)(Extent, N32·Allocate_MemoryFault); + N32·T *(*allocate_array)(Extent, N32·Allocate_MemoryFault); + void (*deallocate)(N32·T*); + + void (*copy)(N32·T*, N32·T*); + void (*bit_and)(N32·T*, N32·T*, N32·T*); + void (*bit_or)(N32·T*, N32·T*, N32·T*); + void (*bit_complement)(N32·T*, N32·T*); + void (*bit_twos_complement)(N32·T*, N32·T*); + N32·Order (*compare)(N32·T*, N32·T*); + bool (*lt)(N32·T*, N32·T*); + bool (*gt)(N32·T*, N32·T*); + bool (*eq)(N32·T*, N32·T*); + bool (*eq_zero)(N32·T*); + N32·Status (*accumulate)(N32·T *accumulator1 ,N32·T *accumulator0 ,...); + N32·Status (*add)(N32·T*, N32·T*, N32·T*); + bool (*increment)(N32·T *a); + N32·Status (*subtract)(N32·T*, N32·T*, N32·T*); + N32·Status (*multiply)(N32·T*, N32·T*, N32·T*, N32·T*); + N32·Status (*divide)(N32·T*, N32·T*, N32·T*, N32·T*); + N32·Status (*modulus)(N32·T*, N32·T*, N32·T*); + N32·Status (*shift_left)(Extent, N32·T*, N32·T*, N32·T*); + N32·Status (*shift_right)(Extent, N32·T*, N32·T*, N32·T*); + N32·Status (*arithmetic_shift_right)(Extent, N32·T*, N32·T*); + + N32·T* (*access)(N32·T*, Extent); + void (*from_uint32)(N32·T *destination ,uint32_t value); + } N32·M; + + Local const N32·M N32·m; // initialized in the LOCAL section + +#endif + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef N32·IMPLEMENTATION + + // this part goes into the library + #ifndef LOCAL + + #include + #include + + struct N32·T{ + Digit d0; + }; + + N32·T N32·constant[4] = { + {.d0 = 0}, + {.d0 = 1}, + {.d0 = ~(uint32_t)0}, + {.d0 = 1 << 31} + }; + + N32·T *N32·zero = &N32·constant[0]; + N32·T *N32·one = &N32·constant[1]; + N32·T *N32·all_one_bit = &N32·constant[2]; + N32·T *N32·msb = &N32·constant[3]; + N32·T *N32·lsb = &N32·constant[1]; + + // the allocate an array of N32 + N32·T *N32·allocate_array(Extent extent ,N32·Allocate_MemoryFault memory_fault){ + N32·T *instance = malloc((extent + 1) * sizeof(N32·T) ); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + N32·T *N32·allocate_array_zero(Extent extent ,N32·Allocate_MemoryFault memory_fault){ + N32·T *instance = calloc( extent + 1 ,sizeof(N32·T) ); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + void N32·deallocate(N32·T *unencumbered){ + free(unencumbered); + } + + #endif + + // This part is included after the library user's code + #ifdef LOCAL + + // instance + + struct N32·T{ + Digit d0; + }; + + // temporary variables + // making these LOCAL rather than reserving one block in the library is thread safe + // allocating a block once is more efficient + // library code writes these, they are not on the interface + + Local N32·T N32·t[4]; + + + // allocation + + extern N32·T *N32·allocate_array(Extent, N32·Allocate_MemoryFault); + extern N32·T *N32·allocate_array_zero(Extent, N32·Allocate_MemoryFault); + extern void N32·deallocate(N32·T *); + + // so the user can access numbers in an array allocation + Local N32·T* N32·access(N32·T *array ,Extent index){ + return &array[index]; + } + + Local void N32·from_uint32(N32·T *destination ,uint32_t value){ + if(destination == NULL) return; + destination->d0 = value; + } + + // copy, convenience copy + + Local void N32·copy(N32·T *destination ,N32·T *source){ + if(source == destination) return; // that was easy! + *destination = *source; + } + + Local void N32·set_to_zero(N32·T *instance){ + instance->d0 = 0; + } + + Local void N32·set_to_one(N32·T *instance){ + instance->d0 = 1; + } + + // bit operations + + Local void N32·bit_and(N32·T *result, N32·T *a, N32·T *b){ + result->d0 = a->d0 & b->d0; + } + + // result can be one of the operands + Local void N32·bit_or(N32·T *result, N32·T *a, N32·T *b){ + result->d0 = a->d0 | b->d0; + } + + // result can the same as the operand + Local void N32·bit_complement(N32·T *result, N32·T *a){ + result->d0 = ~a->d0; + } + + // result can the same as the operand + Local void N32·bit_twos_complement(N32·T *result ,N32·T *a){ + result->d0 = ~a->d0 + 1; + } + + // test functions + + Local N32·Order N32·compare(N32·T *a, N32·T *b){ + if(a->d0 < b->d0) return N32·Order_lt; + if(a->d0 > b->d0) return N32·Order_gt; + return N32·Order_eq; + } + + Local bool N32·lt(N32·T *a ,N32·T *b){ + return a->d0 < b->d0; + } + + Local bool N32·gt(N32·T *a ,N32·T *b){ + return a->d0 > b->d0; + } + + Local bool N32·eq(N32·T *a ,N32·T *b){ + return a->d0 == b->d0; + } + + Local bool N32·eq_zero(N32·T *a){ + return a->d0 == 0; + } + + + // arithmetic operations + + // For a large number of summands for the lower precision Natural implementations, for accumulate/add/sub, the 'overflow' operand could overflow and thus this routine will halt and return N32·Status·accumulator1_overflow + // + // When accumulator1 and accumulator0 point to the same location, the result is the accumulator1 value. + Local N32·Status N32·accumulate(N32·T *accumulator1 ,N32·T *accumulator0 ,...){ + + va_list args; + va_start(args ,accumulator0); + uint32_t sum = accumulator0->d0; + uint32_t carry = 0; + N32·T *current; + + while( (current = va_arg(args ,N32·T *)) ){ + sum += current->d0; + if(sum < current->d0){ // Accumulator1 into carry + (carry)++; + if(carry == 0){ + va_end(args); + return N32·Status·accumulator1_overflow; + } + } + } + va_end(args); + + // wipes out prior value of accumulator1 + accumulator1->d0 = carry; + + return N32·Status·ok; + } + + Local N32·Status N32·add(N32·T *sum ,N32·T *a ,N32·T *b){ + uint64_t result = (uint64_t)a->d0 + (uint64_t)b->d0; + sum->d0 = (uint32_t)result; + return (result >> 32) ? N32·Status·carry : N32·Status·ok; + } + + Local bool N32·increment(N32·T *a){ + a->d0++; + return a->d0 == 0; + } + + Local N32·Status N32·subtract(N32·T *difference ,N32·T *a ,N32·T *b){ + uint64_t diff = (uint64_t) a->d0 - (uint64_t) b->d0; + difference->d0 = (uint32_t)diff; + return (diff > a->d0) ? N32·Status·borrow : N32·Status·ok; + } + + + Local N32·Status N32·multiply(N32·T *product1 ,N32·T *product0 ,N32·T *a ,N32·T *b){ + uint64_t product = (uint64_t)a->d0 * (uint64_t)b->d0; + product0->d0 = (uint32_t)product; + product1->d0 = (uint32_t)(product >> 32); + + if(product1->d0 == 0) return N32·Status·one_word_product; + return N32·Status·two_word_product; + } + + Local N32·Status N32·divide(N32·T *remainder ,N32·T *quotient ,N32·T *a ,N32·T *b){ + if(b->d0 == 0) return N32·Status·undefined_divide_by_zero; + + quotient->d0 = a->d0 / b->d0; + remainder->d0 = a->d0 - (quotient->d0 * b->d0); + + return N32·Status·ok; + } + + Local N32·Status N32·modulus(N32·T *remainder ,N32·T *a ,N32·T *b){ + if(b->d0 == 0) return N32·Status·undefined_modulus_zero; + uint32_t quotient = a->d0 / b->d0; + remainder->d0 = a->d0 - (quotient * b->d0); + return N32·Status·ok; + } + + // bit motion + + typedef uint32_t (*ShiftOp)(uint32_t, uint32_t); + + Local uint32_t shift_left_op(uint32_t value, uint32_t amount){ + return value << amount; + } + + Local uint32_t shift_right_op(uint32_t value, uint32_t amount){ + return value >> amount; + } + + // modifies all three of its operands + // in the case of duplicate operands this is the order: first modifies operand, then fill, then spill, + Local N32·Status N32·shift + ( + uint32_t shift_count + ,N32·T *spill + ,N32·T *operand + ,N32·T *fill + ,ShiftOp shift_op + ,ShiftOp complement_shift_op + ){ + + // If no result is needed, return immediately. + if(operand == NULL && spill == NULL) return N32·Status·ok; + + // Treat NULL operand as zero. + if(operand == NULL){ + operand = &N32·t[0]; + N32·copy(operand, N32·zero); + } + + // Shifting more than one word breaks our fill/spill model. + if(shift_count > 31) return N32·Status·gt_max_shift_count; + + // The given operand is still required after it is modified, so we copy it. + N32·T *given_operand = &N32·t[1]; + N32·copy(given_operand, operand); + + // Perform the shift + operand->d0 = shift_op(given_operand->d0, shift_count); + if(fill != NULL){ + fill->d0 = complement_shift_op(fill->d0, (32 - shift_count)); + N32·bit_or(operand, operand, fill); + } + if(spill != NULL){ + spill->d0 = shift_op(spill->d0, shift_count); + spill->d0 += complement_shift_op(given_operand->d0, (32 - shift_count)); + } + + return N32·Status·ok; + } + + // Define concrete shift functions using valid C function pointers + Local N32·Status + N32·shift_left(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ + return N32·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); + } + + Local N32·Status + N32·shift_right(uint32_t shift_count, N32·T *spill, N32·T *operand, N32·T *fill){ + return N32·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); + } + + Local N32·Status + N32·arithmetic_shift_right(uint32_t shift_count, N32·T *operand, N32·T *spill){ + + // Guard against excessive shift counts + if(shift_count > 31) return N32·Status·gt_max_shift_count; + + // A NULL operand is treated as zero + if(operand == NULL){ + operand = &N32·t[0]; + N32·copy(operand, N32·zero); + } + + // Pick the fill value based on the sign bit + N32·T *fill = (operand->d0 & 0x80000000) ? N32·all_one_bit : N32·zero; + + // Call shift_right with the appropriate fill + return N32·shift_right(shift_count, spill, operand, fill); + } + + Local const N32·M N32·m = { + + .allocate_array = N32·allocate_array + ,.allocate_array_zero = N32·allocate_array_zero + ,.deallocate = N32·deallocate + + ,.copy = N32·copy + ,.bit_and = N32·bit_and + ,.bit_or = N32·bit_or + ,.bit_complement = N32·bit_complement + ,.bit_twos_complement = N32·bit_twos_complement + ,.compare = N32·compare + ,.lt = N32·lt + ,.gt = N32·gt + ,.eq = N32·eq + ,.eq_zero = N32·eq_zero + ,.accumulate = N32·accumulate + ,.add = N32·add + ,.increment = N32·increment + ,.subtract = N32·subtract + ,.multiply = N32·multiply + ,.divide = N32·divide + ,.modulus = N32·modulus + ,.shift_left = N32·shift_left + ,.shift_right = N32·shift_right + ,.arithmetic_shift_right = N32·arithmetic_shift_right + + ,.access = N32·access + ,.from_uint32 = N32·from_uint32 + }; + + #endif + +#endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/N64.lib.c" "b/developer/deprecated\360\237\226\211/2025-03-29/N64.lib.c" new file mode 100644 index 0000000..6058e9b --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/N64.lib.c" @@ -0,0 +1,477 @@ +/* + N64 - a 64-bit native type + + For binary operations: a op b -> c + + Similar to N32, but now each Digit is 64 bits. Where a 128-bit + intermediate is necessary (e.g. multiplication), we handle it + manually using two 64-bit parts. + + On the subject of multiple pointers indicating the same location in memory: + + When a routine has multiple results, and one or more of the result location + pointers point to the same storage, the routine will either return an error + status, or have defined behavior. + + When a routine has multiple operands, in any combination, those + pointers can point to the same location, and the routine will + function as advertised. + + When an operand functions as both an input and a result, perhaps due + to a result pointer pointing to the same place as an operand + pointer, the routine will function as advertised. (Internally the + routine might make a temporary copy of the operand to accomplish + this.) +*/ + +#define N64·DEBUG + +#ifndef FACE +#define N64·IMPLEMENTATION +#define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef N64·FACE +#define N64·FACE + + #include + #include + #include + #include + + //---------------------------------------- + // Instance Data (Declaration Only) + + typedef uint64_t Extent; + typedef uint64_t Digit; + + typedef struct N64·T N64·T; + + extern N64·T *N64·zero; + extern N64·T *N64·one; + extern N64·T *N64·all_one_bit; + extern N64·T *N64·lsb; + extern N64·T *N64·msb; + + //---------------------------------------- + // Return/Error Status and handlers + + typedef enum { + N64·Status·ok = 0 + ,N64·Status·overflow = 1 + ,N64·Status·accumulator1_overflow = 2 + ,N64·Status·carry = 3 + ,N64·Status·borrow = 4 + ,N64·Status·undefined_divide_by_zero = 5 + ,N64·Status·undefined_modulus_zero = 6 + ,N64·Status·gt_max_shift_count = 7 + ,N64·Status·spill_eq_operand = 8 // not currently signaled, result will be spill value + ,N64·Status·one_word_product = 9 + ,N64·Status·two_word_product = 10 + } N64·Status; + + typedef enum { + N64·Order_lt = -1 + ,N64·Order_eq = 0 + ,N64·Order_gt = 1 + } N64·Order; + + typedef N64·T *(*N64·Allocate_MemoryFault)(Extent); + + //---------------------------------------- + // Interface + + typedef struct { + + N64·T *(*allocate_array_zero)(Extent, N64·Allocate_MemoryFault); + N64·T *(*allocate_array)(Extent, N64·Allocate_MemoryFault); + void (*deallocate)(N64·T*); + + void (*copy)(N64·T*, N64·T*); + void (*bit_and)(N64·T*, N64·T*, N64·T*); + void (*bit_or)(N64·T*, N64·T*, N64·T*); + void (*bit_complement)(N64·T*, N64·T*); + void (*bit_twos_complement)(N64·T*, N64·T*); + N64·Order (*compare)(N64·T*, N64·T*); + bool (*lt)(N64·T*, N64·T*); + bool (*gt)(N64·T*, N64·T*); + bool (*eq)(N64·T*, N64·T*); + bool (*eq_zero)(N64·T*); + N64·Status (*accumulate)(N64·T *accumulator1, N64·T *accumulator0, ...); + N64·Status (*add)(N64·T*, N64·T*, N64·T*); + bool (*increment)(N64·T *a); + N64·Status (*subtract)(N64·T*, N64·T*, N64·T*); + N64·Status (*multiply)(N64·T*, N64·T*, N64·T*, N64·T*); + N64·Status (*divide)(N64·T*, N64·T*, N64·T*, N64·T*); + N64·Status (*modulus)(N64·T*, N64·T*, N64·T*); + N64·Status (*shift_left)(Extent, N64·T*, N64·T*, N64·T*); + N64·Status (*shift_right)(Extent, N64·T*, N64·T*, N64·T*); + N64·Status (*arithmetic_shift_right)(Extent, N64·T*, N64·T*); + + N64·T* (*access)(N64·T*, Extent); + void (*from_uint64)(N64·T *destination, uint64_t value); + + } N64·M; + + Local const N64·M N64·m; // initialized in the LOCAL section + +#endif + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef N64·IMPLEMENTATION + + // this part goes into the library + #ifndef LOCAL + + #include + #include + + struct N64·T { + Digit d0; + }; + + // For constants, we store them in an array for convenience + // 0, 1, all bits set (~0ULL), and MSB set (1ULL<<63) + N64·T N64·constant[4] = { + {.d0 = 0ULL}, + {.d0 = 1ULL}, + {.d0 = ~(uint64_t)0ULL}, + {.d0 = 1ULL << 63} + }; + + N64·T *N64·zero = &N64·constant[0]; + N64·T *N64·one = &N64·constant[1]; + N64·T *N64·all_one_bit = &N64·constant[2]; + N64·T *N64·msb = &N64·constant[3]; + N64·T *N64·lsb = &N64·constant[1]; + + // allocate an array of N64 + N64·T *N64·allocate_array(Extent extent, N64·Allocate_MemoryFault memory_fault){ + N64·T *instance = malloc( (extent + 1) * sizeof(N64·T) ); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + N64·T *N64·allocate_array_zero(Extent extent, N64·Allocate_MemoryFault memory_fault){ + N64·T *instance = calloc(extent + 1, sizeof(N64·T)); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + void N64·deallocate(N64·T *unencumbered){ + free(unencumbered); + } + + #endif + + // This part is included after the library user's code + #ifdef LOCAL + + // instance + + struct N64·T { + Digit d0; + }; + + // local temporary variables + Local N64·T N64·t[4]; + + // allocation references + extern N64·T *N64·allocate_array(Extent, N64·Allocate_MemoryFault); + extern N64·T *N64·allocate_array_zero(Extent, N64·Allocate_MemoryFault); + extern void N64·deallocate(N64·T *); + + // Access array + Local N64·T* N64·access(N64·T *array, Extent index){ + return &array[index]; + } + + Local void N64·from_uint64(N64·T *destination, uint64_t value){ + if(destination == NULL) return; + destination->d0 = value; + } + + // copy + Local void N64·copy(N64·T *destination, N64·T *source){ + if(source == destination) return; + *destination = *source; + } + + // bit operations + + Local void N64·bit_and(N64·T *result, N64·T *a, N64·T *b){ + result->d0 = a->d0 & b->d0; + } + + Local void N64·bit_or(N64·T *result, N64·T *a, N64·T *b){ + result->d0 = a->d0 | b->d0; + } + + Local void N64·bit_complement(N64·T *result, N64·T *a){ + result->d0 = ~a->d0; + } + + Local void N64·bit_twos_complement(N64·T *result, N64·T *a){ + result->d0 = ~a->d0 + 1ULL; + } + + // compare & test functions + + Local N64·Order N64·compare(N64·T *a, N64·T *b){ + if(a->d0 < b->d0) return N64·Order_lt; + if(a->d0 > b->d0) return N64·Order_gt; + return N64·Order_eq; + } + + Local bool N64·lt(N64·T *a, N64·T *b){ + return (a->d0 < b->d0); + } + + Local bool N64·gt(N64·T *a, N64·T *b){ + return (a->d0 > b->d0); + } + + Local bool N64·eq(N64·T *a, N64·T *b){ + return (a->d0 == b->d0); + } + + Local bool N64·eq_zero(N64·T *a){ + return (a->d0 == 0ULL); + } + + // arithmetic operations + + // accumulate + Local N64·Status N64·accumulate(N64·T *accumulator1, N64·T *accumulator0, ...){ + va_list args; + va_start(args, accumulator0); + + uint64_t sum = accumulator0->d0; + uint64_t carry = 0; + N64·T *current; + + while( (current = va_arg(args, N64·T*)) ){ + uint64_t prior = sum; + sum += current->d0; + if(sum < prior){ // indicates carry + carry++; + // if carry overflowed a 64-bit, that's an accumulator1 overflow + if(carry == 0ULL){ + va_end(args); + return N64·Status·accumulator1_overflow; + } + } + } + va_end(args); + + accumulator1->d0 = carry; + return N64·Status·ok; + } + + // add + Local N64·Status N64·add(N64·T *sum, N64·T *a, N64·T *b){ + __uint128_t result = ( __uint128_t )a->d0 + ( __uint128_t )b->d0; + // But to avoid using a GNU extension, we can do the simpler approach: + // Actually let's do it directly with 64-bit since we only need to detect carry out of 64 bits: + uint64_t temp = a->d0 + b->d0; + sum->d0 = temp; + if(temp < a->d0) return N64·Status·carry; // means we overflowed + return N64·Status·ok; + } + + Local bool N64·increment(N64·T *a){ + uint64_t old = a->d0; + a->d0++; + // if it wrapped around to 0, then it was 0xFFFFFFFFFFFFFFFF + return (a->d0 < old); + } + + // subtract + Local N64·Status N64·subtract(N64·T *difference, N64·T *a, N64·T *b){ + uint64_t tmpA = a->d0; + uint64_t tmpB = b->d0; + uint64_t diff = tmpA - tmpB; + difference->d0 = diff; + if(diff > tmpA) return N64·Status·borrow; // indicates we borrowed + return N64·Status·ok; + } + + // multiply + // We'll do a 64x64->128 using two 64-bit accumulators + Local N64·Status N64·multiply(N64·T *product1, N64·T *product0, N64·T *a, N64·T *b){ + uint64_t A = a->d0; + uint64_t B = b->d0; + + // Break each operand into high & low 32 bits + uint64_t a_lo = (uint32_t)(A & 0xffffffffULL); + uint64_t a_hi = A >> 32; + uint64_t b_lo = (uint32_t)(B & 0xffffffffULL); + uint64_t b_hi = B >> 32; + + // partial products + uint64_t low = a_lo * b_lo; // 64-bit + uint64_t cross = (a_lo * b_hi) + (a_hi * b_lo); // potentially up to 2 * 32 bits => 64 bits + uint64_t high = a_hi * b_hi; // up to 64 bits + + // incorporate cross into low, high + // cross is effectively the middle bits, so shift cross by 32 and add to low + uint64_t cross_low = (cross & 0xffffffffULL) << 32; // lower part + uint64_t cross_high = cross >> 32; // upper part + + // add cross_low to low, capture carry + uint64_t old_low = low; + low += cross_low; + if(low < old_low) cross_high++; + + // final high + high += cross_high; + + // store results + product0->d0 = low; + product1->d0 = high; + + if(high == 0ULL) return N64·Status·one_word_product; + return N64·Status·two_word_product; + } + + // divide + Local N64·Status N64·divide(N64·T *remainder, N64·T *quotient, N64·T *a, N64·T *b){ + // we do not handle a > 64-bit, just the single 64-bit + if(b->d0 == 0ULL) return N64·Status·undefined_divide_by_zero; + + uint64_t divd = a->d0; // dividend + uint64_t divs = b->d0; // divisor + + quotient->d0 = divd / divs; + remainder->d0 = divd - (quotient->d0 * divs); + + return N64·Status·ok; + } + + // modulus + Local N64·Status N64·modulus(N64·T *remainder, N64·T *a, N64·T *b){ + if(b->d0 == 0ULL) return N64·Status·undefined_modulus_zero; + + uint64_t divd = a->d0; + uint64_t divs = b->d0; + uint64_t q = divd / divs; + remainder->d0 = divd - (q * divs); + + return N64·Status·ok; + } + + // bit motion + + typedef uint64_t (*ShiftOp)(uint64_t, uint64_t); + + Local uint64_t shift_left_op(uint64_t value, uint64_t amount){ + return (value << amount); + } + + Local uint64_t shift_right_op(uint64_t value, uint64_t amount){ + return (value >> amount); + } + + // modifies all three of its operands + // in the case of duplicate operands this is the order: first modifies operand, then fill, then spill + Local N64·Status N64·shift + ( + uint64_t shift_count, + N64·T *spill, + N64·T *operand, + N64·T *fill, + ShiftOp shift_op, + ShiftOp complement_shift_op + ){ + if(operand == NULL && spill == NULL) return N64·Status·ok; + + // Treat NULL operand as zero + if(operand == NULL){ + operand = &N64·t[0]; + N64·copy(operand, N64·zero); + } + + // Shifting more than 63 bits breaks fill/spill logic + if(shift_count > 63ULL) return N64·Status·gt_max_shift_count; + + N64·T *given_operand = &N64·t[1]; + N64·copy(given_operand, operand); + + // Perform the shift + operand->d0 = shift_op(given_operand->d0, shift_count); + if(fill != NULL){ + fill->d0 = complement_shift_op(fill->d0, (64ULL - shift_count)); + N64·bit_or(operand, operand, fill); + } + if(spill != NULL){ + spill->d0 = shift_op(spill->d0, shift_count); + spill->d0 += complement_shift_op(given_operand->d0, (64ULL - shift_count)); + } + + return N64·Status·ok; + } + + Local N64·Status N64·shift_left(uint64_t shift_count, N64·T *spill, N64·T *operand, N64·T *fill){ + return N64·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); + } + + Local N64·Status N64·shift_right(uint64_t shift_count, N64·T *spill, N64·T *operand, N64·T *fill){ + return N64·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); + } + + Local N64·Status N64·arithmetic_shift_right(uint64_t shift_count, N64·T *operand, N64·T *spill){ + if(shift_count > 63ULL) return N64·Status·gt_max_shift_count; + + // A NULL operand is treated as zero + if(operand == NULL){ + operand = &N64·t[0]; + N64·copy(operand, N64·zero); + } + + // sign bit check + N64·T *fill = (operand->d0 & (1ULL << 63)) ? N64·all_one_bit : N64·zero; + return N64·shift_right(shift_count, spill, operand, fill); + } + + Local const N64·M N64·m = { + .allocate_array = N64·allocate_array + ,.allocate_array_zero = N64·allocate_array_zero + ,.deallocate = N64·deallocate + + ,.copy = N64·copy + ,.bit_and = N64·bit_and + ,.bit_or = N64·bit_or + ,.bit_complement = N64·bit_complement + ,.bit_twos_complement = N64·bit_twos_complement + ,.compare = N64·compare + ,.lt = N64·lt + ,.gt = N64·gt + ,.eq = N64·eq + ,.eq_zero = N64·eq_zero + ,.accumulate = N64·accumulate + ,.add = N64·add + ,.increment = N64·increment + ,.subtract = N64·subtract + ,.multiply = N64·multiply + ,.divide = N64·divide + ,.modulus = N64·modulus + ,.shift_left = N64·shift_left + ,.shift_right = N64·shift_right + ,.arithmetic_shift_right = N64·arithmetic_shift_right + + ,.access = N64·access + ,.from_uint64 = N64·from_uint64 + }; + + #endif + +#endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/N8.lib.c" "b/developer/deprecated\360\237\226\211/2025-03-29/N8.lib.c" new file mode 100644 index 0000000..df6e01c --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/N8.lib.c" @@ -0,0 +1,433 @@ +/* + N8 - PN = refers to the use of processor native accumulator + + For binary operations: a op b -> c + + See the document on the proper use of the Natural types. + + On the subject of multiple pointers indicating the same location in memory: + + When a routine has multiple results, and one or more of the result location + pointers point to the same storage, the routine will either return an error + status, or have defined behavior. + + When a routine has multiple operands, in any combination, those + pointers can point to the same location, and the routine will + function as advertised. + + When an operand functions as both an input and a result, perhaps due + to a result pointer pointing to the same place as an operand + pointer, the routine will function as advertised. (Internally the + routine might make a temporary copy of the operand to accomplish + this.) +*/ + +#define N8·DEBUG + +#ifndef FACE +#define N8·IMPLEMENTATION +#define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef N8·FACE +#define N8·FACE + + #include + #include + #include + #include + + //---------------------------------------- + // Instance Data (Declaration Only) + + typedef uint8_t Extent; + typedef uint8_t Digit; + + typedef struct N8·T N8·T; + + extern N8·T *N8·zero; + extern N8·T *N8·one; + extern N8·T *N8·all_one_bit; + extern N8·T *N8·lsb; + extern N8·T *N8·msb; + + //---------------------------------------- + // Return/Error Status and handlers + + typedef enum{ + N8·Status·ok = 0 + ,N8·Status·overflow = 1 + ,N8·Status·accumulator1_overflow = 2 + ,N8·Status·carry = 3 + ,N8·Status·borrow = 4 + ,N8·Status·undefined_divide_by_zero = 5 + ,N8·Status·undefined_modulus_zero = 6 + ,N8·Status·gt_max_shift_count = 7 + ,N8·Status·spill_eq_operand = 8 + ,N8·Status·one_word_product = 9 + ,N8·Status·two_word_product = 10 + } N8·Status; + + typedef enum{ + N8·Order_lt = -1 + ,N8·Order_eq = 0 + ,N8·Order_gt = 1 + } N8·Order; + + typedef N8·T *( *N8·Allocate_MemoryFault )(Extent); + + //---------------------------------------- + // Interface + + typedef struct{ + + N8·T *(*allocate_array_zero)(Extent, N8·Allocate_MemoryFault); + N8·T *(*allocate_array)(Extent, N8·Allocate_MemoryFault); + void (*deallocate)(N8·T*); + + void (*copy)(N8·T*, N8·T*); + void (*bit_and)(N8·T*, N8·T*, N8·T*); + void (*bit_or)(N8·T*, N8·T*, N8·T*); + void (*bit_complement)(N8·T*, N8·T*); + void (*bit_twos_complement)(N8·T*, N8·T*); + N8·Order (*compare)(N8·T*, N8·T*); + bool (*lt)(N8·T*, N8·T*); + bool (*gt)(N8·T*, N8·T*); + bool (*eq)(N8·T*, N8·T*); + bool (*eq_zero)(N8·T*); + N8·Status (*accumulate)(N8·T *accumulator1 ,N8·T *accumulator0 ,...); + N8·Status (*add)(N8·T*, N8·T*, N8·T*); + bool (*increment)(N8·T *a); + N8·Status (*subtract)(N8·T*, N8·T*, N8·T*); + N8·Status (*multiply)(N8·T*, N8·T*, N8·T*, N8·T*); + N8·Status (*divide)(N8·T*, N8·T*, N8·T*, N8·T*); + N8·Status (*modulus)(N8·T*, N8·T*, N8·T*); + N8·Status (*shift_left)(Extent, N8·T*, N8·T*, N8·T*); + N8·Status (*shift_right)(Extent, N8·T*, N8·T*, N8·T*); + N8·Status (*arithmetic_shift_right)(Extent, N8·T*, N8·T*); + + N8·T* (*access)(N8·T*, Extent); + void (*from_uint32)(N8·T *destination ,uint32_t value); + } N8·M; + + Local const N8·M N8·m; // initialized in the LOCAL section + +#endif + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef N8·IMPLEMENTATION + + // this part goes into the library + #ifndef LOCAL + + #include + #include + + struct N8·T{ + Digit d0; + }; + + N8·T N8·constant[4] = { + {.d0 = 0}, + {.d0 = 1}, + {.d0 = ~(uint8_t)0}, + {.d0 = 1 << 7} + }; + + N8·T *N8·zero = &N8·constant[0]; + N8·T *N8·one = &N8·constant[1]; + N8·T *N8·all_one_bit = &N8·constant[2]; + N8·T *N8·msb = &N8·constant[3]; + N8·T *N8·lsb = &N8·constant[1]; + + // the allocate an array of N8 + N8·T *N8·allocate_array(Extent extent ,N8·Allocate_MemoryFault memory_fault){ + N8·T *instance = malloc((extent + 1) * sizeof(N8·T)); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + N8·T *N8·allocate_array_zero(Extent extent ,N8·Allocate_MemoryFault memory_fault){ + N8·T *instance = calloc(extent + 1, sizeof(N8·T)); + if(!instance){ + return memory_fault ? memory_fault(extent) : NULL; + } + return instance; + } + + void N8·deallocate(N8·T *unencumbered){ + free(unencumbered); + } + + + #endif + + // This part is included after the library user's code + #ifdef LOCAL + + // instance + + struct N8·T{ + Digit d0; + }; + + // temporary variables + Local N8·T N8·t[4]; + + // allocation + + extern N8·T *N8·allocate_array(Extent, N8·Allocate_MemoryFault); + extern N8·T *N8·allocate_array_zero(Extent, N8·Allocate_MemoryFault); + extern void N8·deallocate(N8·T *); + + // so the user can access numbers in an array allocation + Local N8·T* N8·access(N8·T *array ,Extent index){ + return &array[index]; + } + + Local void N8·from_uint32(N8·T *destination ,uint32_t value){ + if(destination == NULL) return; + destination->d0 = (uint8_t)(value & 0xFF); + } + + // copy, convenience copy + + Local void N8·copy(N8·T *destination ,N8·T *source){ + if(source == destination) return; + *destination = *source; + } + + Local void N8·set_to_zero(N8·T *instance){ + instance->d0 = 0; + } + + Local void N8·set_to_one(N8·T *instance){ + instance->d0 = 1; + } + + // bit operations + + Local void N8·bit_and(N8·T *result, N8·T *a, N8·T *b){ + result->d0 = a->d0 & b->d0; + } + + Local void N8·bit_or(N8·T *result, N8·T *a, N8·T *b){ + result->d0 = a->d0 | b->d0; + } + + Local void N8·bit_complement(N8·T *result, N8·T *a){ + result->d0 = ~a->d0; + } + + Local void N8·bit_twos_complement(N8·T *result ,N8·T *a){ + result->d0 = (uint8_t)(~a->d0 + 1); + } + + // test functions + + Local N8·Order N8·compare(N8·T *a, N8·T *b){ + if(a->d0 < b->d0) return N8·Order_lt; + if(a->d0 > b->d0) return N8·Order_gt; + return N8·Order_eq; + } + + Local bool N8·lt(N8·T *a ,N8·T *b){ + return a->d0 < b->d0; + } + + Local bool N8·gt(N8·T *a ,N8·T *b){ + return a->d0 > b->d0; + } + + Local bool N8·eq(N8·T *a ,N8·T *b){ + return a->d0 == b->d0; + } + + Local bool N8·eq_zero(N8·T *a){ + return a->d0 == 0; + } + + // arithmetic operations + + Local N8·Status N8·accumulate(N8·T *accumulator1 ,N8·T *accumulator0 ,...){ + + va_list args; + va_start(args ,accumulator0); + uint32_t sum = accumulator0->d0; + uint32_t carry = 0; + N8·T *current; + + while( (current = va_arg(args ,N8·T*)) ){ + sum += current->d0; + if(sum < current->d0){ + (carry)++; + if(carry == 0){ + va_end(args); + return N8·Status·accumulator1_overflow; + } + } + } + va_end(args); + + accumulator1->d0 = (uint8_t)carry; + return N8·Status·ok; + } + + Local N8·Status N8·add(N8·T *sum ,N8·T *a ,N8·T *b){ + uint32_t result = (uint32_t)a->d0 + (uint32_t)b->d0; + sum->d0 = (uint8_t)(result & 0xFF); + return (result >> 8) ? N8·Status·carry : N8·Status·ok; + } + + Local bool N8·increment(N8·T *a){ + a->d0++; + return (a->d0 == 0); + } + + Local N8·Status N8·subtract(N8·T *difference ,N8·T *a ,N8·T *b){ + uint32_t diff = (uint32_t)a->d0 - (uint32_t)b->d0; + difference->d0 = (uint8_t)(diff & 0xFF); + return (diff > a->d0) ? N8·Status·borrow : N8·Status·ok; + } + + Local N8·Status N8·multiply(N8·T *product1 ,N8·T *product0 ,N8·T *a ,N8·T *b){ + uint32_t product = (uint32_t)a->d0 * (uint32_t)b->d0; + product0->d0 = (uint8_t)(product & 0xFF); + product1->d0 = (uint8_t)((product >> 8) & 0xFF); + + if(product1->d0 == 0) return N8·Status·one_word_product; + return N8·Status·two_word_product; + } + + Local N8·Status N8·divide(N8·T *remainder ,N8·T *quotient ,N8·T *a ,N8·T *b){ + if(b->d0 == 0) return N8·Status·undefined_divide_by_zero; + + uint32_t dividend = a->d0; + uint32_t divisor = b->d0; + quotient->d0 = (uint8_t)(dividend / divisor); + remainder->d0 = (uint8_t)(dividend - (quotient->d0 * divisor)); + + return N8·Status·ok; + } + + Local N8·Status N8·modulus(N8·T *remainder ,N8·T *a ,N8·T *b){ + if(b->d0 == 0) return N8·Status·undefined_modulus_zero; + uint32_t dividend = a->d0; + uint32_t divisor = b->d0; + uint32_t q = dividend / divisor; + remainder->d0 = (uint8_t)(dividend - (q * divisor)); + return N8·Status·ok; + } + + // bit motion + + typedef uint8_t (*ShiftOp)(uint8_t, uint8_t); + + Local uint8_t shift_left_op(uint8_t value, uint8_t amount){ + return (uint8_t)(value << amount); + } + + Local uint8_t shift_right_op(uint8_t value, uint8_t amount){ + return (uint8_t)(value >> amount); + } + + Local N8·Status N8·shift + ( + uint8_t shift_count + ,N8·T *spill + ,N8·T *operand + ,N8·T *fill + ,ShiftOp shift_op + ,ShiftOp complement_shift_op + ){ + + if(operand == NULL && spill == NULL) return N8·Status·ok; + + if(operand == NULL){ + operand = &N8·t[0]; + N8·copy(operand, N8·zero); + } + + if(shift_count > 7) return N8·Status·gt_max_shift_count; + + N8·T *given_operand = &N8·t[1]; + N8·copy(given_operand, operand); + + operand->d0 = shift_op(given_operand->d0, shift_count); + if(fill != NULL){ + fill->d0 = complement_shift_op(fill->d0, (8 - shift_count)); + N8·bit_or(operand, operand, fill); + } + if(spill != NULL){ + spill->d0 = shift_op(spill->d0, shift_count); + spill->d0 += complement_shift_op(given_operand->d0, (8 - shift_count)); + } + + return N8·Status·ok; + } + + Local N8·Status + N8·shift_left(uint8_t shift_count, N8·T *spill, N8·T *operand, N8·T *fill){ + return N8·shift(shift_count, spill, operand, fill, shift_left_op, shift_right_op); + } + + Local N8·Status + N8·shift_right(uint8_t shift_count, N8·T *spill, N8·T *operand, N8·T *fill){ + return N8·shift(shift_count, spill, operand, fill, shift_right_op, shift_left_op); + } + + Local N8·Status + N8·arithmetic_shift_right(uint8_t shift_count, N8·T *operand, N8·T *spill){ + + if(shift_count > 7) return N8·Status·gt_max_shift_count; + + if(operand == NULL){ + operand = &N8·t[0]; + N8·copy(operand, N8·zero); + } + + N8·T *fill = (operand->d0 & 0x80) ? N8·all_one_bit : N8·zero; + return N8·shift_right(shift_count, spill, operand, fill); + } + + Local const N8·M N8·m = { + + .allocate_array = N8·allocate_array + ,.allocate_array_zero = N8·allocate_array_zero + ,.deallocate = N8·deallocate + + ,.copy = N8·copy + ,.bit_and = N8·bit_and + ,.bit_or = N8·bit_or + ,.bit_complement = N8·bit_complement + ,.bit_twos_complement = N8·bit_twos_complement + ,.compare = N8·compare + ,.lt = N8·lt + ,.gt = N8·gt + ,.eq = N8·eq + ,.eq_zero = N8·eq_zero + ,.accumulate = N8·accumulate + ,.add = N8·add + ,.increment = N8·increment + ,.subtract = N8·subtract + ,.multiply = N8·multiply + ,.divide = N8·divide + ,.modulus = N8·modulus + ,.shift_left = N8·shift_left + ,.shift_right = N8·shift_right + ,.arithmetic_shift_right = N8·arithmetic_shift_right + + ,.access = N8·access + ,.from_uint32 = N8·from_uint32 + }; + + #endif + +#endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/TM_scratch.c" "b/developer/deprecated\360\237\226\211/2025-03-29/TM_scratch.c" new file mode 100644 index 0000000..13b2240 --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/TM_scratch.c" @@ -0,0 +1,65 @@ + // This initializes 'inner'. + // `alignment` is an extent, e.g. extent_of·AU(uint64_t) = 0x7 + Local TM·Status Ξ(TM·NX ,CVT)·largest_aligned( + TM·NX·AU *outer ,Ξ(TM·NX ,CVT) *inner ,extent·AU alignment + ){ + uintptr_t p0 = (uintptr_t)outer->position; + uintptr_t p1 = (uintptr_t)outer->position + outer->extent; + + CVT *p0_aligned = (CVT *)( + (p0 + alignment) & ~( (uintptr_t)alignment ) + ); + CVT *p1_aligned = (CVT *)( + ( p1 - extent_of·AU(CVT) ) & ~( (uintptr_t)alignment ) + ); + + if( p1_aligned < p0_aligned ) return TM·Status·derailed; + + inner->position = p0_aligned; + inner->extent = (Ξ(extent_t ,CVT))(p1_aligned - p0_aligned}; + return TM·Status·on_track; + } + + + + + Local TM·Status TM·NX·topo(TM·NX *tm ,TM·Tape·Topo *topo){ + #ifdef TM·Debug + TM·Guard·init_count(chk); + TM·Guard·fg.check(&chk ,1 ,tm ,TM·NX_##CVT·Msg·tm); + TM·Guard·fg.check(&chk ,1 ,topo ,"topo ptr is NULL, so nowhere to put result"); + TM·Guard·if_return(chk); + #endif + if(tm->extent·AU == 0){ + *topo = TM·Tape·Topo·singleton; + }else{ + *topo = TM·Tape·Topo·segment; + } + return TM·Status·on_track; + } + + // extent·AU is an AU index + Local TM·Status TM·NX·extent·AU(TM·NX *tm ,extent·AU *extent·AU){ + TM·Tape·Topo topo; + TM·Status status = TM·NX_##CVT·topo(tm ,&topo); + boolean good_topo = + (status == TM·Status·on_track) && (topo & TM·Tape·Topo·finite_nz) + ; + + #ifdef TM·Debug + TM·Guard·init_count(chk); + TM·Guard·fg.check(&chk ,1 ,tm ,TM·NX·Msg·tm); + TM·Guard·fg.check(&chk ,1 ,extent·AU ,TM·NX·Msg·extent·AU); + TM·Guard·fg.check( + &chk ,0 ,good_topo + ,"Tape does not exist or topology does not have an extent·AU." + ); + TM·Guard·if_return(chk); + #endif + + if(!good_topo) return TM·Status·derailed; + *extent·AU = tm->array.extent·AU; + return TM·Status·on_track; + } + + #endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/environment.h" "b/developer/deprecated\360\237\226\211/2025-03-29/environment.h" new file mode 100644 index 0000000..cdea83c --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/environment.h" @@ -0,0 +1,5 @@ +#ifndef Mpblock·ENVIRONMENT_H +#define Mpblock·ENVIRONMENT_H + + +#endif diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/test_setup.cli.c" "b/developer/deprecated\360\237\226\211/2025-03-29/test_setup.cli.c" new file mode 100644 index 0000000..f1c6e68 --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/test_setup.cli.c" @@ -0,0 +1,22 @@ +/* + + A placeholder to see if make etc. is working. + +*/ + +#define IFACE +#include +#include + +// No need to define IMPLEMENTATION as `main` is one and done. + +int main(int argc ,char *argv[] ,char *envp[]){ + if(argc != 1){ + fprintf(stderr, "Usage: %s\n", argv[0]); + return EXIT_FAILURE; + } + + fprintf(stderr, "%s done\n", argv[0]); + + return 0; +} diff --git "a/developer/deprecated\360\237\226\211/2025-03-29/update.lib.c" "b/developer/deprecated\360\237\226\211/2025-03-29/update.lib.c" new file mode 100644 index 0000000..61c5cf4 --- /dev/null +++ "b/developer/deprecated\360\237\226\211/2025-03-29/update.lib.c" @@ -0,0 +1,107 @@ +/* + Copy - Memory copy operations with attention to alignment. + Provides optimized copy and byte order reversal functions. +*/ + +#define Copy·DEBUG + +#ifndef FACE +#define Copy·IMPLEMENTATION +#define FACE +#endif + +//-------------------------------------------------------------------------------- +// Interface + +#ifndef Copy·FACE +#define Copy·FACE + + #include + #include + + typedef struct{ + void *read0 + ,size_t read_size + ,void *write0 + ,size_t write_size; + } Copy·it; + + typedef enum{ + Copy·Status·perfect_fit = 0 + ,Copy·Status·argument_guard + ,Copy·Status·read_surplus + ,Copy·Status·read_surplus_write_gap + ,Copy·Status·write_available + ,Copy·Status·write_gap; + } Copy·Status; + + typedef enum{ + Copy·WFIt·Mode·none = 0 + ,Copy·WFIt·Mode·bytes + ,Copy·WFIt·Mode·bytes_reverse + ,Copy·WFIt·Mode·write_hex + ,Copy·WFIt·Mode·read_hex; + } Copy·WFIt·Mode; + + typedef enum{ + Copy·WFIt·Status·valid = 0 + ,Copy·WFIt·Status·null_read + ,Copy·WFIt·Status·null_write + ,Copy·WFIt·Status·zero_buffer + ,Copy·WFIt·Status·overlap + ,Copy·WFIt·Status·write_too_small; + } Copy·WFIt·Status; + + typedef struct{ + void *region( void *read0 ,void *read1 ,void *write0 ) + ,void *reverse_byte_order( void *read0 ,void *read1 ,void *write0 ); + } Copy·M; + +#endif + +//-------------------------------------------------------------------------------- +// Implementation + +#ifdef Copy·IMPLEMENTATION + + // this part goes into Nlib.a + #ifndef LOCAL + #endif + + #ifdef LOCAL + + Local Copy·WFIt·Status Copy·wellformed_it(Copy·it *it){ + char *this_name = "Copy·wellformed_it"; + Copy·WFIt·Status status = Copy·WFIt·Status·valid; + + if(it->read0 == NULL){ + fprintf( stderr ,"%s: NULL read pointer\n" ,this_name ); + status |= Copy·WFIt·Status·null_read; + } + + if(it->write0 == NULL){ + fprintf( stderr ,"%s: NULL write pointer\n" ,this_name ); + status |= Copy·WFIt·Status·null_write; + } + + if(it->read_size == 0){ + fprintf( stderr ,"%s: Zero-sized read buffer\n" ,this_name ); + status |= Copy·WFIt·Status·zero_read_buffer; + } + + if(it->write_size == 0){ + fprintf( stderr ,"%s: Zero-sized write buffer\n" ,this_name ); + status |= Copy·WFIt·Status·zero_write_buffer; + } + + if( Copy·overlap_size_interval(it->read0 ,it->read_size ,it->write0 ,it->write_size) ){ + fprintf( stderr ,"%s: Read and write buffers overlap!\n" ,this_name ); + status |= Copy·WFIt·Status·overlap; + } + + return status; + } + + #endif // LOCAL + +#endif // IMPLEMENTATION diff --git "a/developer/document\360\237\226\211/cpp_evaluation.org" "b/developer/document\360\237\226\211/cpp_evaluation.org" index ba92ca2..b320ac4 100644 --- "a/developer/document\360\237\226\211/cpp_evaluation.org" +++ "b/developer/document\360\237\226\211/cpp_evaluation.org" @@ -29,6 +29,10 @@ In a call, space is allowed between the macro name and the argument list. + Not in strings, not embedded in other tokens. If a macro definition has the same name as the call, then that is a redefinition, an redefinition is not allowed. + + 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 When the macro is invoked: diff --git a/developer/example/0_readme.org b/developer/example/0_readme.org new file mode 100644 index 0000000..d8f8a7d --- /dev/null +++ b/developer/example/0_readme.org @@ -0,0 +1,3 @@ + +To build these standalone edit the tool🖉/makefil and uncommon the SRC=example and the CEFLAGS+= -I/cpp🖉 lines. Then do the usual make clean dependency; make cli + diff --git a/developer/example/bespoke_type.cli.c b/developer/example/bespoke_type.cli.c new file mode 100644 index 0000000..b8de24b --- /dev/null +++ b/developer/example/bespoke_type.cli.c @@ -0,0 +1,74 @@ +/* + This will print at compile time as: + + example/custom_type.cli.c:6:9: note: ‘#pragma message: C -> 7’ + 6 | #pragma message( STR_VAL(C) ) + | ^~~~~~~ + + Note the C->7 on the right side of the first line. That printed + the name of the macro, and its value. This is a 'note' not an 'error'. +*/ + +#include "cpp_ext.c" +#include "Core.lib.c" +#include "Binding.lib.c" + +/* + This defines the Bespoke type. + + 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 + + // 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); + }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); + }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 + +int main(){ + printf("running example binding.cli.c on %s at %s\n", __DATE__, __TIME__); + + #define A 5 + SHOW(A); + + #define B Ξ(X,Y) + SHOW(B); + +#if 0 + Bespoke·FG = { + .version = Bespoke·version + ,.report = Bespoke·report + }; +#endif + + + return 0; +} + +#define IMPLEMENTATION +#define LOCAL + +//#include "../cc🖉/Core.lib.c" +//#include "../cc🖉/Binding.lib.c" diff --git a/developer/example/cpp_ext_0.c b/developer/example/cpp_ext_0.c deleted file mode 100644 index 573c27c..0000000 --- a/developer/example/cpp_ext_0.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - See also - https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h - and tutorial at: http://jhnet.co.uk/articles/cpp_magic - - documents in $REPO_HOME/developer/document🖉 - -1. Provides: - - Raw constants: ZERO, ONE, COMMA, SEMICOLON - - Token tagging: _TWION_0, _TWION_1 - - Controlled concatenation: CAT2, CAT3, CAT4 - - Existence (now EXISTS) with token safety via ## - - Rewrite matchers: MATCH_RWR, NOT_MATCH_RWR - - Logical base: _AND, _OR, _NOT, BOOL, EQ, NOT_EQ - - Structural access: FIRST, REST, SECOND, THIRD - - Branching: IF_ELSE(...), with macro-safe conditioning - - Tests for all major features: try_eq.c, try_access.c, try_3_if.c, etc. - -2. - These are the non-recursive extensions. See cpp_ext_1 for the recursive extensions. - -3. - The 'twion' is cute. It is reminiscent of a complex number in math. Like the complex number that is fed into scalar equestions. The twion is a pair given to functions that only take singletons. - -4. - 0 is false - 1 is true - - Macros starting with an '_' (underscore) are private. - - EQ comparisons apart from logic comparisons, must be registered in advance. They take the form of, EQ____oo__, note comments below. - -5. todo - -cpp_ext as separate project -make the try into tests -make EXISTS true, leave an empty element as false - -IS_LIST to distinguish element from list, though it will be tough to -detect IS_LIST on a list with NOT_EXISTS elements, then a list with all -empty elements is still a list, still exits. - -mv BOOL AND OR -make AND and OR versions of FIND on EXISTS (existence quantification) - -find a better name for NULL_FN - -*/ - -#ifndef CPP_EXT_0 -#define CPP_EXT_0 - -/*=========================================================================== -DEBUG -===========================================================================*/ - -#include -#define DEBUG_CPP -#define STR(...) #__VA_ARGS__ - -// print the macro and the evaluation of the macro -#define SHOW(expr) printf("%s -> %s\n", #expr, STR(expr)) - -/*=========================================================================== -Constants -===========================================================================*/ - -#define COMMA , -#define SEMICOLON ; - -#define FALSE 0 -#define TRUE 1 - -//--------- - -#define _TWION_0 ~,0 -#define _TWION_1 ~,1 - -// RWR == rewrite rule, RWR_ is followed by macro name it is used in `__` -// Matching text is replaced with nothing, making it empty -// Potential for aliasing if x or y values have '__oo__' embedded in them. -#define _RWR_NOT__0 -#define _RWR_AND__1__oo__1 -#define _RWR_OR__0__oo__0 - -// add more of this form to register other equivalences -#define EQ__0__oo__0 -#define EQ__1__oo__1 - -/*=========================================================================== -Primitive Concatenation - Not due to elegance, as `##` is convenient, rather this is - used to force evaluation of arguments before `##`. - There will be a recursive CAT of n things in cpp_ext_1.c -===========================================================================*/ - -#define _CAT2(a ,b) a ## b -#define CAT2(a ,b) _CAT2(a ,b) - -#define _CAT3(a ,b ,c) a ## b ## c -#define CAT3(a ,b ,c) _CAT3(a ,b ,c) - -#define _CAT4(a ,b ,c ,d) a ## b ## c ## d -#define CAT4(a ,b ,c ,d) _CAT4(a ,b ,c ,d) - -#define APPEND(list ,...) list ,__VA_ARGS__ - - - -/*=========================================================================== -Existence -===========================================================================*/ - - //---------------------------------------- - // primitive access - - // note: _FIRST of nothing, _FIRST(), means passing an empty_item as the first item - // so it will return empty. - #define _FIRST(a ,...) a - #define _SECOND(a ,b ,...) b - - //---------------------------------------- - // existence - // - // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro, don't - // replace that with CAT! - - #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1) - #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0##x_item) - - #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item) - #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) ) - - #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0) - #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1##x_item) - - #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item) - #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) ) - - // useful to use with rewrite rules that substitute to nothing - #define MATCH_RWR(x_item) NOT_EXISTS(x_item) - #define NOT_MATCH_RWR(x_item) EXISTS(x_item) - -/*=========================================================================== -Logic Connectors -===========================================================================*/ - - #define _NOT(x_item) \ - MATCH_RWR( CAT2(_RWR_NOT__ ,x_item) ) - - #define _AND(x_item ,y_item) \ - MATCH_RWR( CAT4(_RWR_AND__ ,x_item ,__oo__ ,y_item) ) - - #define _OR(x_item ,y_item) \ - NOT_MATCH_RWR( CAT4(_RWR_OR__ ,x_item ,__oo__ ,y_item) ) - - #define _BOOL(x_item) \ - _AND( \ - EXISTS_ITEM( x_item ) \ - ,NOT_MATCH_RWR( CAT2(EQ__0__oo__ ,x_item) ) \ - ) - #define BOOL(x_item) _BOOL(_FIRST(x_item)) - - #define NOT(x_item) _NOT(BOOL(x_item)) - #define AND(x_item ,y_item) _AND(BOOL(x_item) ,BOOL(y_item)) - #define OR(x_item ,y_item) _OR(BOOL(x_item) ,BOOL(y_item)) - -/*=========================================================================== - Equality - - more general than a connector because more rules can be added. - - each registered equality rule has the form - EQ____oo__ - for example, logic equalities are already registered: - EQ__0__oo__0 - EQ__1__oo__1 - -===========================================================================*/ - - #define EQ(x_item ,y_item) \ - MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) ) - - #define NOT_EQ(x_item ,y_item) \ - NOT_MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) ) - -/*=========================================================================== - IF-ELSE construct. - Usage: IF_ELSE(condition)()() - - A most amazing little macro. It has no dependencies on the other macros - in this file, though many will be useful for setting (condition) - - The seemingly extra layer prevents BOOL_(condition) from being pasted with a ## which, if done, would prevent it from being evaluated. Recall, the first step in evaluation is a literal copy in of the arguments. ===symbol ========================================================================*/ - - #define IF(predicate) CAT2(_IF_ ,BOOL(predicate)) - #define _IF_1(...) __VA_ARGS__ _IF_1_ELSE - #define _IF_0(...) _IF_0_ELSE - #define _IF_1_ELSE(...) - #define _IF_0_ELSE(...) __VA_ARGS__ - -/*=========================================================================== -Access - see ext_1 with recursion for `Nth` - -===========================================================================*/ - - // _FIRST defined in the logic section - #define FIRST(pad ,...)\ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - (pad) \ - ( _FIRST(__VA_ARGS__) ) - - #define _REST(a ,...) __VA_ARGS__ - #define REST(...)\ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - () \ - ( _REST(__VA_ARGS__) ) - - // _SECOND defined in the logic section - #define SECOND(pad ,...) \ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - (pad) \ - ( _SECOND(__VA_ARGS__ ,pad) ) - - #define _THIRD(a ,b ,c ,...) c - #define THIRD(pad ,...) \ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - (pad) \ - ( _THIRD(__VA_ARGS__ ,pad, pad) ) - -#endif diff --git a/developer/example/cpp_ext_1.c b/developer/example/cpp_ext_1.c deleted file mode 100644 index bc241d7..0000000 --- a/developer/example/cpp_ext_1.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -These are the recursive extension. - -Simple errors can lead to very long error outputs, which might be why -the cpp designers had obviously intended that recursion would not be possible. - -To be added: - -LIST_TOO_LONG - -// scanning left to right finds first that exists -LEFTMOST_EXISTENT - -// scanning left to right finds last that exits -RIGHTMOST_EXISTENT - -DROP_NOT_EXISTS_ALL -DROP_NOT_EXISTS_LEFT -DROPE_NOT_EXISTS_RIGHT - -#define _CAT(sep,first,...) \ - -*/ - -#ifndef CPP_EXT_1 -#define CPP_EXT_1 - -/*=========================================================================== - Force extra macro expansion (the EVAL trick) - This chain of EVAL macros forces the preprocessor to perform many rescans, - which is necessary to “unroll” recursive macros. -===========================================================================*/ -//#define EVAL(...) EVAL1024(__VA_ARGS__) -#define EVAL(...) EVAL32(__VA_ARGS__) -#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__)) -#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__)) -#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__)) -#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__)) -#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__)) -#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) -#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) -#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) -#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) -#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) -#define EVAL1(...) __VA_ARGS__ - -/*=========================================================================== - Defer macros: these help “hide” recursive calls for additional expansion passes. -===========================================================================*/ -#define NULL_FN() -#define DEFER1(m) m NULL_FN() -#define DEFER2(m) m NULL_FN NULL_FN()() -#define DEFER3(m) m NULL_FN NULL_FN NULL_FN()()() -#define DEFER4(m) m NULL_FN NULL_FN NULL_FN NULL_FN()()()() - -/*=========================================================================== - Quantifiers -===========================================================================*/ - -#define _FIND(predicate ,...) \ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - () \ - (IF \ - ( predicate(FIRST(__VA_ARGS__)) ) \ - ( FIRST( ,__VA_ARGS__) ) \ - ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ - ) -#define _FIND_CONFEDERATE() _FIND - -// number of evals required depends upon length of not found list prefix -#define FIND(predicate ,...) EVAL( _FIND(predicate ,__VA_ARGS__) ) - -#define _FIND_ITEM(item ,...) \ - IF \ - ( NOT_EXISTS(__VA_ARGS__) ) \ - () \ - (IF \ - ( EQ(item ,FIRST(__VA_ARGS__)) ) \ - ( FIRST( ,__VA_ARGS__) ) \ - ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ - ) -#define _FIND_ITEM_CONFEDERATE() _FIND_ITEM - -// number of evals required depends upon length of not found list prefix -#define FIND_ITEM(predicate ,...) EVAL( _FIND_ITEM(predicate ,__VA_ARGS__) ) - - - -#endif diff --git a/developer/example/example_A.c b/developer/example/example_A.c deleted file mode 100644 index edc81c6..0000000 --- a/developer/example/example_A.c +++ /dev/null @@ -1,34 +0,0 @@ -// from http://jhnet.co.uk/articles/cpp_magic - -#include -#define STR(x) #x -#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) - -#define NULL_FN() -#define EVAL1(...) __VA_ARGS__ - -#define A(n) I like the number n - - -int main(){ - - printf( - " I like the number 123\n" - " A (123)\n" - ); - SHOW(A (123)); - SHOW(A NULL_FN() (123)); - printf("\n"); - - printf( - " I like the number 123\n" - ); - SHOW(EVAL1(A NULL_FN() (123))); - printf("\n"); - - - /* - ... The reason this works is that when CPP encounters a function-style macro, it recursively expands the macro's arguments before substituting the macro's body and expanding that. ... - */ - -}; diff --git a/developer/example/example_eval.c b/developer/example/example_eval.c deleted file mode 100644 index e60af83..0000000 --- a/developer/example/example_eval.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#define STR(x) #x -#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) - -int main(void){ - printf("example_eval.c\n"); - - #define NULL_FN() - #define NEGATE(x) -x - #define NOT_SO_FAST(x) NEGATE NULL_FN() (x) - SHOW(NOT_SO_FAST(5)); - - #define BE(x) x - SHOW(BE(NOT_SO_FAST(5))) -} - -/* - 2025-03-27T04:47:02Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > gcc example_eval.c - - 2025-03-27T04:47:32Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > ./a.out - example_eval.c - NOT_SO_FAST(5) → NEGATE (5) - BE(NOT_SO_FAST(5)) → -5 - -*/ diff --git a/developer/example/example_grow.c b/developer/example/example_grow.c deleted file mode 100644 index 74f3cca..0000000 --- a/developer/example/example_grow.c +++ /dev/null @@ -1,121 +0,0 @@ -#include -#define STR(x) #x -// no evaluation, and one pass of evaluation -#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) - -#define BE(...) __VA_ARGS__ -#define NULL_FN() - -#include -int main(void){ - printf("example_grow.c\n"); - printf("\n"); - - // case 1 - /* - GROW(7) → 17 * GROW(7) - GROW(GROW(5)) → 17 * GROW(17 * GROW(5)) - */ - #define GROW(x) 17 * GROW(x) - SHOW(GROW(7)); - SHOW(GROW(GROW(5))); - printf("\n"); - - // case 2 - // GROW2(11) --> 19 * GROW2 (11) - #define GROW2(x) 19 * GROW2 NULL_FN() (x) - SHOW(GROW2(11)) ; - printf("\n"); - - // case 3 - // GROW3(13) --> 119 * 19 * GROW2 (13) - #define GROW3(x) BE(119 * GROW2 NULL_FN() (x)) - SHOW(GROW3(13)); - printf("\n"); - - // case 4 - /* - `BE` placed on the outside. The idea is that evaluation will return `123 * GROW (15)` and then this will be evaluated resulting in `123 * 123 * GROW(15)`. - - However, any time GROW4 literally spells out GROW4(...) inside its own expansion - it will leave it literally and not expand it. - - Though it is interesting that here that occurs at a higher level in the evaluation tree than the first ocurrance of the recursive call, but still it is in the tree. - - GROW4(15) --> 123 * GROW4 (15) - */ - #define GROW4(x) BE(123 * GROW4 NULL_FN() (x)) - SHOW(GROW4(15)); - printf("\n"); - - // case 5 - /* - Substitution of the function named followed by a trampoline works. - - The original expression is written in terms of a deferred CONDFEDERATE function - instead of in terms of a recursive call to GROW5. cpp can suspect nothing. - - The result is an expression in terms of the unevaluated CONDFEDERATE function. - - The CONFEDERATE function is defined to return the token GROW5. Hence in a subsequent evaluation, and there must be a subsequent evaluation for this to work, The CONFEDERATE function will run, return GROW5 which is next to its call parenthesis, so then the - recursive call will run. - - BE(GROW5(21)) --> 541 * 541 * CONFEDERATE () (21) - BE(BE(GROW5(57))) --> 541 * 541 * 541 * CONFEDERATE () (57) - */ - #define GROW5(x) 541 * CONFEDERATE NULL_FN() () (x) - #define CONFEDERATE() GROW5 - SHOW(BE(GROW5(21))); - SHOW(BE(BE(GROW5(57)))); - printf("\n"); - - // case 6 - /* - Once a recursively called function is marked, or 'colored' it can never be expanded, even when passed through to another variable and separately evaluation. - */ - #define GROW6(x) 1029 * GROW6 NULL_FN() (x) - #define RESULT1 GROW6(51) - SHOW(RESULT1); - SHOW(BE(RESULT1)); - printf("\n"); - // RESULT1 --> 1029 * GROW6 (51) - // BE(RESULT1) --> 1029 * GROW6 (51) - - // case 7 - #define RESULT2 GROW6(151) - SHOW(RESULT2); - SHOW(BE(RESULT2)); - printf("\n"); - // RESULT2 --> 1029 * GROW6 (151) - // BE(RESULT2) --> 1029 * GROW6 (151) - -} -/* - 2025-03-27T10:45:39Z[developer] -Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ -> gcc example_grow.c - -2025-03-27T11:43:19Z[developer] -Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ -> ./a.out -example_grow.c - -GROW(7) --> 17 * GROW(7) -GROW(GROW(5)) --> 17 * GROW(17 * GROW(5)) - -GROW2(11) --> 19 * GROW2 (11) - -GROW3(13) --> 119 * 19 * GROW2 (13) - -GROW4(15) --> 123 * GROW4 (15) - -BE(GROW5(21)) --> 541 * 541 * CONFEDERATE () (21) -BE(BE(GROW5(57))) --> 541 * 541 * 541 * CONFEDERATE () (57) - -RESULT1 --> 1029 * GROW6 (51) -BE(RESULT1) --> 1029 * GROW6 (51) - -RESULT2 --> 1029 * GROW6 (151) -BE(RESULT2) --> 1029 * GROW6 (151) - -*/ diff --git a/developer/example/example_grow2.c b/developer/example/example_grow2.c deleted file mode 100644 index a421469..0000000 --- a/developer/example/example_grow2.c +++ /dev/null @@ -1,29 +0,0 @@ -#include - -#define STR(...) #__VA_ARGS__ -// no evaluation, and one pass of evaluation -#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) - -#define BE(...) __VA_ARGS__ - -#define NULL_FN() -#define GROW(x) 19 * _GROW NULL_FN() ()(x) -#define _GROW() GROW - - -int main(void) -{ - printf("One-trampoline minimal example:\n\n"); - - //19 * _GROW ()(7) - SHOW(GROW(7)); - - // 19 * 19 * _GROW ()(7) - SHOW(BE(GROW(7))); - - // 19 * 19 * 19 * _GROW ()(7) - SHOW(BE(BE(GROW(7)))); - - - return 0; -} diff --git a/developer/example/example_recurse.c b/developer/example/example_recurse.c deleted file mode 100644 index 5a4b4e0..0000000 --- a/developer/example/example_recurse.c +++ /dev/null @@ -1,54 +0,0 @@ -// from http://jhnet.co.uk/articles/cpp_magic - -#include - -#define STR(...) #__VA_ARGS__ -// no evaluation, and one pass of evalutation -#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) - -#define NULL_FN() - -#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) -#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) -#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) -#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) -#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) -#define EVAL1(...) __VA_ARGS__ - -#define DEFER1(m) m NULL_FN() - -#define RECURSE() I am recursive, look: DEFER1(_RECURSE)()() -#define _RECURSE() RECURSE - - -int main(){ - - printf( - "No EVAL:\n" - " RECURSE()\n" - ); - SHOW(RECURSE()); - printf("\n"); - - printf( - "With EVAL1:\n" - " EVAL1(RECURSE())\n" - ); - SHOW(EVAL1(RECURSE())); - printf("\n"); - - printf( - "With EVAL2:\n" - " EVAL2(RECURSE())\n" - ); - SHOW(EVAL2(RECURSE())); - printf("\n"); - - printf( - "With EVAL32:\n" - " EVAL32(RECURSE())\n" - ); - SHOW(EVAL32(RECURSE())); - printf("\n"); - -}; diff --git a/developer/example/try_1_exists.c b/developer/example/try_1_exists.c deleted file mode 100644 index 5b52fb3..0000000 --- a/developer/example/try_1_exists.c +++ /dev/null @@ -1,110 +0,0 @@ -#include "cpp_ext_0.c" - -#define F 1 -#define O1 2 -#define O2 3 -#define B 4 -#define A 5 -#define R 6 -#define D 7 - - -// Patch for _EXISTS to succeed on 0 -#define _REWRITE_TWION_0 _REWRITE_TWION - -int main(void){ - printf("try_1_exists\n\n"); - - // Constant macros - int x COMMA y = 1; // Tests that COMMA = , - printf("y? %d\n", y); - printf("\n"); - - // Token paste test - int _cat_result = CAT2(CAT3(F ,O1 ,O2) ,CAT4(B ,A ,R ,D)); - printf("FOOBARD %d\n" ,_cat_result); - printf("\n"); - - // Selector macros - int first = _FIRST(11 ,22 ,33); // → 11 - int second = _SECOND(11 ,22 ,33); // → 22 - printf("_FIRST(11 ,22 ,33) = %d\n", first); - printf("_SECOND(11 ,22 ,33) = %d\n", second); - printf("\n"); - - // Existence detection - int empty = EXISTS_ITEM(); // → 1 (rewrite hits) - int empty_0 = EXISTS_ITEM(0); // → 1 (rewrite hits) - int empty_1 = EXISTS_ITEM(1); // → 0 (no rewrite) - int empty_f = EXISTS_ITEM(hello); // → 0 - - printf("EXISTS_ITEM() = %d\n", empty); - printf("EXISTS_ITEM(0) = %d\n", empty_0); - printf("EXISTS_ITEM(1) = %d\n", empty_1); - printf("EXISTS_ITEM(hello) = %d\n", empty_f); - printf("\n"); - - // Not Existence detection - empty = NOT_EXISTS_ITEM(); // → 1 (rewrite hits) - empty_0 = NOT_EXISTS_ITEM(0); // → 1 (rewrite hits) - empty_1 = NOT_EXISTS_ITEM(1); // → 0 (no rewrite) - empty_f = NOT_EXISTS_ITEM(hello); // → 0 - - printf("NOT_EXISTS_ITEM() = %d\n", empty); - printf("NOT_EXISTS_ITEM(0) = %d\n", empty_0); - printf("NOT_EXISTS_ITEM(1) = %d\n", empty_1); - printf("NOT_EXISTS_ITEM(hello) = %d\n", empty_f); - printf("\n"); - - - // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error - int empty_11 = EXISTS(10,11,12); // this is a legal call - int empty_12 = EXISTS(); - - // printf("EXISTS_ITEM(10,11,12) = %d\n", empty_10); - printf("EXISTS(10,11,12) = %d\n", empty_11); - printf("EXISTS() = %d\n", empty_12); - printf("\n"); - - // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error - empty_11 = NOT_EXISTS(10,11,12); // this is a legal call - empty_12 = NOT_EXISTS(); - - // printf("NOT_EXISTS_ITEM(10,11,12) = %d\n", empty_10); - printf("NOT_EXISTS(10,11,12) = %d\n", empty_11); - printf("NOT_EXISTS() = %d\n", empty_12); - printf("\n"); - - - return 0; -} - -/* - 2025-03-27T12:38:04Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > gcc try_1_exists.c - - 2025-03-27T12:40:32Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > ./a.out - _CAT(FOO ,BAR) → 12345 - - _FIRST(11 ,22 ,33) = 11 - _SECOND(11 ,22 ,33) = 22 - - EXISTS_ITEM() = 0 - EXISTS_ITEM(0) = 1 - EXISTS_ITEM(1) = 1 - EXISTS_ITEM(hello) = 1 - - NOT_EXISTS_ITEM() = 1 - NOT_EXISTS_ITEM(0) = 0 - NOT_EXISTS_ITEM(1) = 0 - NOT_EXISTS_ITEM(hello) = 0 - - EXISTS(10,11,12) = 1 - EXISTS() = 0 - - NOT_EXISTS(10,11,12) = 0 - NOT_EXISTS() = 1 -*/ diff --git a/developer/example/try_2_connectors.c b/developer/example/try_2_connectors.c deleted file mode 100644 index 1e99ee3..0000000 --- a/developer/example/try_2_connectors.c +++ /dev/null @@ -1,200 +0,0 @@ -#include "cpp_ext_0.c" - -int main(void){ - - //-------------------------------------------------------------------------- - // Existence Checks (sanity anchor) - //-------------------------------------------------------------------------- - - #define x0 - SHOW( EXISTS_ITEM(x0) ); // → 0 (assumed undefined) - SHOW( NOT_EXISTS_ITEM(x0) ); // → 1 - printf("\n"); - - SHOW( MATCH(x0) ); - SHOW( NOT_MATCH(x0) ); - printf("\n"); - - //-------------------------------------------------------------------------- - // Primitive Connectors - //-------------------------------------------------------------------------- - - SHOW( _NOT(0) ); // _RWR_NOT_0 is defined → MATCH → 1 - SHOW( _NOT(1) ); // no rule → MATCH fails → 0 - printf("\n"); - - SHOW( _AND(0 ,0) ); // rule defined → MATCH → 1 - SHOW( _AND(1 ,0) ); // rule defined → MATCH → 1 - SHOW( _AND(0 ,1) ); // rule defined → MATCH → 1 - SHOW( _AND(1 ,1) ); // rule defined → MATCH → 1 - SHOW( _AND(1 ,x) ); // not legal args, but worked, rule missing → MATCH fails → 0 - printf("\n"); - - SHOW( _OR(0 ,0) ); // rule defined → NOT_MATCH → 0 - SHOW( _OR(0 ,1) ); // rule missing → NOT_MATCH → 1 - SHOW( _OR(1 ,0) ); // rule missing → NOT_MATCH → 1 - SHOW( _OR(1 ,1) ); // rule missing → NOT_MATCH → 1 - printf("\n"); - - //-------------------------------------------------------------------------- - // Logical Connectors (BOOL + AND/OR/NOT) - //-------------------------------------------------------------------------- - - printf("x0 is a macro with an empty definition"); - - SHOW( _BOOL(0) ); // 0 - SHOW( _BOOL(1) ); // 1 - SHOW( _BOOL(2) ); // 1 because it exists - SHOW( _BOOL(x0) ); // 0 because it does not exit (see the #define at the top) - printf("\n"); - - SHOW( BOOL(0) ); // _FIRST = 0, EXISTS_ITEM(_FIRST) = 0 → _AND(0 ,1) → 0 - SHOW( BOOL(1) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 - SHOW( BOOL(10) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 - SHOW( BOOL() ); // EXISTS_ITEM(1) = 0 → BOOL = 0 - SHOW( BOOL(x0) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 - printf("\n"); - - SHOW( NOT(0) ); // BOOL = 0 → NOT(0) = _NOT(0) = 1 - SHOW( NOT(1) ); // BOOL = 0 → NOT(0) = 1 - SHOW( NOT() ); // BOOL = 0 → NOT(0) = 1 - SHOW( NOT(10) ); // BOOL = 0 → NOT(0) = 1 - printf("\n"); - - SHOW( AND(1 ,0) ); // 0 - SHOW( AND(1 ,1) ); // BOOL(1), BOOL(1) = 0,0 → AND(0 ,0) = _AND(0 ,0) = 1 - printf("\n"); - - SHOW( OR(0 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0 - SHOW( OR(1 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0 - printf("\n"); - - //-------------------------------------------------------------------------- - // Compound Connectors - //-------------------------------------------------------------------------- - - // Double NOT - SHOW( NOT(NOT(0)) ); // → NOT(1) → _NOT(1) → 0 - SHOW( NOT(NOT(1)) ); // → NOT(0) → _NOT(0) → 1 - - // Triple NOT - SHOW( NOT(NOT(NOT(0))) ); // → NOT(0) → _NOT(0) → 1 - SHOW( NOT(NOT(NOT(1))) ); // → NOT(1) → _NOT(1) → 0 - printf("\n"); - - // Nested AND - SHOW( AND(1 ,AND(1 ,0)) ); // AND(1 ,AND(1 ,0)) → AND(1 ,0) → _AND(1 ,0) = 0 - SHOW( AND(1 ,AND(1 ,1)) ); // → AND(1 ,1) → _AND(1 ,1) = 1 - printf("\n"); - - // Nested OR - SHOW( OR(0 ,OR(0 ,1)) ); // → OR(0 ,1) → _OR(0 ,1) = 1 - SHOW( OR(0 ,OR(0 ,0)) ); // → OR(0 ,0) → _OR(0 ,0) = 0 - printf("\n"); - - // Mixed nesting - SHOW( AND(NOT(0) ,1) ); // → AND(1 ,1) → _AND(1 ,1) = 1 - SHOW( AND(NOT(1) ,1) ); // → AND(0 ,1) → _AND(0 ,1) = 0 - SHOW( OR(NOT(1) ,1) ); // → OR(0 ,1) → _OR(0 ,1) = 1 - SHOW( OR(NOT(0) ,0) ); // → OR(1 ,0) → _OR(1 ,0) = 1 - printf("\n"); - - // Deep mix - SHOW( NOT(AND(1 ,NOT(1))) ); // AND(1 ,0) = _AND(1 ,0) = 0 → NOT(0) = _NOT(0) = 1 - SHOW( NOT(OR(0 ,NOT(0))) ); // OR(0 ,1) = _OR(0 ,1) = 1 → NOT(1) = _NOT(1) = 0 - printf("\n"); - - // Asymmetric nesting - SHOW( AND(OR(0 ,1) ,AND(1 ,1)) ); // OR(0 ,1) = 1, AND(1 ,1) = 1 → AND(1 ,1) = 1 - SHOW( OR(AND(1 ,0) ,AND(1 ,1)) ); // AND(1 ,0) = 0, AND(1 ,1) = 1 → OR(0 ,1) = 1 - printf("\n"); - - return 0; -} -/* - 2025-03-27T12:59:39Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > gcc try_2_connectors.c - - 2025-03-27T13:00:11Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > ./a.out - EXISTS_ITEM(x0) --> 0 - NOT_EXISTS_ITEM(x0) --> 1 - - MATCH(x0) --> MATCH() - NOT_MATCH(x0) --> NOT_MATCH() - - _NOT(0) --> 1 - _NOT(1) --> 0 - - _AND(0 ,0) --> 0 - _AND(1 ,0) --> 0 - _AND(0 ,1) --> 0 - _AND(1 ,1) --> 1 - _AND(1 ,x) --> 0 - - _OR(0 ,0) --> 0 - _OR(0 ,1) --> 1 - _OR(1 ,0) --> 1 - _OR(1 ,1) --> 1 - - _EQ(0 ,0) --> 1 - _EQ(1 ,1) --> 1 - _EQ(0 ,1) --> 0 - _EQ(x ,x) --> 0 - - _NOT_EQ(0 ,1) --> 1 - _NOT_EQ(0 ,0) --> 0 - - _BOOL_2(0) --> 0 - _BOOL_2(1) --> 1 - _BOOL_2(2) --> 1 - _BOOL_2(x0) --> 0 - - BOOL(0) --> 0 - BOOL(1) --> 1 - BOOL(10) --> 1 - BOOL() --> 0 - BOOL(x0) --> 0 - - NOT(0) --> 1 - NOT(1) --> 0 - NOT() --> 1 - NOT(10) --> 0 - - AND(1 ,0) --> 0 - AND(1 ,1) --> 1 - - OR(0 ,0) --> 0 - OR(1 ,0) --> 1 - - NOT(NOT(0)) --> 0 - NOT(NOT(1)) --> 1 - NOT(NOT(NOT(0))) --> 1 - NOT(NOT(NOT(1))) --> 0 - - AND(1 ,AND(1 ,0)) --> 0 - AND(1 ,AND(1 ,1)) --> 1 - - OR(0 ,OR(0 ,1)) --> 1 - OR(0 ,OR(0 ,0)) --> 0 - - AND(NOT(0) ,1) --> 1 - AND(NOT(1) ,1) --> 0 - OR(NOT(1) ,1) --> 1 - OR(NOT(0) ,0) --> 1 - - NOT(AND(1 ,NOT(1))) --> 1 - NOT(OR(0 ,NOT(0))) --> 0 - - AND(OR(0 ,1) ,AND(1 ,1)) --> 1 - OR(AND(1 ,0) ,AND(1 ,1)) --> 1 - - - 2025-03-27T13:00:12Z[developer] - Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ - > -*/ - - diff --git a/developer/example/try_3_eq.c b/developer/example/try_3_eq.c deleted file mode 100644 index 6cb8aaf..0000000 --- a/developer/example/try_3_eq.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "cpp_ext_0.c" - -int main(void){ - - //--------------------------------------------------------------------------- - // EQ Tests — identity and mismatch - //--------------------------------------------------------------------------- - - SHOW(EQ(0 ,0)); // Expected → 1 - SHOW(EQ(1 ,1)); // Expected → 1 - SHOW(EQ(0 ,1)); // Expected → 0 - SHOW(EQ(1 ,0)); // Expected → 0 - - SHOW(EQ(x ,x)); // Expected → 0 (no _RWREQ__x__oo__x defined) - SHOW(EQ(x ,y)); // Expected → 0 - - //--------------------------------------------------------------------------- - // NOTEQ Tests — inverse behavior - //--------------------------------------------------------------------------- - - SHOW(NOT_EQ(0 ,0)); // Expected → 0 (because EQ → 1, so EXISTS → 0) - SHOW(NOT_EQ(1 ,1)); // Expected → 0 - SHOW(NOT_EQ(0 ,1)); // Expected → 1 - SHOW(NOT_EQ(1 ,0)); // Expected → 1 - - SHOW(NOT_EQ(x ,x)); // Expected → 1 (EQ not defined → NOTEQ = 1) - SHOW(NOT_EQ(x ,y)); // Expected → 1 - - //--------------------------------------------------------------------------- - // Mixed cases with macros - //--------------------------------------------------------------------------- - - #define XSYM 0 - #define YSYM 1 - - SHOW(EQ(XSYM ,XSYM)); // Expected → 1 (0,0) - SHOW(EQ(XSYM ,YSYM)); // Expected → 0 (0,1) - SHOW(NOT_EQ(XSYM ,YSYM)); // Expected → 1 - - SHOW(EQ(XSYM ,0)); // Expected → 1 - SHOW(EQ(XSYM ,1)); // Expected → 0 - - SHOW(NOT_EQ(YSYM ,0)); // Expected → 1 - SHOW(NOT_EQ(YSYM ,1)); // Expected → 0 - - //--------------------------------------------------------------------------- - // Edge case: undefined symbol - //--------------------------------------------------------------------------- - - SHOW(EQ(z ,z)); // Expected → 0 - SHOW(NOT_EQ(z ,z)); // Expected → 1 - - printf("\n"); - return 0; -} diff --git a/developer/example/try_4_if.c b/developer/example/try_4_if.c deleted file mode 100644 index cdb60e6..0000000 --- a/developer/example/try_4_if.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "cpp_ext_0.c" - -int main(void){ - - //--------------------------------------------------------------------------- - // Basic boolean cases - //--------------------------------------------------------------------------- - - SHOW(IF_ELSE(1)(yes)(no)); - SHOW(IF_ELSE(0)(yes)(no)); // → no - printf("\n"); - - //--------------------------------------------------------------------------- - // Symbolic identifiers - //--------------------------------------------------------------------------- - SHOW(IF_ELSE(TRUE)(ok)(fail)); // → ok - SHOW(IF_ELSE(FALSE)(ok)(fail)); // → fail - SHOW(IF_ELSE(foo)(alpha)(omega)); // → omega (foo is undefined) - printf("\n"); - - //--------------------------------------------------------------------------- - // Logic expressions - //--------------------------------------------------------------------------- - SHOW(IF_ELSE(AND(1 ,1))(pass)(fail)); // → pass - SHOW(IF_ELSE(OR(0 ,0))(yes)(no)); // → no - SHOW(IF_ELSE(NOT(0))(on)(off)); // → on - printf("\n"); - - //--------------------------------------------------------------------------- - // Code-like output - //--------------------------------------------------------------------------- - SHOW(IF_ELSE(1)(int x = 1;)(int x = 2;)); // → int x = 1; - SHOW(IF_ELSE(0)(int x = 1;)(int x = 2;)); // → int x = 2; - printf("\n"); - - //--------------------------------------------------------------------------- - // Comma usage in true/false branches - //--------------------------------------------------------------------------- - SHOW(IF_ELSE(1)(a ,b ,c)(x ,y ,z)); // → a ,b ,c - SHOW(IF_ELSE(0)(a ,b ,c)(x ,y ,z)); // → x ,y ,z - printf("\n"); - - //--------------------------------------------------------------------------- - // Empty condition - //--------------------------------------------------------------------------- - SHOW(IF_ELSE()(true)(false)); // → false (BOOL() = 0) - printf("\n"); - - //--------------------------------------------------------------------------- - // Nested IF_ELSE - //--------------------------------------------------------------------------- - SHOW( - IF_ELSE(AND(1 ,1))( - IF_ELSE(0)(inner_true)(inner_false) - )( - outer_false - ) - ); // → inner_false - printf("\n"); - - return 0; -} diff --git a/developer/example/try_5_access.c b/developer/example/try_5_access.c deleted file mode 100644 index e9db0ae..0000000 --- a/developer/example/try_5_access.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "cpp_ext_0.c" - -int main(void){ - - //--------------------------------------------------------------------------- - // FIRST - //--------------------------------------------------------------------------- - - SHOW(FIRST(foo)); // → foo (only pad, no args) - SHOW(FIRST(foo ,a)); // → a - SHOW(FIRST(foo ,a ,b ,c)); // → a - printf("\n"); - - //--------------------------------------------------------------------------- - // REST - //--------------------------------------------------------------------------- - - SHOW(REST()); // → (empty) - SHOW(REST(a)); // → (empty) - SHOW(REST(a ,b)); // → b - SHOW(REST(a ,b ,c ,d)); // → b ,c ,d - printf("\n"); - - //--------------------------------------------------------------------------- - // SECOND - //--------------------------------------------------------------------------- - - SHOW(SECOND(X)); // → X (only pad) - SHOW(SECOND(X ,a)); // → X (only one arg, fallback to pad) - SHOW(SECOND(X ,a ,b)); // → b - SHOW(SECOND(X ,a ,b ,c)); // → b - printf("\n"); - - //--------------------------------------------------------------------------- - // THIRD - //--------------------------------------------------------------------------- - - SHOW(THIRD(X)); // → X (pad returned) - SHOW(THIRD(X ,a)); // → X - SHOW(THIRD(X ,a ,b)); // → X - SHOW(THIRD(X ,a ,b ,c)); // → c - SHOW(THIRD(X ,a ,b ,c ,d)); // → c - printf("\n"); - - return 0; -} diff --git a/developer/example/try_6_list.c b/developer/example/try_6_list.c deleted file mode 100644 index 2bcc339..0000000 --- a/developer/example/try_6_list.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "cpp_ext_0.c" -#include "cpp_ext_1.c" - -#define LIST int ,float ,char ,void - -// register equality -#define EQ__int__oo__int -#define EQ__float__oo__float -#define EQ__char__oo__char -#define EQ__void__oo__void - -// make predicates -#define IS_int(x) EQ(x ,int) -#define IS_float(x) EQ(x ,float) -#define IS_double(x) EQ(x ,double) -#define IS_char(x) EQ(x ,char) -#define IS_void(x) EQ(x ,void) - -int main(void){ - -#define BE(...) __VA_ARGS__ - - SHOW(IS_char(int)); - SHOW(IS_char(char)); - printf("\n"); - - SHOW( FIND(IS_char ,) ); - SHOW( FIND(IS_char ,char) ); // → char - SHOW( FIND(IS_char ,int) ); // → - printf("\n"); - - SHOW( FIND(IS_char ,int ,void) ); // → - SHOW( FIND(IS_void ,int ,void) ); // → - printf("\n"); - - SHOW( FIND(IS_int ,LIST) ); - SHOW( FIND(IS_float ,LIST) ); - SHOW( FIND(IS_double ,LIST) ); - SHOW( FIND(IS_char ,LIST) ); - SHOW( FIND(IS_void ,LIST) ); - SHOW( FIND(IS_big ,LIST) ); - printf("\n"); - - - //#endif - - return 0; -} diff --git a/developer/example_cpp/.githolder b/developer/example_cpp/.githolder new file mode 100644 index 0000000..e69de29 diff --git a/developer/example_cpp/0_readme.org b/developer/example_cpp/0_readme.org new file mode 100644 index 0000000..d10769b --- /dev/null +++ b/developer/example_cpp/0_readme.org @@ -0,0 +1,9 @@ +These are direct built one at a time, for example: + + #+BEGIN_SRC bash + > gcc try_6_list.c + > ./a.out + IS_char(int) -> 0 + IS_char(char) -> 1 + ... + EOF diff --git a/developer/example_cpp/cpp_ext_0.c b/developer/example_cpp/cpp_ext_0.c new file mode 100644 index 0000000..573c27c --- /dev/null +++ b/developer/example_cpp/cpp_ext_0.c @@ -0,0 +1,245 @@ +/* + See also + https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h + and tutorial at: http://jhnet.co.uk/articles/cpp_magic + + documents in $REPO_HOME/developer/document🖉 + +1. Provides: + + Raw constants: ZERO, ONE, COMMA, SEMICOLON + + Token tagging: _TWION_0, _TWION_1 + + Controlled concatenation: CAT2, CAT3, CAT4 + + Existence (now EXISTS) with token safety via ## + + Rewrite matchers: MATCH_RWR, NOT_MATCH_RWR + + Logical base: _AND, _OR, _NOT, BOOL, EQ, NOT_EQ + + Structural access: FIRST, REST, SECOND, THIRD + + Branching: IF_ELSE(...), with macro-safe conditioning + + Tests for all major features: try_eq.c, try_access.c, try_3_if.c, etc. + +2. + These are the non-recursive extensions. See cpp_ext_1 for the recursive extensions. + +3. + The 'twion' is cute. It is reminiscent of a complex number in math. Like the complex number that is fed into scalar equestions. The twion is a pair given to functions that only take singletons. + +4. + 0 is false + 1 is true + + Macros starting with an '_' (underscore) are private. + + EQ comparisons apart from logic comparisons, must be registered in advance. They take the form of, EQ____oo__, note comments below. + +5. todo + +cpp_ext as separate project +make the try into tests +make EXISTS true, leave an empty element as false + +IS_LIST to distinguish element from list, though it will be tough to +detect IS_LIST on a list with NOT_EXISTS elements, then a list with all +empty elements is still a list, still exits. + +mv BOOL AND OR +make AND and OR versions of FIND on EXISTS (existence quantification) + +find a better name for NULL_FN + +*/ + +#ifndef CPP_EXT_0 +#define CPP_EXT_0 + +/*=========================================================================== +DEBUG +===========================================================================*/ + +#include +#define DEBUG_CPP +#define STR(...) #__VA_ARGS__ + +// print the macro and the evaluation of the macro +#define SHOW(expr) printf("%s -> %s\n", #expr, STR(expr)) + +/*=========================================================================== +Constants +===========================================================================*/ + +#define COMMA , +#define SEMICOLON ; + +#define FALSE 0 +#define TRUE 1 + +//--------- + +#define _TWION_0 ~,0 +#define _TWION_1 ~,1 + +// RWR == rewrite rule, RWR_ is followed by macro name it is used in `__` +// Matching text is replaced with nothing, making it empty +// Potential for aliasing if x or y values have '__oo__' embedded in them. +#define _RWR_NOT__0 +#define _RWR_AND__1__oo__1 +#define _RWR_OR__0__oo__0 + +// add more of this form to register other equivalences +#define EQ__0__oo__0 +#define EQ__1__oo__1 + +/*=========================================================================== +Primitive Concatenation + Not due to elegance, as `##` is convenient, rather this is + used to force evaluation of arguments before `##`. + There will be a recursive CAT of n things in cpp_ext_1.c +===========================================================================*/ + +#define _CAT2(a ,b) a ## b +#define CAT2(a ,b) _CAT2(a ,b) + +#define _CAT3(a ,b ,c) a ## b ## c +#define CAT3(a ,b ,c) _CAT3(a ,b ,c) + +#define _CAT4(a ,b ,c ,d) a ## b ## c ## d +#define CAT4(a ,b ,c ,d) _CAT4(a ,b ,c ,d) + +#define APPEND(list ,...) list ,__VA_ARGS__ + + + +/*=========================================================================== +Existence +===========================================================================*/ + + //---------------------------------------- + // primitive access + + // note: _FIRST of nothing, _FIRST(), means passing an empty_item as the first item + // so it will return empty. + #define _FIRST(a ,...) a + #define _SECOND(a ,b ,...) b + + //---------------------------------------- + // existence + // + // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro, don't + // replace that with CAT! + + #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1) + #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0##x_item) + + #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item) + #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) ) + + #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0) + #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1##x_item) + + #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item) + #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) ) + + // useful to use with rewrite rules that substitute to nothing + #define MATCH_RWR(x_item) NOT_EXISTS(x_item) + #define NOT_MATCH_RWR(x_item) EXISTS(x_item) + +/*=========================================================================== +Logic Connectors +===========================================================================*/ + + #define _NOT(x_item) \ + MATCH_RWR( CAT2(_RWR_NOT__ ,x_item) ) + + #define _AND(x_item ,y_item) \ + MATCH_RWR( CAT4(_RWR_AND__ ,x_item ,__oo__ ,y_item) ) + + #define _OR(x_item ,y_item) \ + NOT_MATCH_RWR( CAT4(_RWR_OR__ ,x_item ,__oo__ ,y_item) ) + + #define _BOOL(x_item) \ + _AND( \ + EXISTS_ITEM( x_item ) \ + ,NOT_MATCH_RWR( CAT2(EQ__0__oo__ ,x_item) ) \ + ) + #define BOOL(x_item) _BOOL(_FIRST(x_item)) + + #define NOT(x_item) _NOT(BOOL(x_item)) + #define AND(x_item ,y_item) _AND(BOOL(x_item) ,BOOL(y_item)) + #define OR(x_item ,y_item) _OR(BOOL(x_item) ,BOOL(y_item)) + +/*=========================================================================== + Equality + + more general than a connector because more rules can be added. + + each registered equality rule has the form + EQ____oo__ + for example, logic equalities are already registered: + EQ__0__oo__0 + EQ__1__oo__1 + +===========================================================================*/ + + #define EQ(x_item ,y_item) \ + MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) ) + + #define NOT_EQ(x_item ,y_item) \ + NOT_MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) ) + +/*=========================================================================== + IF-ELSE construct. + Usage: IF_ELSE(condition)()() + + A most amazing little macro. It has no dependencies on the other macros + in this file, though many will be useful for setting (condition) + + The seemingly extra layer prevents BOOL_(condition) from being pasted with a ## which, if done, would prevent it from being evaluated. Recall, the first step in evaluation is a literal copy in of the arguments. ===symbol ========================================================================*/ + + #define IF(predicate) CAT2(_IF_ ,BOOL(predicate)) + #define _IF_1(...) __VA_ARGS__ _IF_1_ELSE + #define _IF_0(...) _IF_0_ELSE + #define _IF_1_ELSE(...) + #define _IF_0_ELSE(...) __VA_ARGS__ + +/*=========================================================================== +Access + see ext_1 with recursion for `Nth` + +===========================================================================*/ + + // _FIRST defined in the logic section + #define FIRST(pad ,...)\ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + (pad) \ + ( _FIRST(__VA_ARGS__) ) + + #define _REST(a ,...) __VA_ARGS__ + #define REST(...)\ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + () \ + ( _REST(__VA_ARGS__) ) + + // _SECOND defined in the logic section + #define SECOND(pad ,...) \ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + (pad) \ + ( _SECOND(__VA_ARGS__ ,pad) ) + + #define _THIRD(a ,b ,c ,...) c + #define THIRD(pad ,...) \ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + (pad) \ + ( _THIRD(__VA_ARGS__ ,pad, pad) ) + +#endif diff --git a/developer/example_cpp/cpp_ext_1.c b/developer/example_cpp/cpp_ext_1.c new file mode 100644 index 0000000..bc241d7 --- /dev/null +++ b/developer/example_cpp/cpp_ext_1.c @@ -0,0 +1,90 @@ +/* +These are the recursive extension. + +Simple errors can lead to very long error outputs, which might be why +the cpp designers had obviously intended that recursion would not be possible. + +To be added: + +LIST_TOO_LONG + +// scanning left to right finds first that exists +LEFTMOST_EXISTENT + +// scanning left to right finds last that exits +RIGHTMOST_EXISTENT + +DROP_NOT_EXISTS_ALL +DROP_NOT_EXISTS_LEFT +DROPE_NOT_EXISTS_RIGHT + +#define _CAT(sep,first,...) \ + +*/ + +#ifndef CPP_EXT_1 +#define CPP_EXT_1 + +/*=========================================================================== + Force extra macro expansion (the EVAL trick) + This chain of EVAL macros forces the preprocessor to perform many rescans, + which is necessary to “unroll” recursive macros. +===========================================================================*/ +//#define EVAL(...) EVAL1024(__VA_ARGS__) +#define EVAL(...) EVAL32(__VA_ARGS__) +#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__)) +#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__)) +#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__)) +#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__)) +#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__)) +#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) +#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) +#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) +#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) +#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) +#define EVAL1(...) __VA_ARGS__ + +/*=========================================================================== + Defer macros: these help “hide” recursive calls for additional expansion passes. +===========================================================================*/ +#define NULL_FN() +#define DEFER1(m) m NULL_FN() +#define DEFER2(m) m NULL_FN NULL_FN()() +#define DEFER3(m) m NULL_FN NULL_FN NULL_FN()()() +#define DEFER4(m) m NULL_FN NULL_FN NULL_FN NULL_FN()()()() + +/*=========================================================================== + Quantifiers +===========================================================================*/ + +#define _FIND(predicate ,...) \ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + () \ + (IF \ + ( predicate(FIRST(__VA_ARGS__)) ) \ + ( FIRST( ,__VA_ARGS__) ) \ + ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ + ) +#define _FIND_CONFEDERATE() _FIND + +// number of evals required depends upon length of not found list prefix +#define FIND(predicate ,...) EVAL( _FIND(predicate ,__VA_ARGS__) ) + +#define _FIND_ITEM(item ,...) \ + IF \ + ( NOT_EXISTS(__VA_ARGS__) ) \ + () \ + (IF \ + ( EQ(item ,FIRST(__VA_ARGS__)) ) \ + ( FIRST( ,__VA_ARGS__) ) \ + ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \ + ) +#define _FIND_ITEM_CONFEDERATE() _FIND_ITEM + +// number of evals required depends upon length of not found list prefix +#define FIND_ITEM(predicate ,...) EVAL( _FIND_ITEM(predicate ,__VA_ARGS__) ) + + + +#endif diff --git a/developer/example_cpp/example_A.c b/developer/example_cpp/example_A.c new file mode 100644 index 0000000..edc81c6 --- /dev/null +++ b/developer/example_cpp/example_A.c @@ -0,0 +1,34 @@ +// from http://jhnet.co.uk/articles/cpp_magic + +#include +#define STR(x) #x +#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) + +#define NULL_FN() +#define EVAL1(...) __VA_ARGS__ + +#define A(n) I like the number n + + +int main(){ + + printf( + " I like the number 123\n" + " A (123)\n" + ); + SHOW(A (123)); + SHOW(A NULL_FN() (123)); + printf("\n"); + + printf( + " I like the number 123\n" + ); + SHOW(EVAL1(A NULL_FN() (123))); + printf("\n"); + + + /* + ... The reason this works is that when CPP encounters a function-style macro, it recursively expands the macro's arguments before substituting the macro's body and expanding that. ... + */ + +}; diff --git a/developer/example_cpp/example_eval.c b/developer/example_cpp/example_eval.c new file mode 100644 index 0000000..e60af83 --- /dev/null +++ b/developer/example_cpp/example_eval.c @@ -0,0 +1,29 @@ +#include +#define STR(x) #x +#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) + +int main(void){ + printf("example_eval.c\n"); + + #define NULL_FN() + #define NEGATE(x) -x + #define NOT_SO_FAST(x) NEGATE NULL_FN() (x) + SHOW(NOT_SO_FAST(5)); + + #define BE(x) x + SHOW(BE(NOT_SO_FAST(5))) +} + +/* + 2025-03-27T04:47:02Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > gcc example_eval.c + + 2025-03-27T04:47:32Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > ./a.out + example_eval.c + NOT_SO_FAST(5) → NEGATE (5) + BE(NOT_SO_FAST(5)) → -5 + +*/ diff --git a/developer/example_cpp/example_grow.c b/developer/example_cpp/example_grow.c new file mode 100644 index 0000000..74f3cca --- /dev/null +++ b/developer/example_cpp/example_grow.c @@ -0,0 +1,121 @@ +#include +#define STR(x) #x +// no evaluation, and one pass of evaluation +#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) + +#define BE(...) __VA_ARGS__ +#define NULL_FN() + +#include +int main(void){ + printf("example_grow.c\n"); + printf("\n"); + + // case 1 + /* + GROW(7) → 17 * GROW(7) + GROW(GROW(5)) → 17 * GROW(17 * GROW(5)) + */ + #define GROW(x) 17 * GROW(x) + SHOW(GROW(7)); + SHOW(GROW(GROW(5))); + printf("\n"); + + // case 2 + // GROW2(11) --> 19 * GROW2 (11) + #define GROW2(x) 19 * GROW2 NULL_FN() (x) + SHOW(GROW2(11)) ; + printf("\n"); + + // case 3 + // GROW3(13) --> 119 * 19 * GROW2 (13) + #define GROW3(x) BE(119 * GROW2 NULL_FN() (x)) + SHOW(GROW3(13)); + printf("\n"); + + // case 4 + /* + `BE` placed on the outside. The idea is that evaluation will return `123 * GROW (15)` and then this will be evaluated resulting in `123 * 123 * GROW(15)`. + + However, any time GROW4 literally spells out GROW4(...) inside its own expansion + it will leave it literally and not expand it. + + Though it is interesting that here that occurs at a higher level in the evaluation tree than the first ocurrance of the recursive call, but still it is in the tree. + + GROW4(15) --> 123 * GROW4 (15) + */ + #define GROW4(x) BE(123 * GROW4 NULL_FN() (x)) + SHOW(GROW4(15)); + printf("\n"); + + // case 5 + /* + Substitution of the function named followed by a trampoline works. + + The original expression is written in terms of a deferred CONDFEDERATE function + instead of in terms of a recursive call to GROW5. cpp can suspect nothing. + + The result is an expression in terms of the unevaluated CONDFEDERATE function. + + The CONFEDERATE function is defined to return the token GROW5. Hence in a subsequent evaluation, and there must be a subsequent evaluation for this to work, The CONFEDERATE function will run, return GROW5 which is next to its call parenthesis, so then the + recursive call will run. + + BE(GROW5(21)) --> 541 * 541 * CONFEDERATE () (21) + BE(BE(GROW5(57))) --> 541 * 541 * 541 * CONFEDERATE () (57) + */ + #define GROW5(x) 541 * CONFEDERATE NULL_FN() () (x) + #define CONFEDERATE() GROW5 + SHOW(BE(GROW5(21))); + SHOW(BE(BE(GROW5(57)))); + printf("\n"); + + // case 6 + /* + Once a recursively called function is marked, or 'colored' it can never be expanded, even when passed through to another variable and separately evaluation. + */ + #define GROW6(x) 1029 * GROW6 NULL_FN() (x) + #define RESULT1 GROW6(51) + SHOW(RESULT1); + SHOW(BE(RESULT1)); + printf("\n"); + // RESULT1 --> 1029 * GROW6 (51) + // BE(RESULT1) --> 1029 * GROW6 (51) + + // case 7 + #define RESULT2 GROW6(151) + SHOW(RESULT2); + SHOW(BE(RESULT2)); + printf("\n"); + // RESULT2 --> 1029 * GROW6 (151) + // BE(RESULT2) --> 1029 * GROW6 (151) + +} +/* + 2025-03-27T10:45:39Z[developer] +Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ +> gcc example_grow.c + +2025-03-27T11:43:19Z[developer] +Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ +> ./a.out +example_grow.c + +GROW(7) --> 17 * GROW(7) +GROW(GROW(5)) --> 17 * GROW(17 * GROW(5)) + +GROW2(11) --> 19 * GROW2 (11) + +GROW3(13) --> 119 * 19 * GROW2 (13) + +GROW4(15) --> 123 * GROW4 (15) + +BE(GROW5(21)) --> 541 * 541 * CONFEDERATE () (21) +BE(BE(GROW5(57))) --> 541 * 541 * 541 * CONFEDERATE () (57) + +RESULT1 --> 1029 * GROW6 (51) +BE(RESULT1) --> 1029 * GROW6 (51) + +RESULT2 --> 1029 * GROW6 (151) +BE(RESULT2) --> 1029 * GROW6 (151) + +*/ diff --git a/developer/example_cpp/example_grow2.c b/developer/example_cpp/example_grow2.c new file mode 100644 index 0000000..a421469 --- /dev/null +++ b/developer/example_cpp/example_grow2.c @@ -0,0 +1,29 @@ +#include + +#define STR(...) #__VA_ARGS__ +// no evaluation, and one pass of evaluation +#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) + +#define BE(...) __VA_ARGS__ + +#define NULL_FN() +#define GROW(x) 19 * _GROW NULL_FN() ()(x) +#define _GROW() GROW + + +int main(void) +{ + printf("One-trampoline minimal example:\n\n"); + + //19 * _GROW ()(7) + SHOW(GROW(7)); + + // 19 * 19 * _GROW ()(7) + SHOW(BE(GROW(7))); + + // 19 * 19 * 19 * _GROW ()(7) + SHOW(BE(BE(GROW(7)))); + + + return 0; +} diff --git a/developer/example_cpp/example_recurse.c b/developer/example_cpp/example_recurse.c new file mode 100644 index 0000000..5a4b4e0 --- /dev/null +++ b/developer/example_cpp/example_recurse.c @@ -0,0 +1,54 @@ +// from http://jhnet.co.uk/articles/cpp_magic + +#include + +#define STR(...) #__VA_ARGS__ +// no evaluation, and one pass of evalutation +#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr)) + +#define NULL_FN() + +#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) +#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) +#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) +#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) +#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) +#define EVAL1(...) __VA_ARGS__ + +#define DEFER1(m) m NULL_FN() + +#define RECURSE() I am recursive, look: DEFER1(_RECURSE)()() +#define _RECURSE() RECURSE + + +int main(){ + + printf( + "No EVAL:\n" + " RECURSE()\n" + ); + SHOW(RECURSE()); + printf("\n"); + + printf( + "With EVAL1:\n" + " EVAL1(RECURSE())\n" + ); + SHOW(EVAL1(RECURSE())); + printf("\n"); + + printf( + "With EVAL2:\n" + " EVAL2(RECURSE())\n" + ); + SHOW(EVAL2(RECURSE())); + printf("\n"); + + printf( + "With EVAL32:\n" + " EVAL32(RECURSE())\n" + ); + SHOW(EVAL32(RECURSE())); + printf("\n"); + +}; diff --git a/developer/example_cpp/try_1_exists.c b/developer/example_cpp/try_1_exists.c new file mode 100644 index 0000000..c2ca07d --- /dev/null +++ b/developer/example_cpp/try_1_exists.c @@ -0,0 +1,110 @@ +#include "../cc🖉/cpp_ext_0.c" + +#define F 1 +#define O1 2 +#define O2 3 +#define B 4 +#define A 5 +#define R 6 +#define D 7 + + +// Patch for _EXISTS to succeed on 0 +#define _REWRITE_TWION_0 _REWRITE_TWION + +int main(void){ + printf("try_1_exists\n\n"); + + // Constant macros + int x COMMA y = 1; // Tests that COMMA = , + printf("y? %d\n", y); + printf("\n"); + + // Token paste test + int _cat_result = CAT2(CAT3(F ,O1 ,O2) ,CAT4(B ,A ,R ,D)); + printf("FOOBARD %d\n" ,_cat_result); + printf("\n"); + + // Selector macros + int first = _FIRST(11 ,22 ,33); // → 11 + int second = _SECOND(11 ,22 ,33); // → 22 + printf("_FIRST(11 ,22 ,33) = %d\n", first); + printf("_SECOND(11 ,22 ,33) = %d\n", second); + printf("\n"); + + // Existence detection + int empty = EXISTS_ITEM(); // → 1 (rewrite hits) + int empty_0 = EXISTS_ITEM(0); // → 1 (rewrite hits) + int empty_1 = EXISTS_ITEM(1); // → 0 (no rewrite) + int empty_f = EXISTS_ITEM(hello); // → 0 + + printf("EXISTS_ITEM() = %d\n", empty); + printf("EXISTS_ITEM(0) = %d\n", empty_0); + printf("EXISTS_ITEM(1) = %d\n", empty_1); + printf("EXISTS_ITEM(hello) = %d\n", empty_f); + printf("\n"); + + // Not Existence detection + empty = NOT_EXISTS_ITEM(); // → 1 (rewrite hits) + empty_0 = NOT_EXISTS_ITEM(0); // → 1 (rewrite hits) + empty_1 = NOT_EXISTS_ITEM(1); // → 0 (no rewrite) + empty_f = NOT_EXISTS_ITEM(hello); // → 0 + + printf("NOT_EXISTS_ITEM() = %d\n", empty); + printf("NOT_EXISTS_ITEM(0) = %d\n", empty_0); + printf("NOT_EXISTS_ITEM(1) = %d\n", empty_1); + printf("NOT_EXISTS_ITEM(hello) = %d\n", empty_f); + printf("\n"); + + + // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error + int empty_11 = EXISTS(10,11,12); // this is a legal call + int empty_12 = EXISTS(); + + // printf("EXISTS_ITEM(10,11,12) = %d\n", empty_10); + printf("EXISTS(10,11,12) = %d\n", empty_11); + printf("EXISTS() = %d\n", empty_12); + printf("\n"); + + // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error + empty_11 = NOT_EXISTS(10,11,12); // this is a legal call + empty_12 = NOT_EXISTS(); + + // printf("NOT_EXISTS_ITEM(10,11,12) = %d\n", empty_10); + printf("NOT_EXISTS(10,11,12) = %d\n", empty_11); + printf("NOT_EXISTS() = %d\n", empty_12); + printf("\n"); + + + return 0; +} + +/* + 2025-03-27T12:38:04Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > gcc try_1_exists.c + + 2025-03-27T12:40:32Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > ./a.out + _CAT(FOO ,BAR) → 12345 + + _FIRST(11 ,22 ,33) = 11 + _SECOND(11 ,22 ,33) = 22 + + EXISTS_ITEM() = 0 + EXISTS_ITEM(0) = 1 + EXISTS_ITEM(1) = 1 + EXISTS_ITEM(hello) = 1 + + NOT_EXISTS_ITEM() = 1 + NOT_EXISTS_ITEM(0) = 0 + NOT_EXISTS_ITEM(1) = 0 + NOT_EXISTS_ITEM(hello) = 0 + + EXISTS(10,11,12) = 1 + EXISTS() = 0 + + NOT_EXISTS(10,11,12) = 0 + NOT_EXISTS() = 1 +*/ diff --git a/developer/example_cpp/try_2_connectors.c b/developer/example_cpp/try_2_connectors.c new file mode 100644 index 0000000..98078f1 --- /dev/null +++ b/developer/example_cpp/try_2_connectors.c @@ -0,0 +1,200 @@ +#include "../cc🖉/cpp_ext_0.c" + +int main(void){ + + //-------------------------------------------------------------------------- + // Existence Checks (sanity anchor) + //-------------------------------------------------------------------------- + + #define x0 + SHOW( EXISTS_ITEM(x0) ); // → 0 (assumed undefined) + SHOW( NOT_EXISTS_ITEM(x0) ); // → 1 + printf("\n"); + + SHOW( MATCH(x0) ); + SHOW( NOT_MATCH(x0) ); + printf("\n"); + + //-------------------------------------------------------------------------- + // Primitive Connectors + //-------------------------------------------------------------------------- + + SHOW( _NOT(0) ); // _RWR_NOT_0 is defined → MATCH → 1 + SHOW( _NOT(1) ); // no rule → MATCH fails → 0 + printf("\n"); + + SHOW( _AND(0 ,0) ); // rule defined → MATCH → 1 + SHOW( _AND(1 ,0) ); // rule defined → MATCH → 1 + SHOW( _AND(0 ,1) ); // rule defined → MATCH → 1 + SHOW( _AND(1 ,1) ); // rule defined → MATCH → 1 + SHOW( _AND(1 ,x) ); // not legal args, but worked, rule missing → MATCH fails → 0 + printf("\n"); + + SHOW( _OR(0 ,0) ); // rule defined → NOT_MATCH → 0 + SHOW( _OR(0 ,1) ); // rule missing → NOT_MATCH → 1 + SHOW( _OR(1 ,0) ); // rule missing → NOT_MATCH → 1 + SHOW( _OR(1 ,1) ); // rule missing → NOT_MATCH → 1 + printf("\n"); + + //-------------------------------------------------------------------------- + // Logical Connectors (BOOL + AND/OR/NOT) + //-------------------------------------------------------------------------- + + printf("x0 is a macro with an empty definition"); + + SHOW( _BOOL(0) ); // 0 + SHOW( _BOOL(1) ); // 1 + SHOW( _BOOL(2) ); // 1 because it exists + SHOW( _BOOL(x0) ); // 0 because it does not exit (see the #define at the top) + printf("\n"); + + SHOW( BOOL(0) ); // _FIRST = 0, EXISTS_ITEM(_FIRST) = 0 → _AND(0 ,1) → 0 + SHOW( BOOL(1) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 + SHOW( BOOL(10) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 + SHOW( BOOL() ); // EXISTS_ITEM(1) = 0 → BOOL = 0 + SHOW( BOOL(x0) ); // EXISTS_ITEM(1) = 0 → BOOL = 0 + printf("\n"); + + SHOW( NOT(0) ); // BOOL = 0 → NOT(0) = _NOT(0) = 1 + SHOW( NOT(1) ); // BOOL = 0 → NOT(0) = 1 + SHOW( NOT() ); // BOOL = 0 → NOT(0) = 1 + SHOW( NOT(10) ); // BOOL = 0 → NOT(0) = 1 + printf("\n"); + + SHOW( AND(1 ,0) ); // 0 + SHOW( AND(1 ,1) ); // BOOL(1), BOOL(1) = 0,0 → AND(0 ,0) = _AND(0 ,0) = 1 + printf("\n"); + + SHOW( OR(0 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0 + SHOW( OR(1 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0 + printf("\n"); + + //-------------------------------------------------------------------------- + // Compound Connectors + //-------------------------------------------------------------------------- + + // Double NOT + SHOW( NOT(NOT(0)) ); // → NOT(1) → _NOT(1) → 0 + SHOW( NOT(NOT(1)) ); // → NOT(0) → _NOT(0) → 1 + + // Triple NOT + SHOW( NOT(NOT(NOT(0))) ); // → NOT(0) → _NOT(0) → 1 + SHOW( NOT(NOT(NOT(1))) ); // → NOT(1) → _NOT(1) → 0 + printf("\n"); + + // Nested AND + SHOW( AND(1 ,AND(1 ,0)) ); // AND(1 ,AND(1 ,0)) → AND(1 ,0) → _AND(1 ,0) = 0 + SHOW( AND(1 ,AND(1 ,1)) ); // → AND(1 ,1) → _AND(1 ,1) = 1 + printf("\n"); + + // Nested OR + SHOW( OR(0 ,OR(0 ,1)) ); // → OR(0 ,1) → _OR(0 ,1) = 1 + SHOW( OR(0 ,OR(0 ,0)) ); // → OR(0 ,0) → _OR(0 ,0) = 0 + printf("\n"); + + // Mixed nesting + SHOW( AND(NOT(0) ,1) ); // → AND(1 ,1) → _AND(1 ,1) = 1 + SHOW( AND(NOT(1) ,1) ); // → AND(0 ,1) → _AND(0 ,1) = 0 + SHOW( OR(NOT(1) ,1) ); // → OR(0 ,1) → _OR(0 ,1) = 1 + SHOW( OR(NOT(0) ,0) ); // → OR(1 ,0) → _OR(1 ,0) = 1 + printf("\n"); + + // Deep mix + SHOW( NOT(AND(1 ,NOT(1))) ); // AND(1 ,0) = _AND(1 ,0) = 0 → NOT(0) = _NOT(0) = 1 + SHOW( NOT(OR(0 ,NOT(0))) ); // OR(0 ,1) = _OR(0 ,1) = 1 → NOT(1) = _NOT(1) = 0 + printf("\n"); + + // Asymmetric nesting + SHOW( AND(OR(0 ,1) ,AND(1 ,1)) ); // OR(0 ,1) = 1, AND(1 ,1) = 1 → AND(1 ,1) = 1 + SHOW( OR(AND(1 ,0) ,AND(1 ,1)) ); // AND(1 ,0) = 0, AND(1 ,1) = 1 → OR(0 ,1) = 1 + printf("\n"); + + return 0; +} +/* + 2025-03-27T12:59:39Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > gcc try_2_connectors.c + + 2025-03-27T13:00:11Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > ./a.out + EXISTS_ITEM(x0) --> 0 + NOT_EXISTS_ITEM(x0) --> 1 + + MATCH(x0) --> MATCH() + NOT_MATCH(x0) --> NOT_MATCH() + + _NOT(0) --> 1 + _NOT(1) --> 0 + + _AND(0 ,0) --> 0 + _AND(1 ,0) --> 0 + _AND(0 ,1) --> 0 + _AND(1 ,1) --> 1 + _AND(1 ,x) --> 0 + + _OR(0 ,0) --> 0 + _OR(0 ,1) --> 1 + _OR(1 ,0) --> 1 + _OR(1 ,1) --> 1 + + _EQ(0 ,0) --> 1 + _EQ(1 ,1) --> 1 + _EQ(0 ,1) --> 0 + _EQ(x ,x) --> 0 + + _NOT_EQ(0 ,1) --> 1 + _NOT_EQ(0 ,0) --> 0 + + _BOOL_2(0) --> 0 + _BOOL_2(1) --> 1 + _BOOL_2(2) --> 1 + _BOOL_2(x0) --> 0 + + BOOL(0) --> 0 + BOOL(1) --> 1 + BOOL(10) --> 1 + BOOL() --> 0 + BOOL(x0) --> 0 + + NOT(0) --> 1 + NOT(1) --> 0 + NOT() --> 1 + NOT(10) --> 0 + + AND(1 ,0) --> 0 + AND(1 ,1) --> 1 + + OR(0 ,0) --> 0 + OR(1 ,0) --> 1 + + NOT(NOT(0)) --> 0 + NOT(NOT(1)) --> 1 + NOT(NOT(NOT(0))) --> 1 + NOT(NOT(NOT(1))) --> 0 + + AND(1 ,AND(1 ,0)) --> 0 + AND(1 ,AND(1 ,1)) --> 1 + + OR(0 ,OR(0 ,1)) --> 1 + OR(0 ,OR(0 ,0)) --> 0 + + AND(NOT(0) ,1) --> 1 + AND(NOT(1) ,1) --> 0 + OR(NOT(1) ,1) --> 1 + OR(NOT(0) ,0) --> 1 + + NOT(AND(1 ,NOT(1))) --> 1 + NOT(OR(0 ,NOT(0))) --> 0 + + AND(OR(0 ,1) ,AND(1 ,1)) --> 1 + OR(AND(1 ,0) ,AND(1 ,1)) --> 1 + + + 2025-03-27T13:00:12Z[developer] + Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§ + > +*/ + + diff --git a/developer/example_cpp/try_3_eq.c b/developer/example_cpp/try_3_eq.c new file mode 100644 index 0000000..c388f03 --- /dev/null +++ b/developer/example_cpp/try_3_eq.c @@ -0,0 +1,55 @@ +#include "../cc🖉/cpp_ext_0.c" + +int main(void){ + + //--------------------------------------------------------------------------- + // EQ Tests — identity and mismatch + //--------------------------------------------------------------------------- + + SHOW(EQ(0 ,0)); // Expected → 1 + SHOW(EQ(1 ,1)); // Expected → 1 + SHOW(EQ(0 ,1)); // Expected → 0 + SHOW(EQ(1 ,0)); // Expected → 0 + + SHOW(EQ(x ,x)); // Expected → 0 (no _RWREQ__x__oo__x defined) + SHOW(EQ(x ,y)); // Expected → 0 + + //--------------------------------------------------------------------------- + // NOTEQ Tests — inverse behavior + //--------------------------------------------------------------------------- + + SHOW(NOT_EQ(0 ,0)); // Expected → 0 (because EQ → 1, so EXISTS → 0) + SHOW(NOT_EQ(1 ,1)); // Expected → 0 + SHOW(NOT_EQ(0 ,1)); // Expected → 1 + SHOW(NOT_EQ(1 ,0)); // Expected → 1 + + SHOW(NOT_EQ(x ,x)); // Expected → 1 (EQ not defined → NOTEQ = 1) + SHOW(NOT_EQ(x ,y)); // Expected → 1 + + //--------------------------------------------------------------------------- + // Mixed cases with macros + //--------------------------------------------------------------------------- + + #define XSYM 0 + #define YSYM 1 + + SHOW(EQ(XSYM ,XSYM)); // Expected → 1 (0,0) + SHOW(EQ(XSYM ,YSYM)); // Expected → 0 (0,1) + SHOW(NOT_EQ(XSYM ,YSYM)); // Expected → 1 + + SHOW(EQ(XSYM ,0)); // Expected → 1 + SHOW(EQ(XSYM ,1)); // Expected → 0 + + SHOW(NOT_EQ(YSYM ,0)); // Expected → 1 + SHOW(NOT_EQ(YSYM ,1)); // Expected → 0 + + //--------------------------------------------------------------------------- + // Edge case: undefined symbol + //--------------------------------------------------------------------------- + + SHOW(EQ(z ,z)); // Expected → 0 + SHOW(NOT_EQ(z ,z)); // Expected → 1 + + printf("\n"); + return 0; +} diff --git a/developer/example_cpp/try_4_if.c b/developer/example_cpp/try_4_if.c new file mode 100644 index 0000000..4d9d3ae --- /dev/null +++ b/developer/example_cpp/try_4_if.c @@ -0,0 +1,62 @@ +#include "../cc🖉/cpp_ext_0.c" + +int main(void){ + + //--------------------------------------------------------------------------- + // Basic boolean cases + //--------------------------------------------------------------------------- + + SHOW(IF_ELSE(1)(yes)(no)); + SHOW(IF_ELSE(0)(yes)(no)); // → no + printf("\n"); + + //--------------------------------------------------------------------------- + // Symbolic identifiers + //--------------------------------------------------------------------------- + SHOW(IF_ELSE(TRUE)(ok)(fail)); // → ok + SHOW(IF_ELSE(FALSE)(ok)(fail)); // → fail + SHOW(IF_ELSE(foo)(alpha)(omega)); // → omega (foo is undefined) + printf("\n"); + + //--------------------------------------------------------------------------- + // Logic expressions + //--------------------------------------------------------------------------- + SHOW(IF_ELSE(AND(1 ,1))(pass)(fail)); // → pass + SHOW(IF_ELSE(OR(0 ,0))(yes)(no)); // → no + SHOW(IF_ELSE(NOT(0))(on)(off)); // → on + printf("\n"); + + //--------------------------------------------------------------------------- + // Code-like output + //--------------------------------------------------------------------------- + SHOW(IF_ELSE(1)(int x = 1;)(int x = 2;)); // → int x = 1; + SHOW(IF_ELSE(0)(int x = 1;)(int x = 2;)); // → int x = 2; + printf("\n"); + + //--------------------------------------------------------------------------- + // Comma usage in true/false branches + //--------------------------------------------------------------------------- + SHOW(IF_ELSE(1)(a ,b ,c)(x ,y ,z)); // → a ,b ,c + SHOW(IF_ELSE(0)(a ,b ,c)(x ,y ,z)); // → x ,y ,z + printf("\n"); + + //--------------------------------------------------------------------------- + // Empty condition + //--------------------------------------------------------------------------- + SHOW(IF_ELSE()(true)(false)); // → false (BOOL() = 0) + printf("\n"); + + //--------------------------------------------------------------------------- + // Nested IF_ELSE + //--------------------------------------------------------------------------- + SHOW( + IF_ELSE(AND(1 ,1))( + IF_ELSE(0)(inner_true)(inner_false) + )( + outer_false + ) + ); // → inner_false + printf("\n"); + + return 0; +} diff --git a/developer/example_cpp/try_5_access.c b/developer/example_cpp/try_5_access.c new file mode 100644 index 0000000..aee6c94 --- /dev/null +++ b/developer/example_cpp/try_5_access.c @@ -0,0 +1,46 @@ +#include "../cc🖉/cpp_ext_0.c" + +int main(void){ + + //--------------------------------------------------------------------------- + // FIRST + //--------------------------------------------------------------------------- + + SHOW(FIRST(foo)); // → foo (only pad, no args) + SHOW(FIRST(foo ,a)); // → a + SHOW(FIRST(foo ,a ,b ,c)); // → a + printf("\n"); + + //--------------------------------------------------------------------------- + // REST + //--------------------------------------------------------------------------- + + SHOW(REST()); // → (empty) + SHOW(REST(a)); // → (empty) + SHOW(REST(a ,b)); // → b + SHOW(REST(a ,b ,c ,d)); // → b ,c ,d + printf("\n"); + + //--------------------------------------------------------------------------- + // SECOND + //--------------------------------------------------------------------------- + + SHOW(SECOND(X)); // → X (only pad) + SHOW(SECOND(X ,a)); // → X (only one arg, fallback to pad) + SHOW(SECOND(X ,a ,b)); // → b + SHOW(SECOND(X ,a ,b ,c)); // → b + printf("\n"); + + //--------------------------------------------------------------------------- + // THIRD + //--------------------------------------------------------------------------- + + SHOW(THIRD(X)); // → X (pad returned) + SHOW(THIRD(X ,a)); // → X + SHOW(THIRD(X ,a ,b)); // → X + SHOW(THIRD(X ,a ,b ,c)); // → c + SHOW(THIRD(X ,a ,b ,c ,d)); // → c + printf("\n"); + + return 0; +} diff --git a/developer/example_cpp/try_6_list.c b/developer/example_cpp/try_6_list.c new file mode 100644 index 0000000..a9ba619 --- /dev/null +++ b/developer/example_cpp/try_6_list.c @@ -0,0 +1,60 @@ +#include "../cc🖉/cpp_ext_0.c" +#include "../cc🖉/cpp_ext_1.c" + +#define LIST Integer ,Float ,Char ,Void + +// register equality +#define EQ__Integer__oo__Integer +#define EQ__Float__oo__Float +#define EQ__Char__oo__Char +#define EQ__Void__oo__Void + +// make predicates +#define IS_Integer(x) EQ(x ,Integer) +#define IS_Float(x) EQ(x ,Float) +#define IS_Missing(x) EQ(x ,Missing) +#define IS_Char(x) EQ(x ,Char) +#define IS_Void(x) EQ(x ,Void) + +int main(void){ + + SHOW(IS_Char(Integer)); + SHOW(IS_Char(Char)); + printf("\n"); + + SHOW( FIND(IS_Char ,) ); + SHOW( FIND(IS_Char ,Char) ); // → Char + SHOW( FIND(IS_Char ,Integer) ); // → + printf("\n"); + + SHOW( FIND(IS_Char ,Integer ,Void) ); // → + SHOW( FIND(IS_Void ,Integer ,Void) ); // → + printf("\n"); + + SHOW( FIND(IS_Integer ,LIST) ); + SHOW( FIND(IS_Float ,LIST) ); + SHOW( FIND(IS_Missing ,LIST) ); + SHOW( FIND(IS_Char ,LIST) ); + SHOW( FIND(IS_Void ,LIST) ); + SHOW( FIND(IS_big ,LIST) ); // literal 'IS_big' will be seen as true + printf("\n"); + + SHOW( FIND_ITEM(Char ,) ); + SHOW( FIND_ITEM(Char ,Char) ); // → Char + SHOW( FIND_ITEM(Char ,Integer) ); // → + printf("\n"); + + SHOW( FIND_ITEM(Char ,Integer ,Void) ); // → + SHOW( FIND_ITEM(Void ,Integer ,Void) ); // → + printf("\n"); + + SHOW( FIND_ITEM(Integer ,LIST) ); + SHOW( FIND_ITEM(Float ,LIST) ); + SHOW( FIND_ITEM(Missing ,LIST) ); + SHOW( FIND_ITEM(Char ,LIST) ); + SHOW( FIND_ITEM(Void ,LIST) ); + SHOW( FIND_ITEM(big ,LIST) ); + printf("\n"); + + return 0; +} diff --git "a/developer/tool\360\237\226\211/make" "b/developer/tool\360\237\226\211/make" index cfc2138..246d8df 100755 --- "a/developer/tool\360\237\226\211/make" +++ "b/developer/tool\360\237\226\211/make" @@ -13,10 +13,6 @@ set -e set -x cd "$REPO_HOME"/developer || exit 1 - - pushd python - ./fill_template - popd /bin/make -f tool🖉/makefile $@ set +x diff --git "a/developer/tool\360\237\226\211/makefile" "b/developer/tool\360\237\226\211/makefile" index 7b3660f..8dfa07c 100644 --- "a/developer/tool\360\237\226\211/makefile" +++ "b/developer/tool\360\237\226\211/makefile" @@ -3,7 +3,13 @@ RT-INCOMMON:=$(REPO_HOME)/tool_shared/third_party/RT-project-share/release include $(RT-INCOMMON)/make/environment_RT_0 -CFLAGS+=-Werror -Wno-macro-redefined -include "$(RT-INCOMMON)/make/RT_0.h" +# 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" LINKFLAGS+= -l$(PROJECT) LIBFILE=$(LIBDIR)/lib$(PROJECT).a