|
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