struct pic_dict * pic_attr(pic_state *pic, pic_value obj) { xh_entry *e; if (pic_vtype(obj) != PIC_VTYPE_HEAP) { pic_errorf(pic, "attribute: expected heap object, but got immediate value ~s", obj); } e = xh_get_ptr(&pic->attrs, pic_ptr(obj)); if (e == NULL) { struct pic_dict *dict = pic_make_dict(pic); e = xh_put_ptr(&pic->attrs, pic_ptr(obj), &dict); assert(dict == xh_val(e, struct pic_dict *)); } return xh_val(e, struct pic_dict *); }
static bool internal_equal_p(pic_state *pic, pic_value x, pic_value y, size_t depth, xhash *ht) { pic_value local = pic_nil_value(); size_t c; if (depth > 10) { if (depth > 200) { pic_errorf(pic, "Stack overflow in equal\n"); } if (pic_pair_p(x) || pic_vec_p(x)) { if (xh_get_ptr(ht, pic_obj_ptr(x)) != NULL) { return true; /* `x' was seen already. */ } else { xh_put_ptr(ht, pic_obj_ptr(x), NULL); } } } c = 0; LOOP: if (pic_eqv_p(x, y)) return true; if (pic_type(x) != pic_type(y)) return false; switch (pic_type(x)) { case PIC_TT_STRING: return str_equal_p(pic_str_ptr(x), pic_str_ptr(y)); case PIC_TT_BLOB: return blob_equal_p(pic_blob_ptr(x), pic_blob_ptr(y)); case PIC_TT_PAIR: { if (pic_nil_p(local)) { local = x; } if (internal_equal_p(pic, pic_car(pic, x), pic_car(pic, y), depth + 1, ht)) { x = pic_cdr(pic, x); y = pic_cdr(pic, y); c++; if (c == 2) { c = 0; local = pic_cdr(pic, local); if (pic_eq_p(local, x)) { return true; } } goto LOOP; } else { return false; } } case PIC_TT_VECTOR: { size_t i; struct pic_vector *u, *v; u = pic_vec_ptr(x); v = pic_vec_ptr(y); if (u->len != v->len) { return false; } for (i = 0; i < u->len; ++i) { if (! internal_equal_p(pic, u->data[i], v->data[i], depth + 1, ht)) return false; } return true; } default: return false; } }