[racket] How to create 'Internal Definitions' in a schemeinterpreter.

From: Jos Koot (jos.koot at telefonica.net)
Date: Sat Jul 24 13:11:20 EDT 2010

I did not study your interpreter thoroughly, but I see you use a hash for an
environment. This is bound to go wrong, for the same variable may have
different bindings in nested scopes. You'll need a stack, or an
association-list or something like that, in which variables may be
shaddowed. Your interpreter is bound to give a wrong result for:

(let ((a 1))
  (let ((a 2))'who-cares)
  a)

This should produce 2, but I guess your interpreter returns -who-cares-.

Internal definitions are tricky if you allow -define- to be rebound as in
((lambda (define a) (define a 2)) + 3)
When evaluating (define a 2), you have to check what -define- means in the
current context.
For example:

(let ((a 3) (b 4))
  (define (define a b) (+ a b))
  (define a b)) -> 5

A simple means to avoid these problems is to exclude the names of (some)
syntactic forms from being used as variables (but that is not scheme like).
Following what Matthias already said: first carefully describe your language
(syntactic forms, expressions and primitive functions included). That is
already difficult enough.

Jos

> -----Original Message-----
> From: users-bounces at racket-lang.org 
> [mailto:users-bounces at racket-lang.org] On Behalf Of Pedro Del Gallego
> Sent: 24 July 2010 18:28
> To: users at racket-lang.org
> Subject: [racket] How to create 'Internal Definitions' in a 
> schemeinterpreter.
> 
> Hi,
> 
> I am writing my first interpreter, but  I am struggling with 
> the definitions of  'define', 'let' and 'letrec'.
> 
> Here is the source code intrepreter (> 100 loc) . 
> http://gist.github.com/487501
> 
> The problem is that 'define' requires access to the 
> enviroment. I as understand define is equivalent to these expansions.
> 
> ==== Top level.
> (define (foo)
>    (... (bar) ...))
> 
> => Will be
> 
> (define foo
>         (lambda ()
>            (... (bar) ...)))
> 
> 
> ==== In a lambda environment.
> 
> (define (my-proc)
>    (define (local-proc-1)
>       ...)
>    (define (local-proc-2)
>       ...)
>    (local-proc-1)
>    (local-proc-1))
> 
> => Will be
> 
> (define my-proc
>         (lambda ()
>            (letrec ((local-proc-1 (lambda () ...))
>                     (local-proc-2 (lambda () ...)))
>              (local-proc-1)
>              (local-proc-2)))
> 
> Can anyone point me how to implement this features. I am 
> trying to implement them out of the evaluator function, but I 
> guess that if they need access to the environment, maybe they 
> should be inside of the evaluator method. Maybe something like this?
> 
>     [`(letrec ,binds ,eb)
>           (eval-letrec binds eb env)]
> 
>     [`(let    ,binds ,eb)
>           (eval-let binds eb env)]
> 
> ; eval for letrec:
> (define (eval-letrec bindings body env)
>   (let* ((vars (map car bindings))
>          (exps (map cadr bindings))
>          (fs   (map (lambda _ #f) bindings))
>          (env* (extended-env* env vars fs))
>          (vals (map (evlis env*) exps)))
>     (env-set!* env* vars vals)
>     (eval body env*)))
> 
> ; eval for let:
> (define (eval-let bindings body env)
>   (let* ((vars (map car bindings))
>          (exps (map cadr bindings))
>          (vals (map (evlis env) exps))
>          (env* (extended-env* env vars vals)))
>     (eval body env*)))
> 
> (define ? )
> 
> I am new in this list, so let me know if this question is "off-topic".
> 
> 
> Thx.
> --
> -------------------------------------
> Pedro Del Gallego
> 
> Email              :   pedro.delgallego at gmail.com 
> _________________________________________________
>   For list-related administrative tasks:
>   http://lists.racket-lang.org/listinfo/users




Posted on the users mailing list.