]> Nishi Git Mirror - gwion.git/commitdiff
:white_check_mark: Add dict tests
authorJérémie Astor <fennecdjay@gmail.com>
Sun, 31 Oct 2021 20:16:52 +0000 (21:16 +0100)
committerJérémie Astor <fennecdjay@gmail.com>
Sun, 31 Oct 2021 20:16:52 +0000 (21:16 +0100)
src/emit/emit.c
src/lib/dict.c
tests/dict/dict.gw [new file with mode: 0644]
tests/dict/dict_lit.gw [new file with mode: 0644]
tests/dict/dict_lit_nomatch.gw [new file with mode: 0644]
tests/dict/dict_noleak.gw [new file with mode: 0644]
tests/dict/dict_remove.gw [new file with mode: 0644]

index 594bdc635ddad969f87cec39cd2d7dc8d885c33f..e9c61bd05c83085691207d0cb15b2f0f4d71d09f 100644 (file)
@@ -673,16 +673,20 @@ ANN static m_bool emit_prim_dict(const Emitter emit, Exp *data) {
   const Type  val = e->next->type;
   const Type t = dict_type(emit->gwion, key, val, e->pos);
   const Instr init = emit_add_instr(emit, dict_ctor_alt);
+  const Exp next = e->next;
+  e->next = NULL;
   struct Exp_ func = { .exp_type = ae_exp_primary, .d = { .prim = { .prim_type = ae_prim_id, .d = { .var = insert_symbol("hash") }} }};
+  struct Exp_ call = { .exp_type = ae_exp_call, .d = { .exp_call = { .func = &func, .args = e}}};
+  CHECK_BB(traverse_exp(emit->env, &call));
+  e->next = next;
   m_uint count = 0;
-  CHECK_BB(traverse_exp(emit->env, &func));
   do {
     const Exp next = e->next;
     const Exp nnext = next->next;
     next->next = NULL;
     e->next = NULL;
     CHECK_BB(emit_exp(emit, e));
-    e->next = nnext;
+    e->next = next;
     CHECK_BB(emit_exp(emit, next));
     next->next = nnext;
     if(key->size == SZ_INT) {
index 6a08440a11fdab1ec4e14a3a042ddb4f5cf0dfa3..ba43527e2c3819c61b97a11fb5f619bbc11edeb9 100644 (file)
@@ -66,7 +66,7 @@ static SFUN(mfun_float_h) {
 }
 
 static SFUN(mfun_string_h) {
-  *(m_int*)RETURN = hash(STRING(MEM(0)));
+  *(m_int*)RETURN = hash(STRING(*(M_Object*)MEM(0)));
 }
 
 ANN static void clear_oo(const HMap *a, const VM_Shred shred, const HMapInfo *info NUSED, const m_uint idx) {
@@ -238,11 +238,11 @@ static INSTR(hmap_iter) {
   size_t bucket =  *(m_uint*)(shred->reg - SZ_INT) % hmap->capacity;
   const HState *state = (HState*)(hmap->state + sizeof(HState) * bucket);
   if (state->set) {
-    const m_bit *data = hmap->data + hinfo->sz * bucket;
     m_int *const tombstone = (m_int*)(shred->reg - SZ_INT*2);
     if (state->deleted && *tombstone == -1) {
       *tombstone = bucket++;
     }
+    const m_bit *data = hmap->data + hinfo->sz * bucket;
     *(m_uint*)(shred->reg - SZ_INT) = bucket;
     memcpy(REG(0), data, hmap->key_size);
     shred->reg += hmap->key_size;
@@ -341,7 +341,8 @@ static INSTR(hmap_val) {
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
   const m_uint bucket = *(m_uint*)REG(0);
   const m_bit *new_data = hmap->data + hinfo->sz * bucket;
-
+  HState *const new_state = (HState*)(hmap->state + sizeof(HState) * bucket);
+  if(new_state->deleted) exit(3);
   const m_int tombstone = *(m_int*)(shred->reg - SZ_INT);
   if (tombstone != -1) {
     m_bit  *const old_data = hmap->data + (hmap->key_size + hmap->val_size) * tombstone;
@@ -350,7 +351,7 @@ static INSTR(hmap_val) {
     memcpy(old_state, new_state, sizeof(HState));
     memcpy(old_data, new_data, hinfo->sz);
     new_state->deleted = true;
 }
+ }
 
   shred->reg -= SZ_INT*2 - hmap->val_size;
   memcpy(REG(-hmap->val_size), new_data + hmap->key_size, hmap->val_size);
@@ -367,10 +368,11 @@ static INSTR(hmap_remove_clear) {
 
 static INSTR(hmap_remove) {
   const M_Object o = *(M_Object*)(shred->reg - SZ_INT*2);
-  const HMap *hmap = (HMap*)o->data;
+  HMap *const hmap = (HMap*)o->data;
   const HMapInfo *hinfo = (HMapInfo*)o->type_ref->nspc->class_data;
   const m_uint bucket = *(m_uint*)REG(0);
   m_bit *data = hmap->data + hinfo->sz * bucket;
+  hmap->count--;
   HState *const state = (HState *)(hmap->state + bucket * sizeof(HState));
   state->deleted = true;
   shred->reg -= SZ_INT*3 - hmap->val_size;
diff --git a/tests/dict/dict.gw b/tests/dict/dict.gw
new file mode 100644 (file)
index 0000000..fbdb3b3
--- /dev/null
@@ -0,0 +1,7 @@
+#! [contains] 0
+const Dict:[string, int] d;
+0 => d["foo"];
+1 => d["bar"];
+2 => d["baz"];
+
+<<< d["foo"] >>>;
diff --git a/tests/dict/dict_lit.gw b/tests/dict/dict_lit.gw
new file mode 100644 (file)
index 0000000..6ccc838
--- /dev/null
@@ -0,0 +1,2 @@
+#! [contains] 0
+<<< { "foo" : 0, "bar" : 1, "baz" : 2 }["foo"] >>>;
diff --git a/tests/dict/dict_lit_nomatch.gw b/tests/dict/dict_lit_nomatch.gw
new file mode 100644 (file)
index 0000000..40bad61
--- /dev/null
@@ -0,0 +1,2 @@
+#! [contains] 0
+<<< { "foo" : 0, "bar" : 1, "baz" : 2.2 }["foo"] >>>;
diff --git a/tests/dict/dict_noleak.gw b/tests/dict/dict_noleak.gw
new file mode 100644 (file)
index 0000000..b3fedb6
--- /dev/null
@@ -0,0 +1,5 @@
+#! ensure no leaks
+const Dict:[string, Event] d;
+new Object => d["foo"];
+new Object => d["bar"];
+new Object => d["baz"];
diff --git a/tests/dict/dict_remove.gw b/tests/dict/dict_remove.gw
new file mode 100644 (file)
index 0000000..ddecbcd
--- /dev/null
@@ -0,0 +1,10 @@
+#! [contains] InvalidMapAccess
+const Dict:[string, int] d;
+0 => d["foo"];
+1 => d["bar"];
+2 => d["baz"];
+
+#! could be "foo" ~~ d
+<<< d.remove("foo") >>>;
+
+<<< d["foo"] >>>;