diff options
| author | gingerBill <bill@gingerbill.org> | 2017-10-30 20:26:05 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2017-10-30 20:26:05 +0000 |
| commit | 414486829a539095062c3c035df729c11f7f4235 (patch) | |
| tree | c1c8cc403a26b07bb34812a07a1d9b2fde72c6bf /src/check_decl.cpp | |
| parent | 3e05be8eb8b14729b63ee541d11b3deb19b38710 (diff) | |
Add string_set.cpp; Code clean up
Diffstat (limited to 'src/check_decl.cpp')
| -rw-r--r-- | src/check_decl.cpp | 78 |
1 files changed, 71 insertions, 7 deletions
diff --git a/src/check_decl.cpp b/src/check_decl.cpp index bc8d35a40..4f5fe3ebe 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -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); |