@Override public IResponse define_fun(Idefine_fun cmd) { IResponse res = super.define_fun(cmd); if (res.isError()) return res; try { if (cmd.resultSort().isBool() && cmd.parameters().size() > 0) { StringBuilder sb = new StringBuilder(); sb.append("(DEFPRED ("); sb.append(translate(cmd.symbol())); int n = cmd.parameters().size(); for (int i = 0; i < n; i++) { sb.append(" X"); sb.append(i); } sb.append("))\n"); String s = solverProcess.sendAndListen(sb.toString()); // FIXME - check for error in s -- System.out.println("HEARD " + s); res = smtConfig.responseFactory.success(); } else { res = smtConfig.responseFactory.success(); } IExpr.IFactory f = smtConfig.exprFactory; assertExpr(f.fcn(f.symbol("="), cmd.symbol(), cmd.expression())); } catch (IOException e) { res = smtConfig.responseFactory.error( "Failed to declare-fun: " + e.getMessage(), null); // FIXME - position? } catch (IVisitor.VisitorException e) { res = smtConfig.responseFactory.error("Failed to declare-fun: " + e.getMessage(), null); } return res; }
@Override public String visit(IAttributedExpr e) throws VisitorException { // FIXME - ignoring the name - should use a LBL expression StringBuilder sb = new StringBuilder(); sb.append("(LBL "); sb.append(e.attributes().get(0).attrValue().toString()); // Use the standard printer FIXME sb.append(" "); sb.append(e.expr().accept(this)); sb.append(")"); return sb.toString(); }
// @ requires iter.hasNext(); // @ requires length > 0; private <T extends IExpr> String leftassoc(String fcnname, int length, Iterator<T> iter) throws IVisitor.VisitorException { if (length == 1) { return iter.next().accept(this); } else { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(fcnname); sb.append(" "); sb.append(leftassoc(fcnname, length - 1, iter)); sb.append(" "); sb.append(iter.next().accept(this)); sb.append(")"); return sb.toString(); } }
// @ requires iter.hasNext(); private <T extends IExpr> String rightassoc(String fcnname, Iterator<T> iter) throws IVisitor.VisitorException { T n = iter.next(); if (!iter.hasNext()) { return n.accept(this); } else { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(fcnname); sb.append(" "); sb.append(n.accept(this)); sb.append(" "); sb.append(rightassoc(fcnname, iter)); sb.append(")"); return sb.toString(); } }
@Override public String visit(IExists e) throws IVisitor.VisitorException { if (!isFormula) { throw new VisitorException( "Use of exists in a term position is not yet implemented in the Simplify adapter", e.pos()); // FIXME - booleans as terms } StringBuilder sb = new StringBuilder(); sb.append("(EXISTS ("); for (IDeclaration d : e.parameters()) { if (d.sort().isBool()) { throw new VisitorException( "Boolean quantifiers are not implemented in the Simplify adapter", e.pos()); // FIXME - booleans as terms } sb.append(d.accept(this)); sb.append(" "); } sb.append(") "); sb.append(e.expr().accept(this)); sb.append(")"); return sb.toString(); }
@Override public String visit(IDeclaration e) throws IVisitor.VisitorException { StringBuilder sb = new StringBuilder(); sb.append(e.parameter().accept(this)); return sb.toString(); }
@Override public String visit(IFcnExpr e) throws IVisitor.VisitorException { boolean resultIsFormula = this.isFormula; StringBuilder sb = new StringBuilder(); try { Iterator<IExpr> iter = e.args().iterator(); if (!iter.hasNext()) throw new VisitorException("Did not expect an empty argument list", e.pos()); if (!(e.head() instanceof ISymbol)) { throw new VisitorException( "Have not yet implemented parameterized bit-vector functions", e.pos()); } ISymbol fcn = (ISymbol) e.head(); String newName = fcn.accept(this); // Determine if the arguments are formulas or terms if (resultIsFormula) { if (newName != null && logicNames.contains(newName)) { // Propositional boolean item this.isFormula = true; } else if (e.args().size() <= 1) { this.isFormula = false; } else { IExpr arg = e.args().get(1); // Use argument 1 for ite's sake ISort sort = typemap.get(arg); if (sort == null) { throw new VisitorException( "INTERNAL ERROR: Encountered an un-sorted expression node: " + smtConfig.defaultPrinter.toString(arg), arg.pos()); } if (sort.isBool()) { // Some functions can take both bool and non-bool arguments: // EQ NEQ DISTINCT ite this.isFormula = resultIsFormula; if ("EQ".equals(newName)) newName = "IFF"; } else { // Arguments must be terms this.isFormula = false; } } } else { this.isFormula = false; } ISort s = typemap.get(e); if (s == null) { throw new VisitorException( "INTERNAL ERROR: Encountered an un-sorted expression node: " + smtConfig.defaultPrinter.toString(e), e.pos()); } if (s.isBool() && !resultIsFormula) { throw new VisitorException( "Use of boolean in a term position is not yet implemented in the Simplify adapter", e.pos()); // FIXME - booleans as terms } if (isFormula && newName.equals("NEQ")) { // for formulas, NEQ is (NOT (IFF p q ...)) // In simplify, IFF is not implicitly chainable int length = e.args().size(); if ((length & 1) == 0) sb.append("(NOT "); sb.append(leftassoc("IFF", length, iter)); if ((length & 1) == 0) sb.append(")"); } else if (newName.equals("IMPLIES")) { // right-associative operators that need grouping if (!iter.hasNext()) { throw new VisitorException("implies (=>) operation without arguments", e.pos()); } sb.append(rightassoc(newName, iter)); } else if (newName.equals("DISTINCT")) { // in simplify, DISTINCT is just for term arguments but the result is a formula if (isFormula) { // arguments are formulas, result is formula if (e.args().size() > 2) { // More than two distinct boolean values? sb.append("FALSE"); } else { sb.append("(NOT (IFF"); while (iter.hasNext()) { sb.append(" "); sb.append(iter.next().accept(this)); } sb.append(" ))"); } } else if (resultIsFormula) { // arguments are terms, result is formula - standard use in Simplify sb.append("(DISTINCT"); while (iter.hasNext()) { sb.append(" "); sb.append(iter.next().accept(this)); } sb.append(")"); } else { // used in a term position throw new VisitorException( "Use of DISTINCT in a term position is not yet implemented in the Simplify adapter", e.pos()); // FIXME - distinact as a term } } else if (ite_term.equals(newName)) { if (isFormula) { sb.append("(AND (IMPLIES "); sb.append(e.args().get(0).accept(this)); sb.append(" "); sb.append(e.args().get(1).accept(this)); sb.append(")"); sb.append("(IMPLIES (NOT "); sb.append(e.args().get(0).accept(this)); sb.append(") "); sb.append(e.args().get(2).accept(this)); sb.append("))"); } } if (e.args().size() > 2 && nonchainables.contains(newName)) { Iterator<IExpr> iter2 = e.args().iterator(); sb.append("(AND "); IExpr left = iter2.next(); while (iter2.hasNext()) { IExpr right = iter2.next(); sb.append("(" + newName + " "); sb.append(left.accept(this)); sb.append(" "); sb.append(right.accept(this)); sb.append(")"); left = right; } sb.append(")"); } if (e.args().size() > 2 && (newName.equals("-") || newName.equals("/"))) { Iterator<IExpr> iter2 = e.args().iterator(); sb.append(leftassoc(newName, e.args().size(), iter2)); } if (sb.length() == 0) { sb.append("( "); sb.append(newName); while (iter.hasNext()) { sb.append(" "); sb.append(iter.next().accept(this)); } sb.append(" )"); } } finally { this.isFormula = resultIsFormula; } return sb.toString(); }