1: #!/usr/bin/env rexx
2: /**
3: * The prolog code performs some simple tests for the different possibilities
4: * to create an Enumeration
5: *
6: * a. Only symbols as key/index, where the ascending integer values/items will
7: * be done by the Enumeration creation, starting at zero.
8: *
9: * b. Combination of keys with values, where the key/ndex can be an OORexx
10: * string and the values/items can be any OORexx object, inclusive numbers.
11: *
12: * c. An array containing 2-item arrays where the 2-item arrays contain
13: * the possible combination of the b. case, i.e array index 1 is a String,
14: * array index 2 can be anything.
15: *
16: **/
17: level = .Enumeration~of(LOW,MEDIUM,HIGH,LEVELS)
18: say '---- Automatic sequencing from 0 -----'
19: say low '=' level[low]
20: say 'There are' level['LEVELS'] 'levels'
21: say medium '=' level[medium]
22: say '----- Bitlevels -----'
23: options = .Enumeration~of((BOLD,1),(ITALIC,2),(UNDERSCORE,4))
24: say bold'+'italic '=' options[bold]+options[italic]
25: say '----- Strings -----'
26: colours = .Enumeration~of((RED,'800000'),(GREEN, '008000'),(BLUE,'000080'))
27: say blue '=' colours[blue]
28: say red '=' colours~red
29: say '----- Objects -----'
30: objects = .Enumeration~of((OBJ1, .object~new), (OBJ2, .array~new), ('obj3', .table~new))
31: --say 'enum type =' objects~type
32: say obj2 'is a' objects['oBj2']~class~id 'instance'
33: say obj3 'is an instance of' objects~obj3 'class'
34: say '----- 2-item Array -----'
35: fonts = .array~of((ULTRALIGHT,100),(LIGHT,200),(MEDIUM, 500),(HEAVY,800), (ULTRAHEAVY,1000))
36: font = .Enumeration~of(fonts)
37: say 'The font''s MEDIUM weight is:' font~medium
38:
39: exit
40:
41: ::OPTIONS NOPROLOG
42:
43: /**
44: * Class: Enumeration
45: *
46: * An OORexx implementation of the well known ENUM's in other languages like C(++),C#,
47: * Java etc..
48: *
49: * ENUMs are normally compile time defined and unmutable and function as symbols
50: * for constant values. For simple cases those values are ascending integers
51: * starting at 0, that don't need to be specified.
52: * For more complex situations both the key (in OORex terms: index) and the value
53: * (in OORexx: items) are provided as a 2-item array in the argument array.
54: *
55: * One could think of this as a dynamic inplementation if the ::CONSTANT
56: * directive, as it seems there is no provision for that in the built-in classes
57: *
58: * @version 0.8
59: *
60: * @author Ruurd Idenburg (ruurd@idenburg.net)
61: *
62: * 2024-10-27 Changed '~class~id' to 'isA'
63: *
64: **/
65: ::CLASS Enumeration PUBLIC
66:
67: ::METHOD of PUBLIC CLASS
68: -- get the enum arguments as an array
69: if arg(1)~isA(.String)
70: -- case a. above
71: then do
72: args = arg(1,'A')
73: -- creation will generate the ascending integer sequence
74: simple = .true
75: end
76: else do
77: if arg(1)~isA(.Array) & arg(1)[1]~isA(.Array) then do
78: -- case c. above
79: args = arg(1)
80: end
81: else do
82: -- case b. above
83: args = arg(1,'A')
84: end
85: -- creation does not need the provide the values
86: simple = .false
87: end
88: -- create the supporting table, caseless, as keys/indexes should be
89: -- unique and case differences would make it error prone
90: table = .caselessStringTable~new
91: -- create an instance of this class
92: me = self~new
93: -- give access to the table for the instance
94: me~enum = table
95: -- preset the simpleness (one or two things per argument)
96: -- simple = .false
97: -- do we have a 2-item array per argument
98: -- if args[1]~class~id='String' then simple=.true
99: loop arg=1 to args~last
100: -- if sparse item iterate the loop
101: if \args~hasIndex(arg) then iterate
102: if simple then do
103: -- get key, set index of the key minus 1 as value
104: key = args[arg]
105: value = args~index(key)-1
106: end
107: -- get key and value from the argument array
108: else do
109: key = args[arg][1]
110: value = args[arg][2]
111: end
112: -- and store the map member
113: table[key]= value
114: end
115: return me
116:
117: ::ATTRIBUTE enum PRIVATE
118:
119: ::METHOD '[]'
120: use strict arg key
121: return self~enum[key]
122:
123: /**
124: * The next 3 methods forward the message to the embedded
125: * caselessStringtable, that will return it's result'
126: **/
127: ::METHOD items
128: return self~enum~items
129:
130: ::METHOD allindexes
131: return self~enum~allindexes
132:
133: ::METHOD allitems
134: return self~enum~allitems
135:
136: /**
137: * Method: unknown
138: *
139: * Allows to use the enum symbol to be used as a message
140: *
141: * @param string - the method name of the message
142: *
143: * @param array - an array with the original arguments
144: *
145: * @returns result - the result of the forwarded method
146: * if valid method for the enum otherwise
147: * raises a syntax error.
148: **/
149: ::METHOD unknown PRIVATE
150: use strict arg methodName, rest
151: -- Make sure there is an index with the methodName
152: if self~enum~hasIndex(methodName)
153: then return self~enum[methodName~upper]
154: -- if not raise a syntax error
155: else raise syntax 97.001 array(self,methodName)
156: exit
157:
158: ::REQUIRES 'caselessStringTable.cls'