aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-06 20:54:51 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-06 20:54:51 +0000
commitf11d73ffaa5df21437714e73bb72352ed17d57a9 (patch)
treecd0886e33cd7bf02194619c47b44cc2c359f5865 /src
parentc126339090a57ab29a2c75d3ee79333cf3c88278 (diff)
`map` string keys and `for` iterator
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c8
-rw-r--r--src/check_stmt.c5
-rw-r--r--src/ir.c64
3 files changed, 69 insertions, 8 deletions
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));
@@ -4411,12 +4433,36 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
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));
break;
}
}
+ 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;