Browse Source

Update `String` to use overloading

Ginger Bill 8 years ago
parent
commit
13deb4706c
17 changed files with 213 additions and 186 deletions
  1. 13 13
      src/build_settings.cpp
  2. 2 2
      src/check_decl.cpp
  3. 29 29
      src/check_expr.cpp
  4. 7 7
      src/check_stmt.cpp
  5. 12 12
      src/checker.cpp
  6. 1 1
      src/entity.cpp
  7. 3 1
      src/exact_value.cpp
  8. 4 4
      src/integer128.cpp
  9. 11 11
      src/ir.cpp
  10. 4 4
      src/ir_print.cpp
  11. 5 13
      src/main.cpp
  12. 1 1
      src/map.cpp
  13. 40 40
      src/parser.cpp
  14. 8 8
      src/ssa.cpp
  15. 57 24
      src/string.cpp
  16. 1 1
      src/tokenizer.cpp
  17. 15 15
      src/types.cpp

+ 13 - 13
src/build_settings.cpp

@@ -65,7 +65,7 @@ String odin_root_dir(void) {
 	GetModuleFileNameW(NULL, text, len);
 	GetModuleFileNameW(NULL, text, len);
 	path = string16_to_string(heap_allocator(), make_string16(text, len));
 	path = string16_to_string(heap_allocator(), make_string16(text, len));
 	for (i = path.len-1; i >= 0; i--) {
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 		if (c == '/' || c == '\\') {
 			break;
 			break;
 		}
 		}
@@ -118,7 +118,7 @@ String odin_root_dir(void) {
 
 
 	path = make_string(text, len);
 	path = make_string(text, len);
 	for (i = path.len-1; i >= 0; i--) {
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 		if (c == '/' || c == '\\') {
 			break;
 			break;
 		}
 		}
@@ -175,7 +175,7 @@ String odin_root_dir(void) {
 
 
 	path = make_string(text, len);
 	path = make_string(text, len);
 	for (i = path.len-1; i >= 0; i--) {
 	for (i = path.len-1; i >= 0; i--) {
-		u8 c = path.text[i];
+		u8 c = path[i];
 		if (c == '/' || c == '\\') {
 		if (c == '/' || c == '\\') {
 			break;
 			break;
 		}
 		}
@@ -200,10 +200,10 @@ String path_to_fullpath(gbAllocator a, String s) {
 	String16 string16 = string_to_string16(string_buffer_allocator, s);
 	String16 string16 = string_to_string16(string_buffer_allocator, s);
 	String result = {0};
 	String result = {0};
 
 
-	DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
+	DWORD len = GetFullPathNameW(&string16[0], 0, NULL, NULL);
 	if (len != 0) {
 	if (len != 0) {
 		wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
 		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;
 		text[len] = 0;
 		result = string16_to_string(a, make_string16(text, len));
 		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)
 #elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
 String path_to_fullpath(gbAllocator a, String s) {
 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("");
 	if(p == NULL) return make_string_c("");
 
 
 	return make_string_c(p);
 	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);
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
 
 
 	isize i = 0;
 	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';
 	str[str_len] = '\0';
 	res = path_to_fullpath(a, make_string(str, str_len));
 	res = path_to_fullpath(a, make_string(str, str_len));
 	gb_free(heap_allocator(), str);
 	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;
 	isize str_len = module_dir.len + core_len + path.len;
 	u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
 	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, 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';
 	str[str_len] = '\0';
 
 
 	res = path_to_fullpath(a, make_string(str, str_len));
 	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
 	// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
 	// an architecture option. All compilation done on MacOS must be x64.
 	// 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_X64 ""
 	#define LINK_FLAG_X86 ""
 	#define LINK_FLAG_X86 ""
@@ -311,12 +311,12 @@ void init_build_context(void) {
 	#define LINK_FLAG_X86 "-arch x86"
 	#define LINK_FLAG_X86 "-arch x86"
 	#endif
 	#endif
 
 
-	if (str_eq(bc->ODIN_ARCH, str_lit("amd64"))) {
+	if (bc->ODIN_ARCH == "amd64") {
 		bc->word_size = 8;
 		bc->word_size = 8;
 		bc->max_align = 16;
 		bc->max_align = 16;
 		bc->llc_flags = str_lit("-march=x86-64 ");
 		bc->llc_flags = str_lit("-march=x86-64 ");
 		bc->link_flags = str_lit(LINK_FLAG_X64 " ");
 		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->word_size = 4;
 		bc->max_align = 8;
 		bc->max_align = 8;
 		bc->llc_flags = str_lit("-march=x86 ");
 		bc->llc_flags = str_lit("-march=x86 ");

+ 2 - 2
src/check_decl.cpp

@@ -274,7 +274,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 	bool is_require_results = (pd->tags & ProcTag_require_results) != 0;
 	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) {
 		if (proc_type != NULL) {
 			TypeProc *pt = &proc_type->Proc;
 			TypeProc *pt = &proc_type->Proc;
 			if (pt->param_count != 0 ||
 			if (pt->param_count != 0 ||
@@ -334,7 +334,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
 			String name = foreign_library->Ident.string;
 			String name = foreign_library->Ident.string;
 			Entity *found = scope_lookup_entity(c->context.scope, name);
 			Entity *found = scope_lookup_entity(c->context.scope, name);
 			if (found == NULL) {
 			if (found == NULL) {
-				if (str_eq(name, str_lit("_"))) {
+				if (name == "_") {
 					error_node(foreign_library, "`_` cannot be used as a value type");
 					error_node(foreign_library, "`_` cannot be used as a value type");
 				} else {
 				} else {
 					error_node(foreign_library, "Undeclared name: %.*s", LIT(name));
 					error_node(foreign_library, "Undeclared name: %.*s", LIT(name));

+ 29 - 29
src/check_expr.cpp

@@ -427,9 +427,9 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls,
 
 
 			Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)field_index);
 			Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, is_using, cast(i32)field_index);
 			e->identifier = name;
 			e->identifier = name;
-			if (str_eq(name_token.string, str_lit("_"))) {
+			if (name_token.string == "_") {
 				fields[field_index++] = e;
 				fields[field_index++] = e;
-			} else if (str_eq(name_token.string, str_lit("__tag"))) {
+			} else if (name_token.string == "__tag") {
 				error_node(name, "`__tag` is a reserved identifier for fields");
 				error_node(name, "`__tag` is a reserved identifier for fields");
 			} else {
 			} else {
 				HashKey key = hash_string(name_token.string);
 				HashKey key = hash_string(name_token.string);
@@ -729,7 +729,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
 		type->Named.type_name = e;
 		type->Named.type_name = e;
 		add_entity(c, c->context.scope, f->name, e);
 		add_entity(c, c->context.scope, f->name, e);
 
 
-		if (str_eq(name_token.string, str_lit("_"))) {
+		if (name_token.string == "_") {
 			error(name_token, "`_` cannot be used a union subtype");
 			error(name_token, "`_` cannot be used a union subtype");
 			continue;
 			continue;
 		}
 		}
@@ -857,21 +857,21 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
 
 
 
 
 		// NOTE(bill): Skip blank identifiers
 		// NOTE(bill): Skip blank identifiers
-		if (str_eq(name, str_lit("_"))) {
+		if (name == "_") {
 			continue;
 			continue;
-		} else if (str_eq(name, str_lit("count"))) {
+		} else if (name == "count") {
 			error_node(field, "`count` is a reserved identifier for enumerations");
 			error_node(field, "`count` is a reserved identifier for enumerations");
 			continue;
 			continue;
-		} else if (str_eq(name, str_lit("min_value"))) {
+		} else if (name == "min_value") {
 			error_node(field, "`min_value` is a reserved identifier for enumerations");
 			error_node(field, "`min_value` is a reserved identifier for enumerations");
 			continue;
 			continue;
-		} else if (str_eq(name, str_lit("max_value"))) {
+		} else if (name == "max_value") {
 			error_node(field, "`max_value` is a reserved identifier for enumerations");
 			error_node(field, "`max_value` is a reserved identifier for enumerations");
 			continue;
 			continue;
-		} else if (str_eq(name, str_lit("names"))) {
+		} else if (name == "names") {
 			error_node(field, "`names` is a reserved identifier for enumerations");
 			error_node(field, "`names` is a reserved identifier for enumerations");
 			continue;
 			continue;
-		}/*  else if (str_eq(name, str_lit("base_type"))) {
+		}/*  else if (name == "base_type") {
 			error_node(field, "`base_type` is a reserved identifier for enumerations");
 			error_node(field, "`base_type` is a reserved identifier for enumerations");
 			continue;
 			continue;
 		} */
 		} */
@@ -966,7 +966,7 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
 		e->flags |= EntityFlag_BitFieldValue;
 		e->flags |= EntityFlag_BitFieldValue;
 
 
 		HashKey key = hash_string(name);
 		HashKey key = hash_string(name);
-		if (str_ne(name, str_lit("_")) &&
+		if (name != "_" &&
 		    map_entity_get(&entity_map, key) != NULL) {
 		    map_entity_get(&entity_map, key) != NULL) {
 			error_node(ident, "`%.*s` is already declared in this bit field", LIT(name));
 			error_node(ident, "`%.*s` is already declared in this bit field", LIT(name));
 		} else {
 		} else {
@@ -1164,15 +1164,15 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
 
 
 	for (isize i = 0; i < variable_index; i++) {
 	for (isize i = 0; i < variable_index; i++) {
 		String x = variables[i]->token.string;
 		String x = variables[i]->token.string;
-		if (x.len == 0 || str_eq(x, str_lit("_"))) {
+		if (x.len == 0 || x == "_") {
 			continue;
 			continue;
 		}
 		}
 		for (isize j = i+1; j < variable_index; j++) {
 		for (isize j = i+1; j < variable_index; j++) {
 			String y = variables[j]->token.string;
 			String y = variables[j]->token.string;
-			if (y.len == 0 || str_eq(y, str_lit("_"))) {
+			if (y.len == 0 || y == "_") {
 				continue;
 				continue;
 			}
 			}
-			if (str_eq(x, y)) {
+			if (x == y) {
 				error(variables[j]->token, "Duplicate return value name `%.*s`", LIT(y));
 				error(variables[j]->token, "Duplicate return value name `%.*s`", LIT(y));
 			}
 			}
 		}
 		}
@@ -1187,7 +1187,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
 Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 	Type *new_type = original_type;
 	Type *new_type = original_type;
 
 
-	if (str_eq(build_context.ODIN_OS, str_lit("windows"))) {
+	if (build_context.ODIN_OS == "windows") {
 		// NOTE(bill): Changing the passing parameter value type is to match C's ABI
 		// NOTE(bill): Changing the passing parameter value type is to match C's ABI
 		// IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment
 		// IMPORTANT TODO(bill): This only matches the ABI on MSVC at the moment
 		// SEE: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
 		// SEE: https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
@@ -1223,7 +1223,7 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 			}
 			}
 		} break;
 		} break;
 		}
 		}
-	} else if (str_eq(build_context.ODIN_OS, str_lit("linux"))) {
+	} else if (build_context.ODIN_OS == "linux") {
 		Type *bt = core_type(original_type);
 		Type *bt = core_type(original_type);
 		switch (bt->kind) {
 		switch (bt->kind) {
 		// Okay to pass by value
 		// Okay to pass by value
@@ -1277,7 +1277,7 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
 
 
 
 
 
 
-	if (str_eq(build_context.ODIN_OS, str_lit("windows"))) {
+	if (build_context.ODIN_OS == "windows") {
 		Type *bt = core_type(reduce_tuple_to_single_type(original_type));
 		Type *bt = core_type(reduce_tuple_to_single_type(original_type));
 		// NOTE(bill): This is just reversed engineered from LLVM IR output
 		// NOTE(bill): This is just reversed engineered from LLVM IR output
 		switch (bt->kind) {
 		switch (bt->kind) {
@@ -1301,7 +1301,7 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
 			}
 			}
 		} break;
 		} break;
 		}
 		}
-	} else if (str_eq(build_context.ODIN_OS, str_lit("linux"))) {
+	} else if (build_context.ODIN_OS == "linux") {
 
 
 	} else {
 	} else {
 		// IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
 		// IMPORTANT TODO(bill): figure out the ABI settings for Linux, OSX etc. for
@@ -1330,7 +1330,7 @@ bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *a
 	}
 	}
 
 
 
 
-	if (str_eq(build_context.ODIN_OS, str_lit("windows"))) {
+	if (build_context.ODIN_OS == "windows") {
 		i64 size = 8*type_size_of(a, abi_return_type);
 		i64 size = 8*type_size_of(a, abi_return_type);
 		switch (size) {
 		switch (size) {
 		case 0:
 		case 0:
@@ -1388,7 +1388,7 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 
 
 	Entity *e = scope_lookup_entity(c->context.scope, name);
 	Entity *e = scope_lookup_entity(c->context.scope, name);
 	if (e == NULL) {
 	if (e == NULL) {
-		if (str_eq(name, str_lit("_"))) {
+		if (name == "_") {
 			error(n->Ident, "`_` cannot be used as a value type");
 			error(n->Ident, "`_` cannot be used as a value type");
 		} else {
 		} else {
 			error(n->Ident, "Undeclared name: %.*s", LIT(name));
 			error(n->Ident, "Undeclared name: %.*s", LIT(name));
@@ -1959,7 +1959,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
 	}
 	}
 
 
 	if (is_type_typed(type)) {
 	if (is_type_typed(type)) {
-		add_type_and_value(&c->info, e, Addressing_Type, type, ExactValue{});
+		add_type_and_value(&c->info, e, Addressing_Type, type, empty_exact_value);
 	} else {
 	} else {
 		gbString name = type_to_string(type);
 		gbString name = type_to_string(type);
 		error_node(e, "Invalid type definition of %s", name);
 		error_node(e, "Invalid type definition of %s", name);
@@ -3016,7 +3016,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
 
 
 	if (operand->mode == Addressing_Constant) {
 	if (operand->mode == Addressing_Constant) {
 		if (i128_eq(operand->value.value_integer, I128_ZERO)) {
 		if (i128_eq(operand->value.value_integer, I128_ZERO)) {
-			if (str_ne(make_string_c(expr_str), str_lit("nil"))) { // HACK NOTE(bill): Just in case
+			if (make_string_c(expr_str) != "nil") { // HACK NOTE(bill): Just in case
 				// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
 				// NOTE(bill): Doesn't matter what the type is as it's still zero in the union
 				extra_text = " - Did you want `nil`?";
 				extra_text = " - Did you want `nil`?";
 			}
 			}
@@ -5213,7 +5213,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 		case Token_Rune:    t = t_untyped_rune;    break;
 		case Token_Rune:    t = t_untyped_rune;    break;
 		case Token_Imag: {
 		case Token_Imag: {
 			String s = bl->string;
 			String s = bl->string;
-			Rune r = s.text[s.len-1];
+			Rune r = s[s.len-1];
 			switch (r) {
 			switch (r) {
 			case 'i': t = t_untyped_complex; break;
 			case 'i': t = t_untyped_complex; break;
 			}
 			}
@@ -5226,13 +5226,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 	case_end;
 	case_end;
 
 
 	case_ast_node(bd, BasicDirective, node);
 	case_ast_node(bd, BasicDirective, node);
-		if (str_eq(bd->name, str_lit("file"))) {
+		if (bd->name == "file") {
 			o->type = t_untyped_string;
 			o->type = t_untyped_string;
 			o->value = exact_value_string(bd->token.pos.file);
 			o->value = exact_value_string(bd->token.pos.file);
-		} else if (str_eq(bd->name, str_lit("line"))) {
+		} else if (bd->name == "line") {
 			o->type = t_untyped_integer;
 			o->type = t_untyped_integer;
 			o->value = exact_value_i64(bd->token.pos.line);
 			o->value = exact_value_i64(bd->token.pos.line);
-		} else if (str_eq(bd->name, str_lit("procedure"))) {
+		} else if (bd->name == "procedure") {
 			if (c->proc_stack.count == 0) {
 			if (c->proc_stack.count == 0) {
 				error_node(node, "#procedure may only be used within procedures");
 				error_node(node, "#procedure may only be used within procedures");
 				o->type = t_untyped_string;
 				o->type = t_untyped_string;
@@ -5448,7 +5448,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 					bool all_fields_are_blank = true;
 					bool all_fields_are_blank = true;
 					for (isize i = 0; i < t->Record.field_count; i++) {
 					for (isize i = 0; i < t->Record.field_count; i++) {
 						Entity *field = t->Record.fields_in_src_order[i];
 						Entity *field = t->Record.fields_in_src_order[i];
-						if (str_ne(field->token.string, str_lit("_"))) {
+						if (field->token.string != "_") {
 							all_fields_are_blank = false;
 							all_fields_are_blank = false;
 							break;
 							break;
 						}
 						}
@@ -5466,7 +5466,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 						}
 						}
 
 
 						Entity *field = t->Record.fields_in_src_order[index];
 						Entity *field = t->Record.fields_in_src_order[index];
-						if (!all_fields_are_blank && str_eq(field->token.string, str_lit("_"))) {
+						if (!all_fields_are_blank && field->token.string == "_") {
 							// NOTE(bill): Ignore blank identifiers
 							// NOTE(bill): Ignore blank identifiers
 							continue;
 							continue;
 						}
 						}
@@ -6153,7 +6153,7 @@ gbString write_record_fields_to_string(gbString str, AstNodeArray params) {
 
 
 gbString string_append_token(gbString str, Token token) {
 gbString string_append_token(gbString str, Token token) {
 	if (token.string.len > 0) {
 	if (token.string.len > 0) {
-		return gb_string_append_length(str, token.string.text, token.string.len);
+		return gb_string_append_length(str, &token.string[0], token.string.len);
 	}
 	}
 	return str;
 	return str;
 }
 }
@@ -6186,7 +6186,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 
 
 	case_ast_node(bd, BasicDirective, node);
 	case_ast_node(bd, BasicDirective, node);
 		str = gb_string_appendc(str, "#");
 		str = gb_string_appendc(str, "#");
-		str = gb_string_append_length(str, bd->name.text, bd->name.len);
+		str = gb_string_append_length(str, &bd->name[0], bd->name.len);
 	case_end;
 	case_end;
 
 
 	case_ast_node(pl, ProcLit, node);
 	case_ast_node(pl, ProcLit, node);

+ 7 - 7
src/check_stmt.cpp

@@ -187,7 +187,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 
 
 	// NOTE(bill): Ignore assignments to `_`
 	// NOTE(bill): Ignore assignments to `_`
 	if (node->kind == AstNode_Ident &&
 	if (node->kind == AstNode_Ident &&
-	    str_eq(node->Ident.string, str_lit("_"))) {
+	    node->Ident.string == "_") {
 		add_entity_definition(&c->info, node, NULL);
 		add_entity_definition(&c->info, node, NULL);
 		check_assignment(c, rhs, NULL, str_lit("assignment to `_` identifier"));
 		check_assignment(c, rhs, NULL, str_lit("assignment to `_` identifier"));
 		if (rhs->mode == Addressing_Invalid) {
 		if (rhs->mode == Addressing_Invalid) {
@@ -434,7 +434,7 @@ void check_label(Checker *c, AstNode *label) {
 		return;
 		return;
 	}
 	}
 	String name = l->name->Ident.string;
 	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");
 		error_node(l->name, "A label's name cannot be a blank identifier");
 		return;
 		return;
 	}
 	}
@@ -449,7 +449,7 @@ void check_label(Checker *c, AstNode *label) {
 	bool ok = true;
 	bool ok = true;
 	for_array(i, c->context.decl->labels) {
 	for_array(i, c->context.decl->labels) {
 		BlockLabel bl = c->context.decl->labels.e[i];
 		BlockLabel bl = c->context.decl->labels.e[i];
-		if (str_eq(bl.name, name)) {
+		if (bl.name == name) {
 			error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
 			error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
 			ok = false;
 			ok = false;
 			break;
 			break;
@@ -943,10 +943,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 			}
 			}
 
 
 			if (x.mode != Addressing_Constant) {
 			if (x.mode != Addressing_Constant) {
-				x.value = ExactValue{};
+				x.value = empty_exact_value;
 			}
 			}
 			if (y.mode != Addressing_Constant) {
 			if (y.mode != Addressing_Constant) {
-				y.value = ExactValue{};
+				y.value = empty_exact_value;
 			}
 			}
 
 
 
 
@@ -1032,7 +1032,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 				String str = token.string;
 				String str = token.string;
 				Entity *found = NULL;
 				Entity *found = NULL;
 
 
-				if (str_ne(str, str_lit("_"))) {
+				if (str != "_") {
 					found = current_scope_lookup_entity(c->context.scope, str);
 					found = current_scope_lookup_entity(c->context.scope, str);
 				}
 				}
 				if (found == NULL) {
 				if (found == NULL) {
@@ -1564,7 +1564,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					String str = token.string;
 					String str = token.string;
 					Entity *found = NULL;
 					Entity *found = NULL;
 					// NOTE(bill): Ignore assignments to `_`
 					// NOTE(bill): Ignore assignments to `_`
-					if (str_ne(str, str_lit("_"))) {
+					if (str != "_") {
 						found = current_scope_lookup_entity(c->context.scope, str);
 						found = current_scope_lookup_entity(c->context.scope, str);
 					}
 					}
 					if (found == NULL) {
 					if (found == NULL) {

+ 12 - 12
src/checker.cpp

@@ -867,7 +867,7 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode
 void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) {
 void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) {
 	GB_ASSERT(identifier != NULL);
 	GB_ASSERT(identifier != NULL);
 	if (identifier->kind == AstNode_Ident) {
 	if (identifier->kind == AstNode_Ident) {
-		if (str_eq(identifier->Ident.string, str_lit("_"))) {
+		if (identifier->Ident.string == "_") {
 			return;
 			return;
 		}
 		}
 		HashKey key = hash_pointer(identifier);
 		HashKey key = hash_pointer(identifier);
@@ -879,7 +879,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
 
 
 bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
 bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
 	String name = entity->token.string;
 	String name = entity->token.string;
-	if (!str_eq(name, str_lit("_"))) {
+	if (name != "_") {
 		Entity *ie = scope_insert_entity(scope, entity);
 		Entity *ie = scope_insert_entity(scope, entity);
 		if (ie) {
 		if (ie) {
 			TokenPos pos = ie->token.pos;
 			TokenPos pos = ie->token.pos;
@@ -929,7 +929,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) {
 void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
 void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
 	GB_ASSERT(identifier->kind == AstNode_Ident);
 	GB_ASSERT(identifier->kind == AstNode_Ident);
 	GB_ASSERT(e != NULL && d != NULL);
 	GB_ASSERT(e != NULL && d != NULL);
-	GB_ASSERT(str_eq(identifier->Ident.string, e->token.string));
+	GB_ASSERT(identifier->Ident.string == e->token.string);
 	add_entity(c, e->scope, identifier, e);
 	add_entity(c, e->scope, identifier, e);
 	map_decl_info_set(&c->info.entities, hash_pointer(e), d);
 	map_decl_info_set(&c->info.entities, hash_pointer(e), d);
 }
 }
@@ -1580,7 +1580,7 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
 						d->proc_lit = up_init;
 						d->proc_lit = up_init;
 						d->type_expr = vd->type;
 						d->type_expr = vd->type;
 					} else {
 					} else {
-						e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, ExactValue{});
+						e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, empty_exact_value);
 						d->type_expr = vd->type;
 						d->type_expr = vd->type;
 						d->init_expr = init;
 						d->init_expr = init;
 					}
 					}
@@ -1678,12 +1678,12 @@ void check_all_global_entities(Checker *c) {
 			continue;
 			continue;
 		}
 		}
 
 
-		if (e->kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
+		if (e->kind != Entity_Procedure && e->token.string == "main") {
 			if (e->scope->is_init) {
 			if (e->scope->is_init) {
 				error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
 				error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
 				continue;
 				continue;
 			}
 			}
-		} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
+		} else if (e->scope->is_global && e->token.string == "main") {
 			error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
 			error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
 			continue;
 			continue;
 		}
 		}
@@ -1745,7 +1745,7 @@ String path_to_entity_name(String name, String fullpath) {
 	isize slash = 0;
 	isize slash = 0;
 	isize dot = 0;
 	isize dot = 0;
 	for (isize i = filename.len-1; i >= 0; i--) {
 	for (isize i = filename.len-1; i >= 0; i--) {
-		u8 c = filename.text[i];
+		u8 c = filename[i];
 		if (c == '/' || c == '\\') {
 		if (c == '/' || c == '\\') {
 			break;
 			break;
 		}
 		}
@@ -1757,7 +1757,7 @@ String path_to_entity_name(String name, String fullpath) {
 
 
 	dot = filename.len;
 	dot = filename.len;
 	while (dot --> 0) {
 	while (dot --> 0) {
-		u8 c = filename.text[dot];
+		u8 c = filename[dot];
 		if (c == '.') {
 		if (c == '.') {
 			break;
 			break;
 		}
 		}
@@ -1932,7 +1932,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 
 
 		scope->has_been_imported = true;
 		scope->has_been_imported = true;
 
 
-		if (str_eq(id->import_name.string, str_lit("."))) {
+		if (id->import_name.string == ".") {
 			// NOTE(bill): Add imported entities to this file's scope
 			// NOTE(bill): Add imported entities to this file's scope
 			for_array(elem_index, scope->elements.entries) {
 			for_array(elem_index, scope->elements.entries) {
 				Entity *e = scope->elements.entries.e[elem_index].value;
 				Entity *e = scope->elements.entries.e[elem_index].value;
@@ -1958,7 +1958,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 			}
 			}
 		} else {
 		} else {
 			String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
 			String import_name = path_to_entity_name(id->import_name.string, id->fullpath);
-			if (str_eq(import_name, str_lit("_"))) {
+			if (import_name == "_") {
 				error(token, "File name, %.*s, cannot be as an import name as it is not a valid identifier", LIT(id->import_name.string));
 				error(token, "File name, %.*s, cannot be as an import name as it is not a valid identifier", LIT(id->import_name.string));
 			} else {
 			} else {
 				GB_ASSERT(id->import_name.pos.line != 0);
 				GB_ASSERT(id->import_name.pos.line != 0);
@@ -2010,7 +2010,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 
 
 
 
 		String library_name = path_to_entity_name(fl->library_name.string, file_str);
 		String library_name = path_to_entity_name(fl->library_name.string, file_str);
-		if (str_eq(library_name, str_lit("_"))) {
+		if (library_name == "_") {
 			error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
 			error(fl->token, "File name, %.*s, cannot be as a library name as it is not a valid identifier", LIT(fl->library_name.string));
 		} else {
 		} else {
 			GB_ASSERT(fl->library_name.pos.line != 0);
 			GB_ASSERT(fl->library_name.pos.line != 0);
@@ -2035,7 +2035,7 @@ void check_parsed_files(Checker *c) {
 		scope->is_global = f->is_global_scope;
 		scope->is_global = f->is_global_scope;
 		scope->is_file   = true;
 		scope->is_file   = true;
 		scope->file      = f;
 		scope->file      = f;
-		if (str_eq(f->tokenizer.fullpath, c->parser->init_fullpath)) {
+		if (f->tokenizer.fullpath == c->parser->init_fullpath) {
 			scope->is_init = true;
 			scope->is_init = true;
 		}
 		}
 
 

+ 1 - 1
src/entity.cpp

@@ -148,7 +148,7 @@ bool is_entity_exported(Entity *e) {
 	if (name.len == 0) {
 	if (name.len == 0) {
 		return false;
 		return false;
 	}
 	}
-	return name.text[0] != '_';
+	return name[0] != '_';
 }
 }
 
 
 gb_global u64 global_entity_id = 0;
 gb_global u64 global_entity_id = 0;

+ 3 - 1
src/exact_value.cpp

@@ -36,6 +36,8 @@ typedef struct ExactValue {
 	};
 	};
 } ExactValue;
 } ExactValue;
 
 
+gb_global ExactValue const empty_exact_value = {};
+
 HashKey hash_exact_value(ExactValue v) {
 HashKey hash_exact_value(ExactValue v) {
 	return hashing_proc(&v, gb_size_of(ExactValue));
 	return hashing_proc(&v, gb_size_of(ExactValue));
 }
 }
@@ -191,7 +193,7 @@ ExactValue exact_value_from_basic_literal(Token token) {
 	case Token_Float:   return exact_value_float_from_string(token.string);
 	case Token_Float:   return exact_value_float_from_string(token.string);
 	case Token_Imag: {
 	case Token_Imag: {
 		String str = token.string;
 		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`
 		str.len--; // Ignore the `i|j|k`
 		f64 imag = float_from_string(str);
 		f64 imag = float_from_string(str);
 
 

+ 4 - 4
src/integer128.cpp

@@ -109,8 +109,8 @@ u128 u128_from_string(String string) {
 	// TODO(bill): Allow for numbers with underscores in them
 	// TODO(bill): Allow for numbers with underscores in them
 	u64 base = 10;
 	u64 base = 10;
 	bool has_prefix = false;
 	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 'b': base = 2;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;
@@ -160,8 +160,8 @@ i128 i128_from_string(String string) {
 	// TODO(bill): Allow for numbers with underscores in them
 	// TODO(bill): Allow for numbers with underscores in them
 	u64 base = 10;
 	u64 base = 10;
 	bool has_prefix = false;
 	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 'b': base = 2;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'o': base = 8;  has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;
 		case 'd': base = 10; has_prefix = true; break;

+ 11 - 11
src/ir.cpp

@@ -1399,8 +1399,8 @@ irDebugInfo *ir_add_debug_info_file(irProcedure *proc, AstFile *file) {
 	String directory = filename;
 	String directory = filename;
 	isize slash_index = 0;
 	isize slash_index = 0;
 	for (isize i = filename.len-1; i >= 0; i--) {
 	for (isize i = filename.len-1; i >= 0; i--) {
-		if (filename.text[i] == '\\' ||
-		    filename.text[i] == '/') {
+		if (filename[i] == '\\' ||
+		    filename[i] == '/') {
 			break;
 			break;
 		}
 		}
 		slash_index = i;
 		slash_index = i;
@@ -1612,7 +1612,7 @@ void ir_emit_if(irProcedure *proc, irValue *cond, irBlock *true_block, irBlock *
 }
 }
 
 
 void ir_emit_startup_runtime(irProcedure *proc) {
 void ir_emit_startup_runtime(irProcedure *proc) {
-	GB_ASSERT(proc->parent == NULL && str_eq(proc->name, str_lit("main")));
+	GB_ASSERT(proc->parent == NULL && proc->name == "main");
 	ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime));
 	ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime));
 }
 }
 
 
@@ -4813,7 +4813,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 				GB_ASSERT(e->kind == Entity_Variable);
 				GB_ASSERT(e->kind == Entity_Variable);
 				GB_ASSERT(e->flags & EntityFlag_TypeField);
 				GB_ASSERT(e->flags & EntityFlag_TypeField);
 				String name = e->token.string;
 				String name = e->token.string;
-				if (str_eq(name, str_lit("names"))) {
+				if (name == "names") {
 					irValue *ti_ptr = ir_type_info(proc, type);
 					irValue *ti_ptr = ir_type_info(proc, type);
 
 
 					irValue *names_ptr = NULL;
 					irValue *names_ptr = NULL;
@@ -6733,8 +6733,8 @@ void ir_begin_procedure_body(irProcedure *proc) {
 
 
 			Entity *e = params->variables[i];
 			Entity *e = params->variables[i];
 			Type *abi_type = proc->type->Proc.abi_compat_params[i];
 			Type *abi_type = proc->type->Proc.abi_compat_params[i];
-			if (!str_eq(e->token.string, str_lit("")) &&
-			    !str_eq(e->token.string, str_lit("_"))) {
+			if (e->token.string != "" &&
+			    e->token.string != "_") {
 				irValue *param = ir_add_param(proc, e, name, abi_type);
 				irValue *param = ir_add_param(proc, e, name, abi_type);
 				array_add(&proc->params, param);
 				array_add(&proc->params, param);
 			}
 			}
@@ -6764,7 +6764,7 @@ void ir_end_procedure_body(irProcedure *proc) {
 
 
 void ir_insert_code_before_proc(irProcedure* proc, irProcedure *parent) {
 void ir_insert_code_before_proc(irProcedure* proc, irProcedure *parent) {
 	if (parent == NULL) {
 	if (parent == NULL) {
-		if (str_eq(proc->name, str_lit("main"))) {
+		if (proc->name == "main") {
 			ir_emit_startup_runtime(proc);
 			ir_emit_startup_runtime(proc);
 		}
 		}
 	}
 	}
@@ -7101,15 +7101,15 @@ void ir_gen_tree(irGen *s) {
 		if (e->kind == Entity_Variable) {
 		if (e->kind == Entity_Variable) {
 			global_variable_max_count++;
 			global_variable_max_count++;
 		} else if (e->kind == Entity_Procedure && !e->scope->is_global) {
 		} 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;
 				entry_point = e;
 			}
 			}
 			if ((e->Procedure.tags & ProcTag_export) != 0 ||
 			if ((e->Procedure.tags & ProcTag_export) != 0 ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->scope->is_file && 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;
 					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;
 					has_win_main = true;
 				}
 				}
 			}
 			}
@@ -7146,7 +7146,7 @@ void ir_gen_tree(irGen *s) {
 			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
 			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 				// Handle later
 				// 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 {
 			} else {
 				name = ir_mangle_name(s, e->token.pos.file, e);
 				name = ir_mangle_name(s, e->token.pos.file, e);
 			}
 			}

+ 4 - 4
src/ir_print.cpp

@@ -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) {
 void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, bool prefix_with_dot) {
 	isize extra = 0;
 	isize extra = 0;
 	for (isize i = 0; i < name.len; i++) {
 	for (isize i = 0; i < name.len; i++) {
-		u8 c = name.text[i];
+		u8 c = name[i];
 		if (!ir_valid_char(c)) {
 		if (!ir_valid_char(c)) {
 			extra += 2;
 			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++) {
 	for (isize i = 0; i < name.len; i++) {
-		u8 c = name.text[i];
+		u8 c = name[i];
 		if (ir_valid_char(c)) {
 		if (ir_valid_char(c)) {
 			buf[j++] = c;
 			buf[j++] = c;
 		} else {
 		} else {
@@ -1500,8 +1500,8 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 				ir_fprintf(f, " noalias");
 				ir_fprintf(f, " noalias");
 			}
 			}
 			if (proc->body != NULL) {
 			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_fprintf(f, " ");
 					ir_print_encoded_local(f, e->token.string);
 					ir_print_encoded_local(f, e->token.string);
 				} else {
 				} else {

+ 5 - 13
src/main.cpp

@@ -1,7 +1,3 @@
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
 #define USE_CUSTOM_BACKEND false
 #define USE_CUSTOM_BACKEND false
 
 
 #include "common.cpp"
 #include "common.cpp"
@@ -154,27 +150,27 @@ int main(int argc, char **argv) {
 	char *init_filename = NULL;
 	char *init_filename = NULL;
 	bool run_output = false;
 	bool run_output = false;
 	String arg1 = make_string_c(argv[1]);
 	String arg1 = make_string_c(argv[1]);
-	if (str_eq(arg1, str_lit("run"))) {
+	if (arg1 == "run") {
 		if (argc != 3) {
 		if (argc != 3) {
 			usage(argv[0]);
 			usage(argv[0]);
 			return 1;
 			return 1;
 		}
 		}
 		init_filename = argv[2];
 		init_filename = argv[2];
 		run_output = true;
 		run_output = true;
-	} else if (str_eq(arg1, str_lit("build_dll"))) {
+	} else if (arg1 == "build_dll") {
 		if (argc != 3) {
 		if (argc != 3) {
 			usage(argv[0]);
 			usage(argv[0]);
 			return 1;
 			return 1;
 		}
 		}
 		init_filename = argv[2];
 		init_filename = argv[2];
 		build_context.is_dll = true;
 		build_context.is_dll = true;
-	} else if (str_eq(arg1, str_lit("build"))) {
+	} else if (arg1 == "build") {
 		if (argc != 3) {
 		if (argc != 3) {
 			usage(argv[0]);
 			usage(argv[0]);
 			return 1;
 			return 1;
 		}
 		}
 		init_filename = argv[2];
 		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));
 		gb_printf("%s version %.*s\n", argv[0], LIT(build_context.ODIN_VERSION));
 		return 0;
 		return 0;
 	} else {
 	} else {
@@ -382,7 +378,7 @@ int main(int argc, char **argv) {
 		//   without having to implement any new syntax specifically for MacOS.
 		//   without having to implement any new syntax specifically for MacOS.
 		#if defined(GB_SYSTEM_OSX)
 		#if defined(GB_SYSTEM_OSX)
 			isize len;
 			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),
 				len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
 				                        " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
 				                        " -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
 			} else {
 			} else {
@@ -460,7 +456,3 @@ int main(int argc, char **argv) {
 
 
 	return 0;
 	return 0;
 }
 }
-
-#if defined(__cplusplus)
-}
-#endif

+ 1 - 1
src/map.cpp

@@ -65,7 +65,7 @@ bool hash_key_equal(HashKey a, HashKey b) {
 		// NOTE(bill): If two string's hashes collide, compare the strings themselves
 		// NOTE(bill): If two string's hashes collide, compare the strings themselves
 		if (a.kind == HashKey_String) {
 		if (a.kind == HashKey_String) {
 			if (b.kind == HashKey_String) {
 			if (b.kind == HashKey_String) {
-				return str_eq(a.string, b.string);
+				return a.string == b.string;
 			}
 			}
 			return false;
 			return false;
 		}
 		}

+ 40 - 40
src/parser.cpp

@@ -1547,7 +1547,7 @@ bool allow_token(AstFile *f, TokenKind kind) {
 
 
 bool is_blank_ident(String str) {
 bool is_blank_ident(String str) {
 	if (str.len == 1) {
 	if (str.len == 1) {
-		return str.text[0] == '_';
+		return str[0] == '_';
 	}
 	}
 	return false;
 	return false;
 }
 }
@@ -1605,7 +1605,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
 Token expect_closing(AstFile *f, TokenKind kind, String context) {
 Token expect_closing(AstFile *f, TokenKind kind, String context) {
 	if (f->curr_token.kind != kind &&
 	if (f->curr_token.kind != kind &&
 	    f->curr_token.kind == Token_Semicolon &&
 	    f->curr_token.kind == Token_Semicolon &&
-	    str_eq(f->curr_token.string, str_lit("\n"))) {
+	    f->curr_token.string == "\n") {
 		error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context));
 		error(f->curr_token, "Missing `,` before newline in %.*s", LIT(context));
 		next_token(f);
 		next_token(f);
 	}
 	}
@@ -1847,11 +1847,11 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
 		String tag_name = te->name.string;
 		String tag_name = te->name.string;
 
 
 		#define ELSE_IF_ADD_TAG(name) \
 		#define ELSE_IF_ADD_TAG(name) \
-		else if (str_eq(tag_name, str_lit(#name))) { \
+		else if (tag_name == #name) { \
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
 		}
 		}
 
 
-		if (str_eq(tag_name, str_lit("foreign"))) {
+		if (tag_name == "foreign") {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
 			*foreign_library_token = parse_ident(f);
 			*foreign_library_token = parse_ident(f);
 			if (f->curr_token.kind == Token_String) {
 			if (f->curr_token.kind == Token_String) {
@@ -1863,7 +1863,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
 
 
 				next_token(f);
 				next_token(f);
 			}
 			}
-		} else if (str_eq(tag_name, str_lit("link_name"))) {
+		} else if (tag_name == "link_name") {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
 			if (f->curr_token.kind == Token_String) {
 			if (f->curr_token.kind == Token_String) {
 				*link_name = f->curr_token.string;
 				*link_name = f->curr_token.string;
@@ -1885,25 +1885,25 @@ void parse_proc_tags(AstFile *f, u64 *tags, AstNode **foreign_library_token, Str
 		ELSE_IF_ADD_TAG(no_inline)
 		ELSE_IF_ADD_TAG(no_inline)
 		// ELSE_IF_ADD_TAG(dll_import)
 		// ELSE_IF_ADD_TAG(dll_import)
 		// ELSE_IF_ADD_TAG(dll_export)
 		// ELSE_IF_ADD_TAG(dll_export)
-		else if (str_eq(tag_name, str_lit("cc_odin"))) {
+		else if (tag_name == "cc_odin") {
 			if (cc == ProcCC_Invalid) {
 			if (cc == ProcCC_Invalid) {
 				cc = ProcCC_Odin;
 				cc = ProcCC_Odin;
 			} else {
 			} else {
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 			}
 			}
-		} else if (str_eq(tag_name, str_lit("cc_c"))) {
+		} else if (tag_name == "cc_c") {
 			if (cc == ProcCC_Invalid) {
 			if (cc == ProcCC_Invalid) {
 				cc = ProcCC_C;
 				cc = ProcCC_C;
 			} else {
 			} else {
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 			}
 			}
-		} else if (str_eq(tag_name, str_lit("cc_std"))) {
+		} else if (tag_name == "cc_std") {
 			if (cc == ProcCC_Invalid) {
 			if (cc == ProcCC_Invalid) {
 				cc = ProcCC_Std;
 				cc = ProcCC_Std;
 			} else {
 			} else {
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 				syntax_error_node(tag_expr, "Multiple calling conventions for procedure type");
 			}
 			}
-		} else if (str_eq(tag_name, str_lit("cc_fast"))) {
+		} else if (tag_name == "cc_fast") {
 			if (cc == ProcCC_Invalid) {
 			if (cc == ProcCC_Invalid) {
 				cc = ProcCC_Fast;
 				cc = ProcCC_Fast;
 			} else {
 			} else {
@@ -2025,7 +2025,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 	case Token_Hash: {
 	case Token_Hash: {
 		Token token = expect_token(f, Token_Hash);
 		Token token = expect_token(f, Token_Hash);
 		Token name  = expect_token(f, Token_Ident);
 		Token name  = expect_token(f, Token_Ident);
-		if (str_eq(name.string, str_lit("run"))) {
+		if (name.string == "run") {
 			AstNode *expr = parse_expr(f, false);
 			AstNode *expr = parse_expr(f, false);
 			operand = ast_run_expr(f, token, name, expr);
 			operand = ast_run_expr(f, token, name, expr);
 			if (unparen_expr(expr)->kind != AstNode_CallExpr) {
 			if (unparen_expr(expr)->kind != AstNode_CallExpr) {
@@ -2033,11 +2033,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 				operand = ast_bad_expr(f, token, f->curr_token);
 				operand = ast_bad_expr(f, token, f->curr_token);
 			}
 			}
 			warning(token, "#run is not yet implemented");
 			warning(token, "#run is not yet implemented");
-		} else if (str_eq(name.string, str_lit("file"))) { return ast_basic_directive(f, token, name.string);
-		} else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string);
-		} else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string);
-		} else if (str_eq(name.string, str_lit("type"))) { return ast_helper_type(f, token, parse_type(f));
-		} else if (!lhs && str_eq(name.string, str_lit("alias"))) { return ast_alias(f, token, parse_expr(f, false));
+		} else if (name.string == "file") { return ast_basic_directive(f, token, name.string);
+		} else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
+		} else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
+		} else if (name.string == "type") { return ast_helper_type(f, token, parse_type(f));
+		} else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false));
 		} else {
 		} else {
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 		}
 		}
@@ -2721,7 +2721,7 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
 		next_token(f);
 		next_token(f);
 		switch (f->curr_token.kind) {
 		switch (f->curr_token.kind) {
 		case Token_Ident:
 		case Token_Ident:
-			if (str_eq(f->curr_token.string, str_lit("no_alias"))) {
+			if (f->curr_token.string == "no_alias") {
 				return FieldPrefix_NoAlias;
 				return FieldPrefix_NoAlias;
 			}
 			}
 			break;
 			break;
@@ -2941,7 +2941,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
 		Token hash_token = expect_token(f, Token_Hash);
 		Token hash_token = expect_token(f, Token_Hash);
 		Token name = expect_token(f, Token_Ident);
 		Token name = expect_token(f, Token_Ident);
 		String tag = name.string;
 		String tag = name.string;
-		if (str_eq(tag, str_lit("type"))) {
+		if (tag == "type") {
 			AstNode *type = parse_type(f);
 			AstNode *type = parse_type(f);
 			return ast_helper_type(f, hash_token, type);
 			return ast_helper_type(f, hash_token, type);
 		}
 		}
@@ -3023,17 +3023,17 @@ AstNode *parse_type_or_ident(AstFile *f) {
 
 
 		while (allow_token(f, Token_Hash)) {
 		while (allow_token(f, Token_Hash)) {
 			Token tag = expect_token_after(f, Token_Ident, "#");
 			Token tag = expect_token_after(f, Token_Ident, "#");
-			if (str_eq(tag.string, str_lit("packed"))) {
+			if (tag.string == "packed") {
 				if (is_packed) {
 				if (is_packed) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 				}
 				}
 				is_packed = true;
 				is_packed = true;
-			} else if (str_eq(tag.string, str_lit("ordered"))) {
+			} else if (tag.string == "ordered") {
 				if (is_ordered) {
 				if (is_ordered) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 				}
 				}
 				is_ordered = true;
 				is_ordered = true;
-			} else if (str_eq(tag.string, str_lit("align"))) {
+			} else if (tag.string == "align") {
 				if (align) {
 				if (align) {
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 					syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
 				}
 				}
@@ -3157,7 +3157,7 @@ AstNode *parse_type_or_ident(AstFile *f) {
 
 
 		while (allow_token(f, Token_Hash)) {
 		while (allow_token(f, Token_Hash)) {
 			Token tag = expect_token_after(f, Token_Ident, "#");
 			Token tag = expect_token_after(f, Token_Ident, "#");
-			if (str_eq(tag.string, str_lit("align"))) {
+			if (tag.string == "align") {
 				if (align) {
 				if (align) {
 					syntax_error(tag, "Duplicate bit_field tag `#%.*s`", LIT(tag.string));
 					syntax_error(tag, "Duplicate bit_field tag `#%.*s`", LIT(tag.string));
 				}
 				}
@@ -3687,7 +3687,7 @@ AstNode *parse_stmt(AstFile *f) {
 		Token name = expect_token(f, Token_Ident);
 		Token name = expect_token(f, Token_Ident);
 		String tag = name.string;
 		String tag = name.string;
 
 
-		if (str_eq(tag, str_lit("import"))) {
+		if (tag == "import") {
 			AstNode *cond = NULL;
 			AstNode *cond = NULL;
 			Token import_name = {};
 			Token import_name = {};
 
 
@@ -3706,7 +3706,7 @@ AstNode *parse_stmt(AstFile *f) {
 				break;
 				break;
 			}
 			}
 
 
-			if (str_eq(import_name.string, str_lit("_"))) {
+			if (import_name.string == "_") {
 				syntax_error(import_name, "Illegal #import name: `_`");
 				syntax_error(import_name, "Illegal #import name: `_`");
 			}
 			}
 
 
@@ -3724,7 +3724,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			expect_semicolon(f, decl);
 			expect_semicolon(f, decl);
 			return decl;
 			return decl;
-		} else if (str_eq(tag, str_lit("load"))) {
+		} else if (tag == "load") {
 			AstNode *cond = NULL;
 			AstNode *cond = NULL;
 			Token file_path = expect_token_after(f, Token_String, "#load");
 			Token file_path = expect_token_after(f, Token_String, "#load");
 			Token import_name = file_path;
 			Token import_name = file_path;
@@ -3743,7 +3743,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			expect_semicolon(f, decl);
 			expect_semicolon(f, decl);
 			return decl;
 			return decl;
-		} else if (str_eq(tag, str_lit("shared_global_scope"))) {
+		} else if (tag == "shared_global_scope") {
 			if (f->curr_proc == NULL) {
 			if (f->curr_proc == NULL) {
 				f->is_global_scope = true;
 				f->is_global_scope = true;
 				s = ast_empty_stmt(f, f->curr_token);
 				s = ast_empty_stmt(f, f->curr_token);
@@ -3753,7 +3753,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			expect_semicolon(f, s);
 			expect_semicolon(f, s);
 			return s;
 			return s;
-		} else if (str_eq(tag, str_lit("foreign_system_library"))) {
+		} else if (tag == "foreign_system_library") {
 			AstNode *cond = NULL;
 			AstNode *cond = NULL;
 			Token lib_name = {};
 			Token lib_name = {};
 
 
@@ -3767,7 +3767,7 @@ AstNode *parse_stmt(AstFile *f) {
 				break;
 				break;
 			}
 			}
 
 
-			if (str_eq(lib_name.string, str_lit("_"))) {
+			if (lib_name.string == "_") {
 				syntax_error(lib_name, "Illegal #foreign_library name: `_`");
 				syntax_error(lib_name, "Illegal #foreign_library name: `_`");
 			}
 			}
 			Token file_path = expect_token(f, Token_String);
 			Token file_path = expect_token(f, Token_String);
@@ -3784,7 +3784,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			expect_semicolon(f, s);
 			expect_semicolon(f, s);
 			return s;
 			return s;
-		} else if (str_eq(tag, str_lit("foreign_library"))) {
+		} else if (tag == "foreign_library") {
 			AstNode *cond = NULL;
 			AstNode *cond = NULL;
 			Token lib_name = {};
 			Token lib_name = {};
 
 
@@ -3798,7 +3798,7 @@ AstNode *parse_stmt(AstFile *f) {
 				break;
 				break;
 			}
 			}
 
 
-			if (str_eq(lib_name.string, str_lit("_"))) {
+			if (lib_name.string == "_") {
 				syntax_error(lib_name, "Illegal #foreign_library name: `_`");
 				syntax_error(lib_name, "Illegal #foreign_library name: `_`");
 			}
 			}
 			Token file_path = expect_token(f, Token_String);
 			Token file_path = expect_token(f, Token_String);
@@ -3815,7 +3815,7 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			expect_semicolon(f, s);
 			expect_semicolon(f, s);
 			return s;
 			return s;
-		} else if (str_eq(tag, str_lit("thread_local"))) {
+		} else if (tag == "thread_local") {
 			AstNode *s = parse_stmt(f);
 			AstNode *s = parse_stmt(f);
 
 
 			if (s->kind == AstNode_ValueDecl) {
 			if (s->kind == AstNode_ValueDecl) {
@@ -3831,14 +3831,14 @@ AstNode *parse_stmt(AstFile *f) {
 			}
 			}
 			syntax_error(token, "`thread_local` may only be applied to a variable declaration");
 			syntax_error(token, "`thread_local` may only be applied to a variable declaration");
 			return ast_bad_stmt(f, token, f->curr_token);
 			return ast_bad_stmt(f, token, f->curr_token);
-		} else if (str_eq(tag, str_lit("bounds_check"))) {
+		} else if (tag == "bounds_check") {
 			s = parse_stmt(f);
 			s = parse_stmt(f);
 			s->stmt_state_flags |= StmtStateFlag_bounds_check;
 			s->stmt_state_flags |= StmtStateFlag_bounds_check;
 			if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
 			if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
 				syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
 				syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
 			}
 			}
 			return s;
 			return s;
-		} else if (str_eq(tag, str_lit("no_bounds_check"))) {
+		} else if (tag == "no_bounds_check") {
 			s = parse_stmt(f);
 			s = parse_stmt(f);
 			s->stmt_state_flags |= StmtStateFlag_no_bounds_check;
 			s->stmt_state_flags |= StmtStateFlag_no_bounds_check;
 			if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) {
 			if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) {
@@ -3847,7 +3847,7 @@ AstNode *parse_stmt(AstFile *f) {
 			return s;
 			return s;
 		}
 		}
 
 
-		if (str_eq(tag, str_lit("include"))) {
+		if (tag == "include") {
 			syntax_error(token, "#include is not a valid import declaration kind. Use #load instead");
 			syntax_error(token, "#include is not a valid import declaration kind. Use #load instead");
 			s = ast_bad_stmt(f, token, f->curr_token);
 			s = ast_bad_stmt(f, token, f->curr_token);
 		} else {
 		} else {
@@ -3983,7 +3983,7 @@ bool try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos)
 
 
 	for_array(i, p->imports) {
 	for_array(i, p->imports) {
 		String import = p->imports.e[i].path;
 		String import = p->imports.e[i].path;
-		if (str_eq(import, path)) {
+		if (import == path) {
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -4059,7 +4059,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
 		#if 0
 		#if 0
 			isize colon_pos = -1;
 			isize colon_pos = -1;
 			for (isize j = 0; j < file_str.len; j++) {
 			for (isize j = 0; j < file_str.len; j++) {
-				if (file_str.text[j] == ':') {
+				if (file_str[j] == ':') {
 					colon_pos = j;
 					colon_pos = j;
 					break;
 					break;
 				}
 				}
@@ -4077,12 +4077,12 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
 			}
 			}
 
 
 
 
-			if (str_eq(collection_name, str_lit("core"))) {
+			if (collection_name == "core") {
 				String abs_path = get_fullpath_core(allocator, file_str);
 				String abs_path = get_fullpath_core(allocator, file_str);
 				if (gb_file_exists(cast(char *)abs_path.text)) { // NOTE(bill): This should be null terminated
 				if (gb_file_exists(cast(char *)abs_path.text)) { // NOTE(bill): This should be null terminated
 					import_file = abs_path;
 					import_file = abs_path;
 				}
 				}
-			} else if (str_eq(collection_name, str_lit("local"))) {
+			} else if (collection_name == "local") {
 				String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
 				String rel_path = get_fullpath_relative(allocator, base_dir, file_str);
 				if (gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
 				if (gb_file_exists(cast(char *)rel_path.text)) { // NOTE(bill): This should be null terminated
 					import_file = rel_path;
 					import_file = rel_path;
@@ -4153,8 +4153,8 @@ void parse_file(Parser *p, AstFile *f) {
 	String filepath = f->tokenizer.fullpath;
 	String filepath = f->tokenizer.fullpath;
 	String base_dir = filepath;
 	String base_dir = filepath;
 	for (isize i = filepath.len-1; i >= 0; i--) {
 	for (isize i = filepath.len-1; i >= 0; i--) {
-		if (base_dir.text[i] == '\\' ||
-		    base_dir.text[i] == '/') {
+		if (base_dir[i] == '\\' ||
+		    base_dir[i] == '/') {
 			break;
 			break;
 		}
 		}
 		base_dir.len--;
 		base_dir.len--;
@@ -4202,7 +4202,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
 
 
 		if (err != ParseFile_None) {
 		if (err != ParseFile_None) {
 			if (err == ParseFile_EmptyFile) {
 			if (err == ParseFile_EmptyFile) {
-				if (str_eq(import_path, init_fullpath)) {
+				if (import_path == init_fullpath) {
 					gb_printf_err("Initial file is empty - %.*s\n", LIT(init_fullpath));
 					gb_printf_err("Initial file is empty - %.*s\n", LIT(init_fullpath));
 					gb_exit(1);
 					gb_exit(1);
 				}
 				}

+ 8 - 8
src/ssa.cpp

@@ -378,9 +378,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_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_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_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{}); }
+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_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{}); }
+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) {
 ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) {
 	switch (8*type_size_of(p->allocator, t)) {
 	switch (8*type_size_of(p->allocator, t)) {
@@ -413,7 +413,7 @@ void ssa_reset_value_args(ssaValue *v) {
 
 
 void ssa_reset(ssaValue *v, ssaOp op) {
 void ssa_reset(ssaValue *v, ssaOp op) {
 	v->op = op;
 	v->op = op;
-	v->exact_value = ExactValue{};
+	v->exact_value = empty_exact_value;
 	ssa_reset_value_args(v);
 	ssa_reset_value_args(v);
 }
 }
 
 
@@ -1071,7 +1071,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 				// GB_ASSERT(e->kind == Entity_Variable);
 				// GB_ASSERT(e->kind == Entity_Variable);
 				// GB_ASSERT(e->flags & EntityFlag_TypeField);
 				// GB_ASSERT(e->flags & EntityFlag_TypeField);
 				// String name = e->token.string;
 				// String name = e->token.string;
-				// if (str_eq(name, str_lit("names"))) {
+				// if (name == "names") {
 				// 	ssaValue *ti_ptr = ir_type_info(p, type);
 				// 	ssaValue *ti_ptr = ir_type_info(p, type);
 
 
 				// 	ssaValue *names_ptr = NULL;
 				// 	ssaValue *names_ptr = NULL;
@@ -2497,15 +2497,15 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 		if (e->kind == Entity_Variable) {
 		if (e->kind == Entity_Variable) {
 			global_variable_max_count++;
 			global_variable_max_count++;
 		} else if (e->kind == Entity_Procedure && !e->scope->is_global) {
 		} 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;
 				entry_point = e;
 			}
 			}
 			if ((e->Procedure.tags & ProcTag_export) != 0 ||
 			if ((e->Procedure.tags & ProcTag_export) != 0 ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->Procedure.link_name.len > 0) ||
 			    (e->scope->is_file && 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;
 					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;
 					has_win_main = true;
 				}
 				}
 			}
 			}
@@ -2536,7 +2536,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
 			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
 			if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 			} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
 				// Handle later
 				// 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 {
 			} else {
 				name = ssa_mangle_name(&m, e->token.pos.file, e);
 				name = ssa_mangle_name(&m, e->token.pos.file, e);
 			}
 			}

+ 57 - 24
src/string.cpp

@@ -12,6 +12,15 @@ void init_string_buffer_memory(void) {
 typedef struct String {
 typedef struct String {
 	u8 *  text;
 	u8 *  text;
 	isize len;
 	isize len;
+
+	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];
+	}
 } String;
 } String;
 // NOTE(bill): used for printf style arguments
 // NOTE(bill): used for printf style arguments
 #define LIT(x) ((int)(x).len), (x).text
 #define LIT(x) ((int)(x).len), (x).text
@@ -23,6 +32,14 @@ typedef struct String {
 typedef struct String16 {
 typedef struct String16 {
 	wchar_t *text;
 	wchar_t *text;
 	isize    len;
 	isize    len;
+	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];
+	}
 } String16;
 } String16;
 
 
 
 
@@ -56,8 +73,8 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
 	if (a.len == b.len) {
 	if (a.len == b.len) {
 		isize i;
 		isize i;
 		for (i = 0; i < a.len; 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))
 			if (gb_char_to_lower(x) != gb_char_to_lower(y))
 				return false;
 				return false;
 		}
 		}
@@ -88,16 +105,16 @@ int string_compare(String x, String y) {
 		for (; curr_block < fast; curr_block++) {
 		for (; curr_block < fast; curr_block++) {
 			if (la[curr_block] ^ lb[curr_block]) {
 			if (la[curr_block] ^ lb[curr_block]) {
 				for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
 				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++) {
 		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_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;    }
 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) {
 gb_inline bool str_has_prefix(String s, String prefix) {
 	isize i;
 	isize i;
 	if (prefix.len < s.len) {
 	if (prefix.len < s.len) {
 		return false;
 		return false;
 	}
 	}
 	for (i = 0; i < prefix.len; i++) {
 	for (i = 0; i < prefix.len; i++) {
-		if (s.text[i] != prefix.text[i]) {
+		if (s[i] != prefix[i]) {
 			return false;
 			return false;
 		}
 		}
 	}
 	}
@@ -135,9 +168,9 @@ gb_inline isize string_extension_position(String str) {
 	isize i = str.len;
 	isize i = str.len;
 	bool seen_dot = false;
 	bool seen_dot = false;
 	while (i --> 0) {
 	while (i --> 0) {
-		if (str.text[i] == GB_PATH_SEPARATOR)
+		if (str[i] == GB_PATH_SEPARATOR)
 			break;
 			break;
-		if (str.text[i] == '.') {
+		if (str[i] == '.') {
 			dot_pos = i;
 			dot_pos = i;
 			break;
 			break;
 		}
 		}
@@ -147,11 +180,11 @@ gb_inline isize string_extension_position(String str) {
 }
 }
 
 
 String string_trim_whitespace(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--;
 		str.len--;
 	}
 	}
 
 
-	while (str.len > 0 && rune_is_whitespace(str.text[0])) {
+	while (str.len > 0 && rune_is_whitespace(str[0])) {
 		str.text++;
 		str.text++;
 		str.len--;
 		str.len--;
 	}
 	}
@@ -166,7 +199,7 @@ gb_inline bool string_has_extension(String str, String ext) {
 	}
 	}
 	isize len = str.len;
 	isize len = str.len;
 	for (isize i = len-1; i >= 0; i--) {
 	for (isize i = len-1; i >= 0; i--) {
-		if (str.text[i] == '.') {
+		if (str[i] == '.') {
 			break;
 			break;
 		}
 		}
 		len--;
 		len--;
@@ -182,7 +215,7 @@ gb_inline bool string_has_extension(String str, String ext) {
 bool string_contains_char(String s, u8 c) {
 bool string_contains_char(String s, u8 c) {
 	isize i;
 	isize i;
 	for (i = 0; i < s.len; i++) {
 	for (i = 0; i < s.len; i++) {
-		if (s.text[i] == c)
+		if (s[i] == c)
 			return true;
 			return true;
 	}
 	}
 	return false;
 	return false;
@@ -194,8 +227,8 @@ String filename_from_path(String s) {
 		isize j = 0;
 		isize j = 0;
 		s.len = i;
 		s.len = i;
 		for (j = i-1; j >= 0; j--) {
 		for (j = i-1; j >= 0; j--) {
-			if (s.text[j] == '/' ||
-				s.text[j] == '\\') {
+			if (s[j] == '/' ||
+				s[j] == '\\') {
 				break;
 				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) {
 bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
 	u8 c;
 	u8 c;
 
 
-	if (s.text[0] == quote &&
+	if (s[0] == quote &&
 	    (quote == '\'' || quote == '"')) {
 	    (quote == '\'' || quote == '"')) {
 		return false;
 		return false;
-	} else if (s.text[0] >= 0x80) {
+	} else if (s[0] >= 0x80) {
 		Rune r = -1;
 		Rune r = -1;
 		isize size = gb_utf8_decode(s.text, s.len, &r);
 		isize size = gb_utf8_decode(s.text, s.len, &r);
 		*rune = r;
 		*rune = r;
 		*multiple_bytes = true;
 		*multiple_bytes = true;
 		*tail_string = make_string(s.text+size, s.len-size);
 		*tail_string = make_string(s.text+size, s.len-size);
 		return true;
 		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);
 		*tail_string = make_string(s.text+1, s.len-1);
 		return true;
 		return true;
 	}
 	}
@@ -334,7 +367,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 	if (s.len <= 1) {
 	if (s.len <= 1) {
 		return false;
 		return false;
 	}
 	}
-	c = s.text[1];
+	c = s[1];
 	s = make_string(s.text+2, s.len-2);
 	s = make_string(s.text+2, s.len-2);
 
 
 	switch (c) {
 	switch (c) {
@@ -372,7 +405,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 			return false;
 			return false;
 		}
 		}
 		for (i = 0; i < 2; i++) {
 		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) {
 			if (d < 0 || d > 7) {
 				return false;
 				return false;
 			}
 			}
@@ -400,7 +433,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
 			return false;
 			return false;
 		}
 		}
 		for (i = 0; i < count; i++) {
 		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) {
 			if (d < 0) {
 				return false;
 				return false;
 			}
 			}
@@ -433,8 +466,8 @@ i32 unquote_string(gbAllocator a, String *s_) {
 	if (n < 2) {
 	if (n < 2) {
 		return 0;
 		return 0;
 	}
 	}
-	quote = s.text[0];
-	if (quote != s.text[n-1]) {
+	quote = s[0];
+	if (quote != s[n-1]) {
 		return 0;
 		return 0;
 	}
 	}
 	s.text += 1;
 	s.text += 1;

+ 1 - 1
src/tokenizer.cpp

@@ -760,7 +760,7 @@ Token tokenizer_get_token(Tokenizer *t) {
 		// NOTE(bill): All keywords are > 1
 		// NOTE(bill): All keywords are > 1
 		if (token.string.len > 1) {
 		if (token.string.len > 1) {
 			for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
 			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;
 					token.kind = cast(TokenKind)k;
 					break;
 					break;
 				}
 				}

+ 15 - 15
src/types.cpp

@@ -1025,7 +1025,7 @@ bool are_types_identical(Type *x, Type *y) {
 							if (!are_types_identical(xf->type, yf->type)) {
 							if (!are_types_identical(xf->type, yf->type)) {
 								return false;
 								return false;
 							}
 							}
-							if (str_ne(xf->token.string, yf->token.string)) {
+							if (xf->token.string != yf->token.string) {
 								return false;
 								return false;
 							}
 							}
 							bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
 							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)) {
 							if (!are_types_identical(x->Record.variants[i]->type, y->Record.variants[i]->type)) {
 								return false;
 								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;
 								return false;
 							}
 							}
 						}
 						}
@@ -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) {
 Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
 	GB_ASSERT(type_ != NULL);
 	GB_ASSERT(type_ != NULL);
 
 
-	if (str_eq(field_name, str_lit("_"))) {
+	if (field_name == "_") {
 		return empty_selection;
 		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);
 				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);
 				selection_add_index(&sel, 0);
 				sel.entity = entity__any_data;;
 				sel.entity = entity__any_data;;
 				return sel;
 				return sel;
-			} else if (str_eq(field_name, type_info_str)) {
+			} else if (field_name == type_info_str) {
 				selection_add_index(&sel, 1);
 				selection_add_index(&sel, 1);
 				sel.entity = entity__any_type_info;
 				sel.entity = entity__any_type_info;
 				return sel;
 				return sel;
@@ -1382,7 +1382,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 			switch (type->Vector.count) {
 			switch (type->Vector.count) {
 			#define _VECTOR_FIELD_CASE(_length, _name) \
 			#define _VECTOR_FIELD_CASE(_length, _name) \
 			case (_length): \
 			case (_length): \
-				if (str_eq(field_name, str_lit(_name))) { \
+				if (field_name == _name) { \
 					selection_add_index(&sel, (_length)-1); \
 					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); \
 					sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
 					return sel; \
 					return sel; \
@@ -1403,7 +1403,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 	if (is_type) {
 	if (is_type) {
 		if (type->kind == Type_Record) {
 		if (type->kind == Type_Record) {
 			if (type->Record.names != NULL &&
 			if (type->Record.names != NULL &&
-			    str_eq(field_name, str_lit("names"))) {
+			    field_name == "names") {
 				sel.entity = type->Record.names;
 				sel.entity = type->Record.names;
 				return sel;
 				return sel;
 			}
 			}
@@ -1415,7 +1415,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				GB_ASSERT(f->kind == Entity_TypeName);
 				GB_ASSERT(f->kind == Entity_TypeName);
 				String str = f->token.string;
 				String str = f->token.string;
 
 
-				if (str_eq(str, field_name)) {
+				if (str == field_name) {
 					sel.entity = f;
 					sel.entity = f;
 					// selection_add_index(&sel, i);
 					// selection_add_index(&sel, i);
 					return sel;
 					return sel;
@@ -1424,15 +1424,15 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 		} else if (is_type_enum(type)) {
 		} else if (is_type_enum(type)) {
 			// NOTE(bill): These may not have been added yet, so check in case
 			// NOTE(bill): These may not have been added yet, so check in case
 			if (type->Record.enum_count != NULL) {
 			if (type->Record.enum_count != NULL) {
-				if (str_eq(field_name, str_lit("count"))) {
+				if (field_name == "count") {
 					sel.entity = type->Record.enum_count;
 					sel.entity = type->Record.enum_count;
 					return sel;
 					return sel;
 				}
 				}
-				if (str_eq(field_name, str_lit("min_value"))) {
+				if (field_name == "min_value") {
 					sel.entity = type->Record.enum_min_value;
 					sel.entity = type->Record.enum_min_value;
 					return sel;
 					return sel;
 				}
 				}
-				if (str_eq(field_name, str_lit("max_value"))) {
+				if (field_name == "max_value") {
 					sel.entity = type->Record.enum_max_value;
 					sel.entity = type->Record.enum_max_value;
 					return sel;
 					return sel;
 				}
 				}
@@ -1443,7 +1443,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				GB_ASSERT(f->kind == Entity_Constant);
 				GB_ASSERT(f->kind == Entity_Constant);
 				String str = f->token.string;
 				String str = f->token.string;
 
 
-				if (str_eq(field_name, str)) {
+				if (field_name == str) {
 					sel.entity = f;
 					sel.entity = f;
 					// selection_add_index(&sel, i);
 					// selection_add_index(&sel, i);
 					return sel;
 					return sel;
@@ -1457,7 +1457,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 				continue;
 				continue;
 			}
 			}
 			String str = f->token.string;
 			String str = f->token.string;
-			if (str_eq(field_name, str)) {
+			if (field_name == str) {
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				sel.entity = f;
 				sel.entity = f;
 				return sel;
 				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 (type->Record.kind == TypeRecord_Union) {
-			if (str_eq(field_name, str_lit("__tag"))) {
+			if (field_name == "__tag") {
 				Entity *e = type->Record.union__tag;
 				Entity *e = type->Record.union__tag;
 				GB_ASSERT(e != NULL);
 				GB_ASSERT(e != NULL);
 				selection_add_index(&sel, -1); // HACK(bill): Leaky memory
 				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;
 			String str = f->token.string;
-			if (str_eq(field_name, str)) {
+			if (field_name == str) {
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				selection_add_index(&sel, i);  // HACK(bill): Leaky memory
 				sel.entity = f;
 				sel.entity = f;
 				return sel;
 				return sel;