Example #1
0
 public static Set<Sort> of(Collection<org.kframework.kil.Sort> sorts) {
   ImmutableSet.Builder<Sort> builder = ImmutableSet.builder();
   for (org.kframework.kil.Sort name : sorts) {
     builder.add(Sort.of(name.getName()));
   }
   return builder.build();
 }
  @Override
  public ASTNode visit(org.kframework.kil.KApp node, Void _void) {
    if (node.getLabel() instanceof org.kframework.kil.Token) {
      if (node.getLabel() instanceof BoolBuiltin) {
        return BoolToken.of(((BoolBuiltin) node.getLabel()).booleanValue());
      } else if (node.getLabel() instanceof IntBuiltin) {
        return IntToken.of(((IntBuiltin) node.getLabel()).bigIntegerValue());
      } else if (node.getLabel() instanceof StringBuiltin) {
        return StringToken.of(((StringBuiltin) node.getLabel()).stringValue());
      } else if (node.getLabel() instanceof FloatBuiltin) {
        return FloatToken.of(
            ((FloatBuiltin) node.getLabel()).bigFloatValue(),
            ((FloatBuiltin) node.getLabel()).exponent());
      } else if (node.getLabel() instanceof GenericToken) {
        return UninterpretedToken.of(
            Sort.of(((GenericToken) node.getLabel()).tokenSort()),
            ((GenericToken) node.getLabel()).value());
      } else {
        assert false : "unsupported Token " + node.getLabel();
      }
    }

    Term kLabel = (Term) this.visitNode(node.getLabel());
    Term kList = (Term) this.visitNode(node.getChild());
    if (kList instanceof Variable) {
      kList = kList.sort().equals(Sort.KLIST) ? kList : KList.singleton(kList);
    }
    return KItem.of(kLabel, kList, termContext, node.getSource(), node.getLocation());
  }
Example #3
0
 private static String getSortName(ASTNode node) {
   Sort s;
   if (node instanceof NonTerminal) {
     s = Sort.of(((NonTerminal) node).getSort());
   } else if (node instanceof UserList) {
     s = Sort.of(((UserList) node).getSort());
   } else if (node instanceof Production) {
     s = Sort.of(((Production) node).getSort());
   } else if (node instanceof Variable) {
     s = ((Variable) node).sort();
   } else {
     assert false : "getSortName should be called with a sorted node";
     return null;
   }
   return s == Sort.BIT_VECTOR ? "(_ BitVec " + BitVector.getBitwidthOrDie(node) + ")" : s.name();
 }
Example #4
0
  private static String getSortAndFunctionDeclarations(
      Definition definition, Set<Variable> variables) {
    Set<Sort> sorts = new HashSet<>();
    List<Production> functions = new ArrayList<>();
    for (Production production : definition.context().productions) {
      String smtlib = production.getAttribute(Attribute.SMTLIB_KEY);
      if (smtlib != null && !SMTLIB_BUILTIN_FUNCTIONS.contains(smtlib) && !smtlib.startsWith("(")) {
        functions.add(production);
        sorts.add(Sort.of(production.getSort()));
        for (int i = 0; i < production.getArity(); ++i) {
          sorts.add(Sort.of(production.getChildSort(i)));
        }
      }
    }
    for (Variable variable : variables) {
      sorts.add(variable.sort());
    }

    if (!Sets.intersection(sorts, RESERVED_Z3_SORTS).isEmpty()) {
      throw new UnsupportedOperationException("do not use sorts " + RESERVED_Z3_SORTS);
    }

    StringBuilder sb = new StringBuilder();

    for (Sort sort : Sets.difference(sorts, SMTLIB_BUILTIN_SORTS)) {
      sb.append("(declare-sort ");
      sb.append(sort);
      sb.append(")\n");
    }

    for (Production production : functions) {
      sb.append("(declare-fun ");
      sb.append(production.getAttribute(Attribute.SMTLIB_KEY));
      sb.append(" (");
      List<String> childrenSorts = new ArrayList<>();
      for (int i = 0; i < production.getArity(); ++i) {
        childrenSorts.add(getSortName(production.getChildNode(i)));
      }
      Joiner.on(" ").appendTo(sb, childrenSorts);
      sb.append(") ");
      sb.append(getSortName(production));
      sb.append(")\n");
    }

    return sb.toString();
  }
  @Override
  public ASTNode visit(org.kframework.kil.Variable node, Void _void) {
    String name = node.fullName();

    if (node.getSort().equals(org.kframework.kil.Sort.BAG)
        || node.getSort().equals(org.kframework.kil.Sort.BAG_ITEM)) {
      return new Variable(name, Kind.CELL_COLLECTION.asSort());
    }

    if (node.getSort().equals(org.kframework.kil.Sort.K)) {
      return new Variable(name, Sort.KSEQUENCE);
    }
    if (node.getSort().equals(org.kframework.kil.Sort.KLIST)) {
      return new Variable(name, Sort.KLIST);
    }

    DataStructureSort dataStructureSort = context.dataStructureSortOf(node.getSort());
    if (dataStructureSort != null) {
      Sort sort = null;
      if (dataStructureSort.type().equals(org.kframework.kil.Sort.LIST)) {
        sort = Sort.LIST;
      } else if (dataStructureSort.type().equals(org.kframework.kil.Sort.MAP)) {
        sort = Sort.MAP;
      } else if (dataStructureSort.type().equals(org.kframework.kil.Sort.SET)) {
        sort = Sort.SET;
      } else {
        assert false : "unexpected data structure " + dataStructureSort.type();
      }

      if (concreteCollectionSize.containsKey(node)) {
        return new ConcreteCollectionVariable(name, sort, concreteCollectionSize.get(node));
      } else {
        return new Variable(name, sort);
      }
    }

    return new Variable(name, Sort.of(node.getSort()));
  }
Example #6
0
 public Sort getUserListSort(String separator) {
   return Sort.of(
       org.kframework.kil.Sort.LIST_OF_BOTTOM_PREFIX + name + "{\"" + separator + "\"}");
 }
Example #7
0
/**
 * Sort of a {@link Term}.
 *
 * @author YilongL
 */
public final class Sort implements MaximalSharing, Serializable, org.kframework.kore.Sort {

  private static final ConcurrentMap<String, Sort> cache = new ConcurrentHashMap<>();

  /** see {@link #ordinal()} */
  public static final AtomicInteger maxOrdinal = new AtomicInteger(0);

  public static final Sort KITEM = Sort.of("KItem");
  public static final Sort KSEQUENCE = Sort.of("K");
  public static final Sort KLIST = Sort.of("KList");
  public static final Sort KLABEL = Sort.of("KLabel");
  public static final Sort KRESULT = Sort.of("KResult");

  public static final Sort BAG = Sort.of("Bag");
  public static final Sort BAG_ITEM = Sort.of("BagItem");
  public static final Sort LIST = Sort.of("List");
  public static final Sort MAP = Sort.of("Map");
  public static final Sort SET = Sort.of("Set");

  public static final Sort INT = Sort.of("Int");
  public static final Sort BOOL = Sort.of("Bool");
  public static final Sort FLOAT = Sort.of("Float");
  public static final Sort CHAR = Sort.of("Char");
  public static final Sort STRING = Sort.of("String");
  public static final Sort BIT_VECTOR = Sort.of("MInt");
  public static final Sort META_VARIABLE = Sort.of("MetaVariable");

  public static final Sort VARIABLE = Sort.of("Variable");
  public static final Sort KVARIABLE = Sort.of("KVariable");

  public static final Sort BOTTOM = Sort.of("Bottom");
  public static final Sort SHARP_BOT = Sort.of("#Bot");
  public static final Sort MGU = Sort.of("Mgu");

  /** {@code String} representation of this {@code Sort}. */
  private final String name;

  private final int ordinal;

  /**
   * Gets the corresponding {@code Sort} from its {@code String} representation.
   *
   * @param name the name of the sort
   * @return the sort
   */
  public static Sort of(String name) {
    return cache.computeIfAbsent(name, s -> new Sort(s, maxOrdinal.getAndIncrement()));
  }

  public static Sort of(org.kframework.kil.Sort sort) {
    return of(sort.getName());
  }

  public static Set<Sort> of(Collection<org.kframework.kil.Sort> sorts) {
    ImmutableSet.Builder<Sort> builder = ImmutableSet.builder();
    for (org.kframework.kil.Sort name : sorts) {
      builder.add(Sort.of(name.getName()));
    }
    return builder.build();
  }

  private Sort(String name, int ordinal) {
    this.name = name;
    this.ordinal = ordinal;
  }

  public String name() {
    return name;
  }

  public int ordinal() {
    return ordinal;
  }

  public Sort getUserListSort(String separator) {
    return Sort.of(
        org.kframework.kil.Sort.LIST_OF_BOTTOM_PREFIX + name + "{\"" + separator + "\"}");
  }

  public org.kframework.kil.Sort toFrontEnd() {
    return org.kframework.kil.Sort.of(name);
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }

  @Override
  public boolean equals(Object object) {
    return this == object;
  }

  @Override
  public String toString() {
    return name;
  }

  /**
   * Returns the cached instance rather than the de-serialized instance if there is a cached
   * instance.
   */
  Object readResolve() throws ObjectStreamException {
    if (cache.containsKey(name) && cache.get(name).ordinal != this.ordinal) {
      KEMException.criticalError(
          "The ordinal for sort: "
              + name
              + " is "
              + cache.get(name).ordinal
              + " in the cache and "
              + this.ordinal
              + " serialized.");
    }
    // TODO: fix bug: ordinals from deserialized objects may overlap with those of newly created
    // objects
    return cache.computeIfAbsent(name, x -> this);
  }
}
 @Override
 public ASTNode visit(org.kframework.kil.KItemProjection node, Void _void) {
   return new KItemProjection(
       Kind.of(Sort.of(node.projectedKind())), (Term) this.visitNode(node.getTerm()));
 }
Example #9
0
public class KILtoSMTLib extends CopyOnWriteTransformer {

  public static final ImmutableSet<Sort> SMTLIB_BUILTIN_SORTS =
      ImmutableSet.of(Sort.BOOL, Sort.INT, Sort.BIT_VECTOR, Sort.of("IntSet"));
  public static final ImmutableSet<Sort> RESERVED_Z3_SORTS =
      ImmutableSet.of(Sort.LIST, Sort.SET, Sort.of("Seq"));
  public static final ImmutableSet<String> SMTLIB_BUILTIN_FUNCTIONS =
      ImmutableSet.of(
          "forall",
          "exists",
          /* core theory */
          "not",
          "and",
          "or",
          "xor",
          "=>",
          "=",
          "distinct",
          "ite",
          /* int theory */
          "+",
          "-",
          "*",
          "div",
          "mod",
          "abs",
          "<=",
          "<",
          ">=",
          ">",
          /* extra int theory */
          "int_max",
          "int_min",
          "int_abs",
          /* bit vector theory */
          "concat",
          "extract",
          "bvnot",
          "bvneg",
          "bvand",
          "bvor",
          "bvadd",
          "bvmul",
          "bvudiv",
          "bvurem",
          "bvshl",
          "bvlshr",
          "bvult",
          /* z3-specific bit vector theory */
          "bvsub",
          "bvxor",
          "bvslt",
          "bvule",
          "bvsle",
          "bvugt",
          "bvsgt",
          "bvuge",
          "bvsge",
          "bv2int",
          /* bit vector extras */
          "mint_signed_of_unsigned",
          /* set theory */
          "smt_set_mem",
          "smt_set_add",
          "smt_set_emp",
          "smt_set_cup",
          "smt_set_cap",
          "smt_set_com",
          "smt_set_sin",
          "smt_set_dif",
          "smt_set_sub",
          "smt_set_lt",
          "smt_set_le",
          /* bool2int */
          "smt_bool2int");

  /** Flag set to true if it is sounds to skip equalities that cannot be translated. */
  private final boolean skipEqualities;

  private final HashSet<Variable> variables;

  public static String translateConstraint(SymbolicConstraint constraint) {
    KILtoSMTLib transformer = new KILtoSMTLib(true);
    String expression = ((SMTLibTerm) constraint.accept(transformer)).expression();
    return getSortAndFunctionDeclarations(
            constraint.termContext().definition(), transformer.variables())
        + getAxioms(constraint.termContext().definition())
        + getConstantDeclarations(transformer.variables())
        + "(assert "
        + expression
        + ")";
  }

  public static String translateImplication(
      SymbolicConstraint leftHandSide, SymbolicConstraint rightHandSide) {
    KILtoSMTLib leftTransformer = new KILtoSMTLib(true);
    KILtoSMTLib rightTransformer = new KILtoSMTLib(false);
    String leftExpression = ((SMTLibTerm) leftHandSide.accept(leftTransformer)).expression();
    String rightExpression = ((SMTLibTerm) rightHandSide.accept(rightTransformer)).expression();
    StringBuilder sb = new StringBuilder();
    sb.append(
        getSortAndFunctionDeclarations(
            leftHandSide.termContext().definition(),
            Sets.union(leftTransformer.variables(), rightTransformer.variables())));
    sb.append(getAxioms(leftHandSide.termContext().definition()));
    sb.append(getConstantDeclarations(leftTransformer.variables()));
    sb.append("(assert (and ");
    sb.append(leftExpression);
    sb.append(" (not ");
    Set<Variable> rightHandSideOnlyVariables =
        Sets.difference(rightTransformer.variables(), leftTransformer.variables());
    if (!rightHandSideOnlyVariables.isEmpty()) {
      sb.append("(exists (");
      sb.append(getQuantifiedVariables(rightHandSideOnlyVariables));
      sb.append(") ");
    }
    sb.append(rightExpression);
    if (!rightHandSideOnlyVariables.isEmpty()) {
      sb.append(")");
    }
    sb.append(")))");
    return sb.toString();
  }

  private static String getSortAndFunctionDeclarations(
      Definition definition, Set<Variable> variables) {
    Set<Sort> sorts = new HashSet<>();
    List<Production> functions = new ArrayList<>();
    for (Production production : definition.context().productions) {
      String smtlib = production.getAttribute(Attribute.SMTLIB_KEY);
      if (smtlib != null && !SMTLIB_BUILTIN_FUNCTIONS.contains(smtlib) && !smtlib.startsWith("(")) {
        functions.add(production);
        sorts.add(Sort.of(production.getSort()));
        for (int i = 0; i < production.getArity(); ++i) {
          sorts.add(Sort.of(production.getChildSort(i)));
        }
      }
    }
    for (Variable variable : variables) {
      sorts.add(variable.sort());
    }

    if (!Sets.intersection(sorts, RESERVED_Z3_SORTS).isEmpty()) {
      throw new UnsupportedOperationException("do not use sorts " + RESERVED_Z3_SORTS);
    }

    StringBuilder sb = new StringBuilder();

    for (Sort sort : Sets.difference(sorts, SMTLIB_BUILTIN_SORTS)) {
      sb.append("(declare-sort ");
      sb.append(sort);
      sb.append(")\n");
    }

    for (Production production : functions) {
      sb.append("(declare-fun ");
      sb.append(production.getAttribute(Attribute.SMTLIB_KEY));
      sb.append(" (");
      List<String> childrenSorts = new ArrayList<>();
      for (int i = 0; i < production.getArity(); ++i) {
        childrenSorts.add(getSortName(production.getChildNode(i)));
      }
      Joiner.on(" ").appendTo(sb, childrenSorts);
      sb.append(") ");
      sb.append(getSortName(production));
      sb.append(")\n");
    }

    return sb.toString();
  }

  private static String getAxioms(Definition definition) {
    StringBuilder sb = new StringBuilder();
    for (Rule rule : definition.functionRules().values()) {
      if (rule.containsAttribute(Attribute.SMT_LEMMA_KEY)) {
        try {
          KILtoSMTLib transformer = new KILtoSMTLib(false);
          String leftExpression =
              ((SMTLibTerm) rule.leftHandSide().accept(transformer)).expression();
          String rightExpression =
              ((SMTLibTerm) rule.rightHandSide().accept(transformer)).expression();
          sb.append("(assert (forall (");
          sb.append(getQuantifiedVariables(transformer.variables()));
          sb.append(") (! (= ");
          sb.append(leftExpression);
          sb.append(" ");
          sb.append(rightExpression);
          sb.append(") :pattern(");
          sb.append(leftExpression);
          sb.append("))))\n");
        } catch (UnsupportedOperationException e) {
        }
      }
    }
    return sb.toString();
  }

  private static String getConstantDeclarations(Set<Variable> variables) {
    StringBuilder sb = new StringBuilder();
    for (Variable variable : variables) {
      sb.append("(declare-fun ");
      // TODO(AndreiS): make sure variable names are SMTLib compliant
      sb.append(variable.name());
      sb.append(" () ");
      String sortName;
      sortName = getSortName(variable);
      sb.append(sortName);
      sb.append(")\n");
    }
    return sb.toString();
  }

  private static String getQuantifiedVariables(Set<Variable> variables) {
    StringBuilder sb = new StringBuilder();
    for (Variable variable : variables) {
      sb.append("(");
      // TODO(AndreiS): make sure variable names are SMTLib compliant
      sb.append(variable.name());
      sb.append(" ");
      String sortName;
      sortName = getSortName(variable);
      sb.append(sortName);
      sb.append(")\n");
    }
    return sb.toString();
  }

  private static String getSortName(ASTNode node) {
    Sort s;
    if (node instanceof NonTerminal) {
      s = Sort.of(((NonTerminal) node).getSort());
    } else if (node instanceof UserList) {
      s = Sort.of(((UserList) node).getSort());
    } else if (node instanceof Production) {
      s = Sort.of(((Production) node).getSort());
    } else if (node instanceof Variable) {
      s = ((Variable) node).sort();
    } else {
      assert false : "getSortName should be called with a sorted node";
      return null;
    }
    return s == Sort.BIT_VECTOR ? "(_ BitVec " + BitVector.getBitwidthOrDie(node) + ")" : s.name();
  }

  public KILtoSMTLib(boolean skipEqualities) {
    this.skipEqualities = skipEqualities;
    variables = new HashSet<>();
  }

  /** Returns an unmodifiable view of the sets of variables occurring during the translation. */
  public Set<Variable> variables() {
    return Collections.unmodifiableSet(variables);
  }

  /**
   * Translates the equalities of the given symbolic constraint into SMTLib format. Ignores the
   * substitution of the symbolic constraint.
   */
  @Override
  public ASTNode transform(SymbolicConstraint constraint) {
    if (constraint.data.equalities.isEmpty()) {
      return new SMTLibTerm("true");
    }

    StringBuilder sb = new StringBuilder();
    sb.append("(and");
    boolean isEmptyAdd = true;
    for (SymbolicConstraint.Equality equality : constraint.data.equalities) {
      try {
        String left = ((SMTLibTerm) equality.leftHandSide().accept(this)).expression();
        String right = ((SMTLibTerm) equality.rightHandSide().accept(this)).expression();
        sb.append(" (= ");
        sb.append(left);
        sb.append(" ");
        sb.append(right);
        sb.append(")");
        isEmptyAdd = false;
      } catch (UnsupportedOperationException e) {
        // TODO(AndreiS): fix this translation and the exceptions
        if (skipEqualities) {
          /* it is sound to skip the equalities that cannot be translated */
          e.printStackTrace();
        } else {
          throw e;
        }
      }
    }
    if (isEmptyAdd) {
      sb.append(" true");
    }
    sb.append(")");
    return new SMTLibTerm(sb.toString());
  }

  @Override
  public ASTNode transform(KItem kItem) {
    if (!(kItem.kLabel() instanceof KLabelConstant)) {
      throw new UnsupportedOperationException();
    }
    KLabelConstant kLabel = (KLabelConstant) kItem.kLabel();

    if (!(kItem.kList() instanceof KList)) {
      throw new UnsupportedOperationException();
    }
    KList kList = (KList) kItem.kList();

    if (kList.hasFrame()) {
      throw new UnsupportedOperationException();
    }

    String label = kLabel.smtlib();
    if (label == null) {
      throw new UnsupportedOperationException("missing SMTLib translation for " + kLabel);
    }

    if (label.startsWith("(")) {
      // smtlib expression instead of operator
      String expression = label;
      for (int i = 0; i < kList.getContents().size(); i++) {
        expression =
            expression.replaceAll(
                "\\#" + (i + 1) + "(?![0-9])",
                ((SMTLibTerm) kList.get(i).accept(this)).expression());
      }
      return new SMTLibTerm(expression);
    }

    List<Term> arguments;
    switch (label) {
      case "exists":
        Variable variable = (Variable) kList.get(0);
        label = "exists ((" + variable.name() + " " + variable.sort() + ")) ";
        arguments = ImmutableList.of(kList.get(1));
        break;
      case "extract":
        int beginIndex = ((IntToken) kList.get(1)).intValue();
        int endIndex = ((IntToken) kList.get(2)).intValue() - 1;
        label = "(_ extract " + endIndex + " " + beginIndex + ")";
        arguments = ImmutableList.of(kList.get(0));
        break;
      default:
        arguments = kList.getContents();
    }

    if (!arguments.isEmpty()) {
      StringBuilder sb = new StringBuilder();
      sb.append("(");
      sb.append(label);
      for (Term argument : arguments) {
        sb.append(" ");
        sb.append(((SMTLibTerm) argument.accept(this)).expression());
      }
      sb.append(")");
      return new SMTLibTerm(sb.toString());
    } else {
      return new SMTLibTerm(label);
    }
  }

  @Override
  public ASTNode transform(BoolToken boolToken) {
    return new SMTLibTerm(Boolean.toString(boolToken.booleanValue()));
  }

  @Override
  public ASTNode transform(IntToken intToken) {
    return new SMTLibTerm(Long.toString(intToken.longValue()));
  }

  @Override
  public ASTNode transform(BitVector bitVector) {
    StringBuilder sb = new StringBuilder();
    sb.append("#b");
    for (int i = bitVector.bitwidth() - 1; i >= 0; --i) {
      BigInteger value = bitVector.unsignedValue();
      sb.append(value.testBit(i) ? "1" : "0");
    }
    return new SMTLibTerm(sb.toString());
  }

  @Override
  public ASTNode transform(Variable variable) {
    variables.add(variable);
    return new SMTLibTerm(variable.name());
  }
}