Because I am very interested in conditional compilation and could not wait till @Araq adds some more support to it.
I already tried (successful, yeah!) to implemented when in case/of statements (PR 2184). This only needed a change in semtypes because Araq had the idea and agreed to extend the language to support empty sets as way to skip a case/of.
While doing that I learned a bit about how to extend the compiler and suddenly this "beast" was a bit less fearful to me.
Next I wanted when support in enum and because I felt adventurous I started to implement that too (even if I think the conditional compilation could be done with a macro which generates the needed enums at compile time).
This is a lot more difficulty as it needs to be added to the parser first. The when evaluation is done on the AST and without telling the parser how to handle a when inside the enum definition you just get a error for that.
I peeked at how when is implemented for object and found that this is close to what I need but not identical. The idea is to add the when expressions together with the statements to the AST in the nkEnumTy.
Later when the enum is processed in semtypes.nim I want to handle the when branches in a similar way to the object type of when. This is what I plan at least.
So far I could manage to extend the parser (in a proof of concept quality) to create what I think should go into the AST.
import macros
dumpTree:
type num = enum
NUM_NONE = 0
NUM_ALL = 1+2
when defined(macosx): NUM_OSX = 10# else: NUM_WIN = 15 # only this differs for real
NUM_XTRA = 20
gives me
StmtList
TypeSection
TypeDef
Ident !"num"
Empty
EnumTy
Empty
EnumFieldDef
Ident !"NUM_NONE"
IntLit 0
EnumFieldDef
Ident !"NUM_ALL"
Infix
Ident !"+"
IntLit 1
IntLit 2
EnumFieldWhen # Here it is
ElifBranch
Call
Ident !"defined"
Ident !"macosx"
EnumFieldDef
Ident !"NUM_OSX"
IntLit 10 # until here
EnumFieldDef
Ident !"NUM_XTRA"
IntLit 20
Now for my main question: Should I create a new NodeKind or reuse an existing one?
So far added a new nodekind nkEnumFieldWhen right after nkEnumFieldDef and after some fiddling I also found that I need to add it too in macros.nim to support the dumpTree macro.
But I am unsure if this is what needs to be done. I could also reuse nkRecWhen which would not change the enum order of nodekinds.
I also don't know if something else needs to be extended. I saw "render.nim" using nkRecWhen but don't yet know what that is used for :)
I usually avoid adding new node kinds, so reuse 'nkRecWhen' please. (And while you are at it, please rename it to 'nkTypeWhen'.)
That said, when within an enum is a stupid idea. How can you write code for such an enum? That basically forces you to use when whenever you use the enum!
Why is when a stupid idea? Did you look at my examples?
It is already done and I made it work such that all code still compiles without changes and when can be used for conditional code creation if needed. See my PR from the last post.
I am going to rename nkRecWhen to nkTypeWhen and modify my implementation to use this instead of the new node kind I added.
Why is when a stupid idea?
For the reason I gave you: "That basically forces you to use when whenever you use the enum!"
Did you look at my examples?
Yes, and I saw no convincing examples. That some C code out there is coded like this doesn't make it a good idea.
It is already done and I made it work such that all code still compiles without changes and when can be used for conditional code creation if needed. See my PR from the last post.
Yeah but that only means it's harder to say no to this feature. ;-)
EDIT:
OK. I know what you mean about the "use when if you use the enum" :)
Basically the original example for this was defining enums which later are used in case blocks which use the same when. Thats why it's needed in the first place. The enums get defined "just when" and the case is used also "just when". The same goes for all code which uses the enum anywhere.
So yes: The enum can only be used with a when and for type / code safety this is exactly why I implemented the feature in the first place. So basically your reason to reject it was the reason to implement it :)
The alternative is to define enums which are not used on a platform and check at runtime that it is not used or .. use a when in the case anyway.
My main reason to create this feature was to create nice looking bindings for the nim-fuse project not some theoretical feature.
Besides that it does not even change anything in the AST for all existing code.
Other thread was: http://forum.nim-lang.org/t/867
P.S.: It may not be a feature you want to include. It just bugged me that I didn't understood at first why you reject it. I think there is a use case. Anyway, it was fun to get the compiler do what I want :)
The enum can only be used with a when and for type / code safety this is exactly why I implemented the feature in the first place. So basically your reason to reject it was the reason to implement it
Maybe, but allowing {} in a case branch is useful in general.