boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

115-two-heap.scm (2074B)


      1 ; Two-heap primitives, A → B → C ergonomics. The shape Phase 3 of
      2 ; CC-SCRATCH.md will use at the parse-decl-or-fn boundary.
      3 ;
      4 ;   A: caller. Heap-unaware; just calls (B input) and uses the result.
      5 ;   B: boundary. Switches to scratch, runs C in scratch, switches back
      6 ;      to main, *clones* C's survivor into the main heap (the "promote"
      7 ;      walker), resets scratch, returns the main-heap clone.
      8 ;   C: worker. Heap-unaware; allocates freely in whatever heap is
      9 ;      current. Returns a freshly-allocated (sum . count) pair.
     10 ;
     11 ; The clone runs while main is current and reads from scratch via
     12 ; ordinary pointer access — neither heap selection affects loads, only
     13 ; allocations. After the clone, scratch can be wholesale reset because
     14 ; nothing in main points into it.
     15 
     16 (define (C input)
     17   (let loop ((xs input) (sum 0) (count 0))
     18     (if (null? xs)
     19         (cons sum count)
     20         (loop (cdr xs) (+ sum (car xs)) (+ count 1)))))
     21 
     22 ; Promote: read from scratch-allocated pair, allocate the clone in
     23 ; the currently-selected heap. C's result has fixnum car/cdr so a
     24 ; one-level cons is enough; real promote walkers recurse on heap-
     25 ; allocated children.
     26 (define (promote-pair p)
     27   (cons (car p) (cdr p)))
     28 
     29 (define (B input)
     30   (use-scratch-heap!)
     31   (let ((scratch-result (C input)))
     32     (use-main-heap!)
     33     (let ((main-result (promote-pair scratch-result)))
     34       (reset-scratch-heap!)
     35       main-result)))
     36 
     37 (define (A)
     38   (let ((input (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 '())))))))
     39     (B input)))
     40 
     41 ; Drive B twice. A scratch leak would push the second call past the
     42 ; cap; a missed promotion would leave r1 dangling once r2's run resets.
     43 (define r1 (A))
     44 (define r2 (A))
     45 (define r1-in-main? (heap-in-main? r1))
     46 (define r2-in-main? (heap-in-main? r2))
     47 
     48 (sys-exit
     49   (cond
     50     ((not r1-in-main?)        1)        ; clone landed in main
     51     ((not r2-in-main?)        2)
     52     ((not (= (car r1) 15))    3)        ; r1 still readable after r2's reset
     53     ((not (= (cdr r1) 5))     4)
     54     ((not (= (car r2) 15))    5)
     55     ((not (= (cdr r2) 5))     6)
     56     (else 42)))