In Zig 0.8.0, When switching over u8 characters to get an enum type, I encountered a strange compiler error from this code:
.op_type = switch(c1) {
'+' => .add, '-' => .sub,
'*' => .mul, '/' => .div,
'%' => .mod, '^' => .exp,
'|' => .bor, '~' => .bxor,
'&' => .band,
'<' => if (is_long) .lte else .lt,
'>' => if (is_long) .gte else .gt,
'=' => if (is_long) .eq else .nop,
'!' => if (is_long) .neq else return TokenError.NotAToken,
else => unreachable
}
The error was:
.\lib.zig:137:36: error: values of type '(enum literal)' must be comptime known
'<' => if (is_long) .lte else .lt,
^
Normally in zig, "must be comptime known
" messages mean that I have left off a type signature on a runtime value, such as const x = 3;
. However, there aren't signatures in a switch expression, and the compiler should know what the type is anyway because the field .op_type
takes an Op
type enum.
I was able to solve the issue by using a switch statement instead of an expression, which I used to assign a placeholder value. The result is atrocious:
var op_type: Op = undefined;
switch(c1) {
'+' => op_type = .add, '-' => op_type = .sub,
'*' => op_type = .mul, '/' => op_type = .div,
'%' => op_type = .mod, '^' => op_type = .exp,
'|' => op_type = .bor, '~' => op_type = .bxor,
'&' => op_type = .band,
'<' => if (is_long) {op_type = .lte;} else {op_type = .lt;},
'>' => if (is_long) {op_type = .gte;} else {op_type = .gt;},
'=' => if (is_long) {op_type = .eq ;} else {op_type = .nop;},
'!' => if (is_long) {op_type = .neq;} else return TokenError.NotAToken,
else => unreachable
}
...
... {
...
.op_type = op_type
}
The reason I'm posting this question is that I don't really understand the problem with the first implementation, and I would like to see if there is a better solution than what I came up with.