Skip to content

Commit 9539af9

Browse files
committed
Rewrite all built-in methods as specialized nodes
1 parent 524564a commit 9539af9

File tree

5 files changed

+325
-271
lines changed

5 files changed

+325
-271
lines changed

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

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
import com.adacore.lkql_jit.LKQLTypeSystemGen;
1111
import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;
1212
import com.adacore.lkql_jit.built_ins.BuiltInsHolder;
13+
import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
1314
import com.adacore.lkql_jit.built_ins.functions.UniqueFunction;
1415
import com.adacore.lkql_jit.exception.LKQLRuntimeException;
1516
import com.adacore.lkql_jit.nodes.expressions.Expr;
16-
import com.adacore.lkql_jit.nodes.expressions.FunCall;
1717
import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
1818
import com.adacore.lkql_jit.utils.LKQLTypesHelper;
19-
import com.oracle.truffle.api.frame.VirtualFrame;
19+
import com.oracle.truffle.api.dsl.Fallback;
20+
import com.oracle.truffle.api.dsl.Specialization;
2021
import java.util.Arrays;
2122
import java.util.Map;
2223

@@ -27,58 +28,70 @@
2728
*/
2829
public class ListMethods {
2930

30-
private static final Map.Entry<String, BuiltInMethodFactory> sublistFunction =
31-
createMethod(
32-
"sublist",
33-
"Return a sublist of `list` from `low_bound` to `high_bound`",
34-
new String[] {"low_bound", "high_bound"},
35-
new Expr[] {null, null},
36-
(VirtualFrame frame, FunCall call) -> {
37-
var args = frame.getArguments();
38-
39-
if (!LKQLTypeSystemGen.isLKQLList(args[0])) {
40-
throw LKQLRuntimeException.wrongType(
41-
LKQLTypesHelper.LKQL_LIST,
42-
LKQLTypesHelper.fromJava(args[0]),
43-
call.getArgList().getArgs()[0]);
44-
}
45-
46-
if (!LKQLTypeSystemGen.isLong(args[1])) {
47-
throw LKQLRuntimeException.wrongType(
48-
LKQLTypesHelper.LKQL_INTEGER,
49-
LKQLTypesHelper.fromJava(args[1]),
50-
call.getArgList().getArgs()[1]);
51-
}
52-
53-
if (!LKQLTypeSystemGen.isLong(args[2])) {
54-
throw LKQLRuntimeException.wrongType(
55-
LKQLTypesHelper.LKQL_INTEGER,
56-
LKQLTypesHelper.fromJava(args[2]),
57-
call.getArgList().getArgs()[2]);
58-
}
59-
60-
LKQLList list = LKQLTypeSystemGen.asLKQLList(args[0]);
61-
long lowBound = LKQLTypeSystemGen.asLong(args[1]);
62-
long highBound = LKQLTypeSystemGen.asLong(args[2]);
63-
64-
if (lowBound < 1) {
65-
throw LKQLRuntimeException.invalidIndex((int) lowBound, call);
66-
} else if (highBound > list.getContent().length) {
67-
throw LKQLRuntimeException.invalidIndex((int) highBound, call);
68-
}
69-
70-
return new LKQLList(
71-
Arrays.copyOfRange(
72-
list.getContent(), (int) lowBound - 1, (int) highBound));
73-
});
74-
7531
public static final Map<String, BuiltInMethodFactory> methods =
7632
BuiltInsHolder.combine(
7733
Map.ofEntries(
7834
Map.entry(
7935
UniqueFunction.NAME,
8036
BuiltInMethodFactory.fromFunctionValue(
8137
UniqueFunction.getValue(), true)),
82-
sublistFunction),
38+
createMethod(
39+
"sublist",
40+
"Return a sublist of `list` from "
41+
+ "`low_bound` to `high_bound`",
42+
new String[] {"low_bound", "high_bound"},
43+
new Expr[] {null, null},
44+
new SpecializedBuiltInBody<>(
45+
ListMethodsFactory.SublistExprNodeGen.create()) {
46+
@Override
47+
protected Object dispatch(Object[] args) {
48+
return this.specializedNode.executeSublist(
49+
LKQLTypeSystemGen.asLKQLList(args[0]),
50+
args[1],
51+
args[2]);
52+
}
53+
})),
8354
IterableMethods.methods);
55+
56+
// ----- Inner classes -----
57+
58+
/** Expression of the "sublist" method. */
59+
public abstract static class SublistExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
60+
61+
public abstract LKQLList executeSublist(LKQLList list, Object low, Object high);
62+
63+
@Specialization
64+
protected LKQLList onValid(LKQLList list, long low, long high) {
65+
// Offset the low bound by 1 since LKQL is 1-indexed
66+
low = low - 1;
67+
68+
// Check bounds validity
69+
if (low < 0) {
70+
throw LKQLRuntimeException.invalidIndex((int) low + 1, body.argNode(0));
71+
} else if (high > list.getContent().length) {
72+
throw LKQLRuntimeException.invalidIndex((int) high, body.argNode(1));
73+
}
74+
75+
// Return the sublist
76+
return new LKQLList(Arrays.copyOfRange(list.getContent(), (int) low, (int) high));
77+
}
78+
79+
@Specialization
80+
protected LKQLList onInvalidHigh(
81+
@SuppressWarnings("unused") LKQLList list,
82+
@SuppressWarnings("unused") long low,
83+
Object high) {
84+
throw LKQLRuntimeException.wrongType(
85+
LKQLTypesHelper.LKQL_INTEGER, LKQLTypesHelper.fromJava(high), body.argNode(1));
86+
}
87+
88+
@Fallback
89+
protected LKQLList onInvalidLow(
90+
@SuppressWarnings("unused") LKQLList list,
91+
Object low,
92+
@SuppressWarnings("unused") Object high) {
93+
throw LKQLRuntimeException.wrongType(
94+
LKQLTypesHelper.LKQL_INTEGER, LKQLTypesHelper.fromJava(low), body.argNode(0));
95+
}
96+
}
8497
}

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

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.adacore.lkql_jit.LKQLTypeSystemGen;
1414
import com.adacore.lkql_jit.built_ins.AbstractBuiltInFunctionBody;
1515
import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;
16+
import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
1617
import com.adacore.lkql_jit.exception.LKQLRuntimeException;
1718
import com.adacore.lkql_jit.nodes.expressions.Expr;
1819
import com.adacore.lkql_jit.runtime.values.LKQLNull;
@@ -22,8 +23,9 @@
2223
import com.adacore.lkql_jit.utils.functions.ObjectUtils;
2324
import com.adacore.lkql_jit.utils.functions.ReflectionUtils;
2425
import com.adacore.lkql_jit.utils.functions.StringUtils;
26+
import com.oracle.truffle.api.dsl.Fallback;
27+
import com.oracle.truffle.api.dsl.Specialization;
2528
import com.oracle.truffle.api.frame.VirtualFrame;
26-
import com.oracle.truffle.api.nodes.UnexpectedResultException;
2729
import java.util.ArrayList;
2830
import java.util.Map;
2931

@@ -66,7 +68,16 @@ public final class NodeMethods {
6668
"Return whether two nodes have the same tokens, ignoring trivias",
6769
new String[] {"other"},
6870
new Expr[] {null},
69-
new SameTokensExpr()));
71+
new SpecializedBuiltInBody<>(
72+
NodeMethodsFactory.SameTokensExprNodeGen.create()) {
73+
@Override
74+
protected Object dispatch(Object[] args) {
75+
return this.specializedNode.executeSameTokens(
76+
LKQLTypeSystemGen.asAdaNode(args[0]), args[1]);
77+
}
78+
}));
79+
80+
// ----- Inner classes -----
7081

7182
/** Expression of the "children" method. */
7283
public static final class ChildrenExpr extends AbstractBuiltInFunctionBody {
@@ -171,21 +182,13 @@ public Object executeGeneric(VirtualFrame frame) {
171182
}
172183

173184
/** Expression of the "same_tokens" method. */
174-
public static final class SameTokensExpr extends AbstractBuiltInFunctionBody {
175-
@Override
176-
public Object executeGeneric(VirtualFrame frame) {
177-
// Get the nodes to compare
178-
Libadalang.AdaNode leftNode = LKQLTypeSystemGen.asAdaNode(frame.getArguments()[0]);
179-
Libadalang.AdaNode rightNode;
180-
try {
181-
rightNode = LKQLTypeSystemGen.expectAdaNode(frame.getArguments()[1]);
182-
} catch (UnexpectedResultException e) {
183-
throw LKQLRuntimeException.wrongType(
184-
LKQLTypesHelper.ADA_NODE,
185-
LKQLTypesHelper.fromJava(e.getResult()),
186-
this.callNode.getArgList().getArgs()[0]);
187-
}
185+
public abstract static class SameTokensExpr
186+
extends SpecializedBuiltInBody.SpecializedBuiltInNode {
188187

188+
public abstract boolean executeSameTokens(Libadalang.AdaNode leftNode, Object rightNode);
189+
190+
@Specialization
191+
protected boolean onAdaNode(Libadalang.AdaNode leftNode, Libadalang.AdaNode rightNode) {
189192
// Get the tokens
190193
Libadalang.Token leftToken = leftNode.tokenStart();
191194
Libadalang.Token rightToken = rightNode.tokenStart();
@@ -218,12 +221,16 @@ public Object executeGeneric(VirtualFrame frame) {
218221
return true;
219222
}
220223

221-
/**
222-
* Get the next token from the given one ignoring the trivias
223-
*
224-
* @param t The token to get the next from
225-
* @return The next token
226-
*/
224+
@Fallback
225+
protected boolean onInvalid(
226+
@SuppressWarnings("unused") Libadalang.AdaNode leftNode, Object rightValue) {
227+
throw LKQLRuntimeException.wrongType(
228+
LKQLTypesHelper.ADA_NODE,
229+
LKQLTypesHelper.fromJava(rightValue),
230+
body.argNode(0));
231+
}
232+
233+
/** Get the next token from the given one ignoring the trivias. */
227234
private static Libadalang.Token next(Libadalang.Token t) {
228235
Libadalang.Token res = t.next();
229236
while (!res.isNone() && res.triviaIndex != 0) {

0 commit comments

Comments
 (0)