Add types.odin; Begin work on map

This commit is contained in:
Ginger Bill
2017-02-05 18:17:55 +00:00
parent 2a5b674d33
commit b1562edccf
10 changed files with 442 additions and 40 deletions

View File

@@ -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;
/*
{

View File

@@ -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;
}

View File

@@ -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
core/types.odin Normal file
View File

@@ -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;
}

View File

@@ -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

File diff suppressed because one or more lines are too long

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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) {