68 lines
2.0 KiB
Plaintext
68 lines
2.0 KiB
Plaintext
import "@std/meta"
|
|
|
|
#! keys may be enums or native enum compositions that normalize to an enum, including aliases.
|
|
#! shared variant names follow native composition identity; payload-bearing sums are not enum keys.
|
|
EnumMap proc($E, $V type) type {
|
|
match typeinfo!(E) {
|
|
.enum |info|: return struct {
|
|
present [info.fields.len]mut bool # fixme: replace with bitset
|
|
values [info.fields.len]mut V
|
|
}
|
|
else: compile_error!("EnumMap key must be an enum")
|
|
}
|
|
}
|
|
|
|
init proc(
|
|
$E, $V type,
|
|
values meta.EnumFieldStruct(E, ?V, some!(null)),
|
|
) EnumMap(E, V) {
|
|
return initialize(E, V, null, values)
|
|
}
|
|
|
|
#! initializes absent value slots without making their keys present.
|
|
#! use fully initialized storage when a sparse map must be materialized at compile time.
|
|
init_filled proc(
|
|
$E, $V type,
|
|
storage_default V,
|
|
values meta.EnumFieldStruct(E, ?V, some!(null)),
|
|
) EnumMap(E, V) {
|
|
return initialize(E, V, some!(storage_default), values)
|
|
}
|
|
|
|
@hide:file
|
|
initialize proc(
|
|
$E, $V type,
|
|
storage_default ?V,
|
|
values meta.EnumFieldStruct(E, ?V, some!(null)),
|
|
) EnumMap(E, V) {
|
|
map EnumMap(E, V) := undefined
|
|
|
|
match typeinfo!(E) {
|
|
.enum |info|: inline for info.fields |field, i| {
|
|
map.present[i] = false
|
|
|
|
if field!(values, field.name) |value| {
|
|
map.present[i] = true
|
|
map.values[i] = value
|
|
} else if (storage_default) |value| map.values[i] = value
|
|
}
|
|
else: compile_error!("EnumMap key must be an enum")
|
|
}
|
|
|
|
return map
|
|
}
|
|
|
|
get proc($E, $V type, map @EnumMap(E, V), key E) ?V {
|
|
# fixme: linear lookup; implement an enum index/discriminant map for O(1) lookup
|
|
match typeinfo!(E) {
|
|
.enum |info|: inline for info.fields |field, i| {
|
|
if key == field!(E, field.name) {
|
|
if (map.present[i]) return some!(map.values[i])
|
|
return null
|
|
}
|
|
}
|
|
else: compile_error!("EnumMap key must be an enum")
|
|
}
|
|
return null
|
|
}
|