ThE FoURTh PASCAl
by JOSEph R. Chiko, AC CONTRibUTiNG AUThOR
by JOSEph R. Chiko, AC CONTRibUTiNG AUThOR
CLSN: PASCAL Passed Over
In Mark Miller's article "Advanced C Programming On The Atari 8-Bit" (AC, February and April '93), he mentioned that he knew of only three versions of Pascal. These included Atari, Kyan and Draper. He was less than complimentary when describing their capabilities and even went so far as to say they weren't much better than BASIC.
I'd like to point out that there is a newer, fourth Pascal language. It is CLSN Pascal. Perhaps after reading this article and you'll have a different opinion of capabilities of Pascal on the Atari 8-bit. I consider my experience a good example of what anyone can accomplish with this language. Since teaching myself Pascal with the aid of CLSN, I've authored more programs in the last two years on my old 130XE than I did in BASIC or TurboBASIC in the previous eight years.
A Few Caveats
Before we get into the specifics, I need to mention CLSN's limitations up front. First, the generated object code will only run on a 130XE. Second, since it's the first version, there are some minor-but not insurmountable- bugs in the compiler. C programmers will probably miss the LINKER, which CLSN doesn't use. In addition, CLSN generates machine language instead of p-code, so it doesn't require a separate run time file to execute your program. However, I consider the lack of the last two items an advantage, since this makes CLSN easier to use.
Under The Hood
With these pesky little quirks out of the way, let's get under the hood and check out the engineering of this great little compiler. The reason CLSN only runs on a 130XE is that the compiler, source code, variable name table, and the editor each occupy a 16K bank of memory. This frees main memory for the compiler's generated object code. If the CLSN built-in editor is too limiting, then the word processor or text editor of your choice can be used, provided that individual line lengths don't exceed 128 characters. You may have noticed that line numbers have not been mentioned. You notice I haven't mentioned line numbers? CLSN doesn't use them!
I prefer to use the CLSN editor since it allows me to switch between the compiler, the editor, and the generated object code without exiting to DOS, unless I over run the 4K stack or heap space. In the "live" environment, the stack and free list share 16K and the heap can occupy up to 48K. But during development the editor, heap, stack, and free list share a single 16K bank of memory.
CLSN isn't case sensitive, and identifiers can be 127 characters in length. Labels can be declared for the dreaded "GOTO" statement. CLSN recognizes CHAR, BOOLEAN, BYTE, SHORTINT, WORD, INTEGER, LONGINT, REAL, STRING, and POINTER types. ARRAYS can be multidimensional. SETS are supported as are RECORDS and FILES. In addition, variables can be redefined using the ABSOLUTE clause or defined as residing at a specific location in memory. CLSN also supports a rich set of operators including the DIV, MOD, SHL, SHR, and IN among the less well known.
CLSN Versus Machine Memory
Memory is the only factor limiting the number or type of parameters that can be passed to a procedure or function. Functions can return an ORDINAL, REAL, STRING, or POINTER type. Both procedures and functions can be declared as FORWARD. If the need arises, procedures can be called recursively. The CASE statement is supported and is claimed to be one of the fastest comparisons that CLSN can do. All expressions are completely evaluated (which I prefer), instead of taking the shortcut method. INLINE machine language can be incorporated into the code on those rare occasions where extra speed is needed. Though RECORD types are supported, the WITH statement of Standard Pascal isn't- but I've never missed it.
If the source code exceeds the 16K buffer, CLSN recognizes INCLUDE files. Though this increases compile time, it removes the limitation on the size of the source code file. The use of INCLUDE files can reduce development time, which more than compensates for the longer compile times.
The Docs
The CLSN manual is short but thorough. [Editor's comment: I'm not sure what Mr. Chiko's definition of "short" is. My Version 1.1 CLSN manual, purchased last year from B&C, runs 70 pages. Seemed pretty hefty to me. -BP] It contains a recommended reference reading list, which I found helpful. In addition to the CLSN compiler, several useful demonstration programs are also included. Unfortunately, CLSN is no longer being supported. However, perhaps with our encouragement and the distribution of software written with CLSN Pascal, the author can be enticed to support this fine piece of software once again.
A Taste Of CLSN
Earlier in this article I mentioned I had written a lot of software. Over the past couple years I wrote 20 games (mostly different versions of solitaire), 2 educational programs, 7 applications, and 3 miscellaneous utilities. Not to mention the dozens of different libraries to make coding easier.
I'm including with this article the most frequently used library in my collection to give you a taste of CLSN Pascal. This library controls all delays in all of my programs. I use this module to control the duration of pulsed tones, the length of time that a message is displayed on the screen, or how much time elapses before checking the joystick ports again. The parameter that is passed to the procedure is a real number representing the number of seconds that the pause should last.
CLSN Demo Delay Routine
(* PAUSE.ProcedureLiBrary *)
(* PAUSE for the length of time specified by the value of delay.
The maximum duration is 1092 seconds which is 18.2 minutes. *)
PROCEDURE lsm_pause( delay : real);
TYPE
clock = array[0..2] of byte;
CONST
jiffy = 59.92334;
VAR
rtclok : clock absolute 18; (* real time clock *)
_rtclok : clock; (* copy of the real time clock *)
delay_time,
elapsed_time : word;
BEGIN (* lsm_pause *)
(* set the real time clock to 0 *)
rtclok[0] := $00; rtclok[1] := $00; rtclok[2] : $00;
if delay > 0 then
Begin
(* translate delay in seconds to jiffies *)
delay_time := turnc(jiffy * delay);
elapsed_time := 0;
while delay_time > elapsed_time do
Begin
(* make a copy of the real time clock *)
_rtclok[1] := rtclok[1];
_rtclok[2] := rtclok[2];
(* calculate the number of jiffies *)
elapsed time := 256 * rtclok[1] + rtclok[2];
End;
End;
End; (* lsm_pause *)