EECS 321:   Programming Languages — Homework 3
1 Functions that Accept Multiple Arguments
2 Errors
3 Handin Instructions
7.3

EECS 321: Programming Languages — Homework 3

1 Functions that Accept Multiple Arguments

Start with the F1WAE interpreter (WITHOUT deferred substitution), and extend the implementation to support any number of arguments to a function (including zero), and any number of arguments (including zero) in a function application:

<FunDef> = {deffun {<id> <id>*} <FnWAE>}

<FnWAE> = <num>

        | {+ <FnWAE> <FnWAE>}

        | {- <FnWAE> <FnWAE>}

        | {with {<id> <FnWAE>} <FnWAE>}

        | <id>

        | {<id> <FnWAE>*}

Since you must change the F1WAE datatype, and since different people may change it in different ways, you must provide a parse function this time, which accepts a quoted expression and produces an FnWAE value. For parsing, assume that any symbol other than '+, '-, or 'with can be a function name for a function call. Also, you must provide a parse-defn function that takes one (quoted) deffun form and produces a FunDef value.

Some examples:
(test (interp (parse '{f 1 2})
              (list (parse-defn '{deffun {f x y} {+ x y}})))
      3)
(test (interp (parse '{+ {f} {f}})
              (list (parse-defn '{deffun {f} 5})))
      10)

Hint: remember that the PLAI language provides the following useful function:

2 Errors

At run-time, a new error is now possible: function application with the wrong number of arguments. Your interp function should detect the mismatch and report an error that includes the words "wrong arity".

As with the interpreter from class, the free identifier error is still also possible and must be detected. Your interp function should detect free variables and report an error that includes the words "free identifier".

A function would be ill-defined if two of its argument <id>s were the same. To prevent this problem, your parse-defn function should detect this problem and reports a "bad syntax" error. For example, (parse-defn '{deffun {f x x} x}) should report a "bad syntax" error, while (parse-defn '{deffun {f x y} x}) should produce a FunDef value.

Similarly, your interpreter must check to see if the function position of an application is defined before evaluating the arguments. If not, an "undefined function" error should be raised.

Some examples:
(test/exn (interp (parse '{with {x y} 1})
                  (list))
          "free identifier")
(test/exn (interp (parse '{f 1 2})
                  (list (parse-defn '{deffun {f x x} {+ x x}})))
          "bad syntax")
(test/exn (interp (parse '{f x})
                  (list (parse-defn '{deffun {g a b c} c})))
          "undefined function")
(test/exn (interp (parse '{f 1})
                  (list (parse-defn '{deffun {f x y} {+ x y}})))
          "wrong arity")

Your interpreter must evaluate all of the argument expressions in an application expression before signaling any arity errors. For example:

(test/exn (interp (parse '{f x})
                  (list (parse-defn '{deffun {f a b c} c})))
          "free identifier")

If the list of definitions contains multiple definitions for the same function, use just the first one (ignoring the others).

Your interpreter and parser will not be given any other kinds of erroneous programs.

3 Handin Instructions

Provide definitions for parse, parse-defn, and interp, as above.

Have the 8 rules from the Provost’s website (see the homework 1 for more details).

Submit your code using the Handin button in DrRacket.