public /*@Nullable*/ String translate(IExpr expr) throws IVisitor.VisitorException { Translator t = new Translator(typemap, smtConfig); String r = expr.accept(t); if (t.conjuncts.isEmpty()) return r; String and = "(AND "; for (String c : t.conjuncts) { and = and + c + " "; } and = and + r + " )"; return and; }
@Override public IResponse get_value(IExpr... terms) { TypeChecker tc = new TypeChecker(symTable); try { for (IExpr term : terms) { term.accept(tc); } } catch (IVisitor.VisitorException e) { tc.result.add(smtConfig.responseFactory.error(e.getMessage())); } finally { if (!tc.result.isEmpty()) return tc.result.get(0); // FIXME - report all errors? } // FIXME - do we really want to call get-option here? it involves going to the solver? if (!Utils.TRUE.equals(get_option(smtConfig.exprFactory.keyword(Utils.PRODUCE_MODELS)))) { return smtConfig.responseFactory.error( "The get-value command is only valid if :produce-models has been enabled"); } if (!smtConfig.responseFactory.sat().equals(checkSatStatus) && !smtConfig.responseFactory.unknown().equals(checkSatStatus)) { return smtConfig.responseFactory.error( "A get-value command is valid only after check-sat has returned sat or unknown"); } return smtConfig.responseFactory.unsupported(); }
@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(); }