boot2

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

122-deep-copy.scm (5107B)


      1 ; Generic deep-copy: structural clone of pairs / bytevectors / records,
      2 ; with identity preservation across shared substructure and cycle
      3 ; tolerance via an eager stand-in registered before slot fill. Used by
      4 ; cc.scm to promote scratch-allocated parse output into main; mirror
      5 ; here in scheme1 itself to lock down the contract. See
      6 ; docs/DEEP-COPY.md.
      7 ;
      8 ; By design, deep-copy short-circuits when an object is already in the
      9 ; current heap (so re-promotion is O(1)). The structural tests below
     10 ; therefore allocate sources in scratch and copy with main current.
     11 
     12 (define-record-type cell
     13   (mk-cell head tail)
     14   cell?
     15   (head cell-head cell-head-set!)
     16   (tail cell-tail cell-tail-set!))
     17 
     18 ;; ---- Already-in-target short-circuit returns the same object ----
     19 (define m-pair (cons 1 2))
     20 (define ctx0 (make-deep-copy-context))
     21 (if (eq? m-pair (deep-copy ctx0 m-pair)) 0 (sys-exit 1))
     22 
     23 ;; ---- Symbols pass through untouched (interned) ----
     24 (if (eq? 'foo (deep-copy ctx0 'foo))     0 (sys-exit 2))
     25 
     26 ;; ---- Fixnums / immediates pass through ----
     27 (if (= 42 (deep-copy ctx0 42))           0 (sys-exit 3))
     28 (if (eq? #t (deep-copy ctx0 #t))         0 (sys-exit 4))
     29 (if (eq? '() (deep-copy ctx0 '()))       0 (sys-exit 5))
     30 
     31 ;; ---- Pair deep-copy from scratch -> main ----
     32 (use-scratch-heap!)
     33 (define s-list (cons 1 (cons 2 (cons 3 '()))))
     34 (use-main-heap!)
     35 (define ctx1 (make-deep-copy-context))
     36 (define m-list (deep-copy ctx1 s-list))
     37 (if (equal? s-list m-list)               0 (sys-exit 10))
     38 (if (not (eq? s-list m-list))            0 (sys-exit 11))
     39 (if (heap-in-main? m-list)               0 (sys-exit 12))
     40 (if (heap-in-main? (cdr m-list))         0 (sys-exit 13))
     41 (reset-scratch-heap!)
     42 ;; m-list survives scratch reset
     43 (if (equal? m-list (cons 1 (cons 2 (cons 3 '())))) 0 (sys-exit 14))
     44 
     45 ;; ---- Bytevector deep-copy from scratch -> main ----
     46 (use-scratch-heap!)
     47 (define s-bv (bytevector 1 2 3 4 5))
     48 (use-main-heap!)
     49 (define ctx2 (make-deep-copy-context))
     50 (define m-bv (deep-copy ctx2 s-bv))
     51 (if (bytevector=? s-bv m-bv)             0 (sys-exit 20))
     52 (if (not (eq? s-bv m-bv))                0 (sys-exit 21))
     53 (if (heap-in-main? m-bv)                 0 (sys-exit 22))
     54 (reset-scratch-heap!)
     55 ;; main-heap copy survives scratch reset
     56 (if (= 5 (bytevector-length m-bv))       0 (sys-exit 23))
     57 (if (= 1 (bytevector-u8-ref m-bv 0))     0 (sys-exit 24))
     58 (if (= 5 (bytevector-u8-ref m-bv 4))     0 (sys-exit 25))
     59 
     60 ;; ---- Record deep-copy from scratch -> main ----
     61 (use-scratch-heap!)
     62 (define s-cell (mk-cell 10 20))
     63 (use-main-heap!)
     64 (define ctx3 (make-deep-copy-context))
     65 (define m-cell (deep-copy ctx3 s-cell))
     66 (if (cell? m-cell)                       0 (sys-exit 30))
     67 (if (not (eq? s-cell m-cell))            0 (sys-exit 31))
     68 (if (= 10 (cell-head m-cell))            0 (sys-exit 32))
     69 (if (= 20 (cell-tail m-cell))            0 (sys-exit 33))
     70 ;; Same TD: TDs are persistent and not copied
     71 (if (eq? (record-td s-cell) (record-td m-cell)) 0 (sys-exit 34))
     72 (if (heap-in-main? m-cell)               0 (sys-exit 35))
     73 (reset-scratch-heap!)
     74 (if (= 10 (cell-head m-cell))            0 (sys-exit 36))
     75 
     76 ;; ---- Identity preservation across shared subobjects ----
     77 (use-scratch-heap!)
     78 (define s-shared (cons 'a 'b))
     79 (define s-x (cons s-shared s-shared))
     80 (use-main-heap!)
     81 (define ctx4 (make-deep-copy-context))
     82 (define m-x (deep-copy ctx4 s-x))
     83 ;; Both halves of the result reference one fresh shared cons in main.
     84 (if (eq? (car m-x) (cdr m-x))            0 (sys-exit 40))
     85 (if (not (eq? (car m-x) s-shared))       0 (sys-exit 41))
     86 (if (eq? 'a (car (car m-x)))             0 (sys-exit 42))
     87 (if (eq? 'b (cdr (car m-x)))             0 (sys-exit 43))
     88 (reset-scratch-heap!)
     89 
     90 ;; ---- Cycle handling (record points to itself) ----
     91 (use-scratch-heap!)
     92 (define s-cyc (mk-cell 1 #f))
     93 (cell-tail-set! s-cyc s-cyc)
     94 (use-main-heap!)
     95 (define ctx5 (make-deep-copy-context))
     96 (define m-cyc (deep-copy ctx5 s-cyc))
     97 (if (not (eq? s-cyc m-cyc))              0 (sys-exit 50))
     98 (if (= 1 (cell-head m-cyc))              0 (sys-exit 51))
     99 (if (eq? m-cyc (cell-tail m-cyc))        0 (sys-exit 52))
    100 (reset-scratch-heap!)
    101 ;; m-cyc still its own tail after scratch reset
    102 (if (eq? m-cyc (cell-tail m-cyc))        0 (sys-exit 53))
    103 
    104 ;; ---- Mixed pair-of-record graph ----
    105 (use-scratch-heap!)
    106 (define s-rec (mk-cell 9 (cons 1 (cons 2 '()))))
    107 (use-main-heap!)
    108 (define ctx6 (make-deep-copy-context))
    109 (define m-rec (deep-copy ctx6 s-rec))
    110 (if (not (eq? s-rec m-rec))              0 (sys-exit 60))
    111 (if (= 9 (cell-head m-rec))              0 (sys-exit 61))
    112 (if (equal? (cell-tail m-rec) '(1 2))    0 (sys-exit 62))
    113 (if (heap-in-main? m-rec)                0 (sys-exit 63))
    114 (if (heap-in-main? (cell-tail m-rec))    0 (sys-exit 64))
    115 (reset-scratch-heap!)
    116 (if (equal? (cell-tail m-rec) '(1 2))    0 (sys-exit 65))
    117 
    118 ;; ---- ctx reuse: second pass over the same already-copied root is O(1)
    119 ;; via heap-in-current?, returning the main-heap object directly.
    120 (define ctx7 (make-deep-copy-context))
    121 (define copy-once (deep-copy ctx7 (cons 'a (cons 'b '()))))
    122 (define copy-again (deep-copy ctx7 copy-once))
    123 (if (eq? copy-once copy-again)           0 (sys-exit 70))
    124 
    125 (sys-exit 42)