Support string len() method.

This commit is contained in:
Wilson Snyder
2017-12-07 19:57:11 -05:00
parent 6b6e8dc83e
commit 662ebece71
8 changed files with 180 additions and 0 deletions
+12
View File
@@ -3545,6 +3545,18 @@ public:
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
};
class AstLenN : public AstNodeUniop {
// Length of a string
public:
AstLenN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
dtypeSetSigned32(); }
ASTNODE_NODE_FUNCS(LenN)
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); }
virtual string emitVerilog() { return "%f(%l)"; }
virtual string emitC() { return "VL_LEN_IN(%li)"; }
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
};
class AstLogNot : public AstNodeUniop {
public:
AstLogNot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
+5
View File
@@ -1035,6 +1035,11 @@ V3Number& V3Number::opConcat (const V3Number& lhs, const V3Number& rhs) {
return *this;
}
V3Number& V3Number::opLenN (const V3Number& lhs) {
setQuad(lhs.toString().length());
return *this;
}
V3Number& V3Number::opRepl (const V3Number& lhs, const V3Number& rhs) { // rhs is # of times to replicate
// Hopefully the using routine has a error check too.
// See also error in V3Width
+1
View File
@@ -242,6 +242,7 @@ public:
V3Number& opCLog2 (const V3Number& lhs);
V3Number& opClean (const V3Number& lhs, uint32_t bits);
V3Number& opConcat (const V3Number& lhs, const V3Number& rhs);
V3Number& opLenN (const V3Number& lhs);
V3Number& opRepl (const V3Number& lhs, const V3Number& rhs);
V3Number& opRepl (const V3Number& lhs, uint32_t rhs);
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
+25
View File
@@ -330,6 +330,9 @@ private:
// Widths: Output integer unsigned, input real
virtual void visit(AstRealToBits* nodep) { visit_Ou64_Lr(nodep); }
// Output integer, input string
virtual void visit(AstLenN* nodep) { visit_Os32_string(nodep); }
// Widths: Constant, terminal
virtual void visit(AstTime* nodep) { nodep->dtypeSetUInt64(); }
virtual void visit(AstTimeD* nodep) { nodep->dtypeSetDouble(); }
@@ -1497,6 +1500,7 @@ private:
// Find the fromp dtype - should be a class
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump();
AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL;
UINFO(9," from dt "<<fromDtp<<endl);
if (AstEnumDType* adtypep = fromDtp->castEnumDType()) {
// Method call on enum without following parenthesis, e.g. "ENUM.next"
@@ -1613,6 +1617,17 @@ private:
nodep->v3error("Unknown built-in array method '"<<nodep->fromp()->prettyTypeName()<<"'");
}
}
else if (basicp && basicp->isString()) {
// Method call on string
if (nodep->name() == "len") {
// Constant value
AstNode* newp = new AstLenN(nodep->fileline(), nodep->fromp()->unlinkFrBack());
nodep->replaceWith(newp);
pushDeletep(nodep); VL_DANGLING(nodep);
} else {
nodep->v3error("Unsupported: built-in string method '"<<nodep->fromp()->prettyTypeName()<<"'");
}
}
else {
nodep->v3error("Unsupported: Member call on non-enum object '"
<<nodep->fromp()->prettyTypeName()<<"' which is a '"<<nodep->fromp()->dtypep()->prettyTypeName()<<"'");
@@ -2646,6 +2661,16 @@ private:
nodep->dtypeSetLogicBool();
}
}
void visit_Os32_string(AstNodeUniop* nodep) {
// CALLER: LenN
// Widths: 32 bit out
if (!nodep->lhsp()) nodep->v3fatalSrc("For unary ops only!");
if (m_vup->prelim()) {
// See similar handling in visit_cmp_eq_gt where created
iterateCheckString(nodep,"LHS",nodep->lhsp(),BOTH);
nodep->dtypeSetSigned32();
}
}
void visit_negate_not(AstNodeUniop* nodep, bool real_ok) {
// CALLER: (real_ok=false) Not