Преглед изворни кода

Add `types.odin`; Begin work on `map`

Ginger Bill пре 8 година
родитељ
комит
b1562edccf
10 измењених фајлова са 360 додато и 30 уклоњено
  1. 5 1
      code/demo.odin
  2. 12 0
      core/_preload.odin
  3. 54 1
      core/hash.odin
  4. 146 0
      core/types.odin
  5. 3 0
      src/build.c
  6. 0 1
      src/check_expr.c
  7. 8 0
      src/checker.c
  8. 8 0
      src/ir.c
  9. 12 0
      src/ir_print.c
  10. 112 27
      src/types.c

+ 5 - 1
code/demo.odin

@@ -11,7 +11,11 @@
 
 
 main :: proc() {
-	T0 :: struct #align 8 {};
+	Value :: type f32;
+	m0: map[int]Value;
+	m1: map[string]Value;
+	m2: map[f32]Value;
+	// fm: map[128, int]f32;
 
 /*
 	{

+ 12 - 0
core/_preload.odin

@@ -4,6 +4,7 @@
 #import "fmt.odin";
 #import "mem.odin";
 #import "utf8.odin";
+#import "hash.odin";
 
 // IMPORTANT NOTE(bill): `type_info` & `type_info_val` cannot be used within a
 // #shared_global_scope due to  the internals of the compiler.
@@ -346,6 +347,16 @@ Raw_Dynamic_Array :: struct #ordered {
 	allocator: Allocator,
 };
 
+Raw_Dynamic_Map :: struct #ordered {
+	hashes:  [dynamic]int,
+	entries: Raw_Dynamic_Array,
+};
+
+__default_hash :: proc(data: rawptr, len: int) -> u64 {
+	return hash.murmur64(data, len);
+}
+
+
 __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, capacity: int) -> bool {
 	array := cast(^Raw_Dynamic_Array)array_;
 
@@ -398,3 +409,4 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
 	array.count += item_count;
 	return array.count;
 }
+

+ 54 - 1
core/hash.odin

@@ -50,13 +50,66 @@ fnv32a :: proc(data: rawptr, len: int) -> u32 {
 fnv64a :: proc(data: rawptr, len: int) -> u64 {
 	s := slice_ptr(cast(^u8)data, len);
 
-	h :u64 = 0xcbf29ce484222325;
+	h: u64 = 0xcbf29ce484222325;
 	for i in 0..<len {
 		h = (h ~ cast(u64)s[i]) * 0x100000001b3;
 	}
 	return h;
 }
 
+murmur32 :: proc(data: rawptr, len: int) -> u32 {
+	compile_assert(ODIN_ENDIAN == "little");
+
+	SEED :: 0x9747b28c;
+
+	key := cast(^u8)data;
+	h: u32 = SEED;
+
+	if len > 3 {
+		key_x4 := cast(^u32)key;
+		i := len>>2;
+		for {
+			k := key_x4^; key_x4 += 1;
+			k *= 0xcc9e2d51;
+			k = (k << 15) | (k >> 17);
+			k *= 0x1b873593;
+			h ~= k;
+			h = (h << 13) | (h >> 19);
+			h += (h << 2) + 0xe6546b64;
+			i -= 1;
+			if i == 0 {
+				break;
+			}
+		}
+		key = cast(^u8)key_x4;
+	}
+	if len&3 != 0 {
+		i := len&3;
+		k: u32 = 0;
+		key += i-1;
+		for {
+			k <<= 8;
+			k |= cast(u32)key^;
+			key -= 1;
+			i -= 1;
+			if i == 0 {
+				break;
+			}
+		}
+		k *= 0xcc9e2d51;
+		k = (k << 15) | (k >> 17);
+		k *= 0x1b873593;
+		h ~= k;
+	}
+
+	h ~= cast(u32)len;
+	h ~= h >> 16;
+	h *= 0x85ebca6b;
+	h ~= h >> 13;
+	h *= 0xc2b2ae35;
+	h ~= h >> 16;
+	return h;
+}
 
 murmur64 :: proc(data_: rawptr, len: int) -> u64 {
 	SEED :: 0x9747b28c;

+ 146 - 0
core/types.odin

@@ -0,0 +1,146 @@
+is_signed :: proc(info: ^Type_Info) -> bool {
+	if is_integer(info) {
+		i := cast(^Type_Info.Integer)info;
+		return i.signed;
+	}
+	if is_float(info) {
+		return true;
+	}
+	return false;
+}
+is_integer :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Integer: return true;
+	}
+	return false;
+}
+is_float :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Float: return true;
+	}
+	return false;
+}
+is_any :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Any: return true;
+	}
+	return false;
+}
+is_string :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.String: return true;
+	}
+	return false;
+}
+is_boolean :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Boolean: return true;
+	}
+	return false;
+}
+is_pointer :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Pointer: return true;
+	}
+	return false;
+}
+is_maybe :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Maybe: return true;
+	}
+	return false;
+}
+is_procedure :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Procedure: return true;
+	}
+	return false;
+}
+is_array :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Array: return true;
+	}
+	return false;
+}
+is_dynamic_array :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Dynamic_Array: return true;
+	}
+	return false;
+}
+is_slice :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Slice: return true;
+	}
+	return false;
+}
+is_vector :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Vector: return true;
+	}
+	return false;
+}
+is_tuple :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Tuple: return true;
+	}
+	return false;
+}
+is_struct :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Struct: return true;
+	}
+	return false;
+}
+is_union :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Union: return true;
+	}
+	return false;
+}
+is_raw_union :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Raw_Union: return true;
+	}
+	return false;
+}
+is_enum :: proc(info: ^Type_Info) -> bool {
+	if info == nil { return false; }
+
+	match type i in type_info_base(info) {
+	case Type_Info.Enum: return true;
+	}
+	return false;
+}

+ 3 - 0
src/build.c

@@ -1,6 +1,7 @@
 typedef struct BuildContext {
 	String ODIN_OS;      // target operating system
 	String ODIN_ARCH;    // target architecture
+	String ODIN_ENDIAN;  // target endian
 	String ODIN_VENDOR;  // compiler vendor
 	String ODIN_VERSION; // compiler version
 	String ODIN_ROOT;    // Odin ROOT
@@ -243,9 +244,11 @@ void init_build_context(BuildContext *bc) {
 #if defined(GB_SYSTEM_WINDOWS)
 	bc->ODIN_OS      = str_lit("windows");
 	bc->ODIN_ARCH    = str_lit("amd64");
+	bc->ODIN_ENDIAN  = str_lit("little");
 #elif defined(GB_SYSTEM_OSX)
 	bc->ODIN_OS      = str_lit("osx");
 	bc->ODIN_ARCH    = str_lit("amd64");
+	bc->ODIN_ENDIAN  = str_lit("little");
 #else
 #error Implement system
 #endif

Разлика између датотеке није приказан због своје велике величине
+ 0 - 1
src/check_expr.c


+ 8 - 0
src/checker.c

@@ -28,6 +28,7 @@ typedef enum BuiltinProcId {
 	BuiltinProc_free,
 
 	BuiltinProc_reserve,
+	BuiltinProc_clear,
 	BuiltinProc_append,
 
 	BuiltinProc_size_of,
@@ -69,6 +70,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("free"),             1, false, Expr_Stmt},
 
 	{STR_LIT("reserve"),          2, false, Expr_Stmt},
+	{STR_LIT("clear"),            1, false, Expr_Stmt},
 	{STR_LIT("append"),           1, true,  Expr_Expr},
 
 	{STR_LIT("size_of"),          1, false, Expr_Expr},
@@ -610,6 +612,7 @@ void init_universal_scope(BuildContext *bc) {
 	// TODO(bill): Set through flags in the compiler
 	add_global_string_constant(a, str_lit("ODIN_OS"),      bc->ODIN_OS);
 	add_global_string_constant(a, str_lit("ODIN_ARCH"),    bc->ODIN_ARCH);
+	add_global_string_constant(a, str_lit("ODIN_ENDIAN"),  bc->ODIN_ENDIAN);
 	add_global_string_constant(a, str_lit("ODIN_VENDOR"),  bc->ODIN_VENDOR);
 	add_global_string_constant(a, str_lit("ODIN_VERSION"), bc->ODIN_VERSION);
 	add_global_string_constant(a, str_lit("ODIN_ROOT"),    bc->ODIN_ROOT);
@@ -1141,6 +1144,11 @@ void init_preload(Checker *c) {
 		t_context_ptr = make_type_pointer(c->allocator, t_context);
 	}
 
+	if (t_raw_dynamic_array == NULL) {
+		Entity *e = find_core_entity(c, str_lit("Raw_Dynamic_Array"));
+		t_raw_dynamic_array = e->type;
+	}
+
 	c->done_preload = true;
 }
 

+ 8 - 0
src/ir.c

@@ -2987,6 +2987,14 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 					return ir_emit_global_call(proc, "__dynamic_array_reserve", args, 4);
 				} break;
 
+				case BuiltinProc_clear: {
+					ir_emit_comment(proc, str_lit("reserve"));
+					irValue *array_ptr = ir_build_expr(proc, ce->args.e[0]);
+					irValue *count_ptr = ir_emit_struct_ep(proc, array_ptr, 1);
+					ir_emit_store(proc, count_ptr, v_zero);
+					return NULL;
+				} break;
+
 				case BuiltinProc_append: {
 					ir_emit_comment(proc, str_lit("append"));
 					gbAllocator a = proc->module->allocator;

+ 12 - 0
src/ir_print.c

@@ -292,6 +292,18 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 		}
 		ir_fprintf(f, ")*");
 	} return;
+
+	case Type_Map: {
+		if (t->Map.count > 0) {
+			// ir_fprintf(f, "void");
+		} else {
+			ir_fprintf(f, "{");
+			ir_print_type(f, m, t_raw_dynamic_array);
+			ir_fprintf(f, ", ");
+			ir_print_type(f, m, t_raw_dynamic_array);
+			ir_fprintf(f, "}");
+		}
+	} break;
 	}
 }
 

+ 112 - 27
src/types.c

@@ -95,35 +95,40 @@ typedef struct TypeRecord {
 	Entity * enum_max_value;
 } TypeRecord;
 
-#define TYPE_KINDS \
-	TYPE_KIND(Basic,   BasicType) \
-	TYPE_KIND(Pointer, struct { Type *elem; }) \
+#define TYPE_KINDS                                        \
+	TYPE_KIND(Basic,   BasicType)                         \
+	TYPE_KIND(Pointer, struct { Type *elem; })            \
 	TYPE_KIND(Array,   struct { Type *elem; i64 count; }) \
-	TYPE_KIND(DynamicArray, struct { Type *elem; }) \
+	TYPE_KIND(DynamicArray, struct { Type *elem; })       \
 	TYPE_KIND(Vector,  struct { Type *elem; i64 count; }) \
-	TYPE_KIND(Slice,   struct { Type *elem; }) \
-	TYPE_KIND(Maybe,   struct { Type *elem; }) \
-	TYPE_KIND(Record,  TypeRecord) \
-	TYPE_KIND(Named, struct { \
-		String  name; \
-		Type *  base; \
-		Entity *type_name; /* Entity_TypeName */ \
-	}) \
-	TYPE_KIND(Tuple, struct { \
-		Entity **variables; /* Entity_Variable */ \
-		i32      variable_count; \
-		bool     are_offsets_set; \
-		i64 *    offsets; \
-	}) \
-	TYPE_KIND(Proc, struct { \
-		Scope *scope; \
-		Type * params;  /* Type_Tuple */ \
-		Type * results; /* Type_Tuple */ \
-		i32    param_count; \
-		i32    result_count; \
-		bool   variadic; \
-		ProcCallingConvention calling_convention; \
-	})
+	TYPE_KIND(Slice,   struct { Type *elem; })            \
+	TYPE_KIND(Maybe,   struct { Type *elem; })            \
+	TYPE_KIND(Record,  TypeRecord)                        \
+	TYPE_KIND(Named, struct {                             \
+		String  name;                                     \
+		Type *  base;                                     \
+		Entity *type_name; /* Entity_TypeName */          \
+	})                                                    \
+	TYPE_KIND(Tuple, struct {                             \
+		Entity **variables; /* Entity_Variable */         \
+		i32      variable_count;                          \
+		bool     are_offsets_set;                         \
+		i64 *    offsets;                                 \
+	})                                                    \
+	TYPE_KIND(Proc, struct {                              \
+		Scope *scope;                                     \
+		Type * params;  /* Type_Tuple */                  \
+		Type * results; /* Type_Tuple */                  \
+		i32    param_count;                               \
+		i32    result_count;                              \
+		bool   variadic;                                  \
+		ProcCallingConvention calling_convention;         \
+	})                                                    \
+	TYPE_KIND(Map, struct {                               \
+		i64   count; /* 0 if dynamic */                   \
+		Type *key;                                        \
+		Type *value;                                      \
+	})                                                    \
 
 
 
@@ -319,6 +324,7 @@ gb_global Type *t_allocator_ptr        = NULL;
 gb_global Type *t_context              = NULL;
 gb_global Type *t_context_ptr          = NULL;
 
+gb_global Type *t_raw_dynamic_array    = NULL;
 
 
 
@@ -477,6 +483,23 @@ Type *make_type_proc(gbAllocator a, Scope *scope, Type *params, isize param_coun
 	return t;
 }
 
+bool is_type_valid_for_keys(Type *t);
+
+Type *make_type_map(gbAllocator a, i64 count, Type *key, Type *value) {
+	Type *t = alloc_type(a, Type_Map);
+	if (key != NULL) {
+		GB_ASSERT(is_type_valid_for_keys(key));
+	}
+	t->Map.count = count;
+	t->Map.key   = key;
+	t->Map.value = value;
+	return t;
+}
+
+
+
+
+
 
 Type *type_deref(Type *t) {
 	if (t != NULL) {
@@ -679,6 +702,21 @@ bool is_type_enum(Type *t) {
 	return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
 }
 
+bool is_type_map(Type *t) {
+	t = base_type(t);
+	return t->kind == Type_Map;
+}
+
+bool is_type_fixed_map(Type *t) {
+	t = base_type(t);
+	return t->kind == Type_Map && t->Map.count > 0;
+}
+bool is_type_dynamic_map(Type *t) {
+	t = base_type(t);	return t->kind == Type_Map && t->Map.count == 0;
+}
+
+
+
 
 bool is_type_any(Type *t) {
 	t = base_type(t);
@@ -691,6 +729,28 @@ bool is_type_untyped_nil(Type *t) {
 
 
 
+bool is_type_valid_for_keys(Type *t) {
+	t = base_type(base_enum_type(t));
+	if (is_type_untyped(t)) {
+		return false;
+	}
+	if (is_type_integer(t)) {
+		return true;
+	}
+	if (is_type_float(t)) {
+		return true;
+	}
+	if (is_type_string(t)) {
+		return true;
+	}
+	if (is_type_pointer(t)) {
+		return true;
+	}
+
+	return false;
+}
+
+
 bool is_type_indexable(Type *t) {
 	return is_type_array(t) || is_type_slice(t) || is_type_vector(t) || is_type_string(t);
 }
@@ -1458,6 +1518,14 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
 		return align;
 	}
 
+	case Type_Map: {
+		if (t->Map.count == 0) { // Dynamic
+			// NOTE(bill): same as a dynamic array
+			return s.word_size;
+		}
+		GB_PANIC("TODO(bill): Fixed map alignment");
+	} break;
+
 	case Type_Record: {
 		switch (t->Record.kind) {
 		case TypeRecord_Struct:
@@ -1667,6 +1735,14 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
 		return align_formula(size, align);
 	}
 
+	case Type_Map: {
+		if (t->Map.count == 0) { // Dynamic
+			// NOTE(bill): same as a two dynamic arrays
+			return 2 * type_size_of_internal(s, allocator, t_raw_dynamic_array, path);
+		}
+		GB_PANIC("TODO(bill): Fixed map size");
+	}
+
 	case Type_Tuple: {
 		i64 count, align, size;
 		count = t->Tuple.variable_count;
@@ -1924,6 +2000,15 @@ gbString write_type_to_string(gbString str, Type *type) {
 		}
 	} break;
 
+	case Type_Map: {
+		str = gb_string_appendc(str, "map[");
+		if (type->Map.count > 0) {
+			str = gb_string_appendc(str, gb_bprintf("%lld, ", type->Map.count));
+		}
+		str = write_type_to_string(str, type->Map.key);
+		str = gb_string_appendc(str, "]");
+		str = write_type_to_string(str, type->Map.value);
+	} break;
 
 	case Type_Named:
 		if (type->Named.type_name != NULL) {

Неке датотеке нису приказане због велике количине промена