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;}