CS212 Exams
Spring 1998 -
Final

Brenda and Dylan


In this problem you are to add a new special form to the metacircular evaluator from problem set 6. You may find the following functions from the evaluator useful in writing your code:

------------------------------------------------------------------------

  ;; APPLY
  (defgeneric (brenda-apply obj args env))
  
  ;; The default case is an error
  (defmethod (brenda-apply (obj <top>) 
                           (args <list>)
                           (env <brenda-frame>))
    (brenda-error "Apply : First elements in combination isn't a function." obj))
  
  ;; Primitives
  (defmethod (brenda-apply (obj <brenda-primitive>) 
                           (args <list>)
                           (env <brenda-frame>))
    (let ((evaluated-args (map (lambda (x) (brenda-eval x env)) args)))
      (args-params-match? (params obj) evaluated-args)
      (apply (calls obj) evaluated-args)))
  
  ;; Special Forms
  ;; Apply the Scheme function that performs the work of the special form
  ;; without evaluating the arguments. Assume the special form will do
  ;; type checking.
  (defmethod (brenda-apply (obj <brenda-special-form>) 
                           (args <list>)
                           (env <brenda-frame>))
    ((calls obj) args env))
  
  ;; User methods
  (defmethod (brenda-apply (obj <brenda-user-method>) 
                           (args <list>)
                           (e <brenda-frame>))
    (let ((evaluated-args (map (lambda (x) (brenda-eval x e)) args)))
      (args-params-match? (params obj) evaluated-args)
      (let ((new-env (expand-environment
                       (params obj) evaluated-args (env obj))))
        (eval-sequence (body obj) new-env))))

  ;; Special forms do not follow normal evaluation rules.
  (defclass <brenda-special-form> (<brenda-function>)
    (calls :type <function> :initarg :calls :accessor calls))
  
  (define (make-brenda-special-form f)
    (make <brenda-special-form> :calls f))
  
  ;; Define is basically just a set! at the global level
  (define (define-binding! (name <symbol>) val)
    (set-binding! name val *brenda-global-environment*))
  
  ;; EVAL
  (defgeneric (brenda-eval obj env))
  
  ;; Most kinds of object evaluate to themselves.
  (defmethod (brenda-eval (obj <top>) (env <brenda-fram>))
    obj)
  
  ;; Evaluating symbols causes their associated value to be looked up.
  (defmethod (brenda-eval (obj <symbol>) (env <brenda-fram>))
    (lookup obj env))
  
  ;; Evaluating a pair calls brenda-apply
  (defmethod (brenda-eval (obj <pair>) (env <brenda-fram>))
    (brenda-apply (brenda-eval (head obj) env) (tail obj) env))
  
  ;; If condition is false, an error has occured. reason is the reason.
  (define (brenda-assert (c <boolean>) (reason <string>))
    (when (not c) (brenda-error reason)))
  
  ;; Convert a parameter description from the user input as either "x" or
  ;; "(x <type>)" and create a brenda-parameter object out of it.
  (defgeneric (convert-param obj env))
  
  (defmethod (convert-param (p <symbol>) (e <brenda-frame>))
    (make-brenda-parameter p brenda-object-class))
  
  (defmethod (convert-param (p <list>) (e <brenda-frame>))
    (brenda-assert (= (length p) 2) "Badly formed parameter.")
    (make-brenda-parameter (head p) (brenda-eval (head (tail p)) e)))

  (defmethod (convert-param (p <top>) (e <brenda-frame>))
    (brenda-error "Badly formed parameter."))
------------------------------------------------------------------------

The new special form is called select. The first argument evaluates to a positive integer and the remaining arguments are expressions. select evaluates the first argument, and then selects the corresponding expressions. The selected expression is evaluated and the value is returned. None of the other expressions are evaluated.

==> (select 1 56)
56
==> (select 2 (/ 1 0) (+ 2 2) (+ 3 3))
4
==> (select (+ 1 2) 45 67 12 65)
12
==> (select 56 12)
error : not enough values to select from
==> (select 0 67 78)
error : selector value isn't positive!
==> (select "hello" "there")
error : first argument must evaluate to an <integer>

Write the code that must be added to the metacircular evaluator to handle the select special form.







Solution

Return to CS 212 Final - Spring 1998