Add initial support for Objective-C class implementation

This commit is contained in:
Harold Brenes
2025-04-19 08:04:23 -04:00
parent 2dedb199b8
commit a3de9c8de4
14 changed files with 895 additions and 47 deletions

View File

@@ -1351,10 +1351,12 @@ gb_internal void init_universal(void) {
t_objc_object = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_object"), alloc_type_struct_complete());
t_objc_selector = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_selector"), alloc_type_struct_complete());
t_objc_class = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_class"), alloc_type_struct_complete());
t_objc_ivar = add_global_type_name(intrinsics_pkg->scope, str_lit("objc_ivar"), alloc_type_struct_complete());
t_objc_id = alloc_type_pointer(t_objc_object);
t_objc_SEL = alloc_type_pointer(t_objc_selector);
t_objc_Class = alloc_type_pointer(t_objc_class);
t_objc_Ivar = alloc_type_pointer(t_objc_ivar);
}
}
@@ -1387,6 +1389,9 @@ gb_internal void init_checker_info(CheckerInfo *i) {
array_init(&i->defineables, a);
map_init(&i->objc_msgSend_types);
mpsc_init(&i->objc_class_implementations, a);
map_init(&i->objc_method_implementations);
string_map_init(&i->load_file_cache);
array_init(&i->all_procedures, heap_allocator());
@@ -3345,6 +3350,11 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
ac->test = true;
return true;
} else if (name == "export") {
if (ac->objc_is_implementation) {
error(value, "Setting @(export) explicitly is not allowed when @(objc_implement) is set. It is exported implicitly.");
return false;
}
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_Invalid) {
ac->is_export = true;
@@ -3356,6 +3366,12 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
}
return true;
} else if (name == "linkage") {
if (ac->objc_is_implementation) {
error(value, "Explicit linkage not allowed when @(objc_implement) is set. It is set implicitly");
return false;
}
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind != ExactValue_String) {
error(value, "Expected either a string 'linkage'");
@@ -3662,6 +3678,35 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
}
}
return true;
} else if (name == "objc_implement") {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_Bool) {
ac->objc_is_implementation = ev.value_bool;
} else if (ev.kind == ExactValue_Invalid) {
ac->objc_is_implementation = true;
} else {
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
}
// This implies exported, strongly linked
if (ac->objc_is_implementation) {
ac->is_export = true;
ac->linkage = str_lit("strong");
}
return true;
} else if (name == "objc_selector") {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_String) {
if (string_is_valid_identifier(ev.value_string)) {
ac->objc_selector = ev.value_string;
} else {
error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string));
}
} else {
error(elem, "Expected a string value for '%.*s'", LIT(name));
}
return true;
} else if (name == "require_target_feature") {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_String) {
@@ -3901,8 +3946,36 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) {
ac->objc_class = ev.value_string;
}
return true;
}
return false;
} else if (name == "objc_implement") {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_Bool) {
ac->objc_is_implementation = ev.value_bool;
} else if (ev.kind == ExactValue_Invalid) {
ac->objc_is_implementation = true;
} else {
error(elem, "Expected a boolean value, or no value, for '%.*s'", LIT(name));
}
return true;
} else if (name == "objc_superclass") {
Type *objc_superclass = check_type(c, value);
if (objc_superclass != nullptr) {
ac->objc_superclass = objc_superclass;
} else {
error(value, "'%.*s' expected a named type", LIT(name));
}
return true;
} else if (name == "objc_ivar") {
Type *objc_ivar = check_type(c, value);
if (objc_ivar != nullptr) {
ac->objc_ivar = objc_ivar;
} else {
error(value, "'%.*s' expected a named type", LIT(name));
}
return true;
}
return false;
}