diff --git a/Labs/05.rkt b/Labs/05.rkt new file mode 100644 index 0000000..0866657 --- /dev/null +++ b/Labs/05.rkt @@ -0,0 +1,64 @@ +#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) + (type-case Exp exp + [(strE v) (strT)] + [(numE v) (numT)] + [(prodE l r) + (let + ([lt (typecheck l)] + [rt (typecheck r)]) + (cond + [(and (numT? lt) (numT? rt)) lt] + [(numT? lt) rt] + [(numT? rt) lt] + [else (error 'typecheck "type mismatch")]))])) + +(test (typecheck (numE 6)) (numT)) +(test (typecheck (strE "hello")) (strT)) +(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") \ No newline at end of file