[racket] How to create 'Internal Definitions' in a scheme interpreter.
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