Browse Source

Disable polymorphic overloading in the global scope
TODO: Figure out why it does not work in the global scope

Ginger Bill 8 years ago
parent
commit
bc16b290ba
12 changed files with 276 additions and 222 deletions
  1. 13 2
      code/demo.odin
  2. 68 21
      core/_preload.odin
  3. 36 30
      core/mem.odin
  4. 21 46
      core/os_windows.odin
  5. 1 1
      core/sys/wgl.odin
  6. 1 4
      core/sys/windows.odin
  7. 2 1
      src/check_decl.cpp
  8. 84 62
      src/check_expr.cpp
  9. 11 4
      src/checker.cpp
  10. 22 39
      src/ir.cpp
  11. 2 1
      src/ir_print.cpp
  12. 15 11
      src/types.cpp

+ 13 - 2
code/demo.odin

@@ -364,9 +364,17 @@ explicit_parametric_polymorphic_procedures :: proc() {
 	}
 }
 
+
 main :: proc() {
-	general_stuff();
+	foo :: proc(x: i64,  y: f32) do fmt.println("#1", x, y);
+	foo :: proc(x: type, y: f32) do fmt.println("#2", type_info(x), y);
+	foo :: proc(x: type)         do fmt.println("#3", type_info(x));
+
+	foo(y = 3785.1546, x = 123);
+	foo(x = int, y = 897.513);
+	foo(x = f32);
 /*
+	general_stuff();
 	foreign_blocks();
 	default_arguments();
 	named_arguments();
@@ -376,7 +384,6 @@ main :: proc() {
 
 	// Command line argument(s)!
 	// -opt=0,1,2,3
-*/
 
 	program := "+ + * - /";
 	accumulator := 0;
@@ -393,5 +400,9 @@ main :: proc() {
 
 	fmt.printf("The program \"%s\" calculates the value %d\n",
 	           program, accumulator);
+*/
 }
 
+
+
+

+ 68 - 21
core/_preload.odin

@@ -122,8 +122,7 @@ type_info_base :: proc(info: ^TypeInfo) -> ^TypeInfo {
 
 	base := info;
 	match i in base {
-	case TypeInfo.Named:
-		base = i.base;
+	case TypeInfo.Named: base = i.base;
 	}
 	return base;
 }
@@ -134,10 +133,8 @@ type_info_base_without_enum :: proc(info: ^TypeInfo) -> ^TypeInfo {
 
 	base := info;
 	match i in base {
-	case TypeInfo.Named:
-		base = i.base;
-	case TypeInfo.Enum:
-		base = i.base;
+	case TypeInfo.Named: base = i.base;
+	case TypeInfo.Enum:  base = i.base;
 	}
 	return base;
 }
@@ -258,8 +255,67 @@ resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_AL
 	return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
 }
 
+// append :: proc(s: ^[]$T, args: ..T) -> int {
+// 	if s == nil {
+// 		return 0;
+// 	}
+// 	slice := ^raw.Slice(s);
+// 	arg_len := len(args);
+// 	if arg_len <= 0 {
+// 		return slice.len;
+// 	}
+
+// 	arg_len = min(slice.cap-slice.len, arg_len);
+// 	if arg_len > 0 {
+// 		data := ^T(slice.data);
+// 		assert(data != nil);
+// 		sz :: size_of(T);
+// 		__mem_copy(data + slice.len, &args[0], sz*arg_len);
+// 		slice.len += arg_len;
+// 	}
+// 	return slice.len;
+// }
+
+// append :: proc(a: ^[dynamic]$T, args: ..T) -> int {
+// 	array := ^raw.DynamicArray(a);
+
+// 	arg_len := len(args);
+// 	if arg_len <= 0 || items == nil {
+// 		return array.len;
+// 	}
+
+
+// 	ok := true;
+// 	if array.cap <= array.len+arg_len {
+// 		cap := 2 * array.cap + max(8, arg_len);
+// 		ok = __dynamic_array_reserve(array, size_of(T), align_of(T), cap);
+// 	}
+// 	// TODO(bill): Better error handling for failed reservation
+// 	if !ok do return array.len;
+
+// 	data := ^T(array.data);
+// 	assert(data != nil);
+// 	__mem_copy(data + array.len, items, size_of(T) * arg_len);
+// 	array.len += arg_len;
+// 	return array.len;
+// }
+
+copy :: proc(dst, src: []$T) -> int #cc_contextless {
+	n := max(0, min(len(dst), len(src)));
+	if n > 0 do __mem_copy(&dst[0], &src[0], n*size_of(T));
+	return n;
+}
+
+
+new  :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T)));
+
+/*
+free :: proc(array: [dynamic]$T) do free_ptr(^raw.DynamicArray(&array).data);
+free :: proc(slice: []$T)        do free_ptr(^raw.Slice(&slice).data);
+free :: proc(str:   string)      do free_ptr(^raw.String(&str).data);
+free :: proc(ptr:   rawptr)      do free_ptr(ptr);
+*/
 
-new :: proc(T: type) -> ^T #inline do return ^T(alloc(size_of(T), align_of(T)));
 
 
 
@@ -440,10 +496,8 @@ __mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_con
 __mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
 	for i in 0..<n {
 		match {
-		case (a+i)^ < (b+i)^:
-			return -1;
-		case (a+i)^ > (b+i)^:
-			return +1;
+		case (a+i)^ < (b+i)^: return -1;
+		case (a+i)^ > (b+i)^: return +1;
 		}
 	}
 	return 0;
@@ -569,7 +623,6 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
 	return slice.len;
 }
 
-
 // Map stuff
 
 __default_hash :: proc(data: []u8) -> u128 {
@@ -582,9 +635,7 @@ __default_hash :: proc(data: []u8) -> u128 {
 	}
 	return fnv128a(data);
 }
-__default_hash_string :: proc(s: string) -> u128 {
-	return __default_hash([]u8(s));
-}
+__default_hash_string :: proc(s: string) -> u128 do return __default_hash([]u8(s));
 
 __INITIAL_MAP_CAP :: 16;
 
@@ -634,9 +685,7 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) {
 	for i in 0..<new_count do nm.hashes[i] = -1;
 
 	for i := 0; i < m.entries.len; i++ {
-		if len(nm.hashes) == 0 {
-			__dynamic_map_grow(new_header);
-		}
+		if len(nm.hashes) == 0 do __dynamic_map_grow(new_header);
 
 		entry_header := __dynamic_map_get_entry(header, i);
 		data := ^u8(entry_header);
@@ -655,9 +704,7 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) {
 		ndata := ^u8(e);
 		__mem_copy(ndata+value_offset, data+value_offset, value_size);
 
-		if __dynamic_map_full(new_header) {
-			__dynamic_map_grow(new_header);
-		}
+		if __dynamic_map_full(new_header) do __dynamic_map_grow(new_header);
 	}
 	free_ptr_with_allocator(header_hashes.allocator, header_hashes.data);
 	free_ptr_with_allocator(header.m.entries.allocator, header.m.entries.data);

+ 36 - 30
core/mem.odin

@@ -1,6 +1,7 @@
 import (
 	"fmt.odin";
 	"os.odin";
+	"raw.odin";
 )
 foreign __llvm_core {
 	swap :: proc(b: u16) -> u16 #link_name "llvm.bswap.i16" ---;
@@ -8,33 +9,50 @@ foreign __llvm_core {
 	swap :: proc(b: u64) -> u64 #link_name "llvm.bswap.i64" ---;
 }
 
-set :: proc(data: rawptr, value: i32, len: int) -> rawptr {
+set :: proc(data: rawptr, value: i32, len: int) -> rawptr #cc_contextless {
 	return __mem_set(data, value, len);
 }
-zero :: proc(data: rawptr, len: int) -> rawptr {
+zero :: proc(data: rawptr, len: int) -> rawptr #cc_contextless {
 	return __mem_zero(data, len);
 }
-copy :: proc(dst, src: rawptr, len: int) -> rawptr {
+copy :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
 	return __mem_copy(dst, src, len);
 }
-copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr {
+copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_contextless {
 	return __mem_copy_non_overlapping(dst, src, len);
 }
-compare :: proc(a, b: []u8) -> int {
+compare :: proc(a, b: []u8) -> int #cc_contextless {
 	return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
 }
 
+/*
+slice_ptr :: proc(ptr: ^$T, len: int) -> []T #cc_contextless {
+	assert(len >= 0);
+	slice := raw.Slice{data = ptr, len = len, cap = len};
+	return ^[]T(&slice)^;
+}
+slice_ptr :: proc(ptr: ^$T, len, cap: int) -> []T #cc_contextless {
+	assert(0 <= len && len <= cap);
+	slice := raw.Slice{data = ptr, len = len, cap = cap};
+	return ^[]T(&slice)^;
+}
+
+slice_to_bytes :: proc(slice: []$T) -> []u8 #cc_contextless {
+	s := ^raw.Slice(&slice);
+	s.len *= size_of(T);
+	s.cap *= size_of(T);
+	return ^[]u8(s)^;
+}
+*/
 
 
-kilobytes :: proc(x: int) -> int #inline { return          (x) * 1024; }
-megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
-gigabytes :: proc(x: int) -> int #inline { return megabytes(x) * 1024; }
-terabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
+kilobytes :: proc(x: int) -> int #inline #cc_contextless { return          (x) * 1024; }
+megabytes :: proc(x: int) -> int #inline #cc_contextless { return kilobytes(x) * 1024; }
+gigabytes :: proc(x: int) -> int #inline #cc_contextless { return megabytes(x) * 1024; }
+terabytes :: proc(x: int) -> int #inline #cc_contextless { return gigabytes(x) * 1024; }
 
 is_power_of_two :: proc(x: int) -> bool {
-	if x <= 0 {
-		return false;
-	}
+	if x <= 0 do return false;
 	return (x & (x-1)) == 0;
 }
 
@@ -44,9 +62,7 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
 	a := uint(align);
 	p := uint(ptr);
 	modulo := p & (a-1);
-	if modulo != 0 {
-		p += a - modulo;
-	}
+	if modulo != 0 do p += a - modulo;
 	return rawptr(p);
 }
 
@@ -65,13 +81,9 @@ allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: in
 	}
 }
 allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
-	if data == nil {
-		return nil;
-	}
+	if data == nil do return nil;
 	p := ^int(data);
-	for (p-1)^ == -1 {
-		p = (p-1);
-	}
+	for (p-1)^ == -1 do p = (p-1);
 	return ^AllocationHeader(p-1);
 }
 
@@ -184,9 +196,7 @@ end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
 
 align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
 	prev_pow2 :: proc(n: i64) -> i64 {
-		if n <= 0 {
-			return 0;
-		}
+		if n <= 0 do return 0;
 		n |= n >> 1;
 		n |= n >> 2;
 		n |= n >> 4;
@@ -271,9 +281,7 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
 		return WORD_SIZE;
 	case Array:
 		count := info.count;
-		if count == 0 {
-			return 0;
-		}
+		if count == 0 do return 0;
 		size      := size_of_type_info(info.elem);
 		align     := align_of_type_info(info.elem);
 		alignment := align_formula(size, align);
@@ -284,9 +292,7 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
 		return 2*WORD_SIZE;
 	case Vector:
 		count := info.count;
-		if count == 0 {
-			return 0;
-		}
+		if count == 0 do return 0;
 		size      := size_of_type_info(info.elem);
 		align     := align_of_type_info(info.elem);
 		alignment := align_formula(size, align);

+ 21 - 46
core/os_windows.odin

@@ -1,4 +1,5 @@
 import win32 "sys/windows.odin";
+import "mem.odin";
 
 Handle   :: int;
 FileTime :: u64;
@@ -100,9 +101,8 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
 	copy(buf[..], []u8(path));
 
 	handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
-	if handle != INVALID_HANDLE {
-		return handle, ERROR_NONE;
-	}
+	if handle != INVALID_HANDLE do return handle, ERROR_NONE;
+
 	err := win32.get_last_error();
 	return INVALID_HANDLE, Errno(err);
 }
@@ -113,23 +113,18 @@ close :: proc(fd: Handle) {
 
 
 write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
-	if len(data) == 0 {
-		return 0, ERROR_NONE;
-	}
+	if len(data) == 0 do return 0, ERROR_NONE;
+
 	single_write_length: i32;
 	total_write: i64;
 	length := i64(len(data));
 
 	for total_write < length {
 		remaining := length - total_write;
-		to_read: i32;
 		MAX :: 1<<31-1;
-		if remaining <= MAX {
-			to_read = i32(remaining);
-		} else {
-			to_read = MAX;
-		}
-		e := win32.write_file(win32.Handle(fd), &data[total_write], to_read, &single_write_length, nil);
+		to_write: i32 = min(i32(remaining), MAX);
+
+		e := win32.write_file(win32.Handle(fd), &data[total_write], to_write, &single_write_length, nil);
 		if single_write_length <= 0 || e == win32.FALSE {
 			err := win32.get_last_error();
 			return int(total_write), Errno(e);
@@ -140,9 +135,7 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
 }
 
 read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
-	if len(data) == 0 {
-		return 0, ERROR_NONE;
-	}
+	if len(data) == 0 do return 0, ERROR_NONE;
 
 	single_read_length: i32;
 	total_read: i64;
@@ -150,13 +143,8 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
 
 	for total_read < length {
 		remaining := length - total_read;
-		to_read: u32;
 		MAX :: 1<<32-1;
-		if remaining <= MAX {
-			to_read = u32(remaining);
-		} else {
-			to_read = MAX;
-		}
+		to_read: u32 = min(u32(remaining), MAX);
 
 		e := win32.read_file(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
 		if single_read_length <= 0 || e == win32.FALSE {
@@ -178,9 +166,8 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
 	hi := i32(offset>>32);
 	lo := i32(offset);
 	ft := win32.get_file_type(win32.Handle(fd));
-	if ft == win32.FILE_TYPE_PIPE {
-		return 0, ERROR_FILE_IS_PIPE;
-	}
+	if ft == win32.FILE_TYPE_PIPE do return 0, ERROR_FILE_IS_PIPE;
+
 	dw_ptr := win32.set_file_pointer(win32.Handle(fd), lo, &hi, w);
 	if dw_ptr == win32.INVALID_SET_FILE_POINTER {
 		err := win32.get_last_error();
@@ -253,9 +240,8 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
 		heap_free(ptr);
 		return nil;
 	}
-	if ptr == nil {
-		return heap_alloc(new_size);
-	}
+	if ptr == nil do return heap_alloc(new_size);
+
 	return win32.heap_realloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
 }
 heap_free :: proc(ptr: rawptr) {
@@ -282,9 +268,8 @@ current_thread_id :: proc() -> int {
 _alloc_command_line_arguments :: proc() -> []string {
 	alloc_ucs2_to_utf8 :: proc(wstr: ^u16) -> string {
 		wstr_len := 0;
-		for (wstr+wstr_len)^ != 0 {
-			wstr_len++;
-		}
+		for (wstr+wstr_len)^ != 0 do wstr_len++;
+
 		len := 2*wstr_len-1;
 		buf := make([]u8, len+1);
 		str := slice_ptr(wstr, wstr_len+1);
@@ -293,22 +278,16 @@ _alloc_command_line_arguments :: proc() -> []string {
 		for str[j] != 0 {
 			match {
 			case str[j] < 0x80:
-				if i+1 > len {
-					return "";
-				}
+				if i+1 > len do return "";
 				buf[i] = u8(str[j]); i++;
 				j++;
 			case str[j] < 0x800:
-				if i+2 > len {
-					return "";
-				}
+				if i+2 > len do return "";
 				buf[i] = u8(0xc0 + (str[j]>>6));   i++;
 				buf[i] = u8(0x80 + (str[j]&0x3f)); i++;
 				j++;
 			case 0xd800 <= str[j] && str[j] < 0xdc00:
-				if i+4 > len {
-					return "";
-				}
+				if i+4 > len do return "";
 				c := rune((str[j] - 0xd800) << 10) + rune((str[j+1]) - 0xdc00) + 0x10000;
 				buf[i] = u8(0xf0 +  (c >> 18));         i++;
 				buf[i] = u8(0x80 + ((c >> 12) & 0x3f)); i++;
@@ -318,9 +297,7 @@ _alloc_command_line_arguments :: proc() -> []string {
 			case 0xdc00 <= str[j] && str[j] < 0xe000:
 				return "";
 			case:
-				if i+3 > len {
-					return "";
-				}
+				if i+3 > len do return "";
 				buf[i] = 0xe0 + u8 (str[j] >> 12);         i++;
 				buf[i] = 0x80 + u8((str[j] >>  6) & 0x3f); i++;
 				buf[i] = 0x80 + u8((str[j]      ) & 0x3f); i++;
@@ -334,9 +311,7 @@ _alloc_command_line_arguments :: proc() -> []string {
 	arg_count: i32;
 	arg_list_ptr := win32.command_line_to_argv_w(win32.get_command_line_w(), &arg_count);
 	arg_list := make([]string, arg_count);
-	for _, i in arg_list {
-		arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^);
-	}
+	for _, i in arg_list do arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^);
 	return arg_list;
 }
 

+ 1 - 1
core/sys/wgl.odin

@@ -68,7 +68,7 @@ GetExtensionsStringARBType  :: proc(Hdc) -> ^u8 #cc_c;
 foreign opengl32 {
 	create_context            :: proc(hdc: Hdc) -> Hglrc                                                                                                 #link_name "wglCreateContext"          ---;
 	make_current              :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool                                                                                    #link_name "wglMakeCurrent"            ---;
-	get_proc_address          :: proc(c_str: ^u8) -> Proc                                                                                                #link_name "wglGetProcAddress"         ---;
+	get_proc_address          :: proc(c_str: ^u8) -> rawptr                                                                                              #link_name "wglGetProcAddress"         ---;
 	delete_context            :: proc(hglrc: Hglrc) -> Bool                                                                                              #link_name "wglDeleteContext"          ---;
 	copy_context              :: proc(src, dst: Hglrc, mask: u32) -> Bool                                                                                #link_name "wglCopyContext"            ---;
 	create_layer_context      :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc                                                                               #link_name "wglCreateLayerContext"     ---;

+ 1 - 4
core/sys/windows.odin

@@ -144,9 +144,6 @@ PixelFormatDescriptor :: struct #ordered {
 
 
 
-
-Proc :: proc() #cc_c;
-
 MAPVK_VK_TO_VSC    :: 0;
 MAPVK_VSC_TO_VK    :: 1;
 MAPVK_VK_TO_CHAR   :: 2;
@@ -344,7 +341,7 @@ foreign kernel32 {
 
 	load_library_a   :: proc(c_str: ^u8) -> Hmodule                                                                            #cc_std #link_name "LoadLibraryA"                 ---;
 	free_library     :: proc(h: Hmodule)                                                                                       #cc_std #link_name "FreeLibrary"                  ---;
-	get_proc_address :: proc(h: Hmodule, c_str: ^u8) -> Proc                                                                   #cc_std #link_name "GetProcAddress"               ---;
+	get_proc_address :: proc(h: Hmodule, c_str: ^u8) -> rawptr                                                                 #cc_std #link_name "GetProcAddress"               ---;
 
 }
 

+ 2 - 1
src/check_decl.cpp

@@ -601,6 +601,8 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 	}
 
 	CheckerContext old_context = c->context;
+	defer (c->context = old_context);
+
 	c->context.scope = decl->scope;
 	c->context.decl = decl;
 	c->context.proc_name = proc_name;
@@ -660,7 +662,6 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 
 
 	check_scope_usage(c, c->context.scope);
-	c->context = old_context;
 
 	if (decl->parent != NULL) {
 		// NOTE(bill): Add the dependencies from the procedure literal (lambda)

+ 84 - 62
src/check_expr.cpp

@@ -1084,6 +1084,7 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
 	case Type_Basic:
 		if (compound) return are_types_identical(poly, source);
 		return check_is_assignable_to(c, &o, poly);
+
 	case Type_Named:
 		if (compound) return are_types_identical(poly, source);
 		return check_is_assignable_to(c, &o, poly);
@@ -1097,7 +1098,8 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
 	}
 	case Type_Pointer:
 		if (source->kind == Type_Pointer) {
-			return is_polymorphic_type_assignable(c, poly->Pointer.elem, source->Pointer.elem, true, modify_type);
+			if (compound) return are_types_identical(poly, source);
+			return check_is_assignable_to(c, &o, poly);
 		}
 		return false;
 	case Type_Atomic:
@@ -1354,7 +1356,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 					param->TypeName.is_type_alias = true;
 				} else {
 					if (operands != NULL && is_type_polymorphic_type) {
-						type = determine_type_from_polymorphic(c, type, (*operands)[variable_index]);
+						Operand op = (*operands)[variable_index];
+						type = determine_type_from_polymorphic(c, type, op);
 						if (type == t_invalid) {
 							success = false;
 						}
@@ -4177,6 +4180,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		operand->type = type;
 	} break;
 
+	#if 1
 	case BuiltinProc_free: {
 		// proc free(^Type)
 		// proc free([]Type)
@@ -4206,6 +4210,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 
 		operand->mode = Addressing_NoValue;
 	} break;
+	#endif
 
 
 	case BuiltinProc_reserve: {
@@ -4478,48 +4483,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		operand->type = t_untyped_bool;
 		break;
 
-	case BuiltinProc_copy: {
-		// proc copy(x, y: []Type) -> int
-		Type *dest_type = NULL, *src_type = NULL;
-
-		Type *d = base_type(operand->type);
-		if (d->kind == Type_Slice) {
-			dest_type = d->Slice.elem;
-		}
-		Operand op = {};
-		check_expr(c, &op, ce->args[1]);
-		if (op.mode == Addressing_Invalid) {
-			return false;
-		}
-		Type *s = base_type(op.type);
-		if (s->kind == Type_Slice) {
-			src_type = s->Slice.elem;
-		}
-
-		if (dest_type == NULL || src_type == NULL) {
-			error(call, "`copy` only expects slices as arguments");
-			return false;
-		}
-
-		if (!are_types_identical(dest_type, src_type)) {
-			gbString d_arg = expr_to_string(ce->args[0]);
-			gbString s_arg = expr_to_string(ce->args[1]);
-			gbString d_str = type_to_string(dest_type);
-			gbString s_str = type_to_string(src_type);
-			error(call,
-			      "Arguments to `copy`, %s, %s, have different elem types: %s vs %s",
-			      d_arg, s_arg, d_str, s_str);
-			gb_string_free(s_str);
-			gb_string_free(d_str);
-			gb_string_free(s_arg);
-			gb_string_free(d_arg);
-			return false;
-		}
-
-		operand->type = t_int; // Returns number of elems copied
-		operand->mode = Addressing_Value;
-	} break;
-
 	case BuiltinProc_swizzle: {
 		// proc swizzle(v: {N}T, T..) -> {M}T
 		Type *vector_type = base_type(operand->type);
@@ -4699,6 +4662,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 
 	} break;
 
+	#if 1
 	case BuiltinProc_slice_ptr: {
 		// proc slice_ptr(a: ^T, len: int) -> []T
 		// proc slice_ptr(a: ^T, len, cap: int) -> []T
@@ -4755,6 +4719,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		operand->type = t_u8_slice;
 		operand->mode = Addressing_Value;
 	} break;
+	#endif
 
 	case BuiltinProc_expand_to_tuple: {
 		Type *type = base_type(operand->type);
@@ -5146,7 +5111,13 @@ bool check_unpack_arguments(Checker *c, isize lhs_count, Array<Operand> *operand
 }
 
 // NOTE(bill): Returns `NULL` on failure
-Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Array<Operand> *operands, ProcedureInfo *proc_info_) {
+Entity *find_or_generate_polymorphic_procedure(Checker *c, AstNode *call, Entity *base_entity, CallArgumentCheckerType *call_checker,
+                                               Array<Operand> *operands, ProcedureInfo *proc_info_) {
+	///////////////////////////////////////////////////////////////////////////////
+	//                                                                           //
+	// TODO CLEANUP(bill): This procedure is very messy and hacky. Clean this!!! //
+	//                                                                           //
+	///////////////////////////////////////////////////////////////////////////////
 	if (base_entity == NULL) {
 		return NULL;
 	}
@@ -5172,19 +5143,25 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 	scope->is_proc = true;
 	c->context.scope = scope;
 
+	bool generate_type_again = c->context.no_polymorphic_errors;
+
 	// NOTE(bill): This is slightly memory leaking if the type already exists
 	// Maybe it's better to check with the previous types first?
-	Type *final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
+	Type *final_proc_type = make_type_proc(c->allocator, scope, NULL, 0, NULL, 0, false, pt->calling_convention);
 	bool success = check_procedure_type(c, final_proc_type, pt->node, operands);
-	// if (!success) {
-		// return NULL;
-	// }
+	if (!success) {
+		ProcedureInfo proc_info = {};
+		if (proc_info_) *proc_info_ = proc_info;
+		return NULL;
+	}
 
 	auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
 	if (found_gen_procs) {
-		for_array(i, *found_gen_procs) {
-			Entity *other = (*found_gen_procs)[i];
-			if (are_types_identical(other->type, final_proc_type)) {
+		auto procs = *found_gen_procs;
+		for_array(i, procs) {
+			Entity *other = procs[i];
+			Type *pt = base_type(other->type);
+			if (are_types_identical(pt, final_proc_type)) {
 				// NOTE(bill): This scope is not needed any more, destroy it
 				// destroy_scope(scope);
 				return other;
@@ -5192,6 +5169,37 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 		}
 	}
 
+	if (generate_type_again) {
+		// LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice
+
+		bool prev_no_polymorphic_errors = c->context.no_polymorphic_errors;
+		defer (c->context.no_polymorphic_errors = prev_no_polymorphic_errors);
+		c->context.no_polymorphic_errors = false;
+
+		// NOTE(bill): Reset scope from the failed procedure type
+		scope_reset(scope);
+
+		success = check_procedure_type(c, final_proc_type, pt->node, operands);
+
+		if (!success) {
+			ProcedureInfo proc_info = {};
+			if (proc_info_) *proc_info_ = proc_info;
+			return NULL;
+		}
+
+		if (found_gen_procs) {
+			auto procs = *found_gen_procs;
+			for_array(i, procs) {
+				Entity *other = procs[i];
+				Type *pt = base_type(other->type);
+				if (are_types_identical(pt, final_proc_type)) {
+					// NOTE(bill): This scope is not needed any more, destroy it
+					// destroy_scope(scope);
+					return other;
+				}
+			}
+		}
+	}
 
 	AstNode *proc_lit = clone_ast_node(a, old_decl->proc_lit);
 	ast_node(pl, ProcLit, proc_lit);
@@ -5202,7 +5210,7 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 	u64 tags = base_entity->Procedure.tags;
 	AstNode *ident = clone_ast_node(a, base_entity->identifier);
 	Token token = ident->Ident.token;
-	DeclInfo *d = make_declaration_info(c->allocator, c->context.scope, old_decl->parent);
+	DeclInfo *d = make_declaration_info(c->allocator, scope, old_decl->parent);
 	d->gen_proc_type = final_proc_type;
 	d->type_expr = pl->type;
 	d->proc_lit = proc_lit;
@@ -5212,16 +5220,18 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 	entity->identifier = ident;
 
 	add_entity_and_decl_info(c, ident, entity, d);
-	entity->scope = base_entity->scope;
+	// NOTE(bill): Set the scope afterwards as this is not real overloading
+	entity->scope = scope->parent;
 
 	ProcedureInfo proc_info = {};
 	if (success) {
-		proc_info.file = c->curr_ast_file;
+		proc_info.file  = c->curr_ast_file;
 		proc_info.token = token;
 		proc_info.decl  = d;
 		proc_info.type  = final_proc_type;
 		proc_info.body  = pl->body;
 		proc_info.tags  = tags;
+		proc_info.generated_from_polymorphic = true;
 	}
 
 	if (found_gen_procs) {
@@ -5329,7 +5339,7 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 			ProcedureInfo proc_info = {};
 
 			if (pt->is_polymorphic && !pt->is_poly_specialized) {
-				gen_entity = find_or_generate_polymorphic_procedure(c, entity, &operands, &proc_info);
+				gen_entity = find_or_generate_polymorphic_procedure(c, call, entity, check_call_arguments_internal, &operands, &proc_info);
 				if (gen_entity != NULL) {
 					GB_ASSERT(is_type_proc(gen_entity->type));
 					final_proc_type = gen_entity->type;
@@ -5557,9 +5567,9 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
 	}
 
 	Entity *gen_entity = NULL;
-	if (pt->is_polymorphic && err == CallArgumentError_None) {
+	if (pt->is_polymorphic && !pt->is_poly_specialized && err == CallArgumentError_None) {
 		ProcedureInfo proc_info = {};
-		gen_entity = find_or_generate_polymorphic_procedure(c, entity, &ordered_operands, &proc_info);
+		gen_entity = find_or_generate_polymorphic_procedure(c, call, entity, check_named_call_arguments, &ordered_operands, &proc_info);
 		if (gen_entity != NULL) {
 			if (proc_info.decl != NULL) {
 				check_procedure_later(c, proc_info);
@@ -5684,23 +5694,31 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 		if (valid_count > 1) {
 			gb_sort_array(valids, valid_count, valid_proc_and_score_cmp);
 			i64 best_score = valids[0].score;
+			Entity *best_entity = procs[valids[0].index];
 			for (isize i = 0; i < valid_count; i++) {
 				if (best_score > valids[i].score) {
 					valid_count = i;
 					break;
 				}
+				if (best_entity == procs[valids[i].index]) {
+					valid_count = i;
+					break;
+				}
 				best_score = valids[i].score;
 			}
 		}
 
 
 		if (valid_count == 0) {
-			error(operand->expr, "No overloads for `%.*s` that match with the given arguments", LIT(name));
-			gb_printf_err("Did you mean to use one of these procedures:\n");
+			error(operand->expr, "No overloads or ambiguous call for `%.*s` that match with the given arguments", LIT(name));
+			if (overload_count > 0) {
+				gb_printf_err("Did you mean to use one of the following:\n");
+			}
 			for (isize i = 0; i < overload_count; i++) {
 				Entity *proc = procs[i];
 				TokenPos pos = proc->token.pos;
-				gbString pt = type_to_string(proc->type);
+				// gbString pt = type_to_string(proc->type);
+				gbString pt = expr_to_string(proc->type->Proc.node);
 				gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
 				gb_string_free(pt);
 			}
@@ -5711,7 +5729,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 				Entity *proc = procs[valids[i].index];
 				TokenPos pos = proc->token.pos;
 				gbString pt = type_to_string(proc->type);
-				gb_printf_err("\t%.*s :: %s at %.*s(%td:%td)\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) with score %lld\n", LIT(name), pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
 				gb_string_free(pt);
 			}
 			result_type = t_invalid;
@@ -7253,6 +7271,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = gb_string_appendc(str, ")");
 	case_end;
 
+	case_ast_node(ht, HelperType, node);
+		str = gb_string_appendc(str, "type");
+	case_end;
+
 	case_ast_node(pt, ProcType, node);
 		str = gb_string_appendc(str, "proc(");
 		str = write_expr_to_string(str, pt->params);

+ 11 - 4
src/checker.cpp

@@ -44,8 +44,6 @@ enum BuiltinProcId {
 
 	BuiltinProc_compile_assert,
 
-	BuiltinProc_copy,
-
 	BuiltinProc_swizzle,
 
 	BuiltinProc_complex,
@@ -92,8 +90,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 
 	{STR_LIT("compile_assert"),   1, false, Expr_Expr},
 
-	{STR_LIT("copy"),             2, false, Expr_Expr},
-
 	{STR_LIT("swizzle"),          1, true,  Expr_Expr},
 
 	{STR_LIT("complex"),          2, false, Expr_Expr},
@@ -204,6 +200,7 @@ struct ProcedureInfo {
 	Type *                type; // Type_Procedure
 	AstNode *             body; // AstNode_BlockStmt
 	u64                   tags;
+	bool                  generated_from_polymorphic;
 };
 
 // ExprInfo stores information used for "untyped" expressions
@@ -241,6 +238,16 @@ struct Scope {
 };
 gb_global Scope *universal_scope = NULL;
 
+void scope_reset(Scope *scope) {
+	if (scope == NULL) return;
+
+	scope->first_child = NULL;
+	scope->last_child  = NULL;
+	map_clear  (&scope->elements);
+	map_clear  (&scope->implicit);
+	array_clear(&scope->shared);
+	array_clear(&scope->imported);
+}
 
 
 struct DelayedDecl {

+ 22 - 39
src/ir.cpp

@@ -3532,7 +3532,7 @@ String ir_mangle_name(irGen *s, String path, Entity *e) {
 	isize base_len = ext-1-base;
 
 	isize max_len = base_len + 1 + 1 + 10 + 1 + name.len;
-	bool require_suffix_id = check_is_entity_overloaded(e) || is_type_poly_proc(e->type);
+	bool require_suffix_id = check_is_entity_overloaded(e) || is_type_polymorphic(e->type);
 	if (require_suffix_id) {
 		max_len += 21;
 	}
@@ -3922,6 +3922,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		}
 	} break;
 
+	#if 1
 	case BuiltinProc_free: {
 		ir_emit_comment(proc, str_lit("free"));
 
@@ -3995,6 +3996,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		args[0] = ptr;
 		return ir_emit_global_call(proc, "free_ptr", args, 1);
 	} break;
+	#endif
 
 	case BuiltinProc_reserve: {
 		ir_emit_comment(proc, str_lit("reserve"));
@@ -4183,39 +4185,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
 	} break;
 
-	case BuiltinProc_copy: {
-		ir_emit_comment(proc, str_lit("copy"));
-		// proc copy(dst, src: []Type) -> int
-		AstNode *dst_node = ce->args[0];
-		AstNode *src_node = ce->args[1];
-		irValue *dst_slice = ir_build_expr(proc, dst_node);
-		irValue *src_slice = ir_build_expr(proc, src_node);
-		Type *slice_type = base_type(ir_type(dst_slice));
-		GB_ASSERT(slice_type->kind == Type_Slice);
-		Type *elem_type = slice_type->Slice.elem;
-		i64 size_of_elem = type_size_of(proc->module->allocator, elem_type);
-
-		irValue *dst = ir_emit_conv(proc, ir_slice_elem(proc, dst_slice), t_rawptr);
-		irValue *src = ir_emit_conv(proc, ir_slice_elem(proc, src_slice), t_rawptr);
-
-		irValue *len_dst = ir_slice_count(proc, dst_slice);
-		irValue *len_src = ir_slice_count(proc, src_slice);
-
-		irValue *cond = ir_emit_comp(proc, Token_Lt, len_dst, len_src);
-		irValue *len = ir_emit_select(proc, cond, len_dst, len_src);
-
-		irValue *elem_size = ir_const_int(proc->module->allocator, size_of_elem);
-		irValue *byte_count = ir_emit_arith(proc, Token_Mul, len, elem_size, t_int);
-
-		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
-		args[0] = dst;
-		args[1] = src;
-		args[2] = byte_count;
-
-		ir_emit_global_call(proc, "__mem_copy", args, 3);
 
-		return len;
-	} break;
 	case BuiltinProc_swizzle: {
 		ir_emit_comment(proc, str_lit("swizzle.begin"));
 		irAddr vector_addr = ir_build_addr(proc, ce->args[0]);
@@ -4288,6 +4258,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		return ir_emit_load(proc, res);
 	} break;
 
+	#if 1
 	case BuiltinProc_slice_ptr: {
 		ir_emit_comment(proc, str_lit("slice_ptr"));
 		irValue *ptr = ir_build_expr(proc, ce->args[0]);
@@ -4323,6 +4294,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		ir_fill_slice(proc, slice, ptr, count, capacity);
 		return ir_emit_load(proc, slice);
 	} break;
+	#endif
 
 	case BuiltinProc_expand_to_tuple: {
 		ir_emit_comment(proc, str_lit("expand_to_tuple"));
@@ -4924,7 +4896,10 @@ irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) {
 	}
 
 	if (v == NULL) {
-		GB_PANIC("Unknown value: %.*s, entity: %p %.*s\n", LIT(e->token.string), e, LIT(entity_strings[e->kind]));
+		error(expr, "%.*s Unknown value: %.*s, entity: %p %.*s",
+		      LIT(proc->name),
+		      LIT(e->token.string), e, LIT(entity_strings[e->kind]));
+		GB_PANIC("Unknown value");
 	}
 
 	return ir_addr(v);
@@ -4937,7 +4912,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		switch (i->kind) {
 		case Token_context:
 			v = ir_find_or_generate_context_ptr(proc);
-			// v = ir_find_global_variable(proc, str_lit("__context"));
 			break;
 		}
 
@@ -4950,7 +4924,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			irAddr val = {};
 			return val;
 		}
+		String name = i->token.string;
 		Entity *e = entity_of_ident(proc->module->info, expr);
+		// GB_ASSERT(name == e->token.string);
 		return ir_build_addr_from_entity(proc, e, expr);
 	case_end;
 
@@ -7093,7 +7069,6 @@ void ir_build_proc(irValue *value, irProcedure *parent) {
 			proc->module->stmt_state_flags = out;
 		}
 
-
 		ir_begin_procedure_body(proc);
 		ir_insert_code_before_proc(proc, parent);
 		ir_build_stmt(proc, proc->body);
@@ -7423,12 +7398,14 @@ void ir_gen_tree(irGen *s) {
 			continue;
 		}
 
-		if (map_get(&m->min_dep_map, hash_pointer(e)) == NULL) {
+		if (map_get(&m->min_dep_map, hash_entity(e)) == NULL) {
 			// NOTE(bill): Nothing depends upon it so doesn't need to be built
 			continue;
 		}
 
-		if (!scope->is_global || is_type_poly_proc(e->type)) {
+		String original_name = name;
+
+		if (!scope->is_global || is_type_polymorphic(e->type)) {
 			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 				// Handle later
@@ -7436,8 +7413,14 @@ void ir_gen_tree(irGen *s) {
 			} else {
 				name = ir_mangle_name(s, e->token.pos.file, e);
 			}
+		} else if (check_is_entity_overloaded(e)) {
+			name = ir_mangle_name(s, e->token.pos.file, e);
+
+			gb_printf_err("%.*s|%.*s :: %s\n", LIT(original_name), LIT(name), type_to_string(e->type));
+
 		}
-		map_set(&m->entity_names, hash_pointer(e), name);
+
+		map_set(&m->entity_names, hash_entity(e), name);
 
 		switch (e->kind) {
 		case Entity_TypeName:

+ 2 - 1
src/ir_print.cpp

@@ -732,7 +732,8 @@ void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hin
 		ir_print_encoded_local(f, value->TypeName.name);
 		break;
 	case irValue_Global: {
-		Scope *scope = value->Global.entity->scope;
+		Entity *e = value->Global.entity;
+		Scope *scope = e->scope;
 		bool in_global_scope = false;
 		if (scope != NULL) {
 			// TODO(bill): Fix this rule. What should it be?

+ 15 - 11
src/types.cpp

@@ -1354,15 +1354,14 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
 	TypeProc py = base_type(y)->Proc;
 
 
-	if (px.is_polymorphic != py.is_polymorphic) {
-		return ProcOverload_Polymorphic;
-	}
-
-
 	// if (px.calling_convention != py.calling_convention) {
 		// return ProcOverload_CallingConvention;
 	// }
 
+	// if (px.is_polymorphic != py.is_polymorphic) {
+		// return ProcOverload_Polymorphic;
+	// }
+
 	if (px.param_count != py.param_count) {
 		return ProcOverload_ParamCount;
 	}
@@ -1379,6 +1378,11 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
 		return ProcOverload_ParamVariadic;
 	}
 
+
+	if (px.is_polymorphic != py.is_polymorphic) {
+		return ProcOverload_Polymorphic;
+	}
+
 	if (px.result_count != py.result_count) {
 		return ProcOverload_ResultCount;
 	}
@@ -2448,12 +2452,12 @@ gbString write_type_to_string(gbString str, Type *type) {
 						}
 					} else {
 						GB_ASSERT(var->kind == Entity_TypeName);
-						#if 0
-						str = gb_string_appendc(str, "type/");
-						str = write_type_to_string(str, var->type);
-						#else
-						str = gb_string_appendc(str, "type");
-						#endif
+						if (var->type->kind == Type_Generic) {
+							str = gb_string_appendc(str, "type/");
+							str = write_type_to_string(str, var->type);
+						} else {
+							str = gb_string_appendc(str, "type");
+						}
 					}
 				}
 			}