Generic vector
One macro generates a typed growable vector per element type: generics without a runtime.
+ <stdio.h>
+ <stdlib.h>
# One macro stamps out a typed growable vector per element type: generics without a runtime.
@m vec($T, $name, $push)
s $name
data: *`$ T`
len,cap: i32
f $push(v: *$name, x: $T)
if v->len == v->cap
v->cap = v->cap ? v->cap * 2 : 4
v->data = realloc(v->data, v->cap * sizeof($T))
v->data[v->len++] = x
@vec(int, IntVec, IntVec_push)
@vec(double, DoubleVec, DoubleVec_push)
f main()
a: IntVec = {0}
b: DoubleVec = {0}
for i := 0; i < 10; i++
IntVec_push(&a, i * 3)
DoubleVec_push(&b, i / 4.0)
printf("ints %d, last %d, cap %d\n", a.len, a.data[a.len - 1], a.cap)
printf("doubles %d, last %g\n", b.len, b.data[b.len - 1])
free(a.data)
free(b.data)
< 0
#include <stdio.h>
#include <stdlib.h>
typedef struct IntVec IntVec;
struct IntVec {
$ T *data;
int len,cap;
};
void IntVec_push(IntVec *v, int x) {
if (v->len == v->cap) {
v->cap = v->cap ? v->cap * 2 : 4;
v->data = realloc(v->data, v->cap * sizeof(int));
}
v->data[v->len++] = x;
}
typedef struct DoubleVec DoubleVec;
struct DoubleVec {
$ T *data;
int len,cap;
};
void DoubleVec_push(DoubleVec *v, double x) {
if (v->len == v->cap) {
v->cap = v->cap ? v->cap * 2 : 4;
v->data = realloc(v->data, v->cap * sizeof(double));
}
v->data[v->len++] = x;
}
int main(void) {
IntVec a = {0};
DoubleVec b = {0};
for (int i = 0; i < 10; i++) {
IntVec_push(&a, i * 3);
DoubleVec_push(&b, i / 4.0);
}
printf("ints %d, last %d, cap %d\n", a.len, a.data[a.len - 1], a.cap);
printf("doubles %d, last %g\n", b.len, b.data[b.len - 1]);
free(a.data);
free(b.data);
return 0;
}
What it shows
@m, code generation