Guest8686 has quit [Remote host closed the connection]
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
Guest3889 has joined #amaranth-lang
Guest3889 has quit [Remote host closed the connection]
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
V has joined #amaranth-lang
<RobTaylor[m]>
I've just been thinking of submitting an RFC to add a base repr to Component that displays its interface and metadata. Would that be welcome?
<RobTaylor[m]>
s/repr/`__repr__`/
V has quit [Remote host closed the connection]
<whitequark[cis]1>
i think changing __repr__ is probably not RFC-worthy
<whitequark[cis]1>
technically it does fit under the criteria but i don't think anyone does rely on that being a part of the formal interface (and if they expect that we should probably make it clear that __repr__ isn't meant to be fully stable; even Python itself doesn't do that, PyPy has a different object.__repr__)
V has joined #amaranth-lang
V has quit [Remote host closed the connection]
<RobTaylor[m]>
so just a PR then? :)
<whitequark[cis]1>
let's just discuss the format first?
<whitequark[cis]1>
metadata as in JSON? that can get pretty long
<whitequark[cis]1>
interface definitely makes sense to display though
richardeoin has quit [Remote host closed the connection]
richardeoin has joined #amaranth-lang
<whitequark[cis]1>
were you thinking of just shoving the component signature into the __repr__ or something more complex? I forget how signatures are printed, probably like a `<Signature {members...}>` or something
<RobTaylor[m]>
yeah, just {type(self) {self.signature} {self.metadata}. maybe also a str method with prettyprinting
<RobTaylor[m]>
signature has a repr - though there was a slight bug re current usage patterns (see #1552)
<whitequark[cis]1>
that's intentional, there's a test for it even
<RobTaylor[m]>
and yeah, its dict{self.members.items()}
<whitequark[cis]1>
basically, if you subclass Signature you are expected to implement your own __repr__ since otherwise the additional fields won't get exposed
<whitequark[cis]1>
(and if you add no fields you shouldn't be subclassing it in firts place)
<whitequark[cis]1>
s/firts/first/
<whitequark[cis]1>
if Glasgow did not do that then that's a bug in Glasgow (I probably just forgot, the port to 0.5 was somewhat rushed)
<RobTaylor[m]>
ah, ok, makes sense!
<RobTaylor[m]>
no, my bad it wasnt glasgow, other code ><
<whitequark[cis]1>
ah. that should probably be just Signature = wiring.Signature({...}) I think?
<whitequark[cis]1>
the super().__init__ initialization pattern is somewhat of a remnant from the dark days of Record
<whitequark[cis]1>
although I guess that has a different invocation
<whitequark[cis]1>
right ok i see, JF's choice is fully generic
<RobTaylor[m]>
yep, aleady fixed it locally =)
<whitequark[cis]1>
like if we later decide to add some introspectable parameter (say data_width) then this is the right thing to do to avoid a breaking change
<whitequark[cis]1>
we might want to discuss it once he's back
<whitequark[cis]1>
there isn't a single clearly correct way that i see here
<RobTaylor[m]>
but yeah, there is one case in amaranth-soc: PinSignature
<RobTaylor[m]>
whitequark[cis]1: 👍️
<RobTaylor[m]>
whitequark[cis]1: ah, i see. yeah, that makes sense
<whitequark[cis]1>
wasn't PinSignature the thing we deprecated?..
<RobTaylor[m]>
not marked as deprecated at the moment
<whitequark[cis]1>
nah, that one is fine, we decided to keep PinSignature around just like that
<RobTaylor[m]>
probably wants a repr then?
<whitequark[cis]1>
yes
<whitequark[cis]1>
as currently defined, all derivatives of Signature should have a __repr__
<whitequark[cis]1>
the fact that lots of them don't means that there's a papercut somewhere here, but i also don't know if or how we should fix that
<RobTaylor[m]>
yeah, its a tricky one. Could we use @abstractmethod ?
<whitequark[cis]1>
that would be a compat break requiring an RFC (and honestly i don't see us approving it)
<whitequark[cis]1>
we could add a warning in __init_subclass__
<whitequark[cis]1>
but, again, i'm not sure that we know that there is one specific resolution here that's desirable
<whitequark[cis]1>
for example defining a function def Signature(): preserves the syntax without creating unnecessary named signatures
<RobTaylor[m]>
yeah, needs figuring out
<whitequark[cis]1>
then you can upgrade it to class Signature(wiring.Signature): without a compat break
<whitequark[cis]1>
but this is a ... weird thing to do in idiomatic Python
<RobTaylor[m]>
nod
<whitequark[cis]1>
i'm not opposed to doing weird things but i think that languages have a weirdness budget that needs to be carefully spent
<whitequark[cis]1>
one option is to require a __repr__ implementation but make def __repr__(self): return super().__repr() a valid one
<whitequark[cis]1>
that's still sort of weird to have but it reads like normal Python at least
<whitequark[cis]1>
however, there's an additional problem: these Signature subclasses never override __eq__ and friends
<whitequark[cis]1>
so I think __repr__ is like the least of the problems, they're sort of subtly broken in bigger ways already
<RobTaylor[m]>
yeah. maybe standard should be a class method
<RobTaylor[m]>
and a bit more babysitting to avoid subtle breakage
<whitequark[cis]1>
standard?
<whitequark[cis]1>
i think the first question we need to resolve is: do we use anonymous signatures for components, or named ones?
<whitequark[cis]1>
the docs universally use anonymous ones
<whitequark[cis]1>
it usually doesn't matter
<RobTaylor[m]>
the amarnth-soc usecase seems to be when you're combining components and exposing (some of) their signatures from the combined entity
<RobTaylor[m]>
but I don't fully understand it all yet - hence why i'm looking at __repr__s 😅😅😂
<whitequark[cis]1>
it's a question of how parameterizability works
<RobTaylor[m]>
nod
zyp[m] has joined #amaranth-lang
<zyp[m]>
<whitequark[cis]1> "i think the first question we..." <- I would argue that named signatures only makes sense when they're a predefined reusable thing, and the toplevel signature of a component rarely is, since that implies that the component only has a fixed set of members
<whitequark[cis]1>
i would agree, but this means that parameterized component signatures that are reused internally in another component should use the def Signature(...): pattern
<zyp[m]>
but when are component signatures reused? sounds like something that'd fall under «predefined reusable thing»
<whitequark[cis]1>
see the amaranth-soc example in the backlog
<whitequark[cis]1>
it's a very technical case of reuse
<zyp[m]>
that seems unnecessarily verbose and I don't see why Signature has to exist at all
<zyp[m]>
I'd argue that if UARTPhy wants to just reexport the inner signatures, it could just pick them up from .signature after constructing them and call super().__init__() last