void pic_rope_decref(pic_state *pic, struct pic_rope *x) { if (! --x->refcnt) { if (x->chunk) { CHUNK_DECREF(x->chunk); pic_free(pic, x); return; } pic_rope_decref(pic, x->left); pic_rope_decref(pic, x->right); pic_free(pic, x); } }
static struct pic_rope * rope_sub(pic_state *pic, struct pic_rope *x, size_t i, size_t j) { assert(i <= j); assert(j <= x->weight); if (i == 0 && x->weight == j) { pic_rope_incref(pic, x); return x; } if (x->chunk) { struct pic_rope *y; y = pic_malloc(pic, sizeof(struct pic_rope)); y->refcnt = 1; y->left = NULL; y->right = NULL; y->weight = j - i; y->offset = x->offset + i; y->chunk = x->chunk; CHUNK_INCREF(x->chunk); return y; } if (j <= x->left->weight) { return rope_sub(pic, x->left, i, j); } else if (x->left->weight <= i) { return rope_sub(pic, x->right, i - x->left->weight, j - x->left->weight); } else { struct pic_rope *r, *l; l = rope_sub(pic, x->left, i, x->left->weight); r = rope_sub(pic, x->right, 0, j - x->left->weight); x = rope_cat(pic, l, r); pic_rope_decref(pic, l); pic_rope_decref(pic, r); return x; } }
static void flatten(pic_state *pic, struct pic_rope *x, struct pic_chunk *c, size_t offset) { if (x->chunk) { memcpy(c->str + offset, x->chunk->str + x->offset, x->weight); CHUNK_DECREF(x->chunk); x->chunk = c; x->offset = offset; CHUNK_INCREF(c); return; } flatten(pic, x->left, c, offset); flatten(pic, x->right, c, offset + x->left->weight); pic_rope_decref(pic, x->left); pic_rope_decref(pic, x->right); x->left = x->right = NULL; x->chunk = c; x->offset = offset; CHUNK_INCREF(c); }
void pic_str_set(pic_state *pic, pic_str *str, int i, char c) { pic_str *x, *y, *z, *tmp; char buf[1]; if (pic_str_len(str) <= i) { pic_errorf(pic, "index out of range %d", i); } buf[0] = c; x = pic_str_sub(pic, str, 0, i); y = pic_make_str(pic, buf, 1); z = pic_str_sub(pic, str, i + 1, pic_str_len(str)); tmp = pic_str_cat(pic, x, pic_str_cat(pic, y, z)); pic_rope_incref(pic, tmp->rope); pic_rope_decref(pic, str->rope); str->rope = tmp->rope; }
static void gc_finalize_object(pic_state *pic, struct object *obj) { switch (obj_type(pic, obj)) { case PIC_TYPE_VECTOR: { pic_free(pic, obj->u.vec.data); break; } case PIC_TYPE_BLOB: { pic_free(pic, obj->u.blob.data); break; } case PIC_TYPE_STRING: { pic_rope_decref(pic, obj->u.str.rope); break; } case PIC_TYPE_DATA: { if (obj->u.data.type->dtor) { obj->u.data.type->dtor(pic, obj->u.data.data); } break; } case PIC_TYPE_DICT: { kh_destroy(dict, &obj->u.dict.hash); break; } case PIC_TYPE_SYMBOL: { /* TODO: remove this symbol's entry from pic->syms immediately */ break; } case PIC_TYPE_WEAK: { kh_destroy(weak, &obj->u.weak.hash); break; } case PIC_TYPE_IREP: { struct irep *irep = &obj->u.irep; if ((irep->flags & IREP_CODE_STATIC) == 0) { pic_free(pic, (code_t *) irep->code); } pic_free(pic, irep->obj); pic_free(pic, irep->irep); break; } case PIC_TYPE_PORT: { pic_fclose(pic, obj_value(pic, obj)); /* FIXME */ break; } case PIC_TYPE_FRAME: { pic_free(pic, obj->u.frame.regs); break; } case PIC_TYPE_PAIR: case PIC_TYPE_ERROR: case PIC_TYPE_RECORD: case PIC_TYPE_PROC_FUNC: case PIC_TYPE_PROC_IREP: break; default: PIC_UNREACHABLE(); } }