Q1 ----------------------------------------------------------------------------

              [(with) (app (fun (first (second sexp))
                                (parse (third sexp))) 
                           (parse (second (second sexp))))]

Q2(a) -------------------------------------------------------------------------

(define-type CFAE-Value 
            [numV (n number?)] 
            [closureV (param symbol?) 
                      (body CFAE?) 
                      (env Env?)] 
            [exprV (expr CFAE?) 
                   (env Env?)]) 

Q2(b) -------------------------------------------------------------------------

Linha         Novo conteudo  

 5               [add (l r) (numV (+ (numV-n (strict (interp l env)))
 6                                   (numV-n (strict ((interp r env))))]

 8                    (if (zero? (numV-n (strict (interp test env))))

15                    (local ([define fun-val (strict (interp fun-expr env))])

18                                    (exprV arg-expr env)

Q2(c) -------------------------------------------------------------------------

;; strict : CFAE-Value -> CFAE-Value [exceto exprV] 
(define (strict e) 
       (type-case CFAE-Value e 
                  [exprV (expr env) (strict (interp expr env))]
                  [else e]))

Q3 ----------------------------------------------------------------------------

Na chamada recursiva a interp nas linhas 16-19, o ambiente passado como
parametro deve deixar de estender o ambiente da definicao da funcao (o qual e'
capturado pelo fechamento fun-val) e passar a estender o ambiente de uso da
funcao. Para isso, basta alterar a linha 19, que deixa de ser

    19                                    (closureV-env fun-val))))]))

e passa a ser

    19                                    env)))]))

Q4 ----------------------------------------------------------------------------

    [set (var value) 
            (type-case Value*Store (interp value env store) 
              [v*s (value-value value-store) 
                   (local ([define the-loc (env-lookup var env)])
                     (v*s value-value 
                          (aSto the-loc value-value value-store)))])]

Q5 ----------------------------------------------------------------------------

Restringiremos nossa atencao `as "chamadas mais interessantes" de interp,
isto e', as chamadas que tem alguma novidade no ambiente. Em outras palavras,
vamos ignorar as chamadas recursivas a interp que receberem um ambiente igual 
ao da execucao de interp que efetuou a chamada recursiva.

Esta solucao mostra detalhes de representacao de ambientes (mtSub, aSub, 
aRecSub) mas esses detalhes nao sao importantes.

1. Ambiente externo (ambiente passado como parametro na chamada a interp que
   avalia a forma rec): 

   (mtSub)

2. Ambiente E passado como parametro na chamada recursiva a interp que avalia
   o corpo da forma rec: 

   (aRecSub 'fac 
            (box (closureV 'n
                           (if0 ...)
                           E))
            (mtSub))

   [Aqui o importante e' que o ambiente contido no closureV e' o proprio E!]

3. Ambiente passado como parametro na chamada recursiva a interp que avalia o 
   corpo da funcao na aplicacao {fac 2}:

   (aSub 'n
         (numV 2)
         (aRecSub 'fac 
                  (box (closureV 'n
                                 (if0 ...)
                                 E))
                  (mtSub))

   Como o identificador n nao esta' vinculado a zero, a avaliacao do if0
   gera a aplicacao {fac 1}.

4. Ambiente passado como parametro na chamada recursiva a interp que avalia o
   corpo da funcao na aplicacao {fac 1}:

   (aSub 'n
         (numV 1)
         (aRecSub 'fac 
                  (box (closureV 'n
                                 (if0 ...)
                                 E))
                  (mtSub))

   Como o identificador n nao esta' vinculado a zero, a avaliacao do if0
   gera uma chamada {fac 0}.

5. Ambiente passado como parametro na chamada recursiva a interp que avalia o 
   corpo da funcao na aplicacao {fac 0}:

   (aSub 'n
         (numV 0)
         (aRecSub 'fac 
                  (box (closureV 'n
                                 (if0 ...)
                                 E))
                  (mtSub))

   Agora a avaliacao do if0 produz (numV 1). A chamada a interp para {fac 0} 
   devolve esse valor.

6. O valor de {fac 0} e' multiplicado pelo n do ambiente 4 (que tambem e' 
   (numV 1)), produzindo (numV 1), que e' o valor devolvido pela chamada a 
   interp para {fac 1}.
   

7. O (numV 1) e' multiplicado pelo n do ambiente 3 (que e' (numV 2)), 
   produzindo (numV 2), que e' o valor devolvido pela chamada a interp para
   {fac 2}.

8. A primeira chamada a interp recebe o resultado da chamada recursiva que
   interpretou {fac 2} e o devolve como valor da forma rec.