+(define case-switch cadr)
+(define case-cases cddr)
+
+;; (define (verify-cases data-layouts annotated-program)
+
+;; (define allowed-match-ast-types
+;; '((Int . (int-literal var))
+;; (Bool . (bool-literal var))
+;; (String . (string-literal var))))
+
+;; (define (check-pattern switch-type pat)
+
+;; (define (impossible-match)
+;; (error "Can't pattern match ~a with ~a" switch-type (ann-expr pat)))
+
+;; (if (assoc switch-type data-layouts)
+;; (begin
+;; (let ([sums (cdr (assoc switch-type data-layouts))])
+;; (unless (eqv? (ast-type (ann-expr pat)) 'var) (impossible-match))
+;; (unless (assoc (car (ann-expr pat)) sums) (impossible-match))
+;; (unless
+;; )
+;; (begin
+;; (unless (assoc switch-type allowed-match-ast-types)
+;; (error #f "Can't pattern match on ~a" switch-type))
+
+;; (let ([allowed (cdr (assoc switch-type allowed-match-ast-types))])
+;; (unless (assoc (ast-type (ann-expr pat)) allowed) (impossible-match)))))))
+
+
+;; (let ([expr (ann-expr annotated-program)])
+;; (case (ast-type expr)
+;; ['case
+;; (let* ([switch-type (ann-type (case-switch expr))]
+;; [allowed (cdr (assoc switch-type allowed-match-ast-types))])
+;; (for-each
+;; []))]))))
+
+
+ ; (let ([(foo a b) (foo 123 345)]) a)
+ ; |
+ ; v
+ ; (let ([a (foo~0 (foo 123 345)]
+ ; [b (foo~1 (foo 123 345)]) a)
+(define (expand-pattern-matches program)
+ (define (go x)
+ (define (let-pattern-match binding)
+ (let ([binding-name (car binding)]
+ [body (cadr binding)])
+ (if (eqv? (ast-type binding-name) 'var)
+ (list (list binding-name body))
+
+ (let* ([sum-name (car binding-name)]
+ [destructor (lambda (i) (dtor-name sum-name i))]
+ [products (cdr binding-name)]
+
+ [data-layouts (program-data-layouts program)]
+
+ [type (data-tor-type data-layouts sum-name)]
+
+ [sums (cdr (assoc type data-layouts))]
+ [sum (assoc sum-name sums)]
+
+ [expected-number (length (cdr sum))])
+
+ ; assert that we only do a let pattern match on an ADT with exactly one sum
+ (when (not (= 1 (length sums)))
+ (error #f (format "Cannot pattern match a ~a in a let since it has ~a possible constructors"
+ type
+ (length sums))))
+
+ ; assert that there is the correct number of bindings
+ (when (not (= (length products)
+ expected-number))
+ (error #f (format "Got ~a bindings: expected ~a for ~a"
+ (length products)
+ expected-number
+ binding)))
+
+ (flat-map (lambda (y i)
+ (let-pattern-match (list y `(,(destructor i) ,body))))
+ products
+ (range 0 (length products)))))))
+
+ (case (ast-type x)
+ ['let `(let ,(flat-map let-pattern-match (let-bindings x))
+ ,@(map go (let-body x)))]
+ [else (ast-traverse go x)]))
+ (program-map-exprs go program))
+