;
; Replace all of this top-level comment with a high-level description of your
; general approach to the solution.  Also, add a brief explanatory comment
; above each function that you implement, describing your implementation.
;
; In the body of the outlined functions, replace all of the comment function
; calls with code.  That is replace all of the expressions of the form
; "(comment -- ...)" with Lisp code that does what the comment says needs to be
; done.
;


;
; This macro is used to identify comments that you'll replace with code.
; There's nothing for you to do here but just leave this macro as is.
;
(defmacro comment (&rest l) ())


;
; Evaluate the given expr in the context of the given program memory.  Return a
; two-element list consisting of the result of evaluation and a possibly
; updated memory.
;
(defun xeval (expr memory)

    ;
    ; The body of xeval is a single conditional that checks the form of the
    ; input expr and handles it accordingly.
    ;
    (cond

        ;
        ; The special form ":dump" is for producing a memory dump for
        ; debugging purposes.  There's nothing for you to do here.
        ;
        ( (eq expr ':dump)
          (terpri) (princ "MEMORY DUMP:")
          (pprint memory) (terpri)
          (list 'end\ dump memory) )

        ;
        ; Handle an atomic expression input.
        ;
        ( (numberp expr)       (comment -- return numbers as is) )
        ( (stringp expr)       (comment -- ditto for strings) )
        ( (eq expr t)          (comment -- ditto for t) )
        ( (null expr)          (comment -- and ditto for nil) )
        ( (atom expr)
            (cond
                ( (comment -- check if the atom name is in memory)
                  (comment --  and if so use its bound value) )
                ( t (comment -- otherwise print an "Unbound Variable" error) )
            )
        )

        ;
        ; All possibilities for an atomic expr have been checked to here.  Now
        ; check for function calls.
        ;
        ( (atom (car expr))
            (cond
                ( (eq (car expr) 'xquote)
                  (comment -- return quotes as is) )

                ( (eq (car expr) 'xsetq)
                  (comment -- call eval-xsetq with appropriate args) )

                ( (eq (car expr) 'xcond)
                  (comment -- call eval-xcond with appropriate args) )

                ( (eq (car expr) 'xdefun)
                  (comment -- call eval-xdefun with appropriate args) )

                ( (comment -- if memory value of (car expr) is a function body)
                  (comment -- then call xapply to evaluate it) )

                ( t (comment -- call eval-with-gcl for the rest) )

            )
        )
        ( t (comment -- what if (car expr) is not an atom?) )
    )
)

(defun eval-xsetq (atom-name value memory)
    (comment -- bind name to value in memory))

(defun eval-xcond (expr memory)
    (comment -- evaluate a conditional))

(defun eval-xdefun (fn-name formals fn-body memory)
    (comment -- add fn-name to  along with its formal parms and body))

(defun xapply (fn-body formals actuals memory)
    (comment -- bind args and xeval fn-body))

(defun xbind (formals actuals memory)
    (comment -- extend the memory with new bindings (called from xapply)))

(defun xeval-list (expr-list memory)
    (comment -- x-evaluate a list of exprs returning the value of the last
        (called from eval-xcond and xapply))
)

(defun eval-with-gcl (expr memory)
    (comment -- if expr is a function\, xevaluate each arg\, and then use gcl
    to eval.  If expr is not a function\, send expr directly to gcl.)
)

(defun xeval-list-list (expr-list memory)
    (comment -- x-evaluate a list of exprs returning a list of quoted values
        (called from eval-with-gcl))
)

(comment -- add additional auxiliary function you may need)