diff options
Diffstat (limited to 'src/checker.cpp')
| -rw-r--r-- | src/checker.cpp | 170 |
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"); } |