I’ll try and explain what I need to get working.
In the base code I work with the Terms array.
Now I am making a function which has to extract the name of one of the arrays, when passing the address of one ScorePair argument using the global var terms.
pub fn using_scorepair(sp: *const ScorePair) void {
// in which array resides this sp argument (kind of doable if the compiled order is the same)
// what is the declaration name of that array inside Terms (without if if if if)
}
pub const terms: *const Terms = &default_terms; // default_terms not included here.
pub const Terms = struct {
piece_value: [6]ScorePair,
king_passed_pawn_distance: [8]ScorePair,
enemy_king_passed_pawn_distance: [8]ScorePair,
pawn_phalanx: [8]ScorePair,
passed_pawn: [8]ScorePair,
protected_pawn: [8]ScorePair,
doubled_pawn: [8]ScorePair,
isolated_pawn: [8]ScorePair,
backward_pawn: [8]ScorePair,
king_cannot_reach_passed_pawn: ScorePair,
bishop_pair: ScorePair,
tempo: ScorePair,
knight_mobility: [9]ScorePair,
bishop_mobility: [14]ScorePair,
rook_mobility: [15]ScorePair,
queen_mobility: [28]ScorePair,
attack_power: [6][8]ScorePair,
// some more....
};
pub const ScorePair = struct {
mg: i16,
eg: i16,
};
Probably can’t be done without a pointer to Terms, but if that’s fine, I came up with this comptime monster:
pub const Terms = struct {
piece_value: [6]ScorePair,
king_passed_pawn_distance: [8]ScorePair,
enemy_king_passed_pawn_distance: [8]ScorePair,
pawn_phalanx: [8]ScorePair,
passed_pawn: [8]ScorePair,
protected_pawn: [8]ScorePair,
doubled_pawn: [8]ScorePair,
isolated_pawn: [8]ScorePair,
backward_pawn: [8]ScorePair,
king_cannot_reach_passed_pawn: ScorePair,
bishop_pair: ScorePair,
tempo: ScorePair,
knight_mobility: [9]ScorePair,
bishop_mobility: [14]ScorePair,
rook_mobility: [15]ScorePair,
queen_mobility: [28]ScorePair,
attack_power: [6][8]ScorePair,
// some more....
};
pub const ScorePair = struct {
mg: i16,
eg: i16,
};
fn isScorePairType(T: type) bool {
if (T == ScorePair)
return true;
return switch (@typeInfo(T)) {
.array => |array| isScorePairType(array.child),
else => false,
};
}
fn scorePairName(terms: *const Terms, pair: *const ScorePair) []const u8 {
const names = comptime blk: {
var names: [@sizeOf(Terms) / @sizeOf(ScorePair)][]const u8 = @splat("UNKNOWN");
for (std.meta.fields(Terms)) |field| {
if (!isScorePairType(field.type))
@compileError("Field '" ++ field.name ++ "' is not a (array of) ScorePair");
const start_idx = @offsetOf(Terms, field.name) / @sizeOf(ScorePair);
const end_idx = start_idx + @sizeOf(field.type) / @sizeOf(ScorePair);
names[start_idx..end_idx].* = @splat(field.name);
}
break :blk names;
};
const terms_arr: []const ScorePair = @ptrCast(terms);
std.debug.assert(@intFromPtr(pair) > @intFromPtr(terms_arr.ptr));
const idx = pair - terms_arr.ptr;
std.debug.assert(idx < terms_arr.len);
return names[idx];
}
pub fn main() void {
const some_terms: Terms = undefined;
std.debug.print("{s}\n", .{scorePairName(&some_terms, &some_terms.isolated_pawn[3])});
}
const std = @import("std");
1 Like
That looks like a working comptime monster. I don’t care if it is monster 
Thx. I’ll try and go from this one.
1 Like