This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: GSOC | Extending Common Lisp support
On 21 June 2012 05:30, Jamison Hope <jrh@theptrgroup.com> wrote:
> $ svn diff gnu/expr/Declaration.java
Thanks, this solves the module export problem. Per, you're code didn't
help the module export problem for me (probably I misunderstood your
input).
> Anyway, with any of those changes in place, #'do and #'case run without
> compilation error, but they give the wrong answers.
I can get the right answer for the case example with my change below,
DO is behaving in a confusing way for me still.
> Note that falsehood in CL is checked by comparing for object equality
> with EmptyList.emptyList. However, IsEqv#apply2 performs
>
> Âpublic Object apply2 (Object arg1, Object arg2)
> Â{
> Â Âreturn language.booleanObject(apply(arg1, arg2));
> Â }
>
> using the language from its constructor -- in this case, Scheme. So,
> Boolean.FALSE != EmptyList.emptyList, and false becomes true.
So what I think we'd want is instead of IsEqv, IsEq's apply2 method
calling language.booleanType, we'd rather have
Language.getDefault().booleanType. That's a problem because when the
primitives.lisp file is being evaluated, we haven't finished setting
up the Language environment from the common-line parameters. You get
around this for CL by add the following line to initLisp() (which is
eventually called from the repl.java setup when it invokes
Language.getInstance().
Language.setCurrentLanguage(this);
Then we dispatch to the correct booleanType method in Lisp2 and the
correct answer is obtained for the case example. DO is emitting (to me
at least) some very weird bytecode. Since you need to have fiddled
with the module export stuff to get these results, I'll post the
disassembly here (sorry for the long message)
Scheme first:
#|kawa:1|# (define (f) (do ((i 1 (+ i 1))) ((= i 10) 'fin) (display i)))
#|kawa:2|# (disassemble f)
In class atInteractiveLevel$1
Method name:"f" public static Signature: ()java.lang.Object
Attribute "Code", length:89, max_stack:3, max_locals:1, code_length:31
0: getstatic <Field atInteractiveLevel$1.Lit0 gnu.math.IntNum>
3: astore_0
4: aload_0
5: bipush 10
7: i2l
8: invokestatic <Method gnu.math.IntNum.compare (gnu.math.IntNum,long)int>
11: ifeq 27
14: aload_0
15: invokestatic <Method kawa.lib.ports.display (java.lang.Object)void>
18: aload_0
19: iconst_1
20: invokestatic <Method gnu.math.IntNum.add
(gnu.math.IntNum,int)gnu.math.IntNum>
23: astore_0
24: goto 4
27: getstatic <Field atInteractiveLevel$1.Lit1 gnu.mapping.SimpleSymbol>
30: areturn
Attribute "StackMapTable", length:10, number of entries: 3
offset: 4 - append_frame - define 1 more locals
0: gnu.math.IntNum
offset: 14 - same_frame
offset: 27 - same_frame
Attribute "LineNumberTable", length:6, count: 1
line: 1 at pc: 0
Attribute "LocalVariableTable", length:12, count: 1
slot#0: name: i, type: gnu.math.IntNum (pc: 4 length: 26)
That wasn't surprising. Contrast with CL:
#|kawa:1|# (defun f () (do ((i 1 (+ i 1))) ((= i 10) 'fin) (display i)))
#|kawa:2|# (disassemble #'f)
In class atInteractiveLevel$1
Method name:"f" public static Signature: ()java.lang.Object
Attribute "Code", length:169, max_stack:5, max_locals:1, code_length:71
0: getstatic <Field atInteractiveLevel$1.Lit0 gnu.math.IntNum>
3: astore_0
4: getstatic <Field atInteractiveLevel$1.loc$not gnu.mapping.Location>
7: invokevirtual <Method gnu.mapping.Location.get ()java.lang.Object>
10: invokestatic <Method gnu.mapping.Promise.force
(java.lang.Object)java.lang.Object>
13: checkcast <Class gnu.mapping.Procedure>
16: aload_0
17: bipush 10
19: i2l
20: invokestatic <Method gnu.math.IntNum.compare (gnu.math.IntNum,long)int>
23: ifne 32
26: getstatic <Field atInteractiveLevel$1.Lit1 java.lang.Boolean>
29: goto 35
32: getstatic <Field atInteractiveLevel$1.Lit2 java.lang.Boolean>
35: invokevirtual <Method gnu.mapping.Procedure.apply1
(java.lang.Object)java.lang.Object>
38: getstatic <Field atInteractiveLevel$1.Lit3 gnu.lists.EmptyList>
41: if_acmpeq 57
44: aload_0
45: invokestatic <Method kawa.lib.ports.display (java.lang.Object)void>
48: aload_0
49: iconst_1
50: invokestatic <Method gnu.math.IntNum.add
(gnu.math.IntNum,int)gnu.math.IntNum>
53: astore_0
54: goto 4
57: getstatic <Field atInteractiveLevel$1.Lit4 gnu.mapping.SimpleSymbol>
60: areturn
61: dup
62: ldc <String "/dev/stdin">
64: iconst_1
65: bipush 13
67: invokevirtual <Method
gnu.mapping.UnboundLocationException.setLine
(java.lang.String,int,int)void>
70: athrow
Exceptions (count: 1):
start: 7, end: 10, handler: 61, type: gnu.mapping.UnboundLocationException
Attribute "StackMapTable", length:42, number of entries: 8
offset: 4 - append_frame - define 1 more locals
0: gnu.math.IntNum
offset: 10 - same_locals_1_stack_item_frame
0: java.lang.Object
offset: 26 - same_locals_1_stack_item_frame
0: gnu.mapping.Procedure
offset: 32 - same_locals_1_stack_item_frame
0: gnu.mapping.Procedure
offset: 35 - full_frame. Locals count: 1
0: gnu.math.IntNum
(end of locals) Stack count: 2
0: gnu.mapping.Procedure
1: java.lang.Boolean
offset: 44 - same_frame
offset: 57 - same_frame
offset: 61 - same_locals_1_stack_item_frame
0: gnu.mapping.UnboundLocationException
Attribute "LineNumberTable", length:6, count: 1
line: 1 at pc: 0
Attribute "LocalVariableTable", length:12, count: 1
slot#0: name: i, type: gnu.math.IntNum (pc: 4 length: 56)
Why is line 4 getting changed from aload_0 to a get/force/cast dance?
I decided to look at the out of --debug-print-expr. For Scheme, we
get:
[Module:atInteractiveLevel$1
(Module/atInteractiveLevel$1/1/
* (Declarations: f/15/fl:408c8::gnu.mapping.Procedure)
(Define line:1:1 /Declaration[f/15]
(Lambda/f/5/fl:0 line:1:9 ()
(Let#15 line:1:13
((%do%loop/56/fl:40048(ignorable) = (Quote #!undefined)))
(Begin line:1:13
(Set /Declaration[%do%loop/56]
(Lambda/23/fl:0 (i/62/fl:40040(ignorable))
* (If (Apply (Ref/27/Declaration[applyToArgs/2])
* (Ref/23/Declaration[not/72])
(Apply line:1:33 (Ref/26/Declaration[applyToArgs/2])
(Ref/24/Declaration[=/78])
(Ref/25/Declaration[i/62])
(Quote 10)))
(Begin line:1:49
(Apply line:1:49 (Ref/33/Declaration[applyToArgs/2])
(Ref/31/Declaration[display/114])
(Ref/32/Declaration[i/62]))
(Apply (Ref/39/Declaration[applyToArgs/2])
(Ref/34/Declaration[%do%loop/56])
(Apply line:1:23 (Ref/38/Declaration[applyToArgs/2])
(Ref/36/Declaration[+/132])
(Ref/37/Declaration[i/62])
(Quote 1))))
(Begin line:1:13 (Quote #!void ::void) (Quote fin)))))
(Apply (Ref/45/Declaration[applyToArgs/2])
(Ref/43/Declaration[%do%loop/56])
(Quote 1)))))))]
The lines marked with an asterix indicate points of difference between
that and the corresponding output for CL:
[Module:atInteractiveLevel$1
(Module/atInteractiveLevel$1/1/ (Declarations: f/2/fl:8c2)
*
(Define line:1:1 /Declaration[f/2]
(Lambda/f/2/fl:0 line:1:10 ()
(Let#13 line:1:13
((%do%loop/54/fl:40048(ignorable) = (Quote #!undefined)))
(Begin line:1:13
(Set /Declaration[%do%loop/54]
(Lambda/20/fl:0 (i/57/fl:40040(ignorable))
* (If (Apply (Ref/22/not)
* (Apply line:1:33 (Ref/23/Declaration[=/60])
* (Ref/24/Declaration[i/57])
(Quote 10)))
(Begin line:1:49
(Apply line:1:49 (Ref/28/Declaration[display/89])
(Ref/29/Declaration[i/57]))
(Apply (Ref/30/Declaration[%do%loop/54])
(Apply line:1:23 (Ref/32/Declaration[+/107])
(Ref/33/Declaration[i/57])
(Quote 1))))
(Begin line:1:13 (Quote #!void ::void) (Quote fin)))))
(Apply (Ref/37/Declaration[%do%loop/54]) (Quote 1)))))))]
I know that I can transform the CL output to look a bit closer to the
Scheme output by moving the SchemeCompilation#makeApply method and
associated applyFieldDecl up into Translator so that Lisp2Compilation
can use applyToArgs.
The output of CL is now:
[Module:atInteractiveLevel$1
(Module/atInteractiveLevel$1/1/ (Declarations: f/3/fl:8c2)
*
(Define line:1:1 /Declaration[f/3]
(Lambda/f/2/fl:0 line:1:10 ()
(Let#13 line:1:13
((%do%loop/55/fl:40048(ignorable) = (Quote #!undefined)))
(Begin line:1:13
(Set /Declaration[%do%loop/55]
(Lambda/20/fl:0 (i/58/fl:40040(ignorable))
(If (Apply (Ref/26/Declaration[applyToArgs/2])
* (Ref/22/not)
(Apply line:1:33 (Ref/25/Declaration[applyToArgs/2])
(Ref/23/Declaration[=/61])
(Ref/24/Declaration[i/58])
(Quote 10)))
(Begin line:1:49
(Apply line:1:49 (Ref/32/Declaration[applyToArgs/2])
(Ref/30/Declaration[display/90])
(Ref/31/Declaration[i/58]))
(Apply (Ref/38/Declaration[applyToArgs/2])
(Ref/33/Declaration[%do%loop/55])
(Apply line:1:23 (Ref/37/Declaration[applyToArgs/2])
(Ref/35/Declaration[+/108])
(Ref/36/Declaration[i/58])
(Quote 1))))
(Begin line:1:13 (Quote #!void ::void) (Quote fin)))))
(Apply (Ref/44/Declaration[applyToArgs/2])
(Ref/42/Declaration[%do%loop/55])
(Quote 1)))))))]
So I'm still missing the (Declarations:
f/15/fl:408c8::gnu.mapping.Procedure) line, and more importantly,
instead of (Ref/23/Declaration[not/72]) in Scheme, I have only
(Ref/22/not) in CL. I can't yet explain why this is causing the
problem, nor can I yet explain how to transform the latter into the
former, but my hunch is that it is this difference that is causing the
problem.
Charles.