enums
This commit is contained in:
+72
-13
@@ -65,6 +65,7 @@ Kind :: enum u8 {
|
||||
Named,
|
||||
Alias,
|
||||
Distinct,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
}
|
||||
@@ -91,6 +92,7 @@ Node :: struct {
|
||||
c_layout: bool,
|
||||
opaque: bool,
|
||||
declared: bool,
|
||||
explicit_backing: bool,
|
||||
}
|
||||
|
||||
Field :: struct {
|
||||
@@ -99,17 +101,24 @@ Field :: struct {
|
||||
offset: u64,
|
||||
}
|
||||
|
||||
Enum_Member :: struct {
|
||||
name: u32,
|
||||
value: i128,
|
||||
}
|
||||
|
||||
Store :: struct {
|
||||
nodes: [dynamic]Node,
|
||||
fields: [dynamic]Field,
|
||||
selected: target.Target,
|
||||
allocator: mem.Allocator,
|
||||
nodes: [dynamic]Node,
|
||||
fields: [dynamic]Field,
|
||||
enum_members: [dynamic]Enum_Member,
|
||||
selected: target.Target,
|
||||
allocator: mem.Allocator,
|
||||
}
|
||||
|
||||
init_store :: proc(allocator := context.allocator) -> Store {
|
||||
store: Store
|
||||
store.nodes.allocator = allocator
|
||||
store.fields.allocator = allocator
|
||||
store.enum_members.allocator = allocator
|
||||
store.selected = target.DEFAULT
|
||||
store.allocator = allocator
|
||||
return store
|
||||
@@ -118,19 +127,21 @@ init_store :: proc(allocator := context.allocator) -> Store {
|
||||
destroy_store :: proc(store: ^Store) {
|
||||
delete(store.nodes)
|
||||
delete(store.fields)
|
||||
delete(store.enum_members)
|
||||
}
|
||||
|
||||
clone_store :: proc(source: ^Store, allocator := context.allocator) -> Store {
|
||||
store := init_store(allocator)
|
||||
append(&store.nodes, ..source.nodes[:])
|
||||
append(&store.fields, ..source.fields[:])
|
||||
append(&store.enum_members, ..source.enum_members[:])
|
||||
store.selected = source.selected
|
||||
return store
|
||||
}
|
||||
|
||||
intern :: proc(store: ^Store, candidate: Node) -> Type {
|
||||
if candidate.kind != .Struct && candidate.kind != .Union &&
|
||||
candidate.kind != .Named && candidate.kind != .Distinct {
|
||||
candidate.kind != .Named && candidate.kind != .Distinct && candidate.kind != .Enum {
|
||||
for existing, index in store.nodes {
|
||||
if existing == candidate {
|
||||
return DYNAMIC_START+Type(index)
|
||||
@@ -146,7 +157,7 @@ named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0, file: u32 = 0xf
|
||||
normalized_file := file if qualifier != 0 else u32(0)
|
||||
for existing, index in store.nodes {
|
||||
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Distinct ||
|
||||
existing.kind == .Struct || existing.kind == .Union) &&
|
||||
existing.kind == .Enum || existing.kind == .Struct || existing.kind == .Union) &&
|
||||
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier &&
|
||||
existing.file == normalized_file {
|
||||
return DYNAMIC_START+Type(index)
|
||||
@@ -158,7 +169,7 @@ named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0, file: u32 = 0xf
|
||||
find_named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0) -> Type {
|
||||
for existing, index in store.nodes {
|
||||
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Distinct ||
|
||||
existing.kind == .Struct || existing.kind == .Union) &&
|
||||
existing.kind == .Enum || existing.kind == .Struct || existing.kind == .Union) &&
|
||||
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier {
|
||||
return DYNAMIC_START+Type(index)
|
||||
}
|
||||
@@ -190,6 +201,22 @@ define_distinct :: proc(store: ^Store, id, child: Type) -> bool {
|
||||
return true
|
||||
}
|
||||
|
||||
define_enum :: proc(store: ^Store, id, backing: Type, members: []Enum_Member, explicit_backing: bool) -> bool {
|
||||
existing, ok := node(store, id)
|
||||
if !ok || existing.kind != .Named || existing.declared {
|
||||
return false
|
||||
}
|
||||
index := int(id-DYNAMIC_START)
|
||||
store.nodes[index].kind = .Enum
|
||||
store.nodes[index].child = backing
|
||||
store.nodes[index].field_start = u32(len(store.enum_members))
|
||||
store.nodes[index].field_count = u32(len(members))
|
||||
store.nodes[index].explicit_backing = explicit_backing
|
||||
store.nodes[index].declared = true
|
||||
append(&store.enum_members, ..members)
|
||||
return true
|
||||
}
|
||||
|
||||
define_record :: proc(
|
||||
store: ^Store,
|
||||
id: Type,
|
||||
@@ -247,6 +274,19 @@ params_for :: proc(store: ^Store, value: Type) -> []Field {
|
||||
return store.fields[start:end]
|
||||
}
|
||||
|
||||
enum_members_for :: proc(store: ^Store, value: Type) -> []Enum_Member {
|
||||
item, ok := node(store, value)
|
||||
if !ok || item.kind != .Enum {
|
||||
return nil
|
||||
}
|
||||
start := int(item.field_start)
|
||||
end := start+int(item.field_count)
|
||||
if start < 0 || end > len(store.enum_members) {
|
||||
return nil
|
||||
}
|
||||
return store.enum_members[start:end]
|
||||
}
|
||||
|
||||
kind :: proc(value: Type, store: ^Store = nil) -> Kind {
|
||||
switch value {
|
||||
case INVALID:
|
||||
@@ -409,7 +449,8 @@ is_concrete_scalar :: proc(value: Type) -> bool {
|
||||
is_concrete :: proc(value: Type, store: ^Store = nil) -> bool {
|
||||
value_kind := kind(value, store)
|
||||
if value_kind == .Scalar || value_kind == .Array || value_kind == .Pointer ||
|
||||
value_kind == .Slice || value_kind == .Range || value_kind == .Optional {
|
||||
value_kind == .Slice || value_kind == .Range || value_kind == .Optional ||
|
||||
value_kind == .Enum {
|
||||
return true
|
||||
}
|
||||
if value_kind == .Struct || value_kind == .Union {
|
||||
@@ -460,6 +501,10 @@ is_distinct :: proc(value: Type, store: ^Store) -> bool {
|
||||
return kind(value, store) == .Distinct
|
||||
}
|
||||
|
||||
is_enum :: proc(value: Type, store: ^Store) -> bool {
|
||||
return kind(value, store) == .Enum
|
||||
}
|
||||
|
||||
resolve_alias :: proc(value: Type, store: ^Store, depth := 0) -> Type {
|
||||
if depth > 64 {
|
||||
return INVALID
|
||||
@@ -486,6 +531,9 @@ is_c_record_field_type :: proc(value: Type, store: ^Store, depth := 0) -> bool {
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if item.kind == .Enum {
|
||||
return item.explicit_backing && is_concrete_integer(item.child)
|
||||
}
|
||||
if item.kind == .Array {
|
||||
return item.count > 0 && !item.has_sentinel && !item.inferred_count &&
|
||||
is_c_record_field_type(item.child, store, depth+1)
|
||||
@@ -524,7 +572,7 @@ is_runtime_value :: proc(value: Type, store: ^Store, depth := 0) -> bool {
|
||||
item, ok := node(store, value)
|
||||
return ok && item.declared && !item.opaque && (!item.c_layout || item.field_count > 0)
|
||||
}
|
||||
if value_kind == .Distinct {
|
||||
if value_kind == .Distinct || value_kind == .Enum {
|
||||
item, ok := node(store, value)
|
||||
return ok && item.declared && is_runtime_value(item.child, store, depth+1)
|
||||
}
|
||||
@@ -541,7 +589,7 @@ runtime_representation :: proc(value: Type, store: ^Store, depth := 0) -> Type {
|
||||
return INVALID
|
||||
}
|
||||
item, ok := node(store, value)
|
||||
if !ok || item.kind != .Distinct {
|
||||
if !ok || (item.kind != .Distinct && item.kind != .Enum) {
|
||||
return value
|
||||
}
|
||||
return runtime_representation(item.child, store, depth+1)
|
||||
@@ -585,6 +633,9 @@ is_c_signature_type :: proc(value: Type, store: ^Store, allow_void := false) ->
|
||||
if contains_distinct(value, store) {
|
||||
return false
|
||||
}
|
||||
if item, ok := node(store, value); ok && item.kind == .Enum {
|
||||
return item.explicit_backing && is_concrete_integer(item.child)
|
||||
}
|
||||
return is_concrete_scalar(value) || is_pointer(value, store) || is_optional_pointer(value, store) ||
|
||||
(is_c_struct(value, store) && is_runtime_value(value, store))
|
||||
}
|
||||
@@ -621,7 +672,12 @@ is_c_integer_promotion_candidate :: proc(value: Type) -> bool {
|
||||
return value >= C_CHAR && value <= C_USHORT
|
||||
}
|
||||
|
||||
c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT) -> Type {
|
||||
c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT, store: ^Store = nil) -> Type {
|
||||
if store != nil {
|
||||
if item, ok := node(store, value); ok && item.kind == .Enum {
|
||||
return c_vararg_promotion(item.child, selected, store)
|
||||
}
|
||||
}
|
||||
if !is_concrete_scalar(value) {
|
||||
return value
|
||||
}
|
||||
@@ -642,6 +698,9 @@ c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT) -> Type {
|
||||
}
|
||||
|
||||
is_c_vararg_type :: proc(value: Type, store: ^Store) -> bool {
|
||||
if item, ok := node(store, value); ok && item.kind == .Enum {
|
||||
return item.explicit_backing && is_concrete_integer(item.child)
|
||||
}
|
||||
return is_concrete_scalar(value) || is_pointer(value, store) || is_optional_pointer(value, store)
|
||||
}
|
||||
|
||||
@@ -909,7 +968,7 @@ size :: proc(value: Type, store: ^Store, selected := target.DEFAULT) -> u64 {
|
||||
return ((child_size+1+child_align-1)/child_align)*child_align
|
||||
case .Function:
|
||||
return 0
|
||||
case .Distinct:
|
||||
case .Distinct, .Enum:
|
||||
return size(child_type(value, store), store, selected)
|
||||
case .Struct:
|
||||
item, _ := node(store, value)
|
||||
@@ -952,7 +1011,7 @@ alignment_of :: proc(value: Type, store: ^Store, selected := target.DEFAULT) ->
|
||||
return alignment_of(child_type(value, store), store, selected)
|
||||
case .Function:
|
||||
return 1
|
||||
case .Distinct:
|
||||
case .Distinct, .Enum:
|
||||
return alignment_of(child_type(value, store), store, selected)
|
||||
case .Struct:
|
||||
item, _ := node(store, value)
|
||||
|
||||
Reference in New Issue
Block a user