|
10 | 10 | import com.adacore.lkql_jit.LKQLTypeSystemGen; |
11 | 11 | import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory; |
12 | 12 | import com.adacore.lkql_jit.built_ins.BuiltInsHolder; |
| 13 | +import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody; |
13 | 14 | import com.adacore.lkql_jit.built_ins.functions.UniqueFunction; |
14 | 15 | import com.adacore.lkql_jit.exception.LKQLRuntimeException; |
15 | 16 | import com.adacore.lkql_jit.nodes.expressions.Expr; |
16 | | -import com.adacore.lkql_jit.nodes.expressions.FunCall; |
17 | 17 | import com.adacore.lkql_jit.runtime.values.lists.LKQLList; |
18 | 18 | 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; |
20 | 21 | import java.util.Arrays; |
21 | 22 | import java.util.Map; |
22 | 23 |
|
|
27 | 28 | */ |
28 | 29 | public class ListMethods { |
29 | 30 |
|
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 | | - |
75 | 31 | public static final Map<String, BuiltInMethodFactory> methods = |
76 | 32 | BuiltInsHolder.combine( |
77 | 33 | Map.ofEntries( |
78 | 34 | Map.entry( |
79 | 35 | UniqueFunction.NAME, |
80 | 36 | BuiltInMethodFactory.fromFunctionValue( |
81 | 37 | 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 | + })), |
83 | 54 | 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 | + } |
84 | 97 | } |
0 commit comments