| git.druid.rocks | index | druid520 | nscc | test/ | t53_funcptr.nsc |
test/t53_funcptr.nsc
/* function pointers: &name takes a function's address (a plain ptr),
* and calling a ptr value is an indirect call. a small dispatch table
* picks an op by index; every result is distinct, so the exit code
* proves the RIGHT function ran each time. */
i32 add(i32 a, i32 b) { return a + b; }
i32 sub(i32 a, i32 b) { return a - b; }
i32 mul(i32 a, i32 b) { return a * b; }
i64 hits = 0;
void bump(void) { hits = hits + 1; }
ptr pick(ptr a, ptr b, i32 which) {
if (which) { return a; }
return b;
}
struct ops { ptr fn; i32 bias; };
global i32 main(void) {
ptr tbl[3];
tbl[0] = &add;
tbl[1] = ⊂
tbl[2] = &mul;
i32 acc = 0;
i32 i = 0;
/* (7+3) + (7-3) + (7*3) = 10 + 4 + 21 = 35 */
while (i < 3) {
acc = acc + (i32)tbl[i](7, 3);
i++;
}
/* a plain ptr variable, called by its bare name */
ptr f = &mul;
acc = acc + (i32)f(2, 5); /* 45 */
/* a call through a ptr returned by a call */
acc = acc + (i32)pick(&sub, &add, 1)(9, 4); /* sub: 50 */
/* a statement-level indirect call to a void function */
ptr g = ≎
g();
g();
/* through a struct field */
struct ops o;
o.fn = &add;
o.bias = 1;
acc = acc + (i32)o.fn(o.bias, 1); /* 52 */
/* function addresses compare like any other ptr */
if (tbl[2] == f) { acc = acc + 1; } /* 53 */
if (tbl[0] != f) { acc = acc + 1; } /* 54 */
return acc + (i32)hits; /* 56 */
}