diff --git a/code/demo.odin b/code/demo.odin index d44f7dca3..c4e44aebd 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -11,14 +11,18 @@ main :: proc() { - m: map[int]u32; + m: map[string]u32; reserve(^m, 16); defer free(m); - m[123] = 345; - fmt.println(m[123]); - if x, ok := m[123]; ok { - fmt.println(x); + m["a"] = 56; + m["b"] = 13453; + m["c"] = 7654; + c, ok := m["c"]; + assert(ok && c == 7654); + + for val, key in m { + fmt.printf("m[\"%s\"] == %v\n", key, val); } diff --git a/core/_preload.odin b/core/_preload.odin index 1fb821fea..ec473348e 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -438,7 +438,10 @@ __dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: in __default_hash :: proc(data: []byte) -> u64 { - return hash.murmur64(data); + return hash.fnv64a(data); +} +__default_hash_string :: proc(s: string) -> u64 { + return __default_hash(cast([]byte)s); } Map_Key :: struct #ordered { diff --git a/src/check_expr.c b/src/check_expr.c index 20b041e08..112fae2af 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1136,7 +1136,7 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { /* struct { - hash: u64, + hash: Map_Key, next: int, key: Key_Type, value: Value_Type, @@ -1148,9 +1148,9 @@ void check_map_type(Checker *c, Type *type, AstNode *node) { isize field_count = 3; Entity **fields = gb_alloc_array(a, Entity *, field_count); - fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_u64, false, false); - fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, false); - fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, false); + fields[0] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_map_key, false, false); + fields[1] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, false); + fields[2] = make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, false); check_close_scope(c); diff --git a/src/check_stmt.c b/src/check_stmt.c index 489b97fb4..83d3939e8 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -723,6 +723,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { val = t->Vector.elem; idx = t_int; break; + + case Type_Map: + val = t->Map.value; + idx = t->Map.key; + break; } } diff --git a/src/ir.c b/src/ir.c index d5f52a27a..7d04a0dd4 100644 --- a/src/ir.c +++ b/src/ir.c @@ -975,6 +975,9 @@ irValue *ir_make_const_i32(gbAllocator a, i64 i) { irValue *ir_make_const_i64(gbAllocator a, i64 i) { return ir_make_value_constant(a, t_i64, make_exact_value_integer(i)); } +irValue *ir_make_const_u64(gbAllocator a, u64 i) { + return ir_make_value_constant(a, t_u64, make_exact_value_integer(i)); +} irValue *ir_make_const_f32(gbAllocator a, f32 f) { return ir_make_value_constant(a, t_f32, make_exact_value_float(f)); } @@ -1418,15 +1421,28 @@ irValue *ir_gen_map_header(irProcedure *proc, irValue *map_val, Type *map_type) irValue *ir_gen_map_key(irProcedure *proc, irValue *key) { irValue *v = ir_add_local_generated(proc, t_map_key); - irValue *hash = ir_emit_struct_ep(proc, v, 0); Type *t = base_type(ir_type(key)); if (is_type_integer(t)) { - ir_emit_store(proc, hash, ir_emit_conv(proc, key, t_u64)); + ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, key, t_u64)); } else if (is_type_pointer(t)) { irValue *p = ir_emit_conv(proc, key, t_uint); - ir_emit_store(proc, hash, ir_emit_conv(proc, p, t_u64)); + ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), ir_emit_conv(proc, p, t_u64)); } else { - GB_PANIC("TODO(bill): Map Key type"); + irValue *str = ir_emit_conv(proc, key, t_string); + irValue *hashed_str = NULL; + + if (str->kind == irValue_Constant) { + ExactValue ev = str->Constant.value; + GB_ASSERT(ev.kind == ExactValue_String); + u64 hs = gb_fnv64a(ev.value_string.text, ev.value_string.len); + hashed_str = ir_make_const_u64(proc->module->allocator, hs); + } else { + irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1); + args[0] = str; + hashed_str = ir_emit_global_call(proc, "__default_hash_string", args, 1); + } + ir_emit_store(proc, ir_emit_struct_ep(proc, v, 0), hashed_str); + ir_emit_store(proc, ir_emit_struct_ep(proc, v, 1), str); } return ir_emit_load(proc, v); @@ -4355,6 +4371,7 @@ void ir_emit_increment(irProcedure *proc, irValue *addr) { } + void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, irValue *count_ptr, irValue **val_, irValue **idx_, irBlock **loop_, irBlock **done_) { irValue *count = NULL; @@ -4374,6 +4391,11 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir irBlock *done = NULL; irBlock *body = NULL; + irValue *key = NULL; + if (expr_type->kind == Type_Map) { + key = ir_add_local_generated(proc, expr_type->Map.key); + } + irValue *index = ir_add_local_generated(proc, t_int); ir_emit_store(proc, index, ir_make_const_int(proc->module->allocator, -1)); @@ -4410,6 +4432,26 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir irValue *elem = ir_emit_struct_ep(proc, expr, 0); elem = ir_emit_load(proc, elem); val = ir_emit_load(proc, ir_emit_ptr_offset(proc, elem, idx)); + } break; + case Type_Map: { + irValue *entries = ir_emit_struct_ep(proc, expr, 1); + irValue *elem = ir_emit_struct_ep(proc, entries, 0); + elem = ir_emit_load(proc, elem); + + irValue *entry = ir_emit_ptr_offset(proc, elem, idx); + val = ir_emit_load(proc, ir_emit_struct_ep(proc, entry, 2)); + + irValue *hash = ir_emit_struct_ep(proc, entry, 0); + if (is_type_string(expr_type->Map.key)) { + irValue *str = ir_emit_struct_ep(proc, hash, 1); + ir_emit_store(proc, key, ir_emit_load(proc, str)); + } else { + irValue *hash_ptr = ir_emit_struct_ep(proc, hash, 0); + hash_ptr = ir_emit_conv(proc, hash_ptr, ir_type(key)); + ir_emit_store(proc, key, ir_emit_load(proc, hash_ptr)); + } + + } break; default: GB_PANIC("Cannot do range_indexed of %s", type_to_string(expr_type)); @@ -4417,6 +4459,10 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir } } + if (key != NULL) { + idx = ir_emit_load(proc, key); + } + if (val_) *val_ = val; if (idx_) *idx_ = idx; if (loop_) *loop_ = loop; @@ -4965,6 +5011,16 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { Type *expr_type = type_of_expr(proc->module->info, rs->expr); Type *et = base_type(type_deref(expr_type)); switch (et->kind) { + case Type_Map: { + irAddr addr = ir_build_addr(proc, rs->expr); + irValue *map = addr.addr; + if (is_type_pointer(type_deref(ir_addr_type(addr)))) { + map = ir_addr_load(proc, addr); + } + irValue *entries_ptr = ir_emit_struct_ep(proc, map, 1); + irValue *count_ptr = ir_emit_struct_ep(proc, entries_ptr, 1); + ir_build_range_indexed(proc, map, val_type, count_ptr, &val, &index, &loop, &done); + } break; case Type_Array: { irValue *count_ptr = NULL; irValue *array = ir_build_addr(proc, rs->expr).addr;