I noticed while looking at Oldes's implementation of modern cipher suites that he has a Mezzanine function for creating enums.
Examples
*FX-DX8: enum [
CHORUS
COMPRESSOR
DISTORTION
ECHO
FLANGER
GARGLE
I3DL2REVERB
PARAMEQ
REVERB
] "DX8 effect ID"
assert [object? *FX-DX8]
assert [0 = *FX-DX8/CHORUS]
assert [8 = *FX-DX8/REVERB]
assert [find [ECHO FLANGER] *FX-DX8/name 4]
*family: enum [
Alice: 1
Boban
Bolek
Lolek: #{FF}
Brian ; does Oldes have a sibling named Brian?
] 'Just-Some-Names
assert [object? *family]
assert ['Boban = *family/name 2]
assert ['Lolek = *family/name 255]
assert [not *family/name 13]
assert [256 = *family/Brian]
Observations
-
It follows the C convention that if you don't do a direct assignment (in this case via SET-WORD!) then plain WORD! will be incremented with each value.
-
The values start by default at 0, and not 1... matching C conventions and not Rebol's.
-
If you provide a value, it can be
[integer! | issue! | binary! | char!]... however the enum will be convertedto integer!for its value. (So there is a presumed endianness for BINARY!) -
You have to pass in a name as a second parameter which is used for debug messages.
Implementation
All enums are derived from a standard object. This object has a field title*, and methods assert (to check if a mapped-to value is in an enumeration) and name (which lets you do a reverse-lookup of an enum's name by its value).
system/standard/enum: object [
title*: none
assert: func[
"Checks if value exists as an enumeration. Throws error if not."
value [integer!]
][
unless find values-of self value [
cause-error 'Script 'invalid-value-for reduce [value title*]
]
true
]
name: func[
"Returns name of the emumeration by its value if value exists, else none."
value [integer!]
/local pos
][
all [
pos: find values-of self value
pick words-of self index? pos
]
]
;@@ add some other accessor functions?
]
enum itself is a function that uses PARSE on the specification to make the object:
enum: function [
"Creates enumeration object from given specification"
spec [block!] "Specification with names and values."
title [string! word!] "Enumeration name"
][
enum-value: 0
spec: copy spec
parse spec [any [
pos: word! insert enum-value (
change pos to set-word! pos/1
enum-value: enum-value + 1
)
| some set-word! pos: [
integer! | issue! | binary! | char!
] (
if error? try [
enum-value: to integer! pos/1
pos: change pos enum-value
enum-value: enum-value + 1
][
cause-error 'Script 'invalid-data reduce [pos]
]
) :pos
| pos: 1 skip (
cause-error 'Script 'invalid-data reduce [pos]
)
]
]
enum: make system/standard/enum spec
enum/title*: title
enum
]