BASIC Wars 2
|Column Tag:||BASIC School
BASIC Wars the Sequel!
By Dave Kelly, MacTutor Editorial Board, General Dynamics Corp.
This episode of BASIC Wars finds us looking at the newly released Microsoft Basic Compiler (version 1.0) and MS Basic Interpreter (version 3.0). In the first episode several months back we were introduced to several of the newcomers to Basic programming on the Macintosh. I refer you to the August 1986 MacTutor Basic column entitled "And then came Basic Wars!" for an introduction to ZBasic, True Basic, and PCMacBasic. Of these three, ZBasic now appears to be leading the race. If you have been following the Basic Wars Saga, you know of the major improvements in the reliability of ZBasic. It has come a long ways from the frequent bombs to the fairly reliable product we see now. Finally after a long wait (and some pressure from competition like ZBasic) Microsoft has recently released version 3.0 of the MS Basic Interpreter and version 1.0 of the new Microsoft Basic Compiler.
BASIC 3.0 Improvements
Before the battle begins, we should discuss the MS Basic Interpreter, version 3.0. By now most of you have heard about the improvements that have been made and registered owners have had a chance to upgrade for $25 (Well worth $25, I might add). MS Basic Interpreter is still a very reliable product just as before with major enhancements (i.e. value added). To begin, here is a brief overview of some of the new features:
First and very importantly, Microsoft has now bundled the CLR ToolLib Library with the interpreter. This alone is worth the $25 to upgrade from earlier versions, especially if you didn't already have CLR ToolLib. There are some new and improved toolbox calls included which were not in the original CLR ToolLib. Among those that were added to the original CLR ToolLib are:
BringToFront CmdKey DisposeDialog GetDialogBut GetDialogText
GetMouse GetNewDialog ModalDialog PtInRects RealFont
SetArray SetCreate SetDialogBut SetDialogText SetItemStyle
SetOrigin SetWindowPic SetWTitle SubPt
The list above is fairly complete unless I missed adding something to the list. One great advantage is that now the library calls provided will be more widely used. Previously only those who puchased the CLR Libraries could take advantage of them. This limited the type of programs which could be widely distributed to those that could be written without CLR Libraries. I expect that we will be seeing more widespread use of the Libraries now that they are part of the interpreter package. (NOTE: ZBasic claims to have more Toolbox calls available, but some if not most of them are still not compatible with other ZBasic calls. Example: INSERTRESMENU is not compatible with ZBasic MENU statement. However, INSERTRESMENU is not available with the MS Basic Libraries. Maybe CLR will write some more for us!! The MS ToolLib routines are compatible with all MS Basic commands).
Fig. 1 MS Compiler Options Dialog
The long awaited HFS incompatibility has been corrected with version 3.0. The FILES$ statement now returns the full pathname for HFS files (MFS is not changed). In version 2.x the FILES$ statement would only return the full pathname for a file in the root directory. This problem has been corrected with version 3.0. A new Basic statement has been added - CHDIR. CHDIR changes the current default directory to one specified with the statement. Using CHDIR is similar to setting the PREFIX command in ProDos on the Apple ][ series computers or using 'cd' on a UNIX operating system. (NOTE: no equivalent in ZBasic). Also notice that since the Scrapbook DA uses the default disk, the Scrapbook file that can be accessed will change when the CHDIR statement is used. Problems with single voice sound and the new ROM's has been fixed with version 3.0.
Now up to six windows can be opened at the same time. Older versions of the interpreter only allowed 4 windows open. (Note: ZBasic also allows up to six windows open). WINDOW(6) now returns the handle for the active edit field in the current output window. WINDOW(6) returns zero if the window has no active edit field. This function is useful with some toolbox functions.
The EDIT FIELD statement has been enhanced to include the type values 5,6,7 and 8. These types correspond to the types 1,2,3 and 4 except that the default text in the EDIT FIELD is not highlighted. This will be useful in programming a text editor application ( read on for more statements to make this possible).
Multi-line IF/THEN/ELSE statements are now allowed. Use of multi-line IF/THEN/ELSE improves readability of your program and fewer program lines are required in many cases. For better program structure, the multi-line IF/THEN/ELSE statement makes it easier to avoid the use of GOTO (a no-no if you are following good programming techniques). ZBasic provides multi-line IF/THEN/ELSE via use of the LONG IF/XELSE statement. MS Basic 3.0 uses the following IF/THEN/ELSE structure:
IF condition THEN
statement[statement ] :
ELSEIF condition THEN
statement[statement ] :
statement[statement ] :
While ZBasic multi-line IF/THEN/ELSE statements are functionally the same as the MS Basic implementation, it should be noted that the MS Basic syntax follows a more traditional implementation (as done in other languages). The MS Basic implementation is compatible with the ANSI (American National Standards Institute) Basic implementation.
The new function SADD returns the address of the first byte of data in a string expression. This will typically be used to pass the address of a string to a machine-language routine. [Since the first byte of a Macintosh Pascal string is the length byte, getting to the first character is a bit of a pain. This function is a nice addition. -Ed.]
Improvements have been made to Apple LaserWriter and LaserWriter Plus support. Printer support was lacking in previous versions of MS Basic. I have not verified exactly what improvements have been made. I will reserve that subject for a future issue of MacTutor.
The Basic runtime interpreter package is now bundled with the full interpreter for distributing your programs to others that don't have the interpreter without paying any runtime fees or licenses. The interpreter routines are the same, but the runtime package has no editor and no way to change your program.
Other than what I have just mentioned, there are no other documented changes. It is apparent that there are some improvements that are not documented. One such improvement is found in an example named 'DOUBLE CLICK ME' on the MS Basic disk 1 (there are two disks now, one for Basic and one for the ToolLib stuff). It is also found in a program named 'QnD' on the compiler Toolbox disk. 'QnD' stands for 'Quick and Dirty'. MS has provided us with a quick and dirty editor program written in Basic. Until now a text editor could not be written with either MS Basic or ZBasic. Several new statements show up in boldface in the program:
Also found on the MS Basic Interpreter disk in a demo file also named 'DOUBLE CLICK ME':
Since these statements are in boldface it follows that they are a part of the reserved words built into Basic. It is exciting to find out that they exist because they fill a void. Text editing has been limited in Basic. At the present time I don't have any information on the proper use of these statements, but Microsoft has promised to send me information which I can pass on to you. I suggest that if you want to try to use them before you have documentation that you do so with caution. I will bring you more information on how to use these statements in a future issue as soon as I can get the information from Microsoft on them. (NOTE: these are also supported by the MS Compiler too!).
MS Basic Compiler Unveiled
Finally after months of rumors the MS Basic Compiler has been officially released. Of the compiled basic products now available this one is number one for compatibility with the MS Basic interpreter. There are a few small modifications that may be needed in some programs, but most programs will not require any modification. Compiled programs will likely run up to 10 times faster than the interpreter. Note how similar the options dialog in fig. 1 is to MacFortran. This is because Absoft wrote the compiler. We may find many more similarities between these two compilers in time. The additions and enhancements to the interpreter version 3.0 are all supported by the compiler including the Toolbox libraries. The same CLR ToolLib which is included with the interpreter is also included with the compiler. It should be noted here that any other libraries from CLR or others you may have written for the interpreter are supported equally well by the compiler. The compiler does not support calls to routines written in other languages unless they follow the guidelines setup in "Building Machine Language Libraries". There are a few differences in the BASIC language provided by the interpreter and the compiler. One additional statement (not supported by the interpreter) is the SELECT CASE construct. SELECT CASE is a useful statement which is supported by the ANSI (American National Standards Institute) standard for Basic (also supported by True Basic and many other languages).
With the compiler you may declare your arrays to be static or dynamic. Dynamic arrays can be erased and redimensioned during runtime. Static arrays are set up at compile time and cannot be redimensioned during runtime. All definitions of functions and declaration of variables should appear at the beginning (or close to the beginning) of your compiled program. For example if a function defined by using a GOSUB at the beginning of your program and the subroutine with the function definition appears sequentially later in the program than the first line where the function is called, the compiled program will not work properly. The solution is to define the function and dimension arrays early in the program and avoid setting up functions and dimensions in subroutines.
Compiled subprograms may be called recursively. This allows subprograms to call themselves. Programs written for the MS Basic interpreter will not work recursively. An example is the mathematical factorial function where N! = 1*2*3...*N. A sample subprogram would be the following:
SUB fact (x, result)
IF x = 1 THEN
result = 1
result = x * newresult
Most interpreter programs you will find will compile with no modifications. And best of all they still work as expected. This is not true if you try to convert MS Basic programs to ZBasic. The structure is very similar, but not all the commands work exactly the same way that the MS Basic interpreter and compiler does.
Before we get too far ahead of ourselves in talking about the compiler, it should be noted that the compiler should be thought of as a stand alone package. In other words, although it is compatible with the interpreter, the interpreter is NOT required to write and compile programs. The Apple EDIT program (version 2.0) is included with the compiler. Actually any editor program will work. It just so happens that it is convenient to use the interpreter's editor if you have both the interpreter and compiler. This way you can run your program (provided you understand the few differances between the interpreter and the compiler) with the interpreter until it is debugged. Then when your program runs like you want it to, you may then save the program as TEXT and run the compiler. Both the compler and the interpreter have added a Transfer item in the File menu for transferring from one application to another (in this case from the interpreter to the compiler). You could transfer to and from the EDIT application to compiler equally as well. It should be noted that the last line of a program saved by EDIT is lost when read in by the interpreter. So BEWARE. I don't know which is at fault, interpreter editor or EDIT program (I think it is the interpreter editor but I don't know for sure), but it is not hard to work around this bug.
Two methods may be used in compiling your programs. A set of runtime files (called runtime overlays) may be attached to your application at compile time to create a full double-clickable standalone application. Or you can compile just the program or set of programs (via a compiler list) and use the runtime files separately. This method will save space on a disk where you have several compiled programs. This way the runtime stuff will only have to be on the disk once. ICONS and other resources will have to be added separately with ResEdit.
A few compiler metacommands are provided that may be imbedded in the text of your program. Imbedding the metacommands in your program is helpful for ignoring text that should not be compiled or including text that should not be used when running the interpreter. The metacommands are imbedded in remark statements (which are ignored by the interpreter because they are comments). For example, the Search, Run and Windows menus of the interpreter are normally disabled in an interpreted program by a few lines of code similar to this:
FOR i = 3 TO 5 : MENU i,0,0,"" : NEXT i
This statement leaves 3 blank menus in place of the interpreter menus. In the compiler, these menus are not used and don't need to be erased (because they aren't there). In this case you may want to use the compiler metacommand: '$IGNORE ON before the statement to erase the menus and use '$IGNORE OFF to resume compiling. By doing this, the compiled version or your program will not have include three blank menus as the interpreted version does. The metacommands that are available are:
$INCLUDE to compile a file (stored on disk) and insert that file at the point where the $INCLUDE metacommand is used.
$IGNORE ON instructs the compiler to ignore source lines until it encouters an $IGNORE OFF.
$OPTION is used to change the compiler options that may be set before compilation. $OPTION allows any of the options to be changed during compilation. The options may be selected from a dialog box (see figure 1) before compilation. The program execution speed is affected by the options you choose. For example if you don't select 'C' for checking array boundaries, the error checking code will not be included in the compiled program and the program will run faster.
$PAGE can be used to set page breaks in compiler listing files.
There are only a few things that have not been up to snuff for creating professional Macintosh applications with the MS Basic Compiler. First, there is no compiler option or statement to disable the default window and default menus. If you recall, this was one of my complaints early on in the release of ZBasic. ZBasic has fixed that oversight by adding the WINDOW OFF statement.
There are a few minor bugs which affect only a few things you may want to do, and even then you can program around them with other statements. For example, I found that when compiling my Clipping Region Demo from last March 1986 that the compiled version did not run the same. It turns out that the CLS statement must reset the clipping region to the full screen because the second clipping region in the demo is cleared by CLS and the next items printed are not clipped. The solution is to select the clipping region again after the CLS statement or else not use the CLS statement at all. Since the fix for this problem requires only one extra statement (one that has already been used prior to the CLS statement), I don't consider this a major problem. Microsoft tells me that any bugs that may turn up in the compiler will be corrected in the next update to the compiler which could be as early as the end of March (??). I would hope that Microsoft will be as quick to respond to problems as Zedcor has done with ZBasic. Of course, I think that ZBasic had many more problems as evidenced by all the system bombs that we had all experienced. If Microsoft is responsive to what the users need (as Zedcor has been), then I see no reason why the MS Compiler won't be a success.
Another hangup is the way the compiler must have the Basic Overlays available in just the right folder. This also is something that you can work around because at least the compiler looks for the Overlays in the places you are most likely to put them. I would suggest the same sort of method that Lightspeed Pascal uses to find files when the compiler can't find them. When files can't be found, the GetFile dialog is displayed so the user can help find the file that is needed. If it is not done this way, I really don't feel that there is complete HFS compatiblilty. [This is a simple error trapping methodology. We fail to understand why it is not used by more programming languages. -Ed]
THE BOTTOM LINE
OK, you're probably wondering what's the bottom line. What product is the best? I'm not so sure that the dust has settled yet, but we can come to some conclusions now. For comparison, the benchmark tests form the August 1986 MacTutor have been executed for the MS Compiler. The interpreter results have not changed. The Sieve of Eratosthenes executed in 10 seconds for both binary and decimal compiled versions and static variables. ZBasic as you recall was 7 seconds (also uses static variables, dynamic not available in ZBasic). With dynamic variables the MS Compiler time was 56 seconds. In the same benchmark test done by Microsoft using floating point arrays (instead of integer arrays) the times were dramatically different. The MS Basic binary time was 13 sec., decimal time 17 sec. and ZBasic 75 seconds (all using static arrays). I think that these results just go to show you that one benchmark test does not give conclusive results as to what is better. Sometimes the results are only measuring specific statements and don't represent the performance real-world applications.
The MacTutor benchmark used back in Aug. 1986 returns the same accuracy results as for the Basic interpreter. Only the decimal version got the right answer; the binary version rounded off. The decimal verision ran in 4 seconds, but the binary ran in 1 second. In addition, if you use the RAM cache on the Mac Plus and run the binary version twice in a row, the second time it runs in less than 1 second (0 seconds is returned, but the TIMER statement doesn't return tenths of a second so I assume that the time was rounded to zero).
MACTUTOR BENCHMARK (Aug 1986)
decimal compile time = 12 sec.
Result = 503.54380215, 1.23, in 4 seconds
binary compile time = 11 sec.
Result = 503.5436, 1.23001 in 1 second
Sieve compile time: 13 seconds (other times below)
Microsoft has provided results (performed by Microsoft) to other benchmark tests which offer other comparisons. I have verified most of the ZBasic and MS Compiler results (results are in parenthesis). The table shown in figure 2 indicates these results.
BENCHMARK MS BASIC 3.0 (b) MS BASIC 3.0 (d) MS Compiler (b) MS Compiler (d) Zedcor ZBasic
Dynamic 667 672 56 56 na: NOTE-1
Static na na 10 (10) 10 (10) 7 (7)
SIEVE FloatingPt. Array
Dynamic 733 792 58 63 na: NOTE-1
Static na na 13 17 75 (73)
FOR Loop Integer 7 7 1 (1) 1 (1) 1 (¾1)
FOR Loop Real 15 18 3 (3) 9 (9) 15 (26)
Array Lookup Integer
Dynamic 83 86 17 17 na: NOTE-1
Static na na 1 (1) 1 (1) 1 (1)
Array Lookup Real
Dynamic 85 87 19 20 na: NOTE-1
Static na na 1 (1) 1 (1) 18 (18)
Addition 100 102 1 (1) 1 (¾1) 51 (48)
Subtraction 102 110 1 (1) 1 (¾1) 58 (55)
Multiply 100 204 1 (¾1) 1 (¾1) 211 (208)
Division 107 205 1 (1) 1 (¾1) 488 (486)
Concatenation 63 63 39 (39) 39 (39) 10 (10): NOTE-2
Pattern Match 42 44 30 (30) 31 (31) 6 (6): NOTE-2
Line (BASIC stmt) 23 23 10 (7) 10 (7) 16 (6): NOTE-3
Line (ROM call) 18 18 5 (5) 5 (4) 5 (5)
Diagonal Line 39 39 30 (15) 31 (15) 34 (15): NOTE-3
CIRCLE 38 38 38 (19) 38 (20) 38 (19): NOTE-4
Set Pixel (PSET) 82 82 52 (39) 52 (40) 56 (32): NOTE-5
FILE I/O (data written/read on 400K floppy)
Random PUT 61 61 44 (25) 44 (29) WNR (114)
Random GET 43 41 27 (14) 28 (14) WNR (8)
Sequential PRINT# 24 25 5 (4) 5 (4) 12 (9)
Sequential INPUT 13 13 3 (3) 3 (3) Crashed (Crashed)
WNR: Would Not Run (A few minor modifications by MacTutor allowed these routines to run. Times in parenthesis).
1) Sinse ZBasic does not support ERASE or REDIM, it was assumed that they consider ALL arrays to be static.
2) ZBasic string variables are limited t 255 characters. MS Basic strings can be up to 32,767 characters.
3) ZBasic does not implement a LINE statement within the language. The ZBasic equivalent statement is PLOT. Since ZBasic's default coordinate system is 1024 X 768 and MS Basic's is 512 X 320, a COORDINATE WINDOW statement was included in the benchmark's source code to make all ZBasic graphics operations based on 512 X 320 pixels.
4) ZBasic has a slightly different implementation of the CIRCLE statement. Since ZBasic's default coordinate system is 1024 X 768 and MS Basic's is 512 X 320, a COORDINATE WINDOW statement was included in the benchmark's source code to make all ZBasic graphics operations based on 512 X 320 pixels.
5) ZBasic does not have a PSET statement. The ZBasic equivalent is PLOT. Since ZBasic's default coordinate system is 1024 X 768 and MS Basic's is 512 X 320, a COORDINATE WINDOW statement was included in the benchmark's source code to make all ZBasic graphics operations based on 512 X 320 pixels.
The benchmark presented for sequential file I/O does 5000 writes and 5000 reads from a sequential file. The benchmark presented for random file I/O does 5000 PUTs and 5000 GETs from a sequential file. The math benchmarks presented do 100,000 iterations of each of the four standard math functions in single-precision format. The string operations presented were performed 30,000 times each.
All the benchmarks above were performed by Microsoft on a 512K Macintosh, Finder 5.3, System 3.2, and HyperDrive 20. Benchmark results by MacTutor (those inside parenthesis) were performed on a Macintosh Plus, Finder 5.3, System 3.2 and ProApp 40.
The benchmarks can be obtained by contacting Microsoft Corporation,Public Relations,16011 NE 36th Way,Box 97017, Redmond, WA 98073-9717 (206) 882-8088 and asking for the Microsoft BASIC for Apple Macintosh Benchmark disk.
Fig. 2 Benchmarks for the new MS Basic Compiler
It appears from the results that the MS Compiler does computations much faster, but ZBasic handles string manipulations much faster (keeping in mind note-2 of the table). If you are now wondering if you should buy ZBasic or the MS Compiler you may now have a tough decision. For the price ZBasic has a lot to offer, but as far as being compatible with the MS Interpreter, the MS Compiler is the one. It looks like there are some speed advantages to the MS Compiler that may be a deciding factor for some of you. I have updated and modified the Basic Comparison Chart from the Aug. 1986 issue, shown in figure 3. (The apple rating shown compares each product relative to each other and has no relation to the previous chart in the Aug. 1986 MacTutor. At this time I feel that the MS Compiler has an edge over the other products due to its reliability (it works) and compatibility with the MS Basic Interpreter (ver. 3.0). Toolbox support is sufficient and user expandable (if you want to write your own libraries). The race is still very close, but this is the way I see it at the present time. More to come see you next month.
MS Compiler Bugs
There are a few bugs that we assume will be fixed promptly in the next update of the MS Compiler. At least if Microsoft is responsive to their users I'm sure they will want to make the proper corrections where they apply. Some of the problems are:
° No compiler option is availble to disable the default window. This is undesirable when custom windows are used (most of us use them all the time).
° There is no support for ZOOM windows. This is a feature of the 128K ROMS which many of us would like to use. Of course Microsoft prefers double-clicking on the title bar to zoom the window, but even that doesn't work with the MS Compiler. We fail to understand why all the new ROM routines have not been supported as yet!
° The CLS statement changes the clipping region. This is noticable when using the SetClip toolbox call. There is no problem with this when using the Interpreter. NOTE: Now that the CLR libraries are included as part of the Interpreter and Compiler, it is assumed that Microsoft will support the toolbox by making statements compatible. It should be noted that there may be several things that don't work exactly the same as the Interpreter when using libraries as the libraries were originally written for the interpreter. Most of these type of problems can be worked around without much inconvenience. It would be unreasonable to think that all of the differences have been found.
° Commnications does not work properly. If you want to verify this just compile the 'terminal' program included with the sample programs supplied with the Interpreter. You will find that characters are lost in the compiled version. I verified this by connecting a Mac+ with an Apple //e directly with the imagewriter cable. If you use communications these problems could be a real pain.
° It has been reported to MacTutor that only the Apple printer drivers are supported. I don't have any non-Apple drivers so I could not verify this.
° Printing to a printer with the Compiler does not work the same as with the Interpreter. For example
PRINT #1, TAB(10) USING "$###.###";777.7777
sends a single form feed to the printer and does not print the number. The interpreter tabs over 10 spaces and prints the number as expected. Also:
OPEN "LPT1:PROMPT" FOR OUTPUT AS #1
PRINT "";TAB(10);"HELLO WORLD"
ignores the TAB and prints HELLO WORLD at the left edge of the page. These problems can be overcome with other statements, but we hope that Microsoft will pay attention to problems like this. It appears that anytime TAB is sent to the printer from a compiled Basic program, the TAB functions are ignored. TAB works properly when printing to the screen. It is interesting to note that the Absoft Fortran product also had a lot of problems with printing. We wonder if there is a connection.
° The compiler does not seem to optimize code. Object code files are very large especially when Libraries are used. A solution when using Libraries is to use ResEdit to modify the names of the Library CODE resources to one character long and change program lines to match. Now when program is compiled fewer bytes are required to specify the library CODE resource. Keep in mind that this makes your source code harder to read.
While these problems may seem small, I hope that Microsoft will be responsive to correcting this bugs as quickly as Zedcor has been with ZBasic. Even with the problems mentioned here, it is my opinion that the MS Compiler is closer to being bug free than ZBasic.
If you find any more bugs, please let us know. Also it wouldn't hurt to let Microsoft know. We will be doing the same with hopes that the bugs will be corrected.