Writing an interpreter for a language with breaks

时间:2016-03-04 18:18:40

标签: scheme racket interpreter continuations continuation-passing

I'm trying to write an interpreter for a simple programming language in Scheme. Right now, I'm writing a procedure to handle while-loops with break statements. To approach this problem, I'm using call/cc.

When the language is parsed, it looks like this:

var x = 0;
while (x < 10) {
  x = x - 1;
  break;
  x = x + 100;
}
return x;

turns into

((var x 0) (while (< x 10) (begin (= x (- x 1)) (break) (= x (+ x 100)))) (return x))

My approach to interpreting these statements is as follows:

(define while_break
  (lambda (cond body state)
    (call/cc
     (lambda (break-cont)
       (letrec
           ((Mstate_loop (lambda (cond body state)
                         ; Need second loop
                         (if (eq? (M_Bool cond state) #t)
                             (call/cc
                              (lambda (second-break-cont)
                                (letrec
                                  ((Body_loop (lambda (body_line state)
                                                (cond
                                                  ((null? body_line) (second-break-cont state))
                                              ; Conditions to exit the loop
                                              ((eq? (first_line body_line) 'break) (second-break-cont state))
                                              ; If this is the last line, run it and break
                                              ((null? (rest_of_lines body_line)) (second-break-cont (M_State body_line state)))
                                              ; Otherwise, run the next line
                                              (else (Body_loop (rest_of_lines body_line) (M_State (first_line body_line) state)))))))
                            (Body_loop body state))))
                          (break-cont state)
                          ))))
        (Mstate_loop cond body state))
     ))))


(define first_line car)
(define rest_of_lines cdr)

Where (M_State statement state) returns the current state updated to reflect statement (e.g. the state ((x) (2)) represents x = 2. (M_State '(var x 5) '((x) (2))) would return ((x) (5)).)

When I put this through the debugger, the line ((null? body_line) (second-break-cont state)) always calls upon second-break-cont, even though body_line is not null. I've spent a lot of time debugging this, but can't seem to find the error. Any help in spotting my mistake would be greatly appreciated.

1 个答案:

答案 0 :(得分:1)

我没有详细研究过你的代码,但我注意到了一件事。您的主函数和外部循环都有一个名为cond的参数。这将遮蔽您尝试在内循环中使用的内置cond宏。

事实上,仅此一点就可以解释为什么总是会调用(second-break-cont state)cond表达式不再是宏调用,而是普通的函数调用,因此会对所有表达式进行求值。

您应该将参数调用为cond以外的其他参数。