--- /dev/null
+/*
+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 <stdio.h>
+ #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
*/
-#define Core·DEBUG
-#ifdef FG·DEBUG
- #include <stdio.h>
-#endif
-
-#ifndef FACE
-#define Core·IMPLEMENTATION
-#define FACE
-#endif
-
//--------------------------------------------------------------------------------
-// Interface
+// Interface
#ifndef Core·FACE
#define Core·FACE
+ #define Core·DEBUG
+ #ifdef FG·DEBUG
+ #include <stdio.h>
+ #endif
+
#include <stdint.h>
+ #include <stdbool.h>
#include <stddef.h>
+ #include "cpp_ext.c"
//----------------------------------------
// memory interface
//----------------------------------------
- // Define a namespace.
- // #define _Ξ(a ,b) a##·##b
- /// #define Ξ(a ,b) _Ξ(a ,b)
- #include <xi.c>
-
// 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
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
//----------------------------------------
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
+++ /dev/null
-/*
-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 <stdio.h>
- #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
-
+++ /dev/null
-/*
- 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 <stdint.h>
- #include <stdbool.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- //----------------------------------------
- // 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 <stdarg.h>
- #include <stdlib.h>
-
- 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
+++ /dev/null
-/*
- 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 <stdint.h>
- #include <stdbool.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- //----------------------------------------
- // 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 <stdarg.h>
- #include <stdlib.h>
-
- 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
+++ /dev/null
-/*
- 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 <stdint.h>
- #include <stdbool.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- //----------------------------------------
- // 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 <stdarg.h>
- #include <stdlib.h>
-
- 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
+++ /dev/null
-/*
- 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 <stdint.h>
- #include <stdbool.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- //----------------------------------------
- // 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 <stdarg.h>
- #include <stdlib.h>
-
- 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
/*
- 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
#include "cpp_ext.c"
#include "Core.lib.c"
- #include "FG.lib.c"
+ #include "Binding.lib.c"
#define TM·DEBUG
#ifdef TM·DEBUG
| 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·<TM·CVT>·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{
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);
);
#endif
+#endif
//--------------------------------------------------------------------------------
// Implementation
-#ifdef TM·IMPLEMENTATION
+#ifdef IMPLEMENTATION
// implementation to go into the lib.a file
//
#ifdef LOCAL
//----------------------------------------
- // Dispatch wrapper
+ // included first without defining TM·CVT
//----------------------------------------
#ifndef TM·CVT
//----------------------------------------
// 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
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
//----------------------------------------
// 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
+++ /dev/null
- // 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
#include <stdio.h>
#define DEBUG_CPP
+
+// print the macro and the evaluation of the macro at compile time:
+// #pragma message( STR_VAL(<macro>) )
+
#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))
/*===========================================================================
( 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
( 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
+++ /dev/null
-#ifndef Mpblock·ENVIRONMENT_H
-#define Mpblock·ENVIRONMENT_H
-
-
-#endif
+++ /dev/null
-/*
-
- A placeholder to see if make etc. is working.
-
-*/
-
-#define IFACE
-#include <stdio.h>
-#include <stdlib.h>
-
-// 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;
-}
+++ /dev/null
-/*
- 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 <stdint.h>
- #include <stddef.h>
-
- 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
--- /dev/null
+/*
+ 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 <stdint.h>
+ #include <stdbool.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+
+ //----------------------------------------
+ // 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 <stdarg.h>
+ #include <stdlib.h>
+
+ 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
--- /dev/null
+/*
+ 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 <stdint.h>
+ #include <stdbool.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+
+ //----------------------------------------
+ // 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 <stdarg.h>
+ #include <stdlib.h>
+
+ 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
--- /dev/null
+/*
+ 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 <stdint.h>
+ #include <stdbool.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+
+ //----------------------------------------
+ // 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 <stdarg.h>
+ #include <stdlib.h>
+
+ 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
--- /dev/null
+/*
+ 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 <stdint.h>
+ #include <stdbool.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+
+ //----------------------------------------
+ // 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 <stdarg.h>
+ #include <stdlib.h>
+
+ 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
--- /dev/null
+ // 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
--- /dev/null
+#ifndef Mpblock·ENVIRONMENT_H
+#define Mpblock·ENVIRONMENT_H
+
+
+#endif
--- /dev/null
+/*
+
+ A placeholder to see if make etc. is working.
+
+*/
+
+#define IFACE
+#include <stdio.h>
+#include <stdlib.h>
+
+// 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;
+}
--- /dev/null
+/*
+ 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 <stdint.h>
+ #include <stddef.h>
+
+ 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
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:
--- /dev/null
+
+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
+
--- /dev/null
+/*
+ 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"
+++ /dev/null
-/*
- 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__<x>__oo__<y>, 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 <stdio.h>
-#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 `_<name>_`
-// 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__<x>__oo__<y>
- 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)(<true case>)(<false case>)
-
- 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
+++ /dev/null
-/*
-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
+++ /dev/null
-// from http://jhnet.co.uk/articles/cpp_magic
-
-#include <stdio.h>
-#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. ...
- */
-
-};
+++ /dev/null
-#include <stdio.h>
-#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
-
-*/
+++ /dev/null
-#include <stdio.h>
-#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 <stdio.h>
-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)
-
-*/
+++ /dev/null
-#include <stdio.h>
-
-#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;
-}
+++ /dev/null
-// from http://jhnet.co.uk/articles/cpp_magic
-
-#include <stdio.h>
-
-#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");
-
-};
+++ /dev/null
-#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
-*/
+++ /dev/null
-#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§
- >
-*/
-
-
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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;
-}
--- /dev/null
+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
--- /dev/null
+/*
+ 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__<x>__oo__<y>, 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 <stdio.h>
+#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 `_<name>_`
+// 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__<x>__oo__<y>
+ 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)(<true case>)(<false case>)
+
+ 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
--- /dev/null
+/*
+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
--- /dev/null
+// from http://jhnet.co.uk/articles/cpp_magic
+
+#include <stdio.h>
+#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. ...
+ */
+
+};
--- /dev/null
+#include <stdio.h>
+#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
+
+*/
--- /dev/null
+#include <stdio.h>
+#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 <stdio.h>
+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)
+
+*/
--- /dev/null
+#include <stdio.h>
+
+#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;
+}
--- /dev/null
+// from http://jhnet.co.uk/articles/cpp_magic
+
+#include <stdio.h>
+
+#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");
+
+};
--- /dev/null
+#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
+*/
--- /dev/null
+#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§
+ >
+*/
+
+
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
set -x
cd "$REPO_HOME"/developer || exit 1
-
- pushd python
- ./fill_template
- popd
/bin/make -f tool🖉/makefile $@
set +x
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