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 20, 2012, at 6:12 PM, Charles Turner wrote:

Once again, thanks for the information! I'll spend tomorrow morning
investigating this further, and if I still am not getting anywhere,
then I'll implement basic versions of DO and friends to get started on
DEFPACKAGE.

On 20 June 2012 22:10, Jamison Hope <jrh@theptrgroup.com> wrote:
#|kawa:1|# (do ((temp-one 1 (+ 1 temp-one)) (temp-two 0 (- temp-two 1))) ((>
(- temp-one temp-two) 5) temp-one))
1

It's doubly confusing that with the module exports, this evaluation produces an incorrect answer of 1. It should be 4! (Works OK in Scheme, so it must be related to whatever is going wrong in CL)

Yeah, that's strange. Note that (case 'f ((a e i o u) 'vowel) (else 'consonant)) also gave me the wrong answer in CommonLisp. For the reason, see below.

Helmut was right that this is a namespace bug. When loading the
kawa.lib.std_syntax module, all of the non-exported fields are
loaded as a result of the loop in ModuleInfo#setupModuleExp.
This calls language.declFromField(...) to generate each Declaration.
For Macro fields, this is not returning Declarations with the
PROCEDURE flag set.

I can think of several ways to fix this, and I'm not sure which is
the best/most correct. We need to recognize kawa.lang.Macro
(or should that be kawa.lang.Syntax?), but it looks like it's a minor
no-no to reference kawa.lang.* classes from gnu.kawa.*.

This works:

$ svn diff gnu/kawa/lispexpr/LispLanguage.java
Index: gnu/kawa/lispexpr/LispLanguage.java
===================================================================
--- gnu/kawa/lispexpr/LispLanguage.java (revision 7254)
+++ gnu/kawa/lispexpr/LispLanguage.java (working copy)
@@ -127,6 +127,9 @@
boolean isFinal = (fld.getModifiers() & Access.FINAL) != 0;
if (isFinal && fvalue instanceof Syntax) // FIXME - should check type? not value?
fdecl.setSyntax();
+ if (fld .getType().isSubtype(gnu.bytecode.ClassType.make("kawa.lang.Macro")) &&
+ hasSeparateFunctionNamespace())
+ fdecl.setProcedureDecl(true);
return fdecl;
}


but notice that it's already got a "fvalue instanceof Syntax" check;
maybe we can just use that? Perhaps we just need Declaration#setSyntax
to set the PROCEDURE flag?

$ svn diff gnu/expr/Declaration.java
Index: gnu/expr/Declaration.java
===================================================================
--- gnu/expr/Declaration.java	(revision 7254)
+++ gnu/expr/Declaration.java	(working copy)
@@ -230,7 +230,7 @@
   public final void setSyntax ()
   {
     setSimple(false);
-    setFlag(IS_CONSTANT|IS_SYNTAX|EARLY_INIT);
+    setFlag(IS_CONSTANT|IS_SYNTAX|EARLY_INIT|PROCEDURE);
   }

/** Return the ScopeExp that contains (declares) this Declaration. */


Or does it belong in Language#declFromField, which already has


        if (ftype.isSubtype(Compilation.typeProcedure))
          fdecl.setProcedureDecl(true);

and a bunch of other fdecl.setFlag(...) statements?


Anyway, with any of those changes in place, #'do and #'case run without compilation error, but they give the wrong answers.

$ kawa --lisp
#|kawa:1|# (do ((temp-one 1 (+ 1 temp-one)) (temp-two 0 (- temp-two 1))) ((> (- temp-one temp-two) 5) temp-one))
1
#|kawa:2|# (case 'f ((a e i o u) 'vowel) (else 'consonant))
vowel


This is another case of language booleans biting us. The case expression
compiles down to something including this:

5: getstatic <Field kawa.standard.Scheme.isEqv gnu.kawa.functions.IsEqv>
8: getstatic <Field atInteractiveLevel$1.Lit0 gnu.mapping.SimpleSymbol>
11: getstatic <Field atInteractiveLevel$1.Lit1 gnu.mapping.SimpleSymbol>
14: invokevirtual <Method gnu.mapping.Procedure.apply2 (java.lang.Object,java.lang.Object)java.lang.Object>
17: astore_3
18: aload_3
19: getstatic <Field atInteractiveLevel$1.Lit2 gnu.lists.EmptyList>
22: if_acmpeq 35


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.

--
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]