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

Reply via email to