2

I'm trying to write a toy python Scheme interpreter based on the meta-circular evaluator in SICP. Since python only supports a call stack of limited depth, I have to eliminate the tail calls. I read about trampolines and implemented the parser with it.

But I don't know how to write the analyzer/evaluator functions in continuation-passing style to use them with trampolines. For example, the eval-if function:

(define (eval-if expr env)
    (if (is-true? (eval (if-predicate expr) env))
        (eval (if-consequent expr) env)
        (eval (if-alternate expr) env)))

in python:

def eval_if(expr, env):
    if is_true(eval(if_predicate(expr), env)):
        return eval(if_consequent(expr), env)
    else:
        return eval(if_alternate(expr), env)

when I want to check if the predicate is true, I have to call a new round of eval on it. How should I write this kind of recursive calls in CPS form?

hammar
  • 138,522
  • 17
  • 304
  • 385
pjhades
  • 1,948
  • 2
  • 19
  • 34

1 Answers1

3

In scheme/Racket, you'd write the CPSed form of this function as:

;; evaluate an 'if':
(define (eval-if expr env k)
  (eval (if-predicate expr) env
        (lambda (testval)
          (if (is-true? testval)
              (eval (if-consequent expr) env k)
              (eval (if-alternate expr) env k)))))

Note that this assumes that your 'eval' is also written in CPS. In Python, you can presumably use "lambda" if Guido allows you to; otherwise, I believe that you can define an internal function for this.

John Clements
  • 16,895
  • 3
  • 37
  • 52
  • Thanks:) I followed [this paper](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.45.5447&rep=rep1&type=pdf) to implement the `pogo_stick` trampoline scheduler. I have difficulties in writing these functions in python since it will include a lot of internal functions. The case is worse if I think about separating the analyzer from `eval`. To evaluate `(set! var expr)`, `expr` should be first analyzed and then executed, both of the two steps will be enclosed in the `pogo_stick` scheduler. Maybe I should think of other ways to optimize the tail call? Sorry it's a little vague. – pjhades Feb 15 '12 at 12:24
  • 1
    Yup. You're following a plan similar to what I did with my PyScheme implementation (https://hkn.eecs.berkeley.edu/~dyoo/python/pyscheme/) Good luck with your implementation! – dyoo Feb 15 '12 at 17:29
  • @dyoo, I've read some of your PyScheme code, it helps me a lot when I was confused :). – pjhades Feb 16 '12 at 00:47