Most language interpreters process a data structure generated by a parser commonly referred to as an abstract syntax tree or AST. Before we start defining and writing more serious interpreters, let’s start by defining and manipulating an abstract syntax tree for a simple expression language. Our expression language will have the following form:

value ::= TRUE, FALSE, 0, 1, 2, 3, ...
term ::= value | (term) | term + term | term - term | term < term | if term then term else term

The objective of this project is to define an abstract syntax data structure, define an evaluation function, and define a type checking function.

  1. Define an abstract syntax data structure using Scheme, ML, or Haskell.
  2. Define an evaluation function over your abstract syntax data structure. It should take an arbitrary abstract syntax structure and return either the value resulting from its evaluaton or a simple run-time error. You do not need to deal with ill-formed abstract syntax structures. Assume your AST structures are produced by a valid parser.
  3. Define a type checking function over your abstract syntax data structure. It should take an arbitrary abstract syntax structure and return a Boolean true if the AST structure is well-typed or false if it is not. Report any errors to the screen.
  4. Combine your solutions to problems 2 and 3 to construct a type checking evaluator. This evaluator should first call the type checking routine. If the input AST is not well-typed, then the evaluator should fail. If the input AST is well-typed, the evaluation function from Problem 2 should be called on the result.
  5. Can you guarantee that any AST structure that passes type checking will not crash when evaluated? Please explain