| 34 | } |
| 35 | |
| 36 | @Override |
| 37 | protected Expr opt(final CompileContext cc) throws QueryException { |
| 38 | final Expr input = arg(0); |
| 39 | final SeqType st = input.seqType(); |
| 40 | if(st.zeroOrOne()) return input; |
| 41 | |
| 42 | final long size = input.size(); |
| 43 | // foot(tail(E)) → foot(E) |
| 44 | if(TAIL.is(input) && size > 1) |
| 45 | return cc.function(FOOT, info, input.args()); |
| 46 | // foot(trunk(E)) → items-at(E, size) |
| 47 | if(TRUNK.is(input) && size > 0) |
| 48 | return cc.function(ITEMS_AT, info, input.arg(0), Itr.get(size)); |
| 49 | // foot(reverse(E)) → head(E) |
| 50 | if(REVERSE.is(input)) |
| 51 | return cc.function(HEAD, info, input.args()); |
| 52 | // foot(replicate(E, count)) → foot(E) |
| 53 | if(REPLICATE.is(input)) { |
| 54 | // static integer will always be greater than 1 |
| 55 | if(input.arg(1) instanceof Itr) return cc.function(FOOT, info, input.arg(0)); |
| 56 | } |
| 57 | |
| 58 | // foot((1, 2)) → 2 |
| 59 | // foot((1, (2 to 3)) → foot(2 to 3) |
| 60 | if(input instanceof List) { |
| 61 | final Expr[] args = input.args(); |
| 62 | final Expr last = args[args.length - 1]; |
| 63 | final SeqType stl = last.seqType(); |
| 64 | if(stl.one()) return last; |
| 65 | if(stl.oneOrMore()) return cc.function(FOOT, info, last); |
| 66 | } |
| 67 | // foot(reverse(root)[test]) → head(root[test]) |
| 68 | if(input instanceof final IterFilter filter) { |
| 69 | final Expr root = cc.function(REVERSE, filter.info(), filter.root); |
| 70 | return cc.function(HEAD, info, Filter.get(cc, filter.info(), root, filter.exprs)); |
| 71 | } |
| 72 | |
| 73 | exprType.assign(st.with(st.oneOrMore() ? Occ.EXACTLY_ONE : Occ.ZERO_OR_ONE)).data(input); |
| 74 | return embed(cc, false); |
| 75 | } |
| 76 | } |