Skip to content

Commit 6cfa9e9

Browse files
authored
issue-15 support Java arrays (#58)
1 parent 579a9e8 commit 6cfa9e9

File tree

22 files changed

+635
-118
lines changed

22 files changed

+635
-118
lines changed

idris-jvm-codegen-launcher/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<modelVersion>4.0.0</modelVersion>
1111

1212
<artifactId>idris-jvm-codegen-launcher</artifactId>
13+
<name>Idris JVM Codegen Launcher</name>
1314

1415
<properties>
1516
<assemble.dir.name>dist</assemble.dir.name>

idris-jvm-core/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<modelVersion>4.0.0</modelVersion>
1111

1212
<artifactId>idris-jvm-core</artifactId>
13+
<name>Idris JVM Core</name>
1314

1415
<properties>
1516
<idris.srcdir>${project.basedir}/src/main/idris</idris.srcdir>

idris-jvm-core/src/main/idris/IdrisJvm/Core/Asm.idr

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mutual
1616

1717
data ReferenceTypeDescriptor = ClassDesc ClassName
1818
| InterfaceDesc ClassName
19-
| ArrayDesc ReferenceTypeDescriptor
19+
| ArrayDesc FieldTypeDescriptor
2020
| IdrisExportDesc ClassName
2121
| NullableStrDesc
2222
| NullableRefDesc ClassName
@@ -114,7 +114,7 @@ mutual
114114
Show ReferenceTypeDescriptor where
115115
show (ClassDesc className) = "ClassDesc " ++ show className
116116
show (InterfaceDesc className) = "InterfaceDesc " ++ show className
117-
show (ArrayDesc referenceTypeDescriptor) = "ArrayDesc " ++ show referenceTypeDescriptor
117+
show (ArrayDesc tyDesc) = "ArrayDesc " ++ show tyDesc
118118
show (IdrisExportDesc className) = "IdrisExportDesc " ++ show className
119119
show NullableStrDesc = "NullableStrDesc"
120120
show (NullableRefDesc className) = "NullableRefDesc" ++ show className
@@ -146,34 +146,34 @@ Eq JMethodName where
146146
Show JMethodName where
147147
show (MkJMethodName cname mname) = cname ++ "#" ++ mname
148148

149-
150-
asmRefTyDesc : ReferenceTypeDescriptor -> String
151-
asmRefTyDesc (ClassDesc c) = "L" ++ c ++ ";"
152-
asmRefTyDesc (IdrisExportDesc c) = "L" ++ c ++ ";"
153-
asmRefTyDesc (InterfaceDesc c) = "L" ++ c ++ ";"
154-
asmRefTyDesc (NullableRefDesc c) = "L" ++ c ++ ";"
155-
asmRefTyDesc NullableStrDesc = "Ljava/lang/String;"
156-
asmRefTyDesc (ArrayDesc refTy) = "[" ++ asmRefTyDesc refTy
157-
158-
refTyClassName : ReferenceTypeDescriptor -> ClassName
159-
refTyClassName (ClassDesc c) = c
160-
refTyClassName (InterfaceDesc c) = c
161-
refTyClassName (IdrisExportDesc c) = c
162-
refTyClassName (NullableRefDesc c) = c
163-
refTyClassName NullableStrDesc = "java/lang/String"
164-
refTyClassName arr@(ArrayDesc _) = asmRefTyDesc arr
165-
166-
asmFieldTypeDesc : FieldTypeDescriptor -> String
167-
asmFieldTypeDesc FieldTyDescByte = "B"
168-
asmFieldTypeDesc FieldTyDescChar = "C"
169-
asmFieldTypeDesc FieldTyDescShort = "S"
170-
asmFieldTypeDesc FieldTyDescBoolean = "Z"
171-
asmFieldTypeDesc FieldTyDescArray = "["
172-
asmFieldTypeDesc FieldTyDescDouble = "D"
173-
asmFieldTypeDesc FieldTyDescFloat = "F"
174-
asmFieldTypeDesc FieldTyDescInt = "I"
175-
asmFieldTypeDesc FieldTyDescLong = "J"
176-
asmFieldTypeDesc (FieldTyDescReference f) = asmRefTyDesc f
149+
mutual
150+
asmRefTyDesc : ReferenceTypeDescriptor -> String
151+
asmRefTyDesc (ClassDesc c) = "L" ++ c ++ ";"
152+
asmRefTyDesc (IdrisExportDesc c) = "L" ++ c ++ ";"
153+
asmRefTyDesc (InterfaceDesc c) = "L" ++ c ++ ";"
154+
asmRefTyDesc (NullableRefDesc c) = "L" ++ c ++ ";"
155+
asmRefTyDesc NullableStrDesc = "Ljava/lang/String;"
156+
asmRefTyDesc (ArrayDesc ty) = "[" ++ asmFieldTypeDesc ty
157+
158+
refTyClassName : ReferenceTypeDescriptor -> ClassName
159+
refTyClassName (ClassDesc c) = c
160+
refTyClassName (InterfaceDesc c) = c
161+
refTyClassName (IdrisExportDesc c) = c
162+
refTyClassName (NullableRefDesc c) = c
163+
refTyClassName NullableStrDesc = "java/lang/String"
164+
refTyClassName arr@(ArrayDesc _) = asmRefTyDesc arr
165+
166+
asmFieldTypeDesc : FieldTypeDescriptor -> String
167+
asmFieldTypeDesc FieldTyDescByte = "B"
168+
asmFieldTypeDesc FieldTyDescChar = "C"
169+
asmFieldTypeDesc FieldTyDescShort = "S"
170+
asmFieldTypeDesc FieldTyDescBoolean = "Z"
171+
asmFieldTypeDesc FieldTyDescArray = "["
172+
asmFieldTypeDesc FieldTyDescDouble = "D"
173+
asmFieldTypeDesc FieldTyDescFloat = "F"
174+
asmFieldTypeDesc FieldTyDescInt = "I"
175+
asmFieldTypeDesc FieldTyDescLong = "J"
176+
asmFieldTypeDesc (FieldTyDescReference f) = asmRefTyDesc f
177177

178178
asmTypeDesc : TypeDescriptor -> String
179179
asmTypeDesc (FieldDescriptor t) = asmFieldTypeDesc t
@@ -190,8 +190,23 @@ data Asm : Type -> Type where
190190
Aconstnull : Asm ()
191191
Aload : Int -> Asm ()
192192
Anewarray : Descriptor -> Asm ()
193-
Astore : Int -> Asm ()
193+
194+
Anewbooleanarray : Asm ()
195+
Anewbytearray : Asm ()
196+
Anewchararray : Asm ()
197+
Anewshortarray : Asm ()
198+
Anewintarray : Asm ()
199+
Anewlongarray : Asm ()
200+
Anewfloatarray : Asm ()
201+
Anewdoublearray : Asm ()
202+
203+
Arraylength : Asm ()
194204
Areturn : Asm ()
205+
Astore : Int -> Asm ()
206+
Baload : Asm ()
207+
Bastore : Asm ()
208+
Caload : Asm ()
209+
Castore : Asm ()
195210
Checkcast : Descriptor -> Asm ()
196211
ClassCodeStart : Int -> Access -> ClassName -> (Maybe Signature) -> ClassName -> List ClassName -> List Annotation -> Asm ()
197212
ClassCodeEnd : String -> Asm ()
@@ -201,6 +216,8 @@ data Asm : Type -> Type where
201216
CreateMethod : List Access -> ClassName -> MethodName -> Descriptor -> Maybe Signature ->
202217
Maybe (List Exception) -> List Annotation -> List (List Annotation) -> Asm ()
203218
Dadd : Asm ()
219+
Daload : Asm ()
220+
Dastore : Asm ()
204221
Ddiv : Asm ()
205222
Dload : Int -> Asm ()
206223
Dmul : Asm ()
@@ -210,6 +227,8 @@ data Asm : Type -> Type where
210227
Dup : Asm ()
211228
Error : String -> Asm ()
212229
F2d : Asm ()
230+
Faload : Asm ()
231+
Fastore : Asm ()
213232
Field : FieldInsType -> ClassName -> FieldName -> Descriptor -> Asm ()
214233
FieldEnd : Asm ()
215234
Fload : Int -> Asm ()
@@ -224,7 +243,9 @@ data Asm : Type -> Type where
224243
I2c : Asm ()
225244
I2l : Asm ()
226245
Iadd : Asm ()
246+
Iaload : Asm ()
227247
Iand : Asm ()
248+
Iastore : Asm ()
228249
Ior : Asm ()
229250
Ixor : Asm ()
230251
Icompl : Asm ()
@@ -249,7 +270,9 @@ data Asm : Type -> Type where
249270
L2i : Asm ()
250271
LabelStart : Label -> Asm ()
251272
Ladd : Asm ()
273+
Laload : Asm ()
252274
Land : Asm ()
275+
Lastore : Asm ()
253276
Lor : Asm ()
254277
Lxor : Asm ()
255278
Lcompl : Asm ()
@@ -267,11 +290,14 @@ data Asm : Type -> Type where
267290
MaxStackAndLocal : Int -> Int -> Asm ()
268291
MethodCodeStart : Asm ()
269292
MethodCodeEnd : Asm ()
293+
Multianewarray : Descriptor -> Nat -> Asm ()
270294
New : ClassName -> Asm ()
271295
InstanceOf : ClassName -> Asm ()
272296
Pop : Asm ()
273297
Pop2 : Asm ()
274298
Return : Asm ()
299+
Saload : Asm ()
300+
Sastore : Asm ()
275301
ShouldDescribeFrame : Asm Bool
276302
SourceInfo : SourceFileName -> Asm ()
277303
Subroutine : Asm () -> Asm ()
@@ -296,4 +322,4 @@ Applicative Asm where
296322

297323
(<*>) f a = Bind f (\f' =>
298324
Bind a (\a' =>
299-
Pure (f' a')))
325+
Pure (f' a')))

idris-jvm-core/src/main/idris/IdrisJvm/Core/Common.idr

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,23 @@ repeatObjectDesc n = repeatString n "Ljava/lang/Object;"
9696
sig : Nat -> String
9797
sig nArgs = "(" ++ repeatObjectDesc nArgs ++ ")Ljava/lang/Object;"
9898

99+
anewarray : FieldTypeDescriptor -> Asm ()
100+
anewarray FieldTyDescByte = Anewbytearray
101+
anewarray FieldTyDescChar = Anewchararray
102+
anewarray FieldTyDescShort = Anewshortarray
103+
anewarray FieldTyDescBoolean = Anewbooleanarray
104+
anewarray FieldTyDescArray = jerror $ "array is not a valid element type for a single dimensional array"
105+
anewarray FieldTyDescDouble = Anewdoublearray
106+
anewarray FieldTyDescFloat = Anewfloatarray
107+
anewarray FieldTyDescInt = Anewintarray
108+
anewarray FieldTyDescLong = Anewlongarray
109+
anewarray (FieldTyDescReference f) = Anewarray $ asmRefTyDesc f
110+
111+
arrayDesc : String -> Nat -> String
112+
arrayDesc cname dimensions =
113+
let arrayPrefix = cast $ replicate dimensions '['
114+
in arrayPrefix ++ cname
115+
99116
metafactoryDesc : Descriptor
100117
metafactoryDesc =
101118
concat [ "("
@@ -131,6 +148,34 @@ invokeDynamic cname lambda nArgs =
131148
, BsmArgGetType "()Ljava/lang/Object;"
132149
]
133150

151+
arrayStore : FieldTypeDescriptor -> Asm ()
152+
arrayStore FieldTyDescByte = Bastore
153+
arrayStore FieldTyDescChar = Castore
154+
arrayStore FieldTyDescShort = Sastore
155+
arrayStore FieldTyDescBoolean = Bastore
156+
arrayStore FieldTyDescArray = Aastore
157+
arrayStore FieldTyDescDouble = Dastore
158+
arrayStore FieldTyDescFloat = Fastore
159+
arrayStore FieldTyDescInt = Iastore
160+
arrayStore FieldTyDescLong = Lastore
161+
arrayStore (FieldTyDescReference ReferenceTypeDescriptor) = Aastore
162+
163+
arrayLoad : FieldTypeDescriptor -> Asm ()
164+
arrayLoad FieldTyDescByte = Baload
165+
arrayLoad FieldTyDescChar = Caload
166+
arrayLoad FieldTyDescShort = Saload
167+
arrayLoad FieldTyDescBoolean = Baload
168+
arrayLoad FieldTyDescArray = Aaload
169+
arrayLoad FieldTyDescDouble = Daload
170+
arrayLoad FieldTyDescFloat = Faload
171+
arrayLoad FieldTyDescInt = Iaload
172+
arrayLoad FieldTyDescLong = Laload
173+
arrayLoad (FieldTyDescReference ReferenceTypeDescriptor) = Aaload
174+
175+
typeDescToarrayElemDesc : TypeDescriptor -> FieldTypeDescriptor
176+
typeDescToarrayElemDesc VoidDescriptor = jerror $ "An array cannot have 'void' elements"
177+
typeDescToarrayElemDesc (FieldDescriptor desc) = desc
178+
134179
loadArgsForLambdaTargetMethod : Nat -> Asm ()
135180
loadArgsForLambdaTargetMethod nArgs = case isLTE 1 nArgs of
136181
Yes prf => sequence_ (map (Aload . cast) [0 .. (Nat.(-) nArgs 1)])

idris-jvm-core/src/main/idris/IdrisJvm/Core/Foreign.idr

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,19 @@ data JForeign = JStatic String String
1414
| JSetInstanceField String String
1515
| JInterface String String
1616
| JNew String
17+
| JNewArray
18+
| JMultiNewArray
19+
| JSetArray
20+
| JGetArray
21+
| JArrayLength
1722
| JClassLiteral String
1823

1924
mutual
2025
parseDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
2126
parseDescriptor returns ffi argsDesc = tryParseStaticMethodDescriptor returns ffi argsDesc where
2227

2328
unsupportedDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
24-
unsupportedDescriptor _ fdesc _ = jerror $ "Unsupported descriptor"
29+
unsupportedDescriptor _ fdesc _ = jerror $ ("Unsupported descriptor: " ++ show fdesc)
2530

2631
tryParseClassLiteralDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
2732
tryParseClassLiteralDescriptor returns ffiDesc@(FApp ffi [FStr cname]) argsDesc
@@ -30,19 +35,39 @@ mutual
3035
else unsupportedDescriptor returns ffiDesc argsDesc
3136
tryParseClassLiteralDescriptor returns ffi argsDesc = unsupportedDescriptor returns ffi argsDesc
3237

38+
tryParseArrayLengthDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
39+
tryParseArrayLengthDescriptor returns (FCon "ArrayLength") argsDesc = JArrayLength
40+
tryParseArrayLengthDescriptor returns ffi argsDesc = tryParseClassLiteralDescriptor returns ffi argsDesc
41+
42+
tryParseGetArrayDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
43+
tryParseGetArrayDescriptor returns (FCon "GetArray") argsDesc = JGetArray
44+
tryParseGetArrayDescriptor returns ffi argsDesc = tryParseArrayLengthDescriptor returns ffi argsDesc
45+
46+
tryParseSetArrayDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
47+
tryParseSetArrayDescriptor returns (FCon "SetArray") argsDesc = JSetArray
48+
tryParseSetArrayDescriptor returns ffi argsDesc = tryParseGetArrayDescriptor returns ffi argsDesc
49+
50+
tryParseMultiNewArrayDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
51+
tryParseMultiNewArrayDescriptor returns (FCon "MultiNewArray") argsDesc = JMultiNewArray
52+
tryParseMultiNewArrayDescriptor returns ffi argsDesc = tryParseSetArrayDescriptor returns ffi argsDesc
53+
54+
tryParseNewArrayDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
55+
tryParseNewArrayDescriptor returns (FCon "NewArray") argsDesc = JNewArray
56+
tryParseNewArrayDescriptor returns ffi argsDesc = tryParseMultiNewArrayDescriptor returns ffi argsDesc
57+
3358
tryParseConstructorDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
3459
tryParseConstructorDescriptor returns ffiDesc@(FCon ffi) argsDesc
3560
= if ffi == "New"
3661
then case fdescRefDescriptor returns of
3762
ClassDesc cname => JNew cname
3863
InterfaceDesc _ => jerror $ "Invalid FFI descriptor for constructor. " ++
3964
"A constructor can't return an interface type. "
40-
ArrayDesc _ => jerror "Array construction is not yet supported"
65+
ArrayDesc _ => jerror "No constructors for array types"
4166
IdrisExportDesc _ => jerror "Cannot invoke constructor of Idris exported type"
4267
NullableStrDesc => jerror "A constructor cannot return a nullable string"
4368
NullableRefDesc _ => jerror "A constructor cannot return a nullable reference"
44-
else tryParseClassLiteralDescriptor returns ffiDesc argsDesc
45-
tryParseConstructorDescriptor returns ffi argsDesc = tryParseClassLiteralDescriptor returns ffi argsDesc
69+
else tryParseNewArrayDescriptor returns ffiDesc argsDesc
70+
tryParseConstructorDescriptor returns ffi argsDesc = tryParseNewArrayDescriptor returns ffi argsDesc
4671

4772
tryParseSetInstanceFieldDescriptor : FDesc -> FDesc -> List (FDesc, LVar) -> JForeign
4873
tryParseSetInstanceFieldDescriptor returns ffiDesc@(FApp ffi [FStr fieldName]) argsDesc@((declClass, _)::_)
@@ -110,6 +135,13 @@ mutual
110135
Aload $ locIndex v
111136
idrisDescToJava (FieldDescriptor ty)
112137

138+
idrisToJavaLoadArray : List (FieldTypeDescriptor, LVar) -> Asm ()
139+
idrisToJavaLoadArray = sequence_ . intersperse Aaload . map f where
140+
f : (FieldTypeDescriptor, LVar) -> Asm ()
141+
f (ty, v) = do
142+
Aload $ locIndex v
143+
idrisDescToJava (FieldDescriptor ty)
144+
113145
javaToIdris : TypeDescriptor -> Asm ()
114146
javaToIdris (FieldDescriptor FieldTyDescBoolean) =
115147
InvokeMethod InvokeStatic (rtClassSig "Util") "boolToIdrisBool" "(Z)Ljava/lang/Object;" False
@@ -200,23 +232,26 @@ mutual
200232
fdescFieldDescriptor (FApp "JVM_IntT" [_, FCon "JVM_IntBits16"]) = FieldTyDescShort
201233
fdescFieldDescriptor (FApp "JVM_IntT" [_, FCon "JVM_IntBits32"]) = FieldTyDescInt
202234
fdescFieldDescriptor (FApp "JVM_IntT" [_, FCon "JVM_IntBits64"]) = FieldTyDescLong
203-
fdescFieldDescriptor (FCon "JVM_Str") = FieldTyDescReference $ ClassDesc "java/lang/String"
204235
fdescFieldDescriptor (FCon "JVM_Float") = FieldTyDescFloat
205236
fdescFieldDescriptor (FCon "JVM_Double") = FieldTyDescDouble
206237
fdescFieldDescriptor (FCon "JVM_Bool") = FieldTyDescBoolean
238+
239+
fdescFieldDescriptor (FCon "JVM_Str") = FieldTyDescReference $ ClassDesc "java/lang/String"
207240
fdescFieldDescriptor fdesc = FieldTyDescReference $ fdescRefDescriptor fdesc
208241

209242
fdescRefDescriptor : FDesc -> ReferenceTypeDescriptor
210243
fdescRefDescriptor desc@(FApp "JVM_NativeT" [FApp "Class" [FStr typeName]]) = ClassDesc typeName
211244
fdescRefDescriptor desc@(FApp "JVM_NativeT" [FApp "Interface" [FStr typeName]]) = InterfaceDesc typeName
245+
246+
fdescRefDescriptor desc@(FApp "JVM_ArrayT" [_, elemDesc]) = ArrayDesc $ fdescFieldDescriptor elemDesc
247+
212248
fdescRefDescriptor desc@(FApp "JVM_Nullable" [FApp "Class" [FStr typeName]]) = NullableRefDesc typeName
213249
fdescRefDescriptor desc@(FApp "JVM_Nullable" [FApp "Interface" [FStr typeName]]) = NullableRefDesc typeName
214-
fdescRefDescriptor (FApp "JVM_NativeT" [FApp "Array" [FApp "Class" [FStr typeName]]]) = ArrayDesc (ClassDesc typeName)
250+
215251
fdescRefDescriptor (FCon "JVM_Str") = ClassDesc "java/lang/String"
216252
fdescRefDescriptor (FStr exportedType) = IdrisExportDesc exportedType
217253
fdescRefDescriptor (FCon "JVM_NullableStr") = NullableStrDesc
218-
fdescRefDescriptor desc = jerror $ "Expected a class or interface descriptor. " ++
219-
"Invalid reference type descriptor: " ++ show desc
254+
fdescRefDescriptor desc = jerror $ "Invalid reference type descriptor: " ++ show desc
220255

221256
isExportIO : FDesc -> Bool
222257
isExportIO (FIO _) = True

0 commit comments

Comments
 (0)