title: Implementing an interpreter for "if" statement in scheme
body: <p>I am trying to implement an interpreter in scheme. For now i implemented some part of it, but i am having problems with "if" statement. Here is the grammar:</p>
  
  <pre><code>&lt;s6&gt; -&gt; &lt;expr&gt;
          | &lt;define&gt;
  
  &lt;define&gt; -&gt; ( define IDENT &lt;expr&gt; )
  
  &lt;expr&gt; -&gt; NUMBER
            | IDENT
            | &lt;if&gt;
  
  &lt;if&gt; -&gt; ( if &lt;expr&gt; &lt;expr&gt; &lt;expr&gt; )
  </code></pre>
  
  <p>Here is the code i have written so far:</p>
  
  <pre><code>(define get-operator (lambda (op-symbol)
  (cond
      ((equal? op-symbol '+) +)
      ((equal? op-symbol '-) -)
      ((equal? op-symbol '*) *)
      ((equal? op-symbol '/) /)
      (else (error "s6-interpret: operator not implemented --&gt;" op-symbol)))))
  
  
  (define if-stmt? (lambda (e)
  (and (list? e) (equal? (car e) 'if) (= (length e) 4))))
  
  (define define-stmt? (lambda (e)
  (and (list? e) (equal? (car e) 'define) (symbol? (cadr e)) (= (length e) 3))))
  
  
  (define get-value (lambda (var env)
  (cond
      ((null? env) (error "s6-interpret: unbound variable --&gt;" var))
      ((equal? (caar env) var) (cdar env))
      (else (get-value var (cdr env))))))
  
  
  (define extend-env (lambda (var val old-env)
  (cons (cons var val) old-env)))
  
  
  (define repl (lambda (env)
  (let* (
      (dummy1 (display "cs305&gt; "))
      (expr (read))
      (new-env (if (define-stmt? expr)
                  (extend-env (cadr expr) (s6-interpret (caddr expr) env) env)env))
      (val (if (define-stmt? expr)
                  (cadr expr)
                  (s6-interpret expr env)))
      (dummy2 (display "cs305: "))
      (dummy3 (display val))
      (dummy4 (newline))
      (dummy4 (newline)))
  (repl new-env))))
  
  
  (define s6-interpret (lambda (e env)
  (cond
      ((number? e) e)
      ((symbol? e) (get-value e env))
      ((not (list? e)) (error "s6-interpret: cannot evaluate --&gt;" e))
      (if-stmt? e) (if (eq? (cadr e) 0) (map s6-interpret (cadddr e)) (map s6-interpret(caddr e))))
      (else
          (let ((operands (map s6-interpret (cdr e) (make-list (length (cdr e)) env)))
                  (operator (get-operator (car e))))
              (apply operator operands))))))
  
  
  (define cs305-interpreter (lambda () (repl '())))
  </code></pre>
  
  <p>The define statement works well. My code also includes implementation of some basic math operators, you can ignore them. My problem is, the "if" statement i implemented does not work as i expect. When i write "(if 1 (+ 2 5) 9)" it prints out (+ 2 5) but actually i want it to print out 7, which is 2+5. I think there is a problem about my recursion. Can anyone help me with this?</p>
  
  <p>Thank you</p>