Programming Assignment 4
CS 31600
Programming Languages
Spring, 2023

This assignment makes use of the files contained in this zip file. This assignment is due Friday, April 28.

In this assignment you will write part of a static analyzer for Language_5.

In hw3 you wrote a static analyzer for Language_4. The static analyzer for Language_4 finds syntax errors and type errors in a program before the program runs. Language_5 adds function definitions and function calls to Language_4. The static analyzer for Language_5 should find syntax errors in a program before a program runs, but because functions make the language quite a bit more complicated, the static analyzer for Language_5 cannot find type errors.

In the homework zip file there is a file language5a/AnalyzeAST.java that you need to complete. You need to complete three methods in that file, checkFun, checkLambda, and checkApply. I have completed all of the other static check methods in the file.

Here is what your implementations of checkFun, checkLambda, and checkApply need to check for.

For a function definition, the checkFun and checkLambda methods need to check that the function name has not already been defined, that no parameter name is repeated, and that the body of the lambda expression does not use any undefined variables (the body of a lambda expression should use only formal parameter variables and global variables).

Here is an example of a function definition with repeated parameter names.

    (fun f (lambda x x (* x x)))  // error: repeated parameter name

Here is an example of a function definition with an undefined variable and another function definition that uses a global variable.

    (prog
        (var c 1)
        (fun f (lambda x (+ x y)))  // error, undefined variable y
        (fun g (lambda x (+ x c)))  // no error, c is a global variable
        (apply f 12)
        (apply g 12))

The checkApply method should check the agreement between the number of actual parameters and the number of formal parameters when an apply-expression applies a globally defined function name defined by fun. For example, the following code has an incorrect application of function h, but the static analyzer will not detect this error (the evaluator will detect it at runtime). On the other hand, your checkApply method should detect the incorrect application of function f because the variable f is declared by fun.

    (prog
        (fun f (lambda x (* x x)))
        (var h f)
        (apply h 1 2)  // wrong number of arguments for h
        (apply f 1 2)) // wrong number of arguments for f

In the file language5a/AnalyzeAST.java there are outlines of the steps that each of the methods checkFun, checkLambda, and checkApply must do.

The biggest difference between AnalyzeAST.java and EvaluateAST.java is that the body of a lambda expression is analyzed as part of the analysis of the function declaration, not as part of a function application. So the code for checkLambda looks similar to the code for evaluateApply (and the code for checkApply has far fewer steps than the code for evaluateApply).

Carefully read the code in Language_5's EvlauateAST.java. Understanding that code is the main prerequisite for completing this assignment. If you understand how EvlauateAST.java does function definitions and function applications, then it should be fairly easy to modify its code into the code needed by checkFun, checkLambda, and checkApply in AnalyzeAST.java.

Read the file Language_5a.txt for details about the differences between Language_5a and Language_5.

When you have finished implementing AnalyzeAST.java, the files Language_5a_Examples.java and Language_5_Examples.java should compile and run. The output from running these programs should look exactly like the files Language_5a_Examples_output.txt and Language_5_Examples_output.txt.

You can also compile the program Language_5a.java which implements a REPL for Language_5a. And the folder Language_5a_demo contains a demo version of Language_5a.

Your code should compile without any warnings. These are programs that use Java generics. Getting generic code to compile without warnings can be tricky. But the warnings always mean that you are doing something wrong (they are really errors, not warnings). So try to figure out what is causing each warning (it is usually because you are either forgetting a type parameter or using the wrong type parameter). Ask me questions if you get stuck.

Do not change the package structure of this code. The tree implementation is in the tree package. The tokenizer is in the tokenizer package. The tree language parser is in the treelanguage package. The AnalyzeAST.java program is in the language5a package. The Language_5a.java interpreter and the test programs are in the "default" (unnamed) package. Don't change that. Do not put those files into some named package.

Turn in a zip file called CS316Hw4Surname.zip (where Surname is your last name) containing only your version of AnalyzeAST.java. Please be sure to put your name in your file.

This assignment is due Friday, April 28.