#lang plait
(define-type Exp
[strE (v : String)]
[numE (v : Number)]
[prodE (l : Exp) (r : Exp)])
(define-type Value
[numV (n : Number)]
[strV (s : String)])
(define-type Type
[numT]
[strT])
(define (times n str) (if (zero? n) "" (string-append str (times (sub1 n) str))))
(define (interp slang)
(type-case Exp slang
[(strE s) (strV s)]
[(numE n) (numV n)]
[(prodE l r)
(let ([l-v (interp l)]
[r-v (interp r)])
(cond
[(and (numV? l-v) (numV? r-v))
(numV (* (numV-n l-v) (numV-n r-v)))]
[(numV? l-v)
(strV (times (numV-n l-v) (strV-s r-v)))]
[(numV? r-v)
(strV (times (numV-n r-v) (strV-s l-v)))]
[else (error 'interp "type mismatch")]))]))
(test (interp (prodE (numE 6) (numE 7))) (numV 42))
(test (interp (prodE (numE 3) (strE "ha"))) (strV "hahaha"))
(test (interp (prodE (numE 2) (prodE (numE 2) (strE "ha")))) (strV "hahahaha"))
(test (interp (prodE (strE "hello") (numE 3))) (strV "hellohellohello"))
(test/exn (interp (prodE (strE "hello") (strE "world"))) "mismatch")
(define (typecheck exp)
....)
(test (typecheck (prodE (numE 6) (numE 7))) (numT))
(test (typecheck (prodE (numE 3)
(prodE (numE 6) (numE 7)))) (numT))
(test (typecheck (prodE (numE 3) (strE "ha"))) (strT))
(test (typecheck (prodE (strE "hello") (numE 3))) (strT))
(test (typecheck (prodE (prodE (numE 3) (numE 6))
(numE 7))) (numT))
(test/exn (typecheck (prodE (strE "hello") (strE "world"))) "mismatch")
(test/exn (typecheck (prodE (prodE (numE 2) (strE "hello")) (strE "world"))) "mismatch")
(test/exn (typecheck (prodE (prodE (numE 2) (strE "hello"))
(prodE (strE "world") (numE 3)))) "mismatch")
(test/exn (typecheck (prodE (strE "3") (prodE (numE 6) (strE "7")))) "mismatch")
(test/exn (typecheck (prodE (strE "3") (prodE (strE "6") (strE "7")))) "mismatch")