Closed timotheecour closed 3 years ago
The p()
is called in the when
(and in the try: discard p(hlp,...)
line below) since the cligenHelp
call sites only pass the generated dispatcher name as the first arg and we want to test only the return type, not the whole type signature.
The whole when/else
is only needed because dispatchers inherit returns from the wrapped proc and because you cannot discard
a void and because discard
is required for non-void. I could instead add {.discardable.}
to generated dispatchers and ditch that when/else
entirely.
EDIT: or maybe your new typeOrVoid tests only the return value type anyway? In that case we could also drop the parens/call. Sorry...Early in the AM here.
EDIT: or maybe your new typeOrVoid tests only the return value type anyway? In that case we could also drop the parens/call. Sorry...Early in the AM here.
that would have different semantics from the code before this PR, because it'd then consider the function type (not the expression/statement resulting in evaluating p);
this PR should still be correct (ie preserving the semantics) but the p() still looks funky, unless p()
has same type as p(hlp, usage=use, prefix=pfx, skipHelp=skipHlp, noHdr=noUHdr)
(ie, all args are optional and no overloads of p()
)
there are other options too, eg a maybeDiscard[T](a: T)
which discards if T is not void
@c-blake oh btw, can you please push a new tag? the reason being, CI still fails, see https://github.com/nim-lang/Nim/pull/17807/checks?check_run_id=2399022131 , and I'm suspecting it's because it picks latest tagged release which doesn't pickup HEAD of cligen for these packages that depend on cligen: nimterop, prologue (see https://github.com/nim-lang/Nim/pull/17807)
not 100% sure whether this will fix CI but worth trying
Yeah, yeah. The PR works ok. I was just trying to explain/motivate the funkiness of the p()
"call" (which does have your all-defaulted properties, though no-overload may always be a bit more of a stretch..I do think of my namespace prefixing as guarding against collisions/carving out/declaring others shouldn't). There are a few options that maybe look less weird.
I have some edits to your fix (when declared(typeOrVoid)
basically, removing the https link and cleaning up the TODO bit) that I am working on. I want to test against a freshly compiled Nim and should finish in an hour or so. I'll stamp a new version tag after that. I was actually going to ask if I needed to do that for the CI.
So, I stamped a new version number for you.
Anyway, this p()
aspect seems more like a "looks weird" than "actually a problem", and "looks weird" can be pretty subjective. I could make it safeer by including all the parameters.
Making dispatchFoo
{.discardable.} would also eliminate the last branch in cligenQuit
and it would clearly work at least as far back as nim-0.19.2 which I still support (I guess some Linux distros are veeeery slow to update Nim versions, if they have them at all) for the core functionality (everything all the way back seems impractical and "if you want fancy-new-thing, upgrade your compiler" seems mild).
Your maybeDiscard
might work back then, too, but generics and void stuff has probably evolved more than discardable
or at least has a potentially larger interaction surface area. So, there's probably more a chance that between 0.19.2 and the present there will have been Nim versions where that failed whereas discardable
is used pretty heavily in the stdlib.
Also I doubt anyone out there is likely to call a dispatchFoo
manually/directly unless they maybe wrote their own dispatchMulti
(or multi-dispatch-like thing) yet still using cligen's dispatchGen
macro which also seems pretty unlikely.
You said you wrote your own private cligen-like thing. What did you do? I imagine one could also just factor out the help string construction from argument parsing and not have to call the dispatcher for the effect of dumping help. Or also just not do that in a multi-command.
Anyway, I'm not against cleaning that up, but it also seems not urgent.
So, I stamped a new version number for you.
thanks, that did the trick, CI became green (until i added a changelog with [skip ci]
, unrelated issue)
You said you wrote your own private cligen-like thing. What did you do?
just checked, i'm not handling this properly, but should (probably with maybeDiscard
); i still need to cleanup internal dependencies before publishing it as a nimble package... it probably doesn't have all the features from cligen but it does have real simplifications that you could reuse in cligen too ; i just need to get to it
Yeah...maybeDiscard
may be the way to go for me here, too..maybe for cligenQuit
as well. Adapting at the call site is safer than the def site of the wrapper on the off chance people may want to call dispatchFoo
as an "FFI like" alternate calling convention. One place that might be useful is in some run-time testing with a bunch of synthetic CL arg lists..Not sure I recall correctly, but your vitanim might do that.
(In general my same call site vs. def site observation may motivate having maybeDiscard
in the stdlib somewhere.)
Well, I went with discarder
. It's actually kind of tricky to name because the operation is more "discard If Possible". I have no idea what would be the least confusing name...forcedDiscard, discardVoid, or voidDiscard, non-type-but-emphasized Discard, alwaysDiscard, etc. I do see why Araq would not want a mistaken discard
of a void
to compile, though, since regular code wants to catch such mistakes.
Well, I just punched a new release for unrelated reasons with the new fix. Hopefully I don't break the Nim CI...
/cc @c-blake that was the only package that broke in https://github.com/nim-lang/Nim/pull/17807; the code here is forward and backward compatible wrt https://github.com/nim-lang/Nim/pull/17807, and is regardless of https://github.com/nim-lang/Nim/pull/17807 an improvement as it avoids a call to
compiles()
which causes extra compilation for the underlying expressionthe
p()
incompiles(type(p()))
seems suspicious given thatp
is apparently called also viap(hlp, usage=use, prefix=pfx, skipHelp=skipHlp, noHdr=noUHdr)
, but that's a pre-existing issue unrelated to this PR