| 60 | } |
| 61 | |
| 62 | @Override |
| 63 | public Expr optimize(final CompileContext cc) throws QueryException { |
| 64 | // remove duplicates and too specific catch clauses |
| 65 | final ArrayList<Catch> newCatches = new ArrayList<>(); |
| 66 | final ArrayList<Test> tests = new ArrayList<>(); |
| 67 | if(!((Checks<Catch>) Catch::global).all(catches)) { |
| 68 | for(final Catch ctch : catches) { |
| 69 | if(ctch.simplify(tests, cc)) newCatches.add(ctch); |
| 70 | } |
| 71 | catches = newCatches.toArray(Catch[]::new); |
| 72 | } |
| 73 | |
| 74 | Expr e = null; |
| 75 | if(expr instanceof Value) { |
| 76 | e = expr; |
| 77 | } else if(Function.ERROR.is(expr) && ((FnError) expr).values(true, cc)) { |
| 78 | try { |
| 79 | expr.value(cc.qc); |
| 80 | } catch(final QueryException ex) { |
| 81 | Util.debug(ex); |
| 82 | if(!ex.isCatchable()) throw ex; |
| 83 | final Catch ctch = matches(ex); |
| 84 | if(ctch != null) e = ctch.inline(ex, cc); |
| 85 | else if(fnlly == Empty.VALUE) throw ex; |
| 86 | } |
| 87 | } |
| 88 | if(e != null) { |
| 89 | if(fnlly == Empty.VALUE) return cc.replaceWith(this, e); |
| 90 | expr = e; |
| 91 | catches = new Catch[0]; |
| 92 | } |
| 93 | |
| 94 | // join types of try and catch expressions |
| 95 | SeqType st = expr.seqType(); |
| 96 | for(final Catch ctch : catches) st = st.union(ctch.seqType()); |
| 97 | exprType.assign(st).data(ExprList.concat(catches, expr)); |
| 98 | |
| 99 | return this; |
| 100 | } |
| 101 | |
| 102 | @Override |
| 103 | public Value value(final QueryContext qc) throws QueryException { |