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

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Sat Jul 24 12:35:51 EDT 2010

Let me propose this: 

1. Define the grammar properly. In particular, distinguish the grammar for expressions from those for definitions. For example, 

  Expr is one of: 
    -- Variable 
    -- (+ Expr Expr) 
    -- (local (Definition*) Expr) 
    -- ...

  Definition is one of: 
    -- (define Variable Expr)
    -- (define-struct Variable (Variable*))

2. Then follow the design recipe from HtDP. Design one recursive function per grammar but also define the outputs you wish to get from each: 

  eval-for-expr : Expr -> ValueExpr 
  eval-for-definition* : [Listof Definition] -> ValueDefinition

I leave this to you as an exercise, but I recommend thinking of definitions as operators on environments. 

3. The ideas are embedded in our textbook HtDP. (See htdp.org)





On Jul 24, 2010, at 12:28 PM, Pedro Del Gallego wrote:

> 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.