Re: enum options
- Posted by CChris Jul 18, 2008
- 877 views
There is a little known include file in win32lib that is called series.e. It implements all of the above and more. Why not simply make it a standard include? No need to ask for a permission.
Doing this would make a difference between builtin enums as were implemented and series. But I don't think it would be terribly difficult to put this code inside the interpreter proper. ?ot in 4.0 alpha, there is some urgency to release something. And there are issues to blend the syntax into known enums. I had tried to push for named enums, but....
How about this?
enum [ ( [from start_value] [to end_value] [by additive_value] | [grow multiply_factor] | [using routine_id] [label "fields"] ) ] foo, bar, ...
The brackets only show optional components, and are not to be written.
The parentheses mark the limits of the option list as opposed to the member list. I'd have nothing against using { } instead. Just some pair of delimiters currently not expected after enum.
In keeping with other labels currently in the language, the enum identifier is a string. However, contrary to current other labels, it may need to hold a valid identifier so as to be able to query properties of the enum. This restriction could be removed if we implement the query as enum_meta("fields", ENUM_FROM). You get the idea.
CChris
Is your grow clause for using for flags we see so often in C interfaces where you can specify values by combining constants with binary or?
Yes, and the permission example you give later is simply correct.
I don't think label is consistent with the usage in the rest of the language though. Enum isn't flow control. An enum is a special type. Is "fields" the name of the set of constants?
enum is a for loop with a twist applied to generating constants. In another language, you could say %FOR %I=1 %TO 4;%DO; %LET IDENT=names[&I]; &IDENT = &I,; %END; the last trailing comma needing extra care, left out.
That's why I think presenting an enum as as close as possible as a for loop makes sense. So it can have a label, which is the name of the enum. And if you want to query the properties of an enum, you need a name for it. I find the latter obvious, but some other people never got it.
Now, "using routine_id". Could you explain what this means?
Use a custom function to define what the next value in the enum is. Adding a constant or multiplying by a constant are frequent cases, but you can use a generic iterator. The latter takes current value and returns next value.
function next_value(integer p) return p*p end function
enum (using routine_id(next_value")) three = 3, three_squared, 9 three_power_4, 81 three_power_8, 6561 unrelated_constant = 123
Admittedly, the "from" clause could be removed, I left it in for the purpose of uniform coding. Everything in the ( ) is optional. Overriding with an explicit = is still possible. You can always insert values that didn't fit in the pattern at the end. The "to" part may not be needed either - I'm less sure of this.
The above would be implemented as
constant three = 3, three_squared = call_func(rid,{three}), three_power_4 = call_func(rid, {three_squared}), -- ...
I would go with an example:
type enum linux_mem_access_type from 1 to 8 grow 2 -- check the C docs before using this. :) READ, WRITE, EXEC, NONE = 0 end type
Now the above would not only define the constants but also the type,
I think one of the meta properties of an enum could be the whole set of values it takes, so this syntax would not be necessary.
if find(something,enum_meta("permissions", META_LIST)) then -- ok
assuming you used a label "permissions" clause.
Look at this header: procedure mem_linux_reprotect( atom addr, linux_mem_access_type pr )
Now pr is a new protection for linux_mem_access and the interpreter make sure that pr is some combination of READ, WRITE, EXEC or 0. Essentialy the procedural defniition of linux_mem_access_type() is:
return pr&(READ|WRITE|EXEC) == pr
more generally it would be
type enum typename [ ( [from start_value] [to end_value] [by additive_value] | [grow multiply_factor] | [using routine_id] ) ] foo, bar, ... end type
Why not use what we have?
type permissions_mask(atom x) return x = and_bits(x, or_all(enum_meta("permissions",META_LIST))) end type
Ok, or_all() is not yet in std/math.e, but should be there.
Finally, Often it would be useful but it nearly is always absent for the user, I.E. the programmer, to either through a bug report or on the screen to see the identifier's name rather than the numeric value. An option to include that would be useful for debugging purposes. This is normally done in C by using the macro processor
Shawn Pringle
This means that x = EXEC wouldn't simply store 4 in x, but store something like {"permissions","EXEC",4}, in an adequate way?
Looks good at a glance. trace() could show EXEC instead of 4. Dealing with Windows messages would be so much easier. Nice.
What should trace(1) display after x = or_bits(x, READ)? I think it will be hopelessly outsmarted if asked to obviously answer READ | EXEC.
I don't know what trace() should do if the enum had no name?
This may not be impossible, butlooks very, very tricky.
CChris