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;
|
||||
}
|
||||
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> out;
|
||||
std::set<T_Key> saw;
|
||||
|
|
@ -843,6 +859,21 @@ public:
|
|||
return out;
|
||||
}
|
||||
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> out;
|
||||
for (const auto& i : m_map)
|
||||
|
|
@ -903,6 +934,16 @@ public:
|
|||
});
|
||||
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 {
|
||||
if (m_map.empty()) return VlQueue<T_Value>();
|
||||
const auto it = std::max_element(
|
||||
|
|
@ -912,6 +953,16 @@ public:
|
|||
});
|
||||
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 out(0); // Type must have assignment operator
|
||||
|
|
|
|||
|
|
@ -3219,10 +3219,12 @@ private:
|
|||
if (!nodep->firstAbovep()) newp->dtypeSetVoid();
|
||||
} else if (nodep->name() == "min" || nodep->name() == "max" || nodep->name() == "unique"
|
||||
|| nodep->name() == "unique_index") {
|
||||
AstWith* const withp = methodWithArgument(
|
||||
nodep, false, true, nullptr, nodep->findUInt32DType(), adtypep->subDTypep());
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
methodCallLValueRecurse(nodep, nodep->fromp(), VAccess::READ);
|
||||
newp = new AstCMethodHard{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
|
||||
nodep->name()};
|
||||
nodep->name(), withp};
|
||||
if (nodep->name() == "unique_index") {
|
||||
newp->dtypep(queueDTypeIndexedBy(adtypep->keyDTypep()));
|
||||
} 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);
|
||||
|
||||
module t (/*AUTOARG*/);
|
||||
typedef struct { int x, y; } point;
|
||||
initial begin
|
||||
int q[int];
|
||||
int qe[int]; // Empty
|
||||
int qv[$]; // Value returns
|
||||
int qi[$]; // Index returns
|
||||
point points_q[int];
|
||||
point points_qv[$];
|
||||
int i;
|
||||
string v;
|
||||
|
||||
|
|
@ -37,6 +40,16 @@ module t (/*AUTOARG*/);
|
|||
qi = qe.unique_index;
|
||||
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
|
||||
// TODO add a lint check that with clause is provided
|
||||
qv = q.find with (item == 2);
|
||||
|
|
@ -74,13 +87,22 @@ module t (/*AUTOARG*/);
|
|||
|
||||
qv = q.min;
|
||||
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;
|
||||
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;
|
||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||
qv = qe.min(x) with (x + 1);
|
||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||
qv = qe.max;
|
||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||
qv = qe.max(x) with (x + 1);
|
||||
v = $sformatf("%p", qv); `checks(v, "'{}");
|
||||
|
||||
// Reduction methods
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue