only typecheck left

This commit is contained in:
Isaac Shoebottom 2025-04-08 13:03:17 -03:00
parent 232bd43a7d
commit e5b13e035a

View File

@ -35,7 +35,6 @@
[listT (element : Type)] ;; New [listT (element : Type)] ;; New
[varT (id : Number) (val : (Boxof (Optionof Type)))]) [varT (id : Number) (val : (Boxof (Optionof Type)))])
(define-type ValueEnv (define-type ValueEnv
[EmptyValueEnv] [EmptyValueEnv]
[BindValue (name : Symbol) [BindValue (name : Symbol)
@ -68,6 +67,7 @@
[(plusE l r) (num+ (interp l env) (interp r env))] [(plusE l r) (num+ (interp l env) (interp r env))]
[(minusE l r) (num- (interp l env) (interp r env))] [(minusE l r) (num- (interp l env) (interp r env))]
[(timesE l r) (num* (interp l env) (interp r env))] [(timesE l r) (num* (interp l env) (interp r env))]
[(listE elements) (listV (map (lambda (x) (interp x env)) elements))]
[(idE name) (lookup name env)] [(idE name) (lookup name env)]
[(if0E test then-part else-part) [(if0E test then-part else-part)
(if (numzero? (interp test env)) (if (numzero? (interp test env))
@ -89,8 +89,13 @@
(interp (closureV-body lam-val) (interp (closureV-body lam-val)
(BindValue (closureV-param lam-val) (BindValue (closureV-param lam-val)
arg-val arg-val
(closureV-env lam-val))))] (closureV-env lam-val))))]))
[(listE lst) (listV (map (lambda (x) (interp x env)) lst))])) ;; TODO COME BACK TO
(define (run s-expr)
(interp (parse s-expr) (EmptyValueEnv)))
(define (check s-expr)
(typecheck (parse s-expr) (EmptyTypeEnv)))
(define (lookup name env) (define (lookup name env)
(type-case ValueEnv env (type-case ValueEnv env
@ -120,6 +125,8 @@
[(true) (boolE #t)] [(true) (boolE #t)]
[(false) (boolE #f)] [(false) (boolE #f)]
[else (idE sym)]))] [else (idE sym)]))]
[(s-exp-match? `(list ANY ...) sx)
(listE (map (lambda (elt) (parse elt)) (rest (s-exp->list sx))))]
[(s-exp-match? `(lam (SYMBOL : ANY) ANY) sx) [(s-exp-match? `(lam (SYMBOL : ANY) ANY) sx)
(let* ([args (sx-ref sx 1)] (let* ([args (sx-ref sx 1)]
[id (s-exp->symbol (sx-ref args 0))] [id (s-exp->symbol (sx-ref args 0))]
@ -154,7 +161,9 @@
[(bool) (boolTE)] [(bool) (boolTE)]
[(?) (guessTE)])] [(?) (guessTE)])]
[(s-exp-match? `(ANY -> ANY) sx) [(s-exp-match? `(ANY -> ANY) sx)
(arrowTE (parse-te (sx-ref sx 0)) (parse-te (sx-ref sx 2)))])) (arrowTE (parse-te (sx-ref sx 0)) (parse-te (sx-ref sx 2)))]
[(s-exp-match? `(listof ANY) sx)
(listTE (parse-te (sx-ref sx 1)))]))
(module+ test (module+ test
(define fact-rec (define fact-rec
@ -234,8 +243,8 @@
[(boolTE) (boolT)] [(boolTE) (boolT)]
[(arrowTE a b) (arrowT (parse-type a) [(arrowTE a b) (arrowT (parse-type a)
(parse-type b))] (parse-type b))]
[(guessTE) (varT (gen-tvar-id!) (box (none)))] [(guessTE)(varT (gen-tvar-id!) (box (none)))]
[(listTE e) .... ])) [(listTE element-te) (listT (parse-type element-te))]))
(define (type-lookup name-to-find env) (define (type-lookup name-to-find env)
(type-case TypeEnv env (type-case TypeEnv env
[(EmptyTypeEnv ) (error 'type-lookup "free variable, so no type")] [(EmptyTypeEnv ) (error 'type-lookup "free variable, so no type")]
@ -317,18 +326,24 @@
[(varT id2 is2) (unify-type-var! t2 t1 expr)] [(varT id2 is2) (unify-type-var! t2 t1 expr)]
[(numT) (unify-assert! t1 (numT) expr)] [(numT) (unify-assert! t1 (numT) expr)]
[(boolT) (unify-assert! t1 (boolT) expr)] [(boolT) (unify-assert! t1 (boolT) expr)]
[(listT element-type)
(type-case Type t1
[(listT other-element-type) (unify! element-type other-element-type expr)]
[else (type-error expr t1 t2)])]
[(arrowT a2 b2) [(arrowT a2 b2)
(type-case Type t1 (type-case Type t1
[(arrowT a1 b1) [(arrowT a1 b1)
(begin (begin
(unify! a1 a2 expr) (unify! a1 a2 expr)
(unify! b1 b2 expr))] (unify! b1 b2 expr))]
[else (type-error expr t1 t2)])]
[(listT a2)
(type-case Type t1
[(listT a1) (unify! a1 a2 expr)]
[else (type-error expr t1 t2)])])])) [else (type-error expr t1 t2)])])]))
(module+ test
(test (unify! (listT (boolT)) (listT (boolT)) 'test) (void))
(test/exn (unify! (listT (boolT)) (listT (numT)) 'test) "no type")
(test/exn (unify! (boolT) (listT (numT)) 'test) "no type")
(test/exn (unify! (listT (numT)) (boolT) 'test) "no type"))
(define (typecheck [exp : Exp] [env : TypeEnv]) : Type (define (typecheck [exp : Exp] [env : TypeEnv]) : Type
(type-case Exp exp (type-case Exp exp
[(numE n) (numT)] [(numE n) (numT)]
@ -375,15 +390,12 @@
(let* ([arg-type (parse-type te)] (let* ([arg-type (parse-type te)]
[res-type (typecheck body (BindType name arg-type env))]) [res-type (typecheck body (BindType name arg-type env))])
(arrowT arg-type res-type))] (arrowT arg-type res-type))]
[(listE list) .... ] [(listE elements) (begin
(define type-list (map (lambda (x) (typecheck x env)) elements))
(listT )]
)) ))
;; ---------------------------------------- ;; ----------------------------------------
(define (run s-expr)
(interp (parse s-expr) (EmptyValueEnv)))
(define (check s-expr)
(typecheck (parse s-expr) (EmptyTypeEnv)))
(define-syntax-rule (test/type expr type) (define-syntax-rule (test/type expr type)
(test (test
@ -422,6 +434,10 @@
(numV 3)) (numV 3))
) )
(module+ test
(test (run `{list 1 2}) (listV (list (numV 1) (numV 2))))
(test (run `{list false true false}) (listV (list (boolV #f) (boolV #t) (boolV #f)))))
(module+ test (module+ test
(print-only-errors #t) (print-only-errors #t)
@ -532,20 +548,6 @@
#;(test/exn (typecheck (recE 'f (arrowTE (numTE) (numTE)) (idE 'f) (appE (idE 'f) (numE 10))) #;(test/exn (typecheck (recE 'f (arrowTE (numTE) (numTE)) (idE 'f) (appE (idE 'f) (numE 10)))
(EmptyTypeEnv)) (EmptyTypeEnv))
"no type")) "no type"))
;; New list tests
;; ------------------------------------
(module+ test
(test (unify! (listT (boolT)) (listT (boolT)) 'test) (void))
(test/exn (unify! (listT (boolT)) (listT (numT)) 'test) "no type")
(test/exn (unify! (boolT) (listT (numT)) 'test) "no type")
(test/exn (unify! (listT (numT)) (boolT) 'test) "no type"))
(module+ test
(test (run `{list 1 2}) (listV (list (numV 1) (numV 2))))
(test (run `{list false true false}) (listV (list (boolV #f) (boolV #t) (boolV #f)))))
(module+ test (module+ test
;; lists of numbers ;; lists of numbers
(test/type `{list 1 2} (listT (numT))) (test/type `{list 1 2} (listT (numT)))
@ -572,3 +574,14 @@
;; infer type of list from function application ;; infer type of list from function application
(test/type `{{lam {x : ?} {list x}} 2} (listT (numT))) (test/type `{{lam {x : ?} {list x}} 2} (listT (numT)))
) )
(module+ test
(test (unify! (listT (boolT)) (listT (boolT)) 'test) (void))
(test/exn (unify! (listT (boolT)) (listT (numT)) 'test) "no type")
(test/exn (unify! (boolT) (listT (numT)) 'test) "no type")
(test/exn (unify! (listT (numT)) (boolT) 'test) "no type"))
(module+ test
(test (run `{list 1 2}) (listV (list (numV 1) (numV 2))))
(test (run `{list false true false}) (listV (list (boolV #f) (boolV #t) (boolV #f)))))