Work towards efficient support for to_lower/to_upper.
}
break;
}
+ case kind::SEQ_NTH:
+ {
+ // only strings evaluate
+ Assert (currNode[0].getType().isString());
+ const String& s = results[currNode[0]].d_str;
+ Integer s_len(s.size());
+ Integer i = results[currNode[1]].d_rat.getNumerator();
+ if (i.strictlyNegative() || i >= s_len)
+ {
+ results[currNode] = EvalResult(s);
+ }
+ else
+ {
+ results[currNode] = EvalResult(Rational(s.getVec()[i.toUnsignedInt()]));
+ }
+ break;
+ }
case kind::STRING_UPDATE:
{
operator STRING_ITOS 1 "integer to string"
operator STRING_STOI 1 "string to integer (total function)"
operator STRING_TO_CODE 1 "string to code, returns the code of the first character of the string if it has length one, -1 otherwise"
-operator STRING_FROM_CODE 1 "string from code, returns a string containing a single character whose code point matches the argument to this function, empty string if the argument is out-of-bounds"
+operator STRING_FROM_CODE 1 "string from code, returns a string containing a single character whose code point matches the argument to this function, empty string if the argument is not a valid code point"
+operator STRING_UNIT 1 "string unit, returns a string containing a single character whose code point matches the argument to this function, arbitrary string of length one if the argument is not a valid code point"
operator STRING_TO_LOWER 1 "string to lowercase conversion"
operator STRING_TO_UPPER 1 "string to uppercase conversion"
operator STRING_REV 1 "string reverse"
typerule STRING_STOI "SimpleTypeRule<RInteger, AString>"
typerule STRING_TO_CODE "SimpleTypeRule<RInteger, AString>"
typerule STRING_FROM_CODE "SimpleTypeRule<RString, AInteger>"
+typerule STRING_UNIT "SimpleTypeRule<RString, AInteger>"
typerule STRING_TO_UPPER "SimpleTypeRule<RString, AString>"
typerule STRING_TO_LOWER "SimpleTypeRule<RString, AString>"
STRING_SUBSTR, t, n, nm->mkNode(SUB, nm->mkNode(STRING_LENGTH, t), n));
}
+Node mkUnit(TypeNode tn, Node n)
+{
+ NodeManager* nm = NodeManager::currentNM();
+ if (tn.isString())
+ {
+ return nm->mkNode(STRING_UNIT, n);
+ }
+ Assert(tn.isSequence());
+ TypeNode etn = tn.getSequenceElementType();
+ return nm->mkSeqUnit(etn, n);
+}
+
Node getConstantComponent(Node t)
{
if (t.getKind() == STRING_TO_REGEXP)
allEmptyEqs, std::vector<Node>(emptyNodes.begin(), emptyNodes.end()));
}
-bool isConstantLike(Node n) { return n.isConst() || n.getKind() == SEQ_UNIT; }
+bool isConstantLike(Node n)
+{
+ return n.isConst() || n.getKind() == SEQ_UNIT || n.getKind() == STRING_UNIT;
+}
bool isUnboundedWildcard(const std::vector<Node>& rs, size_t start)
{
*/
Node mkSuffix(Node t, Node n);
+/**
+ * Make a unit, returns either (str.unit n) or (seq.unit n) depending
+ * on if tn is a string or a sequence.
+ */
+Node mkUnit(TypeNode tn, Node n);
+
/**
* Get constant component. Returns the string constant represented by the
* string or regular expression t. For example:
return ret;
}
+Node Word::getNth(TNode x, size_t n)
+{
+ Kind k = x.getKind();
+ if (k == CONST_STRING)
+ {
+ const std::vector<unsigned>& vec = x.getConst<String>().getVec();
+ Assert(n < vec.size());
+ return NodeManager::currentNM()->mkConstInt(vec[n]);
+ }
+ else if (k == CONST_SEQUENCE)
+ {
+ const std::vector<Node>& vec = x.getConst<Sequence>().getVec();
+ Assert(n < vec.size());
+ return vec[n];
+ }
+ Unimplemented();
+ return Node::null();
+}
+
bool Word::isEmpty(TNode x) { return x.isConst() && getLength(x) == 0; }
bool Word::strncmp(TNode x, TNode y, std::size_t n)
* concatenation is equivalent to x.
*/
static std::vector<Node> getChars(TNode x);
+ /**
+ * Get nth. If x is a string constant, this returns the constant integer
+ * corresponding to the code point of x at position n. If x is a sequence
+ * constant, then this returns the nth element of x.
+ */
+ static Node getNth(TNode x, size_t n);
/** Return true if x is empty */
static bool isEmpty(TNode x);