diff --git a/collects/mzlib/pretty.ss b/collects/mzlib/pretty.ss index 8488986855..ecafde5284 100644 --- a/collects/mzlib/pretty.ss +++ b/collects/mzlib/pretty.ss @@ -391,6 +391,13 @@ (add-spaces (- n 8) port)) (write-string " " port 0 n)))) + (define (prefab?! obj v) + (let ([d (prefab-struct-key obj)]) + (and d + (begin + (vector-set! v 0 d) + #t)))) + (define (generic-write obj display? width pport print-graph? print-struct? print-hash-table? print-vec-length? print-box? depth size-hook) @@ -713,7 +720,10 @@ #f #f (lambda () (out "#") - (wr-lst (vector->list (struct->vector obj)) #f (dsub1 depth) pair? car cdr "(" ")"))) + (let ([v (struct->vector obj)]) + (when (prefab?! obj v) + (out "s")) + (wr-lst (vector->list v) #f (dsub1 depth) pair? car cdr "(" ")")))) (parameterize ([print-struct #f]) ((if display? orig-display orig-write) obj pport)))] [(hash-table? obj) @@ -832,7 +842,10 @@ (write-custom pp* obj pport depth display? width)] [(struct? obj) ; print-struct is on if we got here (out "#") - (pp-list (vector->list (struct->vector obj)) extra pp-expr #f depth)] + (let ([v (struct->vector obj)]) + (when (prefab?! obj v) + (out "s")) + (pp-list (vector->list v) extra pp-expr #f depth))] [(hash-table? obj) (out (if (hash-table? obj 'equal) "#hash" diff --git a/collects/mzlib/private/match/render-test-list-impl.ss b/collects/mzlib/private/match/render-test-list-impl.ss index cd8be8ae36..7f763c316e 100644 --- a/collects/mzlib/private/match/render-test-list-impl.ss +++ b/collects/mzlib/private/match/render-test-list-impl.ss @@ -79,11 +79,6 @@ (format "invalid ~a pattern syntax" set!/get!))]))])) - ;; expand the regexp-matcher into an (and) with string? - (define (regexp-matcher ae stx pred cert) - (render-test-list #`(and (? string?) #,pred) ae cert stx)) - - ;;!(function or-gen ;; (form (or-gen exp orpatlist sf bv ks kf let-bound) ;; -> @@ -266,7 +261,6 @@ (map (lambda (x) (cons x #`#,(gensym (syntax-object->datum x)))) bound))) - (list (shape-test `(list? ,ae-datum) @@ -295,13 +289,19 @@ (test-list (list #,@(map (lambda (p) - (create-test-func + (let ([v (create-test-func p sf let-bound bind-map #f - cert)) + cert)]) + (printf "~s ~s ~s\n" + (syntax-object->datum p) + (syntax-object->datum v) + (continuation-mark-set->context + (current-continuation-marks))) + v)) pat-list)))) (if (match:test-no-order test-list #,ae diff --git a/collects/mzlib/private/match/test-no-order.ss b/collects/mzlib/private/match/test-no-order.ss index 99393ba3b6..2929d9e89b 100644 --- a/collects/mzlib/private/match/test-no-order.ss +++ b/collects/mzlib/private/match/test-no-order.ss @@ -35,4 +35,5 @@ rest last-test ddk-num))])) + (printf "~s\n" (list tests l last-test ddk-num)) (ormap (lambda (elem) (dep-first-test elem (remove elem l) tests)) l))) diff --git a/collects/scheme/private/define-struct.ss b/collects/scheme/private/define-struct.ss index 04434abc7d..a76542f7b9 100644 --- a/collects/scheme/private/define-struct.ss +++ b/collects/scheme/private/define-struct.ss @@ -135,8 +135,11 @@ [(eq? (caar config) s) (cons (cons s val) (cdr config))] [else (cons (car config) (extend-config (cdr config) s val))])) + (define insp-keys + "#:inspector, #:transparent, or #:prefab") + ;; Parse sequence of keyword-based struct specs - (define (parse-props p super-id) + (define (parse-props fm p super-id) (let loop ([p p] [config '((#:super . #f) (#:inspector . #f) @@ -145,7 +148,8 @@ (#:mutable . #f) (#:guard . #f) (#:omit-define-values . #f) - (#:omit-define-syntaxes . #f))]) + (#:omit-define-syntaxes . #f))] + [nongen? #f]) (cond [(null? p) config] [(eq? '#:super (syntax-e (car p))) @@ -161,40 +165,62 @@ stx (car p))) (loop (cddr p) - (extend-config config '#:super (cadr p)))] + (extend-config config '#:super (cadr p)) + nongen?)] [(memq (syntax-e (car p)) '(#:guard #:auto-value)) (let ([key (syntax-e (car p))]) (check-exprs 1 p) (when (lookup config key) (bad "multiple" (car p) "s")) + (when (and nongen? + (eq? key '#:guard)) + (bad "cannot provide" (car p) " for prefab structure type")) (loop (cddr p) - (extend-config config key (cadr p))))] + (extend-config config key (cadr p)) + nongen?))] [(eq? '#:property (syntax-e (car p))) (check-exprs 2 p) + (when nongen? + (bad "cannot use" (car p) " for prefab structure type")) (loop (cdddr p) (extend-config config '#:props (cons (cons (cadr p) (caddr p)) - (lookup config '#:props))))] + (lookup config '#:props))) + nongen?)] [(eq? '#:inspector (syntax-e (car p))) (check-exprs 1 p) (when (lookup config '#:inspector) - (bad "multiple" "#:inspector or #:transparent" "s" (car p))) + (bad "multiple" insp-keys "s" (car p))) (loop (cddr p) - (extend-config config '#:inspector (cadr p)))] + (extend-config config '#:inspector + #`(check-inspector '#,fm #,(cadr p))) + nongen?)] [(eq? '#:transparent (syntax-e (car p))) (when (lookup config '#:inspector) - (bad "multiple" "#:inspector or #:transparent" "s" (car p))) + (bad "multiple" insp-keys "s" (car p))) (loop (cdr p) - (extend-config config '#:inspector #'#f))] + (extend-config config '#:inspector #'#f) + nongen?)] + [(eq? '#:prefab (syntax-e (car p))) + (when (lookup config '#:inspector) + (bad "multiple" insp-keys "s" (car p))) + (when (pair? (lookup config '#:props)) + (bad "cannot use" (car p) " for a structure type with properties")) + (when (lookup config '#:guard) + (bad "cannot use" (car p) " for a structure type with a guard")) + (loop (cdr p) + (extend-config config '#:inspector #''prefab) + #t)] [(memq (syntax-e (car p)) '(#:mutable #:omit-define-values #:omit-define-syntaxes)) (let ([key (syntax-e (car p))]) (when (lookup config key) (bad "redundant" (car p) "")) (loop (cdr p) - (extend-config config key #t)))] + (extend-config config key #t) + nongen?))] [else (raise-syntax-error #f @@ -269,7 +295,7 @@ (loop (cdr fields) (cdr field-stxes) #f)]))]) (let-values ([(inspector super-expr props auto-val guard mutable? omit-define-values? omit-define-syntaxes?) - (let ([config (parse-props (syntax->list #'(prop ...)) super-id)]) + (let ([config (parse-props #'fm (syntax->list #'(prop ...)) super-id)]) (values (lookup config '#:inspector) (lookup config '#:super) (lookup config '#:props) @@ -340,8 +366,7 @@ #`(list #,@(map (lambda (p) #`(cons #,(car p) #,(cdr p))) props))) - #,(if inspector - #`(check-inspector 'fm #,inspector) + #,(or inspector #`(current-inspector)) #f '#,(let loop ([i 0] diff --git a/collects/scheme/private/qq-and-or.ss b/collects/scheme/private/qq-and-or.ss index 2d2b587341..f2734314e4 100644 --- a/collects/scheme/private/qq-and-or.ss +++ b/collects/scheme/private/qq-and-or.ss @@ -300,22 +300,35 @@ (((l) (vector->list (syntax-e x)))) (let-values (((l2) (qq l level))) - (let-values - () - (if (eq? l l2) - x - (list (quote-syntax list->vector) l2))))) + (if (eq? l l2) + x + (list (quote-syntax list->vector) l2)))) (if (if (syntax? x) (box? (syntax-e x)) #f) (let-values (((v) (unbox (syntax-e x)))) (let-values (((qv) (qq v level))) - (let-values - () - (if (eq? v qv) - x - (list (quote-syntax box) qv))))) - x))))))) + (if (eq? v qv) + x + (list (quote-syntax box) qv)))) + (if (if (syntax? x) + (if (struct? (syntax-e x)) + (prefab-struct-key (syntax-e x)) + #f) + #f) + ;; pre-fab struct + (let-values + (((l) (cdr (vector->list (struct->vector (syntax-e x)))))) + (let-values + (((l2) (qq l level))) + (if (eq? l l2) + x + (list (quote-syntax apply) + (quote-syntax make-prefab-struct) + (list (quote-syntax quote) + (prefab-struct-key (syntax-e x))) + l2)))) + x)))))))) (qq form 0)) form) in-form))))) diff --git a/collects/scheme/private/sc.ss b/collects/scheme/private/sc.ss index 1e8099d902..4be03d20a5 100644 --- a/collects/scheme/private/sc.ss +++ b/collects/scheme/private/sc.ss @@ -348,6 +348,24 @@ #f))) did-var? #f)))))] + [(and (syntax? p) + (prefab-struct-key (syntax-e p))) + => + (lambda (key) + (let ([l (vector->list (struct->vector (syntax-e p)))]) + ;; Match as a list: + (let-values ([(match-content did-var? ) (m&e (cdr l) p use-ellipses? last? #f)]) + (if just-vars? + (values match-content #f #f) + (values + (if interp-box + (vector 'prefab key match-content) + `(lambda (e) + (if (stx-prefab? ',key e) + ,(app match-content '(cdr (vector->list (struct->vector (syntax-e e))))) + #f))) + did-var? + #f)))))] [else (if just-vars? (values null #f #f) @@ -478,6 +496,7 @@ [(syntax? p) (loop (syntax-e p))] [(pair? p) (or (loop (car p)) (loop (cdr p)))] [(vector? p) (loop (vector->list p))] + [(struct? p) (loop (struct->vector p))] [else #f])) (pfx-loop (string-append "_" pfx)) pfx))]) @@ -616,6 +635,15 @@ (list->vector (stx->list ,(apply-to-r e)))) ;; variables were hashed (void)))] + [(and (syntax? p) + (struct? (syntax-e p)) + (prefab-struct-key (syntax-e p))) + (let ([e (expander (cdr (vector->list (struct->vector (syntax-e p)))) proto-r p use-ellipses? use-tail-pos hash!)]) + (if proto-r + `(lambda (r) + (apply make-prefab-struct ',(prefab-struct-key (syntax-e p)) (stx->list ,(apply-to-r e)))) + ;; variables were hashed + (void)))] [(identifier? p) (if (stx-memq p k) (if proto-r @@ -801,7 +829,8 @@ [(pair? stx) (let ([s1 (stx-size (car stx) up-to)]) (+ s1 (stx-size (cdr stx) (- up-to s1))))] [(vector? stx) (stx-size (vector->list stx) up-to)] - [(box? stx) (add1 (stx-size (unbox stx) (sub1 up-to)))] + [(struct? stx) (stx-size (struct->vector stx) up-to)] + [(box? stx) (add1 (stx-size (unbox stx) (sub1 up-to)))] [else 1])) ;; Generates a list-ref expression; if use-tail-pos @@ -857,6 +886,9 @@ (list p))] [(stx-vector? p #f) (sub (vector->list (syntax-e p)) use-ellipses?)] + [(and (syntax? p) + (prefab-struct-key (syntax-e p))) + (sub (cdr (vector->list (struct->vector (syntax-e p)))) use-ellipses?)] [else '()])))) ;; Checks whether the given nesting matches a nesting in the diff --git a/collects/scheme/private/stx.ss b/collects/scheme/private/stx.ss index 392195b924..2835562c66 100644 --- a/collects/scheme/private/stx.ss +++ b/collects/scheme/private/stx.ss @@ -122,6 +122,12 @@ (lambda (p pos) (vector-ref (syntax-e p) pos))) + (define-values (stx-prefab?) + (lambda (key v) + (if (syntax? v) + (equal? key (prefab-struct-key (syntax-e v))) + #f))) + ;; used in pattern-matching with an escape proc (define-values (stx-check/esc) (lambda (v esc) @@ -197,6 +203,7 @@ (#%provide identifier? stx-null? stx-null/#f stx-pair? stx-list? stx-car stx-cdr stx->list stx-vector? stx-vector-ref + stx-prefab? stx-check/esc cons/#f append/#f stx-rotate stx-rotate* split-stx-list diff --git a/collects/scheme/private/stxcase.ss b/collects/scheme/private/stxcase.ss index d176852916..f5ff7d830c 100644 --- a/collects/scheme/private/stxcase.ss +++ b/collects/scheme/private/stxcase.ss @@ -236,6 +236,9 @@ m (append m body)) body))))))))])))] + [(eq? i 'prefab) + (and (stx-prefab? (vector-ref i 1) e) + (loop (vector-ref i 2) (cdr (vector->list (struct->vector (syntax-e e)))) cap))] [else (error "yikes!" pat)]))])))) (-define-syntax syntax-case** diff --git a/collects/scribble/scheme.ss b/collects/scribble/scheme.ss index 1be9817076..fc16dfe44b 100644 --- a/collects/scribble/scheme.ss +++ b/collects/scribble/scheme.ss @@ -393,10 +393,14 @@ ((loop init-line! quote-depth) converted))] [(or (pair? (syntax-e c)) (null? (syntax-e c)) - (vector? (syntax-e c))) + (vector? (syntax-e c)) + (and (struct? (syntax-e c)) + (prefab-struct-key (syntax-e c)))) (let* ([sh (or (syntax-property c 'paren-shape) #\()] - [quote-depth (if (vector? (syntax-e c)) + [quote-depth (if (and (zero? quote-depth) + (or (vector? (syntax-e c)) + (struct? (syntax-e c)))) +inf.0 quote-depth)] [p-color (if (positive? quote-depth) @@ -413,6 +417,9 @@ (set! src-col (+ src-col (- (syntax-column (vector-ref vec 0)) (syntax-column c) 1)))))) + (when (struct? (syntax-e c)) + (out "#s" p-color) + (set! src-col (+ src-col 2))) (out (case sh [(#\[ #\?) "["] [(#\{) "{"] @@ -420,9 +427,31 @@ p-color) (set! src-col (+ src-col 1)) (hash-table-put! next-col-map src-col dest-col) - (let lloop ([l (if (vector? (syntax-e c)) - (vector->short-list (syntax-e c) syntax-e) - c)]) + (let lloop ([l (cond + [(vector? (syntax-e c)) + (vector->short-list (syntax-e c) syntax-e)] + [(struct? (syntax-e c)) + (let ([l (vector->list (struct->vector (syntax-e c)))]) + ;; Need to build key datum, syntax-ize it internally, and + ;; set the overall width to fit right: + (cons (let ([key (syntax-ize (prefab-struct-key (syntax-e c)) + (+ 3 (or (syntax-column c) 0)) + (or (syntax-line c) 1))] + [end (if (pair? (cdr l)) + (and (equal? (syntax-line c) (syntax-line (cadr l))) + (syntax-column (cadr l))) + (and (syntax-column c) + (+ (syntax-column c) (syntax-span c))))]) + (if end + (datum->syntax #f + (syntax-e key) + (vector #f (syntax-line key) + (syntax-column key) + (syntax-position key) + (- end 1 (syntax-column key)))) + end)) + (cdr l)))] + [else c])]) (cond [(and (syntax? l) (pair? (syntax-e l)) @@ -516,6 +545,7 @@ (eq? 'code:blank s) (pair? s) (vector? s) + (struct? s) (box? s) (null? s) (hash-table? s) @@ -574,6 +604,11 @@ [(vector? v) `(vector ,@(map stx->loc-s-expr (vector->list v)))] + [(and (struct? v) (prefab-struct-key v)) + `(make-prefab-struct (quote ,(prefab-struct-key v)) + ,@(map + stx->loc-s-expr + (cdr (vector->list (struct->vector v)))))] [(box? v) `(box ,(stx->loc-s-expr (unbox v)))] [(null? v) 'null] [else `(quote ,v)])) @@ -623,8 +658,8 @@ (define-struct graph-reference (bx)) (define-struct graph-defn (r bx)) - (define (syntax-ize v col) - (do-syntax-ize v col (make-hash-table) #f)) + (define (syntax-ize v col [line 1]) + (do-syntax-ize v col line (make-hash-table) #f)) (define (graph-count ht graph?) (and graph? @@ -632,16 +667,16 @@ (hash-table-put! ht '#%graph-count (add1 n)) n))) - (define (do-syntax-ize v col ht graph?) + (define (do-syntax-ize v col line ht graph?) (cond [((syntax-ize-hook) v col) => (lambda (r) r)] [(shaped-parens? v) - (syntax-property (do-syntax-ize (shaped-parens-val v) col ht #f) + (syntax-property (do-syntax-ize (shaped-parens-val v) col line ht #f) 'paren-shape (shaped-parens-shape v))] [(just-context? v) - (let ([s (do-syntax-ize (just-context-val v) col ht #f)]) + (let ([s (do-syntax-ize (just-context-val v) col line ht #f)]) (datum->syntax (just-context-ctx v) (syntax-e s) s @@ -653,7 +688,7 @@ (set-box! m #t)) (datum->syntax #f (make-graph-reference m) - (list #f 1 col (+ 1 col) 1)))] + (vector #f line col (+ 1 col) 1)))] [(and (list? v) (pair? v) (memq (let ([s (car v)]) @@ -661,42 +696,52 @@ (just-context-val s) s)) '(quote unquote unquote-splicing))) - (let ([c (do-syntax-ize (cadr v) (+ col 1) ht #f)]) + (let ([c (do-syntax-ize (cadr v) (+ col 1) line ht #f)]) (datum->syntax #f - (list (do-syntax-ize (car v) col ht #f) + (list (do-syntax-ize (car v) col line ht #f) c) - (list #f 1 col (+ 1 col) - (+ 1 (syntax-span c)))))] + (vector #f line col (+ 1 col) + (+ 1 (syntax-span c)))))] [(or (list? v) - (vector? v)) + (vector? v) + (and (struct? v) + (prefab-struct-key v))) (let ([graph-box (box (graph-count ht graph?))]) (hash-table-put! ht v graph-box) (let ([r (let* ([vec-sz (+ (if graph? (+ 2 (string-length (format "~a" (unbox graph-box)))) 0) - (if (vector? v) - (+ 1 #;(string-length (format "~a" (vector-length v)))) - 0))]) + (cond + [(vector? v) + (+ 1 #;(string-length (format "~a" (vector-length v))))] + [(struct? v) 2] + [else 0]))]) (let ([l (let loop ([col (+ col 1 vec-sz)] - [v (if (vector? v) - (vector->short-list v values) - v)]) + [v (cond + [(vector? v) + (vector->short-list v values)] + [(struct? v) + (cons (prefab-struct-key v) + (cdr (vector->list (struct->vector v))))] + [else v])]) (if (null? v) null - (let ([i (do-syntax-ize (car v) col ht #f)]) + (let ([i (do-syntax-ize (car v) col line ht #f)]) (cons i (loop (+ col 1 (syntax-span i)) (cdr v))))))]) (datum->syntax #f - (if (vector? v) - (short-list->vector v l) - l) - (list #f 1 col (+ 1 col) - (+ 2 - vec-sz - (if (zero? (length l)) - 0 - (sub1 (length l))) - (apply + (map syntax-span l)))))))]) + (cond + [(vector? v) (short-list->vector v l)] + [(struct? v) + (apply make-prefab-struct (prefab-struct-key v) (cdr l))] + [else l]) + (vector #f line col (+ 1 col) + (+ 2 + vec-sz + (if (zero? (length l)) + 0 + (sub1 (length l))) + (apply + (map syntax-span l)))))))]) (unless graph? (hash-table-put! ht v #f)) (cond @@ -705,7 +750,7 @@ r)] [(unbox graph-box) ;; Go again, this time knowing that there will be a graph: - (do-syntax-ize v col ht #t)] + (do-syntax-ize v col line ht #t)] [else r])))] [(pair? v) (let ([graph-box (box (graph-count ht graph?))]) @@ -713,33 +758,33 @@ (let* ([inc (if graph? (+ 2 (string-length (format "~a" (unbox graph-box)))) 0)] - [a (do-syntax-ize (car v) (+ col 1 inc) ht #f)] + [a (do-syntax-ize (car v) (+ col 1 inc) line ht #f)] [sep (if (and (pair? (cdr v)) ;; FIXME: what if it turns out to be a graph reference? (not (hash-table-get ht (cdr v) #f))) 0 3)] - [b (do-syntax-ize (cdr v) (+ col 1 inc (syntax-span a) sep) ht #f)]) + [b (do-syntax-ize (cdr v) (+ col 1 inc (syntax-span a) sep) line ht #f)]) (let ([r (datum->syntax #f (cons a b) - (list #f 1 (+ col inc) (+ 1 col inc) - (+ 2 sep (syntax-span a) (syntax-span b))))]) + (vector #f line (+ col inc) (+ 1 col inc) + (+ 2 sep (syntax-span a) (syntax-span b))))]) (unless graph? (hash-table-put! ht v #f)) (cond [graph? (datum->syntax #f (make-graph-defn r graph-box) - (list #f 1 col (+ 1 col) - (+ inc (syntax-span r))))] + (vector #f line col (+ 1 col) + (+ inc (syntax-span r))))] [(unbox graph-box) ;; Go again... - (do-syntax-ize v col ht #t)] + (do-syntax-ize v col line ht #t)] [else r]))))] [(box? v) - (let ([a (do-syntax-ize (unbox v) (+ col 2) ht #f)]) + (let ([a (do-syntax-ize (unbox v) (+ col 2) line ht #f)]) (datum->syntax #f (box a) - (list #f 1 col (+ 1 col) - (+ 2 (syntax-span a)))))] + (vector #f line col (+ 1 col) + (+ 2 (syntax-span a)))))] [else - (datum->syntax #f v (list #f 1 col (+ 1 col) 1))]))) + (datum->syntax #f v (vector #f line col (+ 1 col) 1))]))) diff --git a/collects/scribblings/guide/define-struct.scrbl b/collects/scribblings/guide/define-struct.scrbl index 8f9c56a7cf..ccfe77be46 100644 --- a/collects/scribblings/guide/define-struct.scrbl +++ b/collects/scribblings/guide/define-struct.scrbl @@ -132,11 +132,11 @@ With a structure type definition like an instance of the structure type prints in a way that does not show any information about the fields values. That is, structure types by -default are @defterm{opaque}. If the accessors and mutators of a +default are @deftech{opaque}. If the accessors and mutators of a structure type are kept private to a module, then no other module can rely on the representation of the type's instances. -To make a structure type @defterm{transparent}, use the +To make a structure type @deftech{transparent}, use the @scheme[#:transparent] keyword after the field-name sequence: @def+int[ @@ -158,6 +158,154 @@ can use an opaque structure to encapsulate data, and clients of the library cannot manipulate the data in the structure except as allowed by the library. +@; ------------------------------------------------------------ +@section{Structure Type Generativity} + +Each time that a @scheme[define-struct] form is evaluated, it +generates a structure type that is distinct from all existing +structure types, even if some other structure type has the same name +and fields. + +This generativity is useful for enforcing abstractions and +implementing programs such as interpreters, but beware of placing a +@scheme[define-struct] form in positions that are evaluated multiple +times. + +@defexamples[ +(define (add-bigger-fish lst) + (define-struct fish (size) #:transparent) (code:comment #,(t "new every time")) + (cond + [(null? lst) (list (make-fish 1))] + [else (cons (make-fish (* 2 (fish-size (car lst)))) + lst)])) + +(add-bigger-fish null) +(add-bigger-fish (add-bigger-fish null)) +] +@defs+int[ +[(define-struct fish (size) #:transparent) + (define (add-bigger-fish lst) + (cond + [(null? lst) (list (make-fish 1))] + [else (cons (make-fish (* 2 (fish-size (car lst)))) + lst)]))] +(add-bigger-fish (add-bigger-fish null)) +] + +@; ------------------------------------------------------------ +@section[#:tag "prefab-struct"]{Prefab Stucture Types} + +Although a @tech{transparent} structure type prints in a way that +shows its content, the printed form of the structure cannot be used in +an expression to get the structure back, unlike the printed form of a +number, string, symbol, or list. + +A @deftech{prefab} (``previously fabricated'') structure type is a +built-in type that is known to the Scheme printer and expression +reader. Infinitely many such types exist, and they are indexed by +name, field count, supertype, and other such details. The printed form +of a prefab structure is similar to a vector, but it starts +@litchar{#s} instead of just @litchar{#}, and the first element in the +printed form is the prefab structure type's name. + +The following examples show instances of the @schemeidfont{sprout} +prefab structure type that has one field. The first instance has a +field value @scheme['bean], and the second has field value +@scheme['alfalfa]: + +@interaction[ +'#s(sprout bean) +'#s(sprout alfalfa) +] + +Like numbers and strings, prefab structures are ``self-quoting,'' so +the quotes above are optional: + +@interaction[ +#s(sprout bean) +] + +When you use the @scheme[#:prefab] keyword with +@scheme[define-struct], instead of generating a new structure type, +you obtain bindings that work with the existing prefab structure type: + +@interaction[ +#:eval posn-eval +(define lunch '#s(sprout bean)) +(define-struct sprout (kind) #:prefab) +(sprout? lunch) +(sprout-kind lunch) +(make-sprout 'garlic) +] + +The field name @schemeidfont{kind} above does not matter for finding +the prefab structure type; only the name @schemeidfont{sprout} and the +number of fields matters. At the same time, the prefab structure type +@schemeidfont{sprout} with three fields is a different structure type +than the one with a single field: + +@interaction[ +#:eval posn-eval +(sprout? #s(sprout bean #f 17)) +(code:line (define-struct sprout (kind yummy? count) #:prefab) (code:comment #, @t{redefine})) +(sprout? #s(sprout bean #f 17)) +(sprout? lunch) +] + +A prefab structure type can have another prefab structure type as its +supertype, it can have mutable fields, and it can have auto +fields. Variations in any of these dimensions correspond to different +prefab structure types, and the printed form of the structure type's +name encodes all of the relevant details. + +@interaction[ +(define-struct building (rooms [location #:mutable]) #:prefab) +(define-struct (house building) ([occupied #:auto]) #:prefab + #:auto-value 'no) +(make-house 5 'factory) +] + +Every @tech{prefab} structure type is @tech{transparent}---but even +less abstract than a @tech{transparent} type, because instances can be +created without any access to a particular structure-type declaration +or existing examples. Overall, the different options for structure +types cover a spectrum from more abstract to more convenient: + +@itemize{ + + @item{@tech{Opaque} (the default) : instances cannot be inspected or + forged without access to the structure-type declaration. As + discussed in the next section, @tech{constructor guards} and + @tech{properties} can be attached to the structure type to + further protect or to specialize the behavior of its + instances.} + + @item{@tech{Transparent} : anyone can inspect or create an instance + without access to the structure-type declaration, which means + that the value printer can show the content of an instance. All + instance creation passes through a @tech{constructor guard}, + however, so that the content of an instance can be controlled, + and the behavior of instances can be specialized through + @tech{properties}. Since the structure type is generated by its + definition, instances cannot be manufactured simply through the + name of the structure type, and therefore cannot be generated + automatically by the expression reader. } + + @item{@tech{Prefab} : anyone can inspect or create an instance at any + time, without prior access to a structure-type declaration or + an example instance. Consequently, the expression reader can + manufacture instances directly. The instance cannot have a + @tech{constructor guard} or @tech{properties}.} + +} + +Since the expression reader can generate @tech{prefab} instances, they +are useful when simple @tech{serialization} is needed and weak +abstraction is acceptable. @tech{Opaque} and @tech{transparent} +structures also can be serialized, however, if they are defined with +@scheme[define-serializable-struct] as described in +@secref["serialization"]. + @; ------------------------------------------------------------ @section[#:tag "struct-options"]{More Structure Type Options} @@ -199,18 +347,23 @@ A @scheme[_struct-option] always starts with a keyword: @specspecsubform[(code:line #:transparent)]{ Controls reflective access to structure instances, as discussed - in the previous section (@secref["trans-struct"]).} + in a previous section, @secref["trans-struct"].} @specspecsubform[(code:line #:inspector inspector-expr)]{ Generalizes @scheme[#:transparent] to support more controlled access to reflective operations.} + @specspecsubform[(code:line #:prefab)]{ + Accesses a built-in structure type, as discussed + in a previous section, @secref["prefab-struct"].} + @specspecsubform[(code:line #:auto-value auto-expr)]{ Specifies a value to be used for all automatic fields in the structure type, where an automatic field is indicated by the @scheme[#:auto] field option. The constructor procedure does not - accept arguments for automatic fields. + accept arguments for automatic fields, and they are implicitly + mutable. @defexamples[ (define-struct posn (x y [z #:auto]) @@ -223,12 +376,12 @@ A @scheme[_struct-option] always starts with a keyword: @;-- Explain when to use guards instead of contracts, and vice-versa @specspecsubform[(code:line #:guard guard-expr)]{ - Specifies a guard procedure to be called whenever an instance of - the structure type is created. The guard takes as many arguments - as non-automatic fields in the structure type, and it should return - the same number of values. The guard can raise an exception if one - of the given arguments is unacceptable, or it can convert an - argument. + Specifies a @deftech{constructor guard} procedure to be called + whenever an instance of the structure type is created. The guard + takes as many arguments as non-automatic fields in the structure + type, and it should return the same number of values. The guard can + raise an exception if one of the given arguments is unacceptable, or + it can convert an argument. @defexamples[ #:eval posn-eval @@ -262,10 +415,11 @@ A @scheme[_struct-option] always starts with a keyword: (make-person #f 10)]} @specspecsubform[(code:line #:property prop-expr val-expr)]{ - Associates a property and value with the structure type. For - example, the @scheme[prop:procedure] property allows a structure - instance to be used as a function; the property value determines - how a call is implemented when using the structure as a function. + Associates a @deftech{property} and value with the structure type. + For example, the @scheme[prop:procedure] property allows a + structure instance to be used as a function; the property value + determines how a call is implemented when using the structure as a + function. @defexamples[ (define-struct greeter (name) @@ -302,39 +456,6 @@ A @scheme[_struct-option] always starts with a keyword: (let ([r ((make-raven-constructor struct:thing) "apple")]) (list r (r)))]} - -@; ------------------------------------------------------------ -@section{Structure Type Generativity} - -Each time that a @scheme[define-struct] form is evaluated, it -generates a structure type that is distinct from all existing -structure types, even if some other structure type has the same name -and fields. - -This generativity is useful for enforcing abstractions and -implementing programs such as interpreters, but beware of placing a -@scheme[define-struct] form in positions that are evaluated multiple -times. - -@defexamples[ -(define (add-bigger-fish lst) - (define-struct fish (size) #:transparent) (code:comment #,(t "new every time")) - (cond - [(null? lst) (list (make-fish 1))] - [else (cons (make-fish (* 2 (fish-size (car lst)))) - lst)])) - -(add-bigger-fish null) -(add-bigger-fish (add-bigger-fish null)) -] -@defs+int[ -[(define-struct fish (size) #:transparent) - (define (add-bigger-fish lst) - (cond - [(null? lst) (list (make-fish 1))] - [else (cons (make-fish (* 2 (fish-size (car lst)))) - lst)]))] -(add-bigger-fish (add-bigger-fish null)) -] +@; ---------------------------------------- @refdetails["structures"]{structure types} diff --git a/collects/scribblings/guide/io.scrbl b/collects/scribblings/guide/io.scrbl index e36e659357..50155f011f 100644 --- a/collects/scribblings/guide/io.scrbl +++ b/collects/scribblings/guide/io.scrbl @@ -273,15 +273,26 @@ that many forms of data can be read back in using @scheme[read]. ] @; ---------------------------------------------------------------------- -@section{Datatypes and Serialization} +@section[#:tag "serialization"]{Datatypes and Serialization} -New datatypes created by @scheme[define-struct] by default +@tech{Prefab} structure types (see @secref["prefab-struct"]) +automatically support @deftech{serialization}: they can be written to +an output stream, and a copy can be read back in from an input stream: + +@interaction[ +(define-values (in out) (make-pipe)) +(write #s(sprout bean) out) +(read in) +] + +Other structure types created by @scheme[define-struct], which offer +more abstraction than @tech{prefab} structure types, normally @scheme[write] either using @schemeresultfont{#<....>} notation (for opaque structure types) or using @schemeresultfont{#(....)} vector notation (for transparent structure types). In neither can can the -result be read back in as an instance of the structure type. +result be read back in as an instance of the structure type: -@examples[ +@interaction[ (define-struct posn (x y)) (write (make-posn 1 2)) (define-values (in out) (make-pipe)) diff --git a/collects/scribblings/reference/define-struct.scrbl b/collects/scribblings/reference/define-struct.scrbl index 91e2660e34..02f5121a1a 100644 --- a/collects/scribblings/reference/define-struct.scrbl +++ b/collects/scribblings/reference/define-struct.scrbl @@ -18,26 +18,28 @@ [field-id field-option ...]] [struct-option #:mutable (code:line #:super super-expr) - (code:line #:transparent) (code:line #:inspector inspector-expr) (code:line #:auto-value auto-expr) (code:line #:guard guard-expr) (code:line #:property prop-expr val-exr) + (code:line #:transparent) + (code:line #:prefab) #:omit-define-syntaxes #:omit-define-values] [field-option #:mutable #:auto])]{ -Creates a new @techlink{structure type}, and binds transformers and -variables related to the new @tech{structure type}. A -@scheme[define-struct] form with @math{n} @scheme[field]s defines -up to @math{4+2n} names: +Creates a new @techlink{structure type} (or uses a pre-existing +structure type if @scheme[#:prefab] is specified), and binds +transformers and variables related to the @tech{structure type}. + +A @scheme[define-struct] form with @math{n} @scheme[field]s defines up +to @math{4+2n} names: @itemize{ @item{@schemeidfont{struct:}@scheme[id], a @deftech{structure type - descriptor} value that represents the new @tech{structure - type}.} + descriptor} value that represents the @tech{structure type}.} @item{@schemeidfont{make-}@scheme[id], a @deftech{constructor} procedure that takes @math{m} arguments and returns a new @@ -76,7 +78,7 @@ up to @math{4+2n} names: If @scheme[super-id] is provided, it must have a transformer binding of the same sort bound to @scheme[id] (see @secref["structinfo"]), -and it specifies a supertype for the new structure type. Alternately, +and it specifies a supertype for the structure type. Alternately, the @scheme[#:super] option can be used to specify an expression that must produce a @tech{structure type descriptor}. See @secref["structures"] for more information on structure subtypes @@ -93,13 +95,21 @@ a syntax error is reported. The @scheme[#:inspector], @scheme[#:auto-value], and @scheme[#:guard] options specify an inspector, value for automatic fields, and guard -procedure, respectively. See @scheme[make-struct-type] (in -@secref["creatingmorestructs"]) for more information on these -properties of a structure type. The @scheme[#:transparent] option is a -shorthand for @scheme[#:inspector #f]. The @scheme[#:property] -option, which is the only one that can be specified multiple times, -attaches a property value to the structure type; see -@secref["structprops"] for more information on properties. +procedure, respectively. See @scheme[make-struct-type] for more +information on these attributes of a structure type. The +@scheme[#:property] option, which is the only one that can be supplied +multiple times, attaches a property value to the structure type; see +@secref["structprops"] for more information on properties. The +@scheme[#:transparent] option is a shorthand for @scheme[#:inspector +#f]. + +The @scheme[#:prefab] option obtains a @techlink{prefab} (pre-defined, +globally shared) structure type, as opposed to creating a new +structure type. Such a structure type is inherently transparent and +cannot have a guard or properties, so using @scheme[#:prefab] with +@scheme[#:transparent], @scheme[#:inspector], @scheme[#:guard], or +@scheme[#:property] is a syntax error. If a supertype is specified, it +must also be a @tech{prefab} structure type. If the @scheme[#:omit-define-syntaxes] option is supplied, then @scheme[id] is not bound as a transformer. If the diff --git a/collects/scribblings/reference/pairs.scrbl b/collects/scribblings/reference/pairs.scrbl index cb91f20c83..c2ab5370ca 100644 --- a/collects/scribblings/reference/pairs.scrbl +++ b/collects/scribblings/reference/pairs.scrbl @@ -521,6 +521,8 @@ placeholders: @item{hash tables, both mutable and immutable} + @item{instances of a @techlink{prefab} structure type} + @item{placeholders created by @scheme[make-placeholder] and @scheme[make-hash-table-placeholder]} diff --git a/collects/scribblings/reference/printer.scrbl b/collects/scribblings/reference/printer.scrbl index f23890c05c..3f8988601c 100644 --- a/collects/scribblings/reference/printer.scrbl +++ b/collects/scribblings/reference/printer.scrbl @@ -173,6 +173,38 @@ that when the @scheme[print-vector-length] parameter is @scheme[#t], a decimal integer is printed after the @litchar{#}, and a repeated last element is printed only once.. + +@section[#:tag "print-structure"]{Printing Structures} + +When the @scheme[print-struct] parameter is set to @scheme[#t], then +the way that structures print depends on details of the structure type +for which the structure is an instance: + +@itemize{ + + @item{If the structure type is a @techlink{prefab} structure type, + then it prints using @litchar{#s(} followed by the @tech{prefab} + structure type key, then the printed form each field in the + structure, and then @litchar{)}.} + + @item{If the structure has a @scheme[prop:custom-write] property + value, then the associated procedure is used to print the + structure.} + + @item{If the structure type is transparent, or if any ancestor is + transparent, then the structure prints as the vector produced + by @scheme[struct->vector].} + + @item{For any other structure type, the structure prints as an + unreadable value; see @secref["print-unreadable"] for more + information.} +} + +If the @scheme[print-struct] parameter is set to @scheme[#f], then all +structures without a @scheme[prop:custom-write] property print as +unreadable values. + + @section[#:tag "print-hashtable"]{Printing Hash Tables} When the @scheme[print-hash-table] parameter is set to @scheme[#t], a @@ -227,3 +259,10 @@ starting with @litchar{#px} (for @scheme[pregexp]-based regexps) or @litchar{#rx} (for @scheme[regexp]-based regexps) followed by the @scheme[write] form of the regexp's source string or byte string. + +@section[#:tag "print-unreadable"]{Printing Unreadable Values} + +For any value with no other printing specification, the output form is +@litchar{#<}@nonterm{something}@litchar{>}, where @nonterm{something} +is specific to the type of the value and sometimes to the value +itself. diff --git a/collects/scribblings/reference/reader.scrbl b/collects/scribblings/reference/reader.scrbl index d13098a44c..c456c76eb2 100644 --- a/collects/scribblings/reference/reader.scrbl +++ b/collects/scribblings/reference/reader.scrbl @@ -103,6 +103,10 @@ on the next character or characters in the input stream as follows: @dispatch[@litchar{#[}]{starts a vector; see @secref["parse-vector"]} @dispatch[@litchar["#{"]]{starts a vector; see @secref["parse-vector"]} + @dispatch[@litchar["#s("]]{starts a structure literal; see @secref["parse-structure"]} + @dispatch[@litchar["#s["]]{starts a structure literal; see @secref["parse-structure"]} + @dispatch[@litchar["#s{"]]{starts a structure literal; see @secref["parse-structure"]} + @dispatch[@litchar["#\\"]]{starts a character; see @secref["parse-character"]} @dispatch[@litchar{#"}]{starts a byte string; see @secref["parse-string"]} @@ -538,7 +542,9 @@ file. When the reader encounters a @litchar{#(}, @litchar{#[}, or @litchar["#{"], it starts parsing a vector; see @secref["vectors"] for -information on vectors. +information on vectors. The @litchar{#[} and @litchar["#{"] forms can +be disabled through the @scheme[read-square-bracket-as-paren] and +@scheme[read-curly-brace-as-paren] @tech{parameters}. The elements of the vector are recursively read until a matching @litchar{)}, @litchar{]}, or @litchar["}"] is found, just as for @@ -564,6 +570,37 @@ immutable. "#3()" ] + +@section[#:tag "parse-structure"]{Reading Structures} + +When the reader encounters a @litchar{#s(}, @litchar{#s[}, or +@litchar["#s{"], it starts parsing an instance of a @tech{prefab} +@tech{structure type}; see @secref["structures"] for information on +@tech{structure types}. The @litchar{#s[} and @litchar["#s{"] forms +can be disabled through the @scheme[read-square-bracket-as-paren] and +@scheme[read-curly-brace-as-paren] @tech{parameters}. + +The elements of the structure are recursively read until a matching +@litchar{)}, @litchar{]}, or @litchar["}"] is found, just as for lists +(see @secref["parse-pair"]). A delimited @litchar{.} is not allowed +among the elements. + +The first element is used as the structure descriptor, and it must +have the form (when quoted) of a possible argument to +@scheme[make-prefab-struct]; in the simplest case, it can be a +symbol. The remaining elements correspond to field values within the +structure. + +In @scheme[read-syntax] mode, the structure type must not have any +mutable fields. The structure's elements are read in +@scheme[read-syntax] mode, so that the wrapped structure's elements +are also wraped as syntax objects. + +If the first structure element is not a valid @tech{prefab} structure +type key, or if the number of provided fields is inconsistent with the +indicated @tech{prefab} structure type, the @exnraise[exn:fail:read]. + + @section[#:tag "parse-hashtable"]{Reading Hash Tables} A @as-index{@litchar{#hash}} starts an immutable hash-table constant diff --git a/collects/scribblings/reference/struct.scrbl b/collects/scribblings/reference/struct.scrbl index 1ba88a3231..f03156860f 100644 --- a/collects/scribblings/reference/struct.scrbl +++ b/collects/scribblings/reference/struct.scrbl @@ -49,6 +49,21 @@ accessed with subtype-specific selectors. Subtype-specific @tech{accessors} and @tech{mutators} for the first @math{m} fields do not exist. +The @scheme[define-struct] form and @scheme[make-struct-type] +procedure typically create a new structure type, but they can also +access @deftech{prefab} (i.e., previously fabricated) structure types +that are globally shared, and whose instances can be parsed and +written by the default reader (see @secref["reader"]) and printer (see +@secref["printing"]). Prefab structure types can inherit only from +other prefab structure types, and they cannot have guards (see +@secref["creatingmorestructs"]) or properties (see +@secref["structprops"]). Exactly one prefab structure type exists for +each combination of name, supertype, field count, automatic field +count, automatic field value (when there is at least one automatic +field), and field mutability. + +@refalso["serialization"]{reading and writing structures} + @index['("structures" "equality")]{Two} structure values are @scheme[eqv?] if and only if they are @scheme[eq?]. Two structure values are @scheme[equal?] if they are @scheme[eq?], or if they are @@ -71,7 +86,7 @@ structures depends on the current inspector.) [props (listof (cons/c struct-type-property? any/c)) null] - [inspector (or/c inspector? false/c) + [inspector (or/c inspector? false/c (one-of/c 'prefab)) (current-inspector)] [proc-spec (or/c procedure? nonnegative-exact-integer? @@ -86,24 +101,30 @@ structures depends on the current inspector.) struct-accessor-procedure? struct-mutator-procedure?)]{ -Creates a new structure type. The @scheme[name] argument is used as -the type name. If @scheme[super-type] is not @scheme[#f], the new type -is a subtype of the corresponding structure type. +Creates a new structure type, unless @scheme[inspector] is +@scheme['prefab], in which case @scheme[make-struct-type] accesses a +@techlink{prefab} structre type. The @scheme[name] argument is used +as the type name. If @scheme[super-type] is not @scheme[#f], the +resulting type is a subtype of the corresponding structure type. -The new structure type has @math{@scheme[init-field-cnt]+@scheme[auto-field-cnt]} -fields (in addition to any fields from @scheme[super-type]), but only +The resulting structure type has +@math{@scheme[init-field-cnt]+@scheme[auto-field-cnt]} fields (in +addition to any fields from @scheme[super-type]), but only @scheme[init-field-cnt] constructor arguments (in addition to any -constructor arguments from @scheme[super-type]). The remaining -fields are initialized with @scheme[auto-v]. +constructor arguments from @scheme[super-type]). The remaining fields +are initialized with @scheme[auto-v]. The @scheme[props] argument is a list of pairs, where the @scheme[car] of each pair is a structure type property descriptor, and the @scheme[cdr] is an arbitrary value. See @secref["structprops"] for -more information about properties. +more information about properties. When @scheme[inspector] is +@scheme['prefab], then @scheme[props] must be @scheme[null]. -The @scheme[inspector] argument controls access to reflective +The @scheme[inspector] argument normally controls access to reflective information about the structure type and its instances; see -@secref["inspectors"] for more information. +@secref["inspectors"] for more information. If @scheme[inspector] is +@scheme['prefab], then the resulting @tech{prefab} structure type and +its instances are always transparent. If @scheme[proc-spec] is an integer or procedure, instances of the structure type act as procedures. See @scheme[prop:procedure] for @@ -121,21 +142,22 @@ positions. Each element in the list must be unique, otherwise The @scheme[guard] argument is either a procedure of @math{n} arguments or @scheme[#f], where @math{n} is the number of arguments -for the new structure type's constructor (i.e., @scheme[init-field-cnt] -plus constructor arguments implied by @scheme[super-type], if any). If -@scheme[guard] is a procedure, then the procedure is called -whenever an instance of the type is constructed, or whenever an -instance of a subtype is created. The arguments to -@scheme[guard] are the values provided for the structure's first -@math{n} fields, followed by the name of the instantiated structure -type (which is @scheme[name], unless a subtype is instantiated). The -@scheme[guard] result must be @math{n} values, which become the -actual values for the structure's fields. The @scheme[guard] can -raise an exception to prevent creation of a structure with the given -field values. If a structure subtype has its own guard, the subtype -guard is applied first, and the first @math{n} values produced by the -subtype's guard procedure become the first @math{n} arguments to -@scheme[guard]. +for the new structure type's constructor (i.e., +@scheme[init-field-cnt] plus constructor arguments implied by +@scheme[super-type], if any). If @scheme[guard] is a procedure, then +the procedure is called whenever an instance of the type is +constructed, or whenever an instance of a subtype is created. The +arguments to @scheme[guard] are the values provided for the +structure's first @math{n} fields, followed by the name of the +instantiated structure type (which is @scheme[name], unless a subtype +is instantiated). The @scheme[guard] result must be @math{n} values, +which become the actual values for the structure's fields. The +@scheme[guard] can raise an exception to prevent creation of a +structure with the given field values. If a structure subtype has its +own guard, the subtype guard is applied first, and the first @math{n} +values produced by the subtype's guard procedure become the first +@math{n} arguments to @scheme[guard]. When @scheme[inspector] is +@scheme['prefab], then @scheme[guard] must be @scheme[#f]. The result of @scheme[make-struct-type] is five values: @@ -196,6 +218,16 @@ The result of @scheme[make-struct-type] is five values: (a-ref a-c 1) ]} +@interaction[ +#:eval struct-eval +(define p1 #s(p a b c)) +(define-values (struct:p make-p p? p-ref p-set!) + (make-struct-type 'p #f 3 0 #f null 'prefab #f '(0 1 2))) +(p? p1) +(p-ref p1 0) +(make-p 'x 'y 'z) +] + @defproc[(make-struct-field-accessor [accessor-proc struct-accessot-procedure?] [field-pos exact-nonnegative-integer?] [field-name symbol?]) @@ -350,6 +382,74 @@ is inaccessible.)} @scheme[define-struct], @scheme[make-struct-type], or @scheme[make-struct-field-mutator], @scheme[#f] otherwise.} +@defproc[(prefab-struct-key [v any/c]) (or/c false/c symbol? list?)]{ + +Returns @scheme[#f] if @scheme[v] is not an instance of a +@tech{prefab} structure type. Otherwise, the result is the shorted key +that could be with @scheme[make-prefab-struct] to create an instance +of the structure type. + +@examples[ +(prefab-struct-key #s(cat "Garfield")) +(define-struct cat (name) #:prefab) +(define-struct (cute-cat cat) (shipping-dest) #:prefab) +(make-cute-cat "Nermel" "Abu Dhabi") +]} + + +@defproc[(make-prefab-struct [key (or/c symbol? list?)] [v any/c] ...) struct?]{ + +Creates an instance of a @tech{prefab} structure type, using the +@scheme[v]s as field values. The @scheme[key] and the number of +@scheme[v]s determine the @tech{prefab} structure type. + +A @scheme[key] identifies a structure type based on a list with the +following items: + +@itemize{ + + @item{A symbol for the structure type's name.} + + @item{An exact, nonnegative integer representing the number of + non-automatic fields in the structure type, not counting fields + from the supertype (if any).} + + @item{A list of two items, where the first is an exact, nonnegative + integer for the number of automatic fields in the structure + type that are not from the supertype (if any), and the second + element is an arbitrary value that is the value for the + automatic fields.} + + @item{A vector of exact, nonnegative integers that indicate mutable + non-automatic fields in the structure type, counting from + @scheme[0] and not including fields from the supertype (if + any).} + + @item{Nothing else, if the structure type has no + supertype. Otherwise, the rest of the list matches is the key + for the supertype.} + +} + +An empty vector and an auto-field list that starts with @scheme[0] can +be omitted. Furthermore, the first integer (which indicates the number +of non-automatic fields) can be omitted, since it can be inferred from +the number of supplied @scheme[v]s. Finally, a single symbol can be +used instead of a list that contains only a symbol (in the case that +the structure type has no supertype, no automatic fields, and no +mutable fields). + +If the number of fields indicated by @scheme[key] is inconsistent with +the number of supplied @scheme[v]s, the @exnraise[exn:fail:contract]. + +@examples[ +(make-prefab-struct 'clown "Binky" "pie") +(make-prefab-struct '(clown 2) "Binky" "pie") +(make-prefab-struct '(clown 2 (0 #f) #()) "Binky" "pie") +(make-prefab-struct '(clown 1 (1 #f) #()) "Binky" "pie") +(make-prefab-struct '(clown 1 (1 #f) #(0)) "Binky" "pie") +]} + @;------------------------------------------------------------------------ @section[#:tag "structinfo"]{Structure Type Transformer Binding} diff --git a/collects/scribblings/reference/stx-patterns.scrbl b/collects/scribblings/reference/stx-patterns.scrbl index 95c073483f..13d853b7f3 100644 --- a/collects/scribblings/reference/stx-patterns.scrbl +++ b/collects/scribblings/reference/stx-patterns.scrbl @@ -3,7 +3,7 @@ @(define ellipses (scheme ...)) -@title{Pattern-Based Syntax Matching} +@title[#:tag "stx-patterns"]{Pattern-Based Syntax Matching} @defform/subs[(syntax-case stx-expr (literal-id ...) clause ...) @@ -17,6 +17,8 @@ (pattern ... pattern ellipses pattern ... . pattern) (code:line #,(tt "#")(pattern ...)) (code:line #,(tt "#")(pattern ... pattern ellipses pattern ...)) + (code:line #,(tt "#s")(key-datum pattern ...)) + (code:line #,(tt "#s")(key-datum pattern ... pattern ellipses pattern ...)) (ellipses stat-pattern) const] [stat-pattern id @@ -118,6 +120,19 @@ A syntax object matches a @scheme[pattern] as follows: but matching a vector syntax object whose elements match the corresponding sub-@scheme[pattern]s.} + @specsubform[(code:line #,(tt "#s")(key-datum pattern ...))]{ + + Like a @scheme[(pattern ...)] pattern, but matching a @tech{prefab} + structure syntax object whose fields match the corresponding + sub-@scheme[pattern]s. The @scheme[key-datum] must correspond to a + valid first argument to @scheme[make-prefab-struct].} + + @specsubform[(code:line #,(tt "#s")(key-datum pattern ... pattern ellipses pattern ...))]{ + + Like a @scheme[(pattern ... pattern ellipses pattern ...)] pattern, + but matching a @tech{prefab} structure syntax object whose elements + match the corresponding sub-@scheme[pattern]s.} + @specsubform[(ellipses stat-pattern)]{ Matches the same as @scheme[stat-pattern], which is like a @scheme[pattern], @@ -180,6 +195,7 @@ the individual @scheme[stx-expr].} (template-elem ...) (template-elem ...+ . template) (code:line #,(tt "#")(template-elem ...)) + (code:line #,(tt "#s")(key-datum template-elem ...)) (ellipses stat-template) const] [template-elem (code:line template ellipses ...)] @@ -187,6 +203,7 @@ the individual @scheme[stx-expr].} (stat-template ...) (stat-template ... . stat-template) (code:line #,(tt "#")(stat-template ...)) + (code:line #,(tt "#s")(key-datum stat-template ...)) const] [ellipses #,ellipses])]{ @@ -265,6 +282,13 @@ Template forms produce a syntax object as follows: Like the @scheme[(template-elem ...)] form, but producing a syntax object whose datum is a vector instead of a list.} + @specsubform[(code:line #,(tt "#s")(key-datum template-elem ...))]{ + + Like the @scheme[(template-elem ...)] form, but producing a syntax + object whose datum is a @tech{prefab} structure instead of a list. + The @scheme[key-datum] must correspond to a valid first argument of + @scheme[make-prefab-struct].} + @specsubform[(ellipses stat-template)]{ Produces the same result as @scheme[stat-template], which is like a diff --git a/collects/scribblings/reference/syntax.scrbl b/collects/scribblings/reference/syntax.scrbl index 01c145a116..b5efcf8de5 100644 --- a/collects/scribblings/reference/syntax.scrbl +++ b/collects/scribblings/reference/syntax.scrbl @@ -3,9 +3,11 @@ (for-label (only-in scheme/require-transform make-require-transformer) scheme/require-syntax + scheme/require (only-in scheme/provide-transform make-provide-transformer) - scheme/provide-syntax)) + scheme/provide-syntax + scheme/provide)) @(define cvt (schemefont "CVT")) @@ -1082,11 +1084,15 @@ and the result of the @scheme[_expr] takes the place of the @scheme[(unquote-splicing _expr)] similarly escapes, but the @scheme[_expr] must produce a list, and its elements are spliced as multiple values place of the @scheme[(unquote-splicing _expr)], which -must appear as the @scheme[car] or a quoted pair; if the @scheme[cdr] -of the relevant quoted pair is empty, then @scheme[_expr] need not -produce a list, and its result is used directly in place of the quoted -pair (in the same way that @scheme[append] accepts a non-list final -argument). +must appear as the @scheme[car] or a quoted pair, as an element of a +quoted vector, or as an element of a quoted @tech{prefab} structure; +in the case of a pair, if the @scheme[cdr] of the relevant quoted pair +is empty, then @scheme[_expr] need not produce a list, and its result +is used directly in place of the quoted pair (in the same way that +@scheme[append] accepts a non-list final argument). If +@scheme[unquote] or @scheme[unquote-splicing] appears within +@scheme[quasiquote] in any other way than as @scheme[(unquote _expr)] +or @scheme[(unquote-splicing _expr)], a syntax error is reported. @examples[ (eval:alts (#,(scheme quasiquote) (0 1 2)) `(0 1 2)) @@ -1103,7 +1109,9 @@ form is typically abbreviated with @litchar{`}, @litchar{,}, or @examples[ `(0 1 2) `(1 ,(+ 1 2) 4) +`#s(stuff 1 ,(+ 1 2) 4) `(1 ,@(list 1 2) 4) +`#(1 ,@(list 1 2) 4) ] A @scheme[quasiquote] form within the original @scheme[datum] @@ -1715,15 +1723,16 @@ introduced at the same time. Similarly, @schemeidfont{all-defined} and its variants export only definitions accessible from the lexical context of the @scheme[phaseless-spec] form.} -@subsection{Additional @scheme[require] Macros} +@; -------------------- + +@subsection{Additional @scheme[require] Forms} @note-lib-only[scheme/require] -This library provides additional forms for use in @scheme[require] and -@scheme[provide]. These forms provide more complex selection and -massaging of identifiers that are useful in some cases. Note that a -@scheme[require] form is expanded before it is used, which means that -requiring the library itself should be a separate form. For example, use +The following forms support more complex selection and manipulation of +sets of imported identifiers. Note that a @scheme[require] form is +expanded before it is used, which means that requiring the library +itself should be a separate form. For example, use @schemeblock[ (require scheme/require) @@ -1737,35 +1746,26 @@ instead of (matching-identifiers-in #rx"foo" "foo.ss")) ] -@defsubform[(matching-identifiers-in regexp require-spec)]{ - Like @scheme[require-spec], but including only imports whose names - match @scheme[regexp]. @scheme[regexp] must be a literal regular +@defform[(matching-identifiers-in regexp require-spec)]{ Like + @scheme[require-spec], but including only imports whose names match + @scheme[regexp]. The @scheme[regexp] must be a literal regular expression (see @secref["regexp"]).} -@defsubform[(subtract-in require-spec subtracted-spec ...)]{ - Like @scheme[require-spec], but omitting those imports that are - provided by one of the @scheme[subtracted-spec]s.} +@defform[(subtract-in require-spec subtracted-spec ...)]{ Like + @scheme[require-spec], but omitting those imports that would be + imported by one of the @scheme[subtracted-spec]s.} -@subsection{Additional @scheme[provide] Macros} +@; -------------------- + +@subsection{Additional @scheme[provide] Forms} @note-lib-only[scheme/provide] -This library provides additional forms for use in @scheme[provide], it -mirrors the @scheme[scheme/require] library. - -@defsubform[(matching-identifiers-out regexp provide-spec)]{ - Like @scheme[provide-spec], but omitting the export of each binding - with an external name that matches @scheme[regexp]. @scheme[regexp] +@defform[(matching-identifiers-out regexp provide-spec)]{ Like + @scheme[provide-spec], but omitting the export of each binding with + an external name that matches @scheme[regexp]. The @scheme[regexp] must be a literal regular expression (see @secref["regexp"]).} -@;{ Cute, and symmetric to subtract-in, but useless -@defsubform[(subtract-out provide-spec subtracted-spec ...)]{ - Like @scheme[provide-spec], but omitting exports that are provided - by one of the @scheme[subtracted-spec]s. Note that this form is not - useful by itself: the specified bindings have already been required - so they have no clashes.} -;} - @;------------------------------------------------------------------------ @section[#:tag "#%top-interaction"]{Interaction Wrapper: @scheme[#%top-interaction]} diff --git a/collects/scribblings/reference/write.scrbl b/collects/scribblings/reference/write.scrbl index 3b962046dd..978de5b9d1 100644 --- a/collects/scribblings/reference/write.scrbl +++ b/collects/scribblings/reference/write.scrbl @@ -161,9 +161,9 @@ A parameter that controls printing data with sharing; defaults to @defboolparam[print-struct on?]{ -A parameter that controls printing structure values in vector form; -defaults to @scheme[#t]. See @secref["printing"] for more -information. This parameter has no effect on the printing of +A parameter that controls printing structure values in vector or +@tech{prefab} form; defaults to @scheme[#t]. See @secref["printing"] +for more information. This parameter has no effect on the printing of structures that have a custom-write procedure (see @scheme[prop:custom-write]).} diff --git a/collects/tests/mzscheme/read.ss b/collects/tests/mzscheme/read.ss index df867b3449..36e8666bc6 100644 --- a/collects/tests/mzscheme/read.ss +++ b/collects/tests/mzscheme/read.ss @@ -1023,6 +1023,26 @@ p))) (test s format "~s" (read (open-input-string s)))) +;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Prefab + +(test #t struct? (readstr "#s(v 1)")) +(test #t struct? (readstr "#s((v 1) 1)")) +(test #t struct? (readstr "#s((v 1 #()) 1)")) +(test #t struct? (readstr "#s((v 0 (1 #f) #()) 1)")) +(test #t struct? (readstr "#s((v (1 #f) #()) 1)")) +(test #t struct? (readstr "#s((v #(0)) 1)")) +(test #t struct? (readstr "#0=#s(v #0#)")) +(let ([v1 (readstr "#0=#s(v #0#)")]) + (define-struct v (self) #:prefab) + (test #t eq? v1 (v-self v1))) +(err/rt-test (readstr "#s((v 2) 1)") exn:fail:read?) +(err/rt-test (readstr "#s((v 0) 1)") exn:fail:read?) +(err/rt-test (readstr "#s((v 0) 1)") exn:fail:read?) +(err/rt-test (readstr "#s((v 1 (1 #f) #()) 1)") exn:fail:read?) +(err/rt-test (readstr "#s((v 0 (2 #f) #()) 1)") exn:fail:read?) +(err/rt-test (readstr "#s((v 0 (2 #f) #(0)) 1)") exn:fail:read?) + ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (report-errs) diff --git a/collects/tests/mzscheme/struct.ss b/collects/tests/mzscheme/struct.ss index 61e3f4529d..a66f4e2d6f 100644 --- a/collects/tests/mzscheme/struct.ss +++ b/collects/tests/mzscheme/struct.ss @@ -470,6 +470,13 @@ (struct-syntax-test 'define-struct) +(syntax-test #'(define-struct a (b c) #:transparent #:inspector #f)) +(syntax-test #'(define-struct a (b c) #:transparent #:prefab)) +(syntax-test #'(define-struct a (b c) #:prefab #:guard 10)) +(syntax-test #'(define-struct a (b c) #:prefab #:property 1 10)) +(syntax-test #'(define-struct a (b c) #:guard 10 #:prefab)) +(syntax-test #'(define-struct a (b c) #:property 1 10 #:prefab)) + (define-struct base0 ()) (define-struct base1 (a)) (define-struct base2 (l r)) @@ -638,6 +645,43 @@ (test 10 a-x (make-b 10 20 30)) (test 100 a-x (make-c 100 200 300 400))) +;; ------------------------------------------------------------ +;; Prefab + +(let ([v1 #s(v one)] + [v2 #s(v one two)] + [v2-prime #s((v 2) one two)] + [vw3 #s((v w 2) one two three)] + [vw3-prime #s((v 1 w 2) one two three)]) + (test #f equal? v1 v2) + (test #t equal? v2 v2-prime) + (test #t equal? vw3 vw3-prime) + (let () + (define-struct v (a) #:prefab) + (test #t v? v1) + (test #f v? v2) + (test #f v? vw3) + (test 'one v-a v1)) + (let () + (define-struct v (a b) #:prefab) + (test #f v? v1) + (test #t v? v2) + (test #f v? vw3) + (test 'one v-a v2) + (test 'two v-b v2)) + (let () + (define-struct w (a b) #:prefab) + (define-struct (v w) (c) #:prefab) + (test #f v? v1) + (test #f v? v2) + (test #t v? vw3) + (test #t w? vw3) + (test 'one w-a vw3) + (test 'two w-b vw3) + (test 'three v-c vw3))) + +(err/rt-test (make-struct-type 'bad struct:date 2 0 #f null 'prefab)) + ;; ------------------------------------------------------------ ;; Misc. built-in structures diff --git a/src/mzscheme/src/cstartup.inc b/src/mzscheme/src/cstartup.inc index fdbfa03b00..460111ad70 100644 --- a/src/mzscheme/src/cstartup.inc +++ b/src/mzscheme/src/cstartup.inc @@ -1,24 +1,24 @@ { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,54,50,0,0,0,1,0,0,6,0, -9,0,13,0,18,0,25,0,32,0,37,0,42,0,46,0,59,0,66,0,69, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,56,50,0,0,0,1,0,0,6,0, +9,0,14,0,17,0,24,0,31,0,35,0,42,0,47,0,60,0,65,0,69, 0,78,0,84,0,98,0,112,0,115,0,119,0,121,0,132,0,134,0,148,0, 155,0,177,0,179,0,193,0,253,0,23,1,32,1,41,1,51,1,68,1,107, 1,146,1,215,1,4,2,92,2,137,2,142,2,162,2,53,3,73,3,124,3, 190,3,75,4,233,4,20,5,31,5,110,5,0,0,131,7,0,0,65,98,101, -103,105,110,29,11,11,63,108,101,116,64,99,111,110,100,66,117,110,108,101,115, -115,66,100,101,102,105,110,101,64,119,104,101,110,64,108,101,116,42,63,97,110, -100,72,112,97,114,97,109,101,116,101,114,105,122,101,66,108,101,116,114,101,99, -62,111,114,68,104,101,114,101,45,115,116,120,65,113,117,111,116,101,29,94,2, +103,105,110,29,11,11,64,99,111,110,100,62,111,114,66,108,101,116,114,101,99, +66,117,110,108,101,115,115,63,108,101,116,66,100,101,102,105,110,101,64,119,104, +101,110,72,112,97,114,97,109,101,116,101,114,105,122,101,64,108,101,116,42,63, +97,110,100,68,104,101,114,101,45,115,116,120,65,113,117,111,116,101,29,94,2, 14,68,35,37,107,101,114,110,101,108,11,29,94,2,14,68,35,37,112,97,114, 97,109,122,11,62,105,102,63,115,116,120,61,115,70,108,101,116,45,118,97,108, 117,101,115,61,120,73,108,101,116,114,101,99,45,118,97,108,117,101,115,66,108, 97,109,98,100,97,1,20,112,97,114,97,109,101,116,101,114,105,122,97,116,105, 111,110,45,107,101,121,61,118,73,100,101,102,105,110,101,45,118,97,108,117,101, -115,98,10,34,11,8,143,183,94,159,2,16,34,34,159,2,15,34,34,16,20, +115,98,10,34,11,8,167,184,94,159,2,16,34,34,159,2,15,34,34,16,20, 2,3,2,2,2,5,2,2,2,6,2,2,2,7,2,2,2,8,2,2,2, 9,2,2,2,4,2,2,2,10,2,2,2,11,2,2,2,12,2,2,97,35, -11,8,143,183,93,159,2,15,34,35,16,2,2,13,161,2,2,35,2,13,2, -2,2,13,97,10,11,11,8,143,183,16,0,97,10,36,11,8,143,183,16,0, +11,8,167,184,93,159,2,15,34,35,16,2,2,13,161,2,2,35,2,13,2, +2,2,13,97,10,11,11,8,167,184,16,0,97,10,36,11,8,167,184,16,0, 13,16,4,34,29,11,11,2,2,11,18,98,64,104,101,114,101,8,31,8,30, 8,29,8,28,8,27,27,248,22,180,3,23,196,1,249,22,173,3,80,158,37, 34,251,22,73,2,17,248,22,88,23,200,2,12,249,22,63,2,1,248,22,90, @@ -26,16 +26,16 @@ 73,2,17,248,22,88,23,200,2,249,22,63,2,1,248,22,90,23,202,1,12, 27,248,22,65,248,22,180,3,23,197,1,28,248,22,71,23,194,2,20,15,159, 35,34,35,28,248,22,71,248,22,65,23,195,2,248,22,64,193,249,22,173,3, -80,158,37,34,251,22,73,2,17,248,22,64,23,200,2,249,22,63,2,9,248, +80,158,37,34,251,22,73,2,17,248,22,64,23,200,2,249,22,63,2,12,248, 22,65,23,202,1,11,18,100,10,8,31,8,30,8,29,8,28,8,27,16,4, -11,11,2,18,3,1,7,101,110,118,55,50,49,51,16,4,11,11,2,19,3, -1,7,101,110,118,55,50,49,52,27,248,22,65,248,22,180,3,23,197,1,28, +11,11,2,18,3,1,7,101,110,118,55,50,57,52,16,4,11,11,2,19,3, +1,7,101,110,118,55,50,57,53,27,248,22,65,248,22,180,3,23,197,1,28, 248,22,71,23,194,2,20,15,159,35,34,35,28,248,22,71,248,22,65,23,195, 2,248,22,64,193,249,22,173,3,80,158,37,34,250,22,73,2,20,248,22,73, 249,22,73,248,22,73,2,21,248,22,64,23,202,2,251,22,73,2,17,2,21, -2,21,249,22,63,2,12,248,22,65,23,205,1,18,100,11,8,31,8,30,8, -29,8,28,8,27,16,4,11,11,2,18,3,1,7,101,110,118,55,50,49,54, -16,4,11,11,2,19,3,1,7,101,110,118,55,50,49,55,248,22,180,3,193, +2,21,249,22,63,2,4,248,22,65,23,205,1,18,100,11,8,31,8,30,8, +29,8,28,8,27,16,4,11,11,2,18,3,1,7,101,110,118,55,50,57,55, +16,4,11,11,2,19,3,1,7,101,110,118,55,50,57,56,248,22,180,3,193, 27,248,22,180,3,194,249,22,63,248,22,73,248,22,64,196,248,22,65,195,27, 248,22,65,248,22,180,3,23,197,1,249,22,173,3,80,158,37,34,28,248,22, 51,248,22,174,3,248,22,64,23,198,2,27,249,22,2,32,0,89,162,8,44, @@ -49,8 +49,8 @@ 22,249,22,2,32,0,89,162,8,44,35,45,9,222,33,42,248,22,180,3,248, 22,64,201,248,22,65,198,27,248,22,65,248,22,180,3,196,27,248,22,180,3, 248,22,64,195,249,22,173,3,80,158,38,34,28,248,22,71,195,250,22,74,2, -20,9,248,22,65,199,250,22,73,2,3,248,22,73,248,22,64,199,250,22,74, -2,8,248,22,65,201,248,22,65,202,27,248,22,65,248,22,180,3,23,197,1, +20,9,248,22,65,199,250,22,73,2,7,248,22,73,248,22,64,199,250,22,74, +2,11,248,22,65,201,248,22,65,202,27,248,22,65,248,22,180,3,23,197,1, 27,249,22,1,22,77,249,22,2,22,180,3,248,22,180,3,248,22,64,199,249, 22,173,3,80,158,38,34,251,22,73,1,22,119,105,116,104,45,99,111,110,116, 105,110,117,97,116,105,111,110,45,109,97,114,107,2,24,250,22,74,1,23,101, @@ -61,12 +61,12 @@ 2,20,15,159,35,34,35,249,22,173,3,80,158,37,34,27,248,22,180,3,248, 22,64,23,198,2,28,249,22,140,8,62,61,62,248,22,174,3,248,22,88,23, 197,2,250,22,73,2,20,248,22,73,249,22,73,21,93,2,25,248,22,64,199, -250,22,74,2,4,249,22,73,2,25,249,22,73,248,22,97,203,2,25,248,22, +250,22,74,2,3,249,22,73,2,25,249,22,73,248,22,97,203,2,25,248,22, 65,202,251,22,73,2,17,28,249,22,140,8,248,22,174,3,248,22,64,23,201, 2,64,101,108,115,101,10,248,22,64,23,198,2,250,22,74,2,20,9,248,22, -65,23,201,1,249,22,63,2,4,248,22,65,23,203,1,99,8,31,8,30,8, -29,8,28,8,27,16,4,11,11,2,18,3,1,7,101,110,118,55,50,51,57, -16,4,11,11,2,19,3,1,7,101,110,118,55,50,52,48,18,158,94,10,64, +65,23,201,1,249,22,63,2,3,248,22,65,23,203,1,99,8,31,8,30,8, +29,8,28,8,27,16,4,11,11,2,18,3,1,7,101,110,118,55,51,50,48, +16,4,11,11,2,19,3,1,7,101,110,118,55,51,50,49,18,158,94,10,64, 118,111,105,100,8,47,27,248,22,65,248,22,180,3,196,249,22,173,3,80,158, 37,34,28,248,22,51,248,22,174,3,248,22,64,197,250,22,73,2,26,248,22, 73,248,22,64,199,248,22,88,198,27,248,22,174,3,248,22,64,197,250,22,73, @@ -79,28 +79,28 @@ 10,2,3,2,4,2,5,2,6,2,7,2,8,2,9,2,10,2,11,2,12, 34,44,35,11,11,16,0,16,0,16,0,34,34,11,11,11,16,0,16,0,16, 0,34,34,16,11,16,5,93,2,13,20,15,159,34,34,34,34,20,102,159,34, -16,0,16,1,33,32,10,16,5,93,2,5,89,162,8,44,35,51,9,223,0, +16,0,16,1,33,32,10,16,5,93,2,6,89,162,8,44,35,51,9,223,0, 33,33,34,20,102,159,34,16,1,20,25,159,35,2,2,2,13,16,0,11,16, -5,93,2,7,89,162,8,44,35,51,9,223,0,33,34,34,20,102,159,34,16, -1,20,25,159,35,2,2,2,13,16,0,11,16,5,93,2,9,89,162,8,44, +5,93,2,9,89,162,8,44,35,51,9,223,0,33,34,34,20,102,159,34,16, +1,20,25,159,35,2,2,2,13,16,0,11,16,5,93,2,12,89,162,8,44, 35,51,9,223,0,33,35,34,20,102,159,34,16,1,20,25,159,35,2,2,2, -13,16,1,33,36,11,16,5,93,2,12,89,162,8,44,35,54,9,223,0,33, +13,16,1,33,36,11,16,5,93,2,4,89,162,8,44,35,54,9,223,0,33, 37,34,20,102,159,34,16,1,20,25,159,35,2,2,2,13,16,1,33,38,11, -16,5,93,2,3,89,162,8,44,35,56,9,223,0,33,41,34,20,102,159,34, -16,1,20,25,159,35,2,2,2,13,16,0,11,16,5,93,2,11,89,162,8, +16,5,93,2,7,89,162,8,44,35,56,9,223,0,33,41,34,20,102,159,34, +16,1,20,25,159,35,2,2,2,13,16,0,11,16,5,93,2,5,89,162,8, 44,35,51,9,223,0,33,43,34,20,102,159,34,16,1,20,25,159,35,2,2, -2,13,16,0,11,16,5,93,2,8,89,162,8,44,35,52,9,223,0,33,44, +2,13,16,0,11,16,5,93,2,11,89,162,8,44,35,52,9,223,0,33,44, 34,20,102,159,34,16,1,20,25,159,35,2,2,2,13,16,0,11,16,5,93, 2,10,89,162,8,44,35,53,9,223,0,33,45,34,20,102,159,34,16,1,20, -25,159,35,2,2,2,13,16,0,11,16,5,93,2,4,89,162,8,44,35,56, +25,159,35,2,2,2,13,16,0,11,16,5,93,2,3,89,162,8,44,35,56, 9,223,0,33,46,34,20,102,159,34,16,1,20,25,159,35,2,2,2,13,16, -1,33,48,11,16,5,93,2,6,89,162,8,44,35,52,9,223,0,33,49,34, +1,33,48,11,16,5,93,2,8,89,162,8,44,35,52,9,223,0,33,49,34, 20,102,159,34,16,1,20,25,159,35,2,2,2,13,16,0,11,16,0,94,2, 15,2,16,93,2,15,9,9,34,0}; EVAL_ONE_SIZED_STR((char *)expr, 2046); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,54,61,0,0,0,1,0,0,3,0, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,56,61,0,0,0,1,0,0,3,0, 16,0,21,0,38,0,53,0,71,0,87,0,97,0,115,0,135,0,151,0,169, 0,200,0,229,0,251,0,9,1,15,1,29,1,34,1,44,1,52,1,80,1, 112,1,157,1,202,1,226,1,9,2,11,2,20,2,77,2,167,3,176,3,217, @@ -133,168 +133,168 @@ 99,97,110,110,111,116,32,97,100,100,32,97,32,115,117,102,102,105,120,32,116, 111,32,97,32,114,111,111,116,32,112,97,116,104,58,32,5,0,68,35,37,107, 101,114,110,101,108,27,20,14,159,80,158,35,49,250,80,158,38,50,249,22,27, -11,80,158,40,49,22,140,12,10,248,22,188,4,23,196,2,28,248,22,166,5, +11,80,158,40,49,22,142,12,10,248,22,188,4,23,196,2,28,248,22,166,5, 23,194,2,12,87,94,248,22,143,8,23,194,1,248,80,159,36,53,35,195,28, -248,22,71,23,195,2,9,27,248,22,64,23,196,2,27,28,248,22,185,12,23, -195,2,23,194,1,28,248,22,184,12,23,195,2,249,22,186,12,23,196,1,250, -80,158,41,47,248,22,136,13,2,20,11,10,250,80,158,39,47,248,22,136,13, -2,20,23,197,1,10,28,23,193,2,249,22,63,248,22,188,12,249,22,186,12, -23,198,1,247,22,137,13,27,248,22,65,23,200,1,28,248,22,71,23,194,2, -9,27,248,22,64,23,195,2,27,28,248,22,185,12,23,195,2,23,194,1,28, -248,22,184,12,23,195,2,249,22,186,12,23,196,1,250,80,158,46,47,248,22, -136,13,2,20,11,10,250,80,158,44,47,248,22,136,13,2,20,23,197,1,10, -28,23,193,2,249,22,63,248,22,188,12,249,22,186,12,23,198,1,247,22,137, +248,22,71,23,195,2,9,27,248,22,64,23,196,2,27,28,248,22,187,12,23, +195,2,23,194,1,28,248,22,186,12,23,195,2,249,22,188,12,23,196,1,250, +80,158,41,47,248,22,138,13,2,20,11,10,250,80,158,39,47,248,22,138,13, +2,20,23,197,1,10,28,23,193,2,249,22,63,248,22,190,12,249,22,188,12, +23,198,1,247,22,139,13,27,248,22,65,23,200,1,28,248,22,71,23,194,2, +9,27,248,22,64,23,195,2,27,28,248,22,187,12,23,195,2,23,194,1,28, +248,22,186,12,23,195,2,249,22,188,12,23,196,1,250,80,158,46,47,248,22, +138,13,2,20,11,10,250,80,158,44,47,248,22,138,13,2,20,23,197,1,10, +28,23,193,2,249,22,63,248,22,190,12,249,22,188,12,23,198,1,247,22,139, 13,248,80,159,44,52,35,248,22,65,23,199,1,87,94,23,193,1,248,80,159, 42,52,35,248,22,65,23,197,1,87,94,23,193,1,27,248,22,65,23,198,1, -28,248,22,71,23,194,2,9,27,248,22,64,23,195,2,27,28,248,22,185,12, -23,195,2,23,194,1,28,248,22,184,12,23,195,2,249,22,186,12,23,196,1, -250,80,158,44,47,248,22,136,13,2,20,11,10,250,80,158,42,47,248,22,136, -13,2,20,23,197,1,10,28,23,193,2,249,22,63,248,22,188,12,249,22,186, -12,23,198,1,247,22,137,13,248,80,159,42,52,35,248,22,65,23,199,1,248, +28,248,22,71,23,194,2,9,27,248,22,64,23,195,2,27,28,248,22,187,12, +23,195,2,23,194,1,28,248,22,186,12,23,195,2,249,22,188,12,23,196,1, +250,80,158,44,47,248,22,138,13,2,20,11,10,250,80,158,42,47,248,22,138, +13,2,20,23,197,1,10,28,23,193,2,249,22,63,248,22,190,12,249,22,188, +12,23,198,1,247,22,139,13,248,80,159,42,52,35,248,22,65,23,199,1,248, 80,159,40,52,35,248,22,65,196,249,80,159,36,37,35,2,7,195,27,248,22, -161,12,23,195,2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23, -195,2,27,248,22,183,12,195,28,192,192,248,22,184,12,195,11,87,94,28,28, -248,22,162,12,23,195,2,10,27,248,22,161,12,23,196,2,28,23,193,2,192, -87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,183,12,23,197,2, -28,23,193,2,192,87,94,23,193,1,248,22,184,12,23,197,2,11,12,250,22, +163,12,23,195,2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23, +195,2,27,248,22,185,12,195,28,192,192,248,22,186,12,195,11,87,94,28,28, +248,22,164,12,23,195,2,10,27,248,22,163,12,23,196,2,28,23,193,2,192, +87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,185,12,23,197,2, +28,23,193,2,192,87,94,23,193,1,248,22,186,12,23,197,2,11,12,250,22, 170,8,76,110,111,114,109,97,108,45,112,97,116,104,45,99,97,115,101,6,42, 42,112,97,116,104,32,40,102,111,114,32,97,110,121,32,115,121,115,116,101,109, 41,32,111,114,32,118,97,108,105,100,45,112,97,116,104,32,115,116,114,105,110, -103,23,197,2,28,28,248,22,162,12,23,195,2,249,22,140,8,248,22,163,12, +103,23,197,2,28,28,248,22,164,12,23,195,2,249,22,140,8,248,22,165,12, 23,197,2,2,21,249,22,140,8,247,22,154,7,2,21,27,28,248,22,135,6, -23,196,2,23,195,2,248,22,144,7,248,22,166,12,23,197,2,28,249,22,149, +23,196,2,23,195,2,248,22,144,7,248,22,168,12,23,197,2,28,249,22,151, 13,0,21,35,114,120,34,94,91,92,92,93,91,92,92,93,91,63,93,91,92, -92,93,34,23,195,2,28,248,22,135,6,195,248,22,169,12,195,194,27,248,22, -174,6,23,195,1,249,22,170,12,248,22,147,7,250,22,155,13,0,6,35,114, -120,34,47,34,28,249,22,149,13,0,22,35,114,120,34,91,47,92,92,93,91, -46,32,93,43,91,47,92,92,93,42,36,34,23,201,2,23,199,1,250,22,155, +92,93,34,23,195,2,28,248,22,135,6,195,248,22,171,12,195,194,27,248,22, +174,6,23,195,1,249,22,172,12,248,22,147,7,250,22,157,13,0,6,35,114, +120,34,47,34,28,249,22,151,13,0,22,35,114,120,34,91,47,92,92,93,91, +46,32,93,43,91,47,92,92,93,42,36,34,23,201,2,23,199,1,250,22,157, 13,0,19,35,114,120,34,91,32,46,93,43,40,91,47,92,92,93,42,41,36, 34,23,202,1,6,2,2,92,49,80,158,42,35,2,21,28,248,22,135,6,194, -248,22,169,12,194,193,87,94,28,27,248,22,161,12,23,196,2,28,23,193,2, -192,87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,183,12,23,197, -2,28,23,193,2,192,87,94,23,193,1,248,22,184,12,23,197,2,11,12,250, -22,170,8,23,196,2,2,22,23,197,2,28,248,22,183,12,23,195,2,12,248, -22,185,10,249,22,130,10,248,22,164,6,250,22,183,6,2,23,23,200,1,23, -201,1,247,22,23,87,94,28,27,248,22,161,12,23,196,2,28,23,193,2,192, -87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,183,12,23,197,2, -28,23,193,2,192,87,94,23,193,1,248,22,184,12,23,197,2,11,12,250,22, -170,8,23,196,2,2,22,23,197,2,28,248,22,183,12,23,195,2,12,248,22, -185,10,249,22,130,10,248,22,164,6,250,22,183,6,2,23,23,200,1,23,201, -1,247,22,23,87,94,87,94,28,27,248,22,161,12,23,196,2,28,23,193,2, -192,87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,183,12,23,197, -2,28,23,193,2,192,87,94,23,193,1,248,22,184,12,23,197,2,11,12,250, -22,170,8,195,2,22,23,197,2,28,248,22,183,12,23,195,2,12,248,22,185, -10,249,22,130,10,248,22,164,6,250,22,183,6,2,23,199,23,201,1,247,22, -23,249,22,3,89,162,42,35,48,9,223,2,33,36,196,248,22,185,10,249,22, -160,10,23,196,1,247,22,23,87,94,87,94,249,80,159,36,37,35,2,7,195, +248,22,171,12,194,193,87,94,28,27,248,22,163,12,23,196,2,28,23,193,2, +192,87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,185,12,23,197, +2,28,23,193,2,192,87,94,23,193,1,248,22,186,12,23,197,2,11,12,250, +22,170,8,23,196,2,2,22,23,197,2,28,248,22,185,12,23,195,2,12,248, +22,187,10,249,22,132,10,248,22,164,6,250,22,183,6,2,23,23,200,1,23, +201,1,247,22,23,87,94,28,27,248,22,163,12,23,196,2,28,23,193,2,192, +87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,185,12,23,197,2, +28,23,193,2,192,87,94,23,193,1,248,22,186,12,23,197,2,11,12,250,22, +170,8,23,196,2,2,22,23,197,2,28,248,22,185,12,23,195,2,12,248,22, +187,10,249,22,132,10,248,22,164,6,250,22,183,6,2,23,23,200,1,23,201, +1,247,22,23,87,94,87,94,28,27,248,22,163,12,23,196,2,28,23,193,2, +192,87,94,23,193,1,28,248,22,135,6,23,196,2,27,248,22,185,12,23,197, +2,28,23,193,2,192,87,94,23,193,1,248,22,186,12,23,197,2,11,12,250, +22,170,8,195,2,22,23,197,2,28,248,22,185,12,23,195,2,12,248,22,187, +10,249,22,132,10,248,22,164,6,250,22,183,6,2,23,199,23,201,1,247,22, +23,249,22,3,89,162,42,35,48,9,223,2,33,36,196,248,22,187,10,249,22, +162,10,23,196,1,247,22,23,87,94,87,94,249,80,159,36,37,35,2,7,195, 249,22,3,80,159,36,51,35,196,251,80,159,38,40,35,2,7,32,0,89,162, 42,35,43,9,222,33,38,197,198,32,40,89,162,42,40,57,65,99,108,111,111, 112,222,33,41,28,248,22,71,23,199,2,87,94,23,198,1,248,23,196,1,251, 22,183,6,2,24,23,199,1,28,248,22,71,23,203,2,87,94,23,202,1,23, -201,1,250,22,1,22,179,12,23,204,1,23,205,1,23,198,1,27,249,22,179, -12,248,22,64,23,202,2,23,199,2,28,248,22,174,12,23,194,2,27,250,22, -1,22,179,12,23,197,1,23,202,2,28,248,22,174,12,23,194,2,192,87,94, +201,1,250,22,1,22,181,12,23,204,1,23,205,1,23,198,1,27,249,22,181, +12,248,22,64,23,202,2,23,199,2,28,248,22,176,12,23,194,2,27,250,22, +1,22,181,12,23,197,1,23,202,2,28,248,22,176,12,23,194,2,192,87,94, 23,193,1,27,248,22,65,23,202,1,28,248,22,71,23,194,2,87,94,23,193, 1,248,23,199,1,251,22,183,6,2,24,23,202,1,28,248,22,71,23,206,2, -87,94,23,205,1,23,204,1,250,22,1,22,179,12,23,207,1,23,208,1,23, -201,1,27,249,22,179,12,248,22,64,23,197,2,23,202,2,28,248,22,174,12, -23,194,2,27,250,22,1,22,179,12,23,197,1,204,28,248,22,174,12,193,192, +87,94,23,205,1,23,204,1,250,22,1,22,181,12,23,207,1,23,208,1,23, +201,1,27,249,22,181,12,248,22,64,23,197,2,23,202,2,28,248,22,176,12, +23,194,2,27,250,22,1,22,181,12,23,197,1,204,28,248,22,176,12,193,192, 253,2,40,203,204,205,206,23,15,248,22,65,201,253,2,40,202,203,204,205,206, 248,22,65,200,87,94,23,193,1,27,248,22,65,23,201,1,28,248,22,71,23, 194,2,87,94,23,193,1,248,23,198,1,251,22,183,6,2,24,23,201,1,28, -248,22,71,23,205,2,87,94,23,204,1,23,203,1,250,22,1,22,179,12,23, -206,1,23,207,1,23,200,1,27,249,22,179,12,248,22,64,23,197,2,23,201, -2,28,248,22,174,12,23,194,2,27,250,22,1,22,179,12,23,197,1,203,28, -248,22,174,12,193,192,253,2,40,202,203,204,205,206,248,22,65,201,253,2,40, -201,202,203,204,205,248,22,65,200,27,247,22,138,13,253,2,40,198,199,200,201, -202,198,87,95,28,28,248,22,162,12,23,194,2,10,27,248,22,161,12,23,195, +248,22,71,23,205,2,87,94,23,204,1,23,203,1,250,22,1,22,181,12,23, +206,1,23,207,1,23,200,1,27,249,22,181,12,248,22,64,23,197,2,23,201, +2,28,248,22,176,12,23,194,2,27,250,22,1,22,181,12,23,197,1,203,28, +248,22,176,12,193,192,253,2,40,202,203,204,205,206,248,22,65,201,253,2,40, +201,202,203,204,205,248,22,65,200,27,247,22,140,13,253,2,40,198,199,200,201, +202,198,87,95,28,28,248,22,164,12,23,194,2,10,27,248,22,163,12,23,195, 2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23,195,2,27,248, -22,183,12,23,196,2,28,23,193,2,192,87,94,23,193,1,248,22,184,12,23, +22,185,12,23,196,2,28,23,193,2,192,87,94,23,193,1,248,22,186,12,23, 196,2,11,12,252,22,170,8,23,200,2,2,25,34,23,198,2,23,199,2,28, 28,248,22,135,6,23,195,2,10,248,22,187,6,23,195,2,87,94,23,194,1, 12,252,22,170,8,23,200,2,2,26,35,23,198,2,23,199,1,91,159,37,11, -90,161,37,34,11,248,22,182,12,23,197,2,87,94,23,195,1,87,94,28,192, +90,161,37,34,11,248,22,184,12,23,197,2,87,94,23,195,1,87,94,28,192, 12,250,22,171,8,23,201,1,2,27,23,199,1,249,22,7,194,195,91,159,36, -11,90,161,36,34,11,87,95,28,28,248,22,162,12,23,196,2,10,27,248,22, -161,12,23,197,2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23, -197,2,27,248,22,183,12,23,198,2,28,23,193,2,192,87,94,23,193,1,248, -22,184,12,23,198,2,11,12,252,22,170,8,2,10,2,25,34,23,200,2,23, +11,90,161,36,34,11,87,95,28,28,248,22,164,12,23,196,2,10,27,248,22, +163,12,23,197,2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23, +197,2,27,248,22,185,12,23,198,2,28,23,193,2,192,87,94,23,193,1,248, +22,186,12,23,198,2,11,12,252,22,170,8,2,10,2,25,34,23,200,2,23, 201,2,28,28,248,22,135,6,23,197,2,10,248,22,187,6,23,197,2,12,252, 22,170,8,2,10,2,26,35,23,200,2,23,201,2,91,159,37,11,90,161,37, -34,11,248,22,182,12,23,199,2,87,94,23,195,1,87,94,28,23,193,2,12, +34,11,248,22,184,12,23,199,2,87,94,23,195,1,87,94,28,23,193,2,12, 250,22,171,8,2,10,2,27,23,201,2,249,22,7,23,195,1,23,196,1,27, -249,22,171,12,250,22,154,13,0,18,35,114,120,35,34,40,91,46,93,91,94, -46,93,42,124,41,36,34,248,22,167,12,23,201,1,28,248,22,135,6,23,203, -2,249,22,147,7,23,204,1,8,63,23,202,1,28,248,22,162,12,23,199,2, -248,22,163,12,23,199,1,87,94,23,198,1,247,22,164,12,28,248,22,161,12, -194,249,22,179,12,195,194,192,91,159,36,11,90,161,36,34,11,87,95,28,28, -248,22,162,12,23,196,2,10,27,248,22,161,12,23,197,2,28,23,193,2,192, -87,94,23,193,1,28,248,22,135,6,23,197,2,27,248,22,183,12,23,198,2, -28,23,193,2,192,87,94,23,193,1,248,22,184,12,23,198,2,11,12,252,22, +249,22,173,12,250,22,156,13,0,18,35,114,120,35,34,40,91,46,93,91,94, +46,93,42,124,41,36,34,248,22,169,12,23,201,1,28,248,22,135,6,23,203, +2,249,22,147,7,23,204,1,8,63,23,202,1,28,248,22,164,12,23,199,2, +248,22,165,12,23,199,1,87,94,23,198,1,247,22,166,12,28,248,22,163,12, +194,249,22,181,12,195,194,192,91,159,36,11,90,161,36,34,11,87,95,28,28, +248,22,164,12,23,196,2,10,27,248,22,163,12,23,197,2,28,23,193,2,192, +87,94,23,193,1,28,248,22,135,6,23,197,2,27,248,22,185,12,23,198,2, +28,23,193,2,192,87,94,23,193,1,248,22,186,12,23,198,2,11,12,252,22, 170,8,2,11,2,25,34,23,200,2,23,201,2,28,28,248,22,135,6,23,197, 2,10,248,22,187,6,23,197,2,12,252,22,170,8,2,11,2,26,35,23,200, -2,23,201,2,91,159,37,11,90,161,37,34,11,248,22,182,12,23,199,2,87, +2,23,201,2,91,159,37,11,90,161,37,34,11,248,22,184,12,23,199,2,87, 94,23,195,1,87,94,28,23,193,2,12,250,22,171,8,2,11,2,27,23,201, -2,249,22,7,23,195,1,23,196,1,27,249,22,171,12,249,22,133,7,250,22, -155,13,0,9,35,114,120,35,34,91,46,93,34,248,22,167,12,23,203,1,6, +2,249,22,7,23,195,1,23,196,1,27,249,22,173,12,249,22,133,7,250,22, +157,13,0,9,35,114,120,35,34,91,46,93,34,248,22,169,12,23,203,1,6, 1,1,95,28,248,22,135,6,23,202,2,249,22,147,7,23,203,1,8,63,23, -201,1,28,248,22,162,12,23,199,2,248,22,163,12,23,199,1,87,94,23,198, -1,247,22,164,12,28,248,22,161,12,194,249,22,179,12,195,194,192,249,247,22, -186,5,194,11,248,80,158,35,45,9,27,247,22,140,13,249,80,158,37,46,28, +201,1,28,248,22,164,12,23,199,2,248,22,165,12,23,199,1,87,94,23,198, +1,247,22,166,12,28,248,22,163,12,194,249,22,181,12,195,194,192,249,247,22, +186,5,194,11,248,80,158,35,45,9,27,247,22,142,13,249,80,158,37,46,28, 23,195,2,27,248,22,152,7,6,11,11,80,76,84,67,79,76,76,69,67,84, -83,28,192,192,6,0,0,6,0,0,27,28,23,196,1,250,22,179,12,248,22, -136,13,69,97,100,100,111,110,45,100,105,114,247,22,150,7,6,8,8,99,111, +83,28,192,192,6,0,0,6,0,0,27,28,23,196,1,250,22,181,12,248,22, +138,13,69,97,100,100,111,110,45,100,105,114,247,22,150,7,6,8,8,99,111, 108,108,101,99,116,115,11,27,248,80,159,40,52,35,249,22,77,23,202,1,248, -22,73,248,22,136,13,72,99,111,108,108,101,99,116,115,45,100,105,114,28,23, +22,73,248,22,138,13,72,99,111,108,108,101,99,116,115,45,100,105,114,28,23, 194,2,249,22,63,23,196,1,23,195,1,192,32,49,89,162,8,44,37,49,2, -19,222,33,50,27,249,22,147,13,23,197,2,23,198,2,28,23,193,2,87,94, +19,222,33,50,27,249,22,149,13,23,197,2,23,198,2,28,23,193,2,87,94, 23,196,1,27,248,22,88,23,195,2,27,250,2,49,23,199,2,23,200,1,248, 22,97,23,199,1,28,249,22,129,7,23,196,2,2,28,249,22,77,197,194,87, -94,23,196,1,249,22,63,248,22,170,12,23,197,1,194,87,95,23,195,1,23, +94,23,196,1,249,22,63,248,22,172,12,23,197,1,194,87,95,23,195,1,23, 193,1,28,249,22,129,7,23,198,2,2,28,249,22,77,195,9,87,94,23,194, -1,249,22,63,248,22,170,12,23,199,1,9,87,95,28,28,248,22,187,6,194, +1,249,22,63,248,22,172,12,23,199,1,9,87,95,28,28,248,22,187,6,194, 10,248,22,135,6,194,12,250,22,170,8,2,14,6,21,21,98,121,116,101,32, 115,116,114,105,110,103,32,111,114,32,115,116,114,105,110,103,196,28,28,248,22, -72,195,249,22,4,22,161,12,196,11,12,250,22,170,8,2,14,6,13,13,108, +72,195,249,22,4,22,163,12,196,11,12,250,22,170,8,2,14,6,13,13,108, 105,115,116,32,111,102,32,112,97,116,104,115,197,250,2,49,197,195,28,248,22, 135,6,197,248,22,146,7,197,196,32,52,89,162,8,44,38,56,2,19,222,33, 55,32,53,89,162,8,44,37,53,70,102,111,117,110,100,45,101,120,101,99,222, -33,54,28,23,193,2,91,159,37,11,90,161,37,34,11,248,22,182,12,23,199, -2,87,95,23,195,1,23,194,1,27,28,23,198,2,27,248,22,187,12,23,201, -2,28,249,22,142,8,23,195,2,23,202,2,11,28,248,22,183,12,23,194,2, -250,2,53,23,201,2,23,202,2,249,22,179,12,23,200,2,23,198,1,250,2, +33,54,28,23,193,2,91,159,37,11,90,161,37,34,11,248,22,184,12,23,199, +2,87,95,23,195,1,23,194,1,27,28,23,198,2,27,248,22,189,12,23,201, +2,28,249,22,142,8,23,195,2,23,202,2,11,28,248,22,185,12,23,194,2, +250,2,53,23,201,2,23,202,2,249,22,181,12,23,200,2,23,198,1,250,2, 53,23,201,2,23,202,2,23,196,1,11,28,23,193,2,192,87,94,23,193,1, -27,28,248,22,161,12,23,196,2,27,249,22,179,12,23,198,2,23,201,2,28, -28,248,22,174,12,193,10,248,22,173,12,193,192,11,11,28,23,193,2,192,87, -94,23,193,1,28,23,199,2,11,27,248,22,187,12,23,202,2,28,249,22,142, -8,23,195,2,23,203,1,11,28,248,22,183,12,23,194,2,250,2,53,23,202, -1,23,203,1,249,22,179,12,23,201,1,23,198,1,250,2,53,201,202,195,194, -28,248,22,71,23,197,2,11,27,248,22,186,12,248,22,64,23,199,2,27,249, -22,179,12,23,196,1,23,197,2,28,248,22,173,12,23,194,2,250,2,53,198, +27,28,248,22,163,12,23,196,2,27,249,22,181,12,23,198,2,23,201,2,28, +28,248,22,176,12,193,10,248,22,175,12,193,192,11,11,28,23,193,2,192,87, +94,23,193,1,28,23,199,2,11,27,248,22,189,12,23,202,2,28,249,22,142, +8,23,195,2,23,203,1,11,28,248,22,185,12,23,194,2,250,2,53,23,202, +1,23,203,1,249,22,181,12,23,201,1,23,198,1,250,2,53,201,202,195,194, +28,248,22,71,23,197,2,11,27,248,22,188,12,248,22,64,23,199,2,27,249, +22,181,12,23,196,1,23,197,2,28,248,22,175,12,23,194,2,250,2,53,198, 199,195,87,94,23,193,1,27,248,22,65,23,200,1,28,248,22,71,23,194,2, -11,27,248,22,186,12,248,22,64,23,196,2,27,249,22,179,12,23,196,1,23, -200,2,28,248,22,173,12,23,194,2,250,2,53,201,202,195,87,94,23,193,1, -27,248,22,65,23,197,1,28,248,22,71,23,194,2,11,27,248,22,186,12,248, -22,64,195,27,249,22,179,12,23,196,1,202,28,248,22,173,12,193,250,2,53, -204,205,195,251,2,52,204,205,206,248,22,65,199,87,95,28,27,248,22,161,12, +11,27,248,22,188,12,248,22,64,23,196,2,27,249,22,181,12,23,196,1,23, +200,2,28,248,22,175,12,23,194,2,250,2,53,201,202,195,87,94,23,193,1, +27,248,22,65,23,197,1,28,248,22,71,23,194,2,11,27,248,22,188,12,248, +22,64,195,27,249,22,181,12,23,196,1,202,28,248,22,175,12,193,250,2,53, +204,205,195,251,2,52,204,205,206,248,22,65,199,87,95,28,27,248,22,163,12, 23,196,2,28,23,193,2,192,87,94,23,193,1,28,248,22,135,6,23,196,2, -27,248,22,183,12,23,197,2,28,23,193,2,192,87,94,23,193,1,248,22,184, +27,248,22,185,12,23,197,2,28,23,193,2,192,87,94,23,193,1,248,22,186, 12,23,197,2,11,12,250,22,170,8,2,15,6,25,25,112,97,116,104,32,111, 114,32,115,116,114,105,110,103,32,40,115,97,110,115,32,110,117,108,41,23,197, -2,28,28,23,195,2,28,27,248,22,161,12,23,197,2,28,23,193,2,192,87, -94,23,193,1,28,248,22,135,6,23,197,2,27,248,22,183,12,23,198,2,28, -23,193,2,192,87,94,23,193,1,248,22,184,12,23,198,2,11,248,22,183,12, +2,28,28,23,195,2,28,27,248,22,163,12,23,197,2,28,23,193,2,192,87, +94,23,193,1,28,248,22,135,6,23,197,2,27,248,22,185,12,23,198,2,28, +23,193,2,192,87,94,23,193,1,248,22,186,12,23,198,2,11,248,22,185,12, 23,196,2,11,10,12,250,22,170,8,2,15,6,29,29,35,102,32,111,114,32, 114,101,108,97,116,105,118,101,32,112,97,116,104,32,111,114,32,115,116,114,105, -110,103,23,198,2,28,28,248,22,183,12,23,195,2,91,159,37,11,90,161,37, -34,11,248,22,182,12,23,198,2,249,22,140,8,194,68,114,101,108,97,116,105, +110,103,23,198,2,28,28,248,22,185,12,23,195,2,91,159,37,11,90,161,37, +34,11,248,22,184,12,23,198,2,249,22,140,8,194,68,114,101,108,97,116,105, 118,101,11,27,248,22,152,7,6,4,4,80,65,84,72,251,2,52,23,199,1, 23,200,1,23,201,1,28,23,197,2,27,249,80,158,42,46,23,200,1,9,28, -249,22,140,8,247,22,154,7,2,21,249,22,63,248,22,170,12,5,1,46,23, -195,1,192,9,27,248,22,186,12,23,196,1,28,248,22,173,12,193,250,2,53, +249,22,140,8,247,22,154,7,2,21,249,22,63,248,22,172,12,5,1,46,23, +195,1,192,9,27,248,22,188,12,23,196,1,28,248,22,175,12,193,250,2,53, 198,199,195,11,250,80,158,37,47,196,197,11,250,80,158,37,47,196,11,11,87, 94,249,22,191,5,247,22,168,4,195,248,22,142,5,249,22,153,3,34,249,22, -137,3,197,198,27,248,22,136,13,2,20,27,249,80,158,38,47,23,196,1,11, +137,3,197,198,27,248,22,138,13,2,20,27,249,80,158,38,47,23,196,1,11, 27,27,248,22,156,3,23,199,1,28,192,192,34,27,27,248,22,156,3,23,201, 1,28,192,192,34,27,249,22,185,4,23,198,1,83,158,38,20,96,95,89,162, 8,44,34,46,9,224,4,3,33,59,23,196,1,23,197,1,27,248,22,172,4, @@ -330,7 +330,7 @@ 33,45,80,159,34,43,35,83,158,34,16,2,32,0,89,162,42,35,42,2,12, 222,33,46,80,159,34,44,35,83,158,34,16,2,83,158,37,20,95,95,2,13, 89,162,42,34,41,9,223,0,33,47,89,162,42,35,51,9,223,0,33,48,80, -159,34,45,35,83,158,34,16,2,27,248,22,143,13,248,22,146,7,27,28,249, +159,34,45,35,83,158,34,16,2,27,248,22,145,13,248,22,146,7,27,28,249, 22,140,8,247,22,154,7,2,21,6,1,1,59,6,1,1,58,250,22,183,6, 6,14,14,40,91,94,126,97,93,42,41,126,97,40,46,42,41,23,196,2,23, 196,1,89,162,8,44,36,46,2,14,223,0,33,51,80,159,34,46,35,83,158, @@ -342,12 +342,12 @@ EVAL_ONE_SIZED_STR((char *)expr, 5009); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,54,8,0,0,0,1,0,0,6,0, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,56,8,0,0,0,1,0,0,6,0, 19,0,34,0,48,0,62,0,76,0,111,0,0,0,243,0,0,0,65,113,117, 111,116,101,29,94,2,1,67,35,37,117,116,105,108,115,11,29,94,2,1,69, 35,37,110,101,116,119,111,114,107,11,29,94,2,1,68,35,37,112,97,114,97, 109,122,11,29,94,2,1,68,35,37,101,120,112,111,98,115,11,29,94,2,1, -68,35,37,107,101,114,110,101,108,11,98,10,34,11,8,144,185,97,159,2,2, +68,35,37,107,101,114,110,101,108,11,98,10,34,11,8,168,186,97,159,2,2, 34,34,159,2,3,34,34,159,2,4,34,34,159,2,5,34,34,159,2,6,34, 34,16,0,159,34,20,102,159,34,16,1,20,24,65,98,101,103,105,110,16,0, 83,158,40,20,99,137,69,35,37,98,117,105,108,116,105,110,29,11,11,10,10, @@ -359,7 +359,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 282); } { - static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,54,52,0,0,0,1,0,0,3,0, + static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,9,51,46,57,57,46,48,46,49,56,52,0,0,0,1,0,0,3,0, 14,0,41,0,47,0,60,0,74,0,96,0,122,0,134,0,152,0,172,0,184, 0,200,0,223,0,3,1,8,1,13,1,18,1,23,1,54,1,58,1,66,1, 74,1,82,1,185,1,230,1,253,1,32,2,67,2,101,2,111,2,145,2,155, @@ -382,29 +382,29 @@ 117,108,101,45,110,97,109,101,45,114,101,115,111,108,118,101,114,63,108,105,98, 67,105,103,110,111,114,101,100,249,22,14,195,80,158,36,44,249,80,159,36,47, 35,195,10,27,28,23,195,2,28,249,22,140,8,23,197,2,80,158,37,45,87, -94,23,195,1,80,158,35,46,27,248,22,151,4,23,197,2,28,248,22,161,12, -23,194,2,91,159,37,11,90,161,37,34,11,248,22,182,12,23,197,1,87,95, +94,23,195,1,80,158,35,46,27,248,22,151,4,23,197,2,28,248,22,163,12, +23,194,2,91,159,37,11,90,161,37,34,11,248,22,184,12,23,197,1,87,95, 83,160,36,11,80,158,39,45,198,83,160,36,11,80,158,39,46,192,192,11,11, -28,23,193,2,192,87,94,23,193,1,27,247,22,187,5,28,192,192,247,22,137, +28,23,193,2,192,87,94,23,193,1,27,247,22,187,5,28,192,192,247,22,139, 13,20,14,159,80,158,34,38,250,80,158,37,39,249,22,27,11,80,158,39,38, -22,187,5,28,248,22,161,12,23,198,2,23,197,1,87,94,23,197,1,247,22, -137,13,247,194,250,22,179,12,23,197,1,23,199,1,249,80,158,41,37,23,198, -1,5,3,46,122,111,252,22,179,12,23,199,1,23,201,1,6,6,6,110,97, +22,187,5,28,248,22,163,12,23,198,2,23,197,1,87,94,23,197,1,247,22, +139,13,247,194,250,22,181,12,23,197,1,23,199,1,249,80,158,41,37,23,198, +1,5,3,46,122,111,252,22,181,12,23,199,1,23,201,1,6,6,6,110,97, 116,105,118,101,247,22,155,7,249,80,158,43,37,23,200,1,80,158,43,34,87, -94,23,194,1,27,23,194,1,27,250,22,132,13,196,11,32,0,89,162,8,44, +94,23,194,1,27,23,194,1,27,250,22,134,13,196,11,32,0,89,162,8,44, 34,39,9,222,11,28,192,249,22,63,195,194,11,27,248,23,195,1,23,196,1, -27,250,22,132,13,196,11,32,0,89,162,8,44,34,39,9,222,11,28,192,249, -22,63,195,194,11,249,247,22,142,13,248,22,64,195,195,27,248,23,195,1,23, -196,1,27,250,22,132,13,196,11,32,0,89,162,8,44,34,39,9,222,11,28, +27,250,22,134,13,196,11,32,0,89,162,8,44,34,39,9,222,11,28,192,249, +22,63,195,194,11,249,247,22,144,13,248,22,64,195,195,27,248,23,195,1,23, +196,1,27,250,22,134,13,196,11,32,0,89,162,8,44,34,39,9,222,11,28, 192,249,22,63,195,194,11,249,247,22,185,5,248,22,64,195,195,249,247,22,185, 5,194,195,87,94,28,248,80,158,35,36,23,195,2,12,250,22,170,8,77,108, 111,97,100,47,117,115,101,45,99,111,109,112,105,108,101,100,6,25,25,112,97, 116,104,32,111,114,32,118,97,108,105,100,45,112,97,116,104,32,115,116,114,105, -110,103,23,197,2,91,159,40,11,90,161,35,34,11,28,248,22,185,12,23,201, -2,23,200,1,27,247,22,187,5,28,23,193,2,249,22,186,12,23,203,1,23, -195,1,200,90,161,37,35,11,248,22,182,12,23,194,2,87,94,23,196,1,90, +110,103,23,197,2,91,159,40,11,90,161,35,34,11,28,248,22,187,12,23,201, +2,23,200,1,27,247,22,187,5,28,23,193,2,249,22,188,12,23,203,1,23, +195,1,200,90,161,37,35,11,248,22,184,12,23,194,2,87,94,23,196,1,90, 161,35,38,11,28,249,22,140,8,23,196,2,68,114,101,108,97,116,105,118,101, -87,94,23,194,1,2,17,23,194,1,90,161,35,39,11,247,22,139,13,27,89, +87,94,23,194,1,2,17,23,194,1,90,161,35,39,11,247,22,141,13,27,89, 162,42,35,48,62,122,111,225,7,5,3,33,27,27,83,158,38,20,96,94,89, 162,42,35,50,9,225,8,6,4,33,28,23,197,1,27,249,22,5,89,162,8, 44,35,46,9,223,5,33,29,23,203,2,27,28,23,195,2,27,249,22,5,83, @@ -418,11 +418,11 @@ 193,11,11,11,11,28,192,249,80,159,47,53,35,203,89,162,42,34,44,9,224, 15,2,33,33,249,80,159,47,53,35,203,89,162,42,34,43,9,224,15,7,33, 34,32,36,89,162,8,44,35,53,2,19,222,33,38,0,17,35,114,120,34,94, -40,46,42,63,41,47,40,46,42,41,36,34,27,249,22,147,13,2,37,23,196, +40,46,42,63,41,47,40,46,42,41,36,34,27,249,22,149,13,2,37,23,196, 2,28,23,193,2,87,94,23,194,1,249,22,63,248,22,88,23,196,2,27,248, -22,97,23,197,1,27,249,22,147,13,2,37,23,196,2,28,23,193,2,87,94, +22,97,23,197,1,27,249,22,149,13,2,37,23,196,2,28,23,193,2,87,94, 23,194,1,249,22,63,248,22,88,23,196,2,27,248,22,97,23,197,1,27,249, -22,147,13,2,37,23,196,2,28,23,193,2,87,94,23,194,1,249,22,63,248, +22,149,13,2,37,23,196,2,28,23,193,2,87,94,23,194,1,249,22,63,248, 22,88,23,196,2,248,2,36,248,22,97,23,197,1,248,22,73,194,248,22,73, 194,248,22,73,194,32,39,89,162,42,35,53,2,19,222,33,40,28,248,22,71, 248,22,65,23,195,2,249,22,7,9,248,22,64,195,91,159,36,11,90,161,36, @@ -436,8 +436,8 @@ 39,193,87,95,28,248,22,149,4,195,12,250,22,170,8,2,20,6,20,20,114, 101,115,111,108,118,101,100,45,109,111,100,117,108,101,45,112,97,116,104,197,28, 24,193,2,248,24,194,1,195,87,94,23,193,1,12,27,27,250,22,126,80,158, -40,41,248,22,165,13,247,22,149,11,11,28,23,193,2,192,87,94,23,193,1, -27,247,22,120,87,94,250,22,125,80,158,41,41,248,22,165,13,247,22,149,11, +40,41,248,22,167,13,247,22,151,11,11,28,23,193,2,192,87,94,23,193,1, +27,247,22,120,87,94,250,22,125,80,158,41,41,248,22,167,13,247,22,151,11, 195,192,250,22,125,195,198,66,97,116,116,97,99,104,251,211,197,198,199,10,28, 192,250,22,169,8,11,196,195,248,22,167,8,194,28,249,22,141,6,194,6,1, 1,46,2,17,28,249,22,141,6,194,6,2,2,46,46,62,117,112,192,28,249, @@ -445,70 +445,70 @@ 200,2,23,196,1,251,22,167,8,2,20,6,26,26,99,121,99,108,101,32,105, 110,32,108,111,97,100,105,110,103,32,97,116,32,126,101,58,32,126,101,23,200, 1,249,22,2,22,65,248,22,78,249,22,63,23,206,1,23,202,1,12,12,247, -192,20,14,159,80,158,38,43,249,22,63,247,22,149,11,23,197,1,20,14,159, +192,20,14,159,80,158,38,43,249,22,63,247,22,151,11,23,197,1,20,14,159, 80,158,38,38,250,80,158,41,39,249,22,27,11,80,158,43,38,22,133,4,23, -196,1,249,247,22,186,5,23,198,1,248,22,52,248,22,165,12,23,198,1,87, -94,28,28,248,22,161,12,23,197,2,10,248,22,154,4,23,197,2,12,28,23, +196,1,249,247,22,186,5,23,198,1,248,22,52,248,22,167,12,23,198,1,87, +94,28,28,248,22,163,12,23,197,2,10,248,22,154,4,23,197,2,12,28,23, 198,2,250,22,169,8,11,6,15,15,98,97,100,32,109,111,100,117,108,101,32, 112,97,116,104,23,201,2,250,22,170,8,2,20,6,19,19,109,111,100,117,108, 101,45,112,97,116,104,32,111,114,32,112,97,116,104,23,199,2,28,28,248,22, 61,23,197,2,249,22,140,8,248,22,64,23,199,2,2,4,11,248,22,150,4, 248,22,88,197,28,28,248,22,61,23,197,2,249,22,140,8,248,22,64,23,199, 2,66,112,108,97,110,101,116,11,87,94,28,207,12,20,14,159,80,158,36,38, -250,80,158,39,39,249,22,27,11,80,158,41,38,22,149,11,23,197,1,90,161, +250,80,158,39,39,249,22,27,11,80,158,41,38,22,151,11,23,197,1,90,161, 35,34,10,249,22,134,4,21,94,2,21,6,18,18,112,108,97,110,101,116,47, 114,101,115,111,108,118,101,114,46,115,115,1,27,112,108,97,110,101,116,45,109, 111,100,117,108,101,45,110,97,109,101,45,114,101,115,111,108,118,101,114,12,251, 211,199,200,201,202,87,94,23,193,1,27,89,162,42,35,44,79,115,104,111,119, 45,99,111,108,108,101,99,116,105,111,110,45,101,114,114,223,6,33,44,27,28, 248,22,51,23,199,2,27,250,22,126,80,158,42,42,249,22,63,23,204,2,247, -22,138,13,11,28,23,193,2,192,87,94,23,193,1,91,159,36,11,90,161,36, +22,140,13,11,28,23,193,2,192,87,94,23,193,1,91,159,36,11,90,161,36, 34,11,249,80,159,43,47,35,248,22,54,23,204,2,11,27,251,80,158,46,49, 2,20,23,202,1,28,248,22,71,23,199,2,23,199,2,248,22,64,23,199,2, -28,248,22,71,23,199,2,9,248,22,65,23,199,2,249,22,179,12,23,195,1, +28,248,22,71,23,199,2,9,248,22,65,23,199,2,249,22,181,12,23,195,1, 28,248,22,71,23,197,1,87,94,23,197,1,6,7,7,109,97,105,110,46,115, 115,249,22,158,6,23,199,1,6,3,3,46,115,115,28,248,22,135,6,23,199, 2,87,94,23,194,1,27,248,80,159,40,54,35,23,201,2,27,250,22,126,80, 158,43,42,249,22,63,23,205,2,23,199,2,11,28,23,193,2,192,87,94,23, 193,1,91,159,36,11,90,161,36,34,11,249,80,159,44,47,35,23,204,2,11, -250,22,1,22,179,12,23,199,1,249,22,77,249,22,2,32,0,89,162,8,44, -35,42,9,222,33,45,23,200,1,248,22,73,23,200,1,28,248,22,161,12,23, -199,2,87,94,23,194,1,28,248,22,184,12,23,199,2,23,198,2,248,22,73, +250,22,1,22,181,12,23,199,1,249,22,77,249,22,2,32,0,89,162,8,44, +35,42,9,222,33,45,23,200,1,248,22,73,23,200,1,28,248,22,163,12,23, +199,2,87,94,23,194,1,28,248,22,186,12,23,199,2,23,198,2,248,22,73, 6,26,26,32,40,97,32,112,97,116,104,32,109,117,115,116,32,98,101,32,97, 98,115,111,108,117,116,101,41,28,249,22,140,8,248,22,64,23,201,2,2,21, -27,250,22,126,80,158,42,42,249,22,63,23,204,2,247,22,138,13,11,28,23, +27,250,22,126,80,158,42,42,249,22,63,23,204,2,247,22,140,13,11,28,23, 193,2,192,87,94,23,193,1,91,159,37,11,90,161,36,34,11,249,80,159,44, 47,35,248,22,88,23,205,2,11,90,161,35,36,11,28,248,22,71,248,22,90, -23,204,2,28,248,22,71,23,194,2,249,22,149,13,0,8,35,114,120,34,91, +23,204,2,28,248,22,71,23,194,2,249,22,151,13,0,8,35,114,120,34,91, 46,93,34,23,196,2,11,10,27,27,28,23,197,2,249,22,77,28,248,22,71, 248,22,90,23,208,2,21,93,6,5,5,109,122,108,105,98,249,22,1,22,77, 249,22,2,80,159,50,55,35,248,22,90,23,211,2,23,197,2,28,248,22,71, 23,196,2,248,22,73,23,197,2,23,195,2,251,80,158,48,49,2,20,23,204, -1,248,22,64,23,198,2,248,22,65,23,198,1,249,22,179,12,23,195,1,28, +1,248,22,64,23,198,2,248,22,65,23,198,1,249,22,181,12,23,195,1,28, 23,198,1,87,94,23,196,1,23,197,1,28,248,22,71,23,197,1,87,94,23, -197,1,6,7,7,109,97,105,110,46,115,115,28,249,22,149,13,0,8,35,114, +197,1,6,7,7,109,97,105,110,46,115,115,28,249,22,151,13,0,8,35,114, 120,34,91,46,93,34,23,199,2,23,197,1,249,22,158,6,23,199,1,6,3, 3,46,115,115,28,249,22,140,8,248,22,64,23,201,2,64,102,105,108,101,249, -22,186,12,248,22,88,23,201,2,248,80,159,41,54,35,23,202,2,12,87,94, -28,28,248,22,161,12,23,194,2,10,248,22,157,7,23,194,2,87,94,23,200, +22,188,12,248,22,88,23,201,2,248,80,159,41,54,35,23,202,2,12,87,94, +28,28,248,22,163,12,23,194,2,10,248,22,157,7,23,194,2,87,94,23,200, 1,12,28,23,200,2,250,22,169,8,67,114,101,113,117,105,114,101,249,22,183, 6,6,17,17,98,97,100,32,109,111,100,117,108,101,32,112,97,116,104,126,97, 28,23,198,2,248,22,64,23,199,2,6,0,0,23,203,1,87,94,23,200,1, 250,22,170,8,2,20,249,22,183,6,6,13,13,109,111,100,117,108,101,32,112, 97,116,104,126,97,28,23,198,2,248,22,64,23,199,2,6,0,0,23,201,2, -27,28,248,22,157,7,23,195,2,249,22,162,7,23,196,2,34,249,22,188,12, -248,22,189,12,23,197,2,11,27,28,248,22,157,7,23,196,2,249,22,162,7, +27,28,248,22,157,7,23,195,2,249,22,162,7,23,196,2,34,249,22,190,12, +248,22,191,12,23,197,2,11,27,28,248,22,157,7,23,196,2,249,22,162,7, 23,197,2,35,248,80,158,41,50,23,195,2,91,159,37,11,90,161,37,34,11, 28,248,22,157,7,23,199,2,250,22,7,2,22,249,22,162,7,23,203,2,36, -2,22,248,22,182,12,23,198,2,87,95,23,195,1,23,193,1,27,28,248,22, +2,22,248,22,184,12,23,198,2,87,95,23,195,1,23,193,1,27,28,248,22, 157,7,23,200,2,249,22,162,7,23,201,2,37,249,80,158,46,51,23,197,2, 5,0,27,28,248,22,157,7,23,201,2,249,22,162,7,23,202,2,38,248,22, -150,4,23,200,2,27,27,250,22,126,80,158,50,41,248,22,165,13,247,22,149, +150,4,23,200,2,27,27,250,22,126,80,158,50,41,248,22,167,13,247,22,151, 11,11,28,23,193,2,192,87,94,23,193,1,27,247,22,120,87,94,250,22,125, -80,158,51,41,248,22,165,13,247,22,149,11,195,192,87,95,28,23,209,1,27, +80,158,51,41,248,22,167,13,247,22,151,11,195,192,87,95,28,23,209,1,27, 250,22,126,23,197,2,197,11,28,23,193,1,12,87,95,27,27,28,248,22,17, 80,158,50,44,80,158,49,44,247,22,19,250,22,25,248,22,23,23,197,2,80, -158,52,43,23,196,1,27,247,22,149,11,249,22,3,83,158,38,20,96,94,89, +158,52,43,23,196,1,27,247,22,151,11,249,22,3,83,158,38,20,96,94,89, 162,8,44,35,53,9,226,12,11,2,3,33,46,23,195,1,23,196,1,248,28, 248,22,17,80,158,49,44,32,0,89,162,42,35,40,9,222,33,47,80,159,48, 56,35,89,162,42,34,49,9,227,14,9,8,4,3,33,48,250,22,125,23,197, @@ -516,12 +516,12 @@ 2,28,192,192,28,248,22,61,23,208,2,249,22,140,8,248,22,64,23,210,2, 2,21,11,250,22,125,80,158,49,42,28,248,22,135,6,23,210,2,249,22,63, 23,211,1,248,80,159,52,54,35,23,213,1,87,94,23,210,1,249,22,63,23, -211,1,247,22,138,13,252,22,159,7,23,208,1,23,207,1,23,205,1,23,203, +211,1,247,22,140,13,252,22,159,7,23,208,1,23,207,1,23,205,1,23,203, 1,201,12,193,91,159,36,10,90,161,35,34,10,11,90,161,35,35,10,83,158, 37,20,95,96,2,20,89,162,8,44,35,49,9,224,2,0,33,42,89,162,42, 37,47,9,223,1,33,43,89,162,42,38,8,30,9,225,2,3,0,33,49,208, -87,95,248,22,132,4,248,80,158,36,48,247,22,149,11,248,22,186,5,80,158, -35,35,248,22,135,12,80,159,35,40,35,159,34,20,102,159,34,16,1,20,24, +87,95,248,22,132,4,248,80,158,36,48,247,22,151,11,248,22,186,5,80,158, +35,35,248,22,137,12,80,159,35,40,35,159,34,20,102,159,34,16,1,20,24, 65,98,101,103,105,110,16,0,83,158,40,20,99,137,66,35,37,98,111,111,116, 2,1,11,10,10,36,80,158,34,34,20,102,159,38,16,19,30,2,1,2,2, 193,30,2,1,2,3,193,30,2,5,72,112,97,116,104,45,115,116,114,105,110, diff --git a/src/mzscheme/src/mzmark.c b/src/mzscheme/src/mzmark.c index f71e5acc46..43117e0215 100644 --- a/src/mzscheme/src/mzmark.c +++ b/src/mzscheme/src/mzmark.c @@ -4382,6 +4382,7 @@ static int mark_struct_type_val_MARK(void *p) { gcMARK(t->inspector); gcMARK(t->accessor); gcMARK(t->mutator); + gcMARK(t->prefab_key); gcMARK(t->uninit_val); gcMARK(t->props); gcMARK(t->proc_attr); @@ -4404,6 +4405,7 @@ static int mark_struct_type_val_FIXUP(void *p) { gcFIXUP(t->inspector); gcFIXUP(t->accessor); gcFIXUP(t->mutator); + gcFIXUP(t->prefab_key); gcFIXUP(t->uninit_val); gcFIXUP(t->props); gcFIXUP(t->proc_attr); diff --git a/src/mzscheme/src/mzmarksrc.c b/src/mzscheme/src/mzmarksrc.c index 0d801c6910..289c29c20c 100644 --- a/src/mzscheme/src/mzmarksrc.c +++ b/src/mzscheme/src/mzmarksrc.c @@ -1783,6 +1783,7 @@ mark_struct_type_val { gcMARK(t->inspector); gcMARK(t->accessor); gcMARK(t->mutator); + gcMARK(t->prefab_key); gcMARK(t->uninit_val); gcMARK(t->props); gcMARK(t->proc_attr); diff --git a/src/mzscheme/src/print.c b/src/mzscheme/src/print.c index cf91c486fe..87348cec4b 100644 --- a/src/mzscheme/src/print.c +++ b/src/mzscheme/src/print.c @@ -88,7 +88,8 @@ static void print_pair(Scheme_Object *pair, int notdisplay, int compact, static void print_vector(Scheme_Object *vec, int notdisplay, int compact, Scheme_Hash_Table *ht, Scheme_Marshal_Tables *mt, - PrintParams *pp); + PrintParams *pp, + int as_struct); static void print_char(Scheme_Object *chobj, int notdisplay, PrintParams *pp); static char *print_to_string(Scheme_Object *obj, long * volatile len, int write, Scheme_Object *port, long maxl, int check_honu); @@ -1767,7 +1768,7 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht, } else if (SCHEME_VECTORP(obj)) { - print_vector(obj, notdisplay, compact, ht, mt, pp); + print_vector(obj, notdisplay, compact, ht, mt, pp, 0); closed = 1; } else if ((compact || pp->print_box) && SCHEME_BOXP(obj)) @@ -1868,8 +1869,14 @@ print(Scheme_Object *obj, int notdisplay, int compact, Scheme_Hash_Table *ht, pb = pp->print_struct && PRINTABLE_STRUCT(obj, pp); if (pb) { - obj = scheme_struct_to_vector(obj, NULL, pp->inspector); - closed = print(obj, notdisplay, compact, ht, mt, pp); + Scheme_Object *vec, *prefab; + prefab = ((Scheme_Structure *)obj)->stype->prefab_key; + vec = scheme_struct_to_vector(obj, NULL, pp->inspector); + if (prefab) { + SCHEME_VEC_ELS(vec)[0] = SCHEME_CDR(prefab); + } + print_vector(vec, notdisplay, compact, ht, mt, pp, !!prefab); + closed = 1; } else { Scheme_Object *src; @@ -2968,7 +2975,8 @@ static void print_vector(Scheme_Object *vec, int notdisplay, int compact, Scheme_Hash_Table *ht, Scheme_Marshal_Tables *mt, - PrintParams *pp) + PrintParams *pp, + int as_struct) { int i, size, common = 0; Scheme_Object **elems; @@ -2986,7 +2994,9 @@ print_vector(Scheme_Object *vec, int notdisplay, int compact, } elems = NULL; /* Precise GC: because VEC_ELS is not aligned */ - if (notdisplay && pp->print_vec_shorthand) { + if (as_struct) { + print_utf8_string(pp, "#s(", 0, 3); + } else if (notdisplay && pp->print_vec_shorthand) { if (size == 0) { if (pp->honu_mode) print_utf8_string(pp, "vectorN(0", 0, 7); diff --git a/src/mzscheme/src/read.c b/src/mzscheme/src/read.c index d4eeba3083..cce181f4e9 100644 --- a/src/mzscheme/src/read.c +++ b/src/mzscheme/src/read.c @@ -1217,28 +1217,86 @@ read_inner_inner(Scheme_Object *port, Scheme_Object *stxsrc, Scheme_Hash_Table * break; case 's': case 'S': - ch = scheme_getc_special_ok(port); - if ((ch == 'x') || (ch == 'X')) { - ReadParams params_copy; - Scheme_Object *v; + { + int orig_ch = ch, effective_ch; + ch = scheme_getc_special_ok(port); + if (NOT_EOF_OR_SPECIAL(ch)) + effective_ch = readtable_effective_char(params->table, ch); + else + effective_ch = ch; + if ((orig_ch == 's') + && ((effective_ch == '(') + || (effective_ch == '[' && params->square_brackets_are_parens) + || (effective_ch == '{' && params->curly_braces_are_parens))) { + Scheme_Object *v; + Scheme_Struct_Type *st; + + if (effective_ch == '(') + ch = ')'; + else if (effective_ch == '[') + ch = ']'; + else if (effective_ch == '{') + ch = '}'; - memcpy(¶ms_copy, params, sizeof(ReadParams)); - params_copy.honu_mode = 0; + v = read_vector(port, stxsrc, line, col, pos, ch, -1, NULL, ht, indentation, params); + if (stxsrc) + v = SCHEME_STX_VAL(v); - v = read_inner(port, stxsrc, ht, indentation, ¶ms_copy, 0); + if (SCHEME_VEC_SIZE(v)) { + Scheme_Object *key; + key = SCHEME_VEC_ELS(v)[0]; + if (stxsrc) + key = scheme_syntax_to_datum(key, 0, NULL); + st = scheme_lookup_prefab_type(key, SCHEME_VEC_SIZE(v) - 1); + } else + st = NULL; - if (SCHEME_EOFP(v)) { - scheme_read_err(port, stxsrc, line, col, pos, 2, EOF, indentation, - "read: end-of-file after #sx"); - return NULL; - } + if (!st || (st->num_slots != (SCHEME_VEC_SIZE(v) - 1))) { + scheme_read_err(port, stxsrc, line, col, pos, SPAN(port, pos), EOF, indentation, + (SCHEME_VEC_SIZE(v) + ? (st + ? ("read: mismatch between structure description" + " and number of provided field values in `#s' form") + : "read: invalid structure description in `#s' form") + : "read: missing structure description in `#s' form")); + return NULL; + } - return v; - } else { - scheme_read_err(port, stxsrc, line, col, pos, SPAN(port, pos), ch, indentation, - "read: expected `x' after `#s'"); - return NULL; - } + if (stxsrc && !(MZ_OPT_HASH_KEY(&st->iso) & STRUCT_TYPE_ALL_IMMUTABLE)) { + scheme_read_err(port, stxsrc, line, col, pos, SPAN(port, pos), EOF, indentation, + "read: cannot read mutable `#s' form as syntax"); + } + + v = scheme_make_prefab_struct_instance(st, v); + + if (stxsrc) + v = scheme_make_stx_w_offset(v, line, col, pos, SPAN(port, pos), stxsrc, STX_SRCTAG); + + return v; + } else if ((ch == 'x') || (ch == 'X')) { + ReadParams params_copy; + Scheme_Object *v; + + memcpy(¶ms_copy, params, sizeof(ReadParams)); + params_copy.honu_mode = 0; + + v = read_inner(port, stxsrc, ht, indentation, ¶ms_copy, 0); + + if (SCHEME_EOFP(v)) { + scheme_read_err(port, stxsrc, line, col, pos, 2, EOF, indentation, + "read: end-of-file after #sx"); + return NULL; + } + + return v; + } else { + scheme_read_err(port, stxsrc, line, col, pos, SPAN(port, pos), ch, indentation, + "read: expected `x'%s after `#%c'", + (orig_ch == 's' ? "or `('" : ""), + orig_ch); + return NULL; + } + } case 'X': case 'x': if (!params->honu_mode) { @@ -1546,7 +1604,7 @@ read_inner_inner(Scheme_Object *port, Scheme_Object *stxsrc, Scheme_Hash_Table * int effective_ch; effective_ch = readtable_effective_char(table, ch); if (!(effective_ch == '(') - && ! (effective_ch == '[' && params->square_brackets_are_parens) + && !(effective_ch == '[' && params->square_brackets_are_parens) && !(effective_ch == '{' && params->curly_braces_are_parens)) failed = 1; } else @@ -2122,6 +2180,33 @@ static Scheme_Object *resolve_references(Scheme_Object *obj, scheme_hash_set(t2, key, val); } } + } else if (SCHEME_STRUCTP(obj)) { + Scheme_Structure *s = (Scheme_Structure *)obj; + if (s->stype->prefab_key) { + /* prefab */ + int c, i, diff; + Scheme_Object *prev_v, *v; + + if (clone) { + result = scheme_clone_prefab_struct_instance(s); + } + scheme_hash_set(dht, obj, result); + + c = s->stype->num_slots; + diff = 0; + for (i = 0; i < c; i++) { + prev_v = s->slots[i]; + v = resolve_references(prev_v, port, top, dht, tht, clone, tail_depth + 1); + if (!SAME_OBJ(prev_v, v)) + diff = 1; + ((Scheme_Structure *)result)->slots[i] = v; + } + + if (clone && !diff) { + result = obj; + scheme_hash_set(dht, obj, result); + } + } } return result; diff --git a/src/mzscheme/src/schminc.h b/src/mzscheme/src/schminc.h index 599df299a3..7302a8708b 100644 --- a/src/mzscheme/src/schminc.h +++ b/src/mzscheme/src/schminc.h @@ -13,7 +13,7 @@ #define USE_COMPILED_STARTUP 1 -#define EXPECTED_PRIM_COUNT 897 +#define EXPECTED_PRIM_COUNT 899 #ifdef MZSCHEME_SOMETHING_OMITTED # undef USE_COMPILED_STARTUP diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index 7db2610e9b..f5bd31aa78 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -499,14 +499,16 @@ typedef struct Scheme_Struct_Property { int scheme_inspector_sees_part(Scheme_Object *s, Scheme_Object *insp, int pos); typedef struct Scheme_Struct_Type { - Scheme_Object so; /* scheme_structure_type or scheme_proc_struct_type */ - mzshort num_slots, num_islots; + Scheme_Inclhash_Object iso; /* scheme_structure_type or scheme_proc_struct_type */ + mzshort num_slots; /* initialized + auto + parent-initialized + parent-auto */ + mzshort num_islots; /* initialized + parent-initialized */ mzshort name_pos; Scheme_Object *name; Scheme_Object *inspector; Scheme_Object *accessor, *mutator; + Scheme_Object *prefab_key; Scheme_Object *uninit_val; @@ -521,6 +523,8 @@ typedef struct Scheme_Struct_Type { struct Scheme_Struct_Type *parent_types[1]; } Scheme_Struct_Type; +#define STRUCT_TYPE_ALL_IMMUTABLE 0x1 + typedef struct Scheme_Structure { Scheme_Object so; @@ -570,6 +574,11 @@ Scheme_Object *scheme_is_writable_struct(Scheme_Object *s); extern Scheme_Object *scheme_source_property; +Scheme_Struct_Type *scheme_lookup_prefab_type(Scheme_Object *key, int field_count); +Scheme_Object *scheme_make_prefab_struct_instance(Scheme_Struct_Type *stype, + Scheme_Object *vec); +Scheme_Object *scheme_clone_prefab_struct_instance(Scheme_Structure *s); + /*========================================================================*/ /* syntax objects */ /*========================================================================*/ diff --git a/src/mzscheme/src/schvers.h b/src/mzscheme/src/schvers.h index 832e3e7c4d..3e36aac62d 100644 --- a/src/mzscheme/src/schvers.h +++ b/src/mzscheme/src/schvers.h @@ -13,12 +13,12 @@ consistently.) */ -#define MZSCHEME_VERSION "3.99.0.17" +#define MZSCHEME_VERSION "3.99.0.18" #define MZSCHEME_VERSION_X 3 #define MZSCHEME_VERSION_Y 99 #define MZSCHEME_VERSION_Z 0 -#define MZSCHEME_VERSION_W 17 +#define MZSCHEME_VERSION_W 18 #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W) diff --git a/src/mzscheme/src/struct.c b/src/mzscheme/src/struct.c index 2d7bcd89e7..4427b3565a 100644 --- a/src/mzscheme/src/struct.c +++ b/src/mzscheme/src/struct.c @@ -88,6 +88,8 @@ static Scheme_Object *struct_type_info(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_type_pred(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_type_constr(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_to_vector(int argc, Scheme_Object *argv[]); +static Scheme_Object *prefab_struct_key(int argc, Scheme_Object *argv[]); +static Scheme_Object *make_prefab_struct(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_setter_p(int argc, Scheme_Object *argv[]); static Scheme_Object *struct_getter_p(int argc, Scheme_Object *argv[]); @@ -134,6 +136,9 @@ static Scheme_Object *procedure_extract_target(int argc, Scheme_Object **argv); static void register_traversers(void); #endif +static Scheme_Bucket_Table *prefab_table; +static Scheme_Object *make_prefab_key(Scheme_Struct_Type *type); + #define cons scheme_make_pair #define icons scheme_make_pair #define _intern scheme_intern_symbol @@ -141,7 +146,7 @@ static void register_traversers(void); #define BUILTIN_STRUCT_FLAGS SCHEME_STRUCT_EXPTIME | SCHEME_STRUCT_NO_SET #define LOC_STRUCT_FLAGS BUILTIN_STRUCT_FLAGS | SCHEME_STRUCT_NO_SET -static Scheme_Object *ellipses_symbol; +static Scheme_Object *ellipses_symbol, *prefab_symbol; #define TYPE_NAME(base, blen) make_name("struct:", base, blen, "", NULL, 0, "", 1) #define CSTR_NAME(base, blen) make_name("make-", base, blen, "", NULL, 0, "", 1) @@ -450,6 +455,16 @@ scheme_init_struct (Scheme_Env *env) "struct->vector", 1, 2), env); + scheme_add_global_constant("prefab-struct-key", + scheme_make_prim_w_arity(prefab_struct_key, + "prefab-struct-key", + 1, 1), + env); + scheme_add_global_constant("make-prefab-struct", + scheme_make_prim_w_arity(make_prefab_struct, + "make-prefab-struct", + 1, -1), + env); /*** Predicates ****/ @@ -525,6 +540,9 @@ scheme_init_struct (Scheme_Env *env) REGISTER_SO(ellipses_symbol); ellipses_symbol = scheme_intern_symbol("..."); + REGISTER_SO(prefab_symbol); + prefab_symbol = scheme_intern_symbol("prefab"); + REGISTER_SO(scheme_source_property); { Scheme_Object *guard; @@ -1226,6 +1244,41 @@ scheme_make_struct_instance(Scheme_Object *_stype, int argc, Scheme_Object **arg return (Scheme_Object *)inst; } +Scheme_Object *scheme_make_prefab_struct_instance(Scheme_Struct_Type *stype, + Scheme_Object *vec) +{ + Scheme_Structure *inst; + int i, c; + + c = stype->num_slots; + inst = (Scheme_Structure *) + scheme_malloc_tagged(sizeof(Scheme_Structure) + + ((c - 1) * sizeof(Scheme_Object *))); + + inst->so.type = scheme_structure_type; + inst->stype = stype; + + for (i = 0; i < c; i++) { + inst->slots[i] = SCHEME_VEC_ELS(vec)[i + 1]; + } + + return (Scheme_Object *)inst; +} + +Scheme_Object *scheme_clone_prefab_struct_instance(Scheme_Structure *s) +{ + Scheme_Structure *inst; + int c, sz; + + c = s->stype->num_slots; + sz = (sizeof(Scheme_Structure) + + ((c - 1) * sizeof(Scheme_Object *))); + inst = (Scheme_Structure *)scheme_malloc_tagged(sz); + memcpy(inst, s, sz); + + return (Scheme_Object *)inst; +} + static Scheme_Object * make_struct_instance(int argc, Scheme_Object **args, Scheme_Object *prim) { @@ -1689,6 +1742,42 @@ static Scheme_Object *struct_to_vector(int argc, Scheme_Object *argv[]) scheme_get_param(scheme_current_config(), MZCONFIG_INSPECTOR)); } +static Scheme_Object *prefab_struct_key(int argc, Scheme_Object *argv[]) +{ + Scheme_Structure *s = (Scheme_Structure *)argv[0]; + + if (SCHEME_STRUCTP(argv[0]) + && s->stype->prefab_key) + return SCHEME_CDR(s->stype->prefab_key); + + return scheme_false; +} + +static Scheme_Object *make_prefab_struct(int argc, Scheme_Object *argv[]) +{ + Scheme_Struct_Type *stype; + Scheme_Object *vec; + int i; + + stype = scheme_lookup_prefab_type(argv[0], argc - 1); + + if (!stype) + scheme_wrong_type("make-prefab-struct", "prefab key", 0, argc, argv); + + if (stype->num_slots != (argc - 1)) { + scheme_arg_mismatch("make-struct-type", + "mismatch between argument count and prefab key: ", + argv[0]); + } + + vec = scheme_make_vector(argc, 0); + for (i = 0; i < argc ; i++) { + SCHEME_VEC_ELS(vec)[i] = argv[i]; + } + + return scheme_make_prefab_struct_instance(stype, vec); +} + int scheme_inspector_sees_part(Scheme_Object *s, Scheme_Object *insp, int pos) /* pos == -1 => sees any part pos == -2 => sees all parts */ @@ -2524,7 +2613,7 @@ static Scheme_Object *_make_struct_type(Scheme_Object *basesym, const char *base /* defeats optimizer bug in gcc 2.7.2.3: */ depth = parent_type ? (1 + parent_type->name_pos) : 0; - struct_type->so.type = scheme_struct_type_type; + struct_type->iso.so.type = scheme_struct_type_type; struct_type->name_pos = depth; struct_type->parent_types[depth] = struct_type; @@ -2558,11 +2647,13 @@ static Scheme_Object *_make_struct_type(Scheme_Object *basesym, const char *base "too many fields for struct-type; maximum total field count is 32768"); return NULL; } - + if (!inspector) { - if (parent_type) + if (parent_type) { inspector = parent_type->inspector; - else { + if (SCHEME_SYMBOLP(inspector)) + inspector = scheme_false; + } else { inspector = scheme_get_param(scheme_current_config(), MZCONFIG_INSPECTOR); } } @@ -2875,9 +2966,53 @@ Scheme_Object *scheme_make_struct_type_from_string(const char *base, guard); } +Scheme_Struct_Type *hash_prefab(Scheme_Struct_Type *type) +{ + Scheme_Object *k, *v; + + if (!prefab_table) { + REGISTER_SO(prefab_table); + prefab_table = scheme_make_weak_equal_table(); + } + + k = make_prefab_key(type); + type->prefab_key = k; + + v = scheme_lookup_in_table(prefab_table, (const char *)k); + + if (v) + v = SCHEME_WEAK_BOX_VAL(v); + + if (v) { + type = (Scheme_Struct_Type *)v; + } else { + /* Check all immutable */ + if (type->immutables) { + if (!type->name_pos + || MZ_OPT_HASH_KEY(&type->parent_types[type->name_pos - 1]->iso) & STRUCT_TYPE_ALL_IMMUTABLE) { + int i, size; + size = type->num_islots; + if (type->name_pos) + size -= type->parent_types[type->name_pos - 1]->num_islots; + for (i = 0; i < size; i++) { + if (!type->immutables[i]) + break; + } + if (i == size) + MZ_OPT_HASH_KEY(&type->iso) |= STRUCT_TYPE_ALL_IMMUTABLE; + } + } + + v = scheme_make_weak_box((Scheme_Object *)type); + scheme_add_to_table(prefab_table, (const char *)k, v, 0); + } + + return type; +} + static Scheme_Object *make_struct_type(int argc, Scheme_Object **argv) { - int initc, uninitc, num_props = 0, i; + int initc, uninitc, num_props = 0, i, prefab = 0; Scheme_Object *props = scheme_null, *l, *a, **r; Scheme_Object *inspector = NULL, **names, *uninit_val; Scheme_Struct_Type *type; @@ -2926,13 +3061,13 @@ static Scheme_Object *make_struct_type(int argc, Scheme_Object **argv) } if (argc > 6) { - if (SCHEME_FALSEP(argv[6])) - inspector = scheme_false; - else { + inspector = argv[6]; + if (SAME_OBJ(inspector, prefab_symbol)) { + prefab = 1; + inspector = scheme_false; + } else if (!SCHEME_FALSEP(inspector)) { if (!SAME_TYPE(SCHEME_TYPE(argv[6]), scheme_inspector_type)) - scheme_wrong_type("make-struct-type", "inspector or #f", 6, argc, argv); - - inspector = argv[6]; + scheme_wrong_type("make-struct-type", "inspector, #f, or 'prefab", 6, argc, argv); } if (argc > 7) { @@ -2984,9 +3119,33 @@ static Scheme_Object *make_struct_type(int argc, Scheme_Object **argv) } else uninit_val = scheme_false; + if (!uninitc) + uninit_val = scheme_false; + if (!inspector) inspector = scheme_get_param(scheme_current_config(), MZCONFIG_INSPECTOR); + if (prefab) { + const char *bad = NULL; + Scheme_Object *parent = argv[1]; + if (!SCHEME_FALSEP(parent) && !((Scheme_Struct_Type *)parent)->prefab_key) { + bad = ("make-struct-type: generative supertype disallowed" + " for non-generative structure type with name: "); + } else if (!SCHEME_NULLP(props)) { + bad = ("make-struct-type: properties disallowed" + " for non-generative structure type with name: "); + } else if (proc_attr) { + bad = ("make-struct-type: procedure specification disallowed" + " for non-generative structure type with name: "); + } else if (guard) { + bad = ("make-struct-type: guard disallowed" + " for non-generative structure type with name: "); + } + if (bad) { + scheme_raise_exn(MZEXN_FAIL_CONTRACT, bad, inspector); + } + } + type = (Scheme_Struct_Type *)_make_struct_type(argv[0], NULL, 0, SCHEME_FALSEP(argv[1]) ? NULL : argv[1], inspector, @@ -2996,6 +3155,10 @@ static Scheme_Object *make_struct_type(int argc, Scheme_Object **argv) immutable_pos_list, guard); + if (prefab) { + type = hash_prefab(type); + } + names = scheme_make_struct_names(argv[0], NULL, SCHEME_STRUCT_GEN_GET | SCHEME_STRUCT_GEN_SET, @@ -3006,6 +3169,197 @@ static Scheme_Object *make_struct_type(int argc, Scheme_Object **argv) return scheme_values(i, r); } +static Scheme_Object *make_prefab_key(Scheme_Struct_Type *type) +{ + Scheme_Object *key = scheme_null, *stack = scheme_null, *v; + int cnt, icnt, total_cnt; + + total_cnt = type->num_slots; + + while (type->name_pos) { + stack = scheme_make_pair((Scheme_Object *)type, stack); + type = type->parent_types[type->name_pos - 1]; + } + + while (type) { + cnt = type->num_slots; + icnt = type->num_islots; + if (type->name_pos) { + cnt -= type->parent_types[type->name_pos - 1]->num_slots; + icnt -= type->parent_types[type->name_pos - 1]->num_islots; + } + + if (cnt) { + int i; + v = scheme_null; + for (i = icnt; i--; ) { + if (!type->immutables || !type->immutables[i]) { + v = scheme_make_pair(scheme_make_integer(i), v); + } + } + if (!SCHEME_NULLP(v)) { + v = scheme_list_to_vector(v); + key = scheme_make_pair(v, key); + } + + if (cnt > icnt) { + key = scheme_make_pair(scheme_make_pair(scheme_make_integer(cnt - icnt), + scheme_make_pair(type->uninit_val, + scheme_null)), + key); + } + } + if (!SCHEME_NULLP(stack)) + key = scheme_make_pair(scheme_make_integer(icnt), key); + + key = scheme_make_pair(type->name, key); + + if (SCHEME_PAIRP(stack)) { + type = (Scheme_Struct_Type *)SCHEME_CAR(stack); + stack = SCHEME_CDR(stack); + } else { + type = NULL; + } + } + + if (SCHEME_PAIRP(key) + && SCHEME_NULLP(SCHEME_CDR(key))) + key = SCHEME_CAR(key); + + /* Turn the "external" key into a hashable key by adding the + total field count. */ + + key = scheme_make_pair(scheme_make_integer(total_cnt), + key); + + return key; +} + +Scheme_Struct_Type *scheme_lookup_prefab_type(Scheme_Object *key, int field_count) +{ + Scheme_Struct_Type *parent = NULL; + Scheme_Object *a, *uninit_val, *mutables, *immutable_pos_list, *name; + int i, ucnt, icnt, prev; + + if (SCHEME_SYMBOLP(key)) + key = scheme_make_pair(key, scheme_null); + + if (scheme_proper_list_length(key) < 0) + return NULL; + + if (prefab_table) { + a = scheme_lookup_in_table(prefab_table, (const char *)key); + if (a) + a = SCHEME_WEAK_BOX_VAL(a); + if (a) + return (Scheme_Struct_Type *)a; + } + + key = scheme_reverse(key); + + while (SCHEME_PAIRP(key)) { + /* mutable array? */ + a = SCHEME_CAR(key); + if (SCHEME_VECTORP(a)) { + mutables = a; + key = SCHEME_CDR(key); + } else + mutables = NULL; + + /* auto fields? */ + if (!SCHEME_PAIRP(key)) + return NULL; + a = SCHEME_CAR(key); + if (SCHEME_PAIRP(a)) { + if (scheme_proper_list_length(a) != 2) + return NULL; + if (!SCHEME_INTP(SCHEME_CAR(a))) + return NULL; + ucnt = SCHEME_INT_VAL(SCHEME_CAR(a)); + a = SCHEME_CDR(a); + uninit_val = SCHEME_CAR(a); + key = SCHEME_CDR(key); + } else { + ucnt = 0; + uninit_val = scheme_false; + } + + /* field count? */ + if (!SCHEME_PAIRP(key)) + return NULL; + a = SCHEME_CAR(key); + if (!SCHEME_INTP(a)) { + if (SCHEME_NULLP(SCHEME_CDR(key))) { + /* For last one, size can be inferred */ + icnt = field_count - ucnt - (parent + ? parent->num_slots + : 0); + if (icnt < 0) + icnt = 0; + } else + return NULL; + } else { + icnt = SCHEME_INT_VAL(a); + key = SCHEME_CDR(key); + } + + /* name */ + if (!SCHEME_PAIRP(key)) + return NULL; + a = SCHEME_CAR(key); + key = SCHEME_CDR(key); + + if (!SCHEME_SYMBOLP(a)) + return NULL; + name = a; + + /* convert mutability data to immutability data */ + immutable_pos_list = scheme_null; + prev = -1; + if (mutables) { + int len; + len = SCHEME_VEC_SIZE(mutables); + if (len > icnt) + return NULL; + for (i = 0; i < len; i++) { + a = SCHEME_VEC_ELS(mutables)[i]; + if (!SCHEME_INTP(a) + || (SCHEME_INT_VAL(a) < 0) + || (SCHEME_INT_VAL(a) >= icnt) + || (SCHEME_INT_VAL(a) <= prev)) + return NULL; + while (prev + 1 < SCHEME_INT_VAL(a)) { + immutable_pos_list = scheme_make_pair(scheme_make_integer(prev + 1), + immutable_pos_list); + prev++; + } + prev++; + } + } + while (prev + 1 < icnt) { + immutable_pos_list = scheme_make_pair(scheme_make_integer(prev + 1), + immutable_pos_list); + prev++; + } + + parent = (Scheme_Struct_Type *)_make_struct_type(name, NULL, 0, + (Scheme_Object *)parent, + scheme_false, + icnt, ucnt, + uninit_val, scheme_null, + NULL, + immutable_pos_list, + NULL); + + parent = hash_prefab(parent); + } + + if (!SCHEME_NULLP(key)) + return NULL; + + return parent; +} + /*========================================================================*/ /* procedure struct */ /*========================================================================*/ diff --git a/src/mzscheme/src/stxobj.c b/src/mzscheme/src/stxobj.c index 4bd16a0ccb..ee760b9bb8 100644 --- a/src/mzscheme/src/stxobj.c +++ b/src/mzscheme/src/stxobj.c @@ -109,7 +109,17 @@ static void preemptive_chunk(Scheme_Stx *stx); #define CONS scheme_make_pair #define ICONS scheme_make_pair -#define HAS_SUBSTX(obj) (SCHEME_PAIRP(obj) || SCHEME_VECTORP(obj) || SCHEME_BOXP(obj)) +#define HAS_SUBSTX(obj) (SCHEME_PAIRP(obj) || SCHEME_VECTORP(obj) || SCHEME_BOXP(obj) || prefab_p(obj)) + +XFORM_NONGCING static int prefab_p(Scheme_Object *o) +{ + if (SCHEME_STRUCTP(o)) { + if (((Scheme_Structure *)o)->stype->prefab_key) + if (MZ_OPT_HASH_KEY(&((Scheme_Structure *)o)->stype->iso) & STRUCT_TYPE_ALL_IMMUTABLE) + return 1; + } + return 0; +} #define STX_KEY(stx) MZ_OPT_HASH_KEY(&(stx)->iso) @@ -2550,6 +2560,20 @@ Scheme_Object *scheme_stx_content(Scheme_Object *o) } v = v2; + } else if (prefab_p(v)) { + Scheme_Structure *s = (Scheme_Structure *)v; + Scheme_Object *r; + int size, i; + + s = (Scheme_Structure *)scheme_clone_prefab_struct_instance(s); + + size = s->stype->num_slots; + for (i = 0; i < size; i++) { + r = propagate_wraps(s->slots[i], wl_count, &ml, here_wraps); + s->slots[i] = r; + } + + v = (Scheme_Object *)s; } stx->val = v; @@ -2730,6 +2754,29 @@ static Scheme_Object *stx_activate_certs(Scheme_Object *o, Scheme_Cert **cp) if (size) SCHEME_SET_IMMUTABLE(v2); return v2; + } else if (prefab_p(o)) { + Scheme_Object *e = NULL; + Scheme_Structure *s = (Scheme_Structure *)o; + int i, size = s->stype->num_slots; + + for (i = 0; i < size; i++) { + e = stx_activate_certs(s->slots[i], cp); + if (!SAME_OBJ(e, s->slots[i])) + break; + } + + if (i == size) + return o; + + s = (Scheme_Structure *)scheme_clone_prefab_struct_instance(s); + s->slots[i] = e; + + for (i++; i < size; i++) { + e = stx_activate_certs(s->slots[i], cp); + s->slots[i] = e; + } + + return (Scheme_Object *)s; } else if (SCHEME_STXP(o)) { Scheme_Stx *stx = (Scheme_Stx *)o; @@ -5148,6 +5195,18 @@ static Scheme_Object *syntax_to_datum_inner(Scheme_Object *o, result = r; if (size) SCHEME_SET_IMMUTABLE(result); + } else if (prefab_p(v)) { + Scheme_Structure *s = (Scheme_Structure *)v; + Scheme_Object *a; + int size = s->stype->num_slots, i; + + s = (Scheme_Structure *)scheme_clone_prefab_struct_instance(s); + for (i = 0; i < size; i++) { + a = syntax_to_datum_inner(s->slots[i], with_marks, mt); + s->slots[i] = a; + } + + result = (Scheme_Object *)s; } else result = v; @@ -5885,6 +5944,18 @@ static Scheme_Object *datum_to_syntax_inner(Scheme_Object *o, if (size) SCHEME_SET_VECTOR_IMMUTABLE(result); + } else if (prefab_p(o)) { + Scheme_Structure *s = (Scheme_Structure *)o; + Scheme_Object *a; + int size = s->stype->num_slots, i; + + s = (Scheme_Structure *)scheme_clone_prefab_struct_instance(s); + for (i = 0; i < size; i++) { + a = datum_to_syntax_inner(s->slots[i], ut, stx_src, stx_wraps, ht); + s->slots[i] = a; + } + + result = (Scheme_Object *)s; } else { result = o; } @@ -6103,6 +6174,13 @@ static void simplify_syntax_inner(Scheme_Object *o, for (i = 0; i < size; i++) { simplify_syntax_inner(SCHEME_VEC_ELS(v)[i], rns, marks); } + } else if (prefab_p(v)) { + Scheme_Structure *s = (Scheme_Structure *)v; + int size = s->stype->num_slots, i; + + for (i = 0; i < size; i++) { + simplify_syntax_inner(s->slots[i], rns, marks); + } } if (marks)