/collects/compiler/zo-parse.rkt
http://github.com/gmarceau/PLT · Racket · 1064 lines · 19 code · 11 blank · 1034 comment · 0 complexity · badbf3ca5f76164d6bc1e532cbc66842 MD5 · raw file
- #lang racket/base
- (require racket/function
- racket/match
- racket/list
- unstable/struct
- compiler/zo-structs
- racket/dict
- racket/set)
- (provide zo-parse)
- (provide (all-from-out compiler/zo-structs))
- #| Unresolved Issues
- The order of indirect-et-provides, indirect-syntax-provides, indirect-provides was changed, is that okay?
-
- orig-port of cport struct is never used, is it needed?
- Lines 628, 630 seem to be only for debugging and should probably throw errors
- vector and pair cases of decode-wraps seem to do different things from the corresponding C code
- Line 816: This should be an eqv placeholder (but they don't exist)
- Line 634: Export registry is always matched as false, but might not be
- What are the real differences between the module-binding cases?
- I think parse-module-path-index was only used for debugging, so it is short-circuited now
- |#
- ;; ----------------------------------------
- ;; Bytecode unmarshalers for various forms
- (define (read-toplevel v)
- (define SCHEME_TOPLEVEL_CONST #x01)
- (define SCHEME_TOPLEVEL_READY #x02)
- (match v
- [(cons depth (cons pos flags))
- (make-toplevel depth pos
- (positive? (bitwise-and flags SCHEME_TOPLEVEL_CONST))
- (positive? (bitwise-and flags SCHEME_TOPLEVEL_READY)))]
- [(cons depth pos)
- (make-toplevel depth pos #f #f)]))
- (define (read-topsyntax v)
- (match v
- [`(,depth ,pos . ,midpt)
- (make-topsyntax depth pos midpt)]))
- (define (read-variable v)
- (if (symbol? v)
- (make-global-bucket v)
- (error "expected a symbol")))
- (define (do-not-read-variable v)
- (error "should not get here"))
- (define (read-compilation-top v)
- (match v
- [`(,ld ,prefix . ,code)
- (unless (prefix? prefix)
- (error 'bad "not prefix ~a" prefix))
- (make-compilation-top ld prefix code)]))
- (define (read-resolve-prefix v)
- (let-values ([(v unsafe?) (if (integer? (car v))
- (values v #f)
- (values (cdr v) #t))])
- (match v
- [`(,i ,tv . ,sv)
- ; XXX Why not leave them as vectors and change the contract?
- (make-prefix i (vector->list tv) (vector->list sv))])))
- (define read-free-id-info
- (match-lambda
- [(vector mpi0 symbol0 mpi1 symbol1 num0 num1 num2 bool0) ; I have no idea what these mean
- (make-free-id-info mpi0 symbol0 mpi1 symbol1 num0 num1 num2 bool0)]))
- (define (read-unclosed-procedure v)
- (define CLOS_HAS_REST 1)
- (define CLOS_HAS_REF_ARGS 2)
- (define CLOS_PRESERVES_MARKS 4)
- (define CLOS_NEED_REST_CLEAR 8)
- (define CLOS_IS_METHOD 16)
- (define CLOS_SINGLE_RESULT 32)
- (define BITS_PER_MZSHORT 32)
- (match v
- [`(,flags ,num-params ,max-let-depth ,tl-map ,name ,v . ,rest)
- (let ([rest? (positive? (bitwise-and flags CLOS_HAS_REST))])
- (let*-values ([(closure-size closed-over body)
- (if (zero? (bitwise-and flags CLOS_HAS_REF_ARGS))
- (values (vector-length v) v rest)
- (values v (car rest) (cdr rest)))]
- [(check-bit) (lambda (i)
- (if (zero? (bitwise-and flags CLOS_HAS_REF_ARGS))
- 0
- (let ([byte (vector-ref closed-over
- (+ closure-size (quotient (* 2 i) BITS_PER_MZSHORT)))])
- (+ (if (bitwise-bit-set? byte (remainder (* 2 i) BITS_PER_MZSHORT))
- 1
- 0)
- (if (bitwise-bit-set? byte (add1 (remainder (* 2 i) BITS_PER_MZSHORT)))
- 2
- 0)))))]
- [(arg-types) (let ([num-params ((if rest? sub1 values) num-params)])
- (for/list ([i (in-range num-params)])
- (case (check-bit i)
- [(0) 'val]
- [(1) 'ref]
- [(2) 'flonum])))]
- [(closure-types) (for/list ([i (in-range closure-size)]
- [j (in-naturals num-params)])
- (case (check-bit j)
- [(0) 'val/ref]
- [(2) 'flonum]))])
- (make-lam name
- (append
- (if (zero? (bitwise-and flags flags CLOS_PRESERVES_MARKS)) null '(preserves-marks))
- (if (zero? (bitwise-and flags flags CLOS_IS_METHOD)) null '(is-method))
- (if (zero? (bitwise-and flags flags CLOS_SINGLE_RESULT)) null '(single-result))
- (if (zero? (bitwise-and flags flags CLOS_NEED_REST_CLEAR)) null '(sfs-clear-rest-args))
- (if (and rest? (zero? num-params)) '(only-rest-arg-not-used) null))
- (if (and rest? (num-params . > . 0))
- (sub1 num-params)
- num-params)
- arg-types
- rest?
- (if (= closure-size (vector-length closed-over))
- closed-over
- (let ([v2 (make-vector closure-size)])
- (vector-copy! v2 0 closed-over 0 closure-size)
- v2))
- closure-types
- (and tl-map
- (let* ([bits (if (exact-integer? tl-map)
- tl-map
- (for/fold ([i 0]) ([v (in-vector tl-map)]
- [s (in-naturals)])
- (bitwise-ior i (arithmetic-shift v (* s 16)))))]
- [len (integer-length bits)])
- (list->set
- (let loop ([bit 0])
- (cond
- [(bit . >= . len) null]
- [(bitwise-bit-set? bits bit)
- (cons bit (loop (add1 bit)))]
- [else (loop (add1 bit))])))))
- max-let-depth
- body)))]))
- (define (read-let-value v)
- (match v
- [`(,count ,pos ,boxes? ,rhs . ,body)
- (make-install-value count pos boxes? rhs body)]))
- (define (read-let-void v)
- (match v
- [`(,count ,boxes? . ,body)
- (make-let-void count boxes? body)]))
- (define (read-letrec v)
- (match v
- [`(,count ,body . ,procs)
- (make-let-rec procs body)]))
- (define (read-with-cont-mark v)
- (match v
- [`(,key ,val . ,body)
- (make-with-cont-mark key val body)]))
- (define (read-sequence v)
- (make-seq v))
- ; XXX Allocates unnessary list
- (define (read-define-values v)
- (make-def-values
- (cdr (vector->list v))
- (vector-ref v 0)))
- ; XXX Allocates unnessary list
- (define (read-define-syntaxes mk v)
- (mk (list-tail (vector->list v) 4)
- (vector-ref v 0)
- (vector-ref v 1)
- (vector-ref v 2)
- #;(vector-ref v 3)))
- (define (read-define-syntax v)
- (read-define-syntaxes make-def-syntaxes v))
- (define (read-define-for-syntax v)
- (read-define-syntaxes make-def-for-syntax v))
- (define (read-set! v)
- (make-assign (cadr v) (cddr v) (car v)))
- (define (read-case-lambda v)
- (make-case-lam (car v) (cdr v)))
- (define (read-begin0 v)
- (make-beg0 v))
- (define (read-boxenv v)
- (make-boxenv (car v) (cdr v)))
- (define (read-require v)
- (make-req (cdr v) (car v)))
- (define (read-#%variable-ref v)
- (make-varref (car v) (cdr v)))
- (define (read-apply-values v)
- (make-apply-values (car v) (cdr v)))
- (define (read-splice v)
- (make-splice v))
- (define (in-list* l n)
- (make-do-sequence
- (lambda ()
- (values (lambda (l) (apply values (take l n)))
- (lambda (l) (drop l n))
- l
- (lambda (l) (>= (length l) n))
- (lambda _ #t)
- (lambda _ #t)))))
- (define (read-module v)
- (match v
- [`(,name ,srcname ,self-modidx ,lang-info ,functional? ,et-functional?
- ,rename ,max-let-depth ,dummy
- ,prefix
- ,indirect-et-provides ,num-indirect-et-provides
- ,indirect-syntax-provides ,num-indirect-syntax-provides
- ,indirect-provides ,num-indirect-provides
- ,protects ,et-protects
- ,provide-phase-count . ,rest)
- (let ([phase-data (take rest (* 8 provide-phase-count))])
- (match (list-tail rest (* 8 provide-phase-count))
- [`(,syntax-body ,body
- ,requires ,syntax-requires ,template-requires ,label-requires
- ,more-requires-count . ,more-requires)
- (make-mod name srcname self-modidx
- prefix (let loop ([l phase-data])
- (if (null? l)
- null
- (let ([num-vars (list-ref l 6)]
- [ps (for/list ([name (in-vector (list-ref l 5))]
- [src (in-vector (list-ref l 4))]
- [src-name (in-vector (list-ref l 3))]
- [nom-src (or (list-ref l 2)
- (in-cycle (in-value #f)))]
- [src-phase (or (list-ref l 1)
- (in-cycle (in-value #f)))]
- [protected? (or (case (car l)
- [(0) protects]
- [(1) et-protects]
- [else #f])
- (in-cycle (in-value #f)))])
- (make-provided name src src-name
- (or nom-src src)
- (if src-phase 1 0)
- protected?))])
- (if (null? ps)
- (loop (list-tail l 8))
- (cons
- (list
- (car l)
- (take ps num-vars)
- (drop ps num-vars))
- (loop (list-tail l 8)))))))
- (list*
- (cons 0 requires)
- (cons 1 syntax-requires)
- (cons -1 template-requires)
- (cons #f label-requires)
- (for/list ([(phase reqs) (in-list* more-requires 2)])
- (cons phase reqs)))
- (vector->list body)
- (map (lambda (sb)
- (match sb
- [(? def-syntaxes?) sb]
- [(? def-for-syntax?) sb]
- [`#(,ids ,expr ,max-let-depth ,prefix ,for-stx?)
- ((if for-stx?
- make-def-for-syntax
- make-def-syntaxes)
- (if (list? ids) ids (list ids)) expr prefix max-let-depth)]))
- (vector->list syntax-body))
- (list (vector->list indirect-provides)
- (vector->list indirect-syntax-provides)
- (vector->list indirect-et-provides))
- max-let-depth
- dummy
- lang-info
- rename)]))]))
- (define (read-module-wrap v)
- v)
- ;; ----------------------------------------
- ;; Unmarshal dispatch for various types
- ;; Type mappings from "stypes.h":
- (define (int->type i)
- (case i
- [(0) 'toplevel-type]
- [(6) 'sequence-type]
- [(8) 'unclosed-procedure-type]
- [(9) 'let-value-type]
- [(10) 'let-void-type]
- [(11) 'letrec-type]
- [(13) 'with-cont-mark-type]
- [(14) 'quote-syntax-type]
- [(15) 'define-values-type]
- [(16) 'define-syntaxes-type]
- [(17) 'define-for-syntax-type]
- [(18) 'set-bang-type]
- [(19) 'boxenv-type]
- [(20) 'begin0-sequence-type]
- [(21) 'splice-sequence-type]
- [(22) 'require-form-type]
- [(23) 'varref-form-type]
- [(24) 'apply-values-type]
- [(25) 'case-lambda-sequence-type]
- [(26) 'module-type]
- [(34) 'variable-type]
- [(35) 'module-variable-type]
- [(112) 'resolve-prefix-type]
- [(161) 'free-id-info-type]
- [else (error 'int->type "unknown type: ~e" i)]))
- (define type-readers
- (make-immutable-hash
- (list
- (cons 'toplevel-type read-toplevel)
- (cons 'sequence-type read-sequence)
- (cons 'unclosed-procedure-type read-unclosed-procedure)
- (cons 'let-value-type read-let-value)
- (cons 'let-void-type read-let-void)
- (cons 'letrec-type read-letrec)
- (cons 'with-cont-mark-type read-with-cont-mark)
- (cons 'quote-syntax-type read-topsyntax)
- (cons 'variable-type read-variable)
- (cons 'module-variable-type do-not-read-variable)
- (cons 'compilation-top-type read-compilation-top)
- (cons 'case-lambda-sequence-type read-case-lambda)
- (cons 'begin0-sequence-type read-begin0)
- (cons 'module-type read-module)
- (cons 'resolve-prefix-type read-resolve-prefix)
- (cons 'free-id-info-type read-free-id-info)
- (cons 'define-values-type read-define-values)
- (cons 'define-syntaxes-type read-define-syntax)
- (cons 'define-for-syntax-type read-define-for-syntax)
- (cons 'set-bang-type read-set!)
- (cons 'boxenv-type read-boxenv)
- (cons 'require-form-type read-require)
- (cons 'varref-form-type read-#%variable-ref)
- (cons 'apply-values-type read-apply-values)
- (cons 'sequence-splice-type read-splice))))
- (define (get-reader type)
- (hash-ref type-readers type
- (λ ()
- (error 'read-marshalled "reader for ~a not implemented" type))))
- ;; ----------------------------------------
- ;; Lowest layer of bytecode parsing
- (define (split-so all-short so)
- (define n (if (zero? all-short) 4 2))
- (let loop ([so so])
- (if (zero? (bytes-length so))
- null
- (cons (integer-bytes->integer (subbytes so 0 n) #f #f)
- (loop (subbytes so n))))))
- (define (read-simple-number p)
- (integer-bytes->integer (read-bytes 4 p) #f #f))
- (define-struct cport ([pos #:mutable] shared-start orig-port size bytes-start symtab shared-offsets decoded rns mpis))
- (define (cport-get-bytes cp len)
- (define port (cport-orig-port cp))
- (define pos (cport-pos cp))
- (file-position port (+ (cport-bytes-start cp) pos))
- (read-bytes len port))
- (define (cport-get-byte cp pos)
- (define port (cport-orig-port cp))
- (file-position port (+ (cport-bytes-start cp) pos))
- (read-byte port))
- (define (cport-rpos cp)
- (+ (cport-pos cp) (cport-shared-start cp)))
- (define (cp-getc cp)
- (when ((cport-pos cp) . >= . (cport-size cp))
- (error "off the end"))
- (define r (cport-get-byte cp (cport-pos cp)))
- (set-cport-pos! cp (add1 (cport-pos cp)))
- r)
- (define small-list-max 65)
- (define cpt-table
- ;; The "schcpt.h" mapping
- `([0 escape]
- [1 symbol]
- [2 symref]
- [3 weird-symbol]
- [4 keyword]
- [5 byte-string]
- [6 string]
- [7 char]
- [8 int]
- [9 null]
- [10 true]
- [11 false]
- [12 void]
- [13 box]
- [14 pair]
- [15 list]
- [16 vector]
- [17 hash-table]
- [18 stx]
- [19 let-one-flonum]
- [20 marshalled]
- [21 quote]
- [22 reference]
- [23 local]
- [24 local-unbox]
- [25 svector]
- [26 application]
- [27 let-one]
- [28 branch]
- [29 module-index]
- [30 module-var]
- [31 path]
- [32 closure]
- [33 delayed]
- [34 prefab]
- [35 let-one-unused]
- [36 60 small-number]
- [60 80 small-symbol]
- [80 92 small-marshalled]
- [92 ,(+ 92 small-list-max) small-proper-list]
- [,(+ 92 small-list-max) 192 small-list]
- [192 207 small-local]
- [207 222 small-local-unbox]
- [222 247 small-svector]
- [248 small-application2]
- [249 small-application3]
- [247 255 small-application]))
- (define (cpt-table-lookup i)
- (for/or ([ent cpt-table])
- (match ent
- [(list k sym) (and (= k i) (cons k sym))]
- [(list k k* sym)
- (and (<= k i)
- (< i k*)
- (cons k sym))])))
- (define (read-compact-bytes port c)
- (begin0
- (cport-get-bytes port c)
- (set-cport-pos! port (+ c (cport-pos port)))))
- (define (read-compact-chars port c)
- (bytes->string/utf-8 (read-compact-bytes port c)))
- (define (read-compact-list c proper port)
- (cond [(= 0 c)
- (if proper null (read-compact port))]
- [else (cons (read-compact port) (read-compact-list (sub1 c) proper port))]))
- (define (read-compact-number port)
- (define flag (cp-getc port))
- (cond [(< flag 128)
- flag]
- [(zero? (bitwise-and flag #x40))
- (let ([a (cp-getc port)])
- (+ (a . << . 6) (bitwise-and flag 63)))]
- [(zero? (bitwise-and flag #x20))
- (- (bitwise-and flag #x1F))]
- [else
- (let ([a (cp-getc port)]
- [b (cp-getc port)]
- [c (cp-getc port)]
- [d (cp-getc port)])
- (let ([n (integer-bytes->integer (bytes a b c d) #f #f)])
- (if (zero? (bitwise-and flag #x10))
- (- n)
- n)))]))
- (define (read-compact-svector port n)
- (define v (make-vector n))
- (for ([i (in-range n)])
- (vector-set! v (sub1 (- n i)) (read-compact-number port)))
- v)
- (define (read-marshalled type port)
- (let* ([type (if (number? type) (int->type type) type)]
- [l (read-compact port)]
- [reader (get-reader type)])
- (reader l)))
- (define (make-local unbox? pos flags)
- (define SCHEME_LOCAL_CLEAR_ON_READ #x01)
- (define SCHEME_LOCAL_OTHER_CLEARS #x02)
- (define SCHEME_LOCAL_FLONUM #x03)
- (make-localref unbox? pos
- (= flags SCHEME_LOCAL_CLEAR_ON_READ)
- (= flags SCHEME_LOCAL_OTHER_CLEARS)
- (= flags SCHEME_LOCAL_FLONUM)))
- (define (a . << . b)
- (arithmetic-shift a b))
- (define-struct not-ready ())
- ;; ----------------------------------------
- ;; Syntax unmarshaling
- (define (make-memo) (make-weak-hash))
- (define (with-memo* mt arg thnk)
- (hash-ref! mt arg thnk))
- (define-syntax-rule (with-memo mt arg body ...)
- (with-memo* mt arg (λ () body ...)))
- (define (decode-mark-map alist)
- alist)
- (define stx-memo (make-memo))
- ; XXX More memo use
- (define (decode-stx cp v)
- (with-memo stx-memo v
- (if (integer? v)
- (unmarshal-stx-get/decode cp v decode-stx)
- (let loop ([v v])
- (let-values ([(tamper-status v encoded-wraps)
- (match v
- [`#((,datum . ,wraps)) (values 'tainted datum wraps)]
- [`#((,datum . ,wraps) #f) (values 'armed datum wraps)]
- [`(,datum . ,wraps) (values 'clean datum wraps)]
- [else (error 'decode-wraps "bad datum+wrap: ~.s" v)])])
- (let* ([wraps (decode-wraps cp encoded-wraps)]
- [wrapped-memo (make-memo)]
- [add-wrap (lambda (v) (with-memo wrapped-memo v (make-wrapped v wraps tamper-status)))])
- (cond
- [(pair? v)
- (if (eq? #t (car v))
- ;; Share decoded wraps with all nested parts.
- (let loop ([v (cdr v)])
- (cond
- [(pair? v)
- (let ploop ([v v])
- (cond
- [(null? v) null]
- [(pair? v) (add-wrap (cons (loop (car v)) (ploop (cdr v))))]
- [else (loop v)]))]
- [(box? v) (add-wrap (box (loop (unbox v))))]
- [(vector? v)
- (add-wrap (list->vector (map loop (vector->list v))))]
- [(prefab-struct-key v)
- => (lambda (k)
- (add-wrap
- (apply
- make-prefab-struct
- k
- (map loop (struct->list v)))))]
- [else (add-wrap v)]))
- ;; Decode sub-elements that have their own wraps:
- (let-values ([(v counter) (if (exact-integer? (car v))
- (values (cdr v) (car v))
- (values v -1))])
- (add-wrap
- (let ploop ([v v][counter counter])
- (cond
- [(null? v) null]
- [(or (not (pair? v)) (zero? counter)) (loop v)]
- [(pair? v) (cons (loop (car v))
- (ploop (cdr v) (sub1 counter)))])))))]
- [(box? v) (add-wrap (box (loop (unbox v))))]
- [(vector? v)
- (add-wrap (list->vector (map loop (vector->list v))))]
- [(prefab-struct-key v)
- => (lambda (k)
- (add-wrap
- (apply
- make-prefab-struct
- k
- (map loop (struct->list v)))))]
- [else (add-wrap v)])))))))
- (define wrape-memo (make-memo))
- (define (decode-wrape cp a)
- (define (aloop a) (decode-wrape cp a))
- (with-memo wrape-memo a
- ; A wrap-elem is either
- (cond
- ; A reference
- [(integer? a)
- (unmarshal-stx-get/decode cp a (lambda (cp v) (aloop v)))]
- ; A mark (not actually a number as the C says, but a (list <num>)
- [(and (pair? a) (number? (car a)))
- (make-wrap-mark (car a))]
-
- [(vector? a)
- (make-lexical-rename (vector-ref a 0) (vector-ref a 1)
- (let ([top (+ (/ (- (vector-length a) 2) 2) 2)])
- (let loop ([i 2])
- (if (= i top)
- null
- (cons (cons (vector-ref a i)
- (vector-ref a (+ (- top 2) i)))
- (loop (+ i 1)))))))]
- [(pair? a)
- (let-values ([(plus-kern? a) (if (eq? (car a) #t)
- (values #t (cdr a))
- (values #f a))])
- (match a
- [`(,phase ,kind ,set-id ,maybe-unmarshals . ,renames)
- (let-values ([(unmarshals renames mark-renames)
- (if (vector? maybe-unmarshals)
- (values null maybe-unmarshals renames)
- (values maybe-unmarshals
- (car renames)
- (cdr renames)))])
- (make-module-rename phase
- (if kind 'marked 'normal)
- set-id
- (map (curry decode-all-from-module cp) unmarshals)
- (decode-renames renames)
- mark-renames
- (and plus-kern? 'plus-kern)))]
- [else (error "bad module rename: ~e" a)]))]
- [(boolean? a)
- (make-top-level-rename a)]
- [(symbol? a)
- (make-mark-barrier a)]
- [(box? a)
- (match (unbox a)
- [(list (? symbol?) ...) (make-prune (unbox a))]
- [`#(,amt ,src ,dest #f #f)
- (make-phase-shift amt
- (parse-module-path-index cp src)
- (parse-module-path-index cp dest))]
- [else (error 'parse "bad phase shift: ~e" a)])]
- [else (error 'decode-wraps "bad wrap element: ~e" a)])))
- (define all-from-module-memo (make-memo))
- (define (decode-all-from-module cp afm)
- (define (phase? v)
- (or (number? v) (not v)))
- (with-memo all-from-module-memo afm
- (match afm
- [(list* path (? phase? phase) (? phase? src-phase)
- (list exn ...) prefix)
- (make-all-from-module
- (parse-module-path-index cp path)
- phase src-phase exn (vector prefix))]
- [(list* path (? phase? phase) (list exn ...) (? phase? src-phase))
- (make-all-from-module
- (parse-module-path-index cp path)
- phase src-phase exn #f)]
- [(list* path (? phase? phase) (? phase? src-phase))
- (make-all-from-module
- (parse-module-path-index cp path)
- phase src-phase #f #f)])))
- (define wraps-memo (make-memo))
- (define (decode-wraps cp w)
- (with-memo wraps-memo w
- ; A wraps is either a indirect reference or a list of wrap-elems (from stxobj.c:252)
- (if (integer? w)
- (unmarshal-stx-get/decode cp w decode-wraps)
- (map (curry decode-wrape cp) w))))
- (define (in-vector* v n)
- (make-do-sequence
- (λ ()
- (values (λ (i) (vector->values v i (+ i n)))
- (λ (i) (+ i n))
- 0
- (λ (i) (>= (vector-length v) (+ i n)))
- (λ _ #t)
- (λ _ #t)))))
- (define nominal-path-memo (make-memo))
- (define (decode-nominal-path np)
- (with-memo nominal-path-memo np
- (match np
- [(cons nominal-path (cons import-phase nominal-phase))
- (make-phased-nominal-path nominal-path import-phase nominal-phase)]
- [(cons nominal-path import-phase)
- (make-imported-nominal-path nominal-path import-phase)]
- [nominal-path
- (make-simple-nominal-path nominal-path)])))
- ; XXX Weird test copied from C code. Matthew?
- (define (nom_mod_p p)
- (and (pair? p) (not (pair? (cdr p))) (not (symbol? (cdr p)))))
- (define rename-v-memo (make-memo))
- (define (decode-rename-v v)
- (with-memo rename-v-memo v
- (match v
- [(list-rest path phase export-name nominal-path nominal-export-name)
- (make-phased-module-binding path
- phase
- export-name
- (decode-nominal-path nominal-path)
- nominal-export-name)]
- [(list-rest path export-name nominal-path nominal-export-name)
- (make-exported-nominal-module-binding path
- export-name
- (decode-nominal-path nominal-path)
- nominal-export-name)]
- [(cons module-path-index (? nom_mod_p nominal-path))
- (make-nominal-module-binding module-path-index (decode-nominal-path nominal-path))]
- [(cons module-path-index export-name)
- (make-exported-module-binding module-path-index export-name)]
- [module-path-index
- (make-simple-module-binding module-path-index)])))
- (define renames-memo (make-memo))
- (define (decode-renames renames)
- (with-memo renames-memo renames
- (for/list ([(k v) (in-vector* renames 2)])
- (cons k (decode-rename-v v)))))
- (define (parse-module-path-index cp s)
- s)
- ;; ----------------------------------------
- ;; Main parsing loop
- (define (read-compact cp)
- (let loop ([need-car 0] [proper #f])
- (define ch (cp-getc cp))
- (define-values (cpt-start cpt-tag)
- (let ([x (cpt-table-lookup ch)])
- (unless x
- (error 'read-compact "unknown code : ~a" ch))
- (values (car x) (cdr x))))
- (define v
- (case cpt-tag
- [(delayed)
- (let ([pos (read-compact-number cp)])
- (read-sym cp pos))]
- [(escape)
- (let* ([len (read-compact-number cp)]
- [s (cport-get-bytes cp len)])
- (set-cport-pos! cp (+ (cport-pos cp) len))
- (parameterize ([read-accept-compiled #t]
- [read-accept-bar-quote #t]
- [read-accept-box #t]
- [read-accept-graph #t]
- [read-case-sensitive #t]
- [read-square-bracket-as-paren #t]
- [read-curly-brace-as-paren #t]
- [read-decimal-as-inexact #t]
- [read-accept-dot #t]
- [read-accept-infix-dot #t]
- [read-accept-quasiquote #t]
- [current-readtable
- (make-readtable
- #f
- #\^
- 'dispatch-macro
- (lambda (char port src line col pos)
- (let ([b (read port)])
- (unless (bytes? b)
- (error 'read-escaped-path
- "expected a byte string after #^"))
- (let ([p (bytes->path b)])
- (if (and (relative-path? p)
- (current-load-relative-directory))
- (build-path (current-load-relative-directory) p)
- p)))))])
- (read/recursive (open-input-bytes s))))]
- [(reference)
- (make-primval (read-compact-number cp))]
- [(small-list small-proper-list)
- (let* ([l (- ch cpt-start)]
- [ppr (eq? cpt-tag 'small-proper-list)])
- (if (positive? need-car)
- (if (= l 1)
- (cons (read-compact cp)
- (if ppr null (read-compact cp)))
- (read-compact-list l ppr cp))
- (loop l ppr)))]
- [(let-one let-one-flonum let-one-unused)
- (make-let-one (read-compact cp) (read-compact cp)
- (eq? cpt-tag 'let-one-flonum)
- (eq? cpt-tag 'let-one-unused))]
- [(branch)
- (make-branch (read-compact cp) (read-compact cp) (read-compact cp))]
- [(module-index) (module-path-index-join (read-compact cp) (read-compact cp))]
- [(module-var)
- (let ([mod (read-compact cp)]
- [var (read-compact cp)]
- [pos (read-compact-number cp)])
- (let-values ([(mod-phase pos)
- (if (= pos -2)
- (values 1 (read-compact-number cp))
- (values 0 pos))])
- (make-module-variable mod var pos mod-phase)))]
- [(local-unbox)
- (let* ([p* (read-compact-number cp)]
- [p (if (< p* 0) (- (add1 p*)) p*)]
- [flags (if (< p* 0) (read-compact-number cp) 0)])
- (make-local #t p flags))]
- [(path)
- (let* ([p (bytes->path (read-compact-bytes cp (read-compact-number cp)))])
- (if (relative-path? p)
- (path->complete-path p (or (current-load-relative-directory)
- (current-directory)))
- p))]
- [(small-number)
- (let ([l (- ch cpt-start)])
- l)]
- [(int)
- (read-compact-number cp)]
- [(false) #f]
- [(true) #t]
- [(null) null]
- [(void) (void)]
- [(vector)
- ; XXX We should provide build-immutable-vector and write this as:
- #;(build-immutable-vector (read-compact-number cp)
- (lambda (i) (read-compact cp)))
- ; XXX Now it allocates an unnessary list AND vector
- (let* ([n (read-compact-number cp)]
- [lst (for/list ([i (in-range n)]) (read-compact cp))])
- (vector->immutable-vector (list->vector lst)))]
- [(pair)
- (let* ([a (read-compact cp)]
- [d (read-compact cp)])
- (cons a d))]
- [(list)
- (let ([len (read-compact-number cp)])
- (let loop ([i len])
- (if (zero? i)
- (read-compact cp)
- (list* (read-compact cp)
- (loop (sub1 i))))))]
- [(prefab)
- (let ([v (read-compact cp)])
- ; XXX This is faster than apply+->list, but can we avoid allocating the vector?
- (call-with-values (lambda () (vector->values v))
- make-prefab-struct))]
- [(hash-table)
- ; XXX Allocates an unnessary list (maybe use for/hash(eq))
- (let ([eq (read-compact-number cp)]
- [len (read-compact-number cp)])
- ((case eq
- [(0) make-hasheq-placeholder]
- [(1) make-hash-placeholder]
- [(2) make-hasheqv-placeholder])
- (for/list ([i (in-range len)])
- (cons (read-compact cp)
- (read-compact cp)))))]
- [(marshalled) (read-marshalled (read-compact-number cp) cp)]
- [(stx)
- (let ([v (make-reader-graph (read-compact cp))])
- (make-stx (decode-stx cp v)))]
- [(local local-unbox)
- (let ([c (read-compact-number cp)]
- [unbox? (eq? cpt-tag 'local-unbox)])
- (if (negative? c)
- (make-local unbox? (- (add1 c)) (read-compact-number cp))
- (make-local unbox? c 0)))]
- [(small-local)
- (make-local #f (- ch cpt-start) 0)]
- [(small-local-unbox)
- (make-local #t (- ch cpt-start) 0)]
- [(small-symbol)
- (let ([l (- ch cpt-start)])
- (string->symbol (read-compact-chars cp l)))]
- [(symbol)
- (let ([l (read-compact-number cp)])
- (string->symbol (read-compact-chars cp l)))]
- [(keyword)
- (let ([l (read-compact-number cp)])
- (string->keyword (read-compact-chars cp l)))]
- [(byte-string)
- (let ([l (read-compact-number cp)])
- (read-compact-bytes cp l))]
- [(string)
- (let ([l (read-compact-number cp)]
- [cl (read-compact-number cp)])
- (read-compact-chars cp l))]
- [(char)
- (integer->char (read-compact-number cp))]
- [(box)
- (box (read-compact cp))]
- [(quote)
- (make-reader-graph
- ;; Nested escapes need to share graph references. So get inside the
- ;; read where `read/recursive' can be used:
- (let ([rt (current-readtable)])
- (parameterize ([current-readtable (make-readtable
- #f
- #\x 'terminating-macro
- (lambda args
- (parameterize ([current-readtable rt])
- (read-compact cp))))])
- (read (open-input-bytes #"x")))))]
- [(symref)
- (let* ([l (read-compact-number cp)])
- (read-sym cp l))]
- [(weird-symbol)
- (let ([uninterned (read-compact-number cp)]
- [str (read-compact-chars cp (read-compact-number cp))])
- (if (= 1 uninterned)
- ; uninterned is equivalent to weird in the C implementation
- (string->uninterned-symbol str)
- ; unreadable is equivalent to parallel in the C implementation
- (string->unreadable-symbol str)))]
- [(small-marshalled)
- (read-marshalled (- ch cpt-start) cp)]
- [(small-application2)
- (make-application (read-compact cp)
- (list (read-compact cp)))]
- [(small-application3)
- (make-application (read-compact cp)
- (list (read-compact cp)
- (read-compact cp)))]
- [(small-application)
- (let ([c (add1 (- ch cpt-start))])
- (make-application (read-compact cp)
- (for/list ([i (in-range (sub1 c))])
- (read-compact cp))))]
- [(application)
- (let ([c (read-compact-number cp)])
- (make-application (read-compact cp)
- (for/list ([i (in-range c)])
- (read-compact cp))))]
- [(closure)
- (read-compact-number cp) ; symbol table pos. our marshaler will generate this
- (let ([v (read-compact cp)])
- (make-closure
- v
- (gensym
- (let ([s (lam-name v)])
- (cond
- [(symbol? s) s]
- [(vector? s) (vector-ref s 0)]
- [else 'closure])))))]
- [(svector)
- (read-compact-svector cp (read-compact-number cp))]
- [(small-svector)
- (read-compact-svector cp (- ch cpt-start))]
- [else (error 'read-compact "unknown tag ~a" cpt-tag)]))
- (cond
- [(zero? need-car) v]
- [(and proper (= need-car 1))
- (cons v null)]
- [else
- (cons v (loop (sub1 need-car) proper))])))
- (define (unmarshal-stx-get/decode cp pos decode-stx)
- (define v2 (read-sym cp pos))
- (define decoded? (vector-ref (cport-decoded cp) pos))
- (if decoded?
- v2
- (let ([dv2 (decode-stx cp v2)])
- (symtab-write! cp pos dv2)
- (vector-set! (cport-decoded cp) pos #t)
- dv2)))
- (define (symtab-write! cp i v)
- (placeholder-set! (vector-ref (cport-symtab cp) i) v))
- (define (symtab-lookup cp i)
- (vector-ref (cport-symtab cp) i))
- (require unstable/markparam)
- (define read-sym-mark (mark-parameter))
- (define (read-sym cp i)
- (define ph (symtab-lookup cp i))
- ; We are reading this already, so return the placeholder
- (if (memq i (mark-parameter-all read-sym-mark))
- ph
- ; Otherwise, try to read it and return the real thing
- (let ([vv (placeholder-get ph)])
- (when (not-ready? vv)
- (let ([save-pos (cport-pos cp)])
- (set-cport-pos! cp (vector-ref (cport-shared-offsets cp) (sub1 i)))
- (mark-parameterize
- ([read-sym-mark i])
- (let ([v (read-compact cp)])
- (placeholder-set! ph v)))
- (set-cport-pos! cp save-pos)))
- (placeholder-get ph))))
- ;; path -> bytes
- ;; implementes read.c:read_compiled
- (define (zo-parse [port (current-input-port)])
- ;; skip the "#~"
- (unless (equal? #"#~" (read-bytes 2 port))
- (error 'zo-parse "not a bytecode stream"))
- (define version (read-bytes (min 63 (read-byte port)) port))
- ;; Skip module hash code
- (read-bytes 20 port)
- (define symtabsize (read-simple-number port))
- (define all-short (read-byte port))
- (define cnt (* (if (not (zero? all-short)) 2 4)
- (sub1 symtabsize)))
- (define so (read-bytes cnt port))
- (define so* (list->vector (split-so all-short so)))
- (define shared-size (read-simple-number port))
- (define size* (read-simple-number port))
- (when (shared-size . >= . size*)
- (error 'zo-parse "Non-shared data segment start is not after shared data segment (according to offsets)"))
- (define rst-start (file-position port))
- (file-position port (+ rst-start size*))
- (unless (eof-object? (read-byte port))
- (error 'zo-parse "File too big"))
- (define nr (make-not-ready))
- (define symtab
- (build-vector symtabsize (λ (i) (make-placeholder nr))))
- (define cp
- (make-cport 0 shared-size port size* rst-start symtab so*
- (make-vector symtabsize #f) (make-hash) (make-hash)))
- (for ([i (in-range 1 symtabsize)])
- (read-sym cp i))
- #;(printf "Parsed table:\n")
- #;(for ([(i v) (in-dict (cport-symtab cp))])
- (printf "~a = ~a\n" i (placeholder-get v)))
- (set-cport-pos! cp shared-size)
- (make-reader-graph (read-marshalled 'compilation-top-type cp)))
- ;; ----------------------------------------
- #;
- (begin
- (define (compile/write sexp)
- (define s (open-output-bytes))
- (write (parameterize ([current-namespace (make-base-namespace)])
- (eval '(require (for-syntax scheme/base)))
- (compile sexp))
- s)
- (get-output-bytes s))
- (define (compile/parse sexp)
- (let* ([bs (compile/write sexp)]
- [p (open-input-bytes bs)])
- (zo-parse p)))
- #;(compile/parse #s(foo 10 13))
- (zo-parse (open-input-file "/home/mflatt/proj/plt/collects/scheme/private/compiled/more-scheme_ss.zo"))
- )