Leopold Toetsch wrote: > > 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 ;-): [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.
Well, I wasn't precisely thinking of my interface being *soley* for freeze/thaw, but for clone and dump, too. Cloning would be like freezing followed immediately by thawing, without writing to disk. That is, I was thinking of something like the following psuedocode. class freezer { fifo<PMC*> queue; set<INTVAL> seen; outputer o; void push_integer(INTVAL i) { o.print_int(i); } void push_number(NUMVAL n) { o.print_num(n); } void push_string(STRING*s) { o.print_str(s); } void push_bigint(BIGINT*b) { o.print_big(b); } void push_pmc(PMC *p) { INTVAL i = (INTVAL)p; o.print_int(i); if( !seen.contains(i) ) { seen.add(i); queue.push(p); } } } void do_freeze(PMC *p, outputer o) { PMC * f = new_freezer_dumper(o); f.push_pmc(p); while( f.queue.notempty() ) { p = f.queue.pop(); o.print_int( p.getclass() ); p.freeze(f); } } class thawer { fifo<PMC*> queue; map<INTVAL, PMC*> prep; inputter i; INTVAL shift_integer() { return i.read_int(); } NUMVAL shift_number() { return i.read_num(); } STRING*shift_string() { return i.read_str(); } BIGNUM*shift_bignum() { return i.read_big(); } void shift_pmc() { INTVAL j = i.read_int(); if( prep.contains(j) ) { return prep.get(j); } PMC * n = new_placeholder(); prep.put(j, n); queue.push(n); return n; } } PMC* do_thaw(inputter i) { PMC * t = new_thawer(i); PMC * ret = t.shift_pmc(); PMC * p = ret; do { p.setclass( i.read_int() ); p.thaw(t); p = t.queue.pop(); } while(p); return ret; } class cloner { fifo<pair<PMC*,PMC*> > queue; map<PMC*,PMC*> prep; fifo<PMC*> tempdata; void push_integer(INTVAL i) { tempdata.push_integer(i); } void push_number (NUMVAL n) { tempdata.push_number (n); } void push_string (STRING*s) { tempdata.push_string (s); } void push_bigint (BIGINT*b) { tempdata.push_bigint (b); } void push_pmc(PMC *p) { if( prep.contains(p) ) { tempdata.push_pmc(prep.get(p)); } else { PMC *p2 = new_placeholder(); prep.put(p, p2); queue.push( pair(p, p2) ); tempdata.push_pmc(p2); } } INTVAL shift_integer() { return tempdata.shift_integer(); } NUMVAL shift_number () { return tempdata.shift_number (); } STRING*shift_string () { return tempdata.shift_string (); } BIGINT*shift_bigint () { return tempdata.shift_bigint (); } PMC* shift_pmc() { return tempdata.shift_pmc (); } } PMC * do_clone(PMC *p) { PMC *c = new_cloner(); PMC *r = new_placeholder(); c.prep.put(p, r); p.freeze(c); r.setclass( p.getclass() ); r.thaw(c); assert( c.tempdata.isempty() ); while( c.queue.notempty() ) ) { pair<PMC*,PMC*> x = c.queue.pop(); x.first.freeze(c); x.second.setclass( x.first.getclass() ); x.second.thaw(c); assert( c.tempdata.isempty() ); } return r; } I've ommited the psuedocode for dumping/pretty-printing since I'm not sure how best it would be done. It does require quite a bit more information than freezing (since the computer can tell when/where a pmc class starts and ends, but a human wouldn't be able to), so merely calling do_freeze() with an outputer which sprintfs intvals and numvals nicely wouldn't be sufficient. However, if you replaced the o.print_int inside of push_pmc with a o.print_pmc_pointer, and o.print_int in the main loop with o.print_pmc_class, then the outputter *would* have enough info to make something vaguely human-readable. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}