Skip to content

Commit 3fb48f5

Browse files
committed
support putting things with identity in hashmap
1 parent c7f2490 commit 3fb48f5

7 files changed

Lines changed: 80 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ least for now:
346346
- `__gc_collect`: Have the garbage collector run immediately. It has a scary
347347
name because it seems like a scary thing to do.
348348
- `__dis`: Print the disassembly of the given function directly to stdout.
349+
- `id`: Get the ID of the given value if it has one.
349350

350351
## Standard Library
351352

intrinsics.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
X("toint", toint, 1) \
5353
X("__gc_collect", __gc_collect, 0) \
5454
X("__dis", __dis, 1) \
55-
X("arguments", arguments, 0)
55+
X("arguments", arguments, 0) \
56+
X("id", id, 1)
5657

5758
INTRINSIC_LIST(DECL);
5859

@@ -558,5 +559,19 @@ static int arguments(size_t argc, struct cb_value *argv,
558559
result->type = CB_VALUE_ARRAY;
559560
result->val.as_array = args;
560561

562+
return 0;
563+
}
564+
565+
static int id(size_t argc, struct cb_value *argv, struct cb_value *result)
566+
{
567+
result->type = CB_VALUE_INT;
568+
569+
if (cb_value_id(argv[0], &result->val.as_int)) {
570+
struct cb_value err;
571+
cb_value_from_fmt(&err, "Value of type %s has no identity", cb_value_type_friendly_name(argv[0].type));
572+
cb_error_set(err);
573+
return 1;
574+
}
575+
561576
return 0;
562577
}

lib/hashmap.cb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ export struct HashMap {
1616

1717
struct Bucket { key, value, prev, next }
1818

19-
let default_hash = hash::primitive;
20-
2119
function do_hash(self, key) {
22-
return hash::hash(key) & self.cap - 1;
20+
try {
21+
return hash::hash(key) & self.cap - 1;
22+
} catch (exc) {
23+
if (!trait::implements(key, hash::Hashable)) {
24+
return id(key) & self.cap - 1;
25+
}
26+
throw exc;
27+
}
2328
}
2429

2530
function grow(self) {

tests/test_hashmap.cb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ export function test_basics() {
3030
test::assert(hashmap::has(m, 1), "has 1");
3131
test::assert(hashmap::get(m, 1) == "one", "1 is one");
3232
test::assert(hashmap::size(m) == 3);
33+
34+
let s = struct {};
35+
test::assert(!hashmap::has(m, s));
36+
hashmap::set(m, s, "S");
37+
test::assert(hashmap::has(m, s));
38+
test::assert(hashmap::get(m, s) == "S");
39+
test::assert(hashmap::size(m) == 4);
3340
}
3441

3542
function iterlength(it) {

value.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,4 +865,50 @@ CB_INLINE size_t cb_function_upvalue_count(const struct cb_function *func)
865865
} else {
866866
return func->nupvalues;
867867
}
868+
}
869+
870+
int cb_value_id(struct cb_value value, intptr_t *id_out)
871+
{
872+
union {
873+
void *as_ptr;
874+
intptr_t as_int;
875+
} result;
876+
877+
switch (value.type) {
878+
case CB_VALUE_NULL:
879+
case CB_VALUE_INT:
880+
case CB_VALUE_DOUBLE:
881+
case CB_VALUE_BOOL:
882+
case CB_VALUE_CHAR:
883+
case CB_VALUE_INTERNED_STRING:
884+
case CB_VALUE_STRING:
885+
return 1;
886+
887+
case CB_VALUE_BYTES:
888+
result.as_ptr = value.val.as_bytes;
889+
break;
890+
891+
case CB_VALUE_ARRAY:
892+
result.as_ptr = value.val.as_array;
893+
break;
894+
895+
case CB_VALUE_FUNCTION:
896+
result.as_ptr = value.val.as_function;
897+
break;
898+
899+
case CB_VALUE_STRUCT_SPEC:
900+
result.as_ptr = value.val.as_struct_spec;
901+
break;
902+
903+
case CB_VALUE_STRUCT:
904+
result.as_ptr = value.val.as_struct;
905+
break;
906+
907+
case CB_VALUE_USERDATA:
908+
result.as_ptr = value.val.as_userdata;
909+
break;
910+
}
911+
912+
*id_out = result.as_int;
913+
return 0;
868914
}

value.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ ssize_t cb_value_from_fmt(struct cb_value *val, const char *fmt, ...);
133133
struct cb_bytes *cb_bytes_new(size_t size);
134134
struct cb_value cb_bytes_new_value(size_t size);
135135
size_t cb_function_upvalue_count(const struct cb_function *func);
136+
int cb_value_id(struct cb_value value, intptr_t *id_out);
136137

137138
const char *cb_value_type_name(enum cb_value_type type);
138139
const char *cb_value_type_of(struct cb_value *val);

vim/syntax/cbcvm.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ syn keyword cbcvmStructure struct nextgroup=cbcvmFunction skipwhite
3030
syn keyword cbcvmIntrinsics print println tostring typeof string_chars
3131
\ string_from_chars string_bytes string_concat ord chr truncate32
3232
\ tofloat read_file read_file_bytes argv __upvalues apply now toint
33-
\ __gc_collect __dis arguments
33+
\ __gc_collect __dis arguments id
3434
syn match cbcvmBraces "[{}\[\]]"
3535
syn match cbcvmParens "[()]"
3636

0 commit comments

Comments
 (0)