aboutsummaryrefslogtreecommitdiff
path: root/src/checker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/checker.cpp')
-rw-r--r--src/checker.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/checker.cpp b/src/checker.cpp
index 44e63b750..c6dd1643a 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -1451,6 +1451,9 @@ gb_internal void init_checker_info(CheckerInfo *i) {
mpsc_init(&i->foreign_decls_to_check, a); // 1<<10);
mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used
+ mpsc_init(&i->raddbg_type_views_queue, a);
+ array_init(&i->raddbg_type_views, a);
+
string_map_init(&i->load_directory_cache);
map_init(&i->load_directory_map);
}
@@ -1479,6 +1482,9 @@ gb_internal void destroy_checker_info(CheckerInfo *i) {
mpsc_destroy(&i->foreign_imports_to_check_fullpaths);
mpsc_destroy(&i->foreign_decls_to_check);
+ mpsc_destroy(&i->raddbg_type_views_queue);
+ array_free(&i->raddbg_type_views);
+
map_destroy(&i->objc_msgSend_types);
string_set_destroy(&i->obcj_class_name_set);
mpsc_destroy(&i->objc_class_implementations);
@@ -4066,6 +4072,21 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) {
return true;
}
+ } else if (name == "raddbg_type_view") {
+ ExactValue ev = check_decl_attribute_value(c, value);
+ if (ev.kind == ExactValue_Invalid) {
+ ac->raddbg_type_view = true;
+ } else if (ev.kind == ExactValue_String) {
+ ac->raddbg_type_view = true;
+ ac->raddbg_type_view_string = ev.value_string;
+
+ if (ev.value_string.len == 0) {
+ error(elem, "Expected a non-empty string for '%.*s'", LIT(name));
+ }
+ } else {
+ error(elem, "Expected a string or no value for '%.*s'", LIT(name));
+ }
+ return true;
}
return false;
}
@@ -7037,6 +7058,155 @@ gb_internal void check_parsed_files(Checker *c) {
}
}
+ TIME_SECTION("collate type info stuff");
+ {
+ auto const struct_tag_lookup = [](String tag, char const *key_c, String *value_) -> bool {
+ String t = tag;
+ String key = make_string_c(key_c);
+ while (t.len != 0) {
+ isize i = 0;
+ while (i < t.len && t[i] == ' ') { // Skip whitespace
+ i += 1;
+ }
+ t.text += i;
+ t.len -= i;
+ if (t.len == 0) {
+ break;
+ }
+
+ i = 0;
+
+ while (i < t.len) {
+ u8 c = t[i];
+ if (c == ':' || c == '"') {
+ break;
+ } else if ((0 <= c && c < ' ') || (0x7f <= c && c <= 0x9f)) {
+ // break if control character is found
+ break;
+ }
+ i += 1;
+ }
+
+ if (i == 0) {
+ break;
+ }
+ if (i+1 >= t.len) {
+ break;
+ }
+ if (t[i] != ':' || t[i+1] != '"') {
+ break;
+ }
+ String name = {t.text, i};
+ t = {t.text+i+1, t.len-(i+1)};
+
+ i = 1;
+ while (i < t.len && t[i] != '"') { // find closing quote
+ if (t[i] == '\\') {
+ i += 1; // Skip escaped characters
+ }
+ i += 1;
+ }
+ if (i >= t.len) {
+ break;
+ }
+
+ String value = {t.text, i+1};
+ t = {t.text+i+1, t.len-(i+1)};
+
+ if (key == name) {
+ value = {value.text+1, i-1};
+ if (value_) *value_ = value;
+ return true;
+ }
+ }
+ return false;
+ };
+
+ for (RaddbgTypeView type_view; mpsc_dequeue(&c->info.raddbg_type_views_queue, &type_view); /**/) {
+
+ Type *type = type_view.type;
+ if (type == nullptr || type == t_invalid) {
+ continue;
+ }
+ String view = type_view.view;
+ if (view.len == 0) {
+ // NOTE(bill): Generate one automatically from the struct field tags if they exist
+ // If it cannot be generated, it'll be ignored/err
+
+ Type *bt = base_type(type);
+ if (is_type_struct(type)) {
+ GB_ASSERT(bt->kind == Type_Struct);
+ if (bt->Struct.tags != nullptr) {
+ bool found_any = false;
+
+ for (isize i = 0; i < bt->Struct.fields.count; i++) {
+ String tag = bt->Struct.tags[i];
+ String value = {};
+ if (struct_tag_lookup(tag, "raddbg", &value)) {
+ found_any = true;
+ } else if (struct_tag_lookup(tag, "fmt", &value)) {
+ found_any = true;
+ }
+ }
+
+ if (!found_any) {
+ goto raddbg_type_view_end;
+ }
+
+ gbString s = gb_string_make(heap_allocator(), "");
+
+ s = gb_string_appendc(s, "rows($");
+
+ for (isize i = 0; i < bt->Struct.fields.count; i++) {
+ Entity *field = bt->Struct.fields[i];
+ GB_ASSERT(field != nullptr);
+ String name = field->token.string;
+
+ s = gb_string_appendc(s, ", ");
+
+ bool custom_rule = false;
+
+ String tag = bt->Struct.tags[i];
+ String value = {};
+ if (struct_tag_lookup(tag, "raddbg", &value)) {
+ s = gb_string_append_length(s, value.text, value.len);
+ custom_rule = true;
+ } else if (struct_tag_lookup(tag, "fmt", &value)) {
+ auto p = string_partition(value, make_string_c(","));
+ String tail = p.tail;
+ if (tail.len != 0 && tail != "0") {
+ s = gb_string_appendc(s, "array(");
+ s = gb_string_append_length(s, name.text, name.len);
+ s = gb_string_appendc(s, ", ");
+ s = gb_string_append_length(s, tail.text, tail.len);
+ s = gb_string_appendc(s, ")");
+ custom_rule = true;
+ }
+ }
+
+ if (!custom_rule) {
+ s = gb_string_append_length(s, name.text, name.len);
+ }
+ }
+
+ s = gb_string_appendc(s, ")");
+
+ view = make_string((u8 const *)s, gb_string_length(s));
+ }
+ }
+ }
+
+ raddbg_type_view_end:;
+
+ if (view.len == 0) {
+ // Ignore the type, it didn't anything custom
+ continue;
+ }
+
+ array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view});
+ }
+ }
+
TIME_SECTION("type check finish");
}