package freeboogie.backend; import java.util.logging.Logger; import freeboogie.util.StackedHashMap; /** * This class is responsible for sort-checking. The subclasses * are responsible for actually building a data structure (or calling * the prover to construct such a data structure inside it). * * @author rgrig * @author reviewed by TODO */ public abstract class TermBuilder { private static Logger log = Logger.getLogger("freeboogie.backend"); private StackedHashMap<String, TermDef> termDefs = new StackedHashMap<String, TermDef>(); /** * Define {@code name : s1 x ... x sn -> s}. * @param name a unique identifier * @param argSorts {@code s1 x ... x sn} * @param retSort {@code s} */ public void def(String name, Sort[] argSorts, Sort retSort) { log.fine("register symbol " + name); termDefs.put(name, new TermDef(argSorts, retSort)); } /** * Define {@code name : [sa] -> sr}. * @param name a unique identifier * @param naryArgSort {@code sa} * @param retSort {@code sr} */ public void def(String name, Sort naryArgSort, Sort retSort) { log.fine("register nary symbol " + name); termDefs.put(name, new TermDef(naryArgSort, retSort)); } /** * This maps a Java type to a prover sort. * @param name a unique identifier (for example, "const_int") * @param cls the Java type * @param retSort the prover sort */ public void def(String name, Class cls, Sort retSort) { log.fine("register meta-symbol " + name + " for Java type " + cls.getName()); termDefs.put(name, new TermDef(cls, retSort)); } /** * Undefines a term. * @param name the unique identifier of the term */ public void undef(String name) { termDefs.remove(name); } /** * Start a new `definitions frame'. */ public void pushDef() { termDefs.push(); } /** * Discard the last `definitions frame'. */ public void popDef() { termDefs.pop(); } /** * Retrieve a previously defined term. * @param name a unique id * @return the prover sort of {@code name} */ public TermDef getTermDef(String name) { return termDefs.get(name); } /** * Constructs a prover constant from the Java object {@code a}. * @param termId the term definition that allows this mapping * @param a the argument * @return the constructed term */ public final Term mk(String termId, Object a) { TermDef def = getTermDef(termId); assert def.cls != null; assert def.cls.isInstance(a); return reallyMk(def.retSort, termId, a); } /** * Helper for constructing terms with only one argument. * @param termId what term to be constructed * @param a the argument * @return the constructed term */ public final Term mk(String termId, Term a) { return mk(termId, new Term[] {a}); } /** * Helper for constructing terms with only two arguments. * * @param termId what term to construct * @param a the first argument * @param b the second argument * @return the newly constructed term */ public final Term mk(String termId, Term a, Term b) { return mk(termId, new Term[] {a, b}); } /** * Constructs a term with of the identified by {@code termId} * that takes {@code a} as arguments. * * @param termId identifies the term to be built * @param a the arguments * @return the newly built term */ public final Term mk(String termId, Term[] a) { TermDef def = getTermDef(termId); if (def.naryArgSort != null) { for (int i = 0; i < a.length; ++i) assert a[i].sort().isSubsortOf(def.naryArgSort); return reallyMkNary(def.retSort, termId, a); } else { assert def.argSorts.length == a.length; for (int i = 0; i < a.length; ++i) assert a[i].sort().isSubsortOf(def.argSorts[i]); return reallyMk(def.retSort, termId, a); } } /** * Subclasses should either construct a tree ar communicate with * the prover such that the prover constructs a tree. * * TODO The builder would need to know about the prover to do so. * * @param termId the term to be constructed * @param a the argument * @return the constructed term */ protected abstract Term reallyMk(Sort sort, String termId, Object a); /** * Subclasses should either construct a tree ar communicate with * the prover such that the prover constructs a tree. * * @param termId the term to be constructed * @param a the arguments * @return the constructed term */ protected abstract Term reallyMk(Sort sort, String termId, Term[] a); /** * Subclasses should either construct a tree ar communicate with * the prover such that the prover constructs a tree. * * @param termId the term to be constructed * @param a the arguments * @return the constructed term */ protected abstract Term reallyMkNary(Sort sort, String termId, Term[] a); }