From 3c6f90e5524d38bdd30750eb04441a1897bcd8dd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Dec 2017 11:35:11 +0000 Subject: [PATCH] Fix proc groups from import names --- core/_preload.odin | 6 ++-- core/math.odin | 4 +-- core/raw.odin | 14 +++++++++- src/check_decl.cpp | 11 +++++--- src/check_expr.cpp | 70 ++++++++++++++++++++++++++++------------------ src/check_type.cpp | 3 +- src/entity.cpp | 14 +++++----- src/ir.cpp | 7 +++-- src/parser.cpp | 11 ++++---- src/ptr_set.cpp | 5 ++-- src/tokenizer.cpp | 1 + 11 files changed, 91 insertions(+), 55 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index deb492161..6317c4a36 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -477,13 +477,13 @@ new_clone :: inline proc(data: $T, loc := #caller_location) -> ^T { } free_string :: proc(str: string, loc := #caller_location) { - free_ptr((^raw.String)(&str).data, loc); + free_ptr(raw.data(str), loc); } free_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) { - free_ptr((^raw.Dynamic_Array)(&array).data, loc); + free_ptr(raw.data(array), loc); } free_slice :: proc(array: $T/[]$E, loc := #caller_location) { - free_ptr((^raw.Slice)(&array).data, loc); + free_ptr(raw.data(array), loc); } free_map :: proc(m: $T/map[$K]$V, loc := #caller_location) { raw := cast(^raw.Map)&m; diff --git a/core/math.odin b/core/math.odin index 3c66575fc..6f72ce631 100644 --- a/core/math.odin +++ b/core/math.odin @@ -399,11 +399,11 @@ quat_mulf :: proc(q: Quat, f: f32) -> Quat { return Quat{q.x*f, q.y*f, q.z*f, q. quat_divf :: proc(q: Quat, f: f32) -> Quat { return Quat{q.x/f, q.y/f, q.z/f, q.w/f}; } quat_div :: proc(q0, q1: Quat) -> Quat { return mul(q0, quat_inverse(q1)); } -quat_inverse :: proc(q: Quat) -> Quat { return div(conj(q), quat_dot(q, q)); } +quat_inverse :: proc(q: Quat) -> Quat { return div(conj(q), dot(q, q)); } quat_dot :: proc(q0, q1: Quat) -> f32 { return q0.x*q1.x + q0.y*q1.y + q0.z*q1.z + q0.w*q1.w; } quat_norm :: proc(q: Quat) -> Quat { - m := sqrt(quat_dot(q, q)); + m := sqrt(dot(q, q)); return div(q, m); } diff --git a/core/raw.odin b/core/raw.odin index d044e1114..a8184026e 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -4,7 +4,7 @@ Any :: struct #ordered { } String :: struct #ordered { - data: ^u8, + data: ^byte, len: int, } @@ -25,3 +25,15 @@ Map :: struct #ordered { entries: Dynamic_Array, } +string_data :: inline proc(s: $T/string) -> ^byte { + return (^String)(&s).data; +} + +slice_data :: inline proc(a: $T/[]$E) -> ^E { + return cast(^E)(^Slice)(&a).data; +} +dynamic_array_data :: inline proc(a: $T/[dynamic]$E) -> ^E { + return cast(^E)(^Dynamic_Array)(&a).data; +} + +data :: proc[string_data, slice_data, dynamic_array_data]; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 817377baf..97acc20cd 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -715,12 +715,12 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { GB_ASSERT(pg_entity->kind == Entity_ProcGroup); auto *pge = &pg_entity->ProcGroup; + String proc_group_name = pg_entity->token.string; ast_node(pg, ProcGroup, d->init_expr); array_init(&pge->entities, c->allocator, pg->args.count); - PtrSet entity_map = {}; ptr_set_init(&entity_map, heap_allocator()); defer (ptr_set_destroy(&entity_map)); @@ -735,12 +735,14 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { e = check_selector(c, &o, arg, nullptr); } if (e == nullptr) { - error(arg, "Expected a valid entity name in procedure group"); + error(arg, "Expected a valid entity name in procedure group, got %.*s", LIT(ast_node_strings[arg->kind])); continue; } if (e->kind == Entity_Variable) { if (!is_type_proc(e->type)) { - error(arg, "Expected a procedure variable"); + gbString s = type_to_string(e->type); + defer (gb_string_free(s)); + error(arg, "Expected a procedure, got %s", s); continue; } } else if (e->kind != Entity_Procedure) { @@ -753,7 +755,6 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { continue; } ptr_set_add(&entity_map, e); - array_add(&pge->entities, e); } @@ -816,6 +817,8 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) { } } } + + pg_entity->type = t_invalid; } void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0c3292fb8..9b33dabcd 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2497,7 +2497,8 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } check_entity_decl(c, entity, nullptr, nullptr); - GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcGroup); + GB_ASSERT(entity->type != nullptr); + if (is_alias) { // TODO(bill): Which scope do you search for for an alias? @@ -2514,13 +2515,24 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h is_not_exported = true; } - if (is_not_exported && entity->kind == Entity_ProcGroup) { - check_entity_decl(c, entity, nullptr, nullptr); + + + if (is_not_exported) { + gbString sel_str = expr_to_string(selector); + error(op_expr, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name)); + gb_string_free(sel_str); + operand->mode = Addressing_Invalid; + operand->expr = node; + return nullptr; + } + + if (entity->kind == Entity_ProcGroup) { auto *pge = &entity->ProcGroup; Array procs = pge->entities; bool skip = false; for_array(i, procs) { - Type *t = base_type(procs[i]->type); + Entity *p = procs[i]; + Type *t = base_type(p->type); if (t == t_invalid) { continue; } @@ -2530,7 +2542,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h x.type = t; if (type_hint != nullptr) { if (check_is_assignable_to(c, &x, type_hint)) { - entity = procs[i]; + entity = p; skip = true; break; } @@ -2538,23 +2550,14 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } if (!skip) { - GB_ASSERT(e != nullptr); + GB_ASSERT(entity != nullptr); operand->mode = Addressing_ProcGroup; operand->type = t_invalid; operand->expr = node; - operand->proc_group = e; - return e; + operand->proc_group = entity; + return entity; } } - - if (is_not_exported) { - gbString sel_str = expr_to_string(selector); - error(op_expr, "'%s' is not exported by '%.*s'", sel_str, LIT(import_name)); - gb_string_free(sel_str); - operand->mode = Addressing_Invalid; - operand->expr = node; - return nullptr; - } } } @@ -2693,7 +2696,8 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h break; case Entity_ProcGroup: - entity->type = t_invalid; + operand->mode = Addressing_ProcGroup; + operand->proc_group = entity; break; // NOTE(bill): These cases should never be hit but are here for sanity reasons @@ -3330,7 +3334,9 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id return false; } - operand->type = make_type_array(c->allocator, elem_type, arg_count); + if (arg_count < max_count) { + operand->type = make_type_array(c->allocator, elem_type, arg_count); + } operand->mode = Addressing_Value; break; @@ -4370,6 +4376,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t } if (operand->mode == Addressing_ProcGroup) { + check_entity_decl(c, operand->proc_group, nullptr, nullptr); + Array procs = proc_group_entities(c, *operand); ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count); @@ -4421,7 +4429,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t if (valid_count == 0) { error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name); - gb_printf_err("\tGiven argument types -> ("); + gb_printf_err("\tGiven argument types: ("); for_array(i, operands) { Operand o = operands[i]; if (i > 0) gb_printf_err(", "); @@ -4441,15 +4449,20 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t if (t == t_invalid) continue; GB_ASSERT(t->kind == Type_Proc); gbString pt; + defer (gb_string_free(pt)); if (t->Proc.node != nullptr) { pt = expr_to_string(t->Proc.node); } else { pt = type_to_string(t); } String name = proc->token.string; - gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score); - // gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column); - gb_string_free(pt); + + char const *sep = "::"; + if (proc->kind == Entity_Variable) { + sep = ":="; + } + // gb_printf_err("\t%.*s %s %s at %.*s(%td:%td) with score %lld\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score); + gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column); } if (procs.count > 0) { gb_printf_err("\n"); @@ -4457,7 +4470,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t result_type = t_invalid; } else if (valid_count > 1) { error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name); - gb_printf_err("\tGiven argument types -> ("); + gb_printf_err("\tGiven argument types: ("); for_array(i, operands) { Operand o = operands[i]; if (i > 0) gb_printf_err(", "); @@ -4472,15 +4485,18 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t TokenPos pos = proc->token.pos; Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc); gbString pt; + defer (gb_string_free(pt)); if (t->Proc.node != nullptr) { pt = expr_to_string(t->Proc.node); } else { pt = type_to_string(t); } String name = proc->token.string; - // gb_printf_err("\t%.*s :: %s at %.*s(%td:%td) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score); - gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column); - gb_string_free(pt); + char const *sep = "::"; + if (proc->kind == Entity_Variable) { + sep = ":="; + } + gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column); } result_type = t_invalid; } else { diff --git a/src/check_type.cpp b/src/check_type.cpp index 5c9654a2d..7153bbfa1 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1225,8 +1225,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari bool detemine_type_from_operand = false; Type *specialization = nullptr; - bool is_using = (p->flags&FieldFlag_using) != 0; - + bool is_using = (p->flags&FieldFlag_using) != 0; if (type_expr == nullptr) { if (default_value->kind == AstNode_BasicDirective && diff --git a/src/entity.cpp b/src/entity.cpp index ff3fd5c20..3f81a066d 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -82,17 +82,17 @@ struct Entity { i32 field_index; i32 field_src_index; ExactValue default_value; - bool default_is_nil; - bool default_is_undef; - bool default_is_location; - bool is_immutable; - String thread_local_model; - bool is_foreign; - bool is_export; Entity * foreign_library; AstNode * foreign_library_ident; String link_name; String link_prefix; + String thread_local_model; + bool default_is_nil; + bool default_is_undef; + bool default_is_location; + bool is_immutable; + bool is_foreign; + bool is_export; } Variable; struct { bool is_type_alias; diff --git a/src/ir.cpp b/src/ir.cpp index c869e550b..bf0378743 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5080,8 +5080,11 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { isize arg_count = 0; for_array(i, ce->args) { - AstNode *a = ce->args[i]; - Type *at = base_type(type_of_expr(proc->module->info, a)); + AstNode *arg = ce->args[i]; + TypeAndValue tav = type_and_value_of_expr(proc->module->info, arg); + GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s", expr_to_string(arg)); + GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg)); + Type *at = tav.type; if (at->kind == Type_Tuple) { arg_count += at->Tuple.variables.count; } else { diff --git a/src/parser.cpp b/src/parser.cpp index 704833170..8dd5881a2 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -3280,11 +3280,12 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token) { for_array(i, params->FieldList.list) { AstNode *param = params->FieldList.list[i]; ast_node(f, Field, param); - if (f->type != nullptr && - (f->type->kind == AstNode_TypeType || - f->type->kind == AstNode_PolyType)) { - is_generic = true; - break; + if (f->type != nullptr) { + if (f->type->kind == AstNode_TypeType || + f->type->kind == AstNode_PolyType) { + is_generic = true; + break; + } } } diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index d87a86811..ac055f41d 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -19,7 +19,7 @@ struct PtrSet { template void ptr_set_init (PtrSet *s, gbAllocator a, isize capacity = 16); template void ptr_set_destroy (PtrSet *s); -template void ptr_set_add (PtrSet *s, T ptr); +template T ptr_set_add (PtrSet *s, T ptr); template bool ptr_set_exists (PtrSet *s, T ptr); template void ptr_set_remove (PtrSet *s, T ptr); template void ptr_set_clear (PtrSet *s); @@ -136,7 +136,7 @@ gb_inline bool ptr_set_exists(PtrSet *s, T ptr) { // Returns true if it already exists template -void ptr_set_add(PtrSet *s, T ptr) { +T ptr_set_add(PtrSet *s, T ptr) { isize index; PtrSetFindResult fr; if (s->hashes.count == 0) { @@ -156,6 +156,7 @@ void ptr_set_add(PtrSet *s, T ptr) { if (ptr_set__full(s)) { ptr_set_grow(s); } + return ptr; } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index a8bfb6ee8..b85c62d4b 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -119,6 +119,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \ TOKEN_KIND(Token_offset_of, "offset_of"), \ TOKEN_KIND(Token_type_of, "type_of"), \ TOKEN_KIND(Token_type_info_of, "type_info_of"), \ + TOKEN_KIND(Token_const, "const"), \ TOKEN_KIND(Token_asm, "asm"), \ TOKEN_KIND(Token_yield, "yield"), \ TOKEN_KIND(Token_await, "await"), \