Skip to content

Commit 860a3b2

Browse files
committed
Introduce the 'flatten' built-in method
Introduce the method in the 'Iterable' type.
1 parent 2c73b42 commit 860a3b2

File tree

6 files changed

+136
-0
lines changed

6 files changed

+136
-0
lines changed

lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
1414
import com.adacore.lkql_jit.runtime.values.interfaces.Iterator;
1515
import com.adacore.lkql_jit.runtime.values.lists.BaseLKQLLazyList;
16+
import com.adacore.lkql_jit.runtime.values.lists.LKQLFlattenResult;
1617
import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
1718
import com.adacore.lkql_jit.runtime.values.lists.LKQLMapResult;
1819
import com.adacore.lkql_jit.utils.Constants;
@@ -105,4 +106,19 @@ protected BaseLKQLLazyList onIterable(
105106
return new LKQLMapResult(iterable, function, functionLibrary);
106107
}
107108
}
109+
110+
@BuiltInMethod(
111+
name = "flatten",
112+
doc = """
113+
Given an iterable of iterables, flatten all of them in a resulting iterable value. The \
114+
returned value is lazy.""",
115+
isProperty = true
116+
)
117+
abstract static class FlattenExpr extends BuiltInBody {
118+
119+
@Specialization
120+
protected BaseLKQLLazyList onIterable(Iterable iterable) {
121+
return new LKQLFlattenResult(iterable);
122+
}
123+
}
108124
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//
2+
// Copyright (C) 2005-2025, AdaCore
3+
// SPDX-License-Identifier: GPL-3.0-or-later
4+
//
5+
6+
package com.adacore.lkql_jit.runtime.values.lists;
7+
8+
import com.adacore.lkql_jit.exception.LKQLRuntimeException;
9+
import com.adacore.lkql_jit.runtime.ListStorage;
10+
import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
11+
import com.adacore.lkql_jit.runtime.values.interfaces.Iterator;
12+
import com.adacore.lkql_jit.utils.LKQLTypesHelper;
13+
14+
public final class LKQLFlattenResult extends BaseLKQLLazyList {
15+
16+
/** Collection that is flatten. */
17+
private final Iterator generatorIterator;
18+
19+
/** Iterator used to go though inner collections. */
20+
private Iterator innerIterator;
21+
22+
// ----- Constructors -----
23+
24+
public LKQLFlattenResult(Iterable generator) {
25+
super(new ListStorage<>(32));
26+
this.generatorIterator = generator.iterator();
27+
}
28+
29+
// ----- Lazy list required methods -----
30+
31+
@Override
32+
protected void initCacheTo(long n) {
33+
if (n >= this.cache.size() || n < 0) {
34+
Object next;
35+
do {
36+
next = this.nextElem();
37+
if (next != null) {
38+
this.cache.append(next);
39+
}
40+
} while (next != null && (n >= this.cache.size() || n < 0));
41+
}
42+
}
43+
44+
// ----- Instance methods -----
45+
46+
/**
47+
* Util function to get the next element in the current inner collection.
48+
* If there is no more elements in the current inner collection, this
49+
* function fetch the next one.
50+
* If there is no more inner collection, this function returns null.
51+
*/
52+
private Object nextElem() {
53+
// Ensure the inner iterator is initialized and has a next element
54+
while (this.innerIterator == null || !this.innerIterator.hasNext()) {
55+
if (!this.generatorIterator.hasNext()) {
56+
return null;
57+
}
58+
var nextInner = this.generatorIterator.next();
59+
if (nextInner instanceof Iterable nextInnerIterable) {
60+
this.innerIterator = nextInnerIterable.iterator();
61+
} else {
62+
throw LKQLRuntimeException.wrongType(
63+
LKQLTypesHelper.LKQL_ITERABLE,
64+
LKQLTypesHelper.fromJava(nextInner),
65+
null
66+
);
67+
}
68+
}
69+
70+
// Finally return the next element
71+
return this.innerIterator.next();
72+
}
73+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Perform a simple flattening operation
2+
val inner = [1, 2, 3]
3+
val lst_1 = [inner, inner, inner]
4+
print(lst_1.flatten.to_list)
5+
6+
# Ensure flattening is lazy
7+
fun double(x) = {
8+
print("Computing double of " & x.img);
9+
x * 2
10+
}
11+
val lst_2 = [[1, 2, 3].map(double), [4, 5, 6].map(double)].flatten
12+
print(lst_2[2])
13+
print(lst_2[5])
14+
print(lst_2[4])
15+
16+
# Ensure there is an error when calling "flatten" on a list of non-iterables
17+
val lst_3 = [[1, 2, 3], "what?"].flatten
18+
print(lst_3[1])
19+
print(lst_3[3])
20+
print(lst_3[4])
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[1, 2, 3, 1, 2, 3, 1, 2, 3]
2+
Computing double of 1
3+
Computing double of 2
4+
4
5+
Computing double of 3
6+
Computing double of 4
7+
Computing double of 5
8+
10
9+
8
10+
1
11+
3
12+
error: Type error: expected Iterable but got Str
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
driver: 'interpreter'
2+
project: 'default_project/default.gpr'
3+
lkt_refactor: True

user_manual/generated/std.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ Methods for `LazyList`
173173

174174
Return the content of the iterable object with each element associated to its index in a tuple: [(<index>, <elem>), ...]
175175

176+
.. method:: LazyList.flatten(this)
177+
178+
Given an iterable of iterables, flatten all of them in a resulting iterable value. The returned value is lazy.
179+
176180
.. method:: LazyList.help(this)
177181

178182
Print formatted help for the given object
@@ -216,6 +220,10 @@ Methods for `List`
216220

217221
Return the content of the iterable object with each element associated to its index in a tuple: [(<index>, <elem>), ...]
218222

223+
.. method:: List.flatten(this)
224+
225+
Given an iterable of iterables, flatten all of them in a resulting iterable value. The returned value is lazy.
226+
219227
.. method:: List.help(this)
220228

221229
Print formatted help for the given object
@@ -535,6 +543,10 @@ Methods for `SelectorList`
535543

536544
Return the content of the iterable object with each element associated to its index in a tuple: [(<index>, <elem>), ...]
537545

546+
.. method:: SelectorList.flatten(this)
547+
548+
Given an iterable of iterables, flatten all of them in a resulting iterable value. The returned value is lazy.
549+
538550
.. method:: SelectorList.help(this)
539551

540552
Print formatted help for the given object

0 commit comments

Comments
 (0)