[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: summary: lilypond, lambda, and local-eval

From: Mark H Weaver
Subject: Re: summary: lilypond, lambda, and local-eval
Date: Fri, 16 Dec 2011 05:33:09 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.92 (gnu/linux)

Hi Andy, thanks for the quick feedback.  I'll respond to the rest of
your email later, but just a few quick notes for now:

> What are the meanings of these expressions:
>   ;; Toplevel
>   (local-eval '(define foo 42) (the-environment))
>   ;; Lexical, tail context
>   (local-eval '(define foo 42) (let ((x 100)) (the-environment)))
>   ;; Lexical, tail context -- but with a definition
>   (local-eval '(begin (define foo 42) foo) (let ((x 100)) (the-environment)))
>   ;; Lexical, tail context -- but with a definition, and nested reference
>   (local-eval '(begin (define foo 42) (bar))
>               (let ((x 100)) (define (bar) foo) (the-environment)))
>   ;; Lexical, not a definition context
>   (local-eval '(define foo 42) (let ((x 100)) not-a-definition 
> (the-environment)))

All of these will raise errors, because my current implementation of
`local-eval' (I just posted a new version of the evaluator-only patch)
uses `expand' instead of `expand-top-sequence' to expand the local
expression, therefore definitions are not allowed.

> What about this one:
>   ;; Keeping in mind that `or' expands to (let ((t ...)) (if t t ...)),
>   ;; hygienically
>   (local-eval 't '(let ((t 42)) (or #f (the-environment))))

Yes, even my first patch handles this properly (though you must use
`primitive-eval', since the compiler currently barfs if it encounters

scheme@(guile-user)> (local-eval 't (primitive-eval '(let ((t 42)) (or #f 
$1 = 42

> Can you pass syntax objects into `local-eval'?

I believe so, but I haven't verified that this works as it should.
I don't have much experience using syntax-case.

The expression passed to `local-eval' simply gets passed along to
`expand' within psyntax.scm, using the saved "expander environment":
i.e. the values of the `r', `w', and `mod' in psyntax, at the point
where (the-environment) was expanded.  This "expander environment" is
stored in the tree-il representation of (the-environment).

Here's what I currently see:

scheme@(guile-user)> (local-eval #'t (primitive-eval '(let ((t 42)) (or #f 
ERROR: In procedure memoize-variable-access!:
ERROR: Unbound variable: t

This is the correct behavior, no?

> Are let-syntax / letrec-syntax / nested define-syntax forms present in a
> local environment?


scheme@(guile-user)> (define env1 (primitive-eval '(let-syntax ((foo 
(syntax-rules () ((foo x) (quote x))))) (let ((x 1) (y 2)) (the-environment)))))
scheme@(guile-user)> (local-eval '(foo (1 2)) env1)
$3 = (1 2)
scheme@(guile-user)> (define env2 (local-eval '(let-syntax ((bar (syntax-rules 
() ((bar x) (foo x))))) (let ((x 1) (z 3)) (the-environment))) env1))
scheme@(guile-user)> (local-eval '(bar (1 2)) env2)
$5 = (1 2)
scheme@(guile-user)> (local-eval '(foo (1 2)) env2)
$6 = (1 2)

> Currently these things never leave the expander.  I suppose as long as
> they are understood to be opaque, it would be OK.

Agreed.  However, it should be noted that if we compile a form
containing (the-environment) into a .go file, the "expander environment"
will have to be stored within the .go file as an embedded constant.
This means that if the representations of r, w, or mod within psyntax
changes, any .go files containing uses of (the-environment) will have to
be recompiled, or else `local-eval' could fail ungracefully.

This is indeed an unpleasant complication.  Automatic recompilation
could be achieved using a versioning scheme, using a separate
expander-environment-version number.  With some care, we could perhaps
avoid needless recompilation of .go files that do not use
(the-environment) when the expander environment version changes, though
it might be a bit of a pain to do the necessary bookkeeping to determine
whether a .go file contains any expander environments.  I'll have to
think more about this.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]