Benjamin Goldberg <[EMAIL PROTECTED]> wrote: > Actually, I think the following interface would be better:
> void freeze(PMC *freezer); > void thaw (PMC *thawer); I'm thinking of (in horrible pseudo code ;-): typedef struct { size_t action_func_nr; // clone, freeze, thaw, dump vtable# PMC *todo_list_fifo; PMC *seen; size_t id; UINTVAL flags; PMC *other; // for clone and thaw void *result; // freeze, dump append string here void *other_things_needed; } Traverse_info; INTVAL traverse(Traverse_info *info) { (SELF->vtable[info->action_func_nr]) (INTERP, SELF, info); foreach item (SELF.elements) { if (item->needs_cloning) VTABLE_push(INTERP, info->todo_list, item); else ;// copy native type } return 0; // ok } INTVAL clone(Traverse_info *info) { if (SELF.can("clone")) // overridden? return SELF.invoke(SELF.find_method("clone"), info); if (info->flags & DO_CLONE) copy(info->other->state, SELF.state); else ; // other pointer already done for self-ref aggregates return 0; // ok } freeze_thaw_clone_dump.c // ;-) do_clone(PMC *pmc) { return (PMC*) do_traverse(action_func_nr = (VTABLE.clone-VTABLE[0], CLONE, pmc); } void *do_traverse(func, what, pmc) { info.action_func_nr = func; info.todo_list_fifo = new Fifo; info.flags = what; info.seen = new Hash; info.result = NULL; push(info.todo_list, pmc); while (info.todo_list_fifo.elements()) { todo = shift info.todo_list_fifo; if (seen{todo}) // set flags info.flags = DO_NOT_CLONE; info.other = todo; else { seen{todo} = ++ID; switch (what) { case CLONE: info.other = new todo.type(); if (!info.result) info.result = info.other; // top clone break; ... } } info.id = ID; if (todo->vtable->traverse(...,&info)) ; // error } return (void*) info->result; } [ big snip ] Above functionality does IMHO match your description. The only difference is, that I'd like to use that not only for freeze/thaw, but for clone and dump too. The thaw part is still missing in above pseudocode. It needs an additional ID-array for lookup + some more things. Its better done in a separate subroutine. There is one more indirection through the passed in vtable but that doesn't matter very much. Constructing new PMCs or STRINGs takes much more time. And I'd like to have a vtable->dump too. Dan's approach of first freezing the PMC and then let the debugger construct the dump doesn't work IMHO: we already have dynamic loaded PMC classes. The debugger doesn't know anything about such classes, so these classes have to provide this functionality themselfs. We could rename dump() to pretty_print() though. leo