Skip to content

Instantly share code, notes, and snippets.

@AlexCeleste
Created September 27, 2022 16:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexCeleste/76c1f62321ae21d3c1304052fe6c4830 to your computer and use it in GitHub Desktop.
Save AlexCeleste/76c1f62321ae21d3c1304052fe6c4830 to your computer and use it in GitHub Desktop.
#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);
}
#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);
}
#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 });
}
// 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)
#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);
}
// 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