|
200 | 200 | (struct pat-base (stx) #:transparent)
|
201 | 201 | (struct pat-var pat-base (id) #:transparent)
|
202 | 202 | (struct pat-hole pat-base () #:transparent)
|
203 |
| - (struct pat-con pat-base (constructor pats) #:transparent) |
| 203 | + (struct pat-con pat-base (constructor) #:transparent) |
| 204 | + (struct pat-app pat-base (head pats) #:transparent) |
204 | 205 | (struct pat-str pat-base (str) #:transparent)
|
205 | 206 | (struct pat-int pat-base (int) #:transparent)
|
206 | 207 | (define pat? pat-base?)
|
|
218 | 219 | #:with :pat (local-apply-transformer trans #'pat-exp 'expression)]
|
219 | 220 |
|
220 | 221 | [pattern {~and constructor:data-constructor-val ~!}
|
221 |
| - #:do [(define val (attribute constructor.local-value)) |
222 |
| - (define arity (data-constructor-arity val))] |
223 |
| - #:fail-unless (zero? arity) |
224 |
| - (~a "cannot match ‘" (syntax-e #'constructor) "’ as a value; it is a " |
225 |
| - "constructor with arity " arity) |
226 |
| - #:attr pat (pat-con this-syntax val '()) |
| 222 | + #:do [(define val (attribute constructor.local-value))] |
| 223 | + #:attr pat (pat-con #'constructor val) |
227 | 224 | #:attr disappeared-uses (list (syntax-local-introduce #'constructor))]
|
228 |
| - [pattern (~parens constructor:data-constructor-val ~! arg:pat ...) |
229 |
| - #:do [(define val (attribute constructor.local-value)) |
230 |
| - (define arity (data-constructor-arity val))] |
231 |
| - #:fail-when {(length (attribute arg)) . < . arity} |
232 |
| - (~a "not enough arguments provided for constructor ‘" |
233 |
| - (syntax-e #'constructor) "’, which has arity " arity) |
234 |
| - #:fail-when {(length (attribute arg)) . > . arity} |
235 |
| - (~a "too many arguments provided for constructor ‘" |
236 |
| - (syntax-e #'constructor) "’, which has arity " arity) |
237 |
| - #:attr pat (pat-con this-syntax (attribute constructor.local-value) (attribute arg.pat)) |
| 225 | + [pattern (~parens head:pat ~! arg:pat ...) |
| 226 | + #:attr pat (pat-app this-syntax |
| 227 | + (attribute head.pat) |
| 228 | + (attribute arg.pat)) |
238 | 229 | #:attr disappeared-uses (cons (syntax-local-introduce #'constructor)
|
239 | 230 | (append* (attribute arg.disappeared-uses)))]
|
240 | 231 | [pattern {~braces a:pat constructor:data-constructor-val b:pat}
|
|
246 | 237 | #:fail-when (not (= arity 2))
|
247 | 238 | (~a "cannot match ‘" (syntax-e #'constructor) "’ infix; it has arity "
|
248 | 239 | arity ", but constructors matched infix must have arity 2")
|
249 |
| - #:attr pat (pat-con this-syntax (attribute constructor.local-value) |
| 240 | + #:attr pat (pat-app this-syntax |
| 241 | + (pat-con #'constructor val) |
250 | 242 | (list (attribute a.pat) (attribute b.pat)))
|
251 | 243 | #:attr disappeared-uses (cons (syntax-local-introduce #'constructor)
|
252 | 244 | (append (attribute a.disappeared-uses)
|
|
301 | 293 | (values (expand-type #'String) '() #{values #`(app force- #,str) %})]
|
302 | 294 | [(pat-int _ int)
|
303 | 295 | (values (expand-type #'Integer) '() #{values #`(app force- #,int) %})]
|
304 |
| - [(pat-con _ con pats) |
| 296 | + [(pat-con stx con) |
| 297 | + (define arity (data-constructor-arity con)) |
| 298 | + (unless (zero? arity) |
| 299 | + (raise-syntax-error #f |
| 300 | + (~a "cannot match ‘" (syntax-e stx) "’ as a value; it is a " |
| 301 | + "constructor with arity " arity) |
| 302 | + stx)) |
| 303 | + (pat⇒! (pat-app stx pat '()))] |
| 304 | + [(pat-app stx (pat-con cstx con) pats) |
| 305 | + (define arity (data-constructor-arity con)) |
| 306 | + (when {(length pats) . < . arity} |
| 307 | + (raise-syntax-error #f |
| 308 | + (~a "not enough arguments provided for constructor ‘" |
| 309 | + (syntax-e cstx) "’, which has arity " arity) |
| 310 | + stx)) |
| 311 | + (when {(length pats) . > . arity} |
| 312 | + (raise-syntax-error #f |
| 313 | + (~a "too many arguments provided for constructor ‘" |
| 314 | + (syntax-e cstx) "’, which has arity " arity) |
| 315 | + stx)) |
| 316 | + |
305 | 317 | (let*-values ([(τs_args τ_result) (data-constructor-args/result! con)]
|
306 | 318 | [(assumps mk-pats) (pats⇐! pats τs_args)])
|
307 | 319 | (values τ_result assumps
|
308 | 320 | (λ (ids) (let-values ([(match-pats rest) (mk-pats ids)])
|
309 |
| - (values ((data-constructor-make-match-pat con) match-pats) rest)))))])) |
| 321 | + (values ((data-constructor-make-match-pat con) match-pats) rest)))))] |
| 322 | + [(pat-app outer-stx (pat-base inner-stx) _) |
| 323 | + (raise-syntax-error #f "expected a constructor" outer-stx inner-stx)])) |
310 | 324 |
|
311 | 325 | (define/contract (pat⇐! pat t)
|
312 | 326 | (-> pat? type?
|
|
435 | 449 | ; When we hit a constructor pattern, we check the ideal. If it is a constructor, compare the
|
436 | 450 | ; tags and then recur for the sub-patterns. If it is a variable, then split the ideal into new
|
437 | 451 | ; ideals for each kind of constructor.
|
438 |
| - [(pat-con _ ctor sub-pats) |
| 452 | + [(or (pat-app _ (pat-con _ ctor) sub-pats) |
| 453 | + (and (pat-con _ ctor) (app (λ (x) '()) sub-pats))) |
439 | 454 | (match q
|
440 | 455 | [(ideal-con ctor-tag sub-ideals)
|
441 | 456 | (and (eq? (syntax-local-value ctor-tag) ctor)
|
|
0 commit comments