allocator interface (first pass)

This commit is contained in:
2026-07-06 21:24:49 +02:00
parent 7ce3917c15
commit 95c61311ca
24 changed files with 833 additions and 161 deletions
+66 -3
View File
@@ -43,6 +43,7 @@ C_LONGDOUBLE :: Type(28)
BOOL :: Type(29)
FLOAT :: Type(30)
RANGE :: Type(31)
ANYOPAQUE :: Type(32)
DYNAMIC_START :: Type(64)
@@ -56,6 +57,7 @@ Numeric_Category :: enum u8 {
Kind :: enum u8 {
Invalid,
Void,
Anyopaque,
Int_Constraint,
Float_Constraint,
Range_Constraint,
@@ -555,6 +557,8 @@ kind :: proc(value: Type, store: ^Store = nil) -> Kind {
return .Invalid
case VOID:
return .Void
case ANYOPAQUE:
return .Anyopaque
case INT:
return .Int_Constraint
case FLOAT:
@@ -595,6 +599,10 @@ is_void :: proc(value: Type) -> bool {
return value == VOID
}
is_anyopaque :: proc(value: Type) -> bool {
return value == ANYOPAQUE
}
is_bool :: proc(value: Type) -> bool {
return value == BOOL
}
@@ -915,8 +923,19 @@ is_runtime_value :: proc(value: Type, store: ^Store, depth := 0) -> bool {
if value_kind == .Scalar || value_kind == .Pointer {
return true
}
if value_kind == .Slice || value_kind == .Array || value_kind == .Range || value_kind == .Optional {
return !contains_c_struct_by_value(value, store)
if value_kind == .Slice || value_kind == .Array || value_kind == .Range {
item, ok := node(store, value)
return ok && is_runtime_value(item.child, store, depth+1) && !contains_c_struct_by_value(value, store)
}
if value_kind == .Optional {
item, ok := node(store, value)
if !ok {
return false
}
if is_pointer(item.child, store) {
return true
}
return is_runtime_value(item.child, store, depth+1) && !contains_c_struct_by_value(value, store)
}
if value_kind == .Struct || value_kind == .Union {
item, ok := node(store, value)
@@ -1204,6 +1223,42 @@ function_pointer :: proc(value: Type, store: ^Store) -> (pointer_item, function_
return pointer_node, function_node, pointer_node.child, true
}
replace_pointer_child :: proc(store: ^Store, value, child: Type) -> (Type, bool) {
item, ok := node(store, value)
if !ok {
return INVALID, false
}
if item.kind == .Optional {
replaced, replaced_ok := replace_pointer_child(store, item.child, child)
if !replaced_ok || !is_pointer(replaced, store) {
return INVALID, false
}
return optional(store, replaced), true
}
if item.kind != .Pointer {
return INVALID, false
}
item.child = child
return intern(store, item), true
}
same_pointer_shape :: proc(left, right: Type, store: ^Store) -> bool {
left_item, left_ok := node(store, left)
right_item, right_ok := node(store, right)
if !left_ok || !right_ok {
return false
}
if left_item.kind == .Optional || right_item.kind == .Optional {
return left_item.kind == .Optional && right_item.kind == .Optional &&
same_pointer_shape(left_item.child, right_item.child, store)
}
return left_item.kind == .Pointer && right_item.kind == .Pointer &&
left_item.many == right_item.many &&
left_item.mutable == right_item.mutable &&
left_item.has_sentinel == right_item.has_sentinel &&
(!left_item.has_sentinel || left_item.sentinel == right_item.sentinel)
}
is_c_struct :: proc(value: Type, store: ^Store) -> bool {
item, ok := node(store, value)
return ok && (item.kind == .Struct || item.kind == .Union) && item.c_layout
@@ -1318,6 +1373,10 @@ with_array_count :: proc(store: ^Store, value: Type, count: u64) -> Type {
can_weaken_pointer :: proc(from, to: Type, store: ^Store) -> bool {
from_node, from_ok := node(store, from)
to_node, to_ok := node(store, to)
if from_ok && to_ok && (from_node.kind == .Optional || to_node.kind == .Optional) {
return from_node.kind == .Optional && to_node.kind == .Optional &&
can_weaken_pointer(from_node.child, to_node.child, store)
}
if !from_ok || !to_ok || from_node.kind != .Pointer || to_node.kind != .Pointer ||
from_node.many != to_node.many || (to_node.mutable && !from_node.mutable) {
return false
@@ -1327,9 +1386,12 @@ can_weaken_pointer :: proc(from, to: Type, store: ^Store) -> bool {
return false
}
same_child := from_node.child == to_node.child
anyopaque_erasure := to_node.child == ANYOPAQUE &&
(is_runtime_value(from_node.child, store) ||
is_opaque_struct(from_node.child, store))
c_string := from_node.many && from_node.child == U8 && to_node.child == C_CHAR &&
from_node.has_sentinel && from_node.sentinel == 0 && !to_node.mutable
return same_child || c_string
return same_child || anyopaque_erasure || c_string
}
can_weaken_slice :: proc(from, to: Type, store: ^Store) -> bool {
@@ -1594,6 +1656,7 @@ name :: proc(value: Type) -> string {
switch value {
case INVALID: return "<invalid>"
case VOID: return "void"
case ANYOPAQUE: return "anyopaque"
case BOOL: return "bool"
case INT: return "int"
case FLOAT: return "float"