diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-19 11:50:42 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-19 11:50:42 +0000 |
| commit | 3cec2550d9b15eb56b8dd1b42a30b9f47ace0b4c (patch) | |
| tree | be46857c9738764df840e621c1a371eb21105388 /src | |
| parent | 758dd9ba16a2dc5b01ea131e83c06bf33c33f116 (diff) | |
`delete` for maps
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 34 | ||||
| -rw-r--r-- | src/checker.c | 14 | ||||
| -rw-r--r-- | src/ir.c | 19 |
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); } @@ -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")); |