I want to learn some Zig (that is, literally this is my third day with Zig), so I've decided to write a simple 6502 based 8 bit computer emulator in Zig, based on an existing C project of mine. However I have encountered a problem, I have no idea how I can solve in Zig in an elegant way at least:
#define SOME_MACRO(a,b,OP) do { \
...
some_stuff = a OP b; \
...
} while (0)
... much later ...
SOME_MACRO(u1,u2,|); // OR operand version
...
SOME_MACRO(u1,u2,&); // AND operand version
... etc ...
Obviously, the real code is much more complicated than this, but the key point, that the actual operator (like |
or &
) is passed as "C macro argument".
As far as I know about Zig so far, I can use inline
'd comptime
stuff to have similar behaviour as the C macro, but I have no idea how to pass an operator as an argument. This is also a curiosity in me, since, of course, with some meta-programming like pattern (maybe using for
with comptime
) I can generate the needed inline
functions before and I can use one of them on demand later, instead of the same "SOME_MACRO".
Is there some @builtin
to push directly an operator "name" to the compiler from a constant given by a call parameter or something similar?
Zig doesn't have a way to pass an operator to a function, instead you'll have to use comptime or runtime branching or pass a callback function
#define SOME_MACRO(a,b,OP) do { \
...
some_stuff = a OP b; \
...
} while (0)
With a callback function:
fn SOME_MACRO(a: i32, b: i32, comptime OP: fn(a: i32, b: i32) i32) i32 {
const my_value = OP(a, b);
// or force inline with @call(.always_inline, OP, .{a, b});
return my_value;
}
fn OP_ADD(a: i32, b: i32) i32 {
return a + b;
}
const std = @import("std");
test "my macro" {
try std.testing.assert(SOME_MACRO(5, 6, OP_ADD) == 11);
}
With a comptime switch:
const Operator = enum {add, sub, mul, div, bitwise_or, bitwise_and};
fn SOME_MACRO(a: i32, b: i32, comptime OP: Operator) i32 {
return inline switch(OP) {
.add => a + b,
.sub => a - b,
.mul => a * b,
.div => @divTrunc(a, b),
.bitwise_or => a | b,
.bitwise_and => a & b,
};
}
const std = @import("std");
test "my macro" {
try std.testing.assert(SOME_MACRO(5, 6, .add) == 11);
}