mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-13 06:41:26 -07:00
Add string_set.cpp; Code clean up
This commit is contained in:
+71
-7
@@ -459,8 +459,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
|
||||
bool is_foreign = e->Procedure.is_foreign;
|
||||
bool is_export = e->Procedure.is_export;
|
||||
bool is_inline = (pl->tags & ProcTag_inline) != 0;
|
||||
bool is_no_inline = (pl->tags & ProcTag_no_inline) != 0;
|
||||
bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
|
||||
|
||||
String link_name = {};
|
||||
@@ -513,6 +511,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
if (name == "link_name") {
|
||||
if (ev.kind == ExactValue_String) {
|
||||
link_name = ev.value_string;
|
||||
if (!is_foreign_name_valid(link_name)) {
|
||||
error(elem, "Invalid link name: %.*s", LIT(link_name));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||
}
|
||||
@@ -548,10 +549,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
}
|
||||
|
||||
if (is_inline && is_no_inline) {
|
||||
error(pl->type, "You cannot apply both `inline` and `no_inline` to a procedure");
|
||||
}
|
||||
|
||||
if (is_foreign && is_export) {
|
||||
error(pl->type, "A foreign procedure cannot have an `export` tag");
|
||||
}
|
||||
@@ -673,9 +670,69 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
}
|
||||
e->flags |= EntityFlag_Visited;
|
||||
|
||||
|
||||
String link_name = {};
|
||||
|
||||
DeclInfo *decl = decl_info_of_entity(&c->info, e);
|
||||
if (decl != nullptr && decl->attributes.count > 0) {
|
||||
error(decl->attributes[0], "Attributes are not allowed on variable declarations, yet");
|
||||
StringSet set = {};
|
||||
string_set_init(&set, heap_allocator());
|
||||
defer (string_set_destroy(&set));
|
||||
|
||||
for_array(i, decl->attributes) {
|
||||
AstNode *attr = decl->attributes[i];
|
||||
if (attr->kind != AstNode_Attribute) continue;
|
||||
for_array(j, attr->Attribute.elems) {
|
||||
AstNode *elem = attr->Attribute.elems[j];
|
||||
String name = {};
|
||||
AstNode *value = nullptr;
|
||||
|
||||
switch (elem->kind) {
|
||||
case_ast_node(i, Ident, elem);
|
||||
name = i->token.string;
|
||||
case_end;
|
||||
case_ast_node(fv, FieldValue, elem);
|
||||
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
||||
name = fv->field->Ident.token.string;
|
||||
value = fv->value;
|
||||
case_end;
|
||||
default:
|
||||
error(elem, "Invalid attribute element");
|
||||
continue;
|
||||
}
|
||||
|
||||
ExactValue ev = {};
|
||||
if (value != nullptr) {
|
||||
Operand op = {};
|
||||
check_expr(c, &op, value);
|
||||
if (op.mode != Addressing_Constant) {
|
||||
error(value, "An attribute element must be constant");
|
||||
} else {
|
||||
ev = op.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (string_set_exists(&set, name)) {
|
||||
error(elem, "Previous declaration of `%.*s`", LIT(name));
|
||||
continue;
|
||||
} else {
|
||||
string_set_add(&set, name);
|
||||
}
|
||||
|
||||
if (name == "link_name") {
|
||||
if (ev.kind == ExactValue_String) {
|
||||
link_name = ev.value_string;
|
||||
if (!is_foreign_name_valid(link_name)) {
|
||||
error(elem, "Invalid link name: %.*s", LIT(link_name));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Unknown attribute element name `%.*s`", LIT(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String context_name = str_lit("variable declaration");
|
||||
@@ -704,8 +761,15 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
}
|
||||
init_entity_foreign_library(c, e);
|
||||
}
|
||||
if (link_name.len > 0) {
|
||||
e->Variable.link_name = link_name;
|
||||
}
|
||||
|
||||
if (e->Variable.is_foreign || e->Variable.is_export) {
|
||||
String name = e->token.string;
|
||||
if (link_name.len > 0) {
|
||||
name = link_name;
|
||||
}
|
||||
auto *fp = &c->info.foreigns;
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_get(fp, key);
|
||||
|
||||
+1
-1
@@ -1670,7 +1670,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
CheckerContext prev_context = c->context;
|
||||
if (ok) {
|
||||
c->context.curr_foreign_library = foreign_library;
|
||||
c->context.default_foreign_cc = ProcCC_C;
|
||||
c->context.default_foreign_cc = ProcCC_CDecl;
|
||||
}
|
||||
|
||||
check_foreign_block_decl_attributes(c, fb);
|
||||
|
||||
+4
-8
@@ -1890,7 +1890,7 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
|
||||
|
||||
ProcCallingConvention cc = pt->calling_convention;
|
||||
if (cc == ProcCC_ForeignBlockDefault) {
|
||||
cc = ProcCC_C;
|
||||
cc = ProcCC_CDecl;
|
||||
if (c->context.default_foreign_cc > 0) {
|
||||
cc = c->context.default_foreign_cc;
|
||||
}
|
||||
@@ -1911,14 +1911,10 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
|
||||
if (param_count > 0) {
|
||||
Entity *end = params->Tuple.variables[param_count-1];
|
||||
if (end->flags&EntityFlag_CVarArg) {
|
||||
if (cc == ProcCC_Odin) {
|
||||
error(end->token, "Odin calling convention does not support #c_vararg");
|
||||
} else if (cc == ProcCC_Contextless) {
|
||||
error(end->token, "Odin's contextless calling convention does not support #c_vararg");
|
||||
} else if (cc == ProcCC_Fast) {
|
||||
error(end->token, "Fast calling convention does not support #c_vararg");
|
||||
} else {
|
||||
if (cc == ProcCC_StdCall || cc == ProcCC_CDecl) {
|
||||
type->Proc.c_vararg = true;
|
||||
} else {
|
||||
error(end->token, "Calling convention does not support #c_vararg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2126,7 +2126,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
||||
GB_ASSERT(pl->type->kind == AstNode_ProcType);
|
||||
auto cc = pl->type->ProcType.calling_convention;
|
||||
if (cc == ProcCC_ForeignBlockDefault) {
|
||||
cc = ProcCC_C;
|
||||
cc = ProcCC_CDecl;
|
||||
if (c->context.default_foreign_cc > 0) {
|
||||
cc = c->context.default_foreign_cc;
|
||||
}
|
||||
|
||||
+10
-5
@@ -117,6 +117,7 @@ struct irProcedure {
|
||||
AstNode * type_expr;
|
||||
AstNode * body;
|
||||
u64 tags;
|
||||
ProcInlining inlining;
|
||||
bool is_foreign;
|
||||
bool is_export;
|
||||
bool is_entry_point;
|
||||
@@ -3695,6 +3696,7 @@ irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, AstNode *exp
|
||||
m, nullptr, type, pl->type, pl->body, name);
|
||||
|
||||
value->Proc.tags = pl->tags;
|
||||
value->Proc.inlining = pl->inlining;
|
||||
value->Proc.parent = proc;
|
||||
|
||||
array_add(&m->procs_to_generate, value);
|
||||
@@ -5902,6 +5904,7 @@ void ir_build_poly_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
||||
proc->module, e, e->type, pd->type, pd->body, name);
|
||||
|
||||
value->Proc.tags = pd->tags;
|
||||
value->Proc.inlining = pd->inlining;
|
||||
value->Proc.parent = proc;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
@@ -5987,6 +5990,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
||||
proc->module, e, e->type, pl->type, pl->body, name);
|
||||
|
||||
value->Proc.tags = pl->tags;
|
||||
value->Proc.inlining = pl->inlining;
|
||||
|
||||
ir_module_add_value(proc->module, e, value);
|
||||
ir_build_proc(value, proc);
|
||||
@@ -8295,6 +8299,7 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
||||
p->Proc.tags = pl->tags;
|
||||
p->Proc.inlining = pl->inlining;
|
||||
|
||||
ir_module_add_value(m, e, p);
|
||||
HashKey hash_name = hash_string(name);
|
||||
@@ -8363,7 +8368,7 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
Type *proc_type = make_type_proc(a, proc_scope,
|
||||
proc_params, 3,
|
||||
proc_results, 1, false, ProcCC_Std);
|
||||
proc_results, 1, false, ProcCC_StdCall);
|
||||
|
||||
// TODO(bill): make this more robust
|
||||
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
||||
@@ -8380,7 +8385,7 @@ void ir_gen_tree(irGen *s) {
|
||||
map_set(&m->members, hash_string(name), p);
|
||||
|
||||
irProcedure *proc = &p->Proc;
|
||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
proc->is_entry_point = true;
|
||||
e->Procedure.link_name = name;
|
||||
|
||||
@@ -8434,7 +8439,7 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
Type *proc_type = make_type_proc(a, proc_scope,
|
||||
proc_params, 2,
|
||||
proc_results, 1, false, ProcCC_C);
|
||||
proc_results, 1, false, ProcCC_CDecl);
|
||||
|
||||
// TODO(bill): make this more robust
|
||||
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
||||
@@ -8451,7 +8456,7 @@ void ir_gen_tree(irGen *s) {
|
||||
map_set(&m->members, hash_string(name), p);
|
||||
|
||||
irProcedure *proc = &p->Proc;
|
||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
proc->is_entry_point = true;
|
||||
e->Procedure.link_name = name;
|
||||
|
||||
@@ -8543,7 +8548,7 @@ void ir_gen_tree(irGen *s) {
|
||||
|
||||
|
||||
irProcedure *proc = &p->Proc;
|
||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
|
||||
ir_begin_procedure_body(proc);
|
||||
|
||||
|
||||
+9
-8
@@ -882,9 +882,9 @@ void ir_print_calling_convention(irFileBuffer *f, irModule *m, ProcCallingConven
|
||||
switch (cc) {
|
||||
case ProcCC_Odin: ir_write_string(f, ""); break;
|
||||
case ProcCC_Contextless: ir_write_string(f, ""); break;
|
||||
case ProcCC_C: ir_write_string(f, "ccc "); break;
|
||||
case ProcCC_Std: ir_write_string(f, "cc 64 "); break;
|
||||
case ProcCC_Fast: ir_write_string(f, "cc 65 "); break;
|
||||
case ProcCC_CDecl: ir_write_string(f, "ccc "); break;
|
||||
case ProcCC_StdCall: ir_write_string(f, "cc 64 "); break;
|
||||
case ProcCC_FastCall: ir_write_string(f, "cc 65 "); break;
|
||||
default: GB_PANIC("unknown calling convention: %d", cc);
|
||||
}
|
||||
}
|
||||
@@ -1751,14 +1751,15 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
||||
|
||||
ir_write_string(f, ") ");
|
||||
|
||||
if (proc->tags & ProcTag_inline) {
|
||||
ir_write_string(f, "alwaysinline ");
|
||||
}
|
||||
if (proc->tags & ProcTag_no_inline) {
|
||||
switch (proc->inlining) {
|
||||
case ProcInlining_no_inline:
|
||||
ir_write_string(f, "noinline ");
|
||||
break;
|
||||
case ProcInlining_inline:
|
||||
ir_write_string(f, "alwaysinline ");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (proc->entity != nullptr) {
|
||||
if (proc->body != nullptr) {
|
||||
irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||
|
||||
+36
-28
@@ -88,28 +88,29 @@ struct Parser {
|
||||
gbMutex file_decl_mutex;
|
||||
};
|
||||
|
||||
enum ProcInlining {
|
||||
ProcInlining_none = 0,
|
||||
ProcInlining_inline = 1,
|
||||
ProcInlining_no_inline = 2,
|
||||
};
|
||||
|
||||
enum ProcTag {
|
||||
ProcTag_bounds_check = 1<<0,
|
||||
ProcTag_no_bounds_check = 1<<1,
|
||||
|
||||
|
||||
ProcTag_require_results = 1<<4,
|
||||
|
||||
ProcTag_link_name = 1<<11,
|
||||
ProcTag_inline = 1<<12,
|
||||
ProcTag_no_inline = 1<<13,
|
||||
|
||||
// ProcTag_dll_import = 1<<15,
|
||||
// ProcTag_dll_export = 1<<16,
|
||||
};
|
||||
|
||||
enum ProcCallingConvention {
|
||||
ProcCC_Invalid = 0,
|
||||
ProcCC_Odin = 1,
|
||||
ProcCC_Contextless = 2,
|
||||
ProcCC_C = 3,
|
||||
ProcCC_Std = 4,
|
||||
ProcCC_Fast = 5,
|
||||
ProcCC_Invalid = 0,
|
||||
ProcCC_Odin,
|
||||
ProcCC_Contextless,
|
||||
ProcCC_CDecl,
|
||||
ProcCC_StdCall,
|
||||
ProcCC_FastCall,
|
||||
|
||||
// TODO(bill): Add extra calling conventions
|
||||
// ProcCC_VectorCall,
|
||||
// ProcCC_ClrCall,
|
||||
|
||||
ProcCC_ForeignBlockDefault = -1,
|
||||
};
|
||||
@@ -172,6 +173,7 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
|
||||
AstNode *type; \
|
||||
AstNode *body; \
|
||||
u64 tags; \
|
||||
ProcInlining inlining; \
|
||||
}) \
|
||||
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
||||
AstNode *type; \
|
||||
@@ -2275,11 +2277,20 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
syntax_error(expr, "%.*s must be followed by a procedure literal, got %.*s", LIT(token.string), LIT(ast_node_strings[expr->kind]));
|
||||
return ast_bad_expr(f, token, f->curr_token);
|
||||
}
|
||||
ProcInlining pi = ProcInlining_none;
|
||||
if (token.kind == Token_inline) {
|
||||
expr->ProcLit.tags |= ProcTag_inline;
|
||||
pi = ProcInlining_inline;
|
||||
} else if (token.kind == Token_no_inline) {
|
||||
expr->ProcLit.tags |= ProcTag_no_inline;
|
||||
pi = ProcInlining_no_inline;
|
||||
}
|
||||
if (pi != ProcInlining_none) {
|
||||
if (expr->ProcLit.inlining != ProcInlining_none &&
|
||||
expr->ProcLit.inlining != pi) {
|
||||
syntax_error(expr, "You cannot apply both `inline` and `no_inline` to a procedure literal");
|
||||
}
|
||||
expr->ProcLit.inlining = pi;
|
||||
}
|
||||
|
||||
return expr;
|
||||
} break;
|
||||
|
||||
@@ -3255,17 +3266,14 @@ AstNode *parse_results(AstFile *f) {
|
||||
|
||||
|
||||
ProcCallingConvention string_to_calling_convention(String s) {
|
||||
if (s == "odin") {
|
||||
return ProcCC_Odin;
|
||||
} else if (s == "contextless") {
|
||||
return ProcCC_Contextless;
|
||||
} else if (s == "cdecl" || s == "c") {
|
||||
return ProcCC_C;
|
||||
} else if (s == "stdcall" || s == "std") {
|
||||
return ProcCC_Std;
|
||||
} else if (s == "fastcall" || s == "fast") {
|
||||
return ProcCC_Fast;
|
||||
}
|
||||
if (s == "odin") return ProcCC_Odin;
|
||||
if (s == "contextless") return ProcCC_Contextless;
|
||||
if (s == "cdecl") return ProcCC_CDecl;
|
||||
if (s == "c") return ProcCC_CDecl;
|
||||
if (s == "stdcall") return ProcCC_StdCall;
|
||||
if (s == "std") return ProcCC_StdCall;
|
||||
if (s == "fastcall") return ProcCC_FastCall;
|
||||
if (s == "fast") return ProcCC_FastCall;
|
||||
return ProcCC_Invalid;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
struct StringSetFindResult {
|
||||
isize hash_index;
|
||||
isize entry_prev;
|
||||
isize entry_index;
|
||||
};
|
||||
|
||||
struct StringSetEntry {
|
||||
HashKey key;
|
||||
isize next;
|
||||
String value;
|
||||
};
|
||||
|
||||
struct StringSet {
|
||||
Array<isize> hashes;
|
||||
Array<StringSetEntry> entries;
|
||||
};
|
||||
|
||||
|
||||
void string_set_init (StringSet *s, gbAllocator a, isize capacity = 16);
|
||||
void string_set_destroy(StringSet *s);
|
||||
void string_set_add (StringSet *s, String str);
|
||||
bool string_set_exists (StringSet *s, String str);
|
||||
void string_set_remove (StringSet *s, String str);
|
||||
void string_set_clear (StringSet *s);
|
||||
void string_set_grow (StringSet *s);
|
||||
void string_set_rehash (StringSet *s, isize new_count);
|
||||
|
||||
|
||||
gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) {
|
||||
array_init(&s->hashes, a);
|
||||
array_init(&s->entries, a);
|
||||
}
|
||||
|
||||
gb_inline void string_set_destroy(StringSet *s) {
|
||||
array_free(&s->entries);
|
||||
array_free(&s->hashes);
|
||||
}
|
||||
|
||||
gb_internal isize string_set__add_entry(StringSet *s, HashKey key) {
|
||||
StringSetEntry e = {};
|
||||
e.key = key;
|
||||
e.next = -1;
|
||||
array_add(&s->entries, e);
|
||||
return s->entries.count-1;
|
||||
}
|
||||
|
||||
gb_internal StringSetFindResult string_set__find(StringSet *s, HashKey key) {
|
||||
StringSetFindResult fr = {-1, -1, -1};
|
||||
if (s->hashes.count > 0) {
|
||||
// fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count));
|
||||
fr.hash_index = key.key % s->hashes.count;
|
||||
fr.entry_index = s->hashes[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (hash_key_equal(s->entries[fr.entry_index].key, key)) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = s->entries[fr.entry_index].next;
|
||||
}
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
gb_internal StringSetFindResult string_set__find_from_entry(StringSet *s, StringSetEntry *e) {
|
||||
StringSetFindResult fr = {-1, -1, -1};
|
||||
if (s->hashes.count > 0) {
|
||||
fr.hash_index = e->key.key % s->hashes.count;
|
||||
fr.entry_index = s->hashes[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (&s->entries[fr.entry_index] == e) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = s->entries[fr.entry_index].next;
|
||||
}
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
gb_internal b32 string_set__full(StringSet *s) {
|
||||
return 0.75f * s->hashes.count <= s->entries.count;
|
||||
}
|
||||
|
||||
gb_inline void string_set_grow(StringSet *s) {
|
||||
isize new_count = ARRAY_GROW_FORMULA(s->entries.count);
|
||||
string_set_rehash(s, new_count);
|
||||
}
|
||||
|
||||
void string_set_rehash(StringSet *s, isize new_count) {
|
||||
isize i, j;
|
||||
StringSet ns = {};
|
||||
string_set_init(&ns, s->hashes.allocator);
|
||||
array_resize(&ns.hashes, new_count);
|
||||
array_reserve(&ns.entries, s->entries.count);
|
||||
for (i = 0; i < new_count; i++) {
|
||||
ns.hashes[i] = -1;
|
||||
}
|
||||
for (i = 0; i < s->entries.count; i++) {
|
||||
StringSetEntry *e = &s->entries[i];
|
||||
StringSetFindResult fr;
|
||||
if (ns.hashes.count == 0) {
|
||||
string_set_grow(&ns);
|
||||
}
|
||||
fr = string_set__find(&ns, e->key);
|
||||
j = string_set__add_entry(&ns, e->key);
|
||||
if (fr.entry_prev < 0) {
|
||||
ns.hashes[fr.hash_index] = j;
|
||||
} else {
|
||||
ns.entries[fr.entry_prev].next = j;
|
||||
}
|
||||
ns.entries[j].next = fr.entry_index;
|
||||
ns.entries[j].value = e->value;
|
||||
if (string_set__full(&ns)) {
|
||||
string_set_grow(&ns);
|
||||
}
|
||||
}
|
||||
string_set_destroy(s);
|
||||
*s = ns;
|
||||
}
|
||||
|
||||
gb_inline bool string_set_exists(StringSet *s, String str) {
|
||||
HashKey key = hash_string(str);
|
||||
isize index = string_set__find(s, key).entry_index;
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
void string_set_add(StringSet *s, String str) {
|
||||
isize index;
|
||||
StringSetFindResult fr;
|
||||
HashKey key = hash_string(str);
|
||||
if (s->hashes.count == 0) {
|
||||
string_set_grow(s);
|
||||
}
|
||||
fr = string_set__find(s, key);
|
||||
if (fr.entry_index >= 0) {
|
||||
index = fr.entry_index;
|
||||
} else {
|
||||
index = string_set__add_entry(s, key);
|
||||
if (fr.entry_prev >= 0) {
|
||||
s->entries[fr.entry_prev].next = index;
|
||||
} else {
|
||||
s->hashes[fr.hash_index] = index;
|
||||
}
|
||||
}
|
||||
s->entries[index].value = str;
|
||||
|
||||
if (string_set__full(s)) {
|
||||
string_set_grow(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void string_set__erase(StringSet *s, StringSetFindResult fr) {
|
||||
StringSetFindResult last;
|
||||
if (fr.entry_prev < 0) {
|
||||
s->hashes[fr.hash_index] = s->entries[fr.entry_index].next;
|
||||
} else {
|
||||
s->entries[fr.entry_prev].next = s->entries[fr.entry_index].next;
|
||||
}
|
||||
if (fr.entry_index == s->entries.count-1) {
|
||||
array_pop(&s->entries);
|
||||
return;
|
||||
}
|
||||
s->entries[fr.entry_index] = s->entries[s->entries.count-1];
|
||||
last = string_set__find(s, s->entries[fr.entry_index].key);
|
||||
if (last.entry_prev >= 0) {
|
||||
s->entries[last.entry_prev].next = fr.entry_index;
|
||||
} else {
|
||||
s->hashes[last.hash_index] = fr.entry_index;
|
||||
}
|
||||
}
|
||||
|
||||
void string_set_remove(StringSet *s, String str) {
|
||||
HashKey key = hash_string(str);
|
||||
StringSetFindResult fr = string_set__find(s, key);
|
||||
if (fr.entry_index >= 0) {
|
||||
string_set__erase(s, fr);
|
||||
}
|
||||
}
|
||||
|
||||
gb_inline void string_set_clear(StringSet *s) {
|
||||
array_clear(&s->hashes);
|
||||
array_clear(&s->entries);
|
||||
}
|
||||
+25
-15
@@ -2436,7 +2436,31 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
break;
|
||||
|
||||
case Type_Proc:
|
||||
str = gb_string_appendc(str, "proc(");
|
||||
str = gb_string_appendc(str, "proc");
|
||||
|
||||
switch (type->Proc.calling_convention) {
|
||||
case ProcCC_Odin:
|
||||
break;
|
||||
case ProcCC_Contextless:
|
||||
str = gb_string_appendc(str, " \"contextless\" ");
|
||||
break;
|
||||
case ProcCC_CDecl:
|
||||
str = gb_string_appendc(str, " \"cdecl\" ");
|
||||
break;
|
||||
case ProcCC_StdCall:
|
||||
str = gb_string_appendc(str, " \"stdcall\" ");
|
||||
break;
|
||||
case ProcCC_FastCall:
|
||||
str = gb_string_appendc(str, " \"fastcall\" ");
|
||||
break;
|
||||
// case ProcCC_VectorCall:
|
||||
// str = gb_string_appendc(str, " \"vectorcall\" ");
|
||||
// break;
|
||||
// case ProcCC_ClrCall:
|
||||
// str = gb_string_appendc(str, " \"clrcall\" ");
|
||||
// break;
|
||||
}
|
||||
str = gb_string_appendc(str, "(");
|
||||
if (type->Proc.params) {
|
||||
str = write_type_to_string(str, type->Proc.params);
|
||||
}
|
||||
@@ -2445,20 +2469,6 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
str = gb_string_appendc(str, " -> ");
|
||||
str = write_type_to_string(str, type->Proc.results);
|
||||
}
|
||||
switch (type->Proc.calling_convention) {
|
||||
case ProcCC_Odin:
|
||||
// str = gb_string_appendc(str, " #cc_odin");
|
||||
break;
|
||||
case ProcCC_C:
|
||||
str = gb_string_appendc(str, " #cc_c");
|
||||
break;
|
||||
case ProcCC_Std:
|
||||
str = gb_string_appendc(str, " #cc_std");
|
||||
break;
|
||||
case ProcCC_Fast:
|
||||
str = gb_string_appendc(str, " #cc_fast");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_BitField:
|
||||
|
||||
Reference in New Issue
Block a user