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

Macros; lexcial scope



    Date: Thu, 26 May 88 12:50:54 EDT
    From: Ram-Ashwin@YALE.ARPA (Ashwin Ram)

    >    (define x 1)
    >    (define-macro (m) x)
    > 
    >    (let ((x 2))
    >      (m))
    > 
    > Would you expect that (m) evaluates to 1 or to 2?

    This evaluates (correctly) to 1 in T.

    > Now consider a slighly more complex example:
    > 
    >    (define x 1)
    > 
    >    (let ((x 2))
    >      (define-macro (m) x)
    >      (let ((x 3))
    >        (m)))
    > 
    > In both Common Lisp and C-Scheme, this evaluates to 1.  My mind boggles.

    This evaluates (correctly) to 2 if you use DEFINE-SYNTAX in T, but
    if you use DEFINE-LOCAL-SYNTAX this evaluates to 1.  Is this a bug,
    or am I missing something?

Wait a minute, you are using your own definition of "correct."  I would
say that T's behavior in both cases is incorrect (I designed T macros,
so I get to say).  You are also wrong about what happens; the behavior
you describe is true of interpreted code, but not for compiled code.  If
you compile the file first, you'll get "X unbound variable" for the
first case, and "M unbound variable" in the second.

It was always a goal in T to have interpreted and compiled code behave
the same (except when errors happen), but in the case of macros I
failed.  The fix is to change the semantics of LOAD to more closely
resemble the semantics of the compiler.  In particular, the environment
in which DEFINE-LOCAL-SYNTAX bodies are closed (you might call this the
"compile-time" environment) should be disjoint from that in which the
file in which the DEFINE-LOCAL-SYNTAX form occurs (the "run-time"
environment).  (DEFINE-MACRO is a combination of DEFINE-LOCAL-SYNTAX,
which defines a macro for compilation of the current file, and
DEFINE-SYNTAX, which causes a side-effect on some syntax table when the
file is loaded.)  This would correspond to the situation with, say, a C
compiler, where compilation takes place in a different address space\n from execution; this is a desirable an option for T as well.  Also, when
a file is loaded by the interpreter, all macros should be expanded
before any of the forms are evaluated, in order to reduce sensitivity to
side-effects on the compile-time environment that the file itself may
perform.  I.e.
    (load "foo.t" env) 
ought to mimic
    (block (compile-file "foo.t") (load "foo.obj"))
as closely as possible.

I have considered making these changes for the next version of T, but
they really ought to be done in conjunction with the addition of a
module system, so that values can get from one environment to another
more gracefully (e.g., from the run-time environment to the compile-time
environment) than they do now.