Jump to content
  • entries
    28
  • comments
    28
  • views
    21,062

A/Rexx PoC: using a compound variable as both associative and indexed


OLD CS1

1,426 views

blog-0096836001439448432.png

Actually, I am not really certain what to call what I am doing here. Essentially, I need a table of values which can be referenced both by number (ordinal) and the value itself (associative.)

 

I reach back to the TI-99 ISR (interrupt service routine) sound lists for a practical example. I want to create a transform which will increase or decrease tone values by semitones or octaves (12 semitones.) To do that, I have to load the channel sound command, which consists of two bytes, from the list. Some manipulation has to be done to convert it from (for example) >8C1F to >01FC, A-1 on channel 1, but that is another exercise.

 

Now I have my tone value. Say I want to increase this by an octave to A-2, >00FE. While I know an octave is 12 steps, I have no way of knowing that >00FE is 12 steps away from >01FC unless I have it in an indexed table in which I can count the 12 steps to find the value. But I also need to know at what index the initial value resides. I have not used a language with associative arrays which can actually produce an index as the elements are usually stored as some kind of hash. You can step through all of the elements, but not in any useful order.

 

To accomplish this I only need one variable but two ways of storing information. The first will convert a given value to an index, and the second which can then convert an index to a value.

 

In the example below I am doing this, as well as something else I consider neat. I am actually storing the list of values I need indexed in the script I am running as a long comment. Sure I could have dome some kind of Fu to get a long monotonous list of assignments (in this case 150,) but this method allows me an easy (and did I mention neat?) way to build the stem variable at run-time and more simply maintenance the table.

 

The script scans through itself looking for its table values. In this case I am indicating a wanted value with the ">", which is the hexadecimal notation prefix in 9900 assembler. As the routine takes in values it increments the index variable. Each value is stored in two ways using the same stem: the index is stored as an associative leaf, then the value is stored with the index as its leaf. TONE.0 is used to store the length of the table for walking.

 

Thus, the script is

 

TONE.value = index

TONE.index = value

 

If value is 01FC and index is 13, A/Rexx executes this:

 

TONE.01FC = 13

TONE.13 = 01FC

 

Remember, I want to increase this tone by an octave which is 12 semitones. Because I know the value I can now find the index. The new index is 25, and TONE.25 gives 00FE. Done!

 

I can use this one stem variable to work in both up and down directions, as well as between index and value, for whatever purpose.

 

In the script below, the table is read from the comments at the end of the file. To save time in longer scripts I also facilitate a termination value to stop reading the file any further once the end of the table is read. For some reason i was unable to get BREAK within the DO loop to work in Regina Rexx and I did not try it in ARexx, though the script does otherwise work in ARexx if you comment out or remove the OPTIONS line. As well, since the script was created in Windows it contains carriage-returns at the end of lines, so I had to PARSE that out. If the build routine is fed a file which lacks carriage-returns, the last character of the pattern simply does not get matched and it still executes as expected.

 

Once the table is read into the stem variable, it is then walked and output to the screen, thus proving its might.

 

/* tone_value_table.rexx   This will read a table within its own script into   a stem variable and a related stem holding index   information.  */OPTIONS AREXX_BIFS AREXX_SEMANTICSparse source . . myselfif ~open('input_file', myself, 'r') then exit 30index = 0do until eof('input_file') | value == '@'  /* couldn't get BREAK to work in the loop */   inline = readln('input_file')   if substr(inline,1,1)~='>' then iterate   parse var inline '>' value '0d'x   if value ~= '@' then do      index = index + 1      TONE.value = index      TONE.index = value      endendcall close 'input_file'TONE.0 = indexdo index = 1 to tone.0   sound = tone.index   say 'Tone # ' || index || ' is ' || sound 'and this tone value is index ' || tone.soundendexit/*   TMS-9919 tone value table>03F9>03C0>038A>0357>0327>02FA>02CF>02A7>0281>025D>023B>021B>01FC>01E0>01C5>01AC>0194>017D>0168>0153>0140>012E>011D>010D>00FE>00F0>00E2>00D6>00CA>00BE>00B4>00AA>00A0>0097>008F>0087>007F>0078>0071>006B>0065>005F>005A>0055>0050>004C>0047>0043>0040>003C>0039>0035>0032>0030>002D>002A>0028>0026>0024>0022>0020>001E>001C>001B>0019>0018>0016>0015>0014# Editor assembler manual ends here>0013>0012>0011>0010>000F>000E>@*/

 

 

 

This routine could be adapted to handle more than a single table in a file. For that matter each table could be stored in separate files, but storing the table or tables in the executing script just makes less clutter in the file system. Plus it is kind-of neat.

 

For my purpose, and ease of constructing the two sound channel command bytes, I can and most likely will change the order of the nibbles in the table. Done this way, building the sound channel command is a simple BITOR() instead of a more involved process of swapping nibbles around in the script.

 

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...