Created
September 27, 2022 16:38
-
-
Save AlexCeleste/76c1f62321ae21d3c1304052fe6c4830 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
// typeclasses | |
#define ToLvalue(V) (&(struct { typeof (V) v; }){ V }.v) | |
typedef void (*BinOp) (void * out, void const * lhs, void const * rhs); | |
struct SumInst { | |
BinOp add; | |
BinOp sub; | |
}; | |
void addInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
void subInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
struct SumInst intInst = { | |
addInt, subInt | |
}; | |
void addFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
void subFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
struct SumInst fltInst = { | |
addFloat, subFloat | |
}; | |
void useAdd (struct SumInst const sumInst, void * out, void const * lhs, void const * rhs) | |
{ | |
sumInst.add (out, lhs, rhs); | |
} | |
void call (int x, float y) | |
{ | |
int ri; | |
float rf; | |
useAdd (intInst, &ri, ToLvalue (x), ToLvalue (x)); | |
useAdd (fltInst, &rf, ToLvalue (y), ToLvalue (y)); | |
printf ("%d %f\n", ri, rf); // 12 25.00 | |
} | |
int main (void) { | |
call (6, 12.5); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "typeclass.h" | |
// typeclasses | |
#define ToLvalue(V) (&(struct { typeof (V) v; }){ V }.v) | |
typedef void (*BinOp) (void * out, void const * lhs, void const * rhs); | |
typedef struct SumInst { | |
BinOp add; | |
BinOp sub; | |
} Sum; | |
#include "type_counter.h" | |
ADD_TYPEID (Sum); | |
void addInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
void subInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, int, { | |
addInt, subInt | |
}); | |
void addFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
void subFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, float, { | |
addFloat, subFloat | |
}); | |
void useAdd (Sum const sum, void * out, void const * lhs, void const * rhs) | |
{ | |
sum.add (out, lhs, rhs); | |
} | |
#define gAdd1(Ret, L, R) \ | |
useAdd (Instance (Sum, typeof(Ret)) \ | |
, &(Ret), ToLvalue (L), ToLvalue (R)) | |
#define gAdd2(L, R) ({ \ | |
typeof (L) _ret; \ | |
useAdd (Instance (Sum, typeof(_ret)) \ | |
, &(_ret), ToLvalue (L), ToLvalue (R)); \ | |
_ret; \ | |
}) | |
void call (int x, float y) | |
{ | |
int ri; | |
float rf; | |
Sum intInst = Instance (Sum, int); | |
Sum fltInst = Instance (Sum, float); | |
useAdd (intInst, &ri, ToLvalue (x), ToLvalue (x)); | |
useAdd (fltInst, &rf, ToLvalue (y), ToLvalue (y)); | |
printf ("%d %f\n", ri, rf); // 12 25.00 | |
ri = rf = 0; x += 1; y += 1; | |
gAdd1 (ri, x, x); | |
gAdd1 (rf, y, y); | |
printf ("%d %f\n", ri, rf); // 14 27.00 | |
ri = rf = 0; x += 1; y += 1; | |
ri = gAdd2 (x, x); | |
rf = gAdd2 (y, y); | |
printf ("%d %f\n", ri, rf); // 16 29.00 | |
} | |
int main (void) { | |
call (6, 12.5); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "typeclass.h" | |
// typeclasses | |
#define ToLvalue(V) (&(struct { typeof (V) v; }){ V }.v) | |
typedef void (*BinOp) (void * out, void const * lhs, void const * rhs); | |
typedef struct SumInst { | |
BinOp add; | |
BinOp sub; | |
} Sum; | |
#include "type_counter.h" | |
ADD_TYPEID (Sum); | |
void addInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
void subInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, int, { | |
addInt, subInt | |
}); | |
void addFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
void subFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, float, { | |
addFloat, subFloat | |
}); | |
typedef struct Fixie { | |
int rep; | |
} Fixie; | |
void addFix (void * out, void const * lhs, void const * rhs) { | |
((Fixie *)out)->rep = ((Fixie const *)lhs)->rep + ((Fixie const *)rhs)->rep; | |
} | |
void subFix (void * out, void const * lhs, void const * rhs) { | |
((Fixie *)out)->rep = ((Fixie const *)lhs)->rep - ((Fixie const *)rhs)->rep; | |
} | |
#include "type_counter.h" | |
ADD_TYPEID (Fixie); | |
#include "oper_counter.h" | |
DefInstance (Sum, Fixie, { | |
addFix, subFix | |
}); | |
void useAdd (Sum const sum, void * out, void const * lhs, void const * rhs) | |
{ | |
sum.add (out, lhs, rhs); | |
} | |
#define gAdd1(Ret, L, R) \ | |
useAdd (Instance (Sum, typeof(Ret)) \ | |
, &(Ret), ToLvalue (L), ToLvalue (R)) | |
#define gAdd2(L, R) ({ \ | |
typeof (L) _ret; \ | |
useAdd (Instance (Sum, typeof(_ret)) \ | |
, &(_ret), ToLvalue (L), ToLvalue (R)); \ | |
_ret; \ | |
}) | |
void call (int x, float y, Fixie z) | |
{ | |
int ri; | |
float rf; | |
Sum intInst = Instance (Sum, int); | |
Sum fltInst = Instance (Sum, float); | |
useAdd (intInst, &ri, ToLvalue (x), ToLvalue (x)); | |
useAdd (fltInst, &rf, ToLvalue (y), ToLvalue (y)); | |
printf ("%d %f\n", ri, rf); // 12 25.00 | |
ri = rf = 0; x += 1; y += 1; | |
gAdd1 (ri, x, x); | |
gAdd1 (rf, y, y); | |
printf ("%d %f\n", ri, rf); // 14 27.00 | |
ri = rf = 0; x += 1; y += 1; | |
ri = gAdd2 (x, x); | |
rf = gAdd2 (y, y); | |
printf ("%d %f\n", ri, rf); // 16 29.00 | |
Fixie rF = gAdd2 (z, z); | |
printf ("%d\n", rF.rep); // 22 | |
} | |
int main (void) { | |
call (6, 12.5, (Fixie){ 11 }); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// oper_counter.h | |
// | |
// increment the value of the counter | |
// every time this file is included | |
// | |
// this uses a value representation that can | |
// easily be converted to a single literal, for pasting | |
// | |
// value is handled by binary representation but | |
// stored in a record of single-bit fields rather than | |
// as a composite expression | |
// this can be used as the argument to a simple eval | |
// or a pretty-print, even supporting different fmts | |
// (0b, 0x, etc) - select with OPER_COUNTER_PRINT | |
// | |
// 20-bit hex by default | |
// | |
// no whole-file guard, repeatable inclusion | |
#ifndef OPER_COUNTER_RECORD | |
// starting value of zero | |
#define OPER_COUNTER_RECORD (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) | |
#else | |
#undef OPER_COUNT_COPY_BIT_0 | |
#undef OPER_COUNT_COPY_BIT_1 | |
#undef OPER_COUNT_COPY_BIT_2 | |
#undef OPER_COUNT_COPY_BIT_3 | |
#undef OPER_COUNT_COPY_BIT_4 | |
#undef OPER_COUNT_COPY_BIT_5 | |
#undef OPER_COUNT_COPY_BIT_6 | |
#undef OPER_COUNT_COPY_BIT_7 | |
#undef OPER_COUNT_COPY_BIT_8 | |
#undef OPER_COUNT_COPY_BIT_9 | |
#undef OPER_COUNT_COPY_BIT_10 | |
#undef OPER_COUNT_COPY_BIT_11 | |
#undef OPER_COUNT_COPY_BIT_12 | |
#undef OPER_COUNT_COPY_BIT_13 | |
#undef OPER_COUNT_COPY_BIT_14 | |
#undef OPER_COUNT_COPY_BIT_15 | |
#undef OPER_COUNT_COPY_BIT_16 | |
#undef OPER_COUNT_COPY_BIT_17 | |
#undef OPER_COUNT_COPY_BIT_18 | |
#undef OPER_COUNT_COPY_BIT_19 | |
#define OPER_COUNT_COPY_BIT_0 0 | |
#define OPER_COUNT_COPY_BIT_1 0 | |
#define OPER_COUNT_COPY_BIT_2 0 | |
#define OPER_COUNT_COPY_BIT_3 0 | |
#define OPER_COUNT_COPY_BIT_4 0 | |
#define OPER_COUNT_COPY_BIT_5 0 | |
#define OPER_COUNT_COPY_BIT_6 0 | |
#define OPER_COUNT_COPY_BIT_7 0 | |
#define OPER_COUNT_COPY_BIT_8 0 | |
#define OPER_COUNT_COPY_BIT_9 0 | |
#define OPER_COUNT_COPY_BIT_10 0 | |
#define OPER_COUNT_COPY_BIT_11 0 | |
#define OPER_COUNT_COPY_BIT_12 0 | |
#define OPER_COUNT_COPY_BIT_13 0 | |
#define OPER_COUNT_COPY_BIT_14 0 | |
#define OPER_COUNT_COPY_BIT_15 0 | |
#define OPER_COUNT_COPY_BIT_16 0 | |
#define OPER_COUNT_COPY_BIT_17 0 | |
#define OPER_COUNT_COPY_BIT_18 0 | |
#define OPER_COUNT_COPY_BIT_19 0 | |
#define OPER_INCRVAL (OPER_COUNTER + 1) | |
// update new values for bits | |
#if OPER_INCRVAL & (1ul << 0ul) | |
#undef OPER_COUNT_COPY_BIT_0 | |
#define OPER_COUNT_COPY_BIT_0 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 1ul) | |
#undef OPER_COUNT_COPY_BIT_1 | |
#define OPER_COUNT_COPY_BIT_1 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 2ul) | |
#undef OPER_COUNT_COPY_BIT_2 | |
#define OPER_COUNT_COPY_BIT_2 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 3ul) | |
#undef OPER_COUNT_COPY_BIT_3 | |
#define OPER_COUNT_COPY_BIT_3 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 4ul) | |
#undef OPER_COUNT_COPY_BIT_4 | |
#define OPER_COUNT_COPY_BIT_4 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 5ul) | |
#undef OPER_COUNT_COPY_BIT_5 | |
#define OPER_COUNT_COPY_BIT_5 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 6ul) | |
#undef OPER_COUNT_COPY_BIT_6 | |
#define OPER_COUNT_COPY_BIT_6 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 7ul) | |
#undef OPER_COUNT_COPY_BIT_7 | |
#define OPER_COUNT_COPY_BIT_7 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 8ul) | |
#undef OPER_COUNT_COPY_BIT_8 | |
#define OPER_COUNT_COPY_BIT_8 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 9ul) | |
#undef OPER_COUNT_COPY_BIT_9 | |
#define OPER_COUNT_COPY_BIT_9 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 10ul) | |
#undef OPER_COUNT_COPY_BIT_10 | |
#define OPER_COUNT_COPY_BIT_10 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 11ul) | |
#undef OPER_COUNT_COPY_BIT_11 | |
#define OPER_COUNT_COPY_BIT_11 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 12ul) | |
#undef OPER_COUNT_COPY_BIT_12 | |
#define OPER_COUNT_COPY_BIT_12 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 13ul) | |
#undef OPER_COUNT_COPY_BIT_13 | |
#define OPER_COUNT_COPY_BIT_13 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 14ul) | |
#undef OPER_COUNT_COPY_BIT_14 | |
#define OPER_COUNT_COPY_BIT_14 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 15ul) | |
#undef OPER_COUNT_COPY_BIT_15 | |
#define OPER_COUNT_COPY_BIT_15 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 16ul) | |
#undef OPER_COUNT_COPY_BIT_16 | |
#define OPER_COUNT_COPY_BIT_16 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 17ul) | |
#undef OPER_COUNT_COPY_BIT_17 | |
#define OPER_COUNT_COPY_BIT_17 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 18ul) | |
#undef OPER_COUNT_COPY_BIT_18 | |
#define OPER_COUNT_COPY_BIT_18 1 | |
#endif | |
#if OPER_INCRVAL & (1ul << 19ul) | |
#undef OPER_COUNT_COPY_BIT_19 | |
#define OPER_COUNT_COPY_BIT_19 1 | |
#endif | |
// update actual bits | |
#undef OPER_COUNT_BIT_0 | |
#undef OPER_COUNT_BIT_1 | |
#undef OPER_COUNT_BIT_2 | |
#undef OPER_COUNT_BIT_3 | |
#undef OPER_COUNT_BIT_4 | |
#undef OPER_COUNT_BIT_5 | |
#undef OPER_COUNT_BIT_6 | |
#undef OPER_COUNT_BIT_7 | |
#undef OPER_COUNT_BIT_8 | |
#undef OPER_COUNT_BIT_9 | |
#undef OPER_COUNT_BIT_10 | |
#undef OPER_COUNT_BIT_11 | |
#undef OPER_COUNT_BIT_12 | |
#undef OPER_COUNT_BIT_13 | |
#undef OPER_COUNT_BIT_14 | |
#undef OPER_COUNT_BIT_15 | |
#undef OPER_COUNT_BIT_16 | |
#undef OPER_COUNT_BIT_17 | |
#undef OPER_COUNT_BIT_18 | |
#undef OPER_COUNT_BIT_19 | |
#define OPER_COUNT_BIT_0 0 | |
#define OPER_COUNT_BIT_1 0 | |
#define OPER_COUNT_BIT_2 0 | |
#define OPER_COUNT_BIT_3 0 | |
#define OPER_COUNT_BIT_4 0 | |
#define OPER_COUNT_BIT_5 0 | |
#define OPER_COUNT_BIT_6 0 | |
#define OPER_COUNT_BIT_7 0 | |
#define OPER_COUNT_BIT_8 0 | |
#define OPER_COUNT_BIT_9 0 | |
#define OPER_COUNT_BIT_10 0 | |
#define OPER_COUNT_BIT_11 0 | |
#define OPER_COUNT_BIT_12 0 | |
#define OPER_COUNT_BIT_13 0 | |
#define OPER_COUNT_BIT_14 0 | |
#define OPER_COUNT_BIT_15 0 | |
#define OPER_COUNT_BIT_16 0 | |
#define OPER_COUNT_BIT_17 0 | |
#define OPER_COUNT_BIT_18 0 | |
#define OPER_COUNT_BIT_19 0 | |
#if OPER_COUNT_COPY_BIT_0 | |
#undef OPER_COUNT_BIT_0 | |
#define OPER_COUNT_BIT_0 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_1 | |
#undef OPER_COUNT_BIT_1 | |
#define OPER_COUNT_BIT_1 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_2 | |
#undef OPER_COUNT_BIT_2 | |
#define OPER_COUNT_BIT_2 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_3 | |
#undef OPER_COUNT_BIT_3 | |
#define OPER_COUNT_BIT_3 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_4 | |
#undef OPER_COUNT_BIT_4 | |
#define OPER_COUNT_BIT_4 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_5 | |
#undef OPER_COUNT_BIT_5 | |
#define OPER_COUNT_BIT_5 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_6 | |
#undef OPER_COUNT_BIT_6 | |
#define OPER_COUNT_BIT_6 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_7 | |
#undef OPER_COUNT_BIT_7 | |
#define OPER_COUNT_BIT_7 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_8 | |
#undef OPER_COUNT_BIT_8 | |
#define OPER_COUNT_BIT_8 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_9 | |
#undef OPER_COUNT_BIT_9 | |
#define OPER_COUNT_BIT_9 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_10 | |
#undef OPER_COUNT_BIT_10 | |
#define OPER_COUNT_BIT_10 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_11 | |
#undef OPER_COUNT_BIT_11 | |
#define OPER_COUNT_BIT_11 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_12 | |
#undef OPER_COUNT_BIT_12 | |
#define OPER_COUNT_BIT_12 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_13 | |
#undef OPER_COUNT_BIT_13 | |
#define OPER_COUNT_BIT_13 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_14 | |
#undef OPER_COUNT_BIT_14 | |
#define OPER_COUNT_BIT_14 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_15 | |
#undef OPER_COUNT_BIT_15 | |
#define OPER_COUNT_BIT_15 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_16 | |
#undef OPER_COUNT_BIT_16 | |
#define OPER_COUNT_BIT_16 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_17 | |
#undef OPER_COUNT_BIT_17 | |
#define OPER_COUNT_BIT_17 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_18 | |
#undef OPER_COUNT_BIT_18 | |
#define OPER_COUNT_BIT_18 1 | |
#endif | |
#if OPER_COUNT_COPY_BIT_19 | |
#undef OPER_COUNT_BIT_19 | |
#define OPER_COUNT_BIT_19 1 | |
#endif | |
#undef OPER_INCRVAL | |
#undef OPER_COUNTER_RECORD | |
#define OPER_COUNTER_RECORD \ | |
(OPER_COUNT_BIT_0 \ | |
,OPER_COUNT_BIT_1 \ | |
,OPER_COUNT_BIT_2 \ | |
,OPER_COUNT_BIT_3 \ | |
,OPER_COUNT_BIT_4 \ | |
,OPER_COUNT_BIT_5 \ | |
,OPER_COUNT_BIT_6 \ | |
,OPER_COUNT_BIT_7 \ | |
,OPER_COUNT_BIT_8 \ | |
,OPER_COUNT_BIT_9 \ | |
,OPER_COUNT_BIT_10 \ | |
,OPER_COUNT_BIT_11 \ | |
,OPER_COUNT_BIT_12 \ | |
,OPER_COUNT_BIT_13 \ | |
,OPER_COUNT_BIT_14 \ | |
,OPER_COUNT_BIT_15 \ | |
,OPER_COUNT_BIT_16 \ | |
,OPER_COUNT_BIT_17 \ | |
,OPER_COUNT_BIT_18 \ | |
,OPER_COUNT_BIT_19) | |
#endif | |
// convert record to either expression or single literal | |
#ifndef OPER_COUNTER_EVAL | |
#define OPER_COUNTER_EVAL( B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
( (B0 << 0ul ) | \ | |
(B1 << 1ul ) | \ | |
(B2 << 2ul ) | \ | |
(B3 << 3ul ) | \ | |
(B4 << 4ul ) | \ | |
(B5 << 5ul ) | \ | |
(B6 << 6ul ) | \ | |
(B7 << 7ul ) | \ | |
(B8 << 8ul ) | \ | |
(B9 << 9ul ) | \ | |
(B10 << 10ul) | \ | |
(B11 << 11ul) | \ | |
(B12 << 12ul) | \ | |
(B13 << 13ul) | \ | |
(B14 << 14ul) | \ | |
(B15 << 15ul) | \ | |
(B16 << 16ul) | \ | |
(B17 << 17ul) | \ | |
(B18 << 18ul) | \ | |
(B19 << 19ul) ) | |
// (two level paster) | |
#define OPER_COUNTER_DOPB( B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
0b ## B19##B18##B17##B16##B15##B14##B13##B12##B11##B10##B9##B8##B7##B6##B5##B4##B3##B2##B1##B0 ## ul | |
#define OPER_COUNTER_PBIN( B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
OPER_COUNTER_DOPB(B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) | |
#define OPER_COUNTER_DOH2(Pfx, H0, H1, H2, H3, H4, Sfx) \ | |
Pfx ## H0##H1##H2##H3##H4 ## Sfx | |
#define OPER_COUNTER_DOPH(Pfx, H0, H1, H2, H3, H4, Sfx) \ | |
OPER_COUNTER_DOH2(Pfx, H0, H1, H2, H3, H4, Sfx) | |
#define OPER_COUNTER_GHEX(Pfx, Sfx \ | |
, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
OPER_COUNTER_DOPH (Pfx \ | |
, OPER_COUNTER_HEXC(B19, B18, B17, B16) \ | |
, OPER_COUNTER_HEXC(B15, B14, B13, B12) \ | |
, OPER_COUNTER_HEXC(B11, B10, B9, B8 ) \ | |
, OPER_COUNTER_HEXC(B7, B6, B5, B4 ) \ | |
, OPER_COUNTER_HEXC(B3, B2, B1, B0 ) \ | |
, Sfx) | |
#define OPER_COUNTER_PHEX( B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
OPER_COUNTER_GHEX (0x, ul \ | |
, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) | |
#define OPER_COUNTER_DHEX( B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) \ | |
OPER_COUNTER_GHEX (/* empty */, /* empty */ \ | |
, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9 \ | |
, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19) | |
// generate hex digits from bits | |
#define OPER_COUNTER_HEXC(B0, B1, B2, B3) OPER_COUNTER_HEXC_ ##B0##B1##B2##B3 | |
#define OPER_COUNTER_HEXC_0000 0 | |
#define OPER_COUNTER_HEXC_0001 1 | |
#define OPER_COUNTER_HEXC_0010 2 | |
#define OPER_COUNTER_HEXC_0011 3 | |
#define OPER_COUNTER_HEXC_0100 4 | |
#define OPER_COUNTER_HEXC_0101 5 | |
#define OPER_COUNTER_HEXC_0110 6 | |
#define OPER_COUNTER_HEXC_0111 7 | |
#define OPER_COUNTER_HEXC_1000 8 | |
#define OPER_COUNTER_HEXC_1001 9 | |
#define OPER_COUNTER_HEXC_1010 a | |
#define OPER_COUNTER_HEXC_1011 b | |
#define OPER_COUNTER_HEXC_1100 c | |
#define OPER_COUNTER_HEXC_1101 d | |
#define OPER_COUNTER_HEXC_1110 e | |
#define OPER_COUNTER_HEXC_1111 f | |
// force expand pass | |
#define OPER_COUNTER_EXPAND(V) V | |
#ifndef OPER_COUNTER_PRINT | |
// default to hex printer: 0x12345ul | |
#define OPER_COUNTER_PRINT OPER_COUNTER_PHEX | |
#endif | |
// alt formats also accessible, good for name gen | |
#define OPER_COUNTER_BIN \ | |
OPER_COUNTER_EXPAND (OPER_COUNTER_PBIN OPER_COUNTER_RECORD) | |
#define OPER_COUNTER_HEX \ | |
OPER_COUNTER_EXPAND (OPER_COUNTER_PHEX OPER_COUNTER_RECORD) | |
#define OPER_COUNTER_EXPR \ | |
OPER_COUNTER_EXPAND (OPER_COUNTER_EVAL OPER_COUNTER_RECORD) | |
#define OPER_COUNTER_HEXDIG \ | |
OPER_COUNTER_EXPAND (OPER_COUNTER_DHEX OPER_COUNTER_RECORD) | |
#endif | |
// unconditional, this forces update even after manual reset | |
#undef OPER_COUNTER | |
#define OPER_COUNTER \ | |
OPER_COUNTER_EXPAND (OPER_COUNTER_PRINT OPER_COUNTER_RECORD) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "typeclass.h" | |
// typeclasses | |
#define ToLvalue(V) (&(struct { typeof (V) v; }){ V }.v) | |
typedef void (*BinOp) (void * out, void const * lhs, void const * rhs); | |
typedef struct SumInst { | |
BinOp add; | |
BinOp sub; | |
} Sum; | |
#include "type_counter.h" | |
ADD_TYPEID (Sum); | |
void addInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
void subInt (void * out, void const * lhs, void const * rhs) { | |
*(int *)out = *(int const *)lhs + *(int const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, int, { | |
addInt, subInt | |
}); | |
void addFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
void subFloat (void * out, void const * lhs, void const * rhs) { | |
*(float *)out = *(float const *)lhs + *(float const *) rhs; | |
} | |
#include "oper_counter.h" | |
DefInstance (Sum, float, { | |
addFloat, subFloat | |
}); | |
void useAdd (Sum const sum, void * out, void const * lhs, void const * rhs) | |
{ | |
sum.add (out, lhs, rhs); | |
} | |
void call (int x, float y) | |
{ | |
int ri; | |
float rf; | |
Sum intInst = Instance (Sum, int); | |
Sum fltInst = Instance (Sum, float); | |
useAdd (intInst, &ri, ToLvalue (x), ToLvalue (x)); | |
useAdd (fltInst, &rf, ToLvalue (y), ToLvalue (y)); | |
printf ("%d %f\n", ri, rf); // 12 25.00 | |
} | |
int main (void) { | |
call (6, 12.5); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// typeclass.h | |
// | |
// provide extendable overloads that hook in at current state of type counter | |
// | |
// NOTE this depends on external inclusion of TYPE_COUNTER | |
// there are plenty of values available, generate a new one for each new key | |
// | |
// requires typeof | |
// | |
#ifndef INCLUDED_TYPECLASS_H | |
#define INCLUDED_TYPECLASS_H | |
#include "typeid.h" | |
// #define DefTypeclass(TC) \ | |
// ADD_TYPEID(TC) \ | |
// typedef typeof(TC) TYPECLASS_GLUE(TYPECLASS_, OPER_COUNTER_HEXDIG); | |
// operations list probably contains commas | |
#define DefInstance(TC, IT, ...) \ | |
enum { \ | |
TYPECLASS_GLUE(TC_INST_CLASS_, OPER_COUNTER_HEXDIG) = TYPEID (TC), \ | |
TYPECLASS_GLUE(TC_INST_TYPE_, OPER_COUNTER_HEXDIG) = TYPEID (IT), \ | |
}; \ | |
TC TYPECLASS_GLUE(TC_INST_OPS_, OPER_COUNTER_HEXDIG) = __VA_ARGS__ // { a, b, c } | |
#define TYPECLASS_GLUE(A, B) TYPECLASS_GLUE2(A, B) | |
#define TYPECLASS_GLUE2(A, B) A ## B | |
#define Instance(InC, InT) \ | |
TYPECLASS_GLUE(TC_OPER_, OPER_COUNTER_HEXDIG) \ | |
(TYPEID(InC), TYPEID(InT)) | |
#define TYPECLASS_SEL(TCid, TIid) char(*)[TCid][TIid] | |
#define TYPECLASS_VAL(TCid, TIid) (TYPECLASS_SEL(TCid, TIid))0 | |
#define TYPECLASS_MAT(Id) \ | |
char(*)[TYPECLASS_GLUE (TC_INST_CLASS_, Id)] \ | |
[TYPECLASS_GLUE (TC_INST_TYPE_, Id)] | |
// auto-generate this part with a script, go up to some high value | |
// final branch needs a default (because even if this isn't selected, | |
// it still needs to type check), but the value should be unusable if reached | |
#define TC_OPER_00000(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00000) : TC_INST_OPS_00000, default: (void)0) | |
#define TC_OPER_00001(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00001) : TC_INST_OPS_00001, default: TC_OPER_00000 (C, I)) | |
#define TC_OPER_00002(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00002) : TC_INST_OPS_00002, default: TC_OPER_00001 (C, I)) | |
#define TC_OPER_00003(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00003) : TC_INST_OPS_00003, default: TC_OPER_00002 (C, I)) | |
#define TC_OPER_00004(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00004) : TC_INST_OPS_00004, default: TC_OPER_00003 (C, I)) | |
#define TC_OPER_00005(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00005) : TC_INST_OPS_00005, default: TC_OPER_00004 (C, I)) | |
#define TC_OPER_00006(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00006) : TC_INST_OPS_00006, default: TC_OPER_00005 (C, I)) | |
#define TC_OPER_00007(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00007) : TC_INST_OPS_00007, default: TC_OPER_00006 (C, I)) | |
#define TC_OPER_00008(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00008) : TC_INST_OPS_00008, default: TC_OPER_00007 (C, I)) | |
#define TC_OPER_00009(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00009) : TC_INST_OPS_00009, default: TC_OPER_00008 (C, I)) | |
#define TC_OPER_0000a(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000a) : TC_INST_OPS_0000a, default: TC_OPER_00009 (C, I)) | |
#define TC_OPER_0000b(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000b) : TC_INST_OPS_0000b, default: TC_OPER_0000a (C, I)) | |
#define TC_OPER_0000c(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000c) : TC_INST_OPS_0000c, default: TC_OPER_0000b (C, I)) | |
#define TC_OPER_0000d(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000d) : TC_INST_OPS_0000d, default: TC_OPER_0000c (C, I)) | |
#define TC_OPER_0000e(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000e) : TC_INST_OPS_0000e, default: TC_OPER_0000d (C, I)) | |
#define TC_OPER_0000f(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0000f) : TC_INST_OPS_0000f, default: TC_OPER_0000e (C, I)) | |
#define TC_OPER_00010(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00010) : TC_INST_OPS_00010, default: TC_OPER_0000f (C, I)) | |
#define TC_OPER_00011(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00011) : TC_INST_OPS_00011, default: TC_OPER_00010 (C, I)) | |
#define TC_OPER_00012(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00012) : TC_INST_OPS_00012, default: TC_OPER_00011 (C, I)) | |
#define TC_OPER_00013(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00013) : TC_INST_OPS_00013, default: TC_OPER_00012 (C, I)) | |
#define TC_OPER_00014(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00014) : TC_INST_OPS_00014, default: TC_OPER_00013 (C, I)) | |
#define TC_OPER_00015(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00015) : TC_INST_OPS_00015, default: TC_OPER_00014 (C, I)) | |
#define TC_OPER_00016(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00016) : TC_INST_OPS_00016, default: TC_OPER_00015 (C, I)) | |
#define TC_OPER_00017(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00017) : TC_INST_OPS_00017, default: TC_OPER_00016 (C, I)) | |
#define TC_OPER_00018(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00018) : TC_INST_OPS_00018, default: TC_OPER_00017 (C, I)) | |
#define TC_OPER_00019(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00019) : TC_INST_OPS_00019, default: TC_OPER_00018 (C, I)) | |
#define TC_OPER_0001a(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001a) : TC_INST_OPS_0001a, default: TC_OPER_00019 (C, I)) | |
#define TC_OPER_0001b(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001b) : TC_INST_OPS_0001b, default: TC_OPER_0001a (C, I)) | |
#define TC_OPER_0001c(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001c) : TC_INST_OPS_0001c, default: TC_OPER_0001b (C, I)) | |
#define TC_OPER_0001d(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001d) : TC_INST_OPS_0001d, default: TC_OPER_0001c (C, I)) | |
#define TC_OPER_0001e(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001e) : TC_INST_OPS_0001e, default: TC_OPER_0001d (C, I)) | |
#define TC_OPER_0001f(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(0001f) : TC_INST_OPS_0001f, default: TC_OPER_0001e (C, I)) | |
#define TC_OPER_00020(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00020) : TC_INST_OPS_00020, default: TC_OPER_0001f (C, I)) | |
#define TC_OPER_00021(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00021) : TC_INST_OPS_00021, default: TC_OPER_00020 (C, I)) | |
#define TC_OPER_00022(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00022) : TC_INST_OPS_00022, default: TC_OPER_00021 (C, I)) | |
#define TC_OPER_00023(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00023) : TC_INST_OPS_00023, default: TC_OPER_00022 (C, I)) | |
#define TC_OPER_00024(C, I) _Generic(TYPECLASS_VAL(C, I), TYPECLASS_MAT(00024) : TC_INST_OPS_00024, default: TC_OPER_00023 (C, I)) | |
// etc | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment