syntax/parse: reduce allocation when parsing cannot fail
When parsing cannot fail, avoid allocating expectstacks and failures (thanks samth for the idea). Allocation still happens for progress and failuresets (conses of #t, now), though. Compile with `PLTSTDERR="debug@syntax-parse"` to log cannot-fail syntax-parse expressions and syntax class definitions.
This commit is contained in:
parent
e676ba74a5
commit
bcc8535b78
|
@ -97,7 +97,7 @@
|
||||||
(if (predicate x)
|
(if (predicate x)
|
||||||
(success fh0)
|
(success fh0)
|
||||||
(let ([es (es-add-thing pr 'description #t rl es)])
|
(let ([es (es-add-thing pr 'description #t rl es)])
|
||||||
(fh0 (failure pr es)))))))]))
|
(fh0 (failure* pr es)))))))]))
|
||||||
|
|
||||||
(define-syntax (parser/rhs stx)
|
(define-syntax (parser/rhs stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
|
@ -108,23 +108,27 @@
|
||||||
(parameterize ((current-syntax-context #'ctx))
|
(parameterize ((current-syntax-context #'ctx))
|
||||||
(parse-rhs #'rhss (syntax->datum #'relsattrs) (syntax-e #'splicing?)
|
(parse-rhs #'rhss (syntax->datum #'relsattrs) (syntax-e #'splicing?)
|
||||||
#:context #'ctx)))
|
#:context #'ctx)))
|
||||||
(rhs->parser #'name #'formals #'relsattrs the-rhs (syntax-e #'splicing?))))]))
|
(rhs->parser #'name #'formals #'relsattrs the-rhs (syntax-e #'splicing?) #'ctx)))]))
|
||||||
|
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
(define (rhs->parser name formals relsattrs the-rhs splicing?)
|
(define (rhs->parser name formals relsattrs the-rhs splicing? [ctx #f])
|
||||||
(define-values (transparent? description variants defs commit? delimit-cut?)
|
(define-values (transparent? description variants defs commit? delimit-cut?)
|
||||||
(match the-rhs
|
(match the-rhs
|
||||||
[(rhs _ transparent? description variants defs commit? delimit-cut?)
|
[(rhs _ transparent? description variants defs commit? delimit-cut?)
|
||||||
(values transparent? description variants defs commit? delimit-cut?)]))
|
(values transparent? description variants defs commit? delimit-cut?)]))
|
||||||
(define vdefss (map variant-definitions variants))
|
(define vdefss (map variant-definitions variants))
|
||||||
(define formals* (rewrite-formals formals #'x #'rl))
|
(define formals* (rewrite-formals formals #'x #'rl))
|
||||||
|
(define patterns (map variant-pattern variants))
|
||||||
|
(define no-fail?
|
||||||
|
(and (not splicing?) ;; FIXME: commit? needed?
|
||||||
|
(patterns-cannot-fail? patterns)))
|
||||||
|
(when no-fail? (log-syntax-parse-debug "(stxclass) cannot fail: ~e" ctx))
|
||||||
(define body
|
(define body
|
||||||
(cond [(null? variants)
|
(cond [(null? patterns)
|
||||||
#'(fail (failure pr es))]
|
#'(fail (failure* pr es))]
|
||||||
[splicing?
|
[splicing?
|
||||||
(with-syntax ([(alternative ...)
|
(with-syntax ([(alternative ...)
|
||||||
(for/list ([variant (in-list variants)])
|
(for/list ([pattern (in-list patterns)])
|
||||||
(define pattern (variant-pattern variant))
|
|
||||||
(with-syntax ([pattern pattern]
|
(with-syntax ([pattern pattern]
|
||||||
[relsattrs relsattrs]
|
[relsattrs relsattrs]
|
||||||
[iattrs (pattern-attrs pattern)]
|
[iattrs (pattern-attrs pattern)]
|
||||||
|
@ -140,8 +144,7 @@
|
||||||
[else
|
[else
|
||||||
(with-syntax ([matrix
|
(with-syntax ([matrix
|
||||||
(optimize-matrix
|
(optimize-matrix
|
||||||
(for/list ([variant (in-list variants)])
|
(for/list ([pattern (in-list patterns)])
|
||||||
(define pattern (variant-pattern variant))
|
|
||||||
(with-syntax ([iattrs (pattern-attrs pattern)]
|
(with-syntax ([iattrs (pattern-attrs pattern)]
|
||||||
[relsattrs relsattrs]
|
[relsattrs relsattrs]
|
||||||
[commit? commit?])
|
[commit? commit?])
|
||||||
|
@ -165,7 +168,8 @@
|
||||||
(syntax-parameterize ((this-context-syntax
|
(syntax-parameterize ((this-context-syntax
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
[(tbs) (ps-context-syntax pr)])))
|
[(tbs) (ps-context-syntax pr)])))
|
||||||
(let ([es (es-add-thing pr description 'transparent? rl es)]
|
(let ([es (es-add-thing pr description 'transparent? rl
|
||||||
|
#,(if no-fail? #'#f #'es))]
|
||||||
[pr (if 'transparent? pr (ps-add-opaque pr))])
|
[pr (if 'transparent? pr (ps-add-opaque pr))])
|
||||||
(with ([fail-handler fh0]
|
(with ([fail-handler fh0]
|
||||||
[cut-prompt cp0])
|
[cut-prompt cp0])
|
||||||
|
@ -274,6 +278,7 @@ Some optimizations:
|
||||||
- commit protocol for stxclasses (but not ~commit, no point)
|
- commit protocol for stxclasses (but not ~commit, no point)
|
||||||
- avoid continue-vs-end choice point in (EH ... . ()) by eager pair check
|
- avoid continue-vs-end choice point in (EH ... . ()) by eager pair check
|
||||||
- integrable stxclasses, specialize ellipses of integrable stxclasses
|
- integrable stxclasses, specialize ellipses of integrable stxclasses
|
||||||
|
- pattern lists that cannot fail set es=#f to disable ExpectStack allocation
|
||||||
|#
|
|#
|
||||||
|
|
||||||
;; ----
|
;; ----
|
||||||
|
@ -425,10 +430,12 @@ Conventions:
|
||||||
(define-values (patterns body-exprs defs2s)
|
(define-values (patterns body-exprs defs2s)
|
||||||
(for/lists (patterns body-exprs defs2s) ([clause (in-list (stx->list clauses-stx))])
|
(for/lists (patterns body-exprs defs2s) ([clause (in-list (stx->list clauses-stx))])
|
||||||
(for-clause clause)))
|
(for-clause clause)))
|
||||||
|
(define no-fail? (patterns-cannot-fail? patterns))
|
||||||
|
(when no-fail? (log-syntax-parse-debug "cannot fail: ~e" #'ctx))
|
||||||
(with-syntax ([(def ...) (apply append (get-txlifts-as-definitions) defs defs2s)])
|
(with-syntax ([(def ...) (apply append (get-txlifts-as-definitions) defs defs2s)])
|
||||||
#`(let* ([ctx0 (normalize-context '#,who #,context x)]
|
#`(let* ([ctx0 (normalize-context '#,who #,context x)]
|
||||||
[pr (ps-empty x (cadr ctx0))]
|
[pr (ps-empty x (cadr ctx0))]
|
||||||
[es #f]
|
[es #,(if no-fail? #'#f #'#t)]
|
||||||
[cx x]
|
[cx x]
|
||||||
[fh0 (syntax-patterns-fail ctx0)])
|
[fh0 (syntax-patterns-fail ctx0)])
|
||||||
def ...
|
def ...
|
||||||
|
@ -450,7 +457,7 @@ Conventions:
|
||||||
#`(try alternative ...))
|
#`(try alternative ...))
|
||||||
|#]
|
|#]
|
||||||
[else
|
[else
|
||||||
#`(fail (failure pr es))]))))))))]))
|
#`(fail (failure* pr es))]))))))))]))
|
||||||
|
|
||||||
;; ----
|
;; ----
|
||||||
|
|
||||||
|
@ -488,7 +495,7 @@ Conventions:
|
||||||
[tpr (ps-add-cdr pr)])
|
[tpr (ps-add-cdr pr)])
|
||||||
(parse:matrix ((hx hcx hpr es) (tx tcx tpr es) . ins) inner))
|
(parse:matrix ((hx hcx hpr es) (tx tcx tpr es) . ins) inner))
|
||||||
(let ([es* (if (null? datum) (es-add-proper-pair (first-desc:matrix inner) es) es)])
|
(let ([es* (if (null? datum) (es-add-proper-pair (first-desc:matrix inner) es) es)])
|
||||||
(fail (failure pr es*)))))]
|
(fail (failure* pr es*)))))]
|
||||||
[(parse:pk (in1 . ins) #s(pk/and inner))
|
[(parse:pk (in1 . ins) #s(pk/and inner))
|
||||||
#'(parse:matrix (in1 in1 . ins) inner)]))
|
#'(parse:matrix (in1 in1 . ins) inner)]))
|
||||||
|
|
||||||
|
@ -569,12 +576,12 @@ Conventions:
|
||||||
#`(let ([d unwrap-x])
|
#`(let ([d unwrap-x])
|
||||||
(if (equal? d (quote datum))
|
(if (equal? d (quote datum))
|
||||||
k
|
k
|
||||||
(fail (failure pr (es-add-atom 'datum es))))))]
|
(fail (failure* pr (es-add-atom 'datum es))))))]
|
||||||
[#s(pat:literal literal input-phase lit-phase)
|
[#s(pat:literal literal input-phase lit-phase)
|
||||||
#`(if (and (identifier? x)
|
#`(if (and (identifier? x)
|
||||||
(free-identifier=? x (quote-syntax literal) input-phase lit-phase))
|
(free-identifier=? x (quote-syntax literal) input-phase lit-phase))
|
||||||
k
|
k
|
||||||
(fail (failure pr (es-add-literal (quote-syntax literal) es))))]
|
(fail (failure* pr (es-add-literal (quote-syntax literal) es))))]
|
||||||
[#s(pat:action action subpattern)
|
[#s(pat:action action subpattern)
|
||||||
#'(parse:A x cx action pr es (parse:S x cx subpattern pr es k))]
|
#'(parse:A x cx action pr es (parse:S x cx subpattern pr es k))]
|
||||||
[#s(pat:head head tail)
|
[#s(pat:head head tail)
|
||||||
|
@ -607,7 +614,7 @@ Conventions:
|
||||||
(with ([fail-handler fail-to-succeed]
|
(with ([fail-handler fail-to-succeed]
|
||||||
[cut-prompt fail-to-succeed]) ;; to be safe
|
[cut-prompt fail-to-succeed]) ;; to be safe
|
||||||
(parse:S x cx subpattern pr es
|
(parse:S x cx subpattern pr es
|
||||||
(fh0 (failure pr0 es0)))))]
|
(fh0 (failure* pr0 es0)))))]
|
||||||
[#s(pat:pair head tail)
|
[#s(pat:pair head tail)
|
||||||
#`(let ([datum (if (syntax? x) (syntax-e x) x)]
|
#`(let ([datum (if (syntax? x) (syntax-e x) x)]
|
||||||
[cx (if (syntax? x) x cx)]) ;; FIXME: shadowing cx?!
|
[cx (if (syntax? x) x cx)]) ;; FIXME: shadowing cx?!
|
||||||
|
@ -620,7 +627,7 @@ Conventions:
|
||||||
(parse:S hx hcx head hpr es
|
(parse:S hx hcx head hpr es
|
||||||
(parse:S tx cx tail tpr es k)))
|
(parse:S tx cx tail tpr es k)))
|
||||||
(let ([es* (if (null? datum) (es-add-proper-pair (first-desc:S head) es) es)])
|
(let ([es* (if (null? datum) (es-add-proper-pair (first-desc:S head) es) es)])
|
||||||
(fail (failure pr es*)))))]
|
(fail (failure* pr es*)))))]
|
||||||
[#s(pat:vector subpattern)
|
[#s(pat:vector subpattern)
|
||||||
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
||||||
(if (vector? datum)
|
(if (vector? datum)
|
||||||
|
@ -628,7 +635,7 @@ Conventions:
|
||||||
[vcx (if (syntax? x) x cx)] ;; FIXME: (vector? datum) => (syntax? x) ???
|
[vcx (if (syntax? x) x cx)] ;; FIXME: (vector? datum) => (syntax? x) ???
|
||||||
[pr* (ps-add-unvector pr)])
|
[pr* (ps-add-unvector pr)])
|
||||||
(parse:S datum vcx subpattern pr* es k))
|
(parse:S datum vcx subpattern pr* es k))
|
||||||
(fail (failure pr es))))]
|
(fail (failure* pr es))))]
|
||||||
[#s(pat:box subpattern)
|
[#s(pat:box subpattern)
|
||||||
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
||||||
(if (box? datum)
|
(if (box? datum)
|
||||||
|
@ -636,7 +643,7 @@ Conventions:
|
||||||
[bcx (if (syntax? x) x cx)] ;; FIXME: (box? datum) => (syntax? x) ???
|
[bcx (if (syntax? x) x cx)] ;; FIXME: (box? datum) => (syntax? x) ???
|
||||||
[pr* (ps-add-unbox pr)])
|
[pr* (ps-add-unbox pr)])
|
||||||
(parse:S datum bcx subpattern pr* es k))
|
(parse:S datum bcx subpattern pr* es k))
|
||||||
(fail (failure pr es))))]
|
(fail (failure* pr es))))]
|
||||||
[#s(pat:pstruct key subpattern)
|
[#s(pat:pstruct key subpattern)
|
||||||
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
#`(let ([datum (if (syntax? x) (syntax-e x) x)])
|
||||||
(if (let ([xkey (prefab-struct-key datum)])
|
(if (let ([xkey (prefab-struct-key datum)])
|
||||||
|
@ -645,7 +652,7 @@ Conventions:
|
||||||
[scx (if (syntax? x) x cx)] ;; FIXME: (struct? datum) => (syntax? x) ???
|
[scx (if (syntax? x) x cx)] ;; FIXME: (struct? datum) => (syntax? x) ???
|
||||||
[pr* (ps-add-unpstruct pr)])
|
[pr* (ps-add-unpstruct pr)])
|
||||||
(parse:S datum scx subpattern pr* es k))
|
(parse:S datum scx subpattern pr* es k))
|
||||||
(fail (failure pr es))))]
|
(fail (failure* pr es))))]
|
||||||
[#s(pat:describe pattern description transparent? role)
|
[#s(pat:describe pattern description transparent? role)
|
||||||
#`(let ([es* (es-add-thing pr description transparent? role es)]
|
#`(let ([es* (es-add-thing pr description transparent? role es)]
|
||||||
[pr* (if 'transparent? pr (ps-add-opaque pr))])
|
[pr* (if 'transparent? pr (ps-add-opaque pr))])
|
||||||
|
@ -677,7 +684,7 @@ Conventions:
|
||||||
(if (predicate x*)
|
(if (predicate x*)
|
||||||
(let-attributes (name-attr ...) k)
|
(let-attributes (name-attr ...) k)
|
||||||
(let ([es* (es-add-thing pr 'description #t role es)])
|
(let ([es* (es-add-thing pr 'description #t role es)])
|
||||||
(fail (failure pr es*))))))])]))
|
(fail (failure* pr es*))))))])]))
|
||||||
|
|
||||||
;; (first-desc:S S-pattern) : expr[FirstDesc]
|
;; (first-desc:S S-pattern) : expr[FirstDesc]
|
||||||
(define-syntax (first-desc:S stx)
|
(define-syntax (first-desc:S stx)
|
||||||
|
@ -758,7 +765,7 @@ Conventions:
|
||||||
(if c
|
(if c
|
||||||
(let ([pr* (if (syntax? c) (ps-add-stx pr c) pr)]
|
(let ([pr* (if (syntax? c) (ps-add-stx pr c) pr)]
|
||||||
[es* (es-add-message message es)])
|
[es* (es-add-message message es)])
|
||||||
(fail (failure pr* es*)))
|
(fail (failure* pr* es*)))
|
||||||
k))]
|
k))]
|
||||||
[#s(action:parse pattern expr)
|
[#s(action:parse pattern expr)
|
||||||
#`(let* ([y (datum->syntax/with-clause (wrap-user-code expr))]
|
#`(let* ([y (datum->syntax/with-clause (wrap-user-code expr))]
|
||||||
|
@ -917,7 +924,7 @@ Conventions:
|
||||||
(with ([fail-handler fail-to-succeed]
|
(with ([fail-handler fail-to-succeed]
|
||||||
[cut-prompt fail-to-succeed]) ;; to be safe
|
[cut-prompt fail-to-succeed]) ;; to be safe
|
||||||
(parse:H x cx rest-x rest-cx rest-pr subpattern pr es
|
(parse:H x cx rest-x rest-cx rest-pr subpattern pr es
|
||||||
(fh0 (failure pr0 es0)))))]
|
(fh0 (failure* pr0 es0)))))]
|
||||||
[_
|
[_
|
||||||
#'(parse:S x cx
|
#'(parse:S x cx
|
||||||
;; FIXME: consider proper-list-pattern? (yes is consistent with ~seq)
|
;; FIXME: consider proper-list-pattern? (yes is consistent with ~seq)
|
||||||
|
@ -995,7 +1002,7 @@ Conventions:
|
||||||
...)
|
...)
|
||||||
(cond [(< rel-rep (rep:min-number rel-repc))
|
(cond [(< rel-rep (rep:min-number rel-repc))
|
||||||
(let ([es (expectation-of-reps/too-few es rel-rep rel-repc rel-head)])
|
(let ([es (expectation-of-reps/too-few es rel-rep rel-repc rel-head)])
|
||||||
(fail (failure loop-pr es)))]
|
(fail (failure* loop-pr es)))]
|
||||||
...
|
...
|
||||||
[else
|
[else
|
||||||
(let-attributes ([a (rep:finalize a attr-repc alt-id)] ...)
|
(let-attributes ([a (rep:finalize a attr-repc alt-id)] ...)
|
||||||
|
@ -1010,7 +1017,7 @@ Conventions:
|
||||||
[(topc #t x cx pr es pair-alt null-alt)
|
[(topc #t x cx pr es pair-alt null-alt)
|
||||||
(cond [(stx-pair? x) pair-alt]
|
(cond [(stx-pair? x) pair-alt]
|
||||||
[(stx-null? x) null-alt]
|
[(stx-null? x) null-alt]
|
||||||
[else (fail (failure pr es))])]
|
[else (fail (failure* pr es))])]
|
||||||
[(topc _ x cx pr es alt1 alt2)
|
[(topc _ x cx pr es alt1 alt2)
|
||||||
(try alt1 alt2)]))
|
(try alt1 alt2)]))
|
||||||
|
|
||||||
|
@ -1041,7 +1048,7 @@ Conventions:
|
||||||
(if (< rep (rep:max-number repc))
|
(if (< rep (rep:max-number repc))
|
||||||
(let ([rep (add1 rep)]) k*)
|
(let ([rep (add1 rep)]) k*)
|
||||||
(let ([es* (expectation-of-reps/too-many es rep repc)])
|
(let ([es* (expectation-of-reps/too-many es rep repc)])
|
||||||
(fail (failure pr* es*)))))]))]))
|
(fail (failure* pr* es*)))))]))]))
|
||||||
|
|
||||||
;; (rep:initial-value RepConstraint) : expr
|
;; (rep:initial-value RepConstraint) : expr
|
||||||
(define-syntax (rep:initial-value stx)
|
(define-syntax (rep:initial-value stx)
|
||||||
|
|
|
@ -511,6 +511,15 @@ A RepConstraint is one of
|
||||||
|
|
||||||
;; ----
|
;; ----
|
||||||
|
|
||||||
|
;; patterns-cannot-fail? : (Listof SinglePattern) -> Boolean
|
||||||
|
;; Returns true if the disjunction of the patterns always succeeds---and thus no
|
||||||
|
;; failure-tracking needed. Note: beware cut!
|
||||||
|
(define (patterns-cannot-fail? patterns)
|
||||||
|
(and (not (ormap pattern-has-cut? patterns))
|
||||||
|
(ormap pattern-cannot-fail? patterns)))
|
||||||
|
|
||||||
|
;; ----
|
||||||
|
|
||||||
;; An AbsNullable is 'yes | 'no | 'unknown (3-valued logic)
|
;; An AbsNullable is 'yes | 'no | 'unknown (3-valued logic)
|
||||||
|
|
||||||
(define (3and a b)
|
(define (3and a b)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
ps-difference
|
ps-difference
|
||||||
|
|
||||||
(struct-out failure)
|
(struct-out failure)
|
||||||
|
failure*
|
||||||
|
|
||||||
expect?
|
expect?
|
||||||
(struct-out expect:thing)
|
(struct-out expect:thing)
|
||||||
(struct-out expect:atom)
|
(struct-out expect:atom)
|
||||||
|
@ -49,6 +51,8 @@ A FailFunction = (FailureSet -> Answer)
|
||||||
|#
|
|#
|
||||||
(define-struct failure (progress expectstack) #:prefab)
|
(define-struct failure (progress expectstack) #:prefab)
|
||||||
|
|
||||||
|
;; failure* : PS ExpectStack/#f -> Failure/#t
|
||||||
|
(define (failure* ps es) (if es (failure ps es) #t))
|
||||||
|
|
||||||
;; == Progress ==
|
;; == Progress ==
|
||||||
|
|
||||||
|
@ -177,11 +181,15 @@ An ExpectStack (during parsing) is one of
|
||||||
* (expect:atom Datum ExpectStack)
|
* (expect:atom Datum ExpectStack)
|
||||||
* (expect:literal Identifier ExpectStack)
|
* (expect:literal Identifier ExpectStack)
|
||||||
* (expect:proper-pair FirstDesc ExpectStack)
|
* (expect:proper-pair FirstDesc ExpectStack)
|
||||||
|
* #t
|
||||||
|
|
||||||
The *-marked variants can only occur at the top of the stack (ie, not
|
The *-marked variants can only occur at the top of the stack (ie, not
|
||||||
in the next field of another Expect). The top of the stack contains
|
in the next field of another Expect). The top of the stack contains
|
||||||
the most specific information.
|
the most specific information.
|
||||||
|
|
||||||
|
An ExpectStack can also be #f, which means no failure tracking is
|
||||||
|
requested (and thus no more ExpectStacks should be allocated).
|
||||||
|
|
||||||
-- During reporting, the goal is ease of manipulation.
|
-- During reporting, the goal is ease of manipulation.
|
||||||
|
|
||||||
An ExpectList (during reporting) is (listof Expect).
|
An ExpectList (during reporting) is (listof Expect).
|
||||||
|
@ -221,23 +229,23 @@ RExpectList when the most specific information comes last.
|
||||||
(expect:proper-pair? x)))
|
(expect:proper-pair? x)))
|
||||||
|
|
||||||
(define (es-add-thing ps description transparent? role next)
|
(define (es-add-thing ps description transparent? role next)
|
||||||
(if description
|
(if (and next description)
|
||||||
(expect:thing ps description transparent? role next)
|
(expect:thing ps description transparent? role next)
|
||||||
next))
|
next))
|
||||||
|
|
||||||
(define (es-add-message message next)
|
(define (es-add-message message next)
|
||||||
(if message
|
(if (and next message)
|
||||||
(expect:message message next)
|
(expect:message message next)
|
||||||
next))
|
next))
|
||||||
|
|
||||||
(define (es-add-atom atom next)
|
(define (es-add-atom atom next)
|
||||||
(expect:atom atom next))
|
(and next (expect:atom atom next)))
|
||||||
|
|
||||||
(define (es-add-literal literal next)
|
(define (es-add-literal literal next)
|
||||||
(expect:literal literal next))
|
(and next (expect:literal literal next)))
|
||||||
|
|
||||||
(define (es-add-proper-pair first-desc next)
|
(define (es-add-proper-pair first-desc next)
|
||||||
(expect:proper-pair first-desc next))
|
(and next (expect:proper-pair first-desc next)))
|
||||||
|
|
||||||
#|
|
#|
|
||||||
A FirstDesc is one of
|
A FirstDesc is one of
|
||||||
|
|
|
@ -292,6 +292,7 @@ ie (ps->stx+index ps1) = (ps->stx+index ps2).
|
||||||
(let loop ([es es] [acc null])
|
(let loop ([es es] [acc null])
|
||||||
(match es
|
(match es
|
||||||
['#f acc]
|
['#f acc]
|
||||||
|
['#t acc]
|
||||||
[(expect:thing ps desc tr? role rest-es)
|
[(expect:thing ps desc tr? role rest-es)
|
||||||
(cond [(and truncate-opaque? (not tr?))
|
(cond [(and truncate-opaque? (not tr?))
|
||||||
(loop rest-es (cons (expect:thing #f desc #t role (ps->stx+index ps)) null))]
|
(loop rest-es (cons (expect:thing #f desc #t role (ps->stx+index ps)) null))]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user