Browse Source

Update ImplicitValue "architecture"

Ginger Bill 8 years ago
parent
commit
79af939522
10 changed files with 131 additions and 90 deletions
  1. 0 9
      code/demo.odin
  2. 8 8
      core/fmt.odin
  3. 1 1
      core/hash.odin
  4. 44 2
      src/checker/checker.cpp
  5. 8 3
      src/checker/entity.cpp
  6. 6 1
      src/checker/expr.cpp
  7. 10 6
      src/checker/type.cpp
  8. 17 23
      src/codegen/ssa.cpp
  9. 26 26
      src/gb/gb.h
  10. 11 11
      src/string.cpp

+ 0 - 9
code/demo.odin

@@ -1,15 +1,6 @@
 #import "fmt.odin"
 
 main :: proc() {
-	Vec3 :: struct {
-		x, y: i16
-		z: ?i32
-	}
-	a := [..]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
-	offset: u8 = 2
-	ptr := ^a[4]
 
-
-	fmt.println((ptr+offset) - ptr)
 }
 

+ 8 - 8
core/fmt.odin

@@ -406,8 +406,9 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
 
 
 	case Array:
-		print_string_to_buffer(buf, "[")
-		defer print_string_to_buffer(buf, "]")
+		bprintf(buf, "[%]%{", info.count, info.elem)
+		defer print_string_to_buffer(buf, "}")
+
 
 		for i := 0; i < info.count; i++ {
 			if i > 0 {
@@ -420,8 +421,8 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
 
 	case Slice:
 		slice := arg.data as ^[]byte
-		print_string_to_buffer(buf, "[")
-		defer print_string_to_buffer(buf, "]")
+		bprintf(buf, "[]%{", info.elem)
+		defer print_string_to_buffer(buf, "}")
 
 		for i := 0; i < slice.count; i++ {
 			if i > 0 {
@@ -443,8 +444,8 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
 			return false
 		}
 
-		print_string_to_buffer(buf, "<")
-		defer print_string_to_buffer(buf, ">")
+		bprintf(buf, "{%}%{", info.count, info.elem)
+		defer print_string_to_buffer(buf, "}")
 
 		if is_bool(info.elem) {
 			return
@@ -461,8 +462,7 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
 
 
 	case Struct:
-		print_string_to_buffer(buf, "struct")
-		print_string_to_buffer(buf, "{")
+		bprintf(buf, "%{", arg.type_info)
 		defer print_string_to_buffer(buf, "}")
 
 		for i := 0; i < info.fields.count; i++ {

+ 1 - 1
core/hash.odin

@@ -138,7 +138,7 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
 			len -= 4
 		}
 
-		data8 := slice_ptr(ptr_offset(data.data, i) as ^u8, 3) // NOTE(bill): This is unsafe
+		data8 := slice_ptr((data.data+i) as ^u8, 3) // NOTE(bill): This is unsafe
 
 		match len {
 		case 3: h2 ~= data8[2] as u32 << 16; fallthrough

+ 44 - 2
src/checker/checker.cpp

@@ -181,6 +181,23 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("enum_to_string"),   1, false, Expr_Expr},
 };
 
+enum ImplicitValueId {
+	ImplicitValue_Invalid,
+
+	ImplicitValue_context,
+
+	ImplicitValue_Count,
+};
+struct ImplicitValueInfo {
+	String  name;
+	String  backing_name;
+	Type *  type;
+};
+// NOTE(bill): This is initialized later
+gb_global ImplicitValueInfo implicit_value_infos[ImplicitValue_Count] = {};
+
+
+
 struct CheckerContext {
 	Scope *scope;
 	DeclInfo *decl;
@@ -199,6 +216,8 @@ struct CheckerInfo {
 	Map<isize>             type_info_map;   // Key: Type *
 	Map<AstFile *>         files;           // Key: String
 	isize                  type_info_index;
+
+	Entity *               implicit_values[ImplicitValue_Count];
 };
 
 struct Checker {
@@ -423,8 +442,9 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
 	String name = entity->token.string;
 	HashKey key = hash_string(name);
 	Entity **found = map_get(&s->elements, key);
-	if (found)
+	if (found) {
 		return *found;
+	}
 	map_set(&s->elements, key, entity);
 	if (entity->scope == NULL) {
 		entity->scope = s;
@@ -950,8 +970,17 @@ void init_preload_types(Checker *c) {
 		t_context = e->type;
 		t_context_ptr = make_type_pointer(c->allocator, t_context);
 
-		add_global_entity(make_entity_implicit_value(gb_heap_allocator(), make_string("context"), t_context));
 	}
+
+}
+
+void add_implicit_value(Checker *c, ImplicitValueId id, String name, String backing_name, Type *type) {
+	ImplicitValueInfo info = {name, backing_name, type};
+	Entity *value = make_entity_implicit_value(c->allocator, info.name, info.type, id);
+	Entity *prev = scope_insert_entity(c->global_scope, value);
+	GB_ASSERT(prev == NULL);
+	implicit_value_infos[id] = info;
+	c->info.implicit_values[id] = value;
 }
 
 void check_parsed_files(Checker *c) {
@@ -1228,11 +1257,24 @@ void check_parsed_files(Checker *c) {
 	check_global_entity(c, Entity_TypeName);
 
 	init_preload_types(c);
+	add_implicit_value(c, ImplicitValue_context, make_string("context"), make_string("__context"), t_context);
 
 	check_global_entity(c, Entity_Constant);
 	check_global_entity(c, Entity_Procedure);
 	check_global_entity(c, Entity_Variable);
 
+	for (isize i = 1; i < ImplicitValue_Count; i++) {
+		// NOTE(bill): First is invalid
+		Entity *e = c->info.implicit_values[i];
+		GB_ASSERT(e->kind == Entity_ImplicitValue);
+
+		ImplicitValueInfo *ivi = &implicit_value_infos[i];
+		Entity *backing = scope_lookup_entity(e->scope, ivi->backing_name);
+		GB_ASSERT(backing != NULL);
+		e->ImplicitValue.backing = backing;
+	}
+
+
 	// Check procedure bodies
 	for_array(i, c->procs) {
 		ProcedureInfo *pi = &c->procs[i];

+ 8 - 3
src/checker/entity.cpp

@@ -2,6 +2,7 @@ struct Scope;
 struct Checker;
 struct Type;
 enum BuiltinProcId;
+enum ImplicitValueId;
 
 #define ENTITY_KINDS \
 	ENTITY_KIND(Invalid), \
@@ -63,10 +64,13 @@ struct Entity {
 			String path;
 			String name;
 			Scope *scope;
-			b32 used;
+			b32    used;
 		} ImportName;
 		struct {} Nil;
-		struct {} ImplicitValue;
+		struct {
+			ImplicitValueId id;
+			Entity *        backing;
+		} ImplicitValue;
 	};
 };
 
@@ -160,9 +164,10 @@ Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
 	return entity;
 }
 
-Entity *make_entity_implicit_value(gbAllocator a, String name, Type *type) {
+Entity *make_entity_implicit_value(gbAllocator a, String name, Type *type, ImplicitValueId id) {
 	Token token = make_token_ident(name);
 	Entity *entity = alloc_entity(a, Entity_ImplicitValue, NULL, token, type);
+	entity->ImplicitValue.id = id;
 	return entity;
 }
 

+ 6 - 1
src/checker/expr.cpp

@@ -3677,7 +3677,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 
 		default: {
 			gbString str = type_to_string(type);
-			error(ast_node_token(node), "Invalid or unyet supported compound literal type `%s`", str);
+			error(ast_node_token(node), "Invalid compound literal type `%s`", str);
 			gb_string_free(str);
 			goto error;
 		} break;
@@ -4187,6 +4187,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, pt->type);
 	case_end;
 
+	case_ast_node(mt, MaybeType, node);
+		str = gb_string_appendc(str, "?");
+		str = write_expr_to_string(str, mt->type);
+	case_end;
+
 	case_ast_node(at, ArrayType, node);
 		str = gb_string_appendc(str, "[");
 		str = write_expr_to_string(str, at->count);

+ 10 - 6
src/checker/type.cpp

@@ -1102,8 +1102,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 		BasicKind kind = t->Basic.kind;
 		if (kind < gb_count_of(basic_type_sizes)) {
 			i64 size = basic_type_sizes[kind];
-			if (size > 0)
+			if (size > 0) {
 				return size;
+			}
 		}
 		if (kind == Basic_string) {
 			return 2 * s.word_size;
@@ -1114,8 +1115,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 
 	case Type_Array: {
 		i64 count = t->Array.count;
-		if (count == 0)
+		if (count == 0) {
 			return 0;
+		}
 		i64 align = type_align_of(s, allocator, t->Array.elem);
 		i64 size  = type_size_of(s,  allocator, t->Array.elem);
 		i64 alignment = align_formula(size, align);
@@ -1124,8 +1126,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 
 	case Type_Vector: {
 		i64 count = t->Vector.count;
-		if (count == 0)
+		if (count == 0) {
 			return 0;
+		}
 		// i64 align = type_align_of(s, allocator, t->Vector.elem);
 		i64 bit_size = 8*type_size_of(s,  allocator, t->Vector.elem);
 		if (is_type_boolean(t->Vector.elem)) {
@@ -1169,8 +1172,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 			// NOTE(bill): Zeroth field is invalid
 			for (isize i = 1; i < count; i++) {
 				i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
-				if (max < size)
+				if (max < size) {
 					max = size;
+				}
 			}
 			// NOTE(bill): Align to int
 			i64 align = type_align_of(s, allocator, t);
@@ -1184,8 +1188,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 			i64 max = 0;
 			for (isize i = 0; i < count; i++) {
 				i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
-				if (max < size)
+				if (max < size) {
 					max = size;
+				}
 			}
 			// TODO(bill): Is this how it should work?
 			i64 align = type_align_of(s, allocator, t);
@@ -1211,7 +1216,6 @@ i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index)
 			return t->Record.struct_offsets[index];
 		}
 	} else if (t->kind == Type_Basic) {
-		gb_printf_err("here!!\n");
 		if (t->Basic.kind == Basic_string) {
 			switch (index) {
 			case 0: return 0;

+ 17 - 23
src/codegen/ssa.cpp

@@ -2306,21 +2306,22 @@ void ssa_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaV
 }
 
 ssaValue *ssa_find_global_variable(ssaProcedure *proc, String name) {
-	ssaValue *value = *map_get(&proc->module->members, hash_string(name));
-	return value;
+	ssaValue **value = map_get(&proc->module->members, hash_string(name));
+	GB_ASSERT_MSG(value != NULL, "Unable to find global variable `%.*s`", LIT(name));
+	return *value;
 }
 
-ssaValue *ssa_emit_implicit_value(ssaProcedure *proc, Entity *e) {
-	String name = e->token.string;
-	ssaValue *g = NULL;
-	if (name == "context") {
-		g = ssa_emit_load(proc, ssa_find_global_variable(proc, make_string("__context")));
-	}
-	GB_ASSERT(g != NULL);
-	return g;
+ssaValue *ssa_find_implicit_value_backing(ssaProcedure *proc, ImplicitValueId id) {
+	Entity *e = proc->module->info->implicit_values[id];
+	GB_ASSERT(e->kind == Entity_ImplicitValue);
+	Entity *backing = e->ImplicitValue.backing;
+	ssaValue **value = map_get(&proc->module->values, hash_pointer(backing));
+	GB_ASSERT_MSG(value != NULL, "Unable to find implicit value backing `%.*s`", LIT(backing->token.string));
+	return *value;
 }
 
 
+
 ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue *tv) {
 	switch (expr->kind) {
 	case_ast_node(bl, BasicLit, expr);
@@ -2338,7 +2339,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
 		} else if (e->kind == Entity_Nil) {
 			return ssa_make_value_nil(proc->module->allocator, tv->type);
 		} else if (e->kind == Entity_ImplicitValue) {
-			return ssa_emit_implicit_value(proc, e);
+			return ssa_emit_load(proc, ssa_find_implicit_value_backing(proc, e->ImplicitValue.id));
 		}
 
 		auto *found = map_get(&proc->module->values, hash_pointer(e));
@@ -3069,8 +3070,6 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
 	if (tv->value.kind != ExactValue_Invalid) {
 		if (tv->value.kind == ExactValue_String) {
 			ssa_emit_comment(proc, make_string("Emit string constant"));
-
-			// TODO(bill): Optimize by not allocating everytime
 			if (tv->value.value_string.len > 0) {
 				return ssa_emit_global_string(proc, tv->value.value_string);
 			} else {
@@ -3084,8 +3083,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
 
 	ssaValue *value = NULL;
 	if (tv->mode == Addressing_Variable) {
-		ssaAddr addr = ssa_build_addr(proc, expr);
-		value = ssa_lvalue_load(proc, addr);
+		value = ssa_lvalue_load(proc, ssa_build_addr(proc, expr));
 	} else {
 		value = ssa_build_single_expr(proc, expr, tv);
 	}
@@ -3122,8 +3120,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 
 		Entity *e = entity_of_ident(proc->module->info, expr);
 		TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(expr));
-		// GB_ASSERT(tv == NULL || tv->mode == Addressing_Variable);
-
 
 		if (e->kind == Entity_Constant) {
 			if (base_type(e->type) == t_string) {
@@ -3148,10 +3144,8 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 		} else if (e->kind == Entity_Variable && e->Variable.anonymous) {
 			v = ssa_add_using_variable(proc, e);
 		} else if (e->kind == Entity_ImplicitValue) {
-			ssaValue *g = ssa_emit_implicit_value(proc, e);
-			// NOTE(bill): Create a copy as it's by value
-			v = ssa_add_local_generated(proc, ssa_type(g));
-			ssa_emit_store(proc, v, g);
+			// TODO(bill): Should a copy be made?
+			v = ssa_find_implicit_value_backing(proc, e->ImplicitValue.id);
 		}
 
 		if (v == NULL) {
@@ -4210,7 +4204,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 		ssa_open_scope(proc);
 		defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
 
-		ssaValue *context_ptr = ssa_find_global_variable(proc, make_string("__context"));
+		ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
 		ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
 		ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
 
@@ -4229,7 +4223,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 		ssa_open_scope(proc);
 		defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
 
-		ssaValue *context_ptr = ssa_find_global_variable(proc, make_string("__context"));
+		ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
 		ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
 		ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
 

+ 26 - 26
src/gb/gb.h

@@ -1928,7 +1928,7 @@ typedef union gbFileDescriptor {
 
 typedef struct gbFileOperations gbFileOperations;
 
-#define GB_FILE_OPEN_PROC(name)     gbFileError name(gbFileDescriptor *fd, gbFileOperations const **ops, gbFileMode mode, char const *filename)
+#define GB_FILE_OPEN_PROC(name)     gbFileError name(gbFileDescriptor *fd, gbFileOperations *ops, gbFileMode mode, char const *filename)
 #define GB_FILE_READ_AT_PROC(name)  b32         name(gbFileDescriptor fd, void *buffer, isize size, i64 offset, isize *bytes_read)
 #define GB_FILE_WRITE_AT_PROC(name) b32         name(gbFileDescriptor fd, void const *buffer, isize size, i64 offset, isize *bytes_written)
 #define GB_FILE_SEEK_PROC(name)     b32         name(gbFileDescriptor fd, i64 offset, gbSeekWhenceType whence, i64 *new_offset)
@@ -1958,11 +1958,11 @@ extern gbFileOperations const gbDefaultFileOperations;
 typedef u64 gbFileTime;
 
 typedef struct gbFile {
-	gbFileOperations const *ops;
-	gbFileDescriptor        fd;
-	char const *            filename;
-	gbFileTime              last_write_time;
-	// gbDirInfo *          dir_info; // TODO(bill): Get directory info
+	gbFileOperations ops;
+	gbFileDescriptor fd;
+	char const *     filename;
+	gbFileTime       last_write_time;
+	// gbDirInfo *   dir_info; // TODO(bill): Get directory info
 } gbFile;
 
 // TODO(bill): gbAsyncFile
@@ -1980,7 +1980,7 @@ GB_DEF gbFile *const gb_file_get_standard(gbFileStandardType std);
 GB_DEF gbFileError gb_file_create        (gbFile *file, char const *filename);
 GB_DEF gbFileError gb_file_open          (gbFile *file, char const *filename);
 GB_DEF gbFileError gb_file_open_mode     (gbFile *file, gbFileMode mode, char const *filename);
-GB_DEF gbFileError gb_file_new           (gbFile *file, gbFileDescriptor fd, gbFileOperations const *ops, char const *filename);
+GB_DEF gbFileError gb_file_new           (gbFile *file, gbFileDescriptor fd, gbFileOperations ops, char const *filename);
 GB_DEF b32         gb_file_read_at_check (gbFile *file, void *buffer, isize size, i64 offset, isize *bytes_read);
 GB_DEF b32         gb_file_write_at_check(gbFile *file, void const *buffer, isize size, i64 offset, isize *bytes_written);
 GB_DEF b32         gb_file_read_at       (gbFile *file, void *buffer, isize size, i64 offset);
@@ -7299,7 +7299,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
 		}
 
 		fd->p = handle;
-		*ops = &gbDefaultFileOperations;
+		*ops = gbDefaultFileOperations;
 		return gbFileError_None;
 	}
 
@@ -7381,7 +7381,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
 			return gbFileError_Invalid;
 		}
 
-		*ops = &gbDefaultFileOperations;
+		*ops = gbDefaultFileOperations;
 		return gbFileError_None;
 	}
 
@@ -7389,7 +7389,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) {
 
 
 
-gbFileError gb_file_new(gbFile *f, gbFileDescriptor fd, gbFileOperations const *ops, char const *filename) {
+gbFileError gb_file_new(gbFile *f, gbFileDescriptor fd, gbFileOperations ops, char const *filename) {
 	gbFileError err = gbFileError_None;
 
 	f->ops = ops;
@@ -7428,20 +7428,20 @@ gbFileError gb_file_close(gbFile *f) {
 		return gbFileError_Invalid;
 #endif
 
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	f->ops->close(f->fd);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	f->ops.close(f->fd);
 
 	return gbFileError_None;
 }
 
 gb_inline b32 gb_file_read_at_check(gbFile *f, void *buffer, isize size, i64 offset, isize *bytes_read) {
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	return f->ops->read_at(f->fd, buffer, size, offset, bytes_read);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	return f->ops.read_at(f->fd, buffer, size, offset, bytes_read);
 }
 
 gb_inline b32 gb_file_write_at_check(gbFile *f, void const *buffer, isize size, i64 offset, isize *bytes_written) {
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	return f->ops->write_at(f->fd, buffer, size, offset, bytes_written);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	return f->ops.write_at(f->fd, buffer, size, offset, bytes_written);
 }
 
 
@@ -7455,30 +7455,30 @@ gb_inline b32 gb_file_write_at(gbFile *f, void const *buffer, isize size, i64 of
 
 gb_inline i64 gb_file_seek(gbFile *f, i64 offset) {
 	i64 new_offset = 0;
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	f->ops->seek(f->fd, offset, gbSeekWhence_Begin, &new_offset);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	f->ops.seek(f->fd, offset, gbSeekWhence_Begin, &new_offset);
 	return new_offset;
 }
 
 gb_inline i64 gb_file_seek_to_end(gbFile *f) {
 	i64 new_offset = 0;
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	f->ops->seek(f->fd, 0, gbSeekWhence_End, &new_offset);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	f->ops.seek(f->fd, 0, gbSeekWhence_End, &new_offset);
 	return new_offset;
 }
 
 // NOTE(bill): Skips a certain amount of bytes
 gb_inline i64 gb_file_skip(gbFile *f, i64 bytes) {
 	i64 new_offset = 0;
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	f->ops->seek(f->fd, bytes, gbSeekWhence_Current, &new_offset);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	f->ops.seek(f->fd, bytes, gbSeekWhence_Current, &new_offset);
 	return new_offset;
 }
 
 gb_inline i64 gb_file_tell(gbFile *f) {
 	i64 new_offset = 0;
-	if (!f->ops) f->ops = &gbDefaultFileOperations;
-	f->ops->seek(f->fd, 0, gbSeekWhence_Current, &new_offset);
+	if (!f->ops.read_at) f->ops = gbDefaultFileOperations;
+	f->ops.seek(f->fd, 0, gbSeekWhence_Current, &new_offset);
 	return new_offset;
 }
 gb_inline b32 gb_file_read (gbFile *f, void *buffer, isize size)       { return gb_file_read_at(f, buffer, size, gb_file_tell(f)); }
@@ -7516,7 +7516,7 @@ gb_global gbFile gb__std_files[gbFileStandard_Count] = {{0}};
 
 gb_inline gbFile *const gb_file_get_standard(gbFileStandardType std) {
 	if (!gb__std_file_set) {
-	#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.p = v; gb__std_files[type].ops = &gbDefaultFileOperations
+	#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.p = v; gb__std_files[type].ops = gbDefaultFileOperations
 		GB__SET_STD_FILE(gbFileStandard_Input,  GetStdHandle(STD_INPUT_HANDLE));
 		GB__SET_STD_FILE(gbFileStandard_Output, GetStdHandle(STD_OUTPUT_HANDLE));
 		GB__SET_STD_FILE(gbFileStandard_Error,  GetStdHandle(STD_ERROR_HANDLE));
@@ -7555,7 +7555,7 @@ b32 gb_file_exists(char const *name) {
 
 gb_inline gbFile *const gb_file_get_standard(gbFileStandardType std) {
 	if (!gb__std_file_set) {
-	#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.i = v; gb__std_files[type].ops = &gbDefaultFileOperations
+	#define GB__SET_STD_FILE(type, v) gb__std_files[type].fd.i = v; gb__std_files[type].ops = gbDefaultFileOperations
 		GB__SET_STD_FILE(gbFileStandard_Input,  0);
 		GB__SET_STD_FILE(gbFileStandard_Output, 1);
 		GB__SET_STD_FILE(gbFileStandard_Error,  2);

+ 11 - 11
src/string.cpp

@@ -115,17 +115,17 @@ GB_COMPARE_PROC(string_cmp_proc) {
 }
 
 
-bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
-bool operator !=(String a, String b) { return !operator==(a, b); }
-bool operator < (String a, String b) { return string_compare(a, b) < 0; }
-bool operator > (String a, String b) { return string_compare(a, b) > 0; }
-bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
-bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
-
-template <size_t N> bool operator ==(String a, char const (&b)[N]) { return a == make_string(b); }
-template <size_t N> bool operator !=(String a, char const (&b)[N]) { return a != make_string(b); }
-template <size_t N> bool operator ==(char const (&a)[N], String b) { return make_string(a) == b; }
-template <size_t N> bool operator !=(char const (&a)[N], String b) { return make_string(a) != b; }
+gb_inline bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
+gb_inline bool operator !=(String a, String b) { return !operator==(a, b); }
+gb_inline bool operator < (String a, String b) { return string_compare(a, b) < 0; }
+gb_inline bool operator > (String a, String b) { return string_compare(a, b) > 0; }
+gb_inline bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
+gb_inline bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
+
+template <size_t N> gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); }
+template <size_t N> gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); }
+template <size_t N> gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; }
+template <size_t N> gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; }