@@ -3,15 +3,13 @@ package org.combinators.ep.language.java.paradigm.ffi /*DI:LD:AI*/
33import com .github .javaparser .ast .`type` .ArrayType
44import com .github .javaparser .ast .expr .{ArrayAccessExpr , ArrayCreationExpr , ArrayInitializerExpr , AssignExpr , FieldAccessExpr , IntegerLiteralExpr , MethodCallExpr , NameExpr , SimpleName }
55import com .github .javaparser .ast .{ArrayCreationLevel , NodeList }
6- import org .combinators .cogen .InstanceRep
7- import org .combinators .cogen .TypeRep
6+ import org .combinators .cogen .{Command , InstanceRep , TypeRep , Understands }
87import org .combinators .cogen .paradigm .{Apply , ffi }
98import org .combinators .cogen .Command .Generator
10- import org .combinators .cogen .paradigm .AnyParadigm .syntax ._
11- import org .combinators .cogen .paradigm .ffi .{CreateArray , Get , Length , Arrays as Arrs }
12- import org .combinators .cogen .Understands
9+ import org .combinators .cogen .paradigm .AnyParadigm .syntax .*
10+ import org .combinators .cogen .paradigm .ffi .{CreateArray , Get , Length , Set , Arrays as Arrs }
1311import org .combinators .ep .language .java .CodeGenerator .Enable
14- import org .combinators .ep .language .java .Syntax .default ._
12+ import org .combinators .ep .language .java .Syntax .default .*
1513import org .combinators .ep .language .java .paradigm .AnyParadigm
1614import org .combinators .ep .language .java .{ContextSpecificResolver , ProjectCtxt }
1715
@@ -23,12 +21,32 @@ class Arrays[Ctxt, AP <: AnyParadigm](val base:AP) extends Arrs[Ctxt] {
2321 def perform (
2422 context : Ctxt ,
2523 command : Apply [CreateArray [Type ], Expression , Expression ]
26- ): (Ctxt , Expression ) =
27- (context,
28- new ArrayCreationExpr (command.functional.elementType,
29- new NodeList (new ArrayCreationLevel (1 )),
30- new ArrayInitializerExpr (new NodeList (command.arguments* )))
31- )
24+ ): (Ctxt , Expression ) = {
25+
26+ if (command.functional.dimensions.length == 1 ) {
27+ (context,
28+ new ArrayCreationExpr (command.functional.elementType,
29+ new NodeList (new ArrayCreationLevel ()),
30+ new ArrayInitializerExpr (new NodeList (command.arguments: _ * )))
31+ )
32+ } else {
33+ val levels = command.functional.dimensions.map(level => new ArrayCreationLevel ()) // inserting actual value causes problems since cannot have int[len1][len2] with initial values.
34+ val dims = command.functional.dimensions
35+ val innerFold = dims.reverse.tail.foldLeft[Seq [ArrayInitializerExpr ]](
36+ command.arguments.grouped(dims.last).toSeq.map(subSeq => new ArrayInitializerExpr (new NodeList (subSeq : _* )))
37+ )
38+ { case (inits, dim) => inits.grouped(dim).toSeq.map(subSeq => new ArrayInitializerExpr (new NodeList (subSeq : _* ))) }
39+
40+ // When creating array with initial values, cannot pass in lengths. Cannot do the following for example
41+ // new int[2][3] { { 4, 5, 1 }, { 1, 2, 3 } }
42+
43+ (context,
44+ new ArrayCreationExpr (command.functional.elementType,
45+ new NodeList (levels : _* ),
46+ innerFold.head) // new ArrayInitializerExpr(new NodeList(command.arguments: _ *)))
47+ )
48+ }
49+ }
3250 }
3351
3452 val arrayCapabilities : ArrayCapabilities =
@@ -42,17 +60,22 @@ class Arrays[Ctxt, AP <: AnyParadigm](val base:AP) extends Arrs[Ctxt] {
4260 context : Ctxt ,
4361 command : Apply [Get , Expression , Expression ]
4462 ): (Ctxt , Expression ) = {
45- (context, new ArrayAccessExpr (command.arguments(0 ), command.arguments(1 )))
63+
64+ val indices = command.arguments.tail.foldLeft(command.arguments.head) { case (acc, level) => new ArrayAccessExpr (acc, level) }
65+
66+ (context, indices)
4667 }
4768 }
4869
49- implicit val canSet : Understands [Ctxt , Apply [ffi. Set , Expression , Expression ]] =
50- new Understands [Ctxt , Apply [ffi. Set , Expression , Expression ]] {
70+ implicit val canSet : Understands [Ctxt , Apply [Set , Expression , Expression ]] =
71+ new Understands [Ctxt , Apply [Set , Expression , Expression ]] {
5172 override def perform (
5273 context : Ctxt ,
53- command : Apply [ffi. Set , Expression , Expression ]
74+ command : Apply [Set , Expression , Expression ]
5475 ): (Ctxt , Expression ) = {
55- (context, new AssignExpr (new ArrayAccessExpr (command.arguments(0 ), command.arguments(1 )), command.arguments(2 ), AssignExpr .Operator .ASSIGN ))
76+ val indices = command.arguments.init.tail.foldLeft(command.arguments.head) { case (acc, level) => new ArrayAccessExpr (acc, level) }
77+
78+ (context, new AssignExpr (indices, command.arguments.last, AssignExpr .Operator .ASSIGN ))
5679 }
5780 }
5881
@@ -62,7 +85,9 @@ class Arrays[Ctxt, AP <: AnyParadigm](val base:AP) extends Arrs[Ctxt] {
6285 context : Ctxt ,
6386 command : Apply [Length , Expression , Expression ]
6487 ): (Ctxt , Expression ) = {
65- (context, new FieldAccessExpr (command.arguments(0 ), " length" ))
88+ val indices = command.arguments.tail.foldLeft(command.arguments.head) { case (acc, level) => new ArrayAccessExpr (acc, level) }
89+
90+ (context, new FieldAccessExpr (indices, " length" ))
6691 }
6792 }
6893 }
@@ -80,9 +105,10 @@ class Arrays[Ctxt, AP <: AnyParadigm](val base:AP) extends Arrs[Ctxt] {
80105 toResolution : ContextSpecificResolver => TypeRep => Generator [Ctxt , Type ],
81106 projectResolution : ContextSpecificResolver => TypeRep => Generator [Ctxt , Type ]
82107 ): ContextSpecificResolver => TypeRep => Generator [Ctxt , Type ] = k => {
83- case TypeRep .Array (elemRep) =>
108+ case TypeRep .Array (elemTypeRep) =>
109+
84110 for {
85- elemType <- projectResolution(k)(elemRep )
111+ elemType <- projectResolution(k)(elemTypeRep )
86112 } yield new ArrayType (elemType)
87113 case other => toResolution(k)(other)
88114 }
@@ -94,14 +120,72 @@ class Arrays[Ctxt, AP <: AnyParadigm](val base:AP) extends Arrs[Ctxt] {
94120 canCreateArray : Understands [Ctxt , Apply [CreateArray [Type ], Expression , Expression ]]
95121 ): ContextSpecificResolver => InstanceRep => Generator [Ctxt , Expression ] =
96122 k => rep => rep.tpe match {
97- case TypeRep .Array (elemTypeRep) =>
98- for {
99- elems <- forEach(rep.inst.asInstanceOf [Seq [elemTypeRep.HostType ]]) { elem =>
100- projectReification(k)(InstanceRep (elemTypeRep)(elem))
123+ case TypeRep .Array (elemTypeRep) => {
124+
125+
126+ // helper function to get flattened elements
127+ def elements (elemTypeRep: TypeRep )(elem: elemTypeRep.HostType ) : Generator [Ctxt , Seq [Expression ]] = {
128+ elemTypeRep match {
129+ case TypeRep .Array (innerElemTypeRep) => {
130+ val seq_gen = elem.asInstanceOf [Array [innerElemTypeRep.HostType ]].map(innerElem => elements(innerElemTypeRep)(innerElem))
131+ for {
132+ flattened <- seq_gen.foldLeft(Command .lift[Ctxt ,Seq [Expression ]](Seq .empty[Expression ])){ case (acc, next_gen) =>
133+ for {
134+ acc_result <- acc
135+ next_result <- next_gen
136+ } yield acc_result ++ next_result
137+ }
138+ } yield flattened
139+ }
140+
141+ // recursively translates innermost elements
142+ case _ => for {
143+ elems <- forEach(elem.asInstanceOf [Seq [elemTypeRep.HostType ]]) { el =>
144+ projectReification(k)(InstanceRep (elemTypeRep)(el))
145+ }
146+ } yield elems
101147 }
102- elemType <- projectResolution(k)(elemTypeRep)
103- res <- Apply [CreateArray [Type ], Expression , Expression ](CreateArray (elemType), elems).interpret(canCreateArray)
148+ }
149+
150+ // helper function to get type of innermost element -- assume homogenous array
151+ def elementType (elemTypeRep: TypeRep )(elem: elemTypeRep.HostType ) : Generator [Ctxt , Type ] = {
152+ elemTypeRep match {
153+ case TypeRep .Array (innerElemTypeRep) =>
154+ elementType(innerElemTypeRep)(elem.asInstanceOf [Array [innerElemTypeRep.HostType ]].head)
155+
156+ // recursively find type of innermost element
157+ case _ => for {
158+ elemType <- projectResolution(k)(elemTypeRep)
159+ } yield elemType
160+ }
161+ }
162+
163+ // helper function to get flattened elements
164+ def dimensions (elemTypeRep: TypeRep )(elem: elemTypeRep.HostType ) : Seq [Int ] = {
165+ elemTypeRep match {
166+ case TypeRep .Array (innerElemTypeRep) => {
167+ val outer = elem.asInstanceOf [Seq [elemTypeRep.HostType ]].length
168+
169+ // inner arrays must be uniform length
170+ val inner = dimensions(innerElemTypeRep)(elem.asInstanceOf [Array [innerElemTypeRep.HostType ]].head)
171+ outer +: inner
172+ }
173+
174+ // recursively translates innermost elements
175+ case _ => Seq (elem.asInstanceOf [Seq [elemTypeRep.HostType ]].length)
176+
177+ }
178+ }
179+
180+
181+ for {
182+ elems <- elements(rep.tpe)(rep.inst)
183+ dims = dimensions(rep.tpe)(rep.inst)
184+ elemType <- elementType(rep.tpe)(rep.inst)
185+ res <- Apply [CreateArray [Type ], Expression , Expression ](CreateArray (elemType, dims), elems).interpret(canCreateArray)
104186 } yield res
187+
188+ }
105189 case _ => reify(k)(rep)
106190 }
107191
0 commit comments