aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-19 11:50:42 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-19 11:50:42 +0000
commit3cec2550d9b15eb56b8dd1b42a30b9f47ace0b4c (patch)
treebe46857c9738764df840e621c1a371eb21105388 /src
parent758dd9ba16a2dc5b01ea131e83c06bf33c33f116 (diff)
`delete` for maps
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.c34
-rw-r--r--src/checker.c14
-rw-r--r--src/ir.c19
3 files changed, 52 insertions, 15 deletions
diff --git a/src/check_expr.c b/src/check_expr.c
index 21eb59ff3..883f98865 100644
--- a/src/check_expr.c
+++ b/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
diff --git a/src/checker.c b/src/checker.c
index 4e27dbf3f..c512e6e69 100644
--- a/src/checker.c
+++ b/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);
}
diff --git a/src/ir.c b/src/ir.c
index 2a83a9601..2f8155225 100644
--- a/src/ir.c
+++ b/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"));