Baja arrays
From
U. CraZy Diamond@VERT/TALAMASC/SPORT! to
All on Sat Jul 10 08: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