Support locator methods with "with" on assoc arrays (#4335)
This commit is contained in:
parent
9249ffdb84
commit
97feba6898
|
|
@ -830,6 +830,22 @@ public:
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
template <typename Func>
|
||||||
|
VlQueue<T_Value> unique(Func with_func) const {
|
||||||
|
VlQueue<T_Value> out;
|
||||||
|
T_Key default_key;
|
||||||
|
using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second));
|
||||||
|
std::set<WithType> saw;
|
||||||
|
for (const auto& i : m_map) {
|
||||||
|
const auto i_mapped = with_func(default_key, i.second);
|
||||||
|
const auto it = saw.find(i_mapped);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i_mapped);
|
||||||
|
out.push_back(i.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
VlQueue<T_Key> unique_index() const {
|
VlQueue<T_Key> unique_index() const {
|
||||||
VlQueue<T_Key> out;
|
VlQueue<T_Key> out;
|
||||||
std::set<T_Key> saw;
|
std::set<T_Key> saw;
|
||||||
|
|
@ -843,6 +859,21 @@ public:
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
|
VlQueue<T_Key> unique_index(Func with_func) const {
|
||||||
|
VlQueue<T_Key> out;
|
||||||
|
using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second));
|
||||||
|
std::set<WithType> saw;
|
||||||
|
for (const auto& i : m_map) {
|
||||||
|
const auto i_mapped = with_func(i.first, i.second);
|
||||||
|
auto it = saw.find(i_mapped);
|
||||||
|
if (it == saw.end()) {
|
||||||
|
saw.insert(it, i_mapped);
|
||||||
|
out.push_back(i.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
template <typename Func>
|
||||||
VlQueue<T_Value> find(Func with_func) const {
|
VlQueue<T_Value> find(Func with_func) const {
|
||||||
VlQueue<T_Value> out;
|
VlQueue<T_Value> out;
|
||||||
for (const auto& i : m_map)
|
for (const auto& i : m_map)
|
||||||
|
|
@ -903,6 +934,16 @@ public:
|
||||||
});
|
});
|
||||||
return VlQueue<T_Value>::cons(it->second);
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
}
|
}
|
||||||
|
template <typename Func>
|
||||||
|
VlQueue<T_Value> min(Func with_func) const {
|
||||||
|
if (m_map.empty()) return VlQueue<T_Value>();
|
||||||
|
const auto it = std::min_element(
|
||||||
|
m_map.begin(), m_map.end(),
|
||||||
|
[&with_func](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||||
|
return with_func(a.first, a.second) < with_func(b.first, b.second);
|
||||||
|
});
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
VlQueue<T_Value> max() const {
|
VlQueue<T_Value> max() const {
|
||||||
if (m_map.empty()) return VlQueue<T_Value>();
|
if (m_map.empty()) return VlQueue<T_Value>();
|
||||||
const auto it = std::max_element(
|
const auto it = std::max_element(
|
||||||
|
|
@ -912,6 +953,16 @@ public:
|
||||||
});
|
});
|
||||||
return VlQueue<T_Value>::cons(it->second);
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
}
|
}
|
||||||
|
template <typename Func>
|
||||||
|
VlQueue<T_Value> max(Func with_func) const {
|
||||||
|
if (m_map.empty()) return VlQueue<T_Value>();
|
||||||
|
const auto it = std::max_element(
|
||||||
|
m_map.begin(), m_map.end(),
|
||||||
|
[&with_func](const std::pair<T_Key, T_Value>& a, const std::pair<T_Key, T_Value>& b) {
|
||||||
|
return with_func(a.first, a.second) < with_func(b.first, b.second);
|
||||||
|
});
|
||||||
|
return VlQueue<T_Value>::cons(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
T_Value r_sum() const {
|
T_Value r_sum() const {
|
||||||
T_Value out(0); // Type must have assignment operator
|
T_Value out(0); // Type must have assignment operator
|
||||||
|
|
|
||||||
|
|
@ -3219,10 +3219,12 @@ private:
|
||||||
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
|
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
|
||||||
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|
||||||
|| nodep->name() == "unique_index") {
|
|| nodep->name() == "unique_index") {
|
||||||
|
AstWith* const withp = methodWithArgument(
|
||||||
|
nodep, false, true, nullptr, nodep->findUInt32DType(), adtypep->subDTypep());
|
||||||
methodOkArguments(nodep, 0, 0);
|
methodOkArguments(nodep, 0, 0);
|
||||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||||
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||||
nodep->name()};
|
nodep->name(), withp};
|
||||||
if (nodep->name() == "unique_index") {
|
if (nodep->name() == "unique_index") {
|
||||||
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
|
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,14 @@
|
||||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||||
|
|
||||||
module t (/*AUTOARG*/);
|
module t (/*AUTOARG*/);
|
||||||
|
typedef struct { int x, y; } point;
|
||||||
initial begin
|
initial begin
|
||||||
int q[int];
|
int q[int];
|
||||||
int qe[int]; // Empty
|
int qe[int]; // Empty
|
||||||
int qv[$]; // Value returns
|
int qv[$]; // Value returns
|
||||||
int qi[$]; // Index returns
|
int qi[$]; // Index returns
|
||||||
|
point points_q[int];
|
||||||
|
point points_qv[$];
|
||||||
int i;
|
int i;
|
||||||
string v;
|
string v;
|
||||||
|
|
||||||
|
|
@ -37,6 +40,16 @@ module t (/*AUTOARG*/);
|
||||||
qi = qe.unique_index;
|
qi = qe.unique_index;
|
||||||
v = $sformatf("%p", qi); `checks(v, "'{}");
|
v = $sformatf("%p", qi); `checks(v, "'{}");
|
||||||
|
|
||||||
|
points_q[0] = point'{1, 2};
|
||||||
|
points_q[1] = point'{2, 4};
|
||||||
|
points_q[5] = point'{1, 4};
|
||||||
|
|
||||||
|
points_qv = points_q.unique(p) with (p.x);
|
||||||
|
`checkh(points_qv.size, 2);
|
||||||
|
qi = points_q.unique_index(p) with (p.x + p.y);
|
||||||
|
qi.sort;
|
||||||
|
v = $sformatf("%p", qi); `checks(v, "'{'h0, 'h1, 'h5} ");
|
||||||
|
|
||||||
// These require an with clause or are illegal
|
// These require an with clause or are illegal
|
||||||
// TODO add a lint check that with clause is provided
|
// TODO add a lint check that with clause is provided
|
||||||
qv = q.find with (item == 2);
|
qv = q.find with (item == 2);
|
||||||
|
|
@ -74,13 +87,22 @@ module t (/*AUTOARG*/);
|
||||||
|
|
||||||
qv = q.min;
|
qv = q.min;
|
||||||
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
|
v = $sformatf("%p", qv); `checks(v, "'{'h1} ");
|
||||||
|
points_qv = points_q.min(p) with (p.x + p.y);
|
||||||
|
if (points_qv[0].x != 1 || points_qv[0].y != 2) $stop;
|
||||||
|
|
||||||
qv = q.max;
|
qv = q.max;
|
||||||
v = $sformatf("%p", qv); `checks(v, "'{'h4} ");
|
v = $sformatf("%p", qv); `checks(v, "'{'h4} ");
|
||||||
|
points_qv = points_q.max(p) with (p.x + p.y);
|
||||||
|
if (points_qv[0].x != 2 || points_qv[0].y != 4) $stop;
|
||||||
|
|
||||||
qv = qe.min;
|
qv = qe.min;
|
||||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||||
|
qv = qe.min(x) with (x + 1);
|
||||||
|
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||||
qv = qe.max;
|
qv = qe.max;
|
||||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||||
|
qv = qe.max(x) with (x + 1);
|
||||||
|
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||||
|
|
||||||
// Reduction methods
|
// Reduction methods
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue