(include "#.scm")

(define bool #f)

;; proper lists
(define lst0 (list))
(define lst1 (list 11))
(define lst2 (list 22 33))

;; dotted list
(define lst3 (cons 44 55))
(define lst4 (cons 66 (cons 77 88)))

(check-eq? (concatenate lst0) '())
(check-eq? (concatenate (list bool)) bool)
(check-eq? (concatenate (list lst0 bool)) bool)
(check-eq? (concatenate (list lst0 lst0)) lst0)
(check-eq? (concatenate (list lst0 lst1)) lst1)
(check-eq? (concatenate (list lst0 lst2)) lst2)
(check-eq? (concatenate (list lst0 lst3)) lst3)
(check-eq? (concatenate (list lst0 lst4)) lst4)
(check-eq? (concatenate (list lst0 lst0 bool)) bool)
(check-eq? (concatenate (list lst0 lst0 lst0)) lst0)
(check-eq? (concatenate (list lst0 lst0 lst1)) lst1)
(check-eq? (concatenate (list lst0 lst0 lst2)) lst2)
(check-eq? (concatenate (list lst0 lst0 lst3)) lst3)
(check-eq? (concatenate (list lst0 lst0 lst4)) lst4)
(check-equal? (concatenate (list lst1 bool)) '(11 . #f))
(check-equal? (concatenate (list lst1 lst0)) '(11))
(check-equal? (concatenate (list lst1 lst1)) '(11 11))
(check-equal? (concatenate (list lst1 lst2)) '(11 22 33))
(check-equal? (concatenate (list lst1 lst3)) '(11 44 . 55))
(check-equal? (concatenate (list lst1 lst4)) '(11 66 77 . 88))
(check-equal? (concatenate (list lst1 lst0 bool)) '(11 . #f))
(check-equal? (concatenate (list lst1 lst0 lst0)) '(11))
(check-equal? (concatenate (list lst1 lst0 lst1)) '(11 11))
(check-equal? (concatenate (list lst1 lst0 lst2)) '(11 22 33))
(check-equal? (concatenate (list lst1 lst0 lst3)) '(11 44 . 55))
(check-equal? (concatenate (list lst1 lst0 lst4)) '(11 66 77 . 88))
(check-equal? (concatenate (list lst2 bool)) '(22 33 . #f))
(check-equal? (concatenate (list lst2 lst0)) '(22 33))
(check-equal? (concatenate (list lst2 lst1)) '(22 33 11))
(check-equal? (concatenate (list lst2 lst2)) '(22 33 22 33))
(check-equal? (concatenate (list lst2 lst3)) '(22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst4)) '(22 33 66 77 . 88))
(check-equal? (concatenate (list lst2 lst0 bool)) '(22 33 . #f))
(check-equal? (concatenate (list lst2 lst0 lst0)) '(22 33))
(check-equal? (concatenate (list lst2 lst0 lst1)) '(22 33 11))
(check-equal? (concatenate (list lst2 lst0 lst2)) '(22 33 22 33))
(check-equal? (concatenate (list lst2 lst0 lst3)) '(22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst0 lst4)) '(22 33 66 77 . 88))
(check-equal? (concatenate (list lst1 lst2 lst3)) '(11 22 33 44 . 55))

(check-eq? (concatenate lst0 lst0) '())
(check-eq? (concatenate (list bool) lst0) bool)
(check-eq? (concatenate (list lst0 bool) lst0) bool)
(check-eq? (concatenate (list lst0 lst0) lst0) lst0)
(check-eq? (concatenate (list lst0 lst1) lst0) lst1)
(check-eq? (concatenate (list lst0 lst2) lst0) lst2)
(check-eq? (concatenate (list lst0 lst3) lst0) lst3)
(check-eq? (concatenate (list lst0 lst4) lst0) lst4)
(check-eq? (concatenate (list lst0 lst0 bool) lst0) bool)
(check-eq? (concatenate (list lst0 lst0 lst0) lst0) lst0)
(check-eq? (concatenate (list lst0 lst0 lst1) lst0) lst1)
(check-eq? (concatenate (list lst0 lst0 lst2) lst0) lst2)
(check-eq? (concatenate (list lst0 lst0 lst3) lst0) lst3)
(check-eq? (concatenate (list lst0 lst0 lst4) lst0) lst4)
(check-equal? (concatenate (list lst1 bool) lst0) '(11 . #f))
(check-equal? (concatenate (list lst1 lst0) lst0) '(11))
(check-equal? (concatenate (list lst1 lst1) lst0) '(11 11))
(check-equal? (concatenate (list lst1 lst2) lst0) '(11 22 33))
(check-equal? (concatenate (list lst1 lst3) lst0) '(11 44 . 55))
(check-equal? (concatenate (list lst1 lst4) lst0) '(11 66 77 . 88))
(check-equal? (concatenate (list lst1 lst0 bool) lst0) '(11 . #f))
(check-equal? (concatenate (list lst1 lst0 lst0) lst0) '(11))
(check-equal? (concatenate (list lst1 lst0 lst1) lst0) '(11 11))
(check-equal? (concatenate (list lst1 lst0 lst2) lst0) '(11 22 33))
(check-equal? (concatenate (list lst1 lst0 lst3) lst0) '(11 44 . 55))
(check-equal? (concatenate (list lst1 lst0 lst4) lst0) '(11 66 77 . 88))
(check-equal? (concatenate (list lst2 bool) lst0) '(22 33 . #f))
(check-equal? (concatenate (list lst2 lst0) lst0) '(22 33))
(check-equal? (concatenate (list lst2 lst1) lst0) '(22 33 11))
(check-equal? (concatenate (list lst2 lst2) lst0) '(22 33 22 33))
(check-equal? (concatenate (list lst2 lst3) lst0) '(22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst4) lst0) '(22 33 66 77 . 88))
(check-equal? (concatenate (list lst2 lst0 bool) lst0) '(22 33 . #f))
(check-equal? (concatenate (list lst2 lst0 lst0) lst0) '(22 33))
(check-equal? (concatenate (list lst2 lst0 lst1) lst0) '(22 33 11))
(check-equal? (concatenate (list lst2 lst0 lst2) lst0) '(22 33 22 33))
(check-equal? (concatenate (list lst2 lst0 lst3) lst0) '(22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst0 lst4) lst0) '(22 33 66 77 . 88))
(check-equal? (concatenate (list lst1 lst2 lst3) lst0) '(11 22 33 44 . 55))

(check-eq? (concatenate lst0 lst1) '())
(check-eq? (concatenate (list bool) lst1) bool)
(check-equal? (concatenate (list lst0 bool) lst1) '(11 . #f))
(check-equal? (concatenate (list lst0 lst0) lst1) '(11))
(check-equal? (concatenate (list lst0 lst1) lst1) '(11 11))
(check-equal? (concatenate (list lst0 lst2) lst1) '(11 22 33))
(check-equal? (concatenate (list lst0 lst3) lst1) '(11 44 . 55))
(check-equal? (concatenate (list lst0 lst4) lst1) '(11 66 77 . 88))
(check-equal? (concatenate (list lst0 lst0 bool) lst1) '(11 11 . #f))
(check-equal? (concatenate (list lst0 lst0 lst0) lst1) '(11 11))
(check-equal? (concatenate (list lst0 lst0 lst1) lst1) '(11 11 11))
(check-equal? (concatenate (list lst0 lst0 lst2) lst1) '(11 11 22 33))
(check-equal? (concatenate (list lst0 lst0 lst3) lst1) '(11 11 44 . 55))
(check-equal? (concatenate (list lst0 lst0 lst4) lst1) '(11 11 66 77 . 88))
(check-equal? (concatenate (list lst1 bool) lst1) '(11 11 . #f))
(check-equal? (concatenate (list lst1 lst0) lst1) '(11 11))
(check-equal? (concatenate (list lst1 lst1) lst1) '(11 11 11))
(check-equal? (concatenate (list lst1 lst2) lst1) '(11 11 22 33))
(check-equal? (concatenate (list lst1 lst3) lst1) '(11 11 44 . 55))
(check-equal? (concatenate (list lst1 lst4) lst1) '(11 11 66 77 . 88))
(check-equal? (concatenate (list lst1 lst0 bool) lst1) '(11 11 11 . #f))
(check-equal? (concatenate (list lst1 lst0 lst0) lst1) '(11 11 11))
(check-equal? (concatenate (list lst1 lst0 lst1) lst1) '(11 11 11 11))
(check-equal? (concatenate (list lst1 lst0 lst2) lst1) '(11 11 11 22 33))
(check-equal? (concatenate (list lst1 lst0 lst3) lst1) '(11 11 11 44 . 55))
(check-equal? (concatenate (list lst1 lst0 lst4) lst1) '(11 11 11 66 77 . 88))
(check-equal? (concatenate (list lst2 bool) lst1) '(22 33 11 . #f))
(check-equal? (concatenate (list lst2 lst0) lst1) '(22 33 11))
(check-equal? (concatenate (list lst2 lst1) lst1) '(22 33 11 11))
(check-equal? (concatenate (list lst2 lst2) lst1) '(22 33 11 22 33))
(check-equal? (concatenate (list lst2 lst3) lst1) '(22 33 11 44 . 55))
(check-equal? (concatenate (list lst2 lst4) lst1) '(22 33 11 66 77 . 88))
(check-equal? (concatenate (list lst2 lst0 bool) lst1) '(22 33 11 11 . #f))
(check-equal? (concatenate (list lst2 lst0 lst0) lst1) '(22 33 11 11))
(check-equal? (concatenate (list lst2 lst0 lst1) lst1) '(22 33 11 11 11))
(check-equal? (concatenate (list lst2 lst0 lst2) lst1) '(22 33 11 11 22 33))
(check-equal? (concatenate (list lst2 lst0 lst3) lst1) '(22 33 11 11 44 . 55))
(check-equal? (concatenate (list lst2 lst0 lst4) lst1) '(22 33 11 11 66 77 . 88))
(check-equal? (concatenate (list lst1 lst2 lst3) lst1) '(11 11 22 33 11 44 . 55))

(check-eq? (concatenate lst0 lst2) '())
(check-eq? (concatenate (list bool) lst2) bool)
(check-equal? (concatenate (list lst0 bool) lst2) '(22 33 . #f))
(check-equal? (concatenate (list lst0 lst0) lst2) '(22 33))
(check-equal? (concatenate (list lst0 lst1) lst2) '(22 33 11))
(check-equal? (concatenate (list lst0 lst2) lst2) '(22 33 22 33))
(check-equal? (concatenate (list lst0 lst3) lst2) '(22 33 44 . 55))
(check-equal? (concatenate (list lst0 lst4) lst2) '(22 33 66 77 . 88))
(check-equal? (concatenate (list lst0 lst0 bool) lst2) '(22 33 22 33 . #f))
(check-equal? (concatenate (list lst0 lst0 lst0) lst2) '(22 33 22 33))
(check-equal? (concatenate (list lst0 lst0 lst1) lst2) '(22 33 22 33 11))
(check-equal? (concatenate (list lst0 lst0 lst2) lst2) '(22 33 22 33 22 33))
(check-equal? (concatenate (list lst0 lst0 lst3) lst2) '(22 33 22 33 44 . 55))
(check-equal? (concatenate (list lst0 lst0 lst4) lst2) '(22 33 22 33 66 77 . 88))
(check-equal? (concatenate (list lst1 bool) lst2) '(11 22 33 . #f))
(check-equal? (concatenate (list lst1 lst0) lst2) '(11 22 33))
(check-equal? (concatenate (list lst1 lst1) lst2) '(11 22 33 11))
(check-equal? (concatenate (list lst1 lst2) lst2) '(11 22 33 22 33))
(check-equal? (concatenate (list lst1 lst3) lst2) '(11 22 33 44 . 55))
(check-equal? (concatenate (list lst1 lst4) lst2) '(11 22 33 66 77 . 88))
(check-equal? (concatenate (list lst1 lst0 bool) lst2) '(11 22 33 22 33 . #f))
(check-equal? (concatenate (list lst1 lst0 lst0) lst2) '(11 22 33 22 33))
(check-equal? (concatenate (list lst1 lst0 lst1) lst2) '(11 22 33 22 33 11))
(check-equal? (concatenate (list lst1 lst0 lst2) lst2) '(11 22 33 22 33 22 33))
(check-equal? (concatenate (list lst1 lst0 lst3) lst2) '(11 22 33 22 33 44 . 55))
(check-equal? (concatenate (list lst1 lst0 lst4) lst2) '(11 22 33 22 33 66 77 . 88))
(check-equal? (concatenate (list lst2 bool) lst2) '(22 33 22 33 . #f))
(check-equal? (concatenate (list lst2 lst0) lst2) '(22 33 22 33))
(check-equal? (concatenate (list lst2 lst1) lst2) '(22 33 22 33 11))
(check-equal? (concatenate (list lst2 lst2) lst2) '(22 33 22 33 22 33))
(check-equal? (concatenate (list lst2 lst3) lst2) '(22 33 22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst4) lst2) '(22 33 22 33 66 77 . 88))
(check-equal? (concatenate (list lst2 lst0 bool) lst2) '(22 33 22 33 22 33 . #f))
(check-equal? (concatenate (list lst2 lst0 lst0) lst2) '(22 33 22 33 22 33))
(check-equal? (concatenate (list lst2 lst0 lst1) lst2) '(22 33 22 33 22 33 11))
(check-equal? (concatenate (list lst2 lst0 lst2) lst2) '(22 33 22 33 22 33 22 33))
(check-equal? (concatenate (list lst2 lst0 lst3) lst2) '(22 33 22 33 22 33 44 . 55))
(check-equal? (concatenate (list lst2 lst0 lst4) lst2) '(22 33 22 33 22 33 66 77 . 88))
(check-equal? (concatenate (list lst1 lst2 lst3) lst2) '(11 22 33 22 33 22 33 44 . 55))

(check-equal? (concatenate lst0 lst3) lst0)

(check-tail-exn type-exception? (lambda () (concatenate bool)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 bool))))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst0 bool)))))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst1 (cons lst0 bool)))))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst1 bool)))))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst3))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 bool))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst3))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 bool))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst3))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst3))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 bool))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst3))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 bool))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst0))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst1))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst2))))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst3))))

(check-tail-exn type-exception? (lambda () (concatenate bool lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 bool) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst0 bool)) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst1 (cons lst0 bool)) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst1 bool)) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst3) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 bool) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst3) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 bool) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst3) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst3) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 bool) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst3) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 bool) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst0) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst1) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst2) lst0)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst3) lst0)))

(check-tail-exn type-exception? (lambda () (concatenate bool lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 bool) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst0 bool)) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst1 (cons lst0 bool)) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (cons lst0 (cons lst1 bool)) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list bool lst3) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 bool) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst3 lst3) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 bool) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst4 lst3) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 bool lst3) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 bool) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst3 lst3) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 bool) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst0) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst1) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst2) lst2)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst4 lst3) lst2)))

(check-tail-exn type-exception? (lambda () (concatenate lst0 bool)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0) bool)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst0) bool)))
(check-tail-exn type-exception? (lambda () (concatenate (list lst0 lst0) lst3)))

(check-tail-exn wrong-number-of-arguments-exception? (lambda () (concatenate)))
(check-tail-exn wrong-number-of-arguments-exception? (lambda () (concatenate lst0 lst1 lst1)))
