Re: enum options

new topic     » goto parent     » topic index » view thread      » older message » newer message
Shawn Pringle said...
CChris said...

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.

Shawn Pringle said...

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.

Shawn Pringle said...

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}), 
-- ... 
Shawn Pringle said...

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.

Shawn Pringle said...

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.

Shawn Pringle said...

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

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu