Browse Source

Fix proc groups from import names

gingerBill 7 years ago
parent
commit
3c6f90e552
11 changed files with 89 additions and 53 deletions
  1. 3 3
      core/_preload.odin
  2. 2 2
      core/math.odin
  3. 13 1
      core/raw.odin
  4. 7 4
      src/check_decl.cpp
  5. 43 27
      src/check_expr.cpp
  6. 1 2
      src/check_type.cpp
  7. 5 5
      src/entity.cpp
  8. 5 2
      src/ir.cpp
  9. 6 5
      src/parser.cpp
  10. 3 2
      src/ptr_set.cpp
  11. 1 0
      src/tokenizer.cpp

+ 3 - 3
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_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_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_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) {
 free_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
 	raw := cast(^raw.Map)&m;
 	raw := cast(^raw.Map)&m;

+ 2 - 2
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_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_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_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 {
 quat_norm :: proc(q: Quat) -> Quat {
-	m := sqrt(quat_dot(q, q));
+	m := sqrt(dot(q, q));
 	return div(q, m);
 	return div(q, m);
 }
 }
 
 

+ 13 - 1
core/raw.odin

@@ -4,7 +4,7 @@ Any :: struct #ordered {
 }
 }
 
 
 String :: struct #ordered {
 String :: struct #ordered {
-	data: ^u8,
+	data: ^byte,
 	len:  int,
 	len:  int,
 }
 }
 
 
@@ -25,3 +25,15 @@ Map :: struct #ordered {
 	entries: Dynamic_Array,
 	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];

+ 7 - 4
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) {
 void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
 	GB_ASSERT(pg_entity->kind == Entity_ProcGroup);
 	GB_ASSERT(pg_entity->kind == Entity_ProcGroup);
 	auto *pge = &pg_entity->ProcGroup;
 	auto *pge = &pg_entity->ProcGroup;
+	String proc_group_name = pg_entity->token.string;
 
 
 	ast_node(pg, ProcGroup, d->init_expr);
 	ast_node(pg, ProcGroup, d->init_expr);
 
 
 	array_init(&pge->entities, c->allocator, pg->args.count);
 	array_init(&pge->entities, c->allocator, pg->args.count);
 
 
-
 	PtrSet<Entity *> entity_map = {};
 	PtrSet<Entity *> entity_map = {};
 	ptr_set_init(&entity_map, heap_allocator());
 	ptr_set_init(&entity_map, heap_allocator());
 	defer (ptr_set_destroy(&entity_map));
 	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);
 			e = check_selector(c, &o, arg, nullptr);
 		}
 		}
 		if (e == 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;
 			continue;
 		}
 		}
 		if (e->kind == Entity_Variable) {
 		if (e->kind == Entity_Variable) {
 			if (!is_type_proc(e->type)) {
 			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;
 				continue;
 			}
 			}
 		} else if (e->kind != Entity_Procedure) {
 		} else if (e->kind != Entity_Procedure) {
@@ -753,7 +755,6 @@ void check_proc_group_decl(Checker *c, Entity *pg_entity, DeclInfo *d) {
 			continue;
 			continue;
 		}
 		}
 		ptr_set_add(&entity_map, e);
 		ptr_set_add(&entity_map, e);
-
 		array_add(&pge->entities, 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) {
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {

+ 43 - 27
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);
 			check_entity_decl(c, entity, nullptr, nullptr);
-			GB_ASSERT(entity->type != nullptr || entity->kind == Entity_ProcGroup);
+			GB_ASSERT(entity->type != nullptr);
+
 
 
 			if (is_alias) {
 			if (is_alias) {
 				// TODO(bill): Which scope do you search for for an 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;
 				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;
 				auto *pge = &entity->ProcGroup;
 				Array<Entity *> procs = pge->entities;
 				Array<Entity *> procs = pge->entities;
 				bool skip = false;
 				bool skip = false;
 				for_array(i, procs) {
 				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) {
 					if (t == t_invalid) {
 						continue;
 						continue;
 					}
 					}
@@ -2530,7 +2542,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 					x.type = t;
 					x.type = t;
 					if (type_hint != nullptr) {
 					if (type_hint != nullptr) {
 						if (check_is_assignable_to(c, &x, type_hint)) {
 						if (check_is_assignable_to(c, &x, type_hint)) {
-							entity = procs[i];
+							entity = p;
 							skip = true;
 							skip = true;
 							break;
 							break;
 						}
 						}
@@ -2538,23 +2550,14 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 				}
 				}
 
 
 				if (!skip) {
 				if (!skip) {
-					GB_ASSERT(e != nullptr);
+					GB_ASSERT(entity != nullptr);
 					operand->mode       = Addressing_ProcGroup;
 					operand->mode       = Addressing_ProcGroup;
 					operand->type       = t_invalid;
 					operand->type       = t_invalid;
 					operand->expr       = node;
 					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;
 		break;
 
 
 	case Entity_ProcGroup:
 	case Entity_ProcGroup:
-		entity->type = t_invalid;
+		operand->mode = Addressing_ProcGroup;
+		operand->proc_group = entity;
 		break;
 		break;
 
 
 	// NOTE(bill): These cases should never be hit but are here for sanity reasons
 	// 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;
 			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;
 		operand->mode = Addressing_Value;
 
 
 		break;
 		break;
@@ -4370,6 +4376,8 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 	}
 	}
 
 
 	if (operand->mode == Addressing_ProcGroup) {
 	if (operand->mode == Addressing_ProcGroup) {
+		check_entity_decl(c, operand->proc_group, nullptr, nullptr);
+
 		Array<Entity *> procs = proc_group_entities(c, *operand);
 		Array<Entity *> procs = proc_group_entities(c, *operand);
 
 
 		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, procs.count);
 		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) {
 		if (valid_count == 0) {
 			error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name);
 			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) {
 			for_array(i, operands) {
 				Operand o = operands[i];
 				Operand o = operands[i];
 				if (i > 0) gb_printf_err(", ");
 				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;
 				if (t == t_invalid) continue;
 				GB_ASSERT(t->kind == Type_Proc);
 				GB_ASSERT(t->kind == Type_Proc);
 				gbString pt;
 				gbString pt;
+				defer (gb_string_free(pt));
 				if (t->Proc.node != nullptr) {
 				if (t->Proc.node != nullptr) {
 					pt = expr_to_string(t->Proc.node);
 					pt = expr_to_string(t->Proc.node);
 				} else {
 				} else {
 					pt = type_to_string(t);
 					pt = type_to_string(t);
 				}
 				}
 				String name = proc->token.string;
 				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) {
 			if (procs.count > 0) {
 				gb_printf_err("\n");
 				gb_printf_err("\n");
@@ -4457,7 +4470,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 			result_type = t_invalid;
 			result_type = t_invalid;
 		} else if (valid_count > 1) {
 		} else if (valid_count > 1) {
 			error(operand->expr, "Ambiguous procedure group call '%s' that match with the given arguments", expr_name);
 			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) {
 			for_array(i, operands) {
 				Operand o = operands[i];
 				Operand o = operands[i];
 				if (i > 0) gb_printf_err(", ");
 				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;
 				TokenPos pos = proc->token.pos;
 				Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
 				Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
 				gbString pt;
 				gbString pt;
+				defer (gb_string_free(pt));
 				if (t->Proc.node != nullptr) {
 				if (t->Proc.node != nullptr) {
 					pt = expr_to_string(t->Proc.node);
 					pt = expr_to_string(t->Proc.node);
 				} else {
 				} else {
 					pt = type_to_string(t);
 					pt = type_to_string(t);
 				}
 				}
 				String name = proc->token.string;
 				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;
 			result_type = t_invalid;
 		} else {
 		} else {

+ 1 - 2
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;
 		bool detemine_type_from_operand = false;
 		Type *specialization = nullptr;
 		Type *specialization = nullptr;
 
 
-		bool is_using          = (p->flags&FieldFlag_using) != 0;
-
+		bool is_using = (p->flags&FieldFlag_using) != 0;
 
 
 		if (type_expr == nullptr) {
 		if (type_expr == nullptr) {
 			if (default_value->kind == AstNode_BasicDirective &&
 			if (default_value->kind == AstNode_BasicDirective &&

+ 5 - 5
src/entity.cpp

@@ -82,17 +82,17 @@ struct Entity {
 			i32        field_index;
 			i32        field_index;
 			i32        field_src_index;
 			i32        field_src_index;
 			ExactValue default_value;
 			ExactValue default_value;
+			Entity *   foreign_library;
+			AstNode *  foreign_library_ident;
+			String     link_name;
+			String     link_prefix;
+			String     thread_local_model;
 			bool       default_is_nil;
 			bool       default_is_nil;
 			bool       default_is_undef;
 			bool       default_is_undef;
 			bool       default_is_location;
 			bool       default_is_location;
 			bool       is_immutable;
 			bool       is_immutable;
-			String     thread_local_model;
 			bool       is_foreign;
 			bool       is_foreign;
 			bool       is_export;
 			bool       is_export;
-			Entity *   foreign_library;
-			AstNode *  foreign_library_ident;
-			String     link_name;
-			String     link_prefix;
 		} Variable;
 		} Variable;
 		struct {
 		struct {
 			bool  is_type_alias;
 			bool  is_type_alias;

+ 5 - 2
src/ir.cpp

@@ -5080,8 +5080,11 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 
 		isize arg_count = 0;
 		isize arg_count = 0;
 		for_array(i, ce->args) {
 		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) {
 			if (at->kind == Type_Tuple) {
 				arg_count += at->Tuple.variables.count;
 				arg_count += at->Tuple.variables.count;
 			} else {
 			} else {

+ 6 - 5
src/parser.cpp

@@ -3280,11 +3280,12 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token) {
 	for_array(i, params->FieldList.list) {
 	for_array(i, params->FieldList.list) {
 		AstNode *param = params->FieldList.list[i];
 		AstNode *param = params->FieldList.list[i];
 		ast_node(f, Field, param);
 		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;
+			}
 		}
 		}
 	}
 	}
 
 

+ 3 - 2
src/ptr_set.cpp

@@ -19,7 +19,7 @@ struct PtrSet {
 
 
 template <typename T> void ptr_set_init             (PtrSet<T> *s, gbAllocator a, isize capacity = 16);
 template <typename T> void ptr_set_init             (PtrSet<T> *s, gbAllocator a, isize capacity = 16);
 template <typename T> void ptr_set_destroy          (PtrSet<T> *s);
 template <typename T> void ptr_set_destroy          (PtrSet<T> *s);
-template <typename T> void ptr_set_add              (PtrSet<T> *s, T ptr);
+template <typename T> T    ptr_set_add              (PtrSet<T> *s, T ptr);
 template <typename T> bool ptr_set_exists           (PtrSet<T> *s, T ptr);
 template <typename T> bool ptr_set_exists           (PtrSet<T> *s, T ptr);
 template <typename T> void ptr_set_remove           (PtrSet<T> *s, T ptr);
 template <typename T> void ptr_set_remove           (PtrSet<T> *s, T ptr);
 template <typename T> void ptr_set_clear            (PtrSet<T> *s);
 template <typename T> void ptr_set_clear            (PtrSet<T> *s);
@@ -136,7 +136,7 @@ gb_inline bool ptr_set_exists(PtrSet<T> *s, T ptr) {
 
 
 // Returns true if it already exists
 // Returns true if it already exists
 template <typename T>
 template <typename T>
-void ptr_set_add(PtrSet<T> *s, T ptr) {
+T ptr_set_add(PtrSet<T> *s, T ptr) {
 	isize index;
 	isize index;
 	PtrSetFindResult fr;
 	PtrSetFindResult fr;
 	if (s->hashes.count == 0) {
 	if (s->hashes.count == 0) {
@@ -156,6 +156,7 @@ void ptr_set_add(PtrSet<T> *s, T ptr) {
 	if (ptr_set__full(s)) {
 	if (ptr_set__full(s)) {
 		ptr_set_grow(s);
 		ptr_set_grow(s);
 	}
 	}
+	return ptr;
 }
 }
 
 
 
 

+ 1 - 0
src/tokenizer.cpp

@@ -119,6 +119,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_offset_of,              "offset_of"),              \
 	TOKEN_KIND(Token_offset_of,              "offset_of"),              \
 	TOKEN_KIND(Token_type_of,                "type_of"),                \
 	TOKEN_KIND(Token_type_of,                "type_of"),                \
 	TOKEN_KIND(Token_type_info_of,           "type_info_of"),           \
 	TOKEN_KIND(Token_type_info_of,           "type_info_of"),           \
+	TOKEN_KIND(Token_const,                  "const"),                  \
 	TOKEN_KIND(Token_asm,                    "asm"),                    \
 	TOKEN_KIND(Token_asm,                    "asm"),                    \
 	TOKEN_KIND(Token_yield,                  "yield"),                  \
 	TOKEN_KIND(Token_yield,                  "yield"),                  \
 	TOKEN_KIND(Token_await,                  "await"),                  \
 	TOKEN_KIND(Token_await,                  "await"),                  \