Baja arrays
From
U. CraZy Diamond@VERT/TALAMASC/SPORT! to
All on Sat Jul 10 12:12:00 1999
Okay, folks, here it is!ãDid some digging and came up with this post from yesteryear FYI:ãããSubj : Baja Arrays?ãTo : AllãFrom : Angus McLeod (VERT/ANJO)ãDate : Mon Dec 02 1996 01:57 am ASTããUntil DM comes out of hibernation, we are stuck with Sync's PCMSã(Programmable Command & Menu System) at it's present state of theãart, and have to live with the fact that improvements (like arrays)ãare simply not possible until then. Right?ããWell... maybe!ããNotice I spoke of the PCMS and _didn't_ say "Baja". Baja is aãprogramming language which is compiled by the BAJA.EXE compilerãinto a Synchronet .BINary file. In fact, it's closer to anãassembler than a compiler. The point being, there is nothing toãprevent some _other_ compiler being written for a totally differentãlanguage, like PL/S (Programming Language/Smeg). PL/S can be asãsophisticated as we like. So long as the PL/S compiler generatesãvalid .BIN files, then the PL/S programs will run.ããPL/S might easily parse statements like:ãã offset = ((rec_no - 1) * rec_size) + field_offsetããand translate this to:ãã opy offset rec_noã sub offset 1ã mul offset rec_sizeã add offset field_offsetããor more correctly, direct into the corresponding binary and writtenãstraight to the .BIN file. Nothing wonderful about this - compilersãhave been doing this since Backus gave us FORTRAN in 1956.ããWhat about:ãã function My_Func ( str local_str ) returns intã local_int resultã ...ã return resultã end_functionãã ...ãã result = My_Func ( some_str )ããbeing translated to:ãã # declare functionã goto skip.My_Funcã :My_Funcã # declare arguments, return value and localsã str My_Func.local_strã int My_Func.result My_Func.return_valã # do whateverã ...ã # returnã copy My_Func.return_val My_Func.resultã returnã :skip.My_Funcãã ...ãã # call function, copying arguments in and return value outã copy My_Func.local_str some_strã call My_Funcã copy result My_Func.return_alããA compiler that would allow the first notation instead of forcing usãto use the second would be some considerable convenience.ããBut so far, our proposed PL/S compiler gives us only the notationalãconveniences of expressing calculations in infix notation, orãcleaning up function definition and call. But that does not actuallyãgive us the power to do anything new! So what about those arrays?ããWell suppose the PL/S compiler interprets:ãã int My_Array[10]ããto mean:ãã int My_Array.1 My_Array.2 My_Array.3 ... My_Array.10ãã(which Baja will compile for us today) and generates tenãappropriately named integer variables for us. That looks like a goodãstart. But how would we actually ACCESS a particular variable at RUN-ãTIME? If the indexes were known at compile-time it would be easy, butãwe want to access the array with indexes that are not known until run-ãtime.ããSuppose it were possible, even if it were very ugly, then we would beãin the home stretch. Because our PL/Scompiler would hide the uglinessãfrom us.ããPlease observe the following code, which I hope is simple enough to beãself-explanatory:ãã ------[TSTARRAY.SRC]------------ã # declare Pseudo-"array" and cursor variableã global_int Array.1 Array.2 Array.3 Cursorãã # declare loop counterã int loopãã # stuff some data into our "array"ã set Array.1 10101ã set Array.2 22002ã set Array.3 30033ãã # access each element by NAMEã set loop 1ã :next_elementã # the next two lines are the ugly ones!ã sprintf str "Cursor Array.%ld" loopã exec *getintã # we now have the array element value in the cursor!ã printf "the value of Array.%ld = %ld\r\n" loop Cursorãã add loop 1ã compare loop 3ã if_less_or_equalã goto next_elementã end_ifãã # wait for a screen-captureã pauseã --------------------------------ããObserve that the array has been declared as GLOBAL, as has theã"cursor variable used to access the values in this array. If we wereãusing PL/S, it might declare our cursor variable(s) behind the scenesãfor us, concealing from us the very necessity for a cursor variable.ããAlso observe the two key lines here, the SPRINTF which specifies theãdestination and source variables _by name_ and the EXEC which calls aãMagic Module. And here is the output captured from my screen:ãã þ Main þ 0:02:04 [4] DOVE-Net [13] Sync Programming: ;EXEC *TSTARRAYã the value of Array.1 = 10101ã the value of Array.2 = 22002ã the value of Array.3 = 30033ã [Hit a key] ÀããObviously, we have been able to access the values in the arrayãelements! Writing to these elements would require only the reversal ofãthe order of the variable names in the SPRINTF statement. Note thatãPL/S could have coded our "getint" module as a subroutine at the end ofãour TSTARRAY program or even embedded the code inline.ããHere for the strong-of-stomach is the nasty, nasty, Magic Module:ãã ------[GTINT.SRC]------------ã !include FILE_IO.INCãã # declare some variablesã int argc dest32 source32 handle glob_int glob_str copy_intã str tmp dest sourceãã # define some BAJA op-codesã set glob_int 3711ã set glob_str 3455ã set copy_int 9343ãã # set name of source and destinationã # variables to null-stringsã set source ""ã set dest ""ãã # extract variable names from command stringã # (stolen piece-meal from QNET.SRC)ã set argc 0ã :process_argsã compare_str ""ã if_trueã goto end_argsã end_ifã sprintf tmp "%.1s" strã shift_str 1ã compare tmp " "ã if_trueã add argc 1ã goto process_argsã end_ifã switch argcã case 0ã strcat dest tmpã end_caseã case 1ã strcat source tmpã end_caseã defaultã goto end_argsã end_switchã goto process_argsã :end_argsãã # THIS is the interesting part! # make uppercase and find out the CRC32 of variablesã strupr sourceã crc32 source32 sourceã strupr destã crc32 dest32 destãã #open .BIN file for writingã fopen handle O_WRONLY+O_CREAT+O_TRUNC "%!otf%#.bin"ã if_trueã fwrite handle glob_int 2ã fwrite handle source32 4ã fwrite handle glob_int 2ã fwrite handle dest32 4ã fwrite handle copy_int 2ã fwrite handle dest32 4ã fwrite handle source32 4ã fflush handleã fclose handleã exec_bin "otf%#"ã end_ifã ------------------------------ããWhat this module basically does is create a .BIN file on-the-fly andãthen immediately execute it. It will copy an GLOBAL_INT to any otherãGLOBAL_INT but it does so _by name_ allowing the name to change at run-ãtime thus giving access to "array" elements. Notice that a large partãof this would not be needed if we placed the code as a subroutine inãour main module or embedded the relevant parts "inline" ince we wouldãnot have to parse the variable names.ããThe BAJA program we create on the fly is the following two-liner:ãã global_int <source_name> <dest_name>ã copy <dest_name> <source_name>ããbut it is created directly as a .BIN file (no source ever exists).ãFor string elements, only a minor change us needed. Yes, I know it'sãugly, and slow and 'orrible, but it's interesting.ããSo, Smeg! Get to work on PL/S right away! Or we'll change the nameãto Programming Language/Synchronet... :)ããSeriously, I am interested in any comments on the academic or practicalãaspects of developing a new language translator as a replacement forãthe venerable BAJA compiler. The objective of any such efforts beingãto make programming for Synchronet easier, by means of notationalãconveniences not available in BAJA, and if/when possible, by theãintroduction of new features.ãã+---ã þ Synchronet þ The ANJO BBS þ Barbados þ (246) 435-2235ãããã ...and in a nutshell, that's it. :)ããã---ã þ Synchronet þ °±² The Serial Port ²±° ¯807ù547ù2134ã