#!/usr/bin/env rexx /** * The prolog code performs some simple tests for the different possibilities * to create an Enumeration * * a. Only symbols as key/index, where the ascending integer values/items will * be done by the Enumeration creation, starting at zero. * * b. Combination of keys with values, where the key/ndex can be an OORexx * string and the values/items can be any OORexx object, inclusive numbers. * * c. An array containing 2-item arrays where the 2-item arrays contain * the possible combination of the b. case, i.e array index 1 is a String, * array index 2 can be anything. * **/ level = .Enumeration~of(LOW,MEDIUM,HIGH,LEVELS) say '---- Automatic sequencing from 0 -----' say low '=' level[low] say 'There are' level['LEVELS'] 'levels' say medium '=' level[medium] say '----- Bitlevels -----' options = .Enumeration~of((BOLD,1),(ITALIC,2),(UNDERSCORE,4)) say bold'+'italic '=' options[bold]+options[italic] say '----- Strings -----' colours = .Enumeration~of((RED,'800000'),(GREEN, '008000'),(BLUE,'000080')) say blue '=' colours[blue] say red '=' colours~red say '----- Objects -----' objects = .Enumeration~of((OBJ1, .object~new), (OBJ2, .array~new), ('obj3', .table~new)) --say 'enum type =' objects~type say obj2 'is a' objects['oBj2']~class~id 'instance' say obj3 'is an instance of' objects~obj3 'class' say '----- 2-item Array -----' fonts = .array~of((ULTRALIGHT,100),(LIGHT,200),(MEDIUM, 500),(HEAVY,800), (ULTRAHEAVY,1000)) font = .Enumeration~of(fonts) say 'The font''s MEDIUM weight is:' font~medium exit ::OPTIONS NOPROLOG /** * Class: Enumeration * * An OORexx implementation of the well known ENUM's in other languages like C(++),C#, * Java etc.. * * ENUMs are normally compile time defined and unmutable and function as symbols * for constant values. For simple cases those values are ascending integers * starting at 0, that don't need to be specified. * For more complex situations both the key (in OORex terms: index) and the value * (in OORexx: items) are provided as a 2-item array in the argument array. * * One could think of this as a dynamic inplementation if the ::CONSTANT * directive, as it seems there is no provision for that in the built-in classes * * @version 0.8 * * @author Ruurd Idenburg (ruurd@idenburg.net) * * 2024-10-27 Changed '~class~id' to 'isA' * **/ ::CLASS Enumeration PUBLIC ::METHOD of PUBLIC CLASS -- get the enum arguments as an array if arg(1)~isA(.String) -- case a. above then do args = arg(1,'A') -- creation will generate the ascending integer sequence simple = .true end else do if arg(1)~isA(.Array) & arg(1)[1]~isA(.Array) then do -- case c. above args = arg(1) end else do -- case b. above args = arg(1,'A') end -- creation does not need the provide the values simple = .false end -- create the supporting table, caseless, as keys/indexes should be -- unique and case differences would make it error prone table = .caselessStringTable~new -- create an instance of this class me = self~new -- give access to the table for the instance me~enum = table -- preset the simpleness (one or two things per argument) -- simple = .false -- do we have a 2-item array per argument -- if args[1]~class~id='String' then simple=.true loop arg=1 to args~last -- if sparse item iterate the loop if \args~hasIndex(arg) then iterate if simple then do -- get key, set index of the key minus 1 as value key = args[arg] value = args~index(key)-1 end -- get key and value from the argument array else do key = args[arg][1] value = args[arg][2] end -- and store the map member table[key]= value end return me ::ATTRIBUTE enum PRIVATE ::METHOD '[]' use strict arg key return self~enum[key] /** * The next 3 methods forward the message to the embedded * caselessStringtable, that will return it's result' **/ ::METHOD items return self~enum~items ::METHOD allindexes return self~enum~allindexes ::METHOD allitems return self~enum~allitems /** * Method: unknown * * Allows to use the enum symbol to be used as a message * * @param string - the method name of the message * * @param array - an array with the original arguments * * @returns result - the result of the forwarded method * if valid method for the enum otherwise * raises a syntax error. **/ ::METHOD unknown PRIVATE use strict arg methodName, rest -- Make sure there is an index with the methodName if self~enum~hasIndex(methodName) then return self~enum[methodName~upper] -- if not raise a syntax error else raise syntax 97.001 array(self,methodName) exit ::REQUIRES 'caselessStringTable.cls'