Browse Source

dynamic `map` insertion and lookup

Ginger Bill 8 years ago
parent
commit
c126339090
5 changed files with 55 additions and 45 deletions
  1. 4 3
      code/demo.odin
  2. 9 6
      core/_preload.odin
  3. 1 7
      src/check_expr.c
  4. 7 3
      src/check_stmt.c
  5. 34 26
      src/ir.c

+ 4 - 3
code/demo.odin

@@ -11,11 +11,12 @@
 
 
 main :: proc() {
-	Value :: type f32;
-	m: map[int]Value;
+	m: map[int]u32;
 	reserve(^m, 16);
 	defer free(m);
-	// m[123] = 345.0;
+
+	m[123] = 345;
+	fmt.println(m[123]);
 	if x, ok := m[123]; ok {
 		fmt.println(x);
 	}

+ 9 - 6
core/_preload.odin

@@ -511,25 +511,27 @@ __dynamic_map_rehash :: proc(using header: Map_Header, new_count: int) {
 			__dynamic_map_grow(new_header);
 		}
 	}
-	free(header.m);
+	free_ptr_with_allocator(header.m.hashes.allocator,  header.m.hashes.data);
+	free_ptr_with_allocator(header.m.entries.allocator, header.m.entries.data);
 	header.m^ = nm;
-
 }
 
 __dynamic_map_get :: proc(h: Map_Header, key: Map_Key) -> rawptr {
 	index := __dynamic_map_find(h, key).entry_index;
 	if index >= 0 {
 		data := cast(^byte)__dynamic_map_get_entry(h, index);
-		return data + h.value_offset;
+		val := data + h.value_offset;
+		return val;
 	}
 	return nil;
 }
 
 __dynamic_map_set :: proc(using h: Map_Header, key: Map_Key, value: rawptr) {
+	index: int;
+
 	if m.hashes.count == 0 {
 		__dynamic_map_grow(h);
 	}
-	index: int;
 	fr := __dynamic_map_find(h, key);
 	if fr.entry_index >= 0 {
 		index = fr.entry_index;
@@ -544,7 +546,8 @@ __dynamic_map_set :: proc(using h: Map_Header, key: Map_Key, value: rawptr) {
 	}
 	{
 		data := cast(^byte)__dynamic_map_get_entry(h, index);
-		mem.copy(data+value_offset, value, entry_size-value_offset);
+		val := data+value_offset;
+		mem.copy(val, value, entry_size-value_offset);
 	}
 
 	if __dynamic_map_full(h) {
@@ -598,7 +601,7 @@ __dynamic_map_add_entry :: proc(using h: Map_Header, key: Map_Key) -> int {
 		end.key = key;
 		end.next = -1;
 	}
-	return c;
+	return prev;
 }
 
 

+ 1 - 7
src/check_expr.c

@@ -3829,12 +3829,6 @@ void check_unpack_arguments(Checker *c, ArrayOperand *operands, AstNodeArray arg
 		Operand o = {0};
 		check_multi_expr(c, &o, args.e[i]);
 
-		if (o.mode == Addressing_MapIndex) {
-			Type *tuple_type = make_map_tuple_type(c->allocator, o.type);
-			add_type_and_value(&c->info, o.expr, o.mode, tuple_type, (ExactValue){0});
-			o.type = tuple_type;
-		}
-
 		if (o.type == NULL || o.type->kind != Type_Tuple) {
 			array_add(operands, o);
 		} else {
@@ -4997,7 +4991,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
 				goto error;
 			}
 			o->mode = Addressing_MapIndex;
-			o->type = t->Map.value;
+			o->type = make_map_tuple_type(c->allocator, t->Map.value);
 			o->expr = node;
 			return Expr_Expr;
 		}

+ 7 - 3
src/check_stmt.c

@@ -256,13 +256,17 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 		e->flags |= EntityFlag_Used;
 	}
 
+	Type *assignment_type = op_b.type;
 	switch (op_b.mode) {
 	case Addressing_Invalid:
 		return NULL;
 	case Addressing_Variable:
 		break;
-	case Addressing_MapIndex:
-		break;
+	case Addressing_MapIndex: {
+		Type *t = base_type(assignment_type); GB_ASSERT(is_type_tuple(t));
+		t = t->Tuple.variables[0]->type;
+		assignment_type = t;
+	} break;
 	default: {
 		if (op_b.expr->kind == AstNode_SelectorExpr) {
 			// NOTE(bill): Extra error checks
@@ -287,7 +291,7 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
 	} break;
 	}
 
-	check_assignment(c, op_a, op_b.type, str_lit("assignment"));
+	check_assignment(c, op_a, assignment_type, str_lit("assignment"));
 	if (op_a->mode == Addressing_Invalid) {
 		return NULL;
 	}

+ 34 - 26
src/ir.c

@@ -372,6 +372,7 @@ typedef struct irAddr {
 		struct {
 			irValue *map_key;
 			Type *   map_type;
+			Type *   map_result;
 		};
 	};
 	// union {
@@ -384,10 +385,11 @@ irAddr ir_make_addr(irValue *addr) {
 	return v;
 }
 
-irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type) {
+irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_result) {
 	irAddr v = {irAddr_Map, addr};
-	v.map_key  = map_key;
-	v.map_type = map_type;
+	v.map_key    = map_key;
+	v.map_type   = map_type;
+	v.map_result = map_result;
 	return v;
 }
 
@@ -589,23 +591,6 @@ Type *ir_type(irValue *value) {
 	return NULL;
 }
 
-Type *ir_addr_type(irAddr addr) {
-	if (addr.addr == NULL) {
-		return NULL;
-	}
-
-	if (addr.kind == irAddr_Map) {
-		Type *t = base_type(addr.map_type);
-		GB_ASSERT(is_type_map(t));
-		return t->Map.value;
-	}
-
-	Type *t = ir_type(addr.addr);
-	GB_ASSERT(is_type_pointer(t));
-	return type_deref(t);
-}
-
-
 
 bool ir_is_blank_ident(AstNode *node) {
 	if (node->kind == AstNode_Ident) {
@@ -1461,6 +1446,23 @@ irValue *ir_address_from_load_or_generate_local(irProcedure *proc, irValue *val)
 }
 
 
+Type *ir_addr_type(irAddr addr) {
+	if (addr.addr == NULL) {
+		return NULL;
+	}
+
+	if (addr.kind == irAddr_Map) {
+		Type *t = base_type(addr.map_type);
+		GB_ASSERT(is_type_map(t));
+		return t->Map.value;
+	}
+
+	Type *t = ir_type(addr.addr);
+	GB_ASSERT(is_type_pointer(t));
+	return type_deref(t);
+}
+
+
 irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
 	if (addr.addr == NULL) {
 		return NULL;
@@ -1469,7 +1471,8 @@ irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
 		Type *map_type = base_type(addr.map_type);
 		irValue *h = ir_gen_map_header(proc, addr.addr, map_type);
 		irValue *key = ir_gen_map_key(proc, addr.map_key);
-		irValue *ptr =ir_address_from_load_or_generate_local(proc, value);
+		irValue *v = ir_emit_conv(proc, value, map_type->Map.value);
+		irValue *ptr = ir_address_from_load_or_generate_local(proc, v);
 		ptr = ir_emit_conv(proc, ptr, t_rawptr);
 
 		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 3);
@@ -1487,7 +1490,7 @@ irValue *ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) {
 		// irValue *out = ir_emit(proc, ir_make_instr_insert_element(proc, v, elem, addr.Vector.index));
 		// return ir_emit_store(proc, addr.addr, out);
 	// } else {
-		irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
+			irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
 		return ir_emit_store(proc, addr.addr, v);
 	// }
 }
@@ -1527,7 +1530,12 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
 		ir_start_block(proc, done);
 
 
-		return ir_emit_load(proc, v);
+		if (is_type_tuple(addr.map_result)) {
+			return ir_emit_load(proc, v);
+		} else {
+			irValue *single = ir_emit_struct_ep(proc, v, 0);
+			return ir_emit_load(proc, single);
+		}
 	}
 
 	// if (addr.kind == irAddr_Vector) {
@@ -3778,7 +3786,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			irValue *key = ir_build_expr(proc, ie->index);
 			key = ir_emit_conv(proc, key, t->Map.key);
 
-			return ir_make_addr_map(map_val, key, t);
+			Type *result_type = type_of_expr(proc->module->info, expr);
+			return ir_make_addr_map(map_val, key, t, result_type);
 		}
 
 		irValue *using_addr = NULL;
@@ -4598,8 +4607,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 					if (lvals.e[i].addr == NULL) {
 						continue;
 					}
-					irValue *v = ir_emit_conv(proc, inits.e[i], ir_addr_type(lvals.e[i]));
-					ir_addr_store(proc, lvals.e[i], v);
+					ir_addr_store(proc, lvals.e[i], inits.e[i]);
 				}
 			}