On this page:
2.18.1 Template
2.18.2 Type Judgments
2.18.3 Required Functions
parse-type
type-of

2.18 Type Checker

Complete this assignment with Team Three.

You must submit this in an archive named "typec.zip".

You must submit this in a file named "typec.ss".

You must complete this assignment in the PLAI Scheme language. You can do so by choosing it from the Language|Choose Language... menu in DrScheme or via the language chooser at the bottom-left. You can also choose the Module language and have the following as the first line of your program:

  #lang planet plai/plai

In this assignment, you will work with a typed language that includes numbers, booleans, conditionals, functions, and numeric lists. The concrete syntax for the language is given by the following BNF grammars:

  expr = num
  | true
  | false
  | (+ expr expr)
  | (- expr expr)
  | (* expr expr)
  | (iszero expr)
  | (bif expr expr expr)
  | id
  | (with (id expr) expr)
  | (fun (id : type) : type expr)
  | (expr expr)
  | nempty
  | (ncons expr expr)
  | (nempty? expr)
  | (nfirst expr)
  | (nrest expr)
     
  type = number
  | boolean
  | nlist
  | (type -> type)

You have not implemented some of these constructs yet, but they should be familiar:

2.18.1 Template

You must use the following template:

  (define-type Expr
    [num (n number?)]
    [id (v symbol?)]
    [bool (b boolean?)]
    [bin-num-op (op procedure?) (lhs Expr?) (rhs Expr?)]
    [iszero (e Expr?)]
    [bif (test Expr?) (then Expr?) (else Expr?)]
    [with (bound-id symbol?) (bound-body Expr?) (body Expr?)]
    [fun (arg-id symbol?)
         (arg-type Type?) (result-type Type?)
         (body Expr?)]
    [app (fun-expr Expr?) (arg-expr Expr?)]
    [nempty]
    [ncons (first Expr?) (rest Expr?)]
    [nfirst (e Expr?)]
    [nrest (e Expr?)]
    [isnempty (e Expr?)])
  
  (define-type Type
    [t-num]
    [t-bool]
    [t-nlist]
    [t-fun (arg Type?) (result Type?)])
  
  ; parse : s-expression -> Expr
  (define (parse sexp)
    (match sexp
      [(list '+ lhs rhs)  (bin-num-op + (parse lhs) (parse rhs))]
      [(list '- lhs rhs)  (bin-num-op - (parse lhs) (parse rhs))]
      [(list '* lhs rhs)  (bin-num-op * (parse lhs) (parse rhs))]
      [(list 'iszero e)   (iszero (parse e))]
      [(list 'bif c t f)  (bif (parse c) (parse t) (parse f))]
      [(list 'with (list name named-expr) body)  (with name (parse named-expr) (parse body))]
      [(list 'fun (list arg-name ': arg-type) ': result-type body)
       (fun arg-name (parse-type arg-type) (parse-type result-type) (parse body))]
      [(list 'ncons f r)  (ncons (parse f) (parse r))]
      [(list 'nempty? l)  (isnempty (parse l))]
      [(list 'nfirst l)  (nfirst (parse l))]
      [(list 'nrest l)  (nrest (parse l))]
      [(list f a)  (app (parse f) (parse a))]
      [_ (case sexp
           [(true)  (bool true)]
           [(false)  (bool false)]
           [(nempty)  (nempty)]
           [else (cond [(number? sexp)  (num sexp)]
                       [(symbol? sexp)  (id sexp)]
                       [else  (error 'parse "illegal syntax: ~e" sexp)])])]))
  
  ; parse-type : s-expression -> Type
  (define (parse-type sexp)
    (error 'parse-type "not implemented"))
  
  ; type-of : Expr -> Type
  (define (type-of e)
    (error 'type-of "not implemented"))

2.18.2 Type Judgments

Write down type judgments for the five numeric list constructs: nempty, ncons, nempty?, nfirst, and nrest. (These count as special test cases.)

You must submit this in a file named "judgments.pdf".

2.18.3 Required Functions

(parse-type sexp)  Type?
  sexp : s-expression?

This consumes an s-expression and returns a Type. It is a helper function for parse.

You should thoroughly test parse-type to ensure that it parses all valid types. You may find match useful (as it is used in parse).

(type-of e)  Type?
  e : Expr?

This consumes the abstract representation of a program (i.e. the result of parse). If the program has no type errors, type-of returns the type of the program. If the program has a type error, type-of should invoke error with an appropriate error message. For example:

  (type-of (parse '{+ 1 2}))

should produce (t-num), while:

  (type-of (parse '{3 4}))

should call error with some string, e.g. "Number is not a function".

You should thoroughly test type-of to ensure that every kind of expression can be typed in as many ways as is reasonable. Similarly, make sure type-of catches every kind of type error. In particular, you should make sure type-of does not catch run-time errors, such as (nfirst nempty).

Do not implement an evaluator, just a type checker.