public inbox for kawa@sourceware.org
 help / color / mirror / Atom feed
* Macro-generated define ignored?
@ 2013-10-10 15:04 Ito Kazumitsu
  2013-10-10 20:41 ` Per Bothner
  0 siblings, 1 reply; 4+ messages in thread
From: Ito Kazumitsu @ 2013-10-10 15:04 UTC (permalink / raw)
  To: kawa

Could you explain this case?

$ cat test.scm
(define-syntax foo
  (syntax-rules ()
    ((_ obj) (define a (obj:toString)))))
(foo (java.lang.String "aaa"))
(display a)(newline)
$ java -cp kawa-1.14.1-svn.jar kawa.repl --script test.scm
aaa
$ java -cp kawa-1.14.1-svn.jar kawa.repl test.scm
test.scm:5:10: warning - no declaration seen for a
test.scm:5:10: unbound location a
        at gnu.mapping.SharedLocation.get(SharedLocation.java:22)
        at gnu.mapping.ThreadLocation.get(ThreadLocation.java:105)
        at test.run(test.scm:5)
        at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:309)
        at gnu.expr.CompiledModule.evalModule(CompiledModule.java:41)
        at gnu.expr.CompiledModule.evalModule(CompiledModule.java:60)
        at kawa.Shell.runFile(Shell.java:497)
        at kawa.Shell.runFileOrClass(Shell.java:420)
        at kawa.repl.main(repl.java:862)

This issue is not kawa 1.14 specific. The same thing occurs with
kawa 1.11, 1.12 and 1.13.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Macro-generated define ignored?
  2013-10-10 15:04 Macro-generated define ignored? Ito Kazumitsu
@ 2013-10-10 20:41 ` Per Bothner
  2013-10-10 23:41   ` Ito Kazumitsu
  0 siblings, 1 reply; 4+ messages in thread
From: Per Bothner @ 2013-10-10 20:41 UTC (permalink / raw)
  To: Ito Kazumitsu; +Cc: kawa

On 10/10/2013 08:03 AM, Ito Kazumitsu wrote:
> Could you explain this case?
>
> $ cat test.scm
> (define-syntax foo
>    (syntax-rules ()
>      ((_ obj) (define a (obj:toString)))))
> (foo (java.lang.String "aaa"))
> (display a)(newline)
> $ java -cp kawa-1.14.1-svn.jar kawa.repl --script test.scm
> aaa
> $ java -cp kawa-1.14.1-svn.jar kawa.repl test.scm
> test.scm:5:10: warning - no declaration seen for a
> test.scm:5:10: unbound location a

This is an example of the power and the mystery of "macro hygiene".
In this case there is an 'a' that is local to the syntax-rules,
and there is an 'a' at the top-level scope.  These are distinct scopes,
so the reference to 'a' at top-level does not "see" the definition
of 'a' generated by the macro.

One solution is to pass the name of the top-level variable as
a macro parameter:

(define-syntax foo
   (syntax-rules ()
     ((_ var obj) (define var (obj:toString)))))
(foo a (java.lang.String "aaa"))
(display a)(newline)

You can replace 'var' by 'a' above if you prefer, but the
above is less confusing:

(define-syntax foo
   (syntax-rules ()
     ((_ a obj) (define a (obj:toString)))))
(foo a (java.lang.String "aaa"))
(display a)(newline)
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Macro-generated define ignored?
  2013-10-10 20:41 ` Per Bothner
@ 2013-10-10 23:41   ` Ito Kazumitsu
  2013-10-11  0:26     ` Per Bothner
  0 siblings, 1 reply; 4+ messages in thread
From: Ito Kazumitsu @ 2013-10-10 23:41 UTC (permalink / raw)
  To: kawa

From: Per Bothner <per@bothner.com>
Subject: Re: Macro-generated define ignored?
Date: Thu, 10 Oct 2013 13:41:04 -0700

> This is an example of the power and the mystery of "macro hygiene".
> In this case there is an 'a' that is local to the syntax-rules,
> and there is an 'a' at the top-level scope.  These are distinct
> scopes,
> so the reference to 'a' at top-level does not "see" the definition
> of 'a' generated by the macro.

Thank you for your explanation.

Is it accidental that the test script with the command line option
"--script" works as "expected"?

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Macro-generated define ignored?
  2013-10-10 23:41   ` Ito Kazumitsu
@ 2013-10-11  0:26     ` Per Bothner
  0 siblings, 0 replies; 4+ messages in thread
From: Per Bothner @ 2013-10-11  0:26 UTC (permalink / raw)
  To: Ito Kazumitsu; +Cc: kawa

On 10/10/2013 04:40 PM, Ito Kazumitsu wrote:
> From: Per Bothner <per@bothner.com>
> Subject: Re: Macro-generated define ignored?
> Date: Thu, 10 Oct 2013 13:41:04 -0700
>
>> This is an example of the power and the mystery of "macro hygiene".
>> In this case there is an 'a' that is local to the syntax-rules,
>> and there is an 'a' at the top-level scope.  These are distinct
>> scopes,
>> so the reference to 'a' at top-level does not "see" the definition
>> of 'a' generated by the macro.
>
> Thank you for your explanation.
>
> Is it accidental that the test script with the command line option
> "--script" works as "expected"?

Yes and no.  The Scheme top-level is an awkward special case:
Scheme is generally a lexically-scoped language.  However, there is
also traditionally a dynamic global environment: If a binding isn't
found in the lexical scope (which is determined at compile-time),
the instead we do a run-time lookup in the dynamic environment.
This is a big tension is Scheme: whether and how to make Scheme into
language focusing more on lexical (compile-time) bindings (such
as libraries/modules and hygienic macros) vs supporting the traditional
dynamic aspects of Scheme (like eval and load and old-fashioned
non-hygienic macro).  All Scheme implementations have to figure out
how to straddle these goals.  Kawa focuses more on the compile-time
bindings and analysis because I think those make it easier to write
correct and efficient programs (Kawa provides more compile-time warnings
that old-school Scheme does), but we still support the dynamic
environment.

So when you use --script (or -f) or you use the REPL we get some
compromises (not always intended): things are a little messier
and inconsistent than ideal.  Without a debugging session, I'm
not 100% sure what is going on with your program, but my assumption
is the following:  When line 4 (the foo macro invocation) is
evaluated in --script mode, we end up with a definition of a in the
dynamic environment.  When we compile line 5 (the reference to a),
the compiler first checks the lexical scope, and it checks the
dynamic scope (as it exists as compile time).  Since it seems
a definition of a, it doesn't complain.

That explains the compile-time warning.  What about the
runtime exception "unbound location a"?  That is because
when a gets defined to the run-time environment at the
*end* of evaluation.  As an experiment, try this:

(begin
(define-syntax foo
   (syntax-rules ()
     ((_ obj) (define a (obj:toString)))))
(foo (java.lang.String "aaa"))
(display a)(newline))

You'll notice that fails even if you evaluate it with --script.

A final complication is that a top-level variable might not get
added to the run-time environment *at all* if the variable is
module-private.  That is the default when you evaluate  a file
in module-at-a-time mode - or if you compile with --main.
-- 
	--Per Bothner
per@bothner.com   http://per.bothner.com/

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-10-11  0:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-10 15:04 Macro-generated define ignored? Ito Kazumitsu
2013-10-10 20:41 ` Per Bothner
2013-10-10 23:41   ` Ito Kazumitsu
2013-10-11  0:26     ` Per Bothner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).