Browse Source

Merge branch 'master' of github.com:gingerBill/Odin

Mikkel Hjortshoej 8 years ago
parent
commit
47c03e376d
28 changed files with 1852 additions and 1736 deletions
  1. 6 9
      build.bat
  2. 92 92
      src/array.cpp
  3. 21 21
      src/build_settings.cpp
  4. 26 26
      src/check_decl.cpp
  5. 187 144
      src/check_expr.cpp
  6. 77 82
      src/check_stmt.cpp
  7. 177 210
      src/checker.cpp
  8. 12 32
      src/common.cpp
  9. 18 18
      src/entity.cpp
  10. 40 38
      src/exact_value.cpp
  11. 111 14
      src/integer128.cpp
  12. 156 169
      src/ir.cpp
  13. 43 43
      src/ir_opt.cpp
  14. 31 31
      src/ir_print.cpp
  15. 17 26
      src/main.cpp
  16. 0 364
      src/map.c
  17. 364 0
      src/map.cpp
  18. 22 17
      src/murmurhash3.cpp
  19. 179 157
      src/parser.cpp
  20. 0 0
      src/printer.cpp
  21. 110 109
      src/ssa.cpp
  22. 0 1
      src/ssa_op.cpp
  23. 66 33
      src/string.cpp
  24. 10 10
      src/timings.cpp
  25. 22 22
      src/tokenizer.cpp
  26. 55 55
      src/types.cpp
  27. 2 1
      src/unicode.cpp
  28. 8 12
      src/utf8proc/utf8proc.c

+ 6 - 9
build.bat

@@ -4,8 +4,8 @@
 set exe_name=odin.exe
 
 :: Debug = 0, Release = 1
-set release_mode=1
-set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
+set release_mode=0
+set compiler_flags= -nologo -Oi -TP -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
 
 if %release_mode% EQU 0 ( rem Debug
 	set compiler_flags=%compiler_flags% -Od -MDd -Z7
@@ -42,13 +42,10 @@ set linker_settings=%libs% %linker_flags%
 del *.pdb > NUL 2> NUL
 del *.ilk > NUL 2> NUL
 
-odin run code/demo.odin
-rem cl %compiler_settings% "src\main.c" ^
-	rem /link %linker_settings% -OUT:%exe_name% ^
-	rem && odin run code/demo.odin
-	rem && odin build code/metagen.odin ^
-	rem && call "code\metagen.exe" "src\ast_nodes.metagen"
-	rem && odin run code/Jaze/src/main.odin
+rem odin run code/demo.odin
+cl %compiler_settings% "src\main.cpp" ^
+	/link %linker_settings% -OUT:%exe_name% ^
+	&& odin run code/demo.odin
 
 del *.obj > NUL 2> NUL
 

+ 92 - 92
src/array.c → src/array.cpp

@@ -1,98 +1,7 @@
 #define ARRAY_GROW_FORMULA(x) (2*(x) + 8)
 GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
 
-#define Array(Type_) struct { \
-	gbAllocator allocator; \
-	Type_ *     e; \
-	isize       count; \
-	isize       capacity; \
-}
-
-typedef Array(void) ArrayVoid;
-
-#define array_init_reserve(x_, allocator_, init_capacity_) do { \
-	void **e = cast(void **)&((x_)->e); \
-	GB_ASSERT((x_) != NULL); \
-	(x_)->allocator = (allocator_); \
-	(x_)->count = 0; \
-	(x_)->capacity = (init_capacity_); \
-	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_capacity_)); \
-} while (0)
-
-#define array_init_count(x_, allocator_, init_count_) do { \
-	void **e = cast(void **)&((x_)->e); \
-	GB_ASSERT((x_) != NULL); \
-	(x_)->allocator = (allocator_); \
-	(x_)->count = (init_count_); \
-	(x_)->capacity = (init_count_); \
-	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_count_)); \
-} while (0)
-
-#define array_init(x_, allocator_)        do { array_init_reserve(x_, allocator_, ARRAY_GROW_FORMULA(0)); } while (0)
-#define array_free(x_)                    do { gb_free((x_)->allocator, (x_)->e); } while (0)
-#define array_set_capacity(x_, capacity_) do { array__set_capacity((x_), (capacity_), gb_size_of(*(x_)->e)); } while (0)
-
-#define array_grow(x_, min_capacity_) do { \
-	isize new_capacity = ARRAY_GROW_FORMULA((x_)->capacity); \
-	if (new_capacity < (min_capacity_)) { \
-		new_capacity = (min_capacity_); \
-	} \
-	array_set_capacity(x_, new_capacity); \
-} while (0)
-
-#define array_add(x_, item_) do { \
-	if ((x_)->capacity < (x_)->count+1) { \
-		array_grow(x_, 0); \
-	} \
-	(x_)->e[(x_)->count++] = item_; \
-} while (0)
-
-#define array_pop(x_)   do { GB_ASSERT((x_)->count > 0); (x_)->count--; } while (0)
-#define array_clear(x_) do { (x_)->count = 0; } while (0)
-
-#define array_resize(x_, new_count_) do { \
-	if ((x_)->capacity < (new_count_)) { \
-		array_grow((x_), (new_count_)); \
-	} \
-	(x_)->count = (new_count_); \
-} while (0)
-
-#define array_reserve(x_, new_capacity_) do { \
-	if ((x_)->capacity < (new_capacity_)) { \
-		array_set_capacity((x_), (new_capacity_)); \
-	} \
-} while (0)
-
-
-
-
-void array__set_capacity(void *ptr, isize capacity, isize element_size) {
-	ArrayVoid *x = cast(ArrayVoid *)ptr;
-	GB_ASSERT(ptr != NULL);
-
-	GB_ASSERT(element_size > 0);
-
-	if (capacity == x->capacity) {
-		return;
-	}
-
-	if (capacity < x->count) {
-		if (x->capacity < capacity) {
-			isize new_capacity = ARRAY_GROW_FORMULA(x->capacity);
-			if (new_capacity < capacity) {
-				new_capacity = capacity;
-			}
-			array__set_capacity(ptr, new_capacity, element_size);
-		}
-		x->count = capacity;
-	}
-
-	x->e = gb_resize(x->allocator, x->e, element_size*x->capacity, element_size*capacity);
-	x->capacity = capacity;
-}
-
-
-#if 0
+#if 1
 template <typename T>
 struct Array {
 	gbAllocator allocator;
@@ -224,6 +133,97 @@ void array_set_capacity(Array<T> *array, isize capacity) {
 	array->capacity = capacity;
 }
 
+#endif
+
+#if 0
+#define Array(Type_) struct { \
+	gbAllocator allocator; \
+	Type_ *     e; \
+	isize       count; \
+	isize       capacity; \
+}
+
+typedef Array(void) ArrayVoid;
+
+#define array_init_reserve(x_, allocator_, init_capacity_) do { \
+	void **e = cast(void **)&((x_)->e); \
+	GB_ASSERT((x_) != NULL); \
+	(x_)->allocator = (allocator_); \
+	(x_)->count = 0; \
+	(x_)->capacity = (init_capacity_); \
+	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_capacity_)); \
+} while (0)
+
+#define array_init_count(x_, allocator_, init_count_) do { \
+	void **e = cast(void **)&((x_)->e); \
+	GB_ASSERT((x_) != NULL); \
+	(x_)->allocator = (allocator_); \
+	(x_)->count = (init_count_); \
+	(x_)->capacity = (init_count_); \
+	*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_count_)); \
+} while (0)
 
+#define array_init(x_, allocator_)        do { array_init_reserve(x_, allocator_, ARRAY_GROW_FORMULA(0)); } while (0)
+#define array_free(x_)                    do { gb_free((x_)->allocator, (x_)->e); } while (0)
+#define array_set_capacity(x_, capacity_) do { array__set_capacity((x_), (capacity_), gb_size_of(*(x_)->e)); } while (0)
 
+#define array_grow(x_, min_capacity_) do { \
+	isize new_capacity = ARRAY_GROW_FORMULA((x_)->capacity); \
+	if (new_capacity < (min_capacity_)) { \
+		new_capacity = (min_capacity_); \
+	} \
+	array_set_capacity(x_, new_capacity); \
+} while (0)
+
+#define array_add(x_, item_) do { \
+	if ((x_)->capacity < (x_)->count+1) { \
+		array_grow(x_, 0); \
+	} \
+	(x_)->e[(x_)->count++] = item_; \
+} while (0)
+
+#define array_pop(x_)   do { GB_ASSERT((x_)->count > 0); (x_)->count--; } while (0)
+#define array_clear(x_) do { (x_)->count = 0; } while (0)
+
+#define array_resize(x_, new_count_) do { \
+	if ((x_)->capacity < (new_count_)) { \
+		array_grow((x_), (new_count_)); \
+	} \
+	(x_)->count = (new_count_); \
+} while (0)
+
+#define array_reserve(x_, new_capacity_) do { \
+	if ((x_)->capacity < (new_capacity_)) { \
+		array_set_capacity((x_), (new_capacity_)); \
+	} \
+} while (0)
+
+
+
+
+void array__set_capacity(void *ptr, isize capacity, isize element_size) {
+	ArrayVoid *x = cast(ArrayVoid *)ptr;
+	GB_ASSERT(ptr != NULL);
+
+	GB_ASSERT(element_size > 0);
+
+	if (capacity == x->capacity) {
+		return;
+	}
+
+	if (capacity < x->count) {
+		if (x->capacity < capacity) {
+			isize new_capacity = ARRAY_GROW_FORMULA(x->capacity);
+			if (new_capacity < capacity) {
+				new_capacity = capacity;
+			}
+			array__set_capacity(ptr, new_capacity, element_size);
+		}
+		x->count = capacity;
+	}
+
+	x->e = gb_resize(x->allocator, x->e, element_size*x->capacity, element_size*capacity);
+	x->capacity = capacity;
+}
 #endif
+

+ 21 - 21
src/build_settings.c → src/build_settings.cpp

@@ -1,5 +1,5 @@
 // This stores the information for the specify architecture of this build
-typedef struct BuildContext {
+struct BuildContext {
 	// Constants
 	String ODIN_OS;      // target operating system
 	String ODIN_ARCH;    // target architecture
@@ -15,7 +15,7 @@ typedef struct BuildContext {
 	String llc_flags;
 	String link_flags;
 	bool   is_dll;
-} BuildContext;
+};
 
 
 gb_global BuildContext build_context = {0};
@@ -35,7 +35,7 @@ String const NIX_SEPARATOR_STRING   = {cast(u8 *)"/",  1};
 #if defined(GB_SYSTEM_WINDOWS)
 String odin_root_dir(void) {
 	String path = global_module_path;
-	Array(wchar_t) path_buf;
+	Array<wchar_t> path_buf;
 	isize len, i;
 	gbTempArenaMemory tmp;
 	wchar_t *text;
@@ -48,7 +48,7 @@ String odin_root_dir(void) {
 
 	len = 0;
 	for (;;) {
-		len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
+		len = GetModuleFileNameW(NULL, &path_buf[0], path_buf.count);
 		if (len == 0) {
 			return make_string(NULL, 0);
 		}
@@ -65,7 +65,7 @@ String odin_root_dir(void) {
 	GetModuleFileNameW(NULL, text, len);
 	path = string16_to_string(heap_allocator(), make_string16(text, len));
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 			break;
 		}
@@ -102,7 +102,7 @@ String odin_root_dir(void) {
 	len = 0;
 	for (;;) {
 		int sz = path_buf.count;
-		int res = _NSGetExecutablePath(&path_buf.e[0], &sz);
+		int res = _NSGetExecutablePath(&path_buf[0], &sz);
 		if(res == 0) {
 			len = sz;
 			break;
@@ -114,11 +114,11 @@ String odin_root_dir(void) {
 
 	tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
 	text = gb_alloc_array(string_buffer_allocator, u8, len + 1);
-	gb_memmove(text, &path_buf.e[0], len);
+	gb_memmove(text, &path_buf[0], len);
 
 	path = make_string(text, len);
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 			break;
 		}
@@ -158,7 +158,7 @@ String odin_root_dir(void) {
 		// of this compiler, it should be _good enough_.
 		// That said, there's no solid 100% method on Linux to get the program's
 		// path without checking this link. Sorry.
-		len = readlink("/proc/self/exe", &path_buf.e[0], path_buf.count);
+		len = readlink("/proc/self/exe", &path_buf[0], path_buf.count);
 		if(len == 0) {
 			return make_string(NULL, 0);
 		}
@@ -171,11 +171,11 @@ String odin_root_dir(void) {
 
 	tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
 	text = gb_alloc_array(string_buffer_allocator, u8, len + 1);
-	gb_memmove(text, &path_buf.e[0], len);
+	gb_memmove(text, &path_buf[0], len);
 
 	path = make_string(text, len);
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 			break;
 		}
@@ -200,10 +200,10 @@ String path_to_fullpath(gbAllocator a, String s) {
 	String16 string16 = string_to_string16(string_buffer_allocator, s);
 	String result = {0};
 
-	DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
+	DWORD len = GetFullPathNameW(&string16[0], 0, NULL, NULL);
 	if (len != 0) {
 		wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
-		GetFullPathNameW(string16.text, len, text, NULL);
+		GetFullPathNameW(&string16[0], len, text, NULL);
 		text[len] = 0;
 		result = string16_to_string(a, make_string16(text, len));
 	}
@@ -212,7 +212,7 @@ String path_to_fullpath(gbAllocator a, String s) {
 }
 #elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
 String path_to_fullpath(gbAllocator a, String s) {
-	char *p = realpath(cast(char *)s.text, 0);
+	char *p = realpath(cast(char *)&s[0], 0);
 	if(p == NULL) return make_string_c("");
 
 	return make_string_c(p);
@@ -229,8 +229,8 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
 
 	isize i = 0;
-	gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len;
-	gb_memmove(str+i, path.text, path.len);
+	gb_memmove(str+i, &base_dir[0], base_dir.len); i += base_dir.len;
+	gb_memmove(str+i, &path[0], path.len);
 	str[str_len] = '\0';
 	res = path_to_fullpath(a, make_string(str, str_len));
 	gb_free(heap_allocator(), str);
@@ -247,9 +247,9 @@ String get_fullpath_core(gbAllocator a, String path) {
 	isize str_len = module_dir.len + core_len + path.len;
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
 
-	gb_memmove(str, module_dir.text, module_dir.len);
+	gb_memmove(str, &module_dir[0], module_dir.len);
 	gb_memmove(str+module_dir.len, core, core_len);
-	gb_memmove(str+module_dir.len+core_len, path.text, path.len);
+	gb_memmove(str+module_dir.len+core_len, &path[0], path.len);
 	str[str_len] = '\0';
 
 	res = path_to_fullpath(a, make_string(str, str_len));
@@ -294,7 +294,7 @@ void init_build_context(void) {
 
 	// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
 	// an architecture option. All compilation done on MacOS must be x64.
-	GB_ASSERT(str_eq(bc->ODIN_ARCH, str_lit("amd64")));
+	GB_ASSERT(bc->ODIN_ARCH == "amd64");
 
 	#define LINK_FLAG_X64 ""
 	#define LINK_FLAG_X86 ""
@@ -311,12 +311,12 @@ void init_build_context(void) {
 	#define LINK_FLAG_X86 "-arch x86"
 	#endif
 
-	if (str_eq(bc->ODIN_ARCH, str_lit("amd64"))) {
+	if (bc->ODIN_ARCH == "amd64") {
 		bc->word_size = 8;
 		bc->max_align = 16;
 		bc->llc_flags = str_lit("-march=x86-64 ");
 		bc->link_flags = str_lit(LINK_FLAG_X64 " ");
-	} else if (str_eq(bc->ODIN_ARCH, str_lit("x86"))) {
+	} else if (bc->ODIN_ARCH == "x86") {
 		bc->word_size = 4;
 		bc->max_align = 8;
 		bc->llc_flags = str_lit("-march=x86 ");

+ 26 - 26
src/check_decl.c → src/check_decl.cpp

@@ -13,7 +13,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 			// TODO(bill): is this a good enough error message?
 			// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
 			error_node(operand->expr,
-				  "Cannot assign builtin procedure `%s` in %.*s",
+				  "Cannot assign built-in procedure `%s` in %.*s",
 				  expr_str,
 				  LIT(context_name));
 
@@ -58,7 +58,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
 	return e->type;
 }
 
-void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
+void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNode *> inits, String context_name) {
 	if ((lhs == NULL || lhs_count == 0) && inits.count == 0) {
 		return;
 	}
@@ -67,20 +67,20 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
 
 	// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 	// an extra allocation
-	ArrayOperand operands = {0};
-	array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
+	Array<Operand> operands = {};
+	array_init(&operands, c->tmp_allocator, 2*lhs_count);
 	check_unpack_arguments(c, lhs_count, &operands, inits, true);
 
 	isize rhs_count = operands.count;
 	for_array(i, operands) {
-		if (operands.e[i].mode == Addressing_Invalid) {
+		if (operands[i].mode == Addressing_Invalid) {
 			rhs_count--;
 		}
 	}
 
 	isize max = gb_min(lhs_count, rhs_count);
 	for (isize i = 0; i < max; i++) {
-		check_init_variable(c, lhs[i], &operands.e[i], context_name);
+		check_init_variable(c, lhs[i], &operands[i], context_name);
 	}
 	if (rhs_count > 0 && lhs_count != rhs_count) {
 		error(lhs[0]->token, "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
@@ -145,7 +145,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
 
 	// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
 
-	Type *bt = check_type_extra(c, type_expr, named);
+	Type *bt = check_type(c, type_expr, named);
 	named->Named.base = base_type(bt);
 	if (named->Named.base == t_invalid) {
 		// gb_printf("check_type_decl: %s\n", type_to_string(named));
@@ -174,7 +174,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
 		e->type = t;
 	}
 
-	Operand operand = {0};
+	Operand operand = {};
 	if (init != NULL) {
 		check_expr_or_type(c, &operand, init);
 	}
@@ -274,7 +274,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 	bool is_require_results = (pd->tags & ProcTag_require_results) != 0;
 
 
-	if (d->scope->is_file && str_eq(e->token.string, str_lit("main"))) {
+	if (d->scope->is_file && e->token.string == "main") {
 		if (proc_type != NULL) {
 			TypeProc *pt = &proc_type->Proc;
 			if (pt->param_count != 0 ||
@@ -319,7 +319,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 	}
 
 	if (is_foreign) {
-		MapEntity *fp = &c->info.foreigns;
+		auto *fp = &c->info.foreigns;
 		String name = e->token.string;
 		if (pd->foreign_name.len > 0) {
 			name = pd->foreign_name;
@@ -334,7 +334,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 			String name = foreign_library->Ident.string;
 			Entity *found = scope_lookup_entity(c->context.scope, name);
 			if (found == NULL) {
-				if (str_eq(name, str_lit("_"))) {
+				if (name == "_") {
 					error_node(foreign_library, "`_` cannot be used as a value type");
 				} else {
 					error_node(foreign_library, "Undeclared name: %.*s", LIT(name));
@@ -352,7 +352,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 		e->Procedure.foreign_name = name;
 
 		HashKey key = hash_string(name);
-		Entity **found = map_entity_get(fp, key);
+		Entity **found = map_get(fp, key);
 		if (found) {
 			Entity *f = *found;
 			TokenPos pos = f->token.pos;
@@ -365,7 +365,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 						   LIT(name), LIT(pos.file), pos.line, pos.column);
 			}
 		} else {
-			map_entity_set(fp, key, e);
+			map_set(fp, key, e);
 		}
 	} else {
 		String name = e->token.string;
@@ -374,12 +374,12 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 		}
 
 		if (is_link_name || is_export) {
-			MapEntity *fp = &c->info.foreigns;
+			auto *fp = &c->info.foreigns;
 
 			e->Procedure.link_name = name;
 
 			HashKey key = hash_string(name);
-			Entity **found = map_entity_get(fp, key);
+			Entity **found = map_get(fp, key);
 			if (found) {
 				Entity *f = *found;
 				TokenPos pos = f->token.pos;
@@ -389,7 +389,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 						   "\tother at %.*s(%td:%td)",
 						   LIT(name), LIT(pos.file), pos.line, pos.column);
 			} else {
-				map_entity_set(fp, key, e);
+				map_set(fp, key, e);
 			}
 		}
 	}
@@ -408,7 +408,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	e->flags |= EntityFlag_Visited;
 
 	if (type_expr != NULL) {
-		e->type = check_type_extra(c, type_expr, NULL);
+		e->type = check_type(c, type_expr);
 	}
 
 	if (init_expr == NULL) {
@@ -420,7 +420,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 
 	if (entities == NULL || entity_count == 1) {
 		GB_ASSERT(entities == NULL || entities[0] == e);
-		Operand operand = {0};
+		Operand operand = {};
 		check_expr(c, &operand, init_expr);
 		check_init_variable(c, e, &operand, str_lit("variable declaration"));
 	}
@@ -431,8 +431,8 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 		}
 	}
 
-	AstNodeArray inits;
-	array_init_reserve(&inits, c->allocator, 1);
+	Array<AstNode *> inits;
+	array_init(&inits, c->allocator, 1);
 	array_add(&inits, init_expr);
 	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 }
@@ -443,7 +443,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 	}
 
 	if (d == NULL) {
-		DeclInfo **found = map_decl_info_get(&c->info.entities, hash_pointer(e));
+		DeclInfo **found = map_get(&c->info.entities, hash_pointer(e));
 		if (found) {
 			d = *found;
 		} else {
@@ -484,7 +484,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
 	GB_ASSERT(body->kind == AstNode_BlockStmt);
 
-	String proc_name = {0};
+	String proc_name = {};
 	if (token.kind == Token_Ident) {
 		proc_name = token.string;
 	} else {
@@ -511,10 +511,10 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 			String name = e->token.string;
 			Type *t = base_type(type_deref(e->type));
 			if (is_type_struct(t) || is_type_raw_union(t)) {
-				Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
+				Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 				GB_ASSERT(found != NULL);
 				for_array(i, (*found)->elements.entries) {
-					Entity *f = (*found)->elements.entries.e[i].value;
+					Entity *f = (*found)->elements.entries[i].value;
 					if (f->kind == Entity_Variable) {
 						Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 						uvar->Variable.is_immutable = is_immutable;
@@ -555,9 +555,9 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
 	if (decl->parent != NULL) {
 		// NOTE(bill): Add the dependencies from the procedure literal (lambda)
 		for_array(i, decl->deps.entries) {
-			HashKey key = decl->deps.entries.e[i].key;
+			HashKey key = decl->deps.entries[i].key;
 			Entity *e = cast(Entity *)key.ptr;
-			map_bool_set(&decl->parent->deps, key, true);
+			map_set(&decl->parent->deps, key, true);
 		}
 	}
 }

File diff suppressed because it is too large
+ 187 - 144
src/check_expr.cpp


+ 77 - 82
src/check_stmt.c → src/check_stmt.cpp

@@ -1,4 +1,4 @@
-void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
+void check_stmt_list(Checker *c, Array<AstNode *> stmts, u32 flags) {
 	if (stmts.count == 0) {
 		return;
 	}
@@ -12,13 +12,13 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 
 	isize max = stmts.count;
 	for (isize i = stmts.count-1; i >= 0; i--) {
-		if (stmts.e[i]->kind != AstNode_EmptyStmt) {
+		if (stmts[i]->kind != AstNode_EmptyStmt) {
 			break;
 		}
 		max--;
 	}
 	for (isize i = 0; i < max; i++) {
-		AstNode *n = stmts.e[i];
+		AstNode *n = stmts[i];
 		if (n->kind == AstNode_EmptyStmt) {
 			continue;
 		}
@@ -40,10 +40,10 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 
 }
 
-bool check_is_terminating_list(AstNodeArray stmts) {
+bool check_is_terminating_list(Array<AstNode *> stmts) {
 	// Iterate backwards
 	for (isize n = stmts.count-1; n >= 0; n--) {
-		AstNode *stmt = stmts.e[n];
+		AstNode *stmt = stmts[n];
 		if (stmt->kind != AstNode_EmptyStmt) {
 			return check_is_terminating(stmt);
 		}
@@ -52,9 +52,9 @@ bool check_is_terminating_list(AstNodeArray stmts) {
 	return false;
 }
 
-bool check_has_break_list(AstNodeArray stmts, bool implicit) {
+bool check_has_break_list(Array<AstNode *> stmts, bool implicit) {
 	for_array(i, stmts) {
-		AstNode *stmt = stmts.e[i];
+		AstNode *stmt = stmts[i];
 		if (check_has_break(stmt, implicit)) {
 			return true;
 		}
@@ -137,7 +137,7 @@ bool check_is_terminating(AstNode *node) {
 	case_ast_node(ms, MatchStmt, node);
 		bool has_default = false;
 		for_array(i, ms->body->BlockStmt.stmts) {
-			AstNode *clause = ms->body->BlockStmt.stmts.e[i];
+			AstNode *clause = ms->body->BlockStmt.stmts[i];
 			ast_node(cc, CaseClause, clause);
 			if (cc->list.count == 0) {
 				has_default = true;
@@ -153,7 +153,7 @@ bool check_is_terminating(AstNode *node) {
 	case_ast_node(ms, TypeMatchStmt, node);
 		bool has_default = false;
 		for_array(i, ms->body->BlockStmt.stmts) {
-			AstNode *clause = ms->body->BlockStmt.stmts.e[i];
+			AstNode *clause = ms->body->BlockStmt.stmts[i];
 			ast_node(cc, CaseClause, clause);
 			if (cc->list.count == 0) {
 				has_default = true;
@@ -187,7 +187,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 
 	// NOTE(bill): Ignore assignments to `_`
 	if (node->kind == AstNode_Ident &&
-	    str_eq(node->Ident.string, str_lit("_"))) {
+	    node->Ident.string == "_") {
 		add_entity_definition(&c->info, node, NULL);
 		check_assignment(c, rhs, NULL, str_lit("assignment to `_` identifier"));
 		if (rhs->mode == Addressing_Invalid) {
@@ -218,7 +218,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 			if (t == t_invalid) {
 				continue;
 			}
-			Operand x = {0};
+			Operand x = {};
 			x.mode = Addressing_Value;
 			x.type = t;
 			if (check_is_assignable_to(c, &x, lhs.type)) {
@@ -340,11 +340,11 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 	return rhs->type;
 }
 
-typedef enum MatchTypeKind {
+enum MatchTypeKind {
 	MatchType_Invalid,
 	MatchType_Union,
 	MatchType_Any,
-} MatchTypeKind;
+};
 
 MatchTypeKind check_valid_type_match_type(Type *type) {
 	type = type_deref(type);
@@ -384,15 +384,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 
 
 
-typedef struct TypeAndToken {
+struct TypeAndToken {
 	Type *type;
 	Token token;
-} TypeAndToken;
-
-#define MAP_TYPE TypeAndToken
-#define MAP_PROC map_type_and_token_
-#define MAP_NAME MapTypeAndToken
-#include "map.c"
+};
 
 void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
 	flags &= ~Stmt_CheckScopeDecls;
@@ -434,7 +429,7 @@ void check_label(Checker *c, AstNode *label) {
 		return;
 	}
 	String name = l->name->Ident.string;
-	if (str_eq(name, str_lit("_"))) {
+	if (name == "_") {
 		error_node(l->name, "A label's name cannot be a blank identifier");
 		return;
 	}
@@ -448,8 +443,8 @@ void check_label(Checker *c, AstNode *label) {
 
 	bool ok = true;
 	for_array(i, c->context.decl->labels) {
-		BlockLabel bl = c->context.decl->labels.e[i];
-		if (str_eq(bl.name, name)) {
+		BlockLabel bl = c->context.decl->labels[i];
+		if (bl.name == name) {
 			error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
 			ok = false;
 			break;
@@ -513,7 +508,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
 	case Entity_ImportName: {
 		Scope *scope = e->ImportName.scope;
 		for_array(i, scope->elements.entries) {
-			Entity *decl = scope->elements.entries.e[i].value;
+			Entity *decl = scope->elements.entries[i].value;
 			Entity *found = scope_insert_entity(c->context.scope, decl);
 			if (found != NULL) {
 				gbString expr_str = expr_to_string(expr);
@@ -535,11 +530,11 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
 		Type *t = base_type(type_deref(e->type));
 		if (is_type_struct(t) || is_type_raw_union(t) || is_type_union(t)) {
 			// TODO(bill): Make it work for unions too
-			Scope **found_ = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
+			Scope **found_ = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 			GB_ASSERT(found_ != NULL);
 			Scope *found = *found_;
 			for_array(i, found->elements.entries) {
-				Entity *f = found->elements.entries.e[i].value;
+				Entity *f = found->elements.entries[i].value;
 				if (f->kind == Entity_Variable) {
 					Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 					// if (is_selector) {
@@ -645,7 +640,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			return;
 		}
 
-		Operand x = {0};
+		Operand x = {};
 		check_expr(c, &x, s->expr);
 		if (x.mode == Addressing_Invalid) {
 			return;
@@ -693,23 +688,23 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 			// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
 			// an extra allocation
-			ArrayOperand operands = {0};
-			array_init_reserve(&operands, c->tmp_allocator, 2 * lhs_count);
+			Array<Operand> operands = {};
+			array_init(&operands, c->tmp_allocator, 2 * lhs_count);
 			check_unpack_arguments(c, lhs_count, &operands, as->rhs, true);
 
 			isize rhs_count = operands.count;
 			for_array(i, operands) {
-				if (operands.e[i].mode == Addressing_Invalid) {
+				if (operands[i].mode == Addressing_Invalid) {
 					rhs_count--;
 				}
 			}
 
 			isize max = gb_min(lhs_count, rhs_count);
 			for (isize i = 0; i < max; i++) {
-				check_assignment_variable(c, &operands.e[i], as->lhs.e[i]);
+				check_assignment_variable(c, &operands[i], as->lhs[i]);
 			}
 			if (lhs_count != rhs_count) {
-				error_node(as->lhs.e[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
+				error_node(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
 			}
 
 			gb_temp_arena_memory_end(tmp);
@@ -732,15 +727,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			be->op = op;
 			be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
 			 // NOTE(bill): Only use the first one will be used
-			be->left  = as->lhs.e[0];
-			be->right = as->rhs.e[0];
+			be->left  = as->lhs[0];
+			be->right = as->rhs[0];
 
 			check_binary_expr(c, &operand, &binary_expr);
 			if (operand.mode == Addressing_Invalid) {
 				return;
 			}
 			// NOTE(bill): Only use the first one will be used
-			check_assignment_variable(c, &operand, as->lhs.e[0]);
+			check_assignment_variable(c, &operand, as->lhs[0]);
 		} break;
 		}
 	case_end;
@@ -794,7 +789,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		}
 
 
-		Type *proc_type = c->proc_stack.e[c->proc_stack.count-1];
+		Type *proc_type = c->proc_stack[c->proc_stack.count-1];
 		isize result_count = 0;
 		if (proc_type->Proc.results) {
 			result_count = proc_type->Proc.results->Tuple.variable_count;
@@ -816,13 +811,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				check_init_variables(c, variables, result_count,
 				                     rs->results, str_lit("return statement"));
 				// if (pos.line == 10) {
-				// 	AstNode *x = rs->results.e[0];
+				// 	AstNode *x = rs->results[0];
 				// 	gb_printf_err("%s\n", expr_to_string(x));
 				// 	gb_printf_err("%s\n", type_to_string(type_of_expr(&c->info, x)));
 				// }
 			}
 		} else if (rs->results.count > 0) {
-			error_node(rs->results.e[0], "No return values expected");
+			error_node(rs->results[0], "No return values expected");
 		}
 	case_end;
 
@@ -863,7 +858,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 		Type *val = NULL;
 		Type *idx = NULL;
-		Entity *entities[2] = {0};
+		Entity *entities[2] = {};
 		isize entity_count = 0;
 
 		AstNode *expr = unparen_expr(rs->expr);
@@ -943,10 +938,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 
 			if (x.mode != Addressing_Constant) {
-				x.value = (ExactValue){0};
+				x.value = empty_exact_value;
 			}
 			if (y.mode != Addressing_Constant) {
-				y.value = (ExactValue){0};
+				y.value = empty_exact_value;
 			}
 
 
@@ -1032,7 +1027,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				String str = token.string;
 				Entity *found = NULL;
 
-				if (str_ne(str, str_lit("_"))) {
+				if (str != "_") {
 					found = current_scope_lookup_entity(c->context.scope, str);
 				}
 				if (found == NULL) {
@@ -1072,7 +1067,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 	case_end;
 
 	case_ast_node(ms, MatchStmt, node);
-		Operand x = {0};
+		Operand x = {};
 
 		mod_flags |= Stmt_BreakAllowed;
 		check_open_scope(c, node);
@@ -1089,7 +1084,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			x.type  = t_bool;
 			x.value = exact_value_bool(true);
 
-			Token token  = {0};
+			Token token  = {};
 			token.pos    = ast_node_token(ms->body).pos;
 			token.string = str_lit("true");
 			x.expr       = ast_ident(c->curr_ast_file, token);
@@ -1106,7 +1101,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		AstNode *first_default = NULL;
 		ast_node(bs, BlockStmt, ms->body);
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts.e[i];
+			AstNode *stmt = bs->stmts[i];
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
 				ast_node(cc, CaseClause, stmt);
@@ -1130,11 +1125,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 		}
 
-		MapTypeAndToken seen = {0}; // NOTE(bill): Multimap
-		map_type_and_token_init(&seen, heap_allocator());
+		Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
+		map_init(&seen, heap_allocator());
 
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts.e[i];
+			AstNode *stmt = bs->stmts[i];
 			if (stmt->kind != AstNode_CaseClause) {
 				// NOTE(bill): error handled by above multiple default checker
 				continue;
@@ -1142,12 +1137,12 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			ast_node(cc, CaseClause, stmt);
 
 			for_array(j, cc->list) {
-				AstNode *expr = unparen_expr(cc->list.e[j]);
+				AstNode *expr = unparen_expr(cc->list[j]);
 
 				if (is_ast_node_a_range(expr)) {
 					ast_node(ie, BinaryExpr, expr);
-					Operand lhs = {0};
-					Operand rhs = {0};
+					Operand lhs = {};
+					Operand rhs = {};
 					check_expr(c, &lhs, ie->left);
 					if (x.mode == Addressing_Invalid) {
 						continue;
@@ -1168,7 +1163,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					}
 
 
-					TokenKind op = {0};
+					TokenKind op = {};
 
 					Operand a = lhs;
 					Operand b = rhs;
@@ -1197,7 +1192,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					Operand b1 = rhs;
 					check_comparison(c, &a1, &b1, op);
 				} else {
-					Operand y = {0};
+					Operand y = {};
 					check_expr(c, &y, expr);
 					if (x.mode == Addressing_Invalid ||
 					    y.mode == Addressing_Invalid) {
@@ -1222,13 +1217,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 					if (y.value.kind != ExactValue_Invalid) {
 						HashKey key = hash_exact_value(y.value);
-						TypeAndToken *found = map_type_and_token_get(&seen, key);
+						TypeAndToken *found = map_get(&seen, key);
 						if (found != NULL) {
 							gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-							isize count = map_type_and_token_multi_count(&seen, key);
+							isize count = multi_map_count(&seen, key);
 							TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
 
-							map_type_and_token_multi_get_all(&seen, key, taps);
+							multi_map_get_all(&seen, key, taps);
 							bool continue_outer = false;
 
 							for (isize i = 0; i < count; i++) {
@@ -1254,7 +1249,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 							}
 						}
 						TypeAndToken tap = {y.type, ast_node_token(y.expr)};
-						map_type_and_token_multi_insert(&seen, key, tap);
+						multi_map_insert(&seen, key, tap);
 					}
 				}
 			}
@@ -1268,13 +1263,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			check_close_scope(c);
 		}
 
-		map_type_and_token_destroy(&seen);
+		map_destroy(&seen);
 
 		check_close_scope(c);
 	case_end;
 
 	case_ast_node(ms, TypeMatchStmt, node);
-		Operand x = {0};
+		Operand x = {};
 
 		mod_flags |= Stmt_BreakAllowed;
 		check_open_scope(c, node);
@@ -1297,8 +1292,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			syntax_error(as_token, "Expected 1 expression after `in`");
 			break;
 		}
-		AstNode *lhs = as->lhs.e[0];
-		AstNode *rhs = as->rhs.e[0];
+		AstNode *lhs = as->lhs[0];
+		AstNode *rhs = as->rhs[0];
 
 		check_expr(c, &x, rhs);
 		check_assignment(c, &x, NULL, str_lit("type match expression"));
@@ -1316,7 +1311,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		AstNode *first_default = NULL;
 		ast_node(bs, BlockStmt, ms->body);
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts.e[i];
+			AstNode *stmt = bs->stmts[i];
 			AstNode *default_stmt = NULL;
 			if (stmt->kind == AstNode_CaseClause) {
 				ast_node(cc, CaseClause, stmt);
@@ -1346,11 +1341,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 		}
 
 
-		MapBool seen = {0}; // Multimap
-		map_bool_init(&seen, heap_allocator());
+		Map<bool> seen = {}; // Multimap
+		map_init(&seen, heap_allocator());
 
 		for_array(i, bs->stmts) {
-			AstNode *stmt = bs->stmts.e[i];
+			AstNode *stmt = bs->stmts[i];
 			if (stmt->kind != AstNode_CaseClause) {
 				// NOTE(bill): error handled by above multiple default checker
 				continue;
@@ -1362,9 +1357,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 			Type *case_type = NULL;
 			for_array(type_index, cc->list) {
-				AstNode *type_expr = cc->list.e[type_index];
+				AstNode *type_expr = cc->list[type_index];
 				if (type_expr != NULL) { // Otherwise it's a default expression
-					Operand y = {0};
+					Operand y = {};
 					check_expr_or_type(c, &y, type_expr);
 
 					if (match_type_kind == MatchType_Union) {
@@ -1391,7 +1386,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					}
 
 					HashKey key = hash_pointer(y.type);
-					bool *found = map_bool_get(&seen, key);
+					bool *found = map_get(&seen, key);
 					if (found) {
 						TokenPos pos = cc->token.pos;
 						gbString expr_str = expr_to_string(y.expr);
@@ -1403,7 +1398,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 						gb_string_free(expr_str);
 						break;
 					}
-					map_bool_set(&seen, key, cast(bool)true);
+					map_set(&seen, key, cast(bool)true);
 				}
 			}
 
@@ -1434,7 +1429,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			check_stmt_list(c, cc->stmts, mod_flags);
 			check_close_scope(c);
 		}
-		map_bool_destroy(&seen);
+		map_destroy(&seen);
 
 		check_close_scope(c);
 	case_end;
@@ -1481,7 +1476,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 			AstNode *ident = bs->label;
 			String name = ident->Ident.string;
-			Operand o = {0};
+			Operand o = {};
 			Entity *e = check_ident(c, &o, ident, NULL, NULL, false);
 			if (e == NULL) {
 				error_node(ident, "Undeclared label name: %.*s", LIT(name));
@@ -1502,15 +1497,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			return;
 		}
 		for_array(i, us->list) {
-			AstNode *expr = unparen_expr(us->list.e[0]);
+			AstNode *expr = unparen_expr(us->list[0]);
 			Entity *e = NULL;
 
 			bool is_selector = false;
 			if (expr->kind == AstNode_Ident) {
-				Operand o = {0};
+				Operand o = {};
 				e = check_ident(c, &o, expr, NULL, NULL, true);
 			} else if (expr->kind == AstNode_SelectorExpr) {
-				Operand o = {0};
+				Operand o = {};
 				e = check_selector(c, &o, expr, NULL);
 				is_selector = true;
 			} else if (expr->kind == AstNode_Implicit) {
@@ -1526,7 +1521,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 	case_ast_node(pa, PushAllocator, node);
-		Operand op = {0};
+		Operand op = {};
 		check_expr(c, &op, pa->expr);
 		check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
 		check_stmt(c, pa->body, mod_flags);
@@ -1534,7 +1529,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 
 	case_ast_node(pa, PushContext, node);
-		Operand op = {0};
+		Operand op = {};
 		check_expr(c, &op, pa->expr);
 		check_assignment(c, &op, t_context, str_lit("argument to push_context"));
 		check_stmt(c, pa->body, mod_flags);
@@ -1555,7 +1550,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 
 			for_array(i, vd->names) {
-				AstNode *name = vd->names.e[i];
+				AstNode *name = vd->names[i];
 				Entity *entity = NULL;
 				if (name->kind != AstNode_Ident) {
 					error_node(name, "A variable declaration must be an identifier");
@@ -1564,11 +1559,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					String str = token.string;
 					Entity *found = NULL;
 					// NOTE(bill): Ignore assignments to `_`
-					if (str_ne(str, str_lit("_"))) {
+					if (str != "_") {
 						found = current_scope_lookup_entity(c->context.scope, str);
 					}
 					if (found == NULL) {
-						entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, vd->flags&VarDeclFlag_immutable);
+						entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, (vd->flags&VarDeclFlag_immutable) != 0);
 						entity->identifier = name;
 					} else {
 						TokenPos pos = found->token.pos;
@@ -1588,7 +1583,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 
 			Type *init_type = NULL;
 			if (vd->type) {
-				init_type = check_type_extra(c, vd->type, NULL);
+				init_type = check_type(c, vd->type, NULL);
 				if (init_type == NULL) {
 					init_type = t_invalid;
 				}
@@ -1635,10 +1630,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					Type *t = base_type(type_deref(e->type));
 
 					if (is_type_struct(t) || is_type_raw_union(t)) {
-						Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
+						Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
 						GB_ASSERT(found != NULL);
 						for_array(i, (*found)->elements.entries) {
-							Entity *f = (*found)->elements.entries.e[i].value;
+							Entity *f = (*found)->elements.entries[i].value;
 							if (f->kind == Entity_Variable) {
 								Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
 								uvar->Variable.is_immutable = is_immutable;

File diff suppressed because it is too large
+ 177 - 210
src/checker.cpp


+ 12 - 32
src/common.c → src/common.cpp

@@ -3,7 +3,7 @@
 #include <xmmintrin.h>
 #endif
 
-#define GB_NO_DEFER
+// #define GB_NO_DEFER
 #define GB_IMPLEMENTATION
 #include "gb/gb.h"
 
@@ -13,22 +13,27 @@ gbAllocator heap_allocator(void) {
 	return gb_heap_allocator();
 }
 
-#include "unicode.c"
-#include "string.c"
-#include "array.c"
-#include "integer128.c"
-#include "murmurhash3.c"
+#include "unicode.cpp"
+#include "string.cpp"
+#include "array.cpp"
+#include "integer128.cpp"
+#include "murmurhash3.cpp"
 
 u128 fnv128a(void const *data, isize len) {
 	u128 o = u128_lo_hi(0x13bull, 0x1000000ull);
 	u128 h = u128_lo_hi(0x62b821756295c58dull, 0x6c62272e07bb0142ull);
 	u8 const *bytes = cast(u8 const *)data;
 	for (isize i = 0; i < len; i++) {
-		h = u128_mul(u128_xor(h, u128_from_u64(bytes[i])), o);
+		h.lo ^= bytes[i];
+		h = h * o;
 	}
 	return h;
 }
 
+#include "map.cpp"
+
+
+
 gb_global String global_module_path = {0};
 gb_global bool global_module_path_set = false;
 
@@ -43,8 +48,6 @@ gbAllocator scratch_allocator(void) {
 	return gb_scratch_allocator(&scratch_memory);
 }
 
-typedef struct DynamicArenaBlock DynamicArenaBlock;
-typedef struct DynamicArena      DynamicArena;
 
 struct DynamicArenaBlock {
 	DynamicArenaBlock *prev;
@@ -236,27 +239,4 @@ f64 gb_sqrt(f64 x) {
 	} \
 } while (0)
 
-////////////////////////////////////////////////////////////////
-//
-// Generic Data Structures
-//
-////////////////////////////////////////////////////////////////
-
-typedef Array(i32)   Array_i32;
-typedef Array(isize) Array_isize;
-
-
-#define MAP_TYPE String
-#define MAP_PROC map_string_
-#define MAP_NAME MapString
-#include "map.c"
-
-#define MAP_TYPE bool
-#define MAP_PROC map_bool_
-#define MAP_NAME MapBool
-#include "map.c"
 
-#define MAP_TYPE isize
-#define MAP_PROC map_isize_
-#define MAP_NAME MapIsize
-#include "map.c"

+ 18 - 18
src/entity.c → src/entity.cpp

@@ -1,7 +1,7 @@
-typedef struct Scope    Scope;
-typedef struct Checker  Checker;
-typedef struct Type     Type;
-typedef struct DeclInfo DeclInfo;
+struct Scope;
+struct Checker;
+struct Type;
+struct DeclInfo;
 // typedef enum BuiltinProcId BuiltinProcId;
 
 
@@ -19,12 +19,12 @@ typedef struct DeclInfo DeclInfo;
 	ENTITY_KIND(Nil) \
 	ENTITY_KIND(Label)
 
-typedef enum EntityKind {
+enum EntityKind {
 #define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
 	ENTITY_KINDS
 #undef ENTITY_KIND
 	Entity_Count,
-} EntityKind;
+};
 
 String const entity_strings[] = {
 #define ENTITY_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1},
@@ -32,7 +32,7 @@ String const entity_strings[] = {
 #undef ENTITY_KIND
 };
 
-typedef enum EntityFlag {
+enum EntityFlag {
 	EntityFlag_Visited       = 1<<0,
 	EntityFlag_Used          = 1<<1,
 	EntityFlag_Using         = 1<<2,
@@ -45,24 +45,23 @@ typedef enum EntityFlag {
 	EntityFlag_Value         = 1<<9,
 	EntityFlag_Sret          = 1<<10,
 	EntityFlag_BitFieldValue = 1<<11,
-} EntityFlag;
+};
 
 // Zero value means the overloading process is not yet done
-typedef enum OverloadKind {
+enum OverloadKind {
 	Overload_Unknown,
 	Overload_No,
 	Overload_Yes,
-} OverloadKind;
+};
 
-typedef	enum EntityAliasKind {
+enum EntityAliasKind {
 	EntityAlias_Invalid,
 	EntityAlias_Type,
 	EntityAlias_Entity,
-} EntityAliasKind;
+};
 
 
 // An Entity is a named "thing" in the language
-typedef struct Entity Entity;
 struct Entity {
 	EntityKind kind;
 	u64        id;
@@ -82,10 +81,11 @@ struct Entity {
 			ExactValue value;
 		} Constant;
 		struct {
-			i32  field_index;
-			i32  field_src_index;
-			bool is_immutable;
-			bool is_thread_local;
+			i32        field_index;
+			i32        field_src_index;
+			bool       is_immutable;
+			bool       is_thread_local;
+			ExactValue default_value;
 		} Variable;
 		struct {
 			bool is_type_alias;
@@ -148,7 +148,7 @@ bool is_entity_exported(Entity *e) {
 	if (name.len == 0) {
 		return false;
 	}
-	return name.text[0] != '_';
+	return name[0] != '_';
 }
 
 gb_global u64 global_entity_id = 0;

+ 40 - 38
src/exact_value.c → src/exact_value.cpp

@@ -3,13 +3,14 @@
 // TODO(bill): Big numbers
 // IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!!
 
-typedef struct AstNode AstNode;
+struct AstNode;
+struct HashKey;
 
-typedef struct Complex128 {
+struct Complex128 {
 	f64 real, imag;
-} Complex128;
+};
 
-typedef enum ExactValueKind {
+enum ExactValueKind {
 	ExactValue_Invalid,
 
 	ExactValue_Bool,
@@ -21,9 +22,9 @@ typedef enum ExactValueKind {
 	ExactValue_Compound, // TODO(bill): Is this good enough?
 
 	ExactValue_Count,
-} ExactValueKind;
+};
 
-typedef struct ExactValue {
+struct ExactValue {
 	ExactValueKind kind;
 	union {
 		bool          value_bool;
@@ -34,7 +35,9 @@ typedef struct ExactValue {
 		Complex128    value_complex;
 		AstNode *     value_compound;
 	};
-} ExactValue;
+};
+
+gb_global ExactValue const empty_exact_value = {};
 
 HashKey hash_exact_value(ExactValue v) {
 	return hashing_proc(&v, gb_size_of(ExactValue));
@@ -191,7 +194,7 @@ ExactValue exact_value_from_basic_literal(Token token) {
 	case Token_Float:   return exact_value_float_from_string(token.string);
 	case Token_Imag: {
 		String str = token.string;
-		Rune last_rune = cast(Rune)str.text[str.len-1];
+		Rune last_rune = cast(Rune)str[str.len-1];
 		str.len--; // Ignore the `i|j|k`
 		f64 imag = float_from_string(str);
 
@@ -314,7 +317,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 			return v;
 		case ExactValue_Integer: {
 			ExactValue i = v;
-			i.value_integer = i128_neg(i.value_integer);
+			i.value_integer = -i.value_integer;
 			return i;
 		}
 		case ExactValue_Float: {
@@ -336,7 +339,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 		case ExactValue_Invalid:
 			return v;
 		case ExactValue_Integer:
-			i = i128_not(v.value_integer);
+			i = ~v.value_integer;
 			break;
 		default:
 			goto failure;
@@ -346,7 +349,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 		// limited to the types precision
 		// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
 		if (0 < precision && precision < 128) {
-			i = i128_and(i, i128_not(i128_shl(I128_NEG_ONE, precision)));
+			i = i & ~(I128_NEG_ONE << precision);
 		}
 
 		return exact_value_i128(i);
@@ -364,7 +367,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 failure:
 	GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
 
-	ExactValue error_value = {0};
+	ExactValue error_value = {};
 	return error_value;
 }
 
@@ -458,19 +461,19 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
 		i128 b = y.value_integer;
 		i128 c = I128_ZERO;
 		switch (op) {
-		case Token_Add:    c = i128_add(a, b);                           break;
-		case Token_Sub:    c = i128_sub(a, b);                           break;
-		case Token_Mul:    c = i128_mul(a, b);                           break;
+		case Token_Add:    c = a + b;               break;
+		case Token_Sub:    c = a - b;               break;
+		case Token_Mul:    c = a * b;               break;
 		case Token_Quo:    return exact_value_float(fmod(i128_to_f64(a), i128_to_f64(b)));
-		case Token_QuoEq:  c = i128_quo(a, b);                           break; // NOTE(bill): Integer division
-		case Token_Mod:    c = i128_mod(a, b);                           break;
-		case Token_ModMod: c = i128_mod(i128_add(i128_mod(a, b), b), b); break;
-		case Token_And:    c = i128_and    (a, b);                       break;
-		case Token_Or:     c = i128_or     (a, b);                       break;
-		case Token_Xor:    c = i128_xor    (a, b);                       break;
-		case Token_AndNot: c = i128_and_not(a, b);                       break;
-		case Token_Shl:    c = i128_shl    (a, i128_to_u64(b));          break;
-		case Token_Shr:    c = i128_shr    (a, i128_to_u64(b));          break;
+		case Token_QuoEq:  c = a / b;               break; // NOTE(bill): Integer division
+		case Token_Mod:    c = a % b;               break;
+		case Token_ModMod: c = ((a % b) + b) % b;   break;
+		case Token_And:    c = a & b;               break;
+		case Token_Or:     c = a | b;               break;
+		case Token_Xor:    c = a ^ b;               break;
+		case Token_AndNot: c = i128_and_not(a, b);  break;
+		case Token_Shl:    c = a << i128_to_u64(b); break;
+		case Token_Shr:    c = a >> i128_to_u64(b); break;
 		default: goto error;
 		}
 
@@ -523,7 +526,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
 
 error:
 	;		// MSVC accepts this??? apparently you cannot declare variables immediately after labels...
-	ExactValue error_value = {0};
+	ExactValue error_value = {};
 	// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
 	return error_value;
 }
@@ -557,12 +560,12 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
 		i128 a = x.value_integer;
 		i128 b = y.value_integer;
 		switch (op) {
-		case Token_CmpEq: return i128_eq(a, b);
-		case Token_NotEq: return i128_ne(a, b);
-		case Token_Lt:    return i128_lt(a, b);
-		case Token_LtEq:  return i128_le(a, b);
-		case Token_Gt:    return i128_gt(a, b);
-		case Token_GtEq:  return i128_ge(a, b);
+		case Token_CmpEq: return a == b;
+		case Token_NotEq: return a != b;
+		case Token_Lt:    return a <  b;
+		case Token_LtEq:  return a <= b;
+		case Token_Gt:    return a >  b;
+		case Token_GtEq:  return a >= b;
 		}
 	} break;
 
@@ -593,15 +596,14 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
 	case ExactValue_String: {
 		String a = x.value_string;
 		String b = y.value_string;
-		isize len = gb_min(a.len, b.len);
 		// TODO(bill): gb_memcompare is used because the strings are UTF-8
 		switch (op) {
-		case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
-		case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
-		case Token_Lt:    return gb_memcompare(a.text, b.text, len) <  0;
-		case Token_LtEq:  return gb_memcompare(a.text, b.text, len) <= 0;
-		case Token_Gt:    return gb_memcompare(a.text, b.text, len) >  0;
-		case Token_GtEq:  return gb_memcompare(a.text, b.text, len) >= 0;
+		case Token_CmpEq: return a == b;
+		case Token_NotEq: return a != b;
+		case Token_Lt:    return a <  b;
+		case Token_LtEq:  return a <= b;
+		case Token_Gt:    return a >  b;
+		case Token_GtEq:  return a >= b;
 		}
 	} break;
 	}

+ 111 - 14
src/integer128.c → src/integer128.cpp

@@ -1,16 +1,25 @@
-typedef struct u128 {u64 lo; u64 hi;} u128;
-typedef struct i128 {u64 lo; i64 hi;} i128;
 
-#define BIT128_U64_HIGHBIT 0x8000000000000000ul
-#define BIT128_U64_BITS62  0x7ffffffffffffffful
-#define BIT128_U64_ALLBITS 0xfffffffffffffffful
+#if defined(GB_COMPILER_MSVC) && defined(GB_ARCH_64_BIT) && defined(GB_CPU_X86)
+	#define MSVC_AMD64_INTRINSICS
+	#include <intrin.h>
+	#pragma intrinsic(_mul128)
+#endif
+
+#define BIT128_U64_HIGHBIT 0x8000000000000000ull
+#define BIT128_U64_BITS62  0x7fffffffffffffffull
+#define BIT128_U64_ALLBITS 0xffffffffffffffffull
+
+
+typedef struct u128 { u64 lo; u64 hi; } u128;
+typedef struct i128 { u64 lo; i64 hi; } i128;
+
 
 static u128 const U128_ZERO = {0, 0};
 static u128 const U128_ONE  = {1, 0};
 static i128 const I128_ZERO = {0, 0};
 static i128 const I128_ONE  = {1, 0};
 static u128 const U128_NEG_ONE = {BIT128_U64_ALLBITS, BIT128_U64_ALLBITS};
-static i128 const I128_NEG_ONE = {BIT128_U64_ALLBITS, BIT128_U64_ALLBITS};
+static i128 const I128_NEG_ONE = {BIT128_U64_ALLBITS, cast(i64)BIT128_U64_ALLBITS};
 
 u128 u128_lo_hi      (u64 lo, u64 hi);
 u128 u128_from_u32   (u32 u);
@@ -84,6 +93,48 @@ void i128_divide (i128 num, i128 den, i128 *quo, i128 *rem);
 i128 i128_quo    (i128 a, i128 b);
 i128 i128_mod    (i128 a, i128 b);
 
+bool operator==(u128 a, u128 b) { return u128_eq(a, b); }
+bool operator!=(u128 a, u128 b) { return u128_ne(a, b); }
+bool operator< (u128 a, u128 b) { return u128_lt(a, b); }
+bool operator> (u128 a, u128 b) { return u128_gt(a, b); }
+bool operator<=(u128 a, u128 b) { return u128_le(a, b); }
+bool operator>=(u128 a, u128 b) { return u128_ge(a, b); }
+
+u128 operator+(u128 a, u128 b) { return u128_add(a, b); }
+u128 operator-(u128 a, u128 b) { return u128_sub(a, b); }
+u128 operator*(u128 a, u128 b) { return u128_mul(a, b); }
+u128 operator/(u128 a, u128 b) { return u128_quo(a, b); }
+u128 operator%(u128 a, u128 b) { return u128_mod(a, b); }
+u128 operator&(u128 a, u128 b) { return u128_and(a, b); }
+u128 operator|(u128 a, u128 b) { return u128_or (a, b); }
+u128 operator^(u128 a, u128 b) { return u128_xor(a, b); }
+u128 operator~(u128 a)         { return u128_not(a); }
+u128 operator+(u128 a)         { return a; }
+u128 operator-(u128 a)         { return u128_neg(a); }
+u128 operator<<(u128 a, u32 b) { return u128_shl(a, b); }
+u128 operator>>(u128 a, u32 b) { return u128_shr(a, b); }
+
+
+bool operator==(i128 a, i128 b) { return i128_eq(a, b); }
+bool operator!=(i128 a, i128 b) { return i128_ne(a, b); }
+bool operator< (i128 a, i128 b) { return i128_lt(a, b); }
+bool operator> (i128 a, i128 b) { return i128_gt(a, b); }
+bool operator<=(i128 a, i128 b) { return i128_le(a, b); }
+bool operator>=(i128 a, i128 b) { return i128_ge(a, b); }
+
+i128 operator+(i128 a, i128 b) { return i128_add(a, b); }
+i128 operator-(i128 a, i128 b) { return i128_sub(a, b); }
+i128 operator*(i128 a, i128 b) { return i128_mul(a, b); }
+i128 operator/(i128 a, i128 b) { return i128_quo(a, b); }
+i128 operator%(i128 a, i128 b) { return i128_mod(a, b); }
+i128 operator&(i128 a, i128 b) { return i128_and(a, b); }
+i128 operator|(i128 a, i128 b) { return i128_or (a, b); }
+i128 operator^(i128 a, i128 b) { return i128_xor(a, b); }
+i128 operator~(i128 a)         { return i128_not(a); }
+i128 operator+(i128 a)         { return a; }
+i128 operator-(i128 a)         { return i128_neg(a); }
+i128 operator<<(i128 a, u32 b) { return i128_shl(a, b); }
+i128 operator>>(i128 a, u32 b) { return i128_shr(a, b); }
 
 ////////////////////////////////////////////////////////////////
 
@@ -99,7 +150,7 @@ u64 bit128__digit_value(Rune r) {
 	return 16; // NOTE(bill): Larger than highest possible
 }
 
-u128 u128_lo_hi(u64 lo, u64 hi) { return (u128){lo, hi}; }
+u128 u128_lo_hi(u64 lo, u64 hi) { return u128{lo, hi}; }
 u128 u128_from_u32(u32 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_u64(u64 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_i64(i64 u)       { return u128_lo_hi(cast(u64)u, u < 0 ? -1 : 0); }
@@ -109,8 +160,8 @@ u128 u128_from_string(String string) {
 	// TODO(bill): Allow for numbers with underscores in them
 	u64 base = 10;
 	bool has_prefix = false;
-	if (string.len > 2 && string.text[0] == '0') {
-		switch (string.text[1]) {
+	if (string.len > 2 && string[0] == '0') {
+		switch (string[1]) {
 		case 'b': base = 2;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;
@@ -160,8 +211,8 @@ i128 i128_from_string(String string) {
 	// TODO(bill): Allow for numbers with underscores in them
 	u64 base = 10;
 	bool has_prefix = false;
-	if (string.len > 2 && string.text[0] == '0') {
-		switch (string.text[1]) {
+	if (string.len > 2 && string[0] == '0') {
+		switch (string[1]) {
 		case 'b': base = 2;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;
@@ -332,7 +383,11 @@ u128 u128_shl(u128 a, u32 n) {
 	if (n >= 128) {
 		return u128_lo_hi(0, 0);
 	}
-
+#if 0 && defined(MSVC_AMD64_INTRINSICS)
+	a.hi = __shiftleft128(a.lo, a.hi, n);
+	a.lo = a.lo << n;
+	return a;
+#else
 	if (n >= 64) {
 		n -= 64;
 		a.hi = a.lo;
@@ -347,13 +402,18 @@ u128 u128_shl(u128 a, u32 n) {
 		a.lo <<= n;
 	}
 	return a;
+#endif
 }
 
 u128 u128_shr(u128 a, u32 n) {
 	if (n >= 128) {
 		return u128_lo_hi(0, 0);
 	}
-
+#if 0 && defined(MSVC_AMD64_INTRINSICS)
+	a.lo = __shiftright128(a.lo, a.hi, n);
+	a.hi = a.hi >> n;
+	return a;
+#else
 	if (n >= 64) {
 		n -= 64;
 		a.lo = a.hi;
@@ -367,6 +427,7 @@ u128 u128_shr(u128 a, u32 n) {
 		a.hi >>= n;
 	}
 	return a;
+#endif
 }
 
 
@@ -383,6 +444,14 @@ u128 u128_mul(u128 a, u128 b) {
 		return a;
 	}
 
+
+#if defined(MSVC_AMD64_INTRINSICS)
+	if (a.hi == 0 && b.hi == 0) {
+		a.lo = _umul128(a.lo, b.lo, &a.hi);
+		return a;
+	}
+#endif
+
 	u128 res = {0};
 	u128 t = b;
 	for (u32 i = 0; i < 128; i++) {
@@ -396,6 +465,8 @@ u128 u128_mul(u128 a, u128 b) {
 	return res;
 }
 
+bool u128_hibit(u128 *d) { return (d->hi & BIT128_U64_HIGHBIT) != 0; }
+
 void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
 	if (u128_eq(den, U128_ZERO)) {
 		if (quo) *quo = u128_from_u64(num.lo/den.lo);
@@ -406,7 +477,7 @@ void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
 		u128 x = U128_ONE;
 		u128 r = U128_ZERO;
 
-		while (u128_ge(n, d) && ((u128_shr(d, 128-1).lo&1) == 0)) {
+		while (u128_ge(n, d) && !u128_hibit(&d)) {
 			x = u128_shl(x, 1);
 			d = u128_shl(d, 1);
 		}
@@ -427,11 +498,18 @@ void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
 }
 
 u128 u128_quo(u128 a, u128 b) {
+	if (a.hi == 0 && b.hi == 0) {
+		return u128_from_u64(a.lo/b.lo);
+	}
+
 	u128 res = {0};
 	u128_divide(a, b, &res, NULL);
 	return res;
 }
 u128 u128_mod(u128 a, u128 b) {
+	if (a.hi == 0 && b.hi == 0) {
+		return u128_from_u64(a.lo%b.lo);
+	}
 	u128 res = {0};
 	u128_divide(a, b, NULL, &res);
 	return res;
@@ -491,6 +569,11 @@ i128 i128_shl(i128 a, u32 n) {
 		return i128_lo_hi(0, 0);
 	}
 
+#if 0 && defined(MSVC_AMD64_INTRINSICS)
+	a.hi = __shiftleft128(a.lo, a.hi, n);
+	a.lo = a.lo << n;
+	return a;
+#else
 	if (n >= 64) {
 		n -= 64;
 		a.hi = a.lo;
@@ -505,6 +588,7 @@ i128 i128_shl(i128 a, u32 n) {
 		a.lo <<= n;
 	}
 	return a;
+#endif
 }
 
 i128 i128_shr(i128 a, u32 n) {
@@ -512,6 +596,11 @@ i128 i128_shr(i128 a, u32 n) {
 		return i128_lo_hi(0, 0);
 	}
 
+#if 0 && defined(MSVC_AMD64_INTRINSICS)
+	a.lo = __shiftright128(a.lo, a.hi, n);
+	a.hi = a.hi >> n;
+	return a;
+#else
 	if (n >= 64) {
 		n -= 64;
 		a.lo = a.hi;
@@ -525,6 +614,7 @@ i128 i128_shr(i128 a, u32 n) {
 		a.hi >>= n;
 	}
 	return a;
+#endif
 }
 
 
@@ -541,6 +631,13 @@ i128 i128_mul(i128 a, i128 b) {
 		return a;
 	}
 
+#if defined(MSVC_AMD64_INTRINSICS)
+	if (a.hi == 0 && b.hi == 0) {
+		a.lo = _mul128(a.lo, b.lo, &a.hi);
+		return a;
+	}
+#endif
+
 	i128 res = {0};
 	i128 t = b;
 	for (u32 i = 0; i < 128; i++) {

File diff suppressed because it is too large
+ 156 - 169
src/ir.cpp


+ 43 - 43
src/ir_opt.c → src/ir_opt.cpp

@@ -1,6 +1,6 @@
 // Optimizations for the IR code
 
-void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
+void ir_opt_add_operands(Array<irValue *> *ops, irInstr *i) {
 	switch (i->kind) {
 	case irInstr_Comment:
 		break;
@@ -48,7 +48,7 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
 		break;
 	case irInstr_Phi:
 		for_array(j, i->Phi.edges) {
-			array_add(ops, i->Phi.edges.e[j]);
+			array_add(ops, i->Phi.edges[j]);
 		}
 		break;
 	case irInstr_Unreachable:
@@ -97,24 +97,24 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
 
 void ir_opt_block_replace_pred(irBlock *b, irBlock *from, irBlock *to) {
 	for_array(i, b->preds) {
-		irBlock *pred = b->preds.e[i];
+		irBlock *pred = b->preds[i];
 		if (pred == from) {
-			b->preds.e[i] = to;
+			b->preds[i] = to;
 		}
 	}
 }
 
 void ir_opt_block_replace_succ(irBlock *b, irBlock *from, irBlock *to) {
 	for_array(i, b->succs) {
-		irBlock *succ = b->succs.e[i];
+		irBlock *succ = b->succs[i];
 		if (succ == from) {
-			b->succs.e[i] = to;
+			b->succs[i] = to;
 		}
 	}
 }
 
 bool ir_opt_block_has_phi(irBlock *b) {
-	return b->instrs.e[0]->Instr.kind == irInstr_Phi;
+	return b->instrs[0]->Instr.kind == irInstr_Phi;
 }
 
 
@@ -126,10 +126,10 @@ bool ir_opt_block_has_phi(irBlock *b) {
 
 
 
-irValueArray ir_get_block_phi_nodes(irBlock *b) {
-	irValueArray phis = {0};
+Array<irValue *> ir_get_block_phi_nodes(irBlock *b) {
+	Array<irValue *> phis = {0};
 	for_array(i, b->instrs) {
-		irInstr *instr = &b->instrs.e[i]->Instr;
+		irInstr *instr = &b->instrs[i]->Instr;
 		if (instr->kind != irInstr_Phi) {
 			phis = b->instrs;
 			phis.count = i;
@@ -140,22 +140,22 @@ irValueArray ir_get_block_phi_nodes(irBlock *b) {
 }
 
 void ir_remove_pred(irBlock *b, irBlock *p) {
-	irValueArray phis = ir_get_block_phi_nodes(b);
+	Array<irValue *> phis = ir_get_block_phi_nodes(b);
 	isize i = 0;
 	for_array(j, b->preds) {
-		irBlock *pred = b->preds.e[j];
+		irBlock *pred = b->preds[j];
 		if (pred != p) {
-			b->preds.e[i] = b->preds.e[j];
+			b->preds[i] = b->preds[j];
 			for_array(k, phis) {
-				irInstrPhi *phi = &phis.e[k]->Instr.Phi;
-				phi->edges.e[i] = phi->edges.e[j];
+				irInstrPhi *phi = &phis[k]->Instr.Phi;
+				phi->edges[i] = phi->edges[j];
 			}
 			i++;
 		}
 	}
 	b->preds.count = i;
 	for_array(k, phis) {
-		irInstrPhi *phi = &phis.e[k]->Instr.Phi;
+		irInstrPhi *phi = &phis[k]->Instr.Phi;
 		phi->edges.count = i;
 	}
 
@@ -164,13 +164,13 @@ void ir_remove_pred(irBlock *b, irBlock *p) {
 void ir_remove_dead_blocks(irProcedure *proc) {
 	isize j = 0;
 	for_array(i, proc->blocks) {
-		irBlock *b = proc->blocks.e[i];
+		irBlock *b = proc->blocks[i];
 		if (b == NULL) {
 			continue;
 		}
 		// NOTE(bill): Swap order
 		b->index = j;
-		proc->blocks.e[j++] = b;
+		proc->blocks[j++] = b;
 	}
 	proc->blocks.count = j;
 }
@@ -180,7 +180,7 @@ void ir_mark_reachable(irBlock *b) {
 	isize const BLACK = -1;
 	b->index = BLACK;
 	for_array(i, b->succs) {
-		irBlock *succ = b->succs.e[i];
+		irBlock *succ = b->succs[i];
 		if (succ->index == WHITE) {
 			ir_mark_reachable(succ);
 		}
@@ -191,23 +191,23 @@ void ir_remove_unreachable_blocks(irProcedure *proc) {
 	isize const WHITE =  0;
 	isize const BLACK = -1;
 	for_array(i, proc->blocks) {
-		proc->blocks.e[i]->index = WHITE;
+		proc->blocks[i]->index = WHITE;
 	}
 
-	ir_mark_reachable(proc->blocks.e[0]);
+	ir_mark_reachable(proc->blocks[0]);
 
 	for_array(i, proc->blocks) {
-		irBlock *b = proc->blocks.e[i];
+		irBlock *b = proc->blocks[i];
 		if (b->index == WHITE) {
 			for_array(j, b->succs) {
-				irBlock *c = b->succs.e[j];
+				irBlock *c = b->succs[j];
 				if (c->index == BLACK) {
 					ir_remove_pred(c, b);
 				}
 			}
 			// NOTE(bill): Mark as empty but don't actually free it
 			// As it's been allocated with an arena
-			proc->blocks.e[i] = NULL;
+			proc->blocks[i] = NULL;
 		}
 	}
 	ir_remove_dead_blocks(proc);
@@ -217,7 +217,7 @@ bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
 	if (a->succs.count != 1) {
 		return false;
 	}
-	irBlock *b = a->succs.e[0];
+	irBlock *b = a->succs[0];
 	if (b->preds.count != 1) {
 		return false;
 	}
@@ -228,21 +228,21 @@ bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
 
 	array_pop(&a->instrs); // Remove branch at end
 	for_array(i, b->instrs) {
-		array_add(&a->instrs, b->instrs.e[i]);
-		ir_set_instr_parent(b->instrs.e[i], a);
+		array_add(&a->instrs, b->instrs[i]);
+		ir_set_instr_parent(b->instrs[i], a);
 	}
 
 	array_clear(&a->succs);
 	for_array(i, b->succs) {
-		array_add(&a->succs, b->succs.e[i]);
+		array_add(&a->succs, b->succs[i]);
 	}
 
 	// Fix preds links
 	for_array(i, b->succs) {
-		ir_opt_block_replace_pred(b->succs.e[i], b, a);
+		ir_opt_block_replace_pred(b->succs[i], b, a);
 	}
 
-	proc->blocks.e[b->index] = NULL;
+	proc->blocks[b->index] = NULL;
 	return true;
 }
 
@@ -254,7 +254,7 @@ void ir_opt_blocks(irProcedure *proc) {
 	while (changed) {
 		changed = false;
 		for_array(i, proc->blocks) {
-			irBlock *b = proc->blocks.e[i];
+			irBlock *b = proc->blocks[i];
 			if (b == NULL) {
 				continue;
 			}
@@ -273,20 +273,20 @@ void ir_opt_blocks(irProcedure *proc) {
 void ir_opt_build_referrers(irProcedure *proc) {
 	gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 
-	irValueArray ops = {0}; // NOTE(bill): Act as a buffer
-	array_init_reserve(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
+	Array<irValue *> ops = {0}; // NOTE(bill): Act as a buffer
+	array_init(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
 	for_array(i, proc->blocks) {
-		irBlock *b = proc->blocks.e[i];
+		irBlock *b = proc->blocks[i];
 		for_array(j, b->instrs) {
-			irValue *instr = b->instrs.e[j];
+			irValue *instr = b->instrs[j];
 			array_clear(&ops);
 			ir_opt_add_operands(&ops, &instr->Instr);
 			for_array(k, ops) {
-				irValue *op = ops.e[k];
+				irValue *op = ops[k];
 				if (op == NULL) {
 					continue;
 				}
-				irValueArray *refs = ir_value_referrers(op);
+				Array<irValue *> *refs = ir_value_referrers(op);
 				if (refs != NULL) {
 					array_add(refs, instr);
 				}
@@ -324,7 +324,7 @@ i32 ir_lt_depth_first_search(irLTState *lt, irBlock *p, i32 i, irBlock **preorde
 	lt->sdom[p->index] = p;
 	ir_lt_link(lt, NULL, p);
 	for_array(index, p->succs) {
-		irBlock *q = p->succs.e[index];
+		irBlock *q = p->succs[index];
 		if (lt->sdom[q->index] == NULL) {
 			lt->parent[q->index] = p;
 			i = ir_lt_depth_first_search(lt, q, i, preorder);
@@ -354,7 +354,7 @@ irDomPrePost ir_opt_number_dom_tree(irBlock *v, i32 pre, i32 post) {
 
 	v->dom.pre = pre++;
 	for_array(i, v->dom.children) {
-		result = ir_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
+		result = ir_opt_number_dom_tree(v->dom.children[i], result.pre, result.post);
 	}
 	v->dom.post = post++;
 
@@ -381,7 +381,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
 
 	irBlock **preorder = &buf[3*n];
 	irBlock **buckets  = &buf[4*n];
-	irBlock *root = proc->blocks.e[0];
+	irBlock *root = proc->blocks[0];
 
 	// Step 1 - number vertices
 	i32 pre_num = ir_lt_depth_first_search(&lt, root, 0, preorder);
@@ -403,7 +403,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
 		// Step 2 - Compute all sdoms
 		lt.sdom[w->index] = lt.parent[w->index];
 		for_array(pred_index, w->preds) {
-			irBlock *v = w->preds.e[pred_index];
+			irBlock *v = w->preds[pred_index];
 			irBlock *u = ir_lt_eval(&lt, v);
 			if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
 				lt.sdom[w->index] = lt.sdom[u->index];
@@ -438,7 +438,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
 			}
 
 			// Calculate children relation as inverse of idom
-			if (w->dom.idom->dom.children.e == NULL) {
+			if (w->dom.idom->dom.children.data == NULL) {
 				// TODO(bill): Is this good enough for memory allocations?
 				array_init(&w->dom.idom->dom.children, heap_allocator());
 			}
@@ -461,7 +461,7 @@ void ir_opt_tree(irGen *s) {
 	s->opt_called = true;
 
 	for_array(member_index, s->module.procs) {
-		irProcedure *proc = s->module.procs.e[member_index];
+		irProcedure *proc = s->module.procs[member_index];
 		if (proc->blocks.count == 0) { // Prototype/external procedure
 			continue;
 		}

+ 31 - 31
src/ir_print.c → src/ir_print.cpp

@@ -1,8 +1,8 @@
-typedef struct irFileBuffer {
+struct irFileBuffer {
 	gbVirtualMemory vm;
 	isize           offset;
 	gbFile *        output;
-} irFileBuffer;
+};
 
 void ir_file_buffer_init(irFileBuffer *f, gbFile *output) {
 	isize size = 8*gb_virtual_memory_page_size(NULL);
@@ -39,7 +39,7 @@ void ir_file_buffer_write(irFileBuffer *f, void *data, isize len) {
 void ir_fprintf(irFileBuffer *f, char *fmt, ...) {
 	va_list va;
 	va_start(va, fmt);
-	char buf[4096] = {0};
+	char buf[4096] = {};
 	isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
 	ir_file_buffer_write(f, buf, len-1);
 	va_end(va);
@@ -48,7 +48,7 @@ void ir_fprint_string(irFileBuffer *f, String s) {
 	ir_file_buffer_write(f, s.text, s.len);
 }
 void ir_fprint_i128(irFileBuffer *f, i128 i) {
-	char buf[200] = {0};
+	char buf[200] = {};
 	String str = i128_to_string(i, buf, gb_size_of(buf)-1);
 	ir_fprint_string(f, str);
 }
@@ -81,7 +81,7 @@ bool ir_valid_char(u8 c) {
 void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, bool prefix_with_dot) {
 	isize extra = 0;
 	for (isize i = 0; i < name.len; i++) {
-		u8 c = name.text[i];
+		u8 c = name[i];
 		if (!ir_valid_char(c)) {
 			extra += 2;
 		}
@@ -111,7 +111,7 @@ void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, boo
 	}
 
 	for (isize i = 0; i < name.len; i++) {
-		u8 c = name.text[i];
+		u8 c = name[i];
 		if (ir_valid_char(c)) {
 			buf[j++] = c;
 		} else {
@@ -306,7 +306,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 
 	case Type_Named:
 		if (is_type_struct(t) || is_type_union(t)) {
-			String *name = map_string_get(&m->entity_names, hash_pointer(t->Named.type_name));
+			String *name = map_get(&m->entity_names, hash_pointer(t->Named.type_name));
 			GB_ASSERT_MSG(name != NULL, "%.*s", LIT(t->Named.name));
 			ir_print_encoded_local(f, *name);
 		} else {
@@ -497,7 +497,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 				if (i > 0) {
 					ir_fprintf(f, ", ");
 				}
-				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
+				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
 				GB_ASSERT(tav.mode != Addressing_Invalid);
 				ir_print_compound_element(f, m, tav.value, elem_type);
 			}
@@ -527,7 +527,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ir_fprintf(f, "][");
 
 			if (elem_count == 1 && type->Vector.count > 1) {
-				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[0]);
+				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[0]);
 				GB_ASSERT(tav.mode != Addressing_Invalid);
 
 				for (isize i = 0; i < type->Vector.count; i++) {
@@ -541,7 +541,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 					if (i > 0) {
 						ir_fprintf(f, ", ");
 					}
-					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
+					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
 					GB_ASSERT(tav.mode != Addressing_Invalid);
 					ir_print_compound_element(f, m, tav.value, elem_type);
 				}
@@ -563,25 +563,25 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
 
 
-			if (cl->elems.e[0]->kind == AstNode_FieldValue) {
+			if (cl->elems[0]->kind == AstNode_FieldValue) {
 				isize elem_count = cl->elems.count;
 				for (isize i = 0; i < elem_count; i++) {
-					ast_node(fv, FieldValue, cl->elems.e[i]);
+					ast_node(fv, FieldValue, cl->elems[i]);
 					String name = fv->field->Ident.string;
 
 					TypeAndValue tav = type_and_value_of_expr(m->info, fv->value);
 					GB_ASSERT(tav.mode != Addressing_Invalid);
 
 					Selection sel = lookup_field(m->allocator, type, name, false);
-					Entity *f = type->Record.fields[sel.index.e[0]];
+					Entity *f = type->Record.fields[sel.index[0]];
 
 					values[f->Variable.field_index] = tav.value;
 				}
 			} else {
 				for (isize i = 0; i < value_count; i++) {
 					Entity *f = type->Record.fields_in_src_order[i];
-					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
-					ExactValue val = {0};
+					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
+					ExactValue val = {};
 					if (tav.mode != Addressing_Invalid) {
 						val = tav.value;
 					}
@@ -891,11 +891,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 				ir_fprintf(f, ", ");
 			}
 
-			irValue *edge = instr->Phi.edges.e[i];
+			irValue *edge = instr->Phi.edges[i];
 			irBlock *block = NULL;
 			if (instr->parent != NULL &&
 			    i < instr->parent->preds.count) {
-				block = instr->parent->preds.e[i];
+				block = instr->parent->preds[i];
 			}
 
 			ir_fprintf(f, "[ ");
@@ -1500,8 +1500,8 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 				ir_fprintf(f, " noalias");
 			}
 			if (proc->body != NULL) {
-				if (!str_eq(e->token.string, str_lit("")) &&
-				    !str_eq(e->token.string, str_lit("_"))) {
+				if (e->token.string != "" &&
+				    e->token.string != "_") {
 					ir_fprintf(f, " ");
 					ir_print_encoded_local(f, e->token.string);
 				} else {
@@ -1523,7 +1523,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 
 	if (proc->entity != NULL) {
 		if (proc->body != NULL) {
-			irDebugInfo **di_ = map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity));
+			irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity));
 			if (di_ != NULL) {
 				irDebugInfo *di = *di_;
 				GB_ASSERT(di->kind == irDebugInfo_Proc);
@@ -1538,14 +1538,14 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 
 		ir_fprintf(f, "{\n");
 		for_array(i, proc->blocks) {
-			irBlock *block = proc->blocks.e[i];
+			irBlock *block = proc->blocks[i];
 
 			if (i > 0) ir_fprintf(f, "\n");
 			ir_print_block_name(f, block);
 			ir_fprintf(f, ":\n");
 
 			for_array(j, block->instrs) {
-				irValue *value = block->instrs.e[j];
+				irValue *value = block->instrs[j];
 				ir_print_instr(f, m, value);
 			}
 		}
@@ -1555,7 +1555,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 	}
 
 	for_array(i, proc->children) {
-		ir_print_proc(f, m, proc->children.e[i]);
+		ir_print_proc(f, m, proc->children[i]);
 	}
 }
 
@@ -1573,7 +1573,7 @@ void ir_print_type_name(irFileBuffer *f, irModule *m, irValue *v) {
 
 void print_llvm_ir(irGen *ir) {
 	irModule *m = &ir->module;
-	irFileBuffer buf = {0}, *f = &buf;
+	irFileBuffer buf = {}, *f = &buf;
 	ir_file_buffer_init(f, &ir->output_file);
 
 	ir_print_encoded_local(f, str_lit("..string"));
@@ -1606,7 +1606,7 @@ void print_llvm_ir(irGen *ir) {
 
 
 	for_array(member_index, m->members.entries) {
-		MapIrValueEntry *entry = &m->members.entries.e[member_index];
+		auto *entry = &m->members.entries[member_index];
 		irValue *v = entry->value;
 		if (v->kind != irValue_TypeName) {
 			continue;
@@ -1619,7 +1619,7 @@ void print_llvm_ir(irGen *ir) {
 	bool dll_main_found = false;
 
 	for_array(member_index, m->members.entries) {
-		MapIrValueEntry *entry = &m->members.entries.e[member_index];
+		auto *entry = &m->members.entries[member_index];
 		irValue *v = entry->value;
 		if (v->kind != irValue_Proc) {
 			continue;
@@ -1631,7 +1631,7 @@ void print_llvm_ir(irGen *ir) {
 	}
 
 	for_array(member_index, m->members.entries) {
-		MapIrValueEntry *entry = &m->members.entries.e[member_index];
+		auto *entry = &m->members.entries[member_index];
 		irValue *v = entry->value;
 		if (v->kind != irValue_Proc) {
 			continue;
@@ -1643,7 +1643,7 @@ void print_llvm_ir(irGen *ir) {
 	}
 
 	for_array(member_index, m->members.entries) {
-		MapIrValueEntry *entry = &m->members.entries.e[member_index];
+		auto *entry = &m->members.entries[member_index];
 		irValue *v = entry->value;
 		if (v->kind != irValue_Global) {
 			continue;
@@ -1707,13 +1707,13 @@ void print_llvm_ir(irGen *ir) {
 		ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3);
 
 		for_array(di_index, m->debug_info.entries) {
-			MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[di_index];
+			MapIrDebugInfoEntry *entry = &m->debug_info.entries[di_index];
 			irDebugInfo *di = entry->value;
 			ir_fprintf(f, "!%d = ", di->id);
 
 			switch (di->kind) {
 			case irDebugInfo_CompileUnit: {
-				irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
+				irDebugInfo *file = *map_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
 				ir_fprintf(f,
 				            "distinct !DICompileUnit("
 				            "language: DW_LANG_Go, " // Is this good enough?
@@ -1752,7 +1752,7 @@ void print_llvm_ir(irGen *ir) {
 			case irDebugInfo_AllProcs:
 				ir_fprintf(f, "!{");
 				for_array(proc_index, di->AllProcs.procs) {
-					irDebugInfo *p = di->AllProcs.procs.e[proc_index];
+					irDebugInfo *p = di->AllProcs.procs[proc_index];
 					if (proc_index > 0) {ir_fprintf(f, ",");}
 					ir_fprintf(f, "!%d", p->id);
 				}

+ 17 - 26
src/main.c → src/main.cpp

@@ -1,20 +1,15 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
 #define USE_CUSTOM_BACKEND false
 
-#include "common.c"
-#include "timings.c"
-#include "build_settings.c"
-#include "tokenizer.c"
-#include "parser.c"
-#include "checker.c"
-#include "ssa.c"
-#include "ir.c"
-#include "ir_opt.c"
-#include "ir_print.c"
-// #include "vm.c"
+#include "common.cpp"
+#include "timings.cpp"
+#include "build_settings.cpp"
+#include "tokenizer.cpp"
+#include "parser.cpp"
+#include "checker.cpp"
+#include "ssa.cpp"
+#include "ir.cpp"
+#include "ir_opt.cpp"
+#include "ir_print.cpp"
 
 #if defined(GB_SYSTEM_WINDOWS)
 // NOTE(bill): `name` is used in debugging and profiling modes
@@ -155,27 +150,27 @@ int main(int argc, char **argv) {
 	char *init_filename = NULL;
 	bool run_output = false;
 	String arg1 = make_string_c(argv[1]);
-	if (str_eq(arg1, str_lit("run"))) {
+	if (arg1 == "run") {
 		if (argc != 3) {
 			usage(argv[0]);
 			return 1;
 		}
 		init_filename = argv[2];
 		run_output = true;
-	} else if (str_eq(arg1, str_lit("build_dll"))) {
+	} else if (arg1 == "build_dll") {
 		if (argc != 3) {
 			usage(argv[0]);
 			return 1;
 		}
 		init_filename = argv[2];
 		build_context.is_dll = true;
-	} else if (str_eq(arg1, str_lit("build"))) {
+	} else if (arg1 == "build") {
 		if (argc != 3) {
 			usage(argv[0]);
 			return 1;
 		}
 		init_filename = argv[2];
-	} else if (str_eq(arg1, str_lit("version"))) {
+	} else if (arg1 == "version") {
 		gb_printf("%s version %.*s\n", argv[0], LIT(build_context.ODIN_VERSION));
 		return 0;
 	} else {
@@ -314,7 +309,7 @@ int main(int argc, char **argv) {
 	// defer (gb_string_free(lib_str));
 	char lib_str_buf[1024] = {0};
 	for_array(i, ir_gen.module.foreign_library_paths) {
-		String lib = ir_gen.module.foreign_library_paths.e[i];
+		String lib = ir_gen.module.foreign_library_paths[i];
 		// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
 		isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
 		                        " \"%.*s\"", LIT(lib));
@@ -376,14 +371,14 @@ int main(int argc, char **argv) {
 	// defer (gb_string_free(lib_str));
 	char lib_str_buf[1024] = {0};
 	for_array(i, ir_gen.module.foreign_library_paths) {
-		String lib = ir_gen.module.foreign_library_paths.e[i];
+		String lib = ir_gen.module.foreign_library_paths[i];
 
 		// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
 		//   This allows you to specify '-f' in a #foreign_system_library,
 		//   without having to implement any new syntax specifically for MacOS.
 		#if defined(GB_SYSTEM_OSX)
 			isize len;
-			if(lib.len > 2 && lib.text[0] == '-' && lib.text[1] == 'f') {
+			if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
 				len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
 				                        " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
 			} else {
@@ -461,7 +456,3 @@ int main(int argc, char **argv) {
 
 	return 0;
 }
-
-#if defined(__cplusplus)
-}
-#endif

+ 0 - 364
src/map.c

@@ -1,364 +0,0 @@
-/*
-	Example of usage:
-
-	#define MAP_TYPE String
-	#define MAP_PROC map_string_
-	#define MAP_NAME MapString
-	#include "map.c"
-*/
-// A `Map` is an unordered hash table which can allow for a key to point to multiple values
-// with the use of the `multi_*` procedures.
-// TODO(bill): I should probably allow the `multi_*` stuff to be #ifdefed out
-
-#ifndef MAP_UTIL_STUFF
-#define MAP_UTIL_STUFF
-// NOTE(bill): This util stuff is the same for every `Map`
-typedef struct MapFindResult {
-	isize hash_index;
-	isize entry_prev;
-	isize entry_index;
-} MapFindResult;
-
-typedef enum HashKeyKind {
-	HashKey_Default,
-	HashKey_String,
-	HashKey_Pointer,
-} HashKeyKind;
-
-typedef struct HashKey {
-	HashKeyKind kind;
-	u64         key;
-	union {
-		String string; // if String, s.len > 0
-		void * ptr;
-	};
-} HashKey;
-
-gb_inline HashKey hashing_proc(void const *data, isize len) {
-	HashKey h = {HashKey_Default};
-	h.kind = HashKey_Default;
-	// h.key = gb_murmur64(data, len);
-	h.key = gb_fnv64a(data, len);
-	// h.key = MurmurHash3_128(data, len, 0x3803cb8e);
-
-	return h;
-}
-
-gb_inline HashKey hash_string(String s) {
-	HashKey h = hashing_proc(s.text, s.len);
-	h.kind = HashKey_String;
-	h.string = s;
-	return h;
-}
-
-gb_inline HashKey hash_pointer(void *ptr) {
-	HashKey h = {HashKey_Default};
-	// h.key = u128_from_u64(cast(u64)cast(uintptr)ptr);
-	h.key = cast(u64)cast(uintptr)ptr;
-	h.ptr = ptr;
-	h.kind = HashKey_Default;
-	return h;
-}
-
-bool hash_key_equal(HashKey a, HashKey b) {
-	if (a.key == b.key) {
-		// NOTE(bill): If two string's hashes collide, compare the strings themselves
-		if (a.kind == HashKey_String) {
-			if (b.kind == HashKey_String) {
-				return str_eq(a.string, b.string);
-			}
-			return false;
-		}
-		return true;
-	}
-	return false;
-}
-#endif
-
-#define _J2_IND(a, b) a##b
-#define _J2(a, b) _J2_IND(a, b)
-
-/*
-MAP_TYPE - Entry type
-MAP_PROC - Function prefix (e.g. entity_map_)
-MAP_NAME - Name of Map (e.g. EntityMap)
-*/
-#define MAP_ENTRY _J2(MAP_NAME,Entry)
-
-typedef struct MAP_ENTRY {
-	HashKey  key;
-	isize    next;
-	MAP_TYPE value;
-} MAP_ENTRY;
-
-typedef struct MAP_NAME {
-	Array(isize)     hashes;
-	Array(MAP_ENTRY) entries;
-} MAP_NAME;
-
-void      _J2(MAP_PROC,init)             (MAP_NAME *h, gbAllocator a);
-void      _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity);
-void      _J2(MAP_PROC,destroy)          (MAP_NAME *h);
-MAP_TYPE *_J2(MAP_PROC,get)              (MAP_NAME *h, HashKey key);
-void      _J2(MAP_PROC,set)              (MAP_NAME *h, HashKey key, MAP_TYPE value);
-void      _J2(MAP_PROC,remove)           (MAP_NAME *h, HashKey key);
-void      _J2(MAP_PROC,clear)            (MAP_NAME *h);
-void      _J2(MAP_PROC,grow)             (MAP_NAME *h);
-void      _J2(MAP_PROC,rehash)           (MAP_NAME *h, isize new_count);
-
-// Mutlivalued map procedure
-MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key);
-MAP_ENTRY *_J2(MAP_PROC,multi_find_next) (MAP_NAME *h, MAP_ENTRY *e);
-
-isize _J2(MAP_PROC,multi_count)     (MAP_NAME *h, HashKey key);
-void  _J2(MAP_PROC,multi_get_all)   (MAP_NAME *h, HashKey key, MAP_TYPE *items);
-void  _J2(MAP_PROC,multi_insert)    (MAP_NAME *h, HashKey key, MAP_TYPE value);
-void  _J2(MAP_PROC,multi_remove)    (MAP_NAME *h, HashKey key, MAP_ENTRY *e);
-void  _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key);
-
-
-
-gb_inline void _J2(MAP_PROC,init)(MAP_NAME *h, gbAllocator a) {
-	array_init(&h->hashes,  a);
-	array_init(&h->entries, a);
-}
-
-gb_inline void _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity) {
-	array_init_reserve(&h->hashes,  a, capacity);
-	array_init_reserve(&h->entries, a, capacity);
-}
-
-gb_inline void _J2(MAP_PROC,destroy)(MAP_NAME *h) {
-	array_free(&h->entries);
-	array_free(&h->hashes);
-}
-
-gb_internal isize _J2(MAP_PROC,_add_entry)(MAP_NAME *h, HashKey key) {
-	MAP_ENTRY e = {0};
-	e.key = key;
-	e.next = -1;
-	array_add(&h->entries, e);
-	return h->entries.count-1;
-}
-
-gb_internal MapFindResult _J2(MAP_PROC,_find)(MAP_NAME *h, HashKey key) {
-	MapFindResult fr = {-1, -1, -1};
-	if (h->hashes.count > 0) {
-		fr.hash_index  = key.key % h->hashes.count;
-		fr.entry_index = h->hashes.e[fr.hash_index];
-		while (fr.entry_index >= 0) {
-			if (hash_key_equal(h->entries.e[fr.entry_index].key, key)) {
-				return fr;
-			}
-			fr.entry_prev = fr.entry_index;
-			fr.entry_index = h->entries.e[fr.entry_index].next;
-		}
-	}
-	return fr;
-}
-
-gb_internal MapFindResult _J2(MAP_PROC,_find_from_entry)(MAP_NAME *h, MAP_ENTRY *e) {
-	MapFindResult fr = {-1, -1, -1};
-	if (h->hashes.count > 0) {
-		fr.hash_index  = e->key.key % h->hashes.count;
-		fr.entry_index = h->hashes.e[fr.hash_index];
-		while (fr.entry_index >= 0) {
-			if (&h->entries.e[fr.entry_index] == e) {
-				return fr;
-			}
-			fr.entry_prev = fr.entry_index;
-			fr.entry_index = h->entries.e[fr.entry_index].next;
-		}
-	}
-	return fr;
-}
-
-
-gb_internal b32 _J2(MAP_PROC,_full)(MAP_NAME *h) {
-	return 0.75f * h->hashes.count <= h->entries.count;
-}
-
-gb_inline void _J2(MAP_PROC,grow)(MAP_NAME *h) {
-	isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
-	_J2(MAP_PROC,rehash)(h, new_count);
-}
-
-void _J2(MAP_PROC,rehash)(MAP_NAME *h, isize new_count) {
-	isize i, j;
-	MAP_NAME nh = {0};
-	_J2(MAP_PROC,init)(&nh, h->hashes.allocator);
-	array_resize(&nh.hashes, new_count);
-	array_reserve(&nh.entries, h->entries.count);
-	for (i = 0; i < new_count; i++) {
-		nh.hashes.e[i] = -1;
-	}
-	for (i = 0; i < h->entries.count; i++) {
-		MAP_ENTRY *e = &h->entries.e[i];
-		MapFindResult fr;
-		if (nh.hashes.count == 0) {
-			_J2(MAP_PROC,grow)(&nh);
-		}
-		fr = _J2(MAP_PROC,_find)(&nh, e->key);
-		j = _J2(MAP_PROC,_add_entry)(&nh, e->key);
-		if (fr.entry_prev < 0) {
-			nh.hashes.e[fr.hash_index] = j;
-		} else {
-			nh.entries.e[fr.entry_prev].next = j;
-		}
-		nh.entries.e[j].next = fr.entry_index;
-		nh.entries.e[j].value = e->value;
-		if (_J2(MAP_PROC,_full)(&nh)) {
-			_J2(MAP_PROC,grow)(&nh);
-		}
-	}
-	_J2(MAP_PROC,destroy)(h);
-	*h = nh;
-}
-
-gb_inline MAP_TYPE *_J2(MAP_PROC,get)(MAP_NAME *h, HashKey key) {
-	isize index = _J2(MAP_PROC,_find)(h, key).entry_index;
-	if (index >= 0) {
-		return &h->entries.e[index].value;
-	}
-	return NULL;
-}
-
-void _J2(MAP_PROC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
-	isize index;
-	MapFindResult fr;
-	if (h->hashes.count == 0)
-		_J2(MAP_PROC,grow)(h);
-	fr = _J2(MAP_PROC,_find)(h, key);
-	if (fr.entry_index >= 0) {
-		index = fr.entry_index;
-	} else {
-		index = _J2(MAP_PROC,_add_entry)(h, key);
-		if (fr.entry_prev >= 0) {
-			h->entries.e[fr.entry_prev].next = index;
-		} else {
-			h->hashes.e[fr.hash_index] = index;
-		}
-	}
-	h->entries.e[index].value = value;
-
-	if (_J2(MAP_PROC,_full)(h)) {
-		_J2(MAP_PROC,grow)(h);
-	}
-}
-
-
-
-void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
-	MapFindResult last;
-	if (fr.entry_prev < 0) {
-		h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
-	} else {
-		h->entries.e[fr.entry_prev].next = h->entries.e[fr.entry_index].next;
-	}
-	if (fr.entry_index == h->entries.count-1) {
-		array_pop(&h->entries);
-		return;
-	}
-	h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
-	last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
-	if (last.entry_prev >= 0) {
-		h->entries.e[last.entry_prev].next = fr.entry_index;
-	} else {
-		h->hashes.e[last.hash_index] = fr.entry_index;
-	}
-}
-
-void _J2(MAP_PROC,remove)(MAP_NAME *h, HashKey key) {
-	MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
-	if (fr.entry_index >= 0) {
-		_J2(MAP_PROC,_erase)(h, fr);
-	}
-}
-
-gb_inline void _J2(MAP_PROC,clear)(MAP_NAME *h) {
-	array_clear(&h->hashes);
-	array_clear(&h->entries);
-}
-
-
-#if 1
-MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key) {
-	isize i = _J2(MAP_PROC,_find)(h, key).entry_index;
-	if (i < 0) {
-		return NULL;
-	}
-	return &h->entries.e[i];
-}
-
-MAP_ENTRY *_J2(MAP_PROC,multi_find_next)(MAP_NAME *h, MAP_ENTRY *e) {
-	isize i = e->next;
-	while (i >= 0) {
-		if (hash_key_equal(h->entries.e[i].key, e->key)) {
-			return &h->entries.e[i];
-		}
-		i = h->entries.e[i].next;
-	}
-	return NULL;
-}
-
-isize _J2(MAP_PROC,multi_count)(MAP_NAME *h, HashKey key) {
-	isize count = 0;
-	MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
-	while (e != NULL) {
-		count++;
-		e = _J2(MAP_PROC,multi_find_next)(h, e);
-	}
-	return count;
-}
-
-void _J2(MAP_PROC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
-	isize i = 0;
-	MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
-	while (e != NULL) {
-		items[i++] = e->value;
-		e = _J2(MAP_PROC,multi_find_next)(h, e);
-	}
-}
-
-void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
-	MapFindResult fr;
-	isize i;
-	if (h->hashes.count == 0) {
-		_J2(MAP_PROC,grow)(h);
-	}
-	// Make
-	fr = _J2(MAP_PROC,_find)(h, key);
-	i = _J2(MAP_PROC,_add_entry)(h, key);
-	if (fr.entry_prev < 0) {
-		h->hashes.e[fr.hash_index] = i;
-	} else {
-		h->entries.e[fr.entry_prev].next = i;
-	}
-	h->entries.e[i].next = fr.entry_index;
-	h->entries.e[i].value = value;
-	// Grow if needed
-	if (_J2(MAP_PROC,_full)(h)) {
-		_J2(MAP_PROC,grow)(h);
-	}
-}
-
-void _J2(MAP_PROC,multi_remove)(MAP_NAME *h, HashKey key, MAP_ENTRY *e) {
-	MapFindResult fr = _J2(MAP_PROC,_find_from_entry)(h, e);
-	if (fr.entry_index >= 0) {
-		_J2(MAP_PROC,_erase)(h, fr);
-	}
-}
-
-void _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key) {
-	while (_J2(MAP_PROC,get)(h, key) != NULL) {
-		_J2(MAP_PROC,remove)(h, key);
-	}
-}
-#endif
-
-
-#undef _J2
-#undef MAP_TYPE
-#undef MAP_PROC
-#undef MAP_NAME
-#undef MAP_ENTRY

+ 364 - 0
src/map.cpp

@@ -0,0 +1,364 @@
+// A `Map` is an unordered hash table which can allow for a key to point to multiple values
+// with the use of the `multi_*` procedures.
+// TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out
+
+#ifndef MAP_UTIL_STUFF
+#define MAP_UTIL_STUFF
+// NOTE(bill): This util stuff is the same for every `Map`
+struct MapFindResult {
+	isize hash_index;
+	isize entry_prev;
+	isize entry_index;
+};
+
+enum HashKeyKind {
+	HashKey_Default,
+	HashKey_String,
+	HashKey_Pointer,
+};
+
+struct HashKey {
+	HashKeyKind kind;
+	// u128        key;
+	u64         key;
+	union {
+		String string; // if String, s.len > 0
+		void * ptr;
+	};
+};
+
+gb_inline HashKey hashing_proc(void const *data, isize len) {
+	HashKey h = {HashKey_Default};
+	h.kind = HashKey_Default;
+	// h.key = u128_from_u64(gb_fnv64a(data, len));
+	h.key = gb_fnv64a(data, len);
+
+	return h;
+}
+
+gb_inline HashKey hash_string(String s) {
+	HashKey h = hashing_proc(s.text, s.len);
+	h.kind = HashKey_String;
+	h.string = s;
+	return h;
+}
+
+gb_inline HashKey hash_pointer(void *ptr) {
+	HashKey h = {HashKey_Default};
+	// h.key = u128_from_u64(cast(u64)cast(uintptr)ptr);
+	h.key = cast(u64)cast(uintptr)ptr;
+	h.ptr = ptr;
+	h.kind = HashKey_Default;
+	return h;
+}
+
+bool hash_key_equal(HashKey a, HashKey b) {
+	if (a.key == b.key) {
+		// NOTE(bill): If two string's hashes collide, compare the strings themselves
+		if (a.kind == HashKey_String) {
+			if (b.kind == HashKey_String) {
+				return a.string == b.string;
+			}
+			return false;
+		}
+		return true;
+	}
+	return false;
+}
+bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); }
+bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); }
+
+#endif
+
+template <typename T>
+struct MapEntry {
+	HashKey  key;
+	isize    next;
+	T        value;
+};
+
+template <typename T>
+struct Map {
+	Array<isize>        hashes;
+	Array<MapEntry<T> > entries;
+};
+
+
+template <typename T> void map_init             (Map<T> *h, gbAllocator a);
+template <typename T> void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity);
+template <typename T> void map_destroy          (Map<T> *h);
+template <typename T> T *  map_get              (Map<T> *h, HashKey key);
+template <typename T> void map_set              (Map<T> *h, HashKey key, T const &value);
+template <typename T> void map_remove           (Map<T> *h, HashKey key);
+template <typename T> void map_clear            (Map<T> *h);
+template <typename T> void map_grow             (Map<T> *h);
+template <typename T> void map_rehash           (Map<T> *h, isize new_count);
+
+// Mutlivalued map procedure
+template <typename T> MapEntry<T> * multi_map_find_first(Map<T> *h, HashKey key);
+template <typename T> MapEntry<T> * multi_map_find_next (Map<T> *h, MapEntry<T> *e);
+
+template <typename T> isize multi_map_count     (Map<T> *h, HashKey key);
+template <typename T> void  multi_map_get_all   (Map<T> *h, HashKey key, T *items);
+template <typename T> void  multi_map_insert    (Map<T> *h, HashKey key, T const &value);
+template <typename T> void  multi_map_remove    (Map<T> *h, HashKey key, MapEntry<T> *e);
+template <typename T> void  multi_map_remove_all(Map<T> *h, HashKey key);
+
+
+template <typename T>
+gb_inline void map_init(Map<T> *h, gbAllocator a) {
+	array_init(&h->hashes,  a);
+	array_init(&h->entries, a);
+}
+
+template <typename T>
+gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
+	array_init(&h->hashes,  a, capacity);
+	array_init(&h->entries, a, capacity);
+}
+
+template <typename T>
+gb_inline void map_destroy(Map<T> *h) {
+	array_free(&h->entries);
+	array_free(&h->hashes);
+}
+
+template <typename T>
+gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
+	MapEntry<T> e = {};
+	e.key = key;
+	e.next = -1;
+	array_add(&h->entries, e);
+	return h->entries.count-1;
+}
+
+template <typename T>
+gb_internal MapFindResult map__find(Map<T> *h, HashKey key) {
+	MapFindResult fr = {-1, -1, -1};
+	if (h->hashes.count > 0) {
+		// fr.hash_index  = u128_to_i64(key.key % u128_from_i64(h->hashes.count));
+		fr.hash_index = key.key % h->hashes.count;
+		fr.entry_index = h->hashes[fr.hash_index];
+		while (fr.entry_index >= 0) {
+			if (hash_key_equal(h->entries[fr.entry_index].key, key)) {
+				return fr;
+			}
+			fr.entry_prev = fr.entry_index;
+			fr.entry_index = h->entries[fr.entry_index].next;
+		}
+	}
+	return fr;
+}
+
+template <typename T>
+gb_internal MapFindResult map__find_from_entry(Map<T> *h, MapEntry<T> *e) {
+	MapFindResult fr = {-1, -1, -1};
+	if (h->hashes.count > 0) {
+		fr.hash_index  = e->key.key % h->hashes.count;
+		fr.entry_index = h->hashes[fr.hash_index];
+		while (fr.entry_index >= 0) {
+			if (&h->entries[fr.entry_index] == e) {
+				return fr;
+			}
+			fr.entry_prev = fr.entry_index;
+			fr.entry_index = h->entries[fr.entry_index].next;
+		}
+	}
+	return fr;
+}
+
+template <typename T>
+gb_internal b32 map__full(Map<T> *h) {
+	return 0.75f * h->hashes.count <= h->entries.count;
+}
+
+template <typename T>
+gb_inline void map_grow(Map<T> *h) {
+	isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
+	map_rehash(h, new_count);
+}
+
+template <typename T>
+void map_rehash(Map<T> *h, isize new_count) {
+	isize i, j;
+	Map<T> nh = {};
+	map_init(&nh, h->hashes.allocator);
+	array_resize(&nh.hashes, new_count);
+	array_reserve(&nh.entries, h->entries.count);
+	for (i = 0; i < new_count; i++) {
+		nh.hashes[i] = -1;
+	}
+	for (i = 0; i < h->entries.count; i++) {
+		MapEntry<T> *e = &h->entries[i];
+		MapFindResult fr;
+		if (nh.hashes.count == 0) {
+			map_grow(&nh);
+		}
+		fr = map__find(&nh, e->key);
+		j = map__add_entry(&nh, e->key);
+		if (fr.entry_prev < 0) {
+			nh.hashes[fr.hash_index] = j;
+		} else {
+			nh.entries[fr.entry_prev].next = j;
+		}
+		nh.entries[j].next = fr.entry_index;
+		nh.entries[j].value = e->value;
+		if (map__full(&nh)) {
+			map_grow(&nh);
+		}
+	}
+	map_destroy(h);
+	*h = nh;
+}
+
+template <typename T>
+gb_inline T *map_get(Map<T> *h, HashKey key) {
+	isize index = map__find(h, key).entry_index;
+	if (index >= 0) {
+		return &h->entries[index].value;
+	}
+	return NULL;
+}
+
+template <typename T>
+void map_set(Map<T> *h, HashKey key, T const &value) {
+	isize index;
+	MapFindResult fr;
+	if (h->hashes.count == 0)
+		map_grow(h);
+	fr = map__find(h, key);
+	if (fr.entry_index >= 0) {
+		index = fr.entry_index;
+	} else {
+		index = map__add_entry(h, key);
+		if (fr.entry_prev >= 0) {
+			h->entries[fr.entry_prev].next = index;
+		} else {
+			h->hashes[fr.hash_index] = index;
+		}
+	}
+	h->entries[index].value = value;
+
+	if (map__full(h)) {
+		map_grow(h);
+	}
+}
+
+
+template <typename T>
+void map__erase(Map<T> *h, MapFindResult fr) {
+	MapFindResult last;
+	if (fr.entry_prev < 0) {
+		h->hashes[fr.hash_index] = h->entries[fr.entry_index].next;
+	} else {
+		h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next;
+	}
+	if (fr.entry_index == h->entries.count-1) {
+		array_pop(&h->entries);
+		return;
+	}
+	h->entries[fr.entry_index] = h->entries[h->entries.count-1];
+	last = map__find(h, h->entries[fr.entry_index].key);
+	if (last.entry_prev >= 0) {
+		h->entries[last.entry_prev].next = fr.entry_index;
+	} else {
+		h->hashes[last.hash_index] = fr.entry_index;
+	}
+}
+
+template <typename T>
+void map_remove(Map<T> *h, HashKey key) {
+	MapFindResult fr = map__find(h, key);
+	if (fr.entry_index >= 0) {
+		map__erase(h, fr);
+	}
+}
+
+template <typename T>
+gb_inline void map_clear(Map<T> *h) {
+	array_clear(&h->hashes);
+	array_clear(&h->entries);
+}
+
+
+#if 1
+template <typename T>
+MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) {
+	isize i = map__find(h, key).entry_index;
+	if (i < 0) {
+		return NULL;
+	}
+	return &h->entries[i];
+}
+
+template <typename T>
+MapEntry<T> *multi_map_find_next(Map<T> *h, MapEntry<T> *e) {
+	isize i = e->next;
+	while (i >= 0) {
+		if (hash_key_equal(h->entries[i].key, e->key)) {
+			return &h->entries[i];
+		}
+		i = h->entries[i].next;
+	}
+	return NULL;
+}
+
+template <typename T>
+isize multi_map_count(Map<T> *h, HashKey key) {
+	isize count = 0;
+	MapEntry<T> *e = multi_map_find_first(h, key);
+	while (e != NULL) {
+		count++;
+		e = multi_map_find_next(h, e);
+	}
+	return count;
+}
+
+template <typename T>
+void multi_map_get_all(Map<T> *h, HashKey key, T *items) {
+	isize i = 0;
+	MapEntry<T> *e = multi_map_find_first(h, key);
+	while (e != NULL) {
+		items[i++] = e->value;
+		e = multi_map_find_next(h, e);
+	}
+}
+
+template <typename T>
+void multi_map_insert(Map<T> *h, HashKey key, T const &value) {
+	MapFindResult fr;
+	isize i;
+	if (h->hashes.count == 0) {
+		map_grow(h);
+	}
+	// Make
+	fr = map__find(h, key);
+	i = map__add_entry(h, key);
+	if (fr.entry_prev < 0) {
+		h->hashes[fr.hash_index] = i;
+	} else {
+		h->entries[fr.entry_prev].next = i;
+	}
+	h->entries[i].next = fr.entry_index;
+	h->entries[i].value = value;
+	// Grow if needed
+	if (map__full(h)) {
+		map_grow(h);
+	}
+}
+
+template <typename T>
+void multi_map_remove(Map<T> *h, HashKey key, MapEntry<T> *e) {
+	MapFindResult fr = map__find_from_entry(h, e);
+	if (fr.entry_index >= 0) {
+		map__erase(h, fr);
+	}
+}
+
+template <typename T>
+void multi_map_remove_all(Map<T> *h, HashKey key) {
+	while (map_get(h, key) != NULL) {
+		map_remove(h, key);
+	}
+}
+#endif

+ 22 - 17
src/murmurhash3.c → src/murmurhash3.cpp

@@ -41,15 +41,15 @@ gb_inline u64 fmix64(u64 k) {
 	return k;
 }
 
-gb_inline u32 mm3_getblock32(u32 *const p, isize i) {
+gb_inline u32 mm3_getblock32(u32 const *p, isize i) {
 	return p[i];
 }
-gb_inline u64 mm3_getblock64(u64 *const p, isize i) {
+gb_inline u64 mm3_getblock64(u64 const *p, isize i) {
 	return p[i];
 }
 
-u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
-	u8 *const data = cast(u8 *const)key;
+void MurmurHash3_x64_128(void const *key, isize len, u32 seed, void *out) {
+	u8 const * data = cast(u8 const *)key;
 	isize nblocks = len / 16;
 
 	u64 h1 = seed;
@@ -58,7 +58,7 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
 	u64 const c1 = 0x87c37b91114253d5ULL;
 	u64 const c2 = 0x4cf5ad432745937fULL;
 
-	u64 *const blocks = cast(u64 *const)data;
+	u64 const * blocks = cast(u64 const *)data;
 
 	for (isize i = 0; i < nblocks; i++) {
 		u64 k1 = mm3_getblock64(blocks, i*2 + 0);
@@ -70,7 +70,7 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
 		h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
 	}
 
-	u8 *const tail = cast(u8 *const)(data + nblocks*16);
+	u8 const * tail = cast(u8 const *)(data + nblocks*16);
 
 	u64 k1 = 0;
 	u64 k2 = 0;
@@ -108,11 +108,12 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
 	h1 += h2;
 	h2 += h1;
 
-	return u128_lo_hi(h1, h2);
+	((u64 *)out)[0] = h1;
+	((u64 *)out)[1] = h2;
 }
 
-u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
-	u8 *const data = cast(u8 * const)key;
+void MurmurHash3_x86_128(void const *key, isize len, u32 seed, void *out) {
+	u8 const * data = cast(u8 * const)key;
 	isize nblocks = len / 16;
 
 	u32 h1 = seed;
@@ -128,7 +129,7 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
 	//----------
 	// body
 
-	u32 *const blocks = cast(u32 *const)(data + nblocks*16);
+	u32 const * blocks = cast(u32 const *)(data + nblocks*16);
 
 	for (isize i = -nblocks; i != 0; i++) {
 		u32 k1 = mm3_getblock32(blocks, i*4 + 0);
@@ -156,7 +157,7 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
 	//----------
 	// tail
 
-	u8 *const tail = cast(u8 *const)(data + nblocks*16);
+	u8 const * tail = cast(u8 const *)(data + nblocks*16);
 
 	u32 k1 = 0;
 	u32 k2 = 0;
@@ -204,17 +205,21 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
 	h1 += h2; h1 += h3; h1 += h4;
 	h2 += h1; h3 += h1; h4 += h1;
 
-	u64 lo = (u64)h1 | ((u64)h2 << 32);
-	u64 hi = (u64)h3 | ((u64)h4 << 32);
-	return u128_lo_hi(lo, hi);
+
+	((u32 *)out)[0] = h1;
+	((u32 *)out)[1] = h2;
+	((u32 *)out)[2] = h3;
+	((u32 *)out)[3] = h4;
 }
 
-gb_inline u128 MurmurHash3_128(void *const key, isize len, u32 seed) {
+gb_inline u128 MurmurHash3_128(void const *key, isize len, u32 seed) {
+	u128 res;
 #if defined(GB_ARCH_64_BIT)
-	return MurmurHash3_x64_128(key, len, seed);
+	MurmurHash3_x64_128(key, len, seed, &res);
 #else
-	return MurmurHash3_x86_128(key, len, seed);
+	MurmurHash3_x86_128(key, len, seed, &res);
 #endif
+	return res;
 }
 
 

File diff suppressed because it is too large
+ 179 - 157
src/parser.cpp


+ 0 - 0
src/printer.c → src/printer.cpp


+ 110 - 109
src/ssa.c → src/ssa.cpp

@@ -1,27 +1,21 @@
-typedef struct ssaModule           ssaModule;
-typedef struct ssaValue            ssaValue;
-typedef struct ssaValueArgs        ssaValueArgs;
-typedef struct ssaDefer            ssaDefer;
-typedef struct ssaBlock            ssaBlock;
-typedef struct ssaProc             ssaProc;
-typedef struct ssaEdge             ssaEdge;
-typedef struct ssaRegister         ssaRegister;
-typedef struct ssaTargetList       ssaTargetList;
-typedef enum   ssaBlockKind        ssaBlockKind;
-typedef enum   ssaBranchPrediction ssaBranchPrediction;
-typedef enum   ssaDeferExitKind    ssaDeferExitKind;
+struct ssaModule;
+struct ssaValue;
+struct ssaValueArgs;
+struct ssaDefer;
+struct ssaBlock;
+struct ssaProc;
+struct ssaEdge;
+struct ssaRegister;
+struct ssaTargetList;
+enum   ssaBlockKind;
+enum   ssaBranchPrediction;
+enum   ssaDeferExitKind;
 
 
 String ssa_mangle_name(ssaModule *m, String path, Entity *e);
 
-#define MAP_TYPE ssaValue *
-#define MAP_PROC map_ssa_value_
-#define MAP_NAME MapSsaValue
-#include "map.c"
 
-typedef Array(ssaValue *) ssaValueArray;
-
-#include "ssa_op.c"
+#include "ssa_op.cpp"
 
 #define SSA_DEFAULT_VALUE_ARG_CAPACITY 8
 struct ssaValueArgs {
@@ -30,6 +24,15 @@ struct ssaValueArgs {
 	isize       capacity;
 	ssaValue *  backing[SSA_DEFAULT_VALUE_ARG_CAPACITY];
 	gbAllocator allocator;
+
+	ssaValue *&operator[](isize i) {
+		GB_ASSERT(0 <= i && i <= count);
+		return e[i];
+	}
+	ssaValue * const &operator[](isize i) const {
+		GB_ASSERT(0 <= i && i <= count);
+		return e[i];
+	}
 };
 
 struct ssaValue {
@@ -67,10 +70,10 @@ enum ssaBranchPrediction {
 	ssaBranch_Unlikely = -1,
 };
 
-typedef enum ssaDeferKind {
+enum ssaDeferKind {
 	ssaDefer_Node,
 	ssaDefer_Instr,
-} ssaDeferKind;
+};
 
 struct ssaDefer {
 	ssaDeferKind     kind;
@@ -97,8 +100,6 @@ struct ssaEdge {
 	isize     index;
 };
 
-typedef Array(ssaEdge) ssaEdgeArray;
-
 struct ssaBlock {
 	i32                  id;   // Unique identifier but the pointer could be used too
 	ssaBlockKind         kind;
@@ -115,9 +116,9 @@ struct ssaBlock {
 	//  - BlockExit will be a memory control value
 	ssaValue *control;
 
-	ssaValueArray values;
-	ssaEdgeArray  preds;
-	ssaEdgeArray  succs;
+	Array<ssaValue *> values;
+	Array<ssaEdge>  preds;
+	Array<ssaEdge>  succs;
 };
 
 struct ssaTargetList {
@@ -134,7 +135,7 @@ struct ssaProc {
 	Entity *          entity;
 	DeclInfo *        decl_info;
 
-	Array(ssaBlock *) blocks;
+	Array<ssaBlock *> blocks;
 	ssaBlock *        entry;      // Entry block
 	ssaBlock *        exit;       // Exit block
 	ssaBlock *        curr_block;
@@ -143,9 +144,9 @@ struct ssaProc {
 
 	i32               block_id;
 	i32               value_id;
-	MapSsaValue       values;   // Key: Entity *
+	Map<ssaValue *>   values;   // Key: Entity *
 
-	Array(ssaDefer)   defer_stmts;
+	Array<ssaDefer>   defer_stmts;
 	i32               scope_level;
 };
 
@@ -161,10 +162,10 @@ struct ssaModule {
 	gbAllocator        tmp_allocator;
 	gbArena            tmp_arena;
 
-	MapEntity          min_dep_map; // Key: Entity *
-	MapSsaValue        values;      // Key: Entity *
+	Map<Entity *>      min_dep_map; // Key: Entity *
+	Map<ssaValue *>    values;      // Key: Entity *
 	// List of registers for the specific architecture
-	Array(ssaRegister) registers;
+	Array<ssaRegister> registers;
 
 	ssaProc *proc; // current procedure
 
@@ -172,19 +173,19 @@ struct ssaModule {
 
 	u32 stmt_state_flags;
 
-	Array(ssaProc *)  procs;
-	ssaValueArray     procs_to_generate;
+	Array<ssaProc *>  procs;
+	Array<ssaValue *>     procs_to_generate;
 };
 
-typedef enum ssaAddrKind {
+enum ssaAddrKind {
 	ssaAddr_Default,
 	ssaAddr_Map,
-} ssaAddrKind;
+};
 
-typedef struct ssaAddr {
+struct ssaAddr {
 	ssaValue *  addr;
 	ssaAddrKind kind;
-} ssaAddr;
+};
 
 
 
@@ -287,7 +288,7 @@ void ssa_add_arg(ssaValueArgs *va, ssaValue *arg) {
 		} else {
 			isize old_cap_size = va->capacity * gb_size_of(ssaValue *);
 			isize new_cap_size = capacity * gb_size_of(ssaValue *);
-			va->e = gb_resize(va->allocator, va->e, old_cap_size, new_cap_size);
+			*(cast(void **)&va->e) = gb_resize(va->allocator, va->e, old_cap_size, new_cap_size);
 		}
 		va->capacity = capacity;
 	}
@@ -378,9 +379,9 @@ ssaValue *ssa_const_i64         (ssaProc *p, Type *t, i64    c)     { return ssa
 ssaValue *ssa_const_f32         (ssaProc *p, Type *t, f32    c)     { return ssa_const_val(p, ssaOp_Const32F,    t, exact_value_float(c)); }
 ssaValue *ssa_const_f64         (ssaProc *p, Type *t, f64    c)     { return ssa_const_val(p, ssaOp_Const64F,    t, exact_value_float(c)); }
 ssaValue *ssa_const_string      (ssaProc *p, Type *t, String c)     { return ssa_const_val(p, ssaOp_ConstString, t, exact_value_string(c)); }
-ssaValue *ssa_const_empty_string(ssaProc *p, Type *t)               { return ssa_const_val(p, ssaOp_ConstString, t, (ExactValue){0}); }
+ssaValue *ssa_const_empty_string(ssaProc *p, Type *t)               { return ssa_const_val(p, ssaOp_ConstString, t, empty_exact_value); }
 ssaValue *ssa_const_slice       (ssaProc *p, Type *t, ExactValue v) { return ssa_const_val(p, ssaOp_ConstSlice,  t, v); }
-ssaValue *ssa_const_nil         (ssaProc *p, Type *t)               { return ssa_const_val(p, ssaOp_ConstNil,    t, (ExactValue){0}); }
+ssaValue *ssa_const_nil         (ssaProc *p, Type *t)               { return ssa_const_val(p, ssaOp_ConstNil,    t, empty_exact_value); }
 
 ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) {
 	switch (8*type_size_of(p->allocator, t)) {
@@ -399,21 +400,21 @@ ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) {
 ssaAddr   ssa_build_addr     (ssaProc *p, AstNode *expr);
 ssaValue *ssa_build_expr     (ssaProc *p, AstNode *expr);
 void      ssa_build_stmt     (ssaProc *p, AstNode *node);
-void      ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes);
+void      ssa_build_stmt_list(ssaProc *p, Array<AstNode *> nodes);
 ssaValue *ssa_emit_deep_field_ptr_index(ssaProc *p, ssaValue *e, Selection sel);
 
 
 
 void ssa_reset_value_args(ssaValue *v) {
 	for_array(i, v->args) {
-		v->args.e[i]->uses--;
+		v->args[i]->uses--;
 	}
 	v->args.count = 0;
 }
 
 void ssa_reset(ssaValue *v, ssaOp op) {
 	v->op = op;
-	v->exact_value = (ExactValue){0};
+	v->exact_value = empty_exact_value;
 	ssa_reset_value_args(v);
 }
 
@@ -425,7 +426,7 @@ ssaValue *ssa_get_last_value(ssaBlock *b) {
 	if (len <= 0) {
 		return 0;
 	}
-	ssaValue *v = b->values.e[len-1];
+	ssaValue *v = b->values[len-1];
 	return v;
 }
 
@@ -451,7 +452,7 @@ void ssa_build_defer_stmt(ssaProc *p, ssaDefer d) {
 void ssa_emit_defer_stmts(ssaProc *p, ssaDeferExitKind kind, ssaBlock *b) {
 	isize count = p->defer_stmts.count;
 	for (isize i = count-1; i >= 0; i--) {
-		ssaDefer d = p->defer_stmts.e[i];
+		ssaDefer d = p->defer_stmts[i];
 		if (kind == ssaDeferExit_Default) {
 			gb_printf_err("scope_level %d %d\n", p->scope_level, d.scope_level);
 			if (p->scope_level == d.scope_level &&
@@ -579,7 +580,7 @@ ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_
 
 	array_init(&p->blocks, heap_allocator());
 	array_init(&p->defer_stmts, heap_allocator());
-	map_ssa_value_init(&p->values, heap_allocator());
+	map_init(&p->values, heap_allocator());
 
 	return p;
 }
@@ -592,14 +593,14 @@ ssaAddr ssa_add_local(ssaProc *p, Entity *e, AstNode *expr) {
 	ssaValue *local = ssa_new_value0(p, ssaOp_Local, t);
 	p->curr_block = cb;
 
-	map_ssa_value_set(&p->values,         hash_pointer(e), local);
-	map_ssa_value_set(&p->module->values, hash_pointer(e), local);
+	map_set(&p->values,         hash_pointer(e), local);
+	map_set(&p->module->values, hash_pointer(e), local);
 	local->comment_string = e->token.string;
 	ssa_new_value1(p, ssaOp_Zero, t, local);
 	return ssa_addr(local);
 }
 ssaAddr ssa_add_local_for_ident(ssaProc *p, AstNode *name) {
-	Entity **found = map_entity_get(&p->module->info->definitions, hash_pointer(name));
+	Entity **found = map_get(&p->module->info->definitions, hash_pointer(name));
 	if (found) {
 		Entity *e = *found;
 		return ssa_add_local(p, e, name);
@@ -705,7 +706,7 @@ ssaValue *ssa_get_using_variable(ssaProc *p, Entity *e) {
 	Entity *parent = e->using_parent;
 	Selection sel = lookup_field(p->allocator, parent->type, name, false);
 	GB_ASSERT(sel.entity != NULL);
-	ssaValue **pv = map_ssa_value_get(&p->module->values, hash_pointer(parent));
+	ssaValue **pv = map_get(&p->module->values, hash_pointer(parent));
 	ssaValue *v = NULL;
 	if (pv != NULL) {
 		v = *pv;
@@ -721,7 +722,7 @@ ssaAddr ssa_build_addr_from_entity(ssaProc *p, Entity *e, AstNode *expr) {
 	GB_ASSERT(e != NULL);
 
 	ssaValue *v = NULL;
-	ssaValue **found = map_ssa_value_get(&p->module->values, hash_pointer(e));
+	ssaValue **found = map_get(&p->module->values, hash_pointer(e));
 	if (found) {
 		v = *found;
 	} else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) {
@@ -782,7 +783,7 @@ ssaValue *ssa_emit_conv(ssaProc *p, ssaValue *v, Type *t) {
 // NOTE(bill): Returns NULL if not possible
 ssaValue *ssa_address_from_load_or_generate_local(ssaProc *p, ssaValue *v) {
 	if (v->op == ssaOp_Load) {
-		return v->args.e[0];
+		return v->args[0];
 	}
 	ssaAddr addr = ssa_add_local_generated(p, v->type);
 	ssa_new_value2(p, ssaOp_Store, addr.addr->type, addr.addr, v);
@@ -863,7 +864,7 @@ ssaValue *ssa_emit_ptr_index(ssaProc *p, ssaValue *s, i64 index) {
 ssaValue *ssa_emit_value_index(ssaProc *p, ssaValue *s, i64 index) {
 	if (s->op == ssaOp_Load) {
 		if (!can_ssa_type(s->type)) {
-			ssaValue *e = ssa_emit_ptr_index(p, s->args.e[0], index);
+			ssaValue *e = ssa_emit_ptr_index(p, s->args[0], index);
 			return ssa_emit_load(p, e);
 		}
 	}
@@ -930,7 +931,7 @@ ssaValue *ssa_emit_deep_field_ptr_index(ssaProc *p, ssaValue *e, Selection sel)
 	Type *type = type_deref(e->type);
 
 	for_array(i, sel.index) {
-		i32 index = cast(i32)sel.index.e[i];
+		i32 index = cast(i32)sel.index[i];
 		if (is_type_pointer(type)) {
 			type = type_deref(type);
 			e = ssa_emit_load(p, e);
@@ -994,14 +995,14 @@ ssaValue *ssa_emit_deep_field_value_index(ssaProc *p, ssaValue *e, Selection sel
 	Type *type = e->type;
 	if (e->op == ssaOp_Load) {
 		if (!can_ssa_type(e->type)) {
-			ssaValue *ptr = ssa_emit_deep_field_ptr_index(p, e->args.e[0], sel);
+			ssaValue *ptr = ssa_emit_deep_field_ptr_index(p, e->args[0], sel);
 			return ssa_emit_load(p, ptr);
 		}
 	}
 	GB_ASSERT(can_ssa_type(e->type));
 
 	for_array(i, sel.index) {
-		i32 index = cast(i32)sel.index.e[i];
+		i32 index = cast(i32)sel.index[i];
 		if (is_type_pointer(type)) {
 			e = ssa_emit_load(p, e);
 		}
@@ -1071,7 +1072,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 				// GB_ASSERT(e->kind == Entity_Variable);
 				// GB_ASSERT(e->flags & EntityFlag_TypeField);
 				// String name = e->token.string;
-				// if (str_eq(name, str_lit("names"))) {
+				// if (name == "names") {
 				// 	ssaValue *ti_ptr = ir_type_info(p, type);
 
 				// 	ssaValue *names_ptr = NULL;
@@ -1685,7 +1686,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 	case_end;
 
 	case_ast_node(i, Ident, expr);
-		Entity *e = *map_entity_get(&p->module->info->uses, hash_pointer(expr));
+		Entity *e = *map_get(&p->module->info->uses, hash_pointer(expr));
 		if (e->kind == Entity_Builtin) {
 			Token token = ast_node_token(expr);
 			GB_PANIC("TODO(bill): ssa_build_expr Entity_Builtin `%.*s`\n"
@@ -1697,7 +1698,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 			return NULL;
 		}
 
-		ssaValue **found = map_ssa_value_get(&p->module->values, hash_pointer(e));
+		ssaValue **found = map_get(&p->module->values, hash_pointer(e));
 		if (found) {
 			ssaValue *v = *found;
 			if (v->op == ssaOp_Proc) {
@@ -1835,9 +1836,9 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 
 
 	case_ast_node(ce, CallExpr, expr);
-		if (map_tav_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
+		if (map_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
 			GB_ASSERT(ce->args.count == 1);
-			ssaValue *x = ssa_build_expr(p, ce->args.e[0]);
+			ssaValue *x = ssa_build_expr(p, ce->args[0]);
 			return ssa_emit_conv(p, x, tv.type);
 		}
 
@@ -1861,9 +1862,9 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 
 
 
-void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes) {
+void ssa_build_stmt_list(ssaProc *p, Array<AstNode *> nodes) {
 	for_array(i, nodes) {
-		ssa_build_stmt(p, nodes.e[i]);
+		ssa_build_stmt(p, nodes[i]);
 	}
 }
 
@@ -1946,7 +1947,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 
 	case_ast_node(us, UsingStmt, node);
 		for_array(i, us->list) {
-			AstNode *decl = unparen_expr(us->list.e[i]);
+			AstNode *decl = unparen_expr(us->list[i]);
 			if (decl->kind == AstNode_ValueDecl) {
 				ssa_build_stmt(p, decl);
 			}
@@ -1973,19 +1974,19 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
 			if (vd->values.count == 0) {
 				for_array(i, vd->names) {
-					AstNode *name = vd->names.e[i];
+					AstNode *name = vd->names[i];
 					if (!ssa_is_blank_ident(name)) {
 						ssa_add_local_for_ident(p, name);
 					}
 				}
 			} else {
-				Array(ssaAddr) lvals = {0};
-				ssaValueArray  inits = {0};
-				array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
-				array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
+				Array<ssaAddr> lvals = {0};
+				Array<ssaValue *>  inits = {0};
+				array_init(&lvals, m->tmp_allocator, vd->names.count);
+				array_init(&inits, m->tmp_allocator, vd->names.count);
 
 				for_array(i, vd->names) {
-					AstNode *name = vd->names.e[i];
+					AstNode *name = vd->names[i];
 					ssaAddr lval = ssa_addr(NULL);
 					if (!ssa_is_blank_ident(name)) {
 						lval = ssa_add_local_for_ident(p, name);
@@ -1995,7 +1996,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 				}
 
 				for_array(i, vd->values) {
-					ssaValue *init = ssa_build_expr(p, vd->values.e[i]);
+					ssaValue *init = ssa_build_expr(p, vd->values[i]);
 					if (init == NULL) { // TODO(bill): remove this
 						continue;
 					}
@@ -2012,7 +2013,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 				}
 
 				for_array(i, inits) {
-					ssa_addr_store(p, lvals.e[i], inits.e[i]);
+					ssa_addr_store(p, lvals[i], inits[i]);
 				}
 			}
 
@@ -2030,11 +2031,11 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 
 		switch (as->op.kind) {
 		case Token_Eq: {
-			Array(ssaAddr) lvals = {0};
+			Array<ssaAddr> lvals = {0};
 			array_init(&lvals, m->tmp_allocator);
 
 			for_array(i, as->lhs) {
-				AstNode *lhs = as->lhs.e[i];
+				AstNode *lhs = as->lhs[i];
 				ssaAddr lval = {0};
 				if (!ssa_is_blank_ident(lhs)) {
 					lval = ssa_build_addr(p, lhs);
@@ -2044,28 +2045,28 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 
 			if (as->lhs.count == as->rhs.count) {
 				if (as->lhs.count == 1) {
-					AstNode *rhs = as->rhs.e[0];
+					AstNode *rhs = as->rhs[0];
 					ssaValue *init = ssa_build_expr(p, rhs);
-					ssa_addr_store(p, lvals.e[0], init);
+					ssa_addr_store(p, lvals[0], init);
 				} else {
-					ssaValueArray inits;
-					array_init_reserve(&inits, m->tmp_allocator, lvals.count);
+					Array<ssaValue *> inits;
+					array_init(&inits, m->tmp_allocator, lvals.count);
 
 					for_array(i, as->rhs) {
-						ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
+						ssaValue *init = ssa_build_expr(p, as->rhs[i]);
 						array_add(&inits, init);
 					}
 
 					for_array(i, inits) {
-						ssa_addr_store(p, lvals.e[i], inits.e[i]);
+						ssa_addr_store(p, lvals[i], inits[i]);
 					}
 				}
 			} else {
-				ssaValueArray inits;
-				array_init_reserve(&inits, m->tmp_allocator, lvals.count);
+				Array<ssaValue *> inits;
+				array_init(&inits, m->tmp_allocator, lvals.count);
 
 				for_array(i, as->rhs) {
-					ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
+					ssaValue *init = ssa_build_expr(p, as->rhs[i]);
 					Type *t = base_type(init->type);
 					// TODO(bill): refactor for code reuse as this is repeated a bit
 					if (t->kind == Type_Tuple) {
@@ -2080,7 +2081,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 				}
 
 				for_array(i, inits) {
-					ssa_addr_store(p, lvals.e[i], inits.e[i]);
+					ssa_addr_store(p, lvals[i], inits[i]);
 				}
 			}
 		} break;
@@ -2091,8 +2092,8 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
 			// +=, -=, etc
 			i32 op = cast(i32)as->op.kind;
 			op += Token_Add - Token_AddEq; // Convert += to +
-			ssaAddr lhs = ssa_build_addr(p, as->lhs.e[0]);
-			ssaValue *value = ssa_build_expr(p, as->rhs.e[0]);
+			ssaAddr lhs = ssa_build_addr(p, as->lhs[0]);
+			ssaValue *value = ssa_build_expr(p, as->rhs[0]);
 			ssa_build_assign_op(p, lhs, value, cast(TokenKind)op);
 		} break;
 		}
@@ -2316,7 +2317,7 @@ void ssa_print_reg_value(gbFile *f, ssaValue *v) {
 
 	for_array(i, v->args) {
 		gb_fprintf(f, " ");
-		ssa_print_value(f, v->args.e[i]);
+		ssa_print_value(f, v->args[i]);
 	}
 
 	if (v->comment_string.len > 0) {
@@ -2335,12 +2336,12 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
 	bool *printed = gb_alloc_array(heap_allocator(), bool, p->value_id+1);
 
 	for_array(i, p->blocks) {
-		ssaBlock *b = p->blocks.e[i];
+		ssaBlock *b = p->blocks[i];
 		gb_fprintf(f, "  b%d:", b->id);
 		if (b->preds.count > 0) {
 			gb_fprintf(f, " <-");
 			for_array(j, b->preds) {
-				ssaBlock *pred = b->preds.e[j].block;
+				ssaBlock *pred = b->preds[j].block;
 				gb_fprintf(f, " b%d", pred->id);
 			}
 		}
@@ -2351,7 +2352,7 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
 
 		isize n = 0;
 		for_array(j, b->values) {
-			ssaValue *v = b->values.e[j];
+			ssaValue *v = b->values[j];
 			if (v->op != ssaOp_Phi) {
 				continue;
 			}
@@ -2363,13 +2364,13 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
 		while (n < b->values.count) {
 			isize m = 0;
 			for_array(j, b->values) {
-				ssaValue *v = b->values.e[j];
+				ssaValue *v = b->values[j];
 				if (printed[v->id]) {
 					continue;
 				}
 				bool skip = false;
 				for_array(k, v->args) {
-					ssaValue *w = v->args.e[k];
+					ssaValue *w = v->args[k];
 					if (w != NULL && w->block == b && !printed[w->id]) {
 						skip = true;
 						break;
@@ -2387,7 +2388,7 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
 			if (m == n) {
 				gb_fprintf(f, "!!!!DepCycle!!!!\n");
 				for_array(k, b->values) {
-					ssaValue *v = b->values.e[k];
+					ssaValue *v = b->values[k];
 					if (printed[v->id]) {
 						continue;
 					}
@@ -2401,14 +2402,14 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
 
 		if (b->kind == ssaBlock_Plain) {
 			GB_ASSERT(b->succs.count == 1);
-			ssaBlock *next = b->succs.e[0].block;
+			ssaBlock *next = b->succs[0].block;
 			gb_fprintf(f, "    ");
 			gb_fprintf(f, "jump b%d", next->id);
 			gb_fprintf(f, "\n");
 		} else if (b->kind == ssaBlock_If) {
 			GB_ASSERT(b->succs.count == 2);
-			ssaBlock *yes = b->succs.e[0].block;
-			ssaBlock *no = b->succs.e[1].block;
+			ssaBlock *yes = b->succs[0].block;
+			ssaBlock *no = b->succs[1].block;
 			gb_fprintf(f, "    ");
 			gb_fprintf(f, "branch v%d, b%d, b%d", b->control->id, yes->id, no->id);
 			gb_fprintf(f, "\n");
@@ -2479,7 +2480,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 		m.tmp_allocator = gb_arena_allocator(&m.tmp_arena);
 		m.allocator     = gb_arena_allocator(&m.arena);
 
-		map_ssa_value_init(&m.values,    heap_allocator());
+		map_init(&m.values,    heap_allocator());
 		array_init(&m.registers,         heap_allocator());
 		array_init(&m.procs,             heap_allocator());
 		array_init(&m.procs_to_generate, heap_allocator());
@@ -2491,21 +2492,21 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 	bool has_win_main = false;
 
 	for_array(i, info->entities.entries) {
-		MapDeclInfoEntry *entry = &info->entities.entries.e[i];
-		Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
+		auto *entry = &info->entities.entries[i];
+		Entity *e = cast(Entity *)entry->key.ptr;
 		String name = e->token.string;
 		if (e->kind == Entity_Variable) {
 			global_variable_max_count++;
 		} else if (e->kind == Entity_Procedure && !e->scope->is_global) {
-			if (e->scope->is_init && str_eq(name, str_lit("main"))) {
+			if (e->scope->is_init && name == "main") {
 				entry_point = e;
 			}
 			if ((e->Procedure.tags & ProcTag_export) != 0 ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->scope->is_file && e->Procedure.link_name.len > 0)) {
-				if (!has_dll_main && str_eq(name, str_lit("DllMain"))) {
+				if (!has_dll_main && name == "DllMain") {
 					has_dll_main = true;
-				} else if (!has_win_main && str_eq(name, str_lit("WinMain"))) {
+				} else if (!has_win_main && name == "WinMain") {
 					has_win_main = true;
 				}
 			}
@@ -2517,7 +2518,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 	m.min_dep_map = generate_minimum_dependency_map(info, entry_point);
 
 	for_array(i, info->entities.entries) {
-		MapDeclInfoEntry *entry = &info->entities.entries.e[i];
+		auto *entry = &info->entities.entries[i];
 		Entity *e = cast(Entity *)entry->key.ptr;
 		String name = e->token.string;
 		DeclInfo *decl = entry->value;
@@ -2527,7 +2528,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 			continue;
 		}
 
-		if (map_entity_get(&m.min_dep_map, hash_pointer(e)) == NULL) {
+		if (map_get(&m.min_dep_map, hash_pointer(e)) == NULL) {
 			// NOTE(bill): Nothing depends upon it so doesn't need to be built
 			continue;
 		}
@@ -2536,7 +2537,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 			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
-			} else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) {
+			} else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {
 			} else {
 				name = ssa_mangle_name(&m, e->token.pos.file, e);
 			}
@@ -2574,8 +2575,8 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 
 			// ssa_module_add_value(m, e, p);
 			// HashKey hash_name = hash_string(name);
-			// if (map_ssa_value_get(&m.members, hash_name) == NULL) {
-				// map_ssa_value_set(&m.members, hash_name, p);
+			// if (map_get(&m.members, hash_name) == NULL) {
+				// map_set(&m.members, hash_name, p);
 			// }
 		} break;
 		}
@@ -2595,7 +2596,7 @@ String ssa_mangle_name(ssaModule *m, String path, Entity *e) {
 	String name = e->token.string;
 	CheckerInfo *info = m->info;
 	gbAllocator a = m->allocator;
-	AstFile *file = *map_ast_file_get(&info->files, hash_string(path));
+	AstFile *file = *map_get(&info->files, hash_string(path));
 
 	char *str = gb_alloc_array(a, char, path.len+1);
 	gb_memmove(str, path.text, path.len);

+ 0 - 1
src/ssa_op.c → src/ssa_op.cpp

@@ -267,7 +267,6 @@ enum ssaOp {
 	SSA_OPS
 #undef SSA_OP
 };
-typedef enum ssaOp ssaOp;
 
 String const ssa_op_strings[] = {
 #define SSA_OP(k) {cast(u8 *)#k, gb_size_of(#k)-1},

+ 66 - 33
src/string.c → src/string.cpp

@@ -1,5 +1,5 @@
-gb_global gbArena string_buffer_arena = {0};
-gb_global gbAllocator string_buffer_allocator = {0};
+gb_global gbArena string_buffer_arena = {};
+gb_global gbAllocator string_buffer_allocator = {};
 
 void init_string_buffer_memory(void) {
 	// NOTE(bill): This should be enough memory for file systems
@@ -9,21 +9,38 @@ void init_string_buffer_memory(void) {
 
 
 // NOTE(bill): Used for UTF-8 strings
-typedef struct String {
+struct String {
 	u8 *  text;
 	isize len;
-} String;
+
+	u8 &operator[](isize i) {
+		GB_ASSERT(0 <= i && i < len);
+		return text[i];
+	}
+	u8 const &operator[](isize i) const {
+		GB_ASSERT(0 <= i && i < len);
+		return text[i];
+	}
+};
 // NOTE(bill): used for printf style arguments
 #define LIT(x) ((int)(x).len), (x).text
 #define STR_LIT(c_str) {cast(u8 *)c_str, gb_size_of(c_str)-1}
-#define str_lit(c_str) (String){cast(u8 *)c_str, gb_size_of(c_str)-1}
+#define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1}
 
 
 // NOTE(bill): String16 is only used for Windows due to its file directories
-typedef struct String16 {
+struct String16 {
 	wchar_t *text;
 	isize    len;
-} String16;
+	wchar_t &operator[](isize i) {
+		GB_ASSERT(0 <= i && i < len);
+		return text[i];
+	}
+	wchar_t const &operator[](isize i) const {
+		GB_ASSERT(0 <= i && i < len);
+		return text[i];
+	}
+};
 
 
 gb_inline String make_string(u8 *text, isize len) {
@@ -56,8 +73,8 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
 	if (a.len == b.len) {
 		isize i;
 		for (i = 0; i < a.len; i++) {
-			char x = cast(char)a.text[i];
-			char y = cast(char)b.text[i];
+			char x = cast(char)a[i];
+			char y = cast(char)b[i];
 			if (gb_char_to_lower(x) != gb_char_to_lower(y))
 				return false;
 		}
@@ -88,16 +105,16 @@ int string_compare(String x, String y) {
 		for (; curr_block < fast; curr_block++) {
 			if (la[curr_block] ^ lb[curr_block]) {
 				for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
-					if (x.text[pos] ^ y.text[pos]) {
-						return cast(int)x.text[pos] - cast(int)y.text[pos];
+					if (x[pos] ^ y[pos]) {
+						return cast(int)x[pos] - cast(int)y[pos];
 					}
 				}
 			}
 		}
 
 		for (; offset < n; offset++) {
-			if (x.text[offset] ^ y.text[offset]) {
-				return cast(int)x.text[offset] - cast(int)y.text[offset];
+			if (x[offset] ^ y[offset]) {
+				return cast(int)x[offset] - cast(int)y[offset];
 			}
 		}
 	}
@@ -117,13 +134,29 @@ gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0;
 gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0;    }
 gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0;    }
 
+bool operator == (String a, String b) { return str_eq(a, b); }
+bool operator != (String a, String b) { return str_ne(a, b); }
+bool operator <  (String a, String b) { return str_lt(a, b); }
+bool operator >  (String a, String b) { return str_gt(a, b); }
+bool operator <= (String a, String b) { return str_le(a, b); }
+bool operator >= (String a, String b) { return str_ge(a, b); }
+
+template <isize N> bool operator == (String a, char const (&b)[N]) { return str_eq(a, make_string(cast(u8 *)b, N-1)); }
+template <isize N> bool operator != (String a, char const (&b)[N]) { return str_ne(a, make_string(cast(u8 *)b, N-1)); }
+template <isize N> bool operator <  (String a, char const (&b)[N]) { return str_lt(a, make_string(cast(u8 *)b, N-1)); }
+template <isize N> bool operator >  (String a, char const (&b)[N]) { return str_gt(a, make_string(cast(u8 *)b, N-1)); }
+template <isize N> bool operator <= (String a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); }
+template <isize N> bool operator >= (String a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); }
+
+
+
 gb_inline bool str_has_prefix(String s, String prefix) {
 	isize i;
 	if (prefix.len < s.len) {
 		return false;
 	}
 	for (i = 0; i < prefix.len; i++) {
-		if (s.text[i] != prefix.text[i]) {
+		if (s[i] != prefix[i]) {
 			return false;
 		}
 	}
@@ -135,9 +168,9 @@ gb_inline isize string_extension_position(String str) {
 	isize i = str.len;
 	bool seen_dot = false;
 	while (i --> 0) {
-		if (str.text[i] == GB_PATH_SEPARATOR)
+		if (str[i] == GB_PATH_SEPARATOR)
 			break;
-		if (str.text[i] == '.') {
+		if (str[i] == '.') {
 			dot_pos = i;
 			break;
 		}
@@ -147,11 +180,11 @@ gb_inline isize string_extension_position(String str) {
 }
 
 String string_trim_whitespace(String str) {
-	while (str.len > 0 && rune_is_whitespace(str.text[str.len-1])) {
+	while (str.len > 0 && rune_is_whitespace(str[str.len-1])) {
 		str.len--;
 	}
 
-	while (str.len > 0 && rune_is_whitespace(str.text[0])) {
+	while (str.len > 0 && rune_is_whitespace(str[0])) {
 		str.text++;
 		str.len--;
 	}
@@ -166,7 +199,7 @@ gb_inline bool string_has_extension(String str, String ext) {
 	}
 	isize len = str.len;
 	for (isize i = len-1; i >= 0; i--) {
-		if (str.text[i] == '.') {
+		if (str[i] == '.') {
 			break;
 		}
 		len--;
@@ -182,7 +215,7 @@ gb_inline bool string_has_extension(String str, String ext) {
 bool string_contains_char(String s, u8 c) {
 	isize i;
 	for (i = 0; i < s.len; i++) {
-		if (s.text[i] == c)
+		if (s[i] == c)
 			return true;
 	}
 	return false;
@@ -194,8 +227,8 @@ String filename_from_path(String s) {
 		isize j = 0;
 		s.len = i;
 		for (j = i-1; j >= 0; j--) {
-			if (s.text[j] == '/' ||
-				s.text[j] == '\\') {
+			if (s[j] == '/' ||
+				s[j] == '\\') {
 				break;
 			}
 		}
@@ -315,18 +348,18 @@ String string16_to_string(gbAllocator a, String16 s) {
 bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
 	u8 c;
 
-	if (s.text[0] == quote &&
+	if (s[0] == quote &&
 	    (quote == '\'' || quote == '"')) {
 		return false;
-	} else if (s.text[0] >= 0x80) {
+	} else if (s[0] >= 0x80) {
 		Rune r = -1;
 		isize size = gb_utf8_decode(s.text, s.len, &r);
 		*rune = r;
 		*multiple_bytes = true;
 		*tail_string = make_string(s.text+size, s.len-size);
 		return true;
-	} else if (s.text[0] != '\\') {
-		*rune = s.text[0];
+	} else if (s[0] != '\\') {
+		*rune = s[0];
 		*tail_string = make_string(s.text+1, s.len-1);
 		return true;
 	}
@@ -334,7 +367,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 	if (s.len <= 1) {
 		return false;
 	}
-	c = s.text[1];
+	c = s[1];
 	s = make_string(s.text+2, s.len-2);
 
 	switch (c) {
@@ -372,7 +405,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 			return false;
 		}
 		for (i = 0; i < 2; i++) {
-			i32 d = gb_digit_to_int(s.text[i]);
+			i32 d = gb_digit_to_int(s[i]);
 			if (d < 0 || d > 7) {
 				return false;
 			}
@@ -400,7 +433,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 			return false;
 		}
 		for (i = 0; i < count; i++) {
-			i32 d = gb_hex_digit_to_int(s.text[i]);
+			i32 d = gb_hex_digit_to_int(s[i]);
 			if (d < 0) {
 				return false;
 			}
@@ -433,8 +466,8 @@ i32 unquote_string(gbAllocator a, String *s_) {
 	if (n < 2) {
 		return 0;
 	}
-	quote = s.text[0];
-	if (quote != s.text[n-1]) {
+	quote = s[0];
+	if (quote != s[n-1]) {
 		return 0;
 	}
 	s.text += 1;
@@ -471,12 +504,12 @@ i32 unquote_string(gbAllocator a, String *s_) {
 
 
 	{
-		u8 rune_temp[4] = {0};
+		u8 rune_temp[4] = {};
 		isize buf_len = 3*s.len / 2;
 		u8 *buf = gb_alloc_array(a, u8, buf_len);
 		isize offset = 0;
 		while (s.len > 0) {
-			String tail_string = {0};
+			String tail_string = {};
 			Rune r = 0;
 			bool multiple_bytes = false;
 			bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);

+ 10 - 10
src/timings.c → src/timings.cpp

@@ -1,14 +1,14 @@
-typedef struct TimeStamp {
+struct TimeStamp {
 	u64    start;
 	u64    finish;
 	String label;
-} TimeStamp;
+};
 
-typedef struct Timings {
+struct Timings {
 	TimeStamp        total;
-	Array(TimeStamp) sections;
+	Array<TimeStamp> sections;
 	u64              freq;
-} Timings;
+};
 
 
 #if defined(GB_SYSTEM_WINDOWS)
@@ -83,7 +83,7 @@ TimeStamp make_time_stamp(String label) {
 }
 
 void timings_init(Timings *t, String label, isize buffer_size) {
-	array_init_reserve(&t->sections, heap_allocator(), buffer_size);
+	array_init(&t->sections, heap_allocator(), buffer_size);
 	t->total = make_time_stamp(label);
 	t->freq  = time_stamp__freq();
 }
@@ -94,7 +94,7 @@ void timings_destroy(Timings *t) {
 
 void timings__stop_current_section(Timings *t) {
 	if (t->sections.count > 0) {
-		t->sections.e[t->sections.count-1].finish = time_stamp_time_now();
+		t->sections[t->sections.count-1].finish = time_stamp_time_now();
 	}
 }
 
@@ -110,14 +110,14 @@ f64 time_stamp_as_ms(TimeStamp ts, u64 freq) {
 
 void timings_print_all(Timings *t) {
 	char const SPACES[] = "                                                                ";
-	isize max_len, i;
+	isize max_len;
 
 	timings__stop_current_section(t);
 	t->total.finish = time_stamp_time_now();
 
 	max_len = t->total.label.len;
 	for_array(i, t->sections) {
-		TimeStamp ts = t->sections.e[i];
+		TimeStamp ts = t->sections[i];
 		max_len = gb_max(max_len, ts.label.len);
 	}
 
@@ -129,7 +129,7 @@ void timings_print_all(Timings *t) {
 	          time_stamp_as_ms(t->total, t->freq));
 
 	for_array(i, t->sections) {
-		TimeStamp ts = t->sections.e[i];
+		TimeStamp ts = t->sections[i];
 		gb_printf("%.*s%.*s - %.3f ms\n",
 		          LIT(ts.label),
 	              cast(int)(max_len-ts.label.len), SPACES,

+ 22 - 22
src/tokenizer.c → src/tokenizer.cpp

@@ -117,11 +117,11 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
 	TOKEN_KIND(Token_Count, "")
 
-typedef enum TokenKind {
+enum TokenKind {
 #define TOKEN_KIND(e, s) e
 	TOKEN_KINDS
 #undef TOKEN_KIND
-} TokenKind;
+};
 
 String const token_strings[] = {
 #define TOKEN_KIND(e, s) {cast(u8 *)s, gb_size_of(s)-1}
@@ -130,11 +130,11 @@ String const token_strings[] = {
 };
 
 
-typedef struct TokenPos {
+struct TokenPos {
 	String file;
 	isize  line;
 	isize  column;
-} TokenPos;
+};
 
 i32 token_pos_cmp(TokenPos a, TokenPos b) {
 	if (a.line == b.line) {
@@ -152,11 +152,11 @@ bool token_pos_eq(TokenPos a, TokenPos b) {
 	return token_pos_cmp(a, b) == 0;
 }
 
-typedef struct Token {
+struct Token {
 	TokenKind kind;
 	String string;
 	TokenPos pos;
-} Token;
+};
 
 Token empty_token = {Token_Invalid};
 Token blank_token = {Token_Ident, {cast(u8 *)"_", 1}};
@@ -167,12 +167,12 @@ Token make_token_ident(String s) {
 }
 
 
-typedef struct ErrorCollector {
+struct ErrorCollector {
 	TokenPos prev;
 	i64     count;
 	i64     warning_count;
 	gbMutex mutex;
-} ErrorCollector;
+};
 
 gb_global ErrorCollector global_error_collector;
 
@@ -306,7 +306,7 @@ gb_inline bool token_is_shift(TokenKind t) {
 gb_inline void print_token(Token t) { gb_printf("%.*s\n", LIT(t.string)); }
 
 
-typedef enum TokenizerInitError {
+enum TokenizerInitError {
 	TokenizerInit_None,
 
 	TokenizerInit_Invalid,
@@ -315,18 +315,18 @@ typedef enum TokenizerInitError {
 	TokenizerInit_Empty,
 
 	TokenizerInit_Count,
-} TokenizerInitError;
+};
 
 
-typedef struct TokenizerState {
+struct TokenizerState {
 	Rune  curr_rune;   // current character
 	u8 *  curr;        // character pos
 	u8 *  read_curr;   // pos from start
 	u8 *  line;        // current line pos
 	isize line_count;
-} TokenizerState;
+};
 
-typedef struct Tokenizer {
+struct Tokenizer {
 	String fullpath;
 	u8 *start;
 	u8 *end;
@@ -338,12 +338,12 @@ typedef struct Tokenizer {
 	isize line_count;
 
 	isize error_count;
-	Array(String) allocated_strings;
-} Tokenizer;
+	Array<String> allocated_strings;
+};
 
 
 TokenizerState save_tokenizer_state(Tokenizer *t) {
-	TokenizerState state = {0};
+	TokenizerState state = {};
 	state.curr_rune  = t->curr_rune;
 	state.curr       = t->curr;
 	state.read_curr  = t->read_curr;
@@ -435,7 +435,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
 
 		array_init(&t->allocated_strings, heap_allocator());
 	} else {
-		gbFile f = {0};
+		gbFile f = {};
 		gbFileError file_err = gb_file_open(&f, c_str);
 
 		switch (file_err) {
@@ -460,7 +460,7 @@ gb_inline void destroy_tokenizer(Tokenizer *t) {
 		gb_free(heap_allocator(), t->start);
 	}
 	for_array(i, t->allocated_strings) {
-		gb_free(heap_allocator(), t->allocated_strings.e[i].text);
+		gb_free(heap_allocator(), t->allocated_strings[i].text);
 	}
 	array_free(&t->allocated_strings);
 }
@@ -492,7 +492,7 @@ gb_inline void scan_mantissa(Tokenizer *t, i32 base) {
 }
 
 Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
-	Token token = {0};
+	Token token = {};
 	token.kind = Token_Integer;
 	token.string = make_string(t->curr, 1);
 	token.pos.file = t->fullpath;
@@ -742,7 +742,7 @@ bool tokenizer_find_line_end(Tokenizer *t) {
 Token tokenizer_get_token(Tokenizer *t) {
 	tokenizer_skip_whitespace(t);
 
-	Token token = {0};
+	Token token = {};
 	token.string = make_string(t->curr, 1);
 	token.pos.file = t->fullpath;
 	token.pos.line = t->line_count;
@@ -760,7 +760,7 @@ Token tokenizer_get_token(Tokenizer *t) {
 		// NOTE(bill): All keywords are > 1
 		if (token.string.len > 1) {
 			for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
-				if (str_eq(token.string, token_strings[k])) {
+				if (token.string == token_strings[k]) {
 					token.kind = cast(TokenKind)k;
 					break;
 				}
@@ -963,7 +963,7 @@ Token tokenizer_get_token(Tokenizer *t) {
 
 		default:
 			if (curr_rune != GB_RUNE_BOM) {
-				u8 str[4] = {0};
+				u8 str[4] = {};
 				int len = cast(int)gb_utf8_encode_rune(str, curr_rune);
 				tokenizer_err(t, "Illegal character: %.*s (%d) ", len, str, curr_rune);
 			}

+ 55 - 55
src/types.c → src/types.cpp

@@ -1,6 +1,6 @@
-typedef struct Scope Scope;
+struct Scope;
 
-typedef enum BasicKind {
+enum BasicKind {
 	Basic_Invalid,
 	Basic_bool,
 	Basic_i8,
@@ -41,9 +41,9 @@ typedef enum BasicKind {
 	Basic_COUNT,
 
 	Basic_byte = Basic_u8,
-} BasicKind;
+};
 
-typedef enum BasicFlag {
+enum BasicFlag {
 	BasicFlag_Boolean     = GB_BIT(0),
 	BasicFlag_Integer     = GB_BIT(1),
 	BasicFlag_Unsigned    = GB_BIT(2),
@@ -57,16 +57,16 @@ typedef enum BasicFlag {
 	BasicFlag_Numeric      = BasicFlag_Integer | BasicFlag_Float   | BasicFlag_Complex,
 	BasicFlag_Ordered      = BasicFlag_Integer | BasicFlag_Float   | BasicFlag_String  | BasicFlag_Pointer | BasicFlag_Rune,
 	BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String  | BasicFlag_Pointer | BasicFlag_Rune,
-} BasicFlag;
+};
 
-typedef struct BasicType {
+struct BasicType {
 	BasicKind kind;
 	u32       flags;
 	i64       size; // -1 if arch. dep.
 	String    name;
-} BasicType;
+};
 
-typedef enum TypeRecordKind {
+enum TypeRecordKind {
 	TypeRecord_Invalid,
 
 	TypeRecord_Struct,
@@ -75,9 +75,9 @@ typedef enum TypeRecordKind {
 	TypeRecord_Enum,
 
 	TypeRecord_Count,
-} TypeRecordKind;
+};
 
-typedef struct TypeRecord {
+struct TypeRecord {
 	TypeRecordKind kind;
 
 	// All record types
@@ -109,7 +109,7 @@ typedef struct TypeRecord {
 	Entity * enum_count;
 	Entity * enum_min_value;
 	Entity * enum_max_value;
-} TypeRecord;
+};
 
 #define TYPE_KINDS                                        \
 	TYPE_KIND(Basic,   BasicType)                         \
@@ -164,13 +164,13 @@ typedef struct TypeRecord {
 
 
 
-typedef enum TypeKind {
+enum TypeKind {
 	Type_Invalid,
 #define TYPE_KIND(k, ...) GB_JOIN2(Type_, k),
 	TYPE_KINDS
 #undef TYPE_KIND
 	Type_Count,
-} TypeKind;
+};
 
 String const type_strings[] = {
 	{cast(u8 *)"Invalid", gb_size_of("Invalid")},
@@ -183,7 +183,7 @@ String const type_strings[] = {
 	TYPE_KINDS
 #undef TYPE_KIND
 
-typedef struct Type {
+struct Type {
 	TypeKind kind;
 	union {
 #define TYPE_KIND(k, ...) GB_JOIN2(Type, k) k;
@@ -191,19 +191,19 @@ typedef struct Type {
 #undef TYPE_KIND
 	};
 	bool failure;
-} Type;
+};
 
 
 // TODO(bill): Should I add extra information here specifying the kind of selection?
 // e.g. field, constant, vector field, type field, etc.
-typedef struct Selection {
-	Entity *  entity;
-	Array_i32 index;
-	bool      indirect; // Set if there was a pointer deref anywhere down the line
-} Selection;
+struct Selection {
+	Entity *   entity;
+	Array<i32> index;
+	bool       indirect; // Set if there was a pointer deref anywhere down the line
+};
 Selection empty_selection = {0};
 
-Selection make_selection(Entity *entity, Array_i32 index, bool indirect) {
+Selection make_selection(Entity *entity, Array<i32> index, bool indirect) {
 	Selection s = {entity, index, indirect};
 	return s;
 }
@@ -212,10 +212,10 @@ void selection_add_index(Selection *s, isize index) {
 	// IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
 	// of heap allocation
 	// TODO(bill): Find a way to use a backing buffer for initial use as the general case is probably .count<3
-	if (s->index.e == NULL) {
+	if (s->index.data == NULL) {
 		array_init(&s->index, heap_allocator());
 	}
-	array_add(&s->index, index);
+	array_add(&s->index, cast(i32)index);
 }
 
 
@@ -1025,7 +1025,7 @@ bool are_types_identical(Type *x, Type *y) {
 							if (!are_types_identical(xf->type, yf->type)) {
 								return false;
 							}
-							if (str_ne(xf->token.string, yf->token.string)) {
+							if (xf->token.string != yf->token.string) {
 								return false;
 							}
 							bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
@@ -1039,7 +1039,7 @@ bool are_types_identical(Type *x, Type *y) {
 							if (!are_types_identical(x->Record.variants[i]->type, y->Record.variants[i]->type)) {
 								return false;
 							}
-							if (str_ne(x->Record.variants[i]->token.string, y->Record.variants[i]->token.string)) {
+							if (x->Record.variants[i]->token.string != y->Record.variants[i]->token.string) {
 								return false;
 							}
 						}
@@ -1199,7 +1199,7 @@ bool is_type_cte_safe(Type *type) {
 	return false;
 }
 
-typedef enum ProcTypeOverloadKind {
+enum ProcTypeOverloadKind {
 	ProcOverload_Identical, // The types are identical
 
 	ProcOverload_CallingConvention,
@@ -1211,7 +1211,7 @@ typedef enum ProcTypeOverloadKind {
 
 	ProcOverload_NotProcedure,
 
-} ProcTypeOverloadKind;
+};
 
 ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
 	if (x == NULL && y == NULL) return ProcOverload_NotProcedure;
@@ -1297,9 +1297,9 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
 			Entity *f = type->Record.fields[i];
 			if (f->kind == Entity_Variable) {
 				if (f->Variable.field_src_index == index) {
-					Array_i32 sel_array = {0};
+					Array<i32> sel_array = {0};
 					array_init_count(&sel_array, a, 1);
-					sel_array.e[0] = i;
+					sel_array[0] = i;
 					return make_selection(f, sel_array, false);
 				}
 			}
@@ -1309,18 +1309,18 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
 		for (isize i = 0; i < max_count; i++) {
 			Entity *f = type->Tuple.variables[i];
 			if (i == index) {
-				Array_i32 sel_array = {0};
+				Array<i32> sel_array = {0};
 				array_init_count(&sel_array, a, 1);
-				sel_array.e[0] = i;
+				sel_array[0] = i;
 				return make_selection(f, sel_array, false);
 			}
 		}
 		break;
 
 	case Type_BitField: {
-		Array_i32 sel_array = {0};
+		Array<i32> sel_array = {0};
 		array_init_count(&sel_array, a, 1);
-		sel_array.e[0] = cast(i32)index;
+		sel_array[0] = cast(i32)index;
 		return make_selection(type->BitField.fields[index], sel_array, false);
 	} break;
 
@@ -1337,7 +1337,7 @@ gb_global Entity *entity__any_type_info  = NULL;
 Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
 	GB_ASSERT(type_ != NULL);
 
-	if (str_eq(field_name, str_lit("_"))) {
+	if (field_name == "_") {
 		return empty_selection;
 	}
 
@@ -1362,11 +1362,11 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 1);
 			}
 
-			if (str_eq(field_name, data_str)) {
+			if (field_name == data_str) {
 				selection_add_index(&sel, 0);
 				sel.entity = entity__any_data;;
 				return sel;
-			} else if (str_eq(field_name, type_info_str)) {
+			} else if (field_name == type_info_str) {
 				selection_add_index(&sel, 1);
 				sel.entity = entity__any_type_info;
 				return sel;
@@ -1382,7 +1382,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 			switch (type->Vector.count) {
 			#define _VECTOR_FIELD_CASE(_length, _name) \
 			case (_length): \
-				if (str_eq(field_name, str_lit(_name))) { \
+				if (field_name == _name) { \
 					selection_add_index(&sel, (_length)-1); \
 					sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
 					return sel; \
@@ -1403,7 +1403,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 	if (is_type) {
 		if (type->kind == Type_Record) {
 			if (type->Record.names != NULL &&
-			    str_eq(field_name, str_lit("names"))) {
+			    field_name == "names") {
 				sel.entity = type->Record.names;
 				return sel;
 			}
@@ -1415,7 +1415,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				GB_ASSERT(f->kind == Entity_TypeName);
 				String str = f->token.string;
 
-				if (str_eq(str, field_name)) {
+				if (str == field_name) {
 					sel.entity = f;
 					// selection_add_index(&sel, i);
 					return sel;
@@ -1424,15 +1424,15 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 		} else if (is_type_enum(type)) {
 			// NOTE(bill): These may not have been added yet, so check in case
 			if (type->Record.enum_count != NULL) {
-				if (str_eq(field_name, str_lit("count"))) {
+				if (field_name == "count") {
 					sel.entity = type->Record.enum_count;
 					return sel;
 				}
-				if (str_eq(field_name, str_lit("min_value"))) {
+				if (field_name == "min_value") {
 					sel.entity = type->Record.enum_min_value;
 					return sel;
 				}
-				if (str_eq(field_name, str_lit("max_value"))) {
+				if (field_name == "max_value") {
 					sel.entity = type->Record.enum_max_value;
 					return sel;
 				}
@@ -1443,7 +1443,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				GB_ASSERT(f->kind == Entity_Constant);
 				String str = f->token.string;
 
-				if (str_eq(field_name, str)) {
+				if (field_name == str) {
 					sel.entity = f;
 					// selection_add_index(&sel, i);
 					return sel;
@@ -1457,7 +1457,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				continue;
 			}
 			String str = f->token.string;
-			if (str_eq(field_name, str)) {
+			if (field_name == str) {
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				sel.entity = f;
 				return sel;
@@ -1479,7 +1479,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 			}
 		}
 		if (type->Record.kind == TypeRecord_Union) {
-			if (str_eq(field_name, str_lit("__tag"))) {
+			if (field_name == "__tag") {
 				Entity *e = type->Record.union__tag;
 				GB_ASSERT(e != NULL);
 				selection_add_index(&sel, -1); // HACK(bill): Leaky memory
@@ -1496,7 +1496,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 			}
 
 			String str = f->token.string;
-			if (str_eq(field_name, str)) {
+			if (field_name == str) {
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				sel.entity = f;
 				return sel;
@@ -1508,10 +1508,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 }
 
 
-typedef struct TypePath {
-	Array(Type *) path; // Entity_TypeName;
+struct TypePath {
+	Array<Type *> path; // Entity_TypeName;
 	bool failure;
-} TypePath;
+};
 
 void type_path_init(TypePath *tp) {
 	// TODO(bill): Use an allocator that uses a backing array if it can and then use alternative allocator when exhausted
@@ -1526,7 +1526,7 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) {
 	GB_ASSERT(tp != NULL);
 
 	GB_ASSERT(start_index < tp->path.count);
-	Type *t = tp->path.e[start_index];
+	Type *t = tp->path[start_index];
 	GB_ASSERT(t != NULL);
 
 	GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
@@ -1534,7 +1534,7 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) {
 	error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
 	// NOTE(bill): Print cycle, if it's deep enough
 	for (isize j = start_index; j < tp->path.count; j++) {
-		Type *t = tp->path.e[j];
+		Type *t = tp->path[j];
 		GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
 		Entity *e = t->Named.type_name;
 		error(e->token, "\t%.*s refers to", LIT(t->Named.name));
@@ -1549,7 +1549,7 @@ TypePath *type_path_push(TypePath *tp, Type *t) {
 	GB_ASSERT(tp != NULL);
 
 	for (isize i = 0; i < tp->path.count; i++) {
-		if (tp->path.e[i] == t) {
+		if (tp->path[i] == t) {
 			type_path_print_illegal_cycle(tp, i);
 		}
 	}
@@ -1617,7 +1617,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 	switch (t->kind) {
 	case Type_Basic: {
 		GB_ASSERT(is_type_typed(t));
-		switch (t->kind) {
+		switch (t->Basic.kind) {
 		case Basic_string: return build_context.word_size;
 		case Basic_any:    return build_context.word_size;
 
@@ -2082,7 +2082,7 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
 	Type *t = type;
 	i64 offset = 0;
 	for_array(i, sel.index) {
-		isize index = sel.index.e[i];
+		isize index = sel.index[i];
 		t = base_type(t);
 		offset += type_offset_of(allocator, t, index);
 		if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
@@ -2291,7 +2291,7 @@ gbString write_type_to_string(gbString str, Type *type) {
 					}
 					if (var->flags&EntityFlag_Ellipsis) {
 						Type *slice = base_type(var->type);
-						str = gb_string_appendc(str, "...");
+						str = gb_string_appendc(str, "..");
 						GB_ASSERT(is_type_slice(var->type));
 						str = write_type_to_string(str, slice->Slice.elem);
 					} else {

+ 2 - 1
src/unicode.c → src/unicode.cpp

@@ -1,9 +1,10 @@
 #pragma warning(push)
 #pragma warning(disable: 4245)
 
+extern "C" {
 // #include "utf8proc/utf8proc.h"
 #include "utf8proc/utf8proc.c"
-
+}
 #pragma warning(pop)
 
 

+ 8 - 12
src/utf8proc/utf8proc.c

@@ -383,7 +383,7 @@ UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
 }
 
 UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) {
-  return utf8proc_get_property(c)->category;
+  return cast(utf8proc_category_t)utf8proc_get_property(c)->category;
 }
 
 UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
@@ -393,15 +393,15 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
 
 #define utf8proc_decompose_lump(replacement_uc) \
   return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
-  options & ~UTF8PROC_LUMP, last_boundclass)
+  (utf8proc_option_t)(options & ~UTF8PROC_LUMP), last_boundclass)
 
 UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
   const utf8proc_property_t *property;
-  utf8proc_propval_t category;
+  utf8proc_category_t category;
   utf8proc_int32_t hangul_sindex;
   if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED;
   property = unsafe_get_property(uc);
-  category = property->category;
+  category = cast(utf8proc_category_t)property->category;
   hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
   if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
     if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) {
@@ -728,28 +728,24 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
 
 UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) {
   utf8proc_uint8_t *retval;
-  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
-    UTF8PROC_DECOMPOSE);
+  utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_DECOMPOSE));
   return retval;
 }
 
 UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) {
   utf8proc_uint8_t *retval;
-  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
-    UTF8PROC_COMPOSE);
+  utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_COMPOSE));
   return retval;
 }
 
 UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) {
   utf8proc_uint8_t *retval;
-  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
-    UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
+  utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_DECOMPOSE|UTF8PROC_COMPAT));
   return retval;
 }
 
 UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) {
   utf8proc_uint8_t *retval;
-  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
-    UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
+  utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_COMPOSE|UTF8PROC_COMPAT));
   return retval;
 }

Some files were not shown because too many files changed in this diff