This is the mail archive of the kawa@sources.redhat.com 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]

pseudo-method patch


Here is a patch for three "pseudo" methods that can be used along with
a namespace alias.  The new methods "instance?", "cast", and "class"
are similar to the "new" pseudo-method in that they are not actually
class methods, but special names that are available when using a
namespace alias.

This might be controversial, so let the comments fly.

    You can use the method name `instance?' to check the type of objects:

         (Int32:instance? x)

    This is equivalent to the Java expression `x instanceof Integer'
    or the Kawa `(instance? x <java.lang.Integer>)' form.  Be aware
    that this overrides normal Kawa name mangling and that methods
    named `isInstance' should be called using `(MyClass:isInstance x)'.

    You can use the method name `cast' to converts or coerces the
    argument to a different type:

         (Int32:cast x)

    This is equivalent to the Java expression `((Integer) x)' or the
    Kawa `(as <java.lang.Integer> x)' form.

    You can use the method name `class' to get the class:

         (Int32:class)

    This is equivalent to the Java expression `java.lang.Integer' or
    the Kawa `<java.lang.Integer>' and `(find-class
    'java.lang.Integer)' forms.



Regards,
Chris Dean



Index: doc/kawa.texi
===================================================================
RCS file: /cvs/kawa/kawa/doc/kawa.texi,v
retrieving revision 1.150
diff -u -w -r1.150 kawa.texi
--- doc/kawa.texi	28 Jul 2004 22:36:49 -0000	1.150
+++ doc/kawa.texi	11 Aug 2004 02:48:42 -0000
@@ -3933,6 +3933,31 @@
 @end example
 This evaluates to the Java String @code{"255"}.
 
+You can use the method name @code{instance?} to check the type of objects:
+@example
+(Int32:instance? x)
+@end example
+This is equivalent to the Java expression @code{x instanceof Integer} or
+the Kawa @code{(instance? x <java.lang.Integer>)} form.  Be aware that
+this overrides normal Kawa name mangling and that methods named
+@code{isInstance} should be called using @code{(MyClass:isInstance x)}.
+
+You can use the method name @code{cast} to converts or coerces the
+argument to a different type:
+@example
+(Int32:cast x)
+@end example
+This is equivalent to the Java expression @code{((Integer) x)} or
+the Kawa @code{(as <java.lang.Integer> x)} form.
+
+You can use the method name @code{class} to get the class:
+@example
+(Int32:class)
+@end example
+This is equivalent to the Java expression @code{java.lang.Integer} or
+the Kawa @code{<java.lang.Integer>} and @code{(find-class
+'java.lang.Integer)} forms.
+
 As a shorthand, you can use the name of a Java class instead of a
 namespace alias:
 @example
Index: gnu/expr/ChangeLog
===================================================================
RCS file: /cvs/kawa/kawa/gnu/expr/ChangeLog,v
retrieving revision 1.324
diff -u -w -r1.324 ChangeLog
--- gnu/expr/ChangeLog	9 Aug 2004 05:26:57 -0000	1.324
+++ gnu/expr/ChangeLog	11 Aug 2004 02:48:43 -0000
@@ -1,3 +1,7 @@
+2004-08-10  Chris Dean  <ctdean@sokitomi.com>
+
+	* InlineCalls.java:  Add instance?, class, and cast pseudo-methods.
+
 2004-08-06  Per Bothner  <per@bothner.com>
 
 	Change tailcall function API to use matchX+apply.
Index: gnu/expr/InlineCalls.java
===================================================================
RCS file: /cvs/kawa/kawa/gnu/expr/InlineCalls.java,v
retrieving revision 1.21
diff -u -w -r1.21 InlineCalls.java
--- gnu/expr/InlineCalls.java	20 Jul 2004 23:30:18 -0000	1.21
+++ gnu/expr/InlineCalls.java	11 Aug 2004 02:48:43 -0000
@@ -15,16 +15,29 @@
   /** Possibly convert a Symbol method call to invokeStatic or make. */
   Expression rewriteToInvocation(Symbol sym, ApplyExp aexp)
   {
-    Expression[] args = aexp.args;
     String uri = sym.getNamespaceURI();
     if (uri == null || ! uri.startsWith("class:"))
       return null;
     String className = uri.substring(6);
     String methodName = sym.getName();
-    ClassType typeInvoke = ClassType.make("gnu.kawa.reflect.Invoke");
+    if (methodName.equals("instance?"))
+      return rewriteToInstance(aexp, className);
+    else if (methodName.equals("class"))
+      return rewriteToClass(aexp, className);
+    else if (methodName.equals("cast"))
+      return rewriteToCast(aexp, className);
+    else
+      return rewriteToInvoke(aexp, className, methodName);
+  }
+
+  private Expression rewriteToInvoke(ApplyExp aexp,
+                                     String className, String methodName) 
+  {
+    Expression[] args = aexp.args;
     String invFieldName;
     Invoke invProc;
     boolean isNew = methodName.equals("new");
+    boolean isInstance = methodName.equals("instance?");
     if (isNew)
       {
 	invFieldName = "make";
@@ -35,6 +48,7 @@
 	invFieldName = "invokeStatic";
 	invProc = gnu.kawa.reflect.Invoke.invokeStatic;
       }
+    ClassType typeInvoke = ClassType.make(invProc.getClass().getName());
     Field invField = typeInvoke.getDeclaredField(invFieldName);
     Declaration invDecl = new Declaration("invoke", invField);
     invDecl.noteValue(new QuoteExp(invProc));
@@ -44,12 +58,90 @@
     xargs[0] = new QuoteExp(className);
     if (! isNew)
       xargs[1] = new QuoteExp(methodName);
-    args = xargs;
-    ApplyExp nexp = new ApplyExp(new ReferenceExp(invDecl), args);
+
+    return finishRewrite(aexp, invDecl, invProc, xargs);
+  }
+
+  private Expression rewriteToInstance(ApplyExp aexp, String className)
+  {
+    Expression[] args = aexp.args;
+    CanInline proc = kawa.standard.Scheme.instanceOf;
+    ClassType type = ClassType.make(proc.getClass().getName());
+    Declaration decl = new Declaration("instance?", type);
+    
+    decl.noteValue(new QuoteExp(proc));
+    decl.setFlag(Declaration.IS_CONSTANT);
+
+    if (args.length != 1) {
+      String nm = className + ":" + "instance?";
+      throw new WrongArguments(nm, args.length,
+                               WrongArguments.checkArgCount(nm, 1, 1,
+                                                            args.length));
+    }
+    
+    Expression[] xargs = new Expression[2];
+    xargs[0] = args[0];
+    xargs[1] = new QuoteExp(ClassType.make(className));
+
+    return finishRewrite(aexp, decl, proc, xargs);
+  }
+
+  private Expression rewriteToClass(ApplyExp aexp, String className)
+  {
+    Expression[] args = aexp.args;
+    CanInline proc = kawa.standard.Scheme.findClass;
+    ClassType type = ClassType.make(proc.getClass().getName());
+    Declaration decl = new Declaration("class", type);
+    
+    decl.noteValue(new QuoteExp(proc));
+    decl.setFlag(Declaration.IS_CONSTANT);
+
+    if (args.length != 0) {
+      String nm = className + ":" + "class";
+      throw new WrongArguments(nm, args.length,
+                               WrongArguments.checkArgCount(nm, 0, 0,
+                                                            args.length));
+    }
+    
+    Expression[] xargs = new Expression[1];
+    xargs[0] = new QuoteExp(ClassType.make(className));
+
+    return finishRewrite(aexp, decl, proc, xargs);
+  }
+  
+  private Expression rewriteToCast(ApplyExp aexp, String className)
+  {
+    Expression[] args = aexp.args;
+    CanInline proc = gnu.kawa.functions.Convert.as;
+    ClassType type = ClassType.make(proc.getClass().getName());
+    Declaration decl = new Declaration("cast", type);
+    
+    decl.noteValue(new QuoteExp(proc));
+    decl.setFlag(Declaration.IS_CONSTANT);
+
+    if (args.length != 1) {
+      String nm = className + ":" + "cast";
+      throw new WrongArguments(nm, args.length,
+                               WrongArguments.checkArgCount(nm, 1, 1,
+                                                            args.length));
+    }
+    
+    Expression[] xargs = new Expression[2];
+    xargs[1] = args[0];
+    xargs[0] = new QuoteExp(ClassType.make(className));
+
+    return finishRewrite(aexp, decl, proc, xargs);
+  }
+
+  private Expression finishRewrite(ApplyExp aexp, Declaration decl, 
+                                   CanInline proc, Expression[] args)
+  {
+    ApplyExp nexp = new ApplyExp(new ReferenceExp(decl), args);
     nexp.setLine(aexp);
-    return invProc.inline(nexp, this);
+    return proc.inline(nexp, this);  
   }
 
+  
   protected Expression walkApplyExp(ApplyExp exp)
   {
     super.walkApplyExp(exp);
Index: gnu/kawa/reflect/ChangeLog
===================================================================
RCS file: /cvs/kawa/kawa/gnu/kawa/reflect/ChangeLog,v
retrieving revision 1.74
diff -u -w -r1.74 ChangeLog
--- gnu/kawa/reflect/ChangeLog	9 Aug 2004 05:30:14 -0000	1.74
+++ gnu/kawa/reflect/ChangeLog	11 Aug 2004 02:48:43 -0000
@@ -1,3 +1,8 @@
+2004-08-10  Chris Dean  <ctdean@sokitomi.com>
+
+	* ClassMethods.java (apply): Add instance?, class, and cast
+	pseudo-methods.
+
 2004-08-08  Per Bothner  <per@bothner.com>
 
 	* Invoke.java (applyN):  Use new matchN method.  Don't use applyV.
Index: gnu/kawa/reflect/ClassMethods.java
===================================================================
RCS file: /cvs/kawa/kawa/gnu/kawa/reflect/ClassMethods.java,v
retrieving revision 1.21
diff -u -w -r1.21 ClassMethods.java
--- gnu/kawa/reflect/ClassMethods.java	11 Feb 2004 20:26:40 -0000	1.21
+++ gnu/kawa/reflect/ClassMethods.java	11 Aug 2004 02:48:43 -0000
@@ -15,11 +15,22 @@
 
   public static MethodProc apply (String className, String methodName)
   {
+    if (methodName.equals("instance?"))
+      return MethodProcWrapper.makeSimple(kawa.standard.Scheme.instanceOf, 
+                                           className, 1, 2);
+    else if (methodName.equals("class"))
+      return MethodProcWrapper.makeSimple(kawa.standard.Scheme.findClass, 
+                                          className, 0, 1);
+    else if (methodName.equals("cast"))
+      return MethodProcWrapper.makeSimple(gnu.kawa.functions.Convert.as, 
+                                          className, 0, 2);
+
     String mname = methodName.equals("new") ? "<init>"
       : Compilation.mangleName(methodName);
     ClassType methodClass = ClassType.make(className);
     MethodProc proc
       = ClassMethods.apply(methodClass, mname, null, null, 0, 0);
+
     if (proc == null)
       {
 	StringBuffer sbuf = new StringBuffer();
Index: gnu/mapping/ChangeLog
===================================================================
RCS file: /cvs/kawa/kawa/gnu/mapping/ChangeLog,v
retrieving revision 1.120
diff -u -w -r1.120 ChangeLog
--- gnu/mapping/ChangeLog	9 Aug 2004 05:25:26 -0000	1.120
+++ gnu/mapping/ChangeLog	11 Aug 2004 02:48:43 -0000
@@ -1,3 +1,8 @@
+2004-08-10  Chris Dean  <ctdean@sokitomi.com>
+
+	* MethodProcWrapper.java:  New class that extends MethodProc.
+	* Makefile.am (java_sources):  Added MethodProcWrapper.java.
+
 2004-08-06  Per Bothner  <per@bothner.com>
 
 	* Procedure.java:  New API, especially for --full-tailcalls.
Index: gnu/mapping/Makefile.am
===================================================================
RCS file: /cvs/kawa/kawa/gnu/mapping/Makefile.am,v
retrieving revision 1.30
diff -u -w -r1.30 Makefile.am
--- gnu/mapping/Makefile.am	9 Aug 2004 05:25:26 -0000	1.30
+++ gnu/mapping/Makefile.am	11 Aug 2004 02:48:43 -0000
@@ -17,6 +17,7 @@
   Location.java \
   LogWriter.java \
   MethodProc.java \
+  MethodProcWrapper.java \
   NameMap.java \
   Named.java \
   OutPort.java \
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/kawa/kawa/testsuite/ChangeLog,v
retrieving revision 1.146
diff -u -w -r1.146 ChangeLog
--- testsuite/ChangeLog	9 Aug 2004 05:40:32 -0000	1.146
+++ testsuite/ChangeLog	11 Aug 2004 02:48:43 -0000
@@ -1,3 +1,8 @@
+2004-08-10  Chris Dean  <ctdean@sokitomi.com>
+
+	* obj-test.scm: Test cases for find-class, namespace:class and
+	namespace:instance.
+
 2004-08-07  Per Bothner  <per@bothner.com>
 
 	* misc-test.scm:  Overload resolution test is now expected to pass.
Index: testsuite/obj-test.scm
===================================================================
RCS file: /cvs/kawa/kawa/testsuite/obj-test.scm,v
retrieving revision 1.45
diff -u -w -r1.45 obj-test.scm
--- testsuite/obj-test.scm	23 May 2004 20:03:46 -0000	1.45
+++ testsuite/obj-test.scm	11 Aug 2004 02:48:43 -0000
@@ -1,4 +1,4 @@
-(test-init "Objects" 91)
+(test-init "Objects" 95)
 
 ;; Force procedure to be applied without being inlined:
 (define-syntax force-eval
@@ -279,6 +279,11 @@
 (test (+ 1900 (date:get-year (date:new)))
       invoke non-simple-date 'get-year)
 
+(test #t date:instance? simple-date)
+(test #f date:instance? "hello")
+(test <SimpleDateTest> find-class 'SimpleDateTest)
+(test <java.util.Date> date:class)
+
 ;; Test for Savannah bug #4289
 (define pa-data (pa-new 10))
 (pa-setter pa-data 5 99)


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