diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-01-17 18:47:38 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-01-17 18:47:38 +0000 |
| commit | cb59c1cf0805166d8b3230fea47d8674dacf157a (patch) | |
| tree | 526e381480c5076e8dce90bc4bbfa07253e5e1ea /src/check_expr.c | |
| parent | 383f5b55ad76d6b670b6ae7e2816cc4d8f0d8731 (diff) | |
Comma for all field separators; Overloaded procedures follow exportation rules
Diffstat (limited to 'src/check_expr.c')
| -rw-r--r-- | src/check_expr.c | 116 |
1 files changed, 88 insertions, 28 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 7ee10f8e9..bd8183069 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -5,7 +5,7 @@ ExprKind check_expr_base (Checker *c, Operand *operand, AstNode * Type * check_type_extra (Checker *c, AstNode *expression, Type *named_type); Type * check_type (Checker *c, AstNode *expression); void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def); -Entity * check_selector (Checker *c, Operand *operand, AstNode *node); +Entity * check_selector (Checker *c, Operand *operand, AstNode *node, Type *type_hint); void check_not_tuple (Checker *c, Operand *operand); void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level); gbString expr_to_string (AstNode *expression); @@ -757,6 +757,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v p->flags &= ~FieldFlag_no_alias; // Remove the flag } } + for_array(j, p->names) { AstNode *name = p->names.e[j]; if (ast_node_expect(name, AstNode_Ident)) { @@ -779,6 +780,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v // Custom Calling convention for variadic parameters Entity *end = variables[variable_count-1]; end->type = make_type_slice(c->allocator, end->type); + end->flags |= EntityFlag_Ellipsis; } Type *tuple = make_type_tuple(c->allocator); @@ -874,10 +876,10 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type Scope *s = e->scope; bool skip = false; + Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count); + map_entity_multi_get_all(&s->elements, key, procs); if (type_hint != NULL) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - Entity **procs = gb_alloc_array(c->tmp_allocator, Entity *, overload_count); - map_entity_multi_get_all(&s->elements, key, procs); // NOTE(bill): These should be done for (isize i = 0; i < overload_count; i++) { Type *t = base_type(procs[i]->type); @@ -899,12 +901,13 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Type } if (!skip) { - o->mode = Addressing_Overload; - o->type = t_invalid; - o->overload_count = overload_count; - o->initial_overload_entity = e; + o->mode = Addressing_Overload; + o->type = t_invalid; + o->overload_count = overload_count; + o->overload_entities = procs; return; } + gb_free(heap_allocator(), procs); } add_entity_use(c, n, e); @@ -1040,7 +1043,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) { case_ast_node(se, SelectorExpr, e); Operand o = {0}; - check_selector(c, &o, e); + check_selector(c, &o, e, NULL); switch (o.mode) { case Addressing_Invalid: @@ -2461,7 +2464,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val return true; } -Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { +Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_hint) { ast_node(se, SelectorExpr, node); bool check_op_expr = true; @@ -2480,31 +2483,88 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { } if (op_expr->kind == AstNode_Ident) { + b32 is_not_exported = true; String name = op_expr->Ident.string; Entity *e = scope_lookup_entity(c->context.scope, name); + add_entity_use(c, op_expr, e); expr_entity = e; + if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) { String sel_name = selector->Ident.string; + check_op_expr = false; entity = scope_lookup_entity(e->ImportName.scope, sel_name); if (entity == NULL) { error_node(op_expr, "`%.*s` is not declared by `%.*s`", LIT(sel_name), LIT(name)); goto error; } - if (entity->type == NULL) { // Not setup yet - check_entity_decl(c, entity, NULL, NULL); - } + check_entity_decl(c, entity, NULL, NULL); GB_ASSERT(entity->type != NULL); - b32 is_not_exported = true; - Entity **found = map_entity_get(&e->ImportName.scope->implicit, hash_string(sel_name)); - if (found == NULL) { + bool is_overloaded = false; + isize overload_count = 0; + HashKey key = {0}; + if (entity->kind == Entity_Procedure) { + key = hash_string(entity->token.string); + // NOTE(bill): Overloads are only allowed with the same scope + Scope *s = entity->scope; + overload_count = map_entity_multi_count(&s->elements, key); + if (overload_count > 1) { + is_overloaded = true; + } + } + + if (is_overloaded) { + Scope *s = entity->scope; + bool skip = false; + + Entity **procs = gb_alloc_array(heap_allocator(), Entity *, overload_count); + map_entity_multi_get_all(&s->elements, key, procs); + for (isize i = 0; i < overload_count; /**/) { + Type *t = base_type(procs[i]->type); + if (t == t_invalid) { + continue; + } + + // NOTE(bill): Check to see if it's imported + if (map_bool_get(&e->ImportName.scope->implicit, hash_pointer(procs[i]))) { + gb_swap(Entity *, procs[i], procs[overload_count-1]); + overload_count--; + continue; + } + + Operand x = {0}; + x.mode = Addressing_Value; + x.type = t; + if (type_hint != NULL) { + if (check_is_assignable_to(c, &x, type_hint)) { + entity = procs[i]; + skip = true; + break; + } + } + + i++; + } + + if (overload_count > 0 && !skip) { + operand->mode = Addressing_Overload; + operand->type = t_invalid; + operand->expr = node; + operand->overload_count = overload_count; + operand->overload_entities = procs; + return procs[0]; + } + } + + bool *found = map_bool_get(&e->ImportName.scope->implicit, hash_pointer(entity)); + + if (!found) { is_not_exported = false; } else { - Entity *f = *found; - if (f->kind == Entity_ImportName) { + if (entity->kind == Entity_ImportName) { is_not_exported = true; } } @@ -2515,8 +2575,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { gb_string_free(sel_str); // NOTE(bill): Not really an error so don't goto error } - - add_entity_use(c, selector, entity); } } if (check_op_expr) { @@ -3606,16 +3664,15 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod if (operand->mode == Addressing_Overload) { - Scope *s = operand->initial_overload_entity->scope; - String name = operand->initial_overload_entity->token.string; - HashKey key = hash_string(name); + GB_ASSERT(operand->overload_entities != NULL && + operand->overload_count > 0); isize overload_count = operand->overload_count; - Entity ** procs = gb_alloc_array(heap_allocator(), Entity *, overload_count); + Entity ** procs = operand->overload_entities; ValidProcAndScore *valids = gb_alloc_array(heap_allocator(), ValidProcAndScore, overload_count); isize valid_count = 0; - map_entity_multi_get_all(&s->elements, key, procs); + String name = procs[0]->token.string; for (isize i = 0; i < overload_count; i++) { Entity *e = procs[i]; @@ -3666,9 +3723,13 @@ Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNod } proc_type = t_invalid; } else { - GB_ASSERT(operand->expr->kind == AstNode_Ident); + AstNode *expr = operand->expr; + while (expr->kind == AstNode_SelectorExpr) { + expr = expr->SelectorExpr.selector; + } + GB_ASSERT(expr->kind == AstNode_Ident); Entity *e = procs[valids[0].index]; - add_entity_use(c, operand->expr, e); + add_entity_use(c, expr, e); proc_type = e->type; i64 score = 0; CallArgumentError err = check_call_arguments_internal(c, call, proc_type, operands.e, operands.count, true, &score); @@ -4473,7 +4534,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(se, SelectorExpr, node); - check_selector(c, o, node); + check_selector(c, o, node, type_hint); case_end; @@ -4763,7 +4824,6 @@ gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) { if (i > 0) { str = gb_string_appendc(str, sep); } - str = write_expr_to_string(str, params.e[i]); } return str; |