Make Sym "XXX:ObjectType" works with `macros.getImpl`
Closed this issue · 8 comments
Make Sym "XXX:ObjectType" works with macros.getImpl
Background story
We have 5 or 6 hasCustomPragma
related issues:
misc issues:
ref/ptr issues:
4. nim-lang/Nim#12523
5. nim-lang/Nim#8457
6. status-im/nim-json-serialization#11 (using alternate implementation of hasCustomPragma
from status-im/stew)
This is about macros.hasCustomPragma
. Current implementation of hasCustomPragma
is barely readable.
That is why we implement an alternate version of hasCustomPragma
in nim-stew/macros.
This new implementation of hasCustomPragma
readability is far above macros.hasCustomPragma
and also easier to use when designing a serialization library.
Issues no 1 to 3 practically can be eliminated easily.
However, issues no 4-6 remain the same for both implementation. stdlib-hasCustomPragma
using various work-around to no avail.
nim-stew-hasCustomPragma
actually very close to get it works.
nim-stew-hasCustomPragma
approach is ignoring ref/ptr types altogether and only focused to regular object/tuple.
The algorithm only use simple getType
+ getImpl
.
This approach make the code simpler. So how we expect ref/ptr to works? use a template:
template hasCustomPragma*(T: type, moreArgs): untyped =
when T is ref|ptr:
type TT = type(default(T)[])
hasCustomPragma(TT, moreArgs)
else:
hasCustomPragma(T, moreArgs)
But, this approach unfortunately doesn't work. Sym "objectName:ObjectType"
return nothing when you use getImpl
.
Using combination of getType + getTypeImpl + getTypeInst + getImpl
only make it worse and make it messier.
It also never reach the same usability compared to only use getType
+ getImpl
.
Proposed solution
If we getType
ref/ptr object, it will return synthetic symbol Sym "objectName:ObjectType"
as a part of it's AST.
Currently, getImpl
will return NilLit
on this symbol. As a user, I don't care much how the compiler internal works.
Putting an AST to that synthetic symbol may have no use to the compiler itself, but as a user, who care?
If this synthetic symbol can works with getImpl
, much of the problem mentioned above will be reduced.
Of course, we also can use dynamicBindSym
as a work around to relate the objectName
back to it's ref/ptr type.
But I prefer getImpl
approach.
Implementation
It only involves NimNode tree copy + add + assign. Not too hard I think.
When we use getImpl
on this symbol, it will return impl AST as if a regular object's symbol does.
Consequences
It will breaks some code. But I think very rare people depends on this NilLit
return value.
Benefits
- It not only works with ref/ptr object, it will make inheritance/climb up parent tree much simpler without become messier.
- Both
stdlib-hasCustomPragma
andnim-stew-hasCustomPragma
can be fused easier to get more power. - Improve it's usage within generic context,
hasCustomPragma
can accept various type declarations such as:
type
T = object/ref/ptr/tuple
TT1 = type(ref/ptr deref)
TT2 = type(variable of T)
TT3 = type(proc call return type)
aliasofT = T
aliasaliasofT = aliasofT
etc
Here is a related PR nim-lang/Nim#11526
getImpl
was never designed for this and only accidentically worked. I think it's not wise to use it for this.
and what is the wiser way to get pragmas from type/proc definition? currently, only getImpl able to return AST + pragmas. getType
family always omit pragmas.
The getType
family should return pragmas. Maybe we should add a flag to them to keep it.
something like proc getType*(n: NimNode, flags: GetTypeFlags = {KeepPragma}): NimNode
?
Exactly. The default should be not to include them though for compatibility.
I agree backward compatibility should not be compromised here. We can add more features to getType
family with this approach while retaining old behavior.
I think we reach consensus here.
This RFC is stale because it has been open for 1095 days with no activity. Contribute a fix or comment on the issue, or it will be closed in 7 days.