@Override public String visit(ISymbol e) throws IVisitor.VisitorException { // Symbols do not necessarily have sorts - e.g. if they are function names ISort sort = typemap.get(e); if (!isFormula && sort != null && sort.isBool()) { throw new VisitorException( "Use of boolean in a term position is not yet implemented in the Simplify adapter", e.pos()); // FIXME - booleans as terms } // Simplify does not allow tab, newline, cr in identifiers; // these are allowed by SMTLIB. // Note that neither simplify nor SMTLIB allows \ or | // All other printable characters are allowed in both. String oldName = e.value(); String newName = fcnNames.get(oldName); if (newName != null) { // There is a direct translation of a pre-defined SMT-LIB name // into a simplify equivalent - use it. } else { // Use the ? character as an escape newName = oldName.replace("?", "??").replace("\n", "?n").replace("\r", "?r").replace("\t", "?t"); if (reservedWords.contains(newName)) { newName = newName + "?!"; } newName = "|" + newName + "|"; } return newName; }
@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(); }