I've been using ABCL to get access to a Java library and it's worked generally well. I have run into one problem I haven't been able to workaround. I need to make a call to a method that takes a short as an argument. I'm passing in a value--10--that fits in a short but ABCL can't find the method (presumedly due to a type issue). I've tried using jcoerce but it's not doing what I expect. What's the right way to do this? Thx. --Brad
On Nov 26, 2019, at 18:38, Brad Knotwell bknotwell@yahoo.com wrote:
I've been using ABCL to get access to a Java library and it's worked generally well. I have run into one problem I haven't been able to workaround.
I need to make a call to a method that takes a short as an argument. I'm passing in a value--10--that fits in a short but ABCL can't find the method (presumedly due to a type issue). I've tried using jcoerce but it's not doing what I expect. What's the right way to do this?
This is probably a bug in how the Bear’s FFI converts the “10” when it attempts to locate your specific Java call site, but without a test the contains the Java code that you are calling into diagnosing exactly what is going in is difficult.
When I get the time (or unless someone beats me to it), I will try to make such a test to figure out what is going on.
We could certainly do with a test suite that combinatorally probes our call site location logic.
I'm pretty sure you're right. I have a MWE below that shows an unintuitive difference. Thx. --Brad
(defun void-function ()
(let* ((result (jstatic "square" "Main" 32)))
(format t "in void-function, result of calling square(32): ~a~%" result)))
(defun void-function-short ()
(let* ((result (jstatic "squareshort" "Main" 16)))
(format t "in void-function, result of calling squareshort(16): ~a~%" result)))
(void-function)
(void-function-short)
import org.armedbear.lisp.*;
public class Main
{
public static int square(int a) {
return a * a;
}
public static int squareshort(short a)
{
return a * a;
} } $ java -cp ~/abcl_excel_gen/abcl-bin-1.6.0/abcl.jar:. org.armedbear.lisp.Main Armed Bear Common Lisp 1.6.0
Java 11.0.1 Oracle Corporation
Java HotSpot(TM) 64-Bit Server VM
Low-level initialization completed in 0.295 seconds.
Startup completed in 1.663 seconds.
Type ":help" for a list of available commands.
CL-USER(1): (load "lispfunctions.lisp")
in void-function, result of calling square(32): 1024
Error loading /Users/bknotwel/abcl_excel_gen/bug/lispfunctions.lisp at line 11 (offset 358)
#<THREAD "interpreter" {560A10B3}>: Debugger invoked on condition of type ERROR
no such method
Restarts:
0: TOP-LEVEL Return to top level. [1] CL-USER(2):
On Tuesday, November 26, 2019, 3:53:11 PM PST, Mark Evenson evenson@panix.com wrote:
On Nov 26, 2019, at 18:38, Brad Knotwell bknotwell@yahoo.com wrote:
I've been using ABCL to get access to a Java library and it's worked generally well. I have run into one problem I haven't been able to workaround.
I need to make a call to a method that takes a short as an argument. I'm passing in a value--10--that fits in a short but ABCL can't find the method (presumedly due to a type issue). I've tried using jcoerce but it's not doing what I expect. What's the right way to do this?
This is probably a bug in how the Bear’s FFI converts the “10” when it attempts to locate your specific Java call site, but without a test the contains the Java code that you are calling into diagnosing exactly what is going in is difficult.
When I get the time (or unless someone beats me to it), I will try to make such a test to figure out what is going on.
We could certainly do with a test suite that combinatorally probes our call site location logic.
Here's a workaround in the meantime (though it's more verbose)... using java.lang.Short.reverseBytes(short s) as the test case[1]:
;; no such method failure (jstatic "reverseBytes" "java.lang.Short" #x7f)
;; this works (jstatic (jmethod (jclass "java.lang.Short") "reverseBytes" (jclass "short")) (jclass "java.lang.Short") #x7f)
This is also true with instance methods...
(require :abcl-contrib) (require :jss)
(defvar *bb* (#"allocate" 'java.nio.ByteBuffer 1024))
;; no such method failure (jcall "putShort" *bb* 20)
;; works (jcall (jmethod (jclass "java.nio.ByteBuffer") "putShort" (jclass "short")) *bb* 20)
;; works (not a short though) (jcall "putInt" *bb* 20)
Hope this helps! I hope to look into this in more detail (potential problem / enhancement opportunity lies in org.armedbear.lisp.Java's method resolution)... a change here would also let the jss syntax also work: (#"putShort" *bb* 20)
[1] https://docs.oracle.com/javase/7/docs/api/java/lang/Short.html#reverseBytes(...)
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Wednesday, November 27, 2019 2:28 AM, Brad Knotwell bknotwell@yahoo.com wrote:
I'm pretty sure you're right. I have a MWE below that shows an unintuitive difference.
Thx.
--Brad
(defun void-function ()
(let* ((result (jstatic "square" "Main" 32)))
(format t "in void-function, result of calling square(32): ~a~%" result)))
(defun void-function-short ()
(let* ((result (jstatic "squareshort" "Main" 16)))
(format t "in void-function, result of calling squareshort(16): ~a~%" result)))
(void-function)
(void-function-short)
import org.armedbear.lisp.*;
public class Main
{
public static int square(int a) {
return a * a;
}
public static int squareshort(short a)
{
return a * a;
}
}
$ java -cp ~/abcl_excel_gen/abcl-bin-1.6.0/abcl.jar:. org.armedbear.lisp.Main
Armed Bear Common Lisp 1.6.0
Java 11.0.1 Oracle Corporation
Java HotSpot(TM) 64-Bit Server VM
Low-level initialization completed in 0.295 seconds.
Startup completed in 1.663 seconds.
Type ":help" for a list of available commands.
CL-USER(1): (load "lispfunctions.lisp")
in void-function, result of calling square(32): 1024
Error loading /Users/bknotwel/abcl_excel_gen/bug/lispfunctions.lisp at line 11 (offset 358)
#<THREAD "interpreter" {560A10B3}>: Debugger invoked on condition of type ERROR
no such method
Restarts:
0: TOP-LEVEL Return to top level.
[1] CL-USER(2):
On Tuesday, November 26, 2019, 3:53:11 PM PST, Mark Evenson evenson@panix.com wrote:
On Nov 26, 2019, at 18:38, Brad Knotwell bknotwell@yahoo.com wrote:
I've been using ABCL to get access to a Java library and it's worked generally well. I have run into one problem I haven't been able to workaround.
I need to make a call to a method that takes a short as an argument. I'm passing in a value--10--that fits in a short but ABCL can't find the method (presumedly due to a type issue). I've tried using jcoerce but it's not doing what I expect. What's the right way to do this?
This is probably a bug in how the Bear’s FFI converts the “10” when it attempts to locate your specific Java call site, but without a test the contains the Java code that you are calling into diagnosing exactly what is going in is difficult.
When I get the time (or unless someone beats me to it), I will try to make such a test to figure out what is going on.
We could certainly do with a test suite that combinatorally probes our call site location logic.
-- "A screaming comes across the sky. It has happened before but there is nothing to compare to it now."
On Nov 27, 2019, at 05:53, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote:
Here's a workaround in the meantime (though it's more verbose)... using java.lang.Short.reverseBytes(short s) as the test case[1]:
;; no such method failure (jstatic "reverseBytes" "java.lang.Short" #x7f)
[Tests via ABCL-PROVE added.][ABCL-PROVE]
[ABCL-PROVE]: https://github.com/armedbear/abcl/pull/131
I've looked into this issue at length now and I think I have something worth discussing and potentially trying[0] . The root issue here lies in how ABCL converts its CL representation of integers to Java, as well as its conversion of Java primitives to other Java primitives.
ABCL's common superclass for all objects (LispObject) includes two methods to convert the lisp object to a Java representation: LispObject.javaInstance() and LispObject.javaInstance(Class). LispObject.javaInstance(Class) presumably tries to convert the internal representation to the type represented by the Class passed in. In practice, this seems to be primarily used for Java primitive types. The current implementation of these methods in ABCL's internal Bignum, DoubleFloat, SingleFloat, Fixnum, LispCharacter, and JavaObject, do not seem to have all the required permutations necessary to support all of the possible Java primitive converting operations.
Even for instances where a conversion /is/ implemented (such as Fixnum.javaInstance(Short) where a Short would be returned), the method lookup strategy in Java.findMethod (which boils down to what Java.isAssignable does) doesn't find the method with the Short parameter. Instead it uses normal rules in the Java Language spec and only looks for methods that potentially /widen/ primitives, and disallows any narrowing without an explicit narrowing cast (and in Brad's example, the literal 16 or 32 is represented by Fixnum, which converts to java.lang.Integer). I think the original intention is to have such methods be called using jcoerce, such as:
(jcoerce 32 (jclass "short")) or (jcoerce 32 (jclass "java.lang.Short"))
This fails in the current implementation, I believe due to a bug in JavaObject(Object, Class) constructor. This only does one type of conversion, to java.lang.Byte, if the intended class is Byte and the Object implements Number.
For jcoerce to work with all primitives, all possible primitive operations need to be covered in JavaObject(Object, Class).
I have attached a patch that adds these conversions to JavaObject(Object, Class). However, I've also changed other places where these primitive conversions are done for consistency. My rule of thumb has been that the Java Language Specification rules[1] should be followed, and the /only/ time a /narrowing/ conversion is allowed where information can potentially be lost, is through the JavaObject(Object, Class) constructor (in Lisp land, called using the (java:jcoerce) function).
As such, the patch also changes the implementation classes Bignum, DoubleFloat, SingleFloat, Fixnum, Character, and JavaObject, to support all possible primitive /widening/ conversions. Their implementations of LispObject.javaInstance(Class) continue to signal type errors for conversions that cannot be performend, but also now for all narrowing operations. Previously /some/ of these classes allowed /some/ narrowing conversions to happen. I think a case could be made for each of these LispObject implementations to allow any primitve conversion. The disadvantage is not knowing an information reducing operation potentially occurred (and is counter to the behavior of not finding narrowing methods such as Brad's original example) -- at the very least if all primitive narrowing operations /were/ allowed from Fixnum.javaInstance(Class) for example, a compiler warning should be emitted (though I'm not sure how that would be implemented).
The following patch may break code that relies on the one conversion that has worked in the past (to byte, in the JavaObject(Object, Class) constructor. In fact, this patch breaks swank. To fix your swank, modify your swank's abcl.lisp to include the now required jcoerce call (in the octets-to-jbytes function): the jstatic call should now look like: ... (around line 191) do (java:jstatic (java:jmethod "java.lang.reflect.Array" "setByte" "java.lang.Object" "int" "byte") "java.lang.reflect.Array" bytes i (java:jcoerce byte "byte")))
What are your thoughts? I dislike backwards incompatible changes like this, but I think the impact is probably low due to the fact that method resolution used rules to only find widening conversions, and the fact that short and byte are not as commonly used in method calls.
Previously, (jfield) and (jproperty) uses would also not signal a type error unless LispObject.javaInstance(Class) did not support the conversion (and like mentioned previously, some classes did some primitive narrowing operations). Uses of these fields will now (consistently) with method calls, error on narrowing conversions unless coerced.
Try the patch (but make sure to modify your swank!)...
Now my old example works like the following: (jstatic "reverseBytes" "java.lang.Short" (jcoerce #x7f "short"))
Note also that the patch didn't break any new tests. I ran tests via: (require 'asdf) (load "~/quicklisp/setup.lisp") (asdf:initialize-source-registry `(:source-registry (:directory ,*default-pathname-defaults*) :inherit-configuration)) (asdf:test-system :abcl)
-Mark
[0] See patch attached (against latest master of https://github.com/armedbear/abcl) (3a54c91f3a0cbb71ae8d161acadecf118a65404c)
[1] Widening Primitve Conversion https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.2
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Wednesday, December 4, 2019 8:37 PM, Mark Evenson evenson@panix.com wrote:
On Nov 27, 2019, at 05:53, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote: Here's a workaround in the meantime (though it's more verbose)... using java.lang.Short.reverseBytes(short s) as the test case[1]: ;; no such method failure (jstatic "reverseBytes" "java.lang.Short" #x7f)
[Tests via ABCL-PROVE added.][ABCL-PROVE]
"A screaming comes across the sky. It has happened before but there is nothing to compare to it now."
On Dec 13, 2019, at 20:14, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote:
I've looked into this issue at length now and I think I have something worth discussing and potentially trying[0] . The root issue here lies in how ABCL converts its CL representation of integers to Java, as well as its conversion of Java primitives to other Java primitives.
[…]
Thanks for the needed extensive re-working here; working [through my review][1] as I find time.
[1]: https://github.com/easye/abcl/tree/somewhat-functional/primitive-narrowing
On Dec 13, 2019, at 20:14, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote:
I've looked into this issue at length now and I think I have something worth discussing and potentially trying[0] . The root issue here lies in how ABCL converts its CL representation of integers to Java, as well as its conversion of Java primitives to other Java primitives.
[…]
What are your thoughts? I dislike backwards incompatible changes like this, but I think the impact is probably low due to the fact that method resolution used rules to only find widening conversions, and the fact that short and byte are not as commonly used in method calls.
After much study, reflection and experimentation, I have decided that I didn't like the incompatible change introduced by this patch in requiring Lisp code to explictly JCOERCE arguments to find Java call sites.
Instead, I [managed to solve the original poster's problems of not being able to call Java methods whose parameters where short or byte][1] by modifying the Java.findMethod() machinery to use the actual arguments that will be used in the call for a decision whether to narrow types for calling a given function makes sense for short or int types. I was unable to find other problems with converting primitive types.
[With a little additional elbow grease][2] , I was able to also code a [fix for finding call-sites][3] that take a varargs parameter such as
java.util.Arrays.asList(T... arg)
[1]: https://github.com/armedbear/abcl/pull/144/commits/bfa6e9e44f854ca0c175e73e358d307a7507eeda [2]: https://github.com/armedbear/abcl/pull/144/commits/9fb39d2c0e445bf45739a4f7bb25938ea23f8b5a [3]: https://abcl.org/trac/ticket/259
Given the major holes pointed out by the someone-functional-programmers examination of of the narrowing/widening convention, I am surprised that there are not more Java calls that can't be made with our current FFI machinery, but after scouring our bug reports and trying various methods I can't find any examples. If anyone knows of a case of the Java FFI not finding call sites with these patches, please pipe up.
--
While reviewing this patch, I noticed that since one can't use CL:COERCE to perform a conversion that loses information, as
(coerce 256 '(unsigned-byte 8))
signals some sort of error for all existing Lisp implementations (SBCL, CCL, ECL, CLISP, Allegro, LispWorks), therefore I would argue that something like
(jcoerce 256 "byte")
should also signal an error. Therefore, JCOERCE should be reworked to signal some sort of error if the conversion would lose information. I continue to work through what we would be needed to both incoporate somewhat-functional-programmer's patch, which allows things like
(jcoerce 2.4 "float")
to work, but that would signal TYPE-ERROR conditions when JCOERCE call that lose information are attempted.
My current inclination would be to release the current state as abcl-1.6.1 without incorporating this patch, as I think the need to [patch ABCL-ASDF's inablity to download Maven artifacts][4] is much more pressing than untangling the incomplete inconsistencies in JCOERCE.
[4]: https://mailman.common-lisp.net/pipermail/armedbear-devel/2020-February/0040...
Thank you for reviewing the patch.
I completely agree that my patch should not be in a minor point release, and I hope I didn't come across as thinking it should. I definitely think that any relatively major incompatible change would at least require a smooth upgrade plan (maybe something new in *features*, and updates pushed to swank/cffi with fixes that would work for the newest ABCL as well as historical ABCLs). So that said, I have absolutely no objection to any 1.6.1 plans (not that I presume to have a say in that anyhow :-)).
So read on, with our common understanding that I have no objection at all to the reversal of the patch :-)...
--
I like and also thought about looking at the argument values dynamically to help determine a proper call site. It certainly makes sense, especially for literal values, to not require extra coercion or annotation, to find the proper call sites. However, here are a couple of inconsistencies that arise from the current implementation (git master branch 702405fe97a1778f5d3683a6a9cc4294071061e6):
;; the following signals the "no such method" error, ;; consistent with my understanding of the intent of the new patch (jstatic "reverseBytes" "java.lang.Short" 6300000)
;; however, this version does not throw and error, and silently narrows ;; 63000 the value to a short (let ((method (jmethod "java.lang.Short" "reverseBytes" "short"))) (jstatic method nil 6300000))
;; this version has a different error, IllegalArgumentException ;; as the runtime won't automatically convert 32.3 to a short (let ((method (jmethod "java.lang.Short" "reverseBytes" "short"))) (jstatic method nil 32.3))
;; this gives the more familiar no such method error (jstatic "reverseBytes" "java.lang.Short" 32.3)
One annoying thing about Java is the "byte" type is signed -- so these value checks will still potentially cause trouble for methods taking a "byte". Consider the following:
(require :abcl-contrib) (require :jss)
(defvar *bb* (#"allocate" 'java.nio.ByteBuffer 1024))
;; Going to use ByteBuffer.put(byte)
;; this signals a NoSuchMethod JAVA-EXCEPTION ;; since the value is > 127, too much for our signed Java byte type (#"put" *bb* #xf2)
;; but this succeeds since it is in range (-127 - 127) (#"put" *bb* #x2f)
Now this is also annoying in Java, often one has to write code like byte[] myBytes = {(byte) 0xfa, (byte) 0xaa}; However, at least there is a cast operator, ugly as it makes Java look :-). (Or one could write byte[] myBytes = {-6, -86}; )
That brings me to my last question -- What is (java:jcoerce) supposed to do?
I had incorrectly assumed it was much like a Java cast -- in Java one can cast from any primitive type to any other primitive type (with the exception of boolean). One can also cast within the inheritance hierarchy for references etc.
The docstring for jcoerce says: Attempts to coerce OBJECT into a JavaObject of class INTENDED-CLASS. Raises a TYPE-ERROR if no conversion is possible.
Here are some examples of the inconsistencies:
;; these all succeed, and produce a java.lang.Byte, narrowing and losing information ;; with no error (like a java cast) (jcoerce #xff "byte") (jcoerce 3.22 "byte") (jcoerce 293847918751987980174873249801273 "byte") (jcoerce 23.49879427598475074398572 "byte")
;; succeeds and returns a java.lang.Float (jcoerce 1.23 "float")
;; these fail
;; value #\c is not of type byte (jcoerce #\c "byte")
;; value 20 is not of type int (jcoerce 20 "int")
;; value 20 is not of type long (jcoerce 20 "long")
;; value 20 is not of type float (jcoerce 20 "float")
;; value 1.23 is not of type double (jcoerce 1.23 "double")
;; these return '(1 2 3) with no error (jcoerce '(1 2 3) "int") (jcoerce '(1 2 3) "javax.swing.JTextArea")
I think the interface with Java must necessarily be a little bit messy, and I think narrowing primitives is very common within Java, and if jcoerce is not the way to do that, it would be nice to define a jcast or some other similar function. One of course could always do something like the following to arrive at a valid Java signed byte (credit stassats [1] for mask-signed):
(defun mask-signed (x size) (logior x (- (mask-field (byte 1 (1- size)) x))))
;; "cast" / narrow our #xfa to the bitwise-equivalent 8 bit signed value ;; this allows our put to succeed, as our value now falls in the ;; valid range for java's signed byte type (#"put" *bb* (mask-signed #xfa 8))
Anyhow, I appreciate you looking at my patch,
-Mark
[1] https://old.reddit.com/r/Common_Lisp/comments/ecl5on/convert_unsignedbyte_to... (credit stassats)
‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Sunday, February 9, 2020 1:45 PM, Mark Evenson evenson@panix.com wrote:
On Dec 13, 2019, at 20:14, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote: I've looked into this issue at length now and I think I have something worth discussing and potentially trying[0] . The root issue here lies in how ABCL converts its CL representation of integers to Java, as well as its conversion of Java primitives to other Java primitives.
[…]
What are your thoughts? I dislike backwards incompatible changes like this, but I think the impact is probably low due to the fact that method resolution used rules to only find widening conversions, and the fact that short and byte are not as commonly used in method calls.
After much study, reflection and experimentation, I have decided that I didn't like the incompatible change introduced by this patch in requiring Lisp code to explictly JCOERCE arguments to find Java call sites.
Instead, I [managed to solve the original poster's problems of not being able to call Java methods whose parameters where short or byte][1] by modifying the Java.findMethod() machinery to use the actual arguments that will be used in the call for a decision whether to narrow types for calling a given function makes sense for short or int types. I was unable to find other problems with converting primitive types.
With a little additional elbow grease , I was able to also code a fix for finding call-sites that take a varargs parameter such as
java.util.Arrays.asList(T... arg)
Given the major holes pointed out by the someone-functional-programmers examination of of the narrowing/widening convention, I am surprised that there are not more Java calls that can't be made with our current FFI machinery, but after scouring our bug reports and trying various methods I can't find any examples. If anyone knows of a case of the Java FFI not finding call sites with these patches, please pipe up.
While reviewing this patch, I noticed that since one can't use CL:COERCE to perform a conversion that loses information, as
(coerce 256 '(unsigned-byte 8))
signals some sort of error for all existing Lisp implementations (SBCL, CCL, ECL, CLISP, Allegro, LispWorks), therefore I would argue that something like
(jcoerce 256 "byte")
should also signal an error. Therefore, JCOERCE should be reworked to signal some sort of error if the conversion would lose information. I continue to work through what we would be needed to both incoporate somewhat-functional-programmer's patch, which allows things like
(jcoerce 2.4 "float")
to work, but that would signal TYPE-ERROR conditions when JCOERCE call that lose information are attempted.
My current inclination would be to release the current state as abcl-1.6.1 without incorporating this patch, as I think the need to [patch ABCL-ASDF's inablity to download Maven artifacts][4] is much more pressing than untangling the incomplete inconsistencies in JCOERCE.
"A screaming comes across the sky. It has happened before but there is nothing to compare to it now."
On Feb 10, 2020, at 02:56, somewhat-functional-programmer somewhat-functional-programmer@protonmail.com wrote:
Thank you for reviewing the patch.
[…]
So read on, with our common understanding that I have no objection at all to the reversal of the patch :-)…
Cool.
I like and also thought about looking at the argument values dynamically to help determine a proper call site. It certainly makes sense, especially for literal values, to not require extra coercion or annotation, to find the proper call sites. However, here are a couple of inconsistencies that arise from the current implementation (git master branch 702405fe97a1778f5d3683a6a9cc4294071061e6):
;; the following signals the "no such method" error, ;; consistent with my understanding of the intent of the new patch (jstatic "reverseBytes" "java.lang.Short" 6300000)
;; however, this version does not throw and error, and silently narrows ;; 63000 the value to a short (let ((method (jmethod "java.lang.Short" "reverseBytes" "short"))) (jstatic method nil 6300000)
Confirmed. Mea Maximus Stupidius Culpa in my patch: I didn’t think about/test an explicitly supplied JMETHOD instance.
;; this version has a different error, IllegalArgumentException ;; as the runtime won't automatically convert 32.3 to a short (let ((method (jmethod "java.lang.Short" "reverseBytes" "short"))) (jstatic method nil 32.3))
Yes, this should probably be caught in the find call site machinery, transformed into a Lisp side TYPE_ERROR.
;; this gives the more familiar no such method error (jstatic "reverseBytes" "java.lang.Short" 32.3)
One annoying thing about Java is the "byte" type is signed -- so these value checks will still potentially cause trouble for methods taking a "byte”.
[…]
That brings me to my last question -- What is (java:jcoerce) supposed to do?
I had incorrectly assumed it was much like a Java cast -- in Java one can cast from any primitive type to any other primitive type (with the exception of boolean). One can also cast within the inheritance hierarchy for references etc.
The docstring for jcoerce says: Attempts to coerce OBJECT into a JavaObject of class INTENDED-CLASS. Raises a TYPE-ERROR if no conversion is possible.
Tentatively, I would suggest that JCOERCE tries as hard as possible to DWIM, signalling a TYPE-ERROR (or possibly a subclass) if any coercian would lose information. Then, JCOERCE is defined as a transformation to values whose inverse round-trips. As such, we would extend JCOERCE to cover as many types as possible under this definition, bringing in all Java primtitive types (float, double, char are what we need I think). For completeness, we should cover all descendents of java.lang.Number. But *not* try to cover java.lang.Character. My thinking here is that “char” has a meaning as an unsigned two bytes value, but not allow coercian of java.lang.Character values as it can potentially wrap both int and char. I could be talked out of the last point if someone can defend the interpolation of such values, but I think users would be too confused.
I agree that we should add a JCAST that potentially strips information according to the JLS widening and narrowing rules for all its floating port horrors.
Here are some examples of the inconsistencies:
[…]
Studying and incorporating it into tests. Thanks for bagging parts of the shaggy monster…
—
Currently, I am for fixing JCOERCE for abcl-1.6.1, and pushing JCAST off to either abcl-1.7 or abcl-2.0, whichever I branch first.
yers in CONS, Mark
[As anarchodin notes in discovering that our Unicode normalization has funny spots][1], we need to fix the idea of what a character is in the Java-based Lisp reader.
Tis involves doing the right thing at the points in the code where we have comments like
// ### BUG: Codepoint conversion
[1] https://github.com/armedbear/abcl/issues/146
armedbear-devel@common-lisp.net