Bläddra i källkod

`delete` for maps

Ginger Bill 8 år sedan
förälder
incheckning
3cec2550d9
5 ändrade filer med 60 tillägg och 16 borttagningar
  1. 7 0
      code/demo.odin
  2. 1 1
      core/_preload.odin
  3. 32 2
      src/check_expr.c
  4. 2 12
      src/checker.c
  5. 18 1
      src/ir.c

+ 7 - 0
code/demo.odin

@@ -8,6 +8,13 @@
 #import "halloc.odin";
 
 main :: proc() {
+
+	m: map[int]int;
+	m[123] = 312;
+	fmt.println(m[123]);
+	delete(m, 123);
+	fmt.println(m[123]);
+
 /*
 /*
 	Version 0.1.1

+ 1 - 1
core/_preload.odin

@@ -633,7 +633,7 @@ __dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key) -> int {
 }
 
 
-__dynamic_map_remove :: proc(using h: __Map_Header, key: __Map_Key) {
+__dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
 	fr := __dynamic_map_find(h, key);
 	if fr.entry_index >= 0 {
 		__dynamic_map_erase(h, fr);

+ 32 - 2
src/check_expr.c

@@ -2643,7 +2643,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 				gbString sel_str = expr_to_string(selector);
 				error_node(op_expr, "`%s` is not exported by `%.*s`", sel_str, LIT(name));
 				gb_string_free(sel_str);
-				// NOTE(bill): Not really an error so don't goto error
 				goto error;
 			}
 
@@ -2966,7 +2965,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 	} break;
 
 	case BuiltinProc_append: {
-		// append :: proc([dynamic]Type, item: ...Type) {
+		// append :: proc([dynamic]Type, item: ...Type)
 		Type *type = operand->type;
 		type = base_type(type);
 		if (!is_type_dynamic_array(type)) {
@@ -2996,6 +2995,37 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		operand->type = t_int;
 	} break;
 
+	case BuiltinProc_delete: {
+		// delete :: proc(map[Key]Value, key: Key)
+		Type *type = operand->type;
+		if (!is_type_map(type)) {
+			gbString str = type_to_string(type);
+			error_node(operand->expr, "Expected a map, got `%s`", str);
+			gb_string_free(str);
+			return false;
+		}
+
+		Type *key = base_type(type)->Map.key;
+		Operand x = {Addressing_Invalid};
+		AstNode *key_node = ce->args.e[1];
+		Operand op = {0};
+		check_expr(c, &op, key_node);
+		if (op.mode == Addressing_Invalid) {
+			return false;
+		}
+
+		if (!check_is_assignable_to(c, &op, key)) {
+			gbString kt = type_to_string(key);
+			gbString ot = type_to_string(op.type);
+			error_node(operand->expr, "Expected a key of type `%s`, got `%s`", key, ot);
+			gb_string_free(ot);
+			gb_string_free(kt);
+			return false;
+		}
+
+		operand->mode = Addressing_NoValue;
+	} break;
+
 
 	case BuiltinProc_size_of: {
 		// size_of :: proc(Type) -> untyped int

+ 2 - 12
src/checker.c

@@ -30,6 +30,7 @@ typedef enum BuiltinProcId {
 	BuiltinProc_reserve,
 	BuiltinProc_clear,
 	BuiltinProc_append,
+	BuiltinProc_delete,
 
 	BuiltinProc_size_of,
 	BuiltinProc_size_of_val,
@@ -73,6 +74,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("reserve"),          2, false, Expr_Stmt},
 	{STR_LIT("clear"),            1, false, Expr_Stmt},
 	{STR_LIT("append"),           1, true,  Expr_Expr},
+	{STR_LIT("delete"),           2, false, Expr_Stmt},
 
 	{STR_LIT("size_of"),          1, false, Expr_Expr},
 	{STR_LIT("size_of_val"),      1, false, Expr_Expr},
@@ -1715,12 +1717,6 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 					continue;
 				}
 				if (id->is_import) {
-					// String gpa = str_lit("GetProcAddress");
-					// if (str_eq(e->token.string, gpa)) {
-					// 	Entity *f = scope_lookup_entity(parent_scope, gpa);
-					// 	gb_printf_err("%.*s %.*s %td\n", LIT(gpa), LIT(f->token.pos.file), entity_procedure_overload_count(f));
-					// }
-
 					if (is_entity_exported(e)) {
 						// TODO(bill): Should these entities be imported but cause an error when used?
 						bool ok = add_entity(c, parent_scope, NULL, e);
@@ -1728,12 +1724,6 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
 							map_bool_set(&parent_scope->implicit, hash_pointer(e), true);
 						}
 					}
-
-					// if (str_eq(e->token.string, gpa)) {
-					// 	Entity *f = scope_lookup_entity(parent_scope, gpa);
-					// 	gb_printf_err("%.*s %.*s %td\n", LIT(gpa), LIT(f->token.pos.file), entity_procedure_overload_count(f));
-					// }
-
 				} else {
 					add_entity(c, parent_scope, NULL, e);
 				}

+ 18 - 1
src/ir.c

@@ -3244,7 +3244,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 						args[3] = capacity;
 						return ir_emit_global_call(proc, "__dynamic_array_reserve", args, 4);
 					} else if (is_type_dynamic_map(type)) {
-						irValue **args = gb_alloc_array(a, irValue *, 4);
+						irValue **args = gb_alloc_array(a, irValue *, 2);
 						args[0] = ir_gen_map_header(proc, ptr, type);
 						args[1] = capacity;
 						return ir_emit_global_call(proc, "__dynamic_map_reserve", args, 2);
@@ -3360,6 +3360,23 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
 					return ir_emit_global_call(proc, "__dynamic_array_append", daa_args, 5);
 				} break;
 
+				case BuiltinProc_delete: {
+					ir_emit_comment(proc, str_lit("delete"));
+					irValue *map = ir_build_expr(proc, ce->args.e[0]);
+					irValue *key = ir_build_expr(proc, ce->args.e[1]);
+					Type *map_type = ir_type(map);
+					GB_ASSERT(is_type_dynamic_map(map_type));
+					Type *key_type = base_type(map_type)->Map.key;
+
+					irValue *addr = ir_address_from_load_or_generate_local(proc, map);
+
+					gbAllocator a = proc->module->allocator;
+					irValue **args = gb_alloc_array(a, irValue *, 2);
+					args[0] = ir_gen_map_header(proc, addr, map_type);
+					args[1] = ir_gen_map_key(proc, key, key_type);
+					return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
+				} break;
+
 
 				case BuiltinProc_assert: {
 					ir_emit_comment(proc, str_lit("assert"));