|
|
Label: ♦english
♦feature planning
fu
created at Sunday, 2010-10-24, 00:47:57
44 Replies, 6904 Hits
The basic idea is to extend the original enum syntax, and allow enum to be type with a set of field names and values:
With such enum type, it will eliminate the need to define some constants just for some function parameters, like stream.seek() , which can be redefined as:
seek( self :stream, pos :int, from : enum<begin,current,end> )=>int
So that only $begin , $current or $end can be passed as the from parameter to seek() . This can be guaranteed by the Dao typing system!Comments
And updated to the repository on dao.googlecode.com .
That's an interesting improvement! But I also propose to allow the following syntax:
enum E {a, b, c}
That seems very useful to me, as it could make code more clear in certain situation. Particularly when there are a lot of enums with simple symbol names. This would be "enum class" which (just by it's name) could provide information about it's metatype (field of usage, to say it simply). As "Font.courier" is somewhat better than "$font_courier", while just "$courier" may have quite ambiguous meaning (depending on context).
x = E.a;
A new crash-bug related to enums:
i: int = $a; #a grave mistake...
Found a serious bug: a variable of enum type cannot be properly compared with enum symbol at all:
x = $a;
if (x == $a) #false ... switch (x) { case $NOT_a: #true?! ... } if (x == x) #false again! ... if ($a == $a) #the same as above ...
And this seems like another defect:
routine p(x: enum<a, b>){}
p($c); #works fine though the argument should be incompatible
Nightwalker commented at Sunday, 2010-10-24, 16:29:42
Nightwalker modified at Sunday, 2010-10-24, 22:53:15
Finally, what is the purpose of old-style enums now?
enum {a, b, c}
x = a; #error 'Symbol not defined'
fu commented at Sunday, 2010-10-24, 22:49:46
I have thought about this too. For these problems you mentioned in your other comments, I began to realize that they haven't been properly handled just after committing, but I was too tired to fix them yesterday :(, I will fix them as soon as possible.
Nightwalker commented at Sunday, 2010-10-24, 23:10:35
fu commented at Monday, 2010-10-25, 01:31:04
Now fixed.
fu commented at Monday, 2010-10-25, 01:40:52
There are two reasons to bind integers to enum symbols:
fu commented at Monday, 2010-10-25, 01:49:31
Unnamed enum defined by enum {a, b, c} will no longer be supported, it has become useless.
Named enum syntax is needed, because there is a minor difference from defining an alias for enum<x,y,z> . That is enum syntax allows constant folding:
const C = 4
Constant folding is not possible in type names.enum EE { AA = C<<1, BB = C<<2 }
Nightwalker commented at Monday, 2010-10-25, 04:53:15
Nightwalker modified at Monday, 2010-10-25, 04:54:37
Alright, but mostly I mean this: why should enum symbols be explicitly assigned to integers in Dao code. Implicit numbering is enough to handle them easily on the API level, while I don't see a necessity to handle enums as numbers on the Dao script level. On this, higher level, they could be just symbolic literals -- it's simpler and nicer, I suppose. As all the examples you cited above matters for the internal level only, why again should this be explicit on the language level?
fu commented at Monday, 2010-10-25, 05:30:23
Maybe sometimes one needs to use enum to define bit flags or flags with specific values. And sometimes it is also good have direct mapping from the low level to the high level, if we want to interfacing well with C/C++.
Pompei2 commented at Monday, 2010-10-25, 06:29:02
Pompei2 modified at Monday, 2010-10-25, 06:38:46
I think this is a really, really good feature, allows us to make the API clear :) I also like it that we can just re-use a same name with no problem!
And that's why you really don't need "Font.courier" syntax: in loadFont($courier) and me.follow($courier) $courier can be two totally different things, but both make sense. As for not hiding the underlying integer, I am not decided. The only reason I see for showing it to the programmer is to make bitfields. And if one really wants to hide the integer, one could even add a "enum bit" or "bitfield" or whatever. But I have no opinion on this one.
Nightwalker commented at Monday, 2010-10-25, 20:25:00
Nightwalker modified at Monday, 2010-10-25, 20:26:11
What is this "operator to get field of enum type" mentioned in the recent enum-fixing revision? Is this a new syntax for something? As I don't have even a vague guess of how may such thing look like... :)
Nightwalker commented at Monday, 2010-10-25, 21:37:12
Nightwalker modified at Monday, 2010-10-25, 21:41:08
Apropos of bit flags: how can new enums represent compound values? One just cannot type "$a | $b" or "$a + $b" (while converting them to "int" is meaningless in this context); however, a list of enums may be used like a set of flags: "{$a, $b}".
fu commented at Monday, 2010-10-25, 21:41:07
Yeah, we can even redesign some of the existing API to take advantage of this new feature.
fu commented at Monday, 2010-10-25, 21:46:14
It's just what you mentioned in comment 410:
enum E{A,B}
x = E.A # or: x = E::A
fu commented at Monday, 2010-10-25, 21:49:52
Now these operations are not yet supported, but they can be supported easily. But currently I am trying to figure out if there is a convenient way to support flag set as enum, or simply add another type for this.
fu commented at Monday, 2010-10-25, 21:58:10
Another reason is that it is necessary to allow the bound integer to appear in type names. Suppose we have two enum types where the same names are bound with different integers, without the integers in their type names, it will be quite ambiguous if they are the same or actually different. Then if integers are allowed in the type names, it is natural to allow them in the enum syntax.
Nightwalker commented at Monday, 2010-10-25, 22:16:56
Hmm, I'm not sure about that syntax's consistency... Maybe something like "$E.A"? Then it would be obvious in any context that this refers to an enum.
fu commented at Monday, 2010-10-25, 23:51:05
Well, $X should be referring to a symbol only in standard context (in macro, it's for macro variables), E.A is just like accessing a class member, is less confusing than $E.A where one may wonder what exactly is $E here.
Pompei2 commented at Tuesday, 2010-10-26, 06:29:56
I think TheTrueNightWalker is right, instead of bitfields, one might just use a list of enums.
Also please keep in mind that one certainly will want to keep an enum in mind and use it later, something along the lines of this (untested):
class Display {
I did not try this, just want to draw your attention to this use case.ratio : enum<standard, wide> # ... routine update() { # someRoutine signature: routine<ratio : enum<standard,wide> => any> someRoutine(ratio); } } d = Display{wide}; d.update();
fu commented at Tuesday, 2010-10-26, 19:02:37
I am thinking to support another type for flags or bitfields, now what I am not sure is whether to add a new keyword flag or to twist the use of enum:
a : flag<AA,BB> = $AA
The problem with this way of using enum is that it doesn't look consistent with anything else in the language. But supporting this type is also quite beneficial (e.g. it can make some API simpler just as enum does). And it should be simpler and more efficient than use list of enums to do the same thing. I prefer to add the flag keyword, maybe I will do so.# or a : enum<AA|BB> = $AA a += $BB # add flag BB a -= $AA # remove flag AA a = $AA + $BB # both flags, like AA|BB in C if( $AA in a ) ...
Nightwalker commented at Tuesday, 2010-10-26, 22:50:11
Nightwalker modified at Tuesday, 2010-10-26, 22:51:36
There may be other alternatives, so it should be considered well before commit. And I do have certain idea: let's provide a set type! Perhaps, similar to this:
s: set<$a, $b, $c>; #it can hold only this enums as elements
It's not a concrete proposition, though, -- just a fantasy of mine :)s = {$a, $b}; #{actually, here would be something not ambiguous with other types; I just don't know what yet #} if ($a in s) ... s += $a; #$a wouldn't be duplicated, it's a set after all s -= $a; for (element in s) ... #What may seem even more interesting: set could support non-enums as well #And perhaps even filtering expressions! s3: enum<1 ... 10>; #a restricted range? s4: enum<"%a">; #a set of regex-filtered strings?
fu commented at Tuesday, 2010-10-26, 23:31:08
I think set type should be for real set. Here enum and flag are meant to be simple tiny types:), which don't do much on its own, but provided to make other things more convenient.
fu commented at Wednesday, 2010-10-27, 04:23:20
I will go with type form and syntax such as enum<AA;BB> and enum Flags{ AA; BB } for flags.
Pompei2 commented at Wednesday, 2010-10-27, 08:38:32
I do prefer the "flag" keyword, as it really makes it obvious what is being done, and what to use it for. I am already confused by all the different symbol syntaxes for map, hashmap, tuple, ... so that would confuse me even more :D
Nightwalker commented at Wednesday, 2010-10-27, 09:32:55
As for me, supporting "flag" seems somewhat redundant. Besides, it's name say nothing concrete about it's usage and may be even more confusing. I suppose if a new (formal) type is to be added, it should be used for something more than just multi-enums.
Nightwalker commented at Wednesday, 2010-10-27, 13:57:28
Nightwalker modified at Wednesday, 2010-10-27, 14:35:28
I've come up with another idea. We could support bit flags on top of existing bitarray type, as they are related by meaning:
bits: bitarray; #a usual bitarray
The advantages:
enums: bitarray<a, b, c>; #a fixed-size bitarray with 3 named bits enums = $a + $b; enums[$c] = 1; #setting a bit enums += $c; #the same as above if (enums[$c]) ... #checking a bit
fu commented at Wednesday, 2010-10-27, 20:09:13
Actually, bitarray is not a keyword, it's just a internally defined type name (like thread, mutex etc.). To use bitarray in this way, it will need to be treated as a new keyword. And also, it can not be used directly as flags in C level. Now I will implement the flag type first, and then decide what type name to use later:)
Nightwalker commented at Wednesday, 2010-10-27, 21:25:54
Nightwalker modified at Wednesday, 2010-10-27, 21:27:57
Yeah, though I didn't welcome new formal type before, I implicitly proved it's necessity in my previous post :) Regarding bitarray: I investigated it a little, and it appeared to be just an alias for "long" type, nothing more. Why then bitarray is supported as type at all?
fu commented at Wednesday, 2010-10-27, 22:57:50
The type object dao_array_bit is used to inform the VM to mark a long integer object as bit array, and handle it properly. This solution is not elegant, but is very convenient. It was created quickly when I was preparing a demo long time ago.
Maybe we can simply support bit array as 2-base long integer, and allow them to be created by:
bits = 101001110L2 # L2 for base 2
Similar to the use of L2 , one may also use:
# or: bits = 101001110B
b3 = 102001210L3 # L3 for base 3
The only problem is these suffixes do not seem to be very visible. Maybe 101001110LB2 or 101001110LX2 is better?b8 = 701005110L8 # L8 for base 8 b16 = 109001A10L16 # L16 for base 16
fu commented at Wednesday, 2010-10-27, 23:01:34
Or just 101001110X2 , so that there will be no problem to support up to 32 base numbers.
Nightwalker commented at Thursday, 2010-10-28, 08:20:28
Hmm, I'm not sure whether arbitrary base should be supported, but adding binary literals (and "long" hexadecimal ones, by the way) sounds good indeed. And it seems better for me to use "Ln" postfix for such things ("L2", "L16") which would indicate that it's "long", not "int".
Nightwalker commented at Saturday, 2010-10-30, 16:06:12
Nightwalker modified at Saturday, 2010-10-30, 16:39:15
So, as now we have enum with combinable flags, do we really need explicit number assignment to enum symbols? I think it may already be excluded from the syntax without any functionality losses.
flags: enum< {a, b} >; #or 'enum< (a, b) >', a usual combinable enum
Why do we need this? There are many cases where certain flags may be incompatible or just meaningless if being used together. Besides, it seems like a good solution for me to make the declaration of combinable enum more clear.flags2: enum < {a, b}, c >; #this means that the enum may contain a combination of 'a' and 'b', or only 'c' flags2 = $c; flags2 += $a; #error: incompatible symbols! flags2 = $a; #OK flags2 += $b; #OK flags3: enum< {a, b}, {c, d} >; #for incompatible sets of flags...
fu commented at Saturday, 2010-10-30, 21:35:26
I have thought about similar things of what you suggest here, but in a slightly different way, my idea was to allow enums from different groups to be combinable, instead of those from the same group in your case. I came up that idea when I was thinking about flags for text alignment, and the form of the enum could be enum<top,center,bottom;left,center,right> , so that top and left are combinable, but top and bottom are not. It seems difficult to do this according the your proposal. Anyway, in the end I gave up this idea, because it would be complicated to implement, and it wouldn't be as useful as we think.
Regarding explicit number assignment, again it is required mainly for interfacing C/C++ libraries (in particular, Qt).
Nightwalker commented at Sunday, 2010-10-31, 00:28:43
I may be totally wrong, but I see a very simple way of implementing such 'smart' combinable enums.
fu commented at Sunday, 2010-10-31, 03:21:17
You are not wrong. Your type of combinable enum is much easier to implement than mine, it is easier to allow symbols from the same group to be combinable than allow symbols from different groups to be combinable. But I am not yet convinced by its usefulness.
Nightwalker commented at Sunday, 2010-10-31, 08:33:46
Nightwalker modified at Sunday, 2010-10-31, 09:42:01
Hmm, I don't understand why your combinable enums are more difficult to implement... You just would need to check that all the bits are stored in the different fragments of value instead. Or to assign the numbers as enum<a = 1, b = 0x10000, c = 2, d = 0x20000, e = 4> -- then the checking would be the same as with my enum variant. Your example of alignment enum would just need to look slightly different: enum<left, right; top, bottom; center> .
Pompei2 commented at Tuesday, 2010-11-02, 14:12:05
I just hope your numbers (3 groups) are just for illustration. If such a feature would be implemented, it should be without any limit.
Nightwalker commented at Tuesday, 2010-11-02, 22:43:42
Yeah, 3 groups were just for the simplicity of illustration; however, if I understand the current implementation of enums right, combinable enum rely on single dint value field to store all the symbols it holds. Therefore, in order to support unlimited number of symbols, the very basis of the enum type would need to be reimplemented in more complicated way.
fu commented at Wednesday, 2010-11-03, 19:30:57
There is no simple equivalence between your idea and mine. And enum<left, right; top, bottom; center> isn't exactly equivalent to what I was talking about, for example, $left+$top+$center is a valid combination for this form of enum type, but it make no sense for text alignment, which requires only a combination of two symbols for horizontal and vertical alignment.
This kind of grouped symbols in enum type doesn't seem to be very useful.
Nightwalker commented at Wednesday, 2010-11-03, 23:08:44
Nightwalker modified at Thursday, 2010-11-04, 06:02:55
Alright, I have a possible solution to this issue as well. To support enum<left, right, center; top, bottom, center> , $center flag could be made a double-bit value. More precisely, enum symbol value could contain a separate bit per each group which has this symbol included. Thus we would have something like enum<left = 1, right = 0x100, top = 2, bottom = 0x200, center = 0x404> .
|
fu: Dao has finally become feature complete! After the recent implementation of communication channel for tasklets, deferred blocks and exception ... (May.18,05:46) fu: A new feature for concurrent programming: tasklet communication channels! I have been looking for ways to improve Dao's support for concurrent programming. The most recent imp ... (May.18,00:35) fu: Dao now supports Go-style panic/exception handling! I recently looked into the panic/ exception handling in the Go programming language (defer- recover), ... (May.07,02:04) deeproot: ... After doing a research, for now I have settled for haxe (rather haxe/ neko target) The most major ... (Apr.23,09:57) |