title: Interpreter in Scheme
body: <p>Apology in advance as there is going to be a large block of code here. I will post the code first, followed by the question. </p>
  
  <pre><code>;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; UTILITY FUNCTIONS
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; Converts a scheme-expression into a string
  ;; INPUT: a scheme-expression EXP
  ;; OUTPUT: a SCHEME String corresponding to EXP
  (define (exp-&gt;string exp)
    (cond ((number? exp) (number-&gt;string exp))
          ((symbol? exp) (symbol-&gt;string exp))
          ((list? exp) (exp-&gt;string (car exp)))))
  
  ;; INPUT: a list of lists
  ;; OUTPUT: a list containing all elements of the first-level lists
  (define (flatten list-of-lists)
    (cond ((null? list-of-lists) '())
          (else (append (car list-of-lists) (flatten (cdr list-of-lists))))))
  
  ;; this is for all error handling.
  ;; programmers don't use this function but
  ;; the interpreter calls this function to
  ;; signal some type of programmer error
  (define (error msg)
    (display "ERROR: ")
    (display msg)
    (newline))
  
  ;; THERE ARE TWO SUPPORTED TYPES: 'int and 'boolean
  ;; INPUT: an element of the ART-C language
  ;; OUTPUT: the type of that element
  (define (type-of val)
    (cond ((number? val) 'int)
          ((boolean? val) 'boolean)))
  
  ;; A MAP is a list of key-value pairs
  ;; INPUT: a MAP and a KEY
  ;; OUTPUT: The value associated with the key or 'error
  (define (map-get map x)
    (cond ((null? map) 'error)
          ((equal? (car (car map)) x) (cadr (car map)))
          (else (map-get (cdr map) x))))
  
  ;; INPUT : A MAP AND KEY
  ;; OUTPUT : true if the key is in the map and false otherwise
  (define (map-contains map x)
    (cond ((null? map) #f)
          ((equal? (car (car map)) x) #t)
          (else (map-contains (cdr map) x))))
  
  ;; INPUT : A MAP, KEY and VALUE
  ;; OUTPUT: The map that results from replacing the key with the new value.  If
  ;; the map doesn't contain KEY, then 'error is returned
  (define (map-replace map key val)
    (cond ((null? map) 'error)
          ((equal? (car (car map)) key)
           (cons (list key val) (cdr map)))
          (else
           (cons (car map) (map-replace (cdr map) key val)))))
  
  ;; INPUT : A MAP, Key and Value
  ;; OUTPUT : The map that results from adding a key-value pair.  This
  ;; allows for duplicate keys (the most-recently added is nearer the front of the list
  (define (map-add map key val)
    (cons (list key val) map))
  
  ;; INPUT: A MAP and KEY
  ;; OUTPUT: The map that results from deleting the key.  No errors occur if the map
  ;; doesn't contain the key
  (define (map-delete map key)
    (cond ((null? map) map)
          ((equal? (car (car map)) key) (cdr map))
          (else (cons (car map)
                      (map-delete (cdr map) key)))))
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; TYPEMAP : A SEMANTIC DOMAIN DATA TYPE
  ;; A typemap is a list of block-level declarations.
  ;; FORM: ((var1 type1) (var2 type2) (var3 type3) ... )
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; INPUT: NONE
  ;; OUTPUT: AN empty typemap
  (define (typemap-create-empty) '())
  
  ;; INPUT: A TYPEMAP
  ;; OUTPUT: The type of variable x
  (define (typemap-type-of tm x)
    (map-get tm x))
  
  ;; INPUT: A TYPEMAP
  ;; OUTPUT: THE TYPEMAP THAT RESULTS FROM INSERTING A DECLARATIONS
  (define (typemap-add tm decl)
    (map-add tm (car decl) (cadr decl)))
  
  (define (typemap-delete tm key)
    (map-delete tm key))
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; STATE : A SEMANTIC DOMAIN DATA TYPE
  ;; A LIST OF (VAR, VALUE) pairs
  ;; FORM :  ( (var1 val1) (var2 val2) ... )
  ;; NOTE: A map can contain duplicate keys but innermost KEYS occur
  ;;       before outermost KEYS and hide them
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
  ;; INPUT : NONE
  ;; OUTPUT: AN EMPTY STATE
  (define (state-create-empty) '())
  
  ;; INPUT: STATE and ID
  ;; OUTPUT: a new state such that the innermost scope now contains a
  ;;         new binding for the specified ID.  The bindings value is 'undefined.
  (define (state-add state id)
    (map-add state id 'undefined))
  
  ;; INPUT : STATE and ID
  ;; OUTPUT: A new state such that the innermost id is removed
  (define (state-delete state id)
    (map-delete state id))
  
  ;; INPUT: STATE and ID
  ;; OUTPUT: The value associated with the specified ID in the given state
  (define (state-get-value state id)
    (map-get state id))
  
  ;; INPUT: STATE and ID
  ;; OUTPUT: A new state that results from changing the mapping from id-&gt;value in
  ;;         the specified state
  (define (state-update state id value)
    (map-replace state id value))
  
  ;; INPUT: STATE and LIST-OF-IDS (VARIABLES)
  ;; OUTPUT: A new state that results from deleting all ids (the variables) from
  ;;         the specified state
  (define (state-delete-all state variables)
    (cond ((null? variables) state)
          (else (state-delete-all (state-delete state (car variables)) (cdr variables)))))
  
  
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; THESE CLASSES CORRESPOND TO THE ABSTRACT SYNTAX SUCH THAT A "PROGRAM"
  ;; REPRESENTS A PARSE-TREE.  THESE FUNCTIONS OPERATE AT THE 'SYNTACTIC' LEVEL
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; (PROGRAM BODY)
  (define (program-get-body stmt)
    (cadr stmt))
  
  ;; (BLOCK S1...SN)
  (define (block-get-body stmt)
    (filter (lambda (x) (not (is-declaration? x))) (cdr stmt)))
  
  (define (block-get-declarations stmt)
    (filter (lambda (x) (is-declaration? x)) (cdr stmt)))
  
  ;; (DECLARE TYPE VAR)
  (define (declaration-get-type stmt)
    (cadr stmt))
  
  (define (declaration-get-var stmt)
    (caddr stmt))
  
  (define (is-declaration? stmt)
    (and (list? stmt) 
         (equal? (car stmt) 'declare)))
  
  ;; (:= VAR EXP)
  (define (assignment-get-var stmt)
    (cadr stmt))
  
  (define (assignment-get-exp stmt)
    (caddr stmt))
  
  ;; (IF TEST THEN [ELSE])
  (define (if-get-test stmt)
    (cadr stmt))
  
  (define (if-get-then stmt)
    (caddr stmt))
  
  (define (if-has-else? stmt)
    (= (length stmt) 4))
  
  (define (if-get-else stmt)
    (cadddr stmt))
  
  ;; (WHILE TEST BODY)
  (define (while-get-test stmt)
    (cadr stmt))
  
  (define (while-get-body stmt)
    (caddr stmt))
  
  ;; (SPRINT LABEL EXP)
  (define (sprint-has-exp? stmt)
    (and (list? stmt)
         (= (length stmt) 3)))
  
  (define (sprint-get-label? stmt)
    (cadr stmt))
  
  (define (sprint-get-exp stmt)
    (caddr stmt))
  
  ;; INPUT: an expression EXP
  ;; OUTPUT: the operator of EXP (an element of ART-C)
  (define (exp-get-operator exp)
    (car exp))
  
  ;; INPUT: an expression EXP
  ;; OUTPUT: the left-operand (an expression) of EXP
  (define (exp-get-left-operand exp)
    (car (cdr exp)))
  
  ;; INPUT: an expression EXP
  ;; OUTPUT: the exp-get-right-operand (an expression) of EXP
  (define (exp-get-right-operand exp)
    (car (cdr (cdr exp))))
  
  ;; INPUT: an expression EXP
  ;; OUTPUT: #t if the expression is a boolean literal and #f otherwise
  (define (bool? exp)
    (or (equal? exp 'true)
        (equal? exp 'false)))
  
  ;; INPUT: a symbol
  ;; OUTPUT: #t if the symbol is 'true and #f if it is 'false and 'void' if neither
  (define (symbol-&gt;bool sym)
    (cond ((equal? sym 'true) #t)
          ((equal? sym 'false) #f)))
  
  
  ;; INPUT: A PROGRAM
  ;; A PROGRAM has syntactic structure (program stmt)
  ;; OUTPUT: THE STATE that results from executing the program
  ;;         in an empty state.
  (define (interpret-program pgm)
    (interpret (program-get-body pgm) (state-create-empty)))
  </code></pre>
  
  <p>For this assignment we've been given this library of functions as a starting point and I'm just having a few comprehension issues following all the code. Using this library of functions our task is to implement the functions within the following interpret function:</p>
  
  <pre><code>(define (interpret stmt state)
    (display stmt) (newline) (display state) (newline)
    (let ((kind (car stmt)))
      (cond ((equal? kind 'block) (interpret-block stmt state))
            ((equal? kind 'declare) (interpret-declaration stmt state))
            ((equal? kind ':=) (interpret-assignment stmt state))
            ((equal? kind 'if) (interpret-if stmt state))
            ((equal? kind 'sprint) (interpret-sprint stmt state))
            ((equal? kind 'while) (interpret-while stmt state))       
            (else (error (string-append "statement expected but saw (" (exp-&gt;string stmt) "...) instead."))))))
  </code></pre>
  
  <p>I'm currently working on the interpret-block function but I'm not fully seeing the purpose of this function or how to implement it. In my mind, interpret-block would only be used for calling interpert-declaration, interpret-assignment, etc, but then isn't that what interpret is doing anyways? So I guess what I'm asking is, what is interpret-block supposed to actually accomplish?</p>
  
  <p>Below I've included a sample program this code is meant to interpret. </p>
  
  <pre><code>(define pgm '(program 
                (block
                 (declare int n)
                 (declare boolean error)
                 (declare int result)   
                 (:= error false)
                 (:= result 1)
                 (block 
                  (declare int local)
                  (:= n 5)
                  (:= local n)
                  (while (&gt; local 0)
                         (block
                          (:= result (* result local))
                          (:= local (- local 1)))))
                (sprint "result: " result)
                (if (! error) (sprint "a") (sprint "b")))))
  </code></pre>