diff options
| author | Ginger Bill <bill@gingerbill.org> | 2016-09-16 11:38:20 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2016-09-16 11:38:20 +0100 |
| commit | 968de5aae886e87f395533283c17d77f31eabd0d (patch) | |
| tree | 9ce5f4b7726c52c6737e65a5c34ca7123df049b7 /src/checker | |
| parent | 807256dea4d22550ee5da48e806b4e773670fbfc (diff) | |
Call expression, either handle all or ignore all results.
Diffstat (limited to 'src/checker')
| -rw-r--r-- | src/checker/checker.cpp | 4 | ||||
| -rw-r--r-- | src/checker/entity.cpp | 11 | ||||
| -rw-r--r-- | src/checker/expr.cpp | 48 | ||||
| -rw-r--r-- | src/checker/stmt.cpp | 62 |
4 files changed, 92 insertions, 33 deletions
diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index bf0454668..f6fb6a381 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -1034,7 +1034,9 @@ void check_parsed_files(Checker *c) { Entity *e = scope->elements.entries[elem_index].value; // NOTE(bill): Do not add other imported entities if (e->scope == scope && e->kind != Entity_ImportName) { - add_entity(c, file_scope, NULL, e); + if (is_entity_exported(e)) { + add_entity(c, file_scope, NULL, e); + } } } } else { diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index 3814f38f0..3a4ffb191 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -51,7 +51,7 @@ struct Entity { b8 is_field; // Is struct field } Variable; struct { - struct DeclInfo *decl; // Usually NULL + // struct DeclInfo *decl; // Usually NULL } TypeName; struct { b8 pure; @@ -66,6 +66,15 @@ struct Entity { }; }; +b32 is_entity_exported(Entity *e) { + // TODO(bill): Do I really want non-exported entities? + // if (e->token.string.len >= 1 && + // e->token.string.text[0] == '_') { + // return false; + // } + return true; +} + gb_global gbAtomic64 entity_guid_counter = {0}; EntityGuid next_entity_guid(void) { diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 982c28942..8b207b373 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -835,27 +835,28 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl } i64 check_array_count(Checker *c, AstNode *e) { - if (e) { - Operand o = {}; - check_expr(c, &o, e); - if (o.mode != Addressing_Constant) { - if (o.mode != Addressing_Invalid) { - error(&c->error_collector, ast_node_token(e), "Array count must be a constant"); - } + if (e == NULL) { + return 0; + } + Operand o = {}; + check_expr(c, &o, e); + if (o.mode != Addressing_Constant) { + if (o.mode != Addressing_Invalid) { + error(&c->error_collector, ast_node_token(e), "Array count must be a constant"); + } + return 0; + } + if (is_type_untyped(o.type) || is_type_integer(o.type)) { + if (o.value.kind == ExactValue_Integer) { + i64 count = o.value.value_integer; + if (count >= 0) + return count; + error(&c->error_collector, ast_node_token(e), "Invalid array count"); return 0; } - if (is_type_untyped(o.type) || is_type_integer(o.type)) { - if (o.value.kind == ExactValue_Integer) { - i64 count = o.value.value_integer; - if (count >= 0) - return count; - error(&c->error_collector, ast_node_token(e), "Invalid array count"); - return 0; - } - } - - error(&c->error_collector, ast_node_token(e), "Array count must be an integer"); } + + error(&c->error_collector, ast_node_token(e), "Array count must be an integer"); return 0; } @@ -2001,17 +2002,24 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { if (e != NULL && e->kind == Entity_ImportName) { check_op_expr = false; entity = scope_lookup_entity(e->ImportName.scope, selector->Ident.string); - add_entity_use(&c->info, selector, entity); if (entity == NULL) { gbString sel_str = expr_to_string(selector); defer (gb_string_free(sel_str)); - error(&c->error_collector, ast_node_token(op_expr), "`%s` is not declared in `%.*s`", sel_str, LIT(name)); + error(&c->error_collector, ast_node_token(op_expr), "`%s` is not declared by `%.*s`", sel_str, LIT(name)); goto error; } if (entity->type == NULL) { // Not setup yet check_entity_decl(c, entity, NULL, NULL); } GB_ASSERT(entity->type != NULL); + if (!is_entity_exported(entity)) { + gbString sel_str = expr_to_string(selector); + defer (gb_string_free(sel_str)); + error(&c->error_collector, ast_node_token(op_expr), "`%s` is not exported by `%.*s`", sel_str, LIT(name)); + // NOTE(bill): Not really an error so don't goto error + } + + add_entity_use(&c->info, selector, entity); } } if (check_op_expr) { diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 1f57519e0..cf040c223 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -8,6 +8,7 @@ enum StmtFlag : u32 { void check_stmt(Checker *c, AstNode *node, u32 flags); +void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later); void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) { b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0; @@ -437,6 +438,44 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod check_scope_usage(c, c->context.scope); } +b32 are_signatures_similar_enough(Type *a_, Type *b_) { + GB_ASSERT(a_->kind == Type_Proc); + GB_ASSERT(b_->kind == Type_Proc); + auto *a = &a_->Proc; + auto *b = &b_->Proc; + + if (a->param_count != b->param_count) { + return false; + } + if (a->result_count != b->result_count) { + return false; + } + for (isize i = 0; i < a->param_count; i++) { + Type *x = get_base_type(a->params->Tuple.variables[i]->type); + Type *y = get_base_type(b->params->Tuple.variables[i]->type); + if (is_type_pointer(x) && is_type_pointer(y)) { + continue; + } + + if (!are_types_identical(x, y)) { + return false; + } + } + for (isize i = 0; i < a->result_count; i++) { + Type *x = get_base_type(a->results->Tuple.variables[i]->type); + Type *y = get_base_type(b->results->Tuple.variables[i]->type); + if (is_type_pointer(x) && is_type_pointer(y)) { + continue; + } + + if (!are_types_identical(x, y)) { + return false; + } + } + + return true; +} + void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { GB_ASSERT(e->type == NULL); @@ -446,13 +485,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { check_open_scope(c, pd->type); defer (check_close_scope(c)); check_procedure_type(c, proc_type, pd->type); - // add_proc_entity(c, d->scope, pd->name, e); - if (d->scope->is_proc) { - // Nested procedures - add_entity(c, d->scope->parent, pd->name, e); - } - - b32 is_foreign = (pd->tags & ProcTag_foreign) != 0; @@ -460,8 +492,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0; - - if (d->scope == c->global_scope && + if ((d->scope->is_file || d->scope->is_global) && are_strings_equal(e->token.string, make_string("main"))) { if (proc_type != NULL) { auto *pt = &proc_type->Proc; @@ -511,7 +542,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) { TokenPos pos = f->token.pos; Type *this_type = get_base_type(e->type); Type *other_type = get_base_type(f->type); - if (!are_types_identical(this_type, other_type)) { + if (!are_signatures_similar_enough(this_type, other_type)) { error(&c->error_collector, ast_node_token(d->proc_decl), "Redeclaration of #foreign procedure `%.*s` with different type signatures\n" "\tat %.*s(%td:%td)", @@ -577,7 +608,10 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc } } - c->context.decl = d; + // c->context.decl = d; + // Scope *prev = c->context.scope; + // c->context.scope = d->scope; + // defer (c->context.scope = prev); if (e->kind == Entity_Procedure) { check_proc_decl(c, e, d, true); @@ -759,6 +793,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { default: { gbString expr_str = expr_to_string(operand.expr); defer (gb_string_free(expr_str)); + if (kind == Expr_Stmt) { + return; + } + if (operand.expr->kind == AstNode_CallExpr) { + return; + } error(&c->error_collector, ast_node_token(node), "Expression is not used: `%s`", expr_str); } break; |