This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GSOC | Extending Common Lisp support


On Jun 2, 2012, at 6:46 PM, I wrote:

On a related note, occasionally the "no declaration seen for" warning is
just plain wrong:


$ cat /tmp/test.lisp
(defvar foo 42)
(write foo) (newline)
$ kawa /tmp/test.lisp
/tmp/test.lisp:2:8: warning - no declaration seen for foo
42

Line 2 apparently didn't notice the declaration of foo on line 1.

and


Note that here the problem is more than just a superfluous or erroneous
warning: without the -f, (write list-of-numbers) is writing the function
and not the list, indicating that the defun stored the procedure in the
wrong place. With the -f, the behavior is correct.


I got a little further along with this, but am stuck now. I found the
reason for the erroneous warnings when defun'ing and defvar'ing: both
defun.java and defvar.java are calling defs.lookup(Object) to look
for previous declarations, when they should only be looking for ones
in their own namespaces. This fixes that (I will send in an actual
patch later):

in defun.java:
-    Declaration decl = defs.lookup(sym);
+    Declaration decl = defs.lookup(sym, tr.getLanguage(),
+                                   Language.FUNCTION_NAMESPACE);

in defvar.java:
-	Declaration decl = defs.lookup(name);
+	Declaration decl = defs.lookup(name, tr.getLanguage(),
+                                       Language.VALUE_NAMESPACE);


Now I'm trying to figure out why it isn't noticing actual declarations, as with (defvar foo 42) (write foo) which issues a warning even though it shouldn't.



First I added a printout to Translator.java when it creates a ReferenceExp:

$ svn diff kawa/lang/Translator.java
Index: kawa/lang/Translator.java
===================================================================
--- kawa/lang/Translator.java (revision 7243)
+++ kawa/lang/Translator.java (working copy)
@@ -813,6 +813,7 @@
return syntaxError("reference to pattern variable "+decl.getName()+" outside syntax template");
}


+ System.out.println("creating refexp: "+nameToLookup+", "+decl);
ReferenceExp rexp = new ReferenceExp (nameToLookup, decl);
rexp.setContextDecl(cdecl);
rexp.setLine(this);

With that, I see this behavior with Scheme:


$ cat /tmp/test.scm
(define x "hello")
(define (y) 1)
(write (y)) (newline)
(write x) (newline)
(write y) (newline)
$ kawa /tmp/test.scm
creating refexp: define, Declaration[define/4]
creating refexp: %define, Declaration[null/14]
creating refexp: define, Declaration[define/4]
creating refexp: %define, Declaration[null/14]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: y, Declaration[y/16]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: x, Declaration[x/15]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: y, Declaration[y/16]
creating refexp: newline, Declaration[newline/35]
1
"hello"
#<procedure y>

Note that each ReferenceExp is being constructed with a non-null Declaration. But in Common Lisp:

$ cat /tmp/namespaces.lisp
(defvar x "hello")
(defun x () 1)
(write (x)) (newline)
(write x) (newline)
(write #'x) (newline)
$ kawa /tmp/namespaces.lisp
creating refexp: defvar, null
creating refexp: defun, null
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: x, null
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: x, null
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: function, null
creating refexp: newline, Declaration[newline/22]
/tmp/namespaces.lisp:3:8: warning - no declaration seen for x
/tmp/namespaces.lisp:4:8: warning - no declaration seen for x
/tmp/namespaces.lisp:5:8: warning - no declaration seen for x
/tmp/namespaces.lisp:3:8: unbound location x (property (function))
	at gnu.mapping.Location.get(Location.java:67)
	at namespaces.run(namespaces.lisp:3)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:299)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:41)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:60)
	at kawa.Shell.runFile(Shell.java:511)
	at kawa.Shell.runFileOrClass(Shell.java:426)
	at kawa.repl.main(repl.java:880)

Not only are my own 'var and 'un declarations null, so are #'defvar and #'defun (!). Not entirely sure what to make of that, but I figured maybe something's going wrong when the Declarations from a ScopeExp are pushed to lexical (a NameLookup).

So I added some more printf's there:

$ svn diff gnu/expr/NameLookup.java
Index: gnu/expr/NameLookup.java
===================================================================
--- gnu/expr/NameLookup.java	(revision 7243)
+++ gnu/expr/NameLookup.java	(working copy)
@@ -52,6 +52,7 @@

   public void push (Declaration decl)
   {
+    System.out.println(" lexical.push: "+decl);
     Object symbol = decl.getSymbol();
     if (symbol == null)
       return;
@@ -93,6 +94,7 @@

   public void push (ScopeExp exp)
   {
+    System.out.println("lexical.push:"+exp);
     for (Declaration decl = exp.firstDecl();
          decl != null;  decl = decl.nextDecl())
       push(decl);


With that in place, when I rerun my Scheme test I see this:

$ kawa /tmp/test.scm
lexical.push:ModuleExp:null/1/
creating refexp: define, Declaration[define/4]
lexical.push:ModuleExp:kawa.lib.prim_syntax/2/
 lexical.push: Declaration[define-syntax/3]
 lexical.push: Declaration[define/4]
...
 lexical.push: Declaration[$instance/13]
lexical.push:kawa.lang.TemplateScope#3(for #<macro define>)
creating refexp: %define, Declaration[null/14]
lexical.push:ModuleExp:null/1/l:1
 lexical.push: Declaration[x/15]
creating refexp: define, Declaration[define/4]
lexical.push:ModuleExp:kawa.lib.prim_syntax/2/
 lexical.push: Declaration[define-syntax/3]
 lexical.push: Declaration[define/4]
...
 lexical.push: Declaration[$instance/13]
lexical.push:kawa.lang.TemplateScope#5(for #<macro define>)
creating refexp: %define, Declaration[null/14]
lexical.push:ModuleExp:null/1/l:1
 lexical.push: Declaration[x/15]
 lexical.push: Declaration[y/16]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: y, Declaration[y/16]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: x, Declaration[x/15]
creating refexp: newline, Declaration[newline/35]
creating refexp: write, Declaration[write/38]
creating refexp: y, Declaration[y/16]
creating refexp: newline, Declaration[newline/35]
1
"hello"
#<procedure y>

Two things jump out at me: (1) My module is pushed three times,
once as ModuleExp:null/1/ and twice as ModuleExp:null/1/l:1,
and the latter two times it actually pushes my declared
symbols (first just x, then x and y). It looks like it's
getting pushed multiple times due to the "finally { setCurrentScope(...); }"
restorations in Translator.java in combination with the happy
accident that the builtins require loading other modules
(notably prim_syntax). (2) By the time we're creating the
x and y ReferenceExps, they've been pushed to the NameLookup.


Here's what happens in CL:

$ kawa /tmp/namespaces.lisp
lexical.push:ModuleExp:null/1/
creating refexp: defvar, null
creating refexp: defun, null
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: x, null
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: x, null
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: function, null
creating refexp: newline, Declaration[newline/22]
/tmp/namespaces.lisp:3:8: warning - no declaration seen for x
/tmp/namespaces.lisp:4:8: warning - no declaration seen for x
/tmp/namespaces.lisp:5:8: warning - no declaration seen for x
/tmp/namespaces.lisp:3:8: unbound location x (property (function))
	at gnu.mapping.Location.get(Location.java:67)
	at namespaces.run(namespaces.lisp:3)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:299)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:41)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:60)
	at kawa.Shell.runFile(Shell.java:511)
	at kawa.Shell.runFileOrClass(Shell.java:426)
	at kawa.repl.main(repl.java:880)

Notice that lexical.push only happens once, at the top (when the Scheme version still didn't have its variable declarations ready yet, either). Maybe I can trick it by forcing another module load, e.g. by putting in a Scheme-style define statement, which I know will trigger prim_syntax:

$ cat /tmp/namespaces.lisp
(define y 2)
(defvar x "hello")
(defun x () 1)
(write (x)) (newline)
(write x) (newline)
(write #'x) (newline)

$ kawa /tmp/namespaces.lisp
lexical.push:ModuleExp:null/1/
creating refexp: define, Declaration[define/3]
lexical.push:ModuleExp:kawa.lib.prim_syntax/2/
 lexical.push: Declaration[define-syntax/2]
... (so far so good)
 lexical.push: Declaration[$instance/12]
lexical.push:kawa.lang.TemplateScope#3(for #<macro define>)
creating refexp: %define, Declaration[null/14]
lexical.push:ModuleExp:null/1/l:1
 lexical.push: Declaration[y/15]
creating refexp: defvar, null
creating refexp: defun, null
creating refexp: write, Declaration[write/39]
creating refexp: newline, Declaration[newline/36]
creating refexp: write, Declaration[write/39]
creating refexp: newline, Declaration[newline/36]
...
/tmp/namespaces.lisp:4:8: warning - no declaration seen for x
/tmp/namespaces.lisp:5:8: warning - no declaration seen for x
/tmp/namespaces.lisp:6:8: warning - no declaration seen for x
/tmp/namespaces.lisp:4:8: unbound location x (property (function))
	at gnu.mapping.Location.get(Location.java:67)
	at namespaces.run(namespaces.lisp:4)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:299)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:41)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:60)
	at kawa.Shell.runFile(Shell.java:511)
	at kawa.Shell.runFileOrClass(Shell.java:426)
	at kawa.repl.main(repl.java:880)


OK, I got my second push, but it only pushed y, and I still
get null refexps for X and the three warnings. Maybe that's
because it's at the top of the file (after all, Scheme took
more than two pushes). So I move the (define y 2) to the
last line and try again:

$ kawa /tmp/namespaces.lisp
lexical.push:ModuleExp:null/1/
creating refexp: defvar, null
creating refexp: defun, null
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: newline, Declaration[newline/22]
creating refexp: define, Declaration[define/46]
lexical.push:ModuleExp:kawa.lib.prim_syntax/3/
 lexical.push: Declaration[define-syntax/45]
 lexical.push: Declaration[define/46]
...
 lexical.push: Declaration[$instance/55]
lexical.push:kawa.lang.TemplateScope#4(for #<macro define>)
creating refexp: %define, Declaration[null/57]
lexical.push:ModuleExp:null/1/l:1
 lexical.push: Declaration[x/2]
 lexical.push: Declaration[x/3]
 lexical.push: Declaration[y/58]
creating refexp: write, Declaration[write/25]
creating refexp: x, Declaration[x/3]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: x, Declaration[x/2]
creating refexp: newline, Declaration[newline/22]
creating refexp: write, Declaration[write/25]
creating refexp: function, null
creating refexp: newline, Declaration[newline/22]
/tmp/namespaces.lisp:5:8: warning - no declaration seen for x
1
"hello"
/tmp/namespaces.lisp:5:8: unbound location x (property (function))
	at gnu.mapping.Location.get(Location.java:67)
	at namespaces.run(namespaces.lisp:5)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:299)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:41)
	at gnu.expr.CompiledModule.evalModule(CompiledModule.java:60)
	at kawa.Shell.runFile(Shell.java:511)
	at kawa.Shell.runFileOrClass(Shell.java:426)
	at kawa.repl.main(repl.java:880)


Better! Kind of. Now both of my X declarations have been pushed,
and their ReferenceExps are non-null. "(write (x))" and "(write x)"
both succeeded, and I'm down to 1 warning, where it's complaining
about "#'x".


But that's where I'm stuck. I have two problems: 1. How/where to force the declarations to be pushed to the NameLookup without requiring the silly hack of loading another module. Clearly the defun/defvar statements themselves *should* be enough. 2. How to get (function x) to find the defun'd function.


-- Jamison Hope The PTR Group www.theptrgroup.com




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]