diff --git a/lib/std/collections/hashmap.c3 b/lib/std/collections/hashmap.c3 index 62bedc105..39f1f9e6b 100644 --- a/lib/std/collections/hashmap.c3 +++ b/lib/std/collections/hashmap.c3 @@ -6,8 +6,9 @@ *> module std::collections::map(); import std::math; +import std::io @norecurse; -struct HashMap +struct HashMap (Printable) { Entry*[] table; Allocator allocator; @@ -446,6 +447,18 @@ fn void HashMap.resize(&map, uint new_capacity) @private map.threshold = (uint)(new_capacity * map.load_factor); } +fn usz! HashMap.to_format(&self, Formatter* f) @dynamic +{ + usz len; + len += f.print("{ ")!; + self.@each_entry(; Entry* entry) + { + if (len > 2) len += f.print(", ")!; + len += f.printf("%s: %s", entry.key, entry.value)!; + }; + return len + f.print(" }"); +} + fn void HashMap.transfer(&map, Entry*[] new_table) @private { Entry*[] src = map.table; diff --git a/releasenotes.md b/releasenotes.md index 9f9977946..555e0a563 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -76,6 +76,7 @@ - New unit test default runner. - Added weakly linked `fmodf`. - Add `@select` to perform the equivalent of `a ? x : y` at compile time. +- `HashMap` is now `Printable`. ## 0.6.6 Change list diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 5038b8a75..1ef698c0c 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -1089,7 +1089,7 @@ const char *llvm_codegen(void *context) void llvm_add_global_decl(GenContext *c, Decl *decl) { - ASSERT(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); + ASSERT_SPAN(decl, decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); bool same_module = decl->unit->module == c->code_module; LLVMTypeRef type = llvm_get_type(c, decl->type); @@ -1282,7 +1282,7 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) { return decl->backend_ref = llvm_get_ref(c, decl->var.alias); } - ASSERT(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); + ASSERT_SPAN(decl, decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); llvm_add_global_decl(c, decl); return decl->backend_ref; case DECL_FUNC: diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index c02fc3a1c..ea6efb167 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -1767,7 +1767,6 @@ static void cast_enum_to_value(Expr* expr, Type *to_type) cast_int_to_int(expr, to_type); return; } - if (expr_is_const_enum(expr)) { expr_replace(expr, copy_expr_single(expr->const_expr.enum_err_val->enum_constant.args[decl->enums.inline_index])); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 0e647b273..4d43f88df 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -277,14 +277,27 @@ Expr *sema_enter_inline_member(Expr *parent, CanonicalType *type) { Decl *decl = type->decl; if (!decl->is_substruct) return NULL; + if (parent->expr_kind == EXPR_CONST) { - return copy_expr_single(parent->const_expr.enum_err_val->enum_constant.args[0]); + if (decl->enums.inline_value) + { + Expr *expr = expr_new_expr(EXPR_CONST, parent); + expr_rewrite_const_int(expr, decl->enums.type_info->type, parent->const_expr.enum_err_val->enum_constant.ordinal); + return expr; + } + return copy_expr_single(parent->const_expr.enum_err_val->enum_constant.args[decl->enums.inline_index]); + } + if (decl->enums.inline_value) + { + Expr *expr = copy_expr_single(parent); + expr->type = decl->enums.type_info->type; + return expr; } Expr *property = expr_new(EXPR_ACCESS_RESOLVED, parent->span); property->resolve_status = RESOLVE_DONE; property->access_resolved_expr.parent = parent; - property->access_resolved_expr.ref = decl->enums.parameters[0]; + property->access_resolved_expr.ref = decl->enums.parameters[decl->enums.inline_value]; property->type = property->access_resolved_expr.ref->type; return property; } diff --git a/test/unit/stdlib/collections/map.c3 b/test/unit/stdlib/collections/map.c3 index 0382f6e8a..b450e2744 100644 --- a/test/unit/stdlib/collections/map.c3 +++ b/test/unit/stdlib/collections/map.c3 @@ -56,6 +56,29 @@ fn void map() } } +def FooMap = HashMap(); +enum Foobar : inline char +{ + FOO, + BAR, + BAZ +} + +enum Foobar2 : int (inline char y) +{ + ABC = 3, + DEF = 5, +} + +fn void map_inline_enum() +{ + FooMap x; + x[Foobar.BAZ] = FOO; + x[Foobar2.ABC] = BAR; + test::eq(string::tformat("%s", x), "{ 2: FOO, 3: BAR }"); + x.free(); +} + fn void map_remove() { TestHashMap m;