#lang plai/gc2/collector (define (init-allocator) (heap-set! 0 1)) (define (malloc n) (define addr (heap-ref 0)) (unless (<= (+ addr n) (heap-size)) (error 'allocator "out of memory")) (heap-set! 0 (+ addr n)) addr) (define (gc:flat? addr) (equal? (heap-ref addr) 'flat)) (define (gc:alloc-flat x) (define addr (malloc 2)) (heap-set! addr 'flat) (heap-set! (+ addr 1) x) addr) (define (gc:deref addr) (unless (equal? (heap-ref addr) 'flat) (error 'gc:deref "not a flat at ~a" addr)) (heap-ref (+ addr 1))) (define (gc:cons f r) (define addr (malloc 3)) (heap-set! addr 'cons) (heap-set! (+ addr 1) (read-root f)) (heap-set! (+ addr 2) (read-root r)) addr) (define (gc:cons? addr) (equal? (heap-ref addr) 'cons)) (define (gc:first addr) (check-pair addr) (heap-ref (+ addr 1))) (define (gc:rest addr) (check-pair addr) (heap-ref (+ addr 2))) (define (check-pair addr) (unless (equal? (heap-ref addr) 'cons) (error 'check-pair "not a pair @ ~a" addr))) (define (gc:set-first! addr v) (check-pair addr) (heap-set! (+ addr 1) v)) (define (gc:set-rest! addr v) (check-pair addr) (heap-set! (+ addr 2) v)) (define (gc:closure code-pointer free-vars) (define addr (malloc (+ 2 (length free-vars)))) (heap-set! addr 'clos) (heap-set! (+ addr 1) code-pointer) (for ([i (in-range 0 (length free-vars))] [v (in-list free-vars)]) (heap-set! (+ addr 2 i) (read-root v))) addr) (define (gc:closure? addr) (equal? (heap-ref addr) 'clos)) (define (gc:closure-code-ptr addr) (unless (gc:closure? addr) (error "not a closure @ ~a" addr)) (heap-ref (+ addr 1))) (define (gc:closure-env-ref addr i) (unless (gc:closure? addr) (error "not a closure @ ~a" addr)) (heap-ref (+ addr 2 i))) (module+ test (with-heap (vector 'x 'x 'x 'x 'x) (init-allocator) (gc:alloc-flat #f) (test (current-heap) (vector 3 'flat #f 'x 'x)))) (module+ test (with-heap (vector 'x 'x 'x 'x 'x 'x 'x 'x 'x) (init-allocator) (gc:cons (simple-root (gc:alloc-flat #f)) (simple-root (gc:alloc-flat #t))) (test (current-heap) (vector 8 'flat #f 'flat #t 'cons 1 3 'x))))