aboutsummaryrefslogtreecommitdiff
path: root/src/checker
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-09-16 11:38:20 +0100
committerGinger Bill <bill@gingerbill.org>2016-09-16 11:38:20 +0100
commit968de5aae886e87f395533283c17d77f31eabd0d (patch)
tree9ce5f4b7726c52c6737e65a5c34ca7123df049b7 /src/checker
parent807256dea4d22550ee5da48e806b4e773670fbfc (diff)
Call expression, either handle all or ignore all results.
Diffstat (limited to 'src/checker')
-rw-r--r--src/checker/checker.cpp4
-rw-r--r--src/checker/entity.cpp11
-rw-r--r--src/checker/expr.cpp48
-rw-r--r--src/checker/stmt.cpp62
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;