
(htdp-syntax-test #'())
(htdp-syntax-test #'#%app)

(htdp-syntax-test #'quote)
(htdp-syntax-test #'(quote 1 2))

(htdp-syntax-test #'define)
(htdp-syntax-test #'(define))
(htdp-syntax-test #'(define x))
(htdp-syntax-test #'(define x 10 12))
(htdp-syntax-test #'(define (10 y) 12))
(htdp-syntax-test #'(define ("x" y) 12))
(htdp-syntax-test #'(define (y 10) 12))
(htdp-syntax-test #'(define (y "x") 12))
(htdp-syntax-test #'(define (y z 10) 12))
(htdp-syntax-test #'(define (x y) 10 12))
(htdp-syntax-test #'(define (x y y) 10))
(htdp-syntax-test #'(define () 10))
(htdp-syntax-test #'(define 1 10))
(htdp-syntax-test #'(define x lambda))
(htdp-syntax-test #'(define x (lambda)))
(htdp-syntax-test #'(define x (lambda (x))))
(htdp-syntax-test #'(define x (lambda y)))
(htdp-syntax-test #'(define x (lambda y 10)))
(htdp-syntax-test #'(define x (lambda (10) 10)))
(htdp-syntax-test #'(define x (lambda (x 10) 10)))
(htdp-syntax-test #'(define x (lambda (y) 10 11)))
(htdp-syntax-test #'(define x (lambda (y) 10 11)))
(htdp-syntax-test #'(define x (lambda (y y) 10)))
(htdp-syntax-test #'(+ (define x 5)))

;; Keywords:
(htdp-syntax-test #'(define (define y) 12))
(htdp-syntax-test #'(define (lambda y) 12))
(htdp-syntax-test #'(define (cond y) 12))
(htdp-syntax-test #'(define (if y) 12))
(htdp-syntax-test #'(define (y define) 12))
(htdp-syntax-test #'(define (y lambda) 12))
(htdp-syntax-test #'(define (y cond) 12))
(htdp-syntax-test #'(define (y if) 12))
(htdp-syntax-test #'(define (y and) 12))
(htdp-syntax-test #'(define (y or) 12))
(htdp-syntax-test #'(define (y true) 12))
(htdp-syntax-test #'(define (y false) 12))
(htdp-syntax-test #'(define (y empty) 12))

(htdp-syntax-test #'define-struct)
(htdp-syntax-test #'(define-struct))
(htdp-syntax-test #'(define-struct a))
(htdp-syntax-test #'(define-struct a (b) 10))
(htdp-syntax-test #'(define-struct a (b) 10 11 12))
(htdp-syntax-test #'(define-struct 10 (b)))
(htdp-syntax-test #'(define-struct a b))
(htdp-syntax-test #'(define-struct a (10)))
(htdp-syntax-test #'(define-struct a (b 10)))
(htdp-syntax-test #'(define-struct (a) (b)))
(htdp-syntax-test #'(define-struct a (b b)))
(htdp-syntax-test #'(define-struct lambda (b)))
(htdp-syntax-test #'(+ 1 (define-struct a (b))))

(htdp-top (define x 5))
(htdp-top (define (f y) (+ x y)))
(htdp-test 5 'lookup x)
(htdp-test 9 'app-f (f 4))
(htdp-top (define f2 (lambda (y) (+ x y))))
(htdp-test 15 'app-f (f 10))
(htdp-top-pop 1)
(htdp-top-pop 1)

(htdp-top (define-struct a0 ()))
(htdp-top (define-struct a1 (b)))
(htdp-top (define-struct a3 (b c d)))
(htdp-test #t 'a0? (a0? (make-a0)))
(htdp-test #t 'a1? (a1? (make-a1 1)))
(htdp-test #t 'a3? (a3? (make-a3 1 2 3)))
(htdp-test #f 'a1? (a1? (make-a3 1 2 3)))
(htdp-test #f 'a3? (a3? (make-a1 1)))

(htdp-syntax-test #'cond)
(htdp-syntax-test #'(cond))
(htdp-syntax-test #'(cond 1))
(htdp-syntax-test #'(cond [#t 6] 2))
(htdp-syntax-test #'(cond [else 6] [#f 10]))
(htdp-syntax-test #'(cond [else 6] [else 10]))
(htdp-syntax-test #'(cond []))
(htdp-syntax-test #'(cond [1]))
(htdp-syntax-test #'(cond [1 2 3]))
(htdp-syntax-test #'(cond [1 2][]))
(htdp-syntax-test #'(cond [1 2][3 4 5]))

(htdp-test 17 'cond (cond [else 17]))
(htdp-test 18 'cond (cond [#t 18]))
(htdp-test 19 'cond (cond [(zero? 10) 0] [#t 19]))
(htdp-test 19 'cond (cond [(zero? 10) 0] [else 19]))

(htdp-err/rt-test (cond [#f 10]) exn:fail?) ;; Should it be a different exception?
(define rx:not-true-or-false "not true or false")
(htdp-err/rt-test (cond [1 10]) rx:not-true-or-false)

(htdp-syntax-test #'if)
(htdp-syntax-test #'(if))
(htdp-syntax-test #'(if #t))
(htdp-syntax-test #'(if #t 1))
(htdp-syntax-test #'(if #t 1 2 3))

(htdp-err/rt-test (if 1 2 3) rx:not-true-or-false)

(htdp-syntax-test #'and)
(htdp-syntax-test #'(and))
(htdp-syntax-test #'(and #t))

(htdp-err/rt-test (and 1 #t) rx:not-true-or-false)
(htdp-err/rt-test (and #t 1) rx:not-true-or-false)
(htdp-test #f 'ok-and (and #t #f 1))

(htdp-syntax-test #'or)
(htdp-syntax-test #'(or))
(htdp-syntax-test #'(or #t))

(htdp-err/rt-test (or 1 #f) rx:not-true-or-false)
(htdp-err/rt-test (or #f 1) rx:not-true-or-false)
(htdp-test #t 'ok-or (or #f #t 1))

(htdp-test #t 'empty? (empty? empty))
(htdp-test #t 'cons? (cons? (cons 1 empty)))

(htdp-err/rt-test (cons 1 2))
(htdp-err/rt-test (append (list 1) 2))

(htdp-test #t 'boolean? (boolean? true))
(htdp-test #t 'boolean? (boolean? false))
(htdp-test #t 'eq? (eq? #t true))
(htdp-test #t 'eq? (eq? #f false))

(htdp-err/rt-test (+) exn:application:arity?)
(htdp-err/rt-test (+ 1) exn:application:arity?)
(htdp-err/rt-test (*) exn:application:arity?)
(htdp-err/rt-test (* 1) exn:application:arity?)
(htdp-err/rt-test (-) exn:application:arity?)
(htdp-err/rt-test (/) exn:application:arity?)
(htdp-err/rt-test (/ 1) exn:application:arity?)

(htdp-test -9 '- (- 9))

(htdp-top (define-struct an-example-structure (first-field second-field)))
(htdp-error-test #'(define an-example-structure 5))
(htdp-error-test #'(define (an-example-structure x) 5))
(htdp-error-test #'(define-struct an-example-structure (y)))
(htdp-error-test #'(define-struct an-example (structure y)))
(htdp-top-pop 1)

(htdp-top (define an-example-value 12))
(htdp-error-test #'(define an-example-value 5))
(htdp-error-test #'(define (an-example-value x) 5))
(htdp-error-test #'(define-struct an-example-value (y)))
(htdp-error-test #'(define-struct an-example (value y)))
(htdp-top-pop 1)

(htdp-top (define (an-example-function x) x))
(htdp-error-test #'(define an-example-function 5))
(htdp-error-test #'(define (an-example-function x) 5))
(htdp-error-test #'(define-struct an-example-function (y)))
(htdp-error-test #'(define-struct an-example (function y)))
(htdp-top-pop 1)

(htdp-test #t 'equal? (equal? 1 1))
(htdp-test #t 'equal? (equal? (list 1) (list 1)))
(htdp-test #t 'equal? (equal? (list #i1.0 2) (list #i1.0 2)))
(htdp-test #f 'equal? (equal? (list #i1.0 2) (list #i1.0 #i2.0)))
(htdp-test #t 'equal? (equal? (list "apple") (list "apple")))
(htdp-test #f 'equal? (equal? (list "apple") (list 'apple)))
(htdp-test #f 'equal? (equal? (list "apple") (list "banana")))
(htdp-test #t 'equal? (equal? (make-posn 1 2) (make-posn 1 2)))
(htdp-test #f 'equal? (equal? (make-posn 1 #i2.0) (make-posn 1 2)))
(htdp-test #t 'equal? (equal? (make-a1 2) (make-a1 2)))
(htdp-test #f 'equal? (equal? (make-a1 #i2.0) (make-a1 2)))

(htdp-test #t 'equal~? (equal~? 1 1 #i0.1))
(htdp-test #t 'equal~? (equal~? (list 1) (list 1) #i0.1))
(htdp-test #t 'equal~? (equal~? (list #i1.0 2) (list #i1.0 2) #i0.1))
(htdp-test #t 'equal~? (equal~? (list #i1.0 2) (list #i1.0 #i2.0) #i0.1))
(htdp-test #f 'equal~? (equal~? (list #i1.0 2) (list #i1.0 2.2) #i0.1))
(htdp-test #t 'equal~? (equal~? (list "apple") (list "apple") #i0.2))
(htdp-test #f 'equal~? (equal~? (list "apple") (list 'apple) #i0.2))
(htdp-test #f 'equal~? (equal~? (list "apple") (list "banana") #i0.2))
(htdp-test #t 'equal~? (equal~? (make-posn 1 2) (make-posn 1 2) #i0.2))
(htdp-test #t 'equal~? (equal~? (make-posn 1 #i2.0) (make-posn 1 2) #i0.2))
(htdp-test #t 'equal~? (equal~? (make-a1 2) (make-a1 2) #i0.2))
(htdp-test #t 'equal~? (equal~? (make-a1 #i2.0) (make-a1 2) #i0.2))
(htdp-test #f 'equal~? (equal~? (make-a1 #i2.3) (make-a1 2) #i0.2))

(htdp-top-pop 1)
(htdp-top-pop 1)
(htdp-top-pop 1)

;; Error messages
(htdp-top (define my-x 5))
(htdp-top (define (my-f x) (+ x 5)))
(htdp-syntax-test #'(cond [true my-x 5]) #rx"found a clause with 3 parts")
(htdp-syntax-test #'(define foo17 my-x 5) #rx"found one extra part")
(htdp-syntax-test #'(my-y 17) #rx"not defined, not an argument, and not a primitive name")
(htdp-syntax-test #'(cond [true my-y 17]) #rx"not defined, not an argument, and not a primitive name")
(htdp-syntax-test #'(define my-f 12) #rx"cannot be re-defined")
(htdp-syntax-test #'(define (my-x h) 12) #rx"cannot be re-defined")
(htdp-top-pop 1)
(htdp-top-pop 1)
