Optimizes the expression. @param cc compilation context @return optimized or original expression @throws QueryException query exception
(final CompileContext cc)
| 88 | * @throws QueryException query exception |
| 89 | */ |
| 90 | private Expr opt(final CompileContext cc) throws QueryException { |
| 91 | final ExprList cases = new ExprList(); |
| 92 | Item cnd = cond instanceof Value ? cond.atomItem(cc.qc, info) : null; |
| 93 | final ArrayList<SwitchGroup> tmpGroups = new ArrayList<>(); |
| 94 | for(final SwitchGroup group : groups) { |
| 95 | final int el = group.exprs.length; |
| 96 | final ExprList list = new ExprList(el).add(group.rtrn()); |
| 97 | for(int e = 1; e < el; e++) { |
| 98 | final Expr expr = group.exprs[e]; |
| 99 | // check if same case expression exists more than once |
| 100 | boolean remove = cases.contains(expr); |
| 101 | if(!remove && cnd != null) { |
| 102 | // pre-evaluate values; skip remaining checks if match is found |
| 103 | if(expr instanceof Value) { |
| 104 | if(group.match(cnd, e, cc.qc)) return group.rtrn(); |
| 105 | remove = true; |
| 106 | } else { |
| 107 | // value unknown at compile: perform no further compile-time checks |
| 108 | cnd = null; |
| 109 | } |
| 110 | } |
| 111 | if(remove) { |
| 112 | cc.info(OPTREMOVE_X_X, expr, (Supplier<?>) this::description); |
| 113 | } else { |
| 114 | cases.add(expr); |
| 115 | list.add(expr); |
| 116 | } |
| 117 | } |
| 118 | // build list of branches (add those with case left, or the default branch) |
| 119 | if(list.size() > 1 || el == 1) { |
| 120 | group.exprs = list.finish(); |
| 121 | tmpGroups.add(group); |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // merge branches with identical return path |
| 126 | for(int g = 0; g < tmpGroups.size(); g++) { |
| 127 | final SwitchGroup group1 = g > 0 ? tmpGroups.get(g - 1) : null, group2 = tmpGroups.get(g); |
| 128 | if(g > 0 && group1.rtrn().equals(group2.rtrn())) { |
| 129 | if(g + 1 == tmpGroups.size() && !group1.has(Flag.NDT)) { |
| 130 | tmpGroups.set(g - 1, group2); |
| 131 | } else { |
| 132 | final ExprList list = new ExprList(group1.exprs.length + group2.exprs.length - 1); |
| 133 | list.add(group1.exprs).add(Arrays.copyOfRange(group2.exprs, 1, group2.exprs.length)); |
| 134 | tmpGroups.set(g - 1, new SwitchGroup(group1.info, list.finish()).optimize(cc)); |
| 135 | } |
| 136 | tmpGroups.remove(g--); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | // update branches |
| 141 | if(tmpGroups.size() != groups.length) { |
| 142 | groups = tmpGroups.toArray(SwitchGroup[]::new); |
| 143 | cc.info(OPTSIMPLE_X_X, (Supplier<?>) this::description, this); |
| 144 | } |
| 145 | |
| 146 | Expr expr = simplify(); |
| 147 | if(expr == this) expr = toIf(cc); |