allocator interface (first pass)
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user