The dialect of BASIC implemented in the Wang 2200 series of computers evolved over time, adding more powerful features and support for new I/O devices. With the introduction of the 2200 VP computer, Wang enhanced the syntax so much (although in a backward compatible way), it renamed the language to BASIC-2. This document only is concerned with the first generation, Wang BASIC. There is a separate page about BASIC-2.
Here is a brief rundown on some of the aspects of Wang BASIC that make it different (for better or for worse) than the Microsoft BASIC that was popular on most 8-bit micros just a few years later. The point of this isn't so much a competition as it is the easiest way I can think to explain Wang BASIC without explaining the "standard" stuff.
Clearly, MS BASIC is more flexible and more powerful in general, especially in regards to its string features. Wang BASIC is more geared towards computation, as evidenced by its matrix capabilities and that all computation is done in double precision. Wang BASIC also does all calculations with a decimal (BCD) floating point representation, which is especially useful in financial applications.
Some slack should be cut in Wang's favor as it delivered a complete computer system and a rich BASIC in May 1973, while Microsoft wasn't founded until two years later.
Wang BASIC has many features that today are pretty non-standard, and are oriented at the typical scientific/business user, not the home user. As such, the focus is more on record processing. This is especially true of some of the advanced features offered, such as the $GIO stuff, matrix sorting operations, and the disk system.
Color coding has been used in the following tables and code examples; Microsoft syntax is shown with a blue background, and Wang syntax examples are shown with a green background.
Variable names (link)
Wang BASIC allows variable names that are only a single letter or a letter and a digit. MS BASIC variable names consist of a starting letter, followed by an arbitrary number of letters or digits, although only the first two characters are significant.
Wang: 10 A = B1 20 R4 = 3 + C1 |
|
MS: 10 A = B1 20 RING = 3 + CAT |
really seen as "20 RI = 3 + CA" |
Numeric precision (link)
Wang BASIC supports only double precision floats, while MS allows 16-bit integers, single-precision floats, and double precision floats; the default is single-precision floats. On the other hand, code written to use the various MS data types is rather cluttered looking. The emphasis on high precision is a case where Wang's scientific calculator background is evident.
Wang: 10 A = A + 1 20 B = C 30 R = 2/3 * C |
double precision double precision double precision |
MS: 10 A% = A% + 1 20 B = C 30 R# = 2.D0/3.D0 * C# |
16 bit integer single precision double precision |
Assignment (link)
One minor feature of Wang BASIC is that it allows multiple variables
to be set by one assignment statement. In both Wang and MS BASIC,
the keyword LET
is optional.
Wang: 10 LET A=1 20 B=2 30 C,D,E=A+B 40 A$,B$="test" |
MS: 10 LET A=1 20 B=2 30 C=A+B:D=C:E=C 40 A$="test":B$=A$ |
String support (link)
Wang strings are statically sized and can be a maximum of 64 characters long; the default is 16 characters. MS BASIC strings are dynamically sized and can be up to 255 characters long.
Wang: 10 DIM A$21 20 DIM B3$(50)40 30 A$ = "This is a long string" 40 B3$(4) = "Fourth one" |
string 21 characters long 50 strings, each 40 characters long |
MS: 20 DIM B3$(50) 30 A$ = "This is a long string" 40 B3$(4) = "Fourth one" |
Also, Wang BASIC has fewer string manipulation functions, and the ones it has are typically weaker.
Wang: 10 A$ = "Here'$ a te$t" 20 N = POS(A$ = "$") |
returns 6 |
MS: 10 A$ = "Here'$ a te$t" 20 N = INSTR(A$,"$") |
returns 6 |
In this example, the two produce the same answer, but if the program
really needed to find the string "$t", Wang's POS()
won't work since it can find only a single character, whereas MS BASIC's
INSTR()
can find arbitrary strings.
MS BASIC has a large number of string operators, while Wang BASIC had
a more limited form and outright didn't have some that MS BASIC has.
In general, all Wang substring operations are handled by the
STR()
operator.
One feature of Wang BASIC that isn't matched by Microsoft BASIC is that
STR()
can be used both on the left and right side of an equation. Line
30 below shows this, although it isn't too painful in MS BASIC because
dynamic string concatenation is allowed. Wang does not have string
concatenation like this.
Wang: 10 A$="ABCDEFGHIJKLM" 20 PRINT STR(A$,3,3) 30 STR(A$,1,4) = "1234" 40 PRINT A$ |
-> "CDE" -> "1234EFGHIJKLM" |
MS: 10 A$="ABCDEFGHIJKLM" 20 PRINT MID$(A$,3,3) 30 A$ = "1234" + MID$(A$,4,99) 40 PRINT A$ |
-> "CDE" -> "1234EFGHIJKLM" |
MS BASIC also has the RIGHT$()
function,
and the STRING$()
function.
Actually, Wang BASIC has something akin to the MS BASIC
STRING$()
function.
Wang: 10 DIM A$8 20 INIT("$") A$ 30 PRINT A$ |
->"$$$$$$$$" |
MS: 10 A$=STRING(8,"$") 20 PRINT A$ |
->"$$$$$$$$" |
Two final oddities in the WANG string length function. In MS BASIC,
string length is dynamically set to be exactly as long as the string requires.
But because Wang BASIC uses statically allocated strings,
LEN()
returns the allocated size of the string minus the trailing number of spaces.
Wang: 10 DIM A$30 20 A$ = "This is a test" 30 PRINT LEN(A$) |
-> 14 |
MS: 20 A$ = "This is a test" 30 PRINT LEN(A$) |
-> 14 |
So far so good. The subtle difference is that MS BASIC can have a string with trailing spaces, while Wang BASIC can't. The second oddity is that there is one caveat to Wang's definition of LEN(). If the string is entirely spaces, LEN() returns 1, not zero.
IF/THEN statement (link)
Wang BASIC's IF
statement is less general
than that of MS BASIC. It is weaker in two ways. Firstly, the Wang
IF
statement doesn't have an
ELSE
clause.
Wang: 100 IF A > 3 THEN 110: PRINT "NO": GOTO 120 110 PRINT "YES" 120 ... |
MS: 100 IF A > 3 THEN PRINT "YES" ELSE PRINT "NO" |
Secondly, Wang IF statement doesn't allow conjunctions, unlike MS BASIC.
Also, the "target" of a THEN
in Wang BASIC
has to be a line number. MS allows it to be any legal sequence of BASIC
commands.
Wang: 100 INPUT "Enter a digit";A$ 110 IF A$ < "0" THEN 120: IF A$ <= "9" THEN 130 120 PRINT "Bad digit": GOTO 100 130 ... |
MS: 100 INPUT "Enter a digit";A$ 110 IF A$ < "0" OR A$ > "9" THEN PRINT "Bad digit": GOTO 100 120 ... |
Machine-level access (link)
Wang BASIC offers no low-level access to the machine language because its CPU was unlike that of a conventional microprocessor.
MS BASIC supports
PEEK
,
POKE
,
VARPTR()
,
USR()
,
IN
,
OUT
, and
WAIT
commands.
FOR/NEXT statements (link)
In Wang BASIC, the loop index of NEXT
statements must be given, and only
one can be given. In MS BASIC, the index variable is optional,
but if it is given, a comma-separated list is allowed to close multiple
loops.
Wang: 10 FOR J=1 TO 10:NEXT J 20 FOR X=1 TO 4:FOR Y=1 TO 3:PRINT X+Y:NEXT Y:NEXT X |
MS: 10 FOR J=1 TO 10:NEXT 20 FOR X=1 TO 4:FOR Y=1 TO 3:PRINT X+Y:NEXT Y,X |
Error handling (link)
MS has ON ERROR GOTO
and
RESUME
commands. Wang added
ON ERROR
later, but it wasn't in the earlier
machines. Wang's ON ERROR
was different than
Microsoft's. Examples are easiest:
Wang: 100 ON ERROR E$, N$ GOTO 900 ... 900 REM ERROR RECOVERY 910 PRINT "Line ";N$ 920 PRINT "Error ";E$ ... 990 GOTO 500 |
If an error occurs, E$ holds a string describing the error number, and N$ contains the line that triggered the error. All FOR loops and pending RETURNS are cleared from the stack. If more than one ON ERROR appears in the program, only the first takes effect. |
MS: 10 ON ERROR GOTO 900 ... 900 REM ERROR RECOVERY 910 PRINT "Line "; ERL 920 PRINT "Error "; ERR ... 990 RESUME |
If an error occurs, ERR contains a numeric representation of the failing line number, and ERL contains the numeric error code. The RESUME statement causes execution to return to the failing line. Optionally, RESUME NEXT resumes with the line after the failing line, and RESUME nnnn continues on at line nnnn. ON ERROR is dynamic, so the one most recently executed is the one that applies. |
DEFFN (link)
The Wang define function DEFFNx()
syntax
allows only one argument variable, whereas MS BASIC allows multiple
arguments. However, Wang BASIC is more liberal in that it permits the
function name to be a single digit as well.
10 DEF FNA(X) = X*X-1 20 DEF FN3(A) = SIN(A)*COS(A/2) |
Array dimensioning (link)
The maximum value of an array index is 255 in Wang BASIC, and the total number of elements must be less than 4096. Arrays may have only one or two indexes, not more. On the positive side, arrays could be redimensioned after they were created. But on the negative side of that positive side, the redimensioned size can't be larger than the original dimensions of the array.
MS BASIC has no limit other than not exceeding available memory, and supports arrays with more than two dimensions. Arrays can not be redimensioned.
Error checking (link)
Wang BASIC checks the each line of the program as they are entered and immediately reports any syntax errors. When a program is run, the interpreter cross-checks for consistency, reporting syntax errors anywhere in the source, errors in dimensioning variables, exceeding memory limits, and any references to undefined functions or line numbers.
MS BASIC reports the error only as it attempts to execute the command in error. This is a drawback because errors can lurk in the code for a long time undetected, unless the bad line is executed or some data dependent behavior is triggered, exposing the problem.
Matrix operations (link)
Wang BASIC has a full complement of matrix operations. According
to the Wang Matrix Statements Reference Manual, the built-in matrix
operations operate at roughly 8x to 10x the speed of doing the function
via FOR
loops.
Example command | String Version? | Explanation |
---|---|---|
MAT REDIM M(5,3) | y | dynamically redimension an array |
MAT M = ZER | n | zero an array |
MAT M = IDN | n | fill with identity array |
MAT M = CON | n | fill with constant 1.0 |
MAT M = TRN(B) | n | transpose |
MAT M = INV(B),D | n | invert matrix, returning determinant |
MAT M = A + B | n | matrix addition |
MAT M = A - B | n | matrix subtraction |
MAT M = A * B | n | matrix multiplication |
MAT M = (2) + A | n | scalar addition |
MAT M = (2) * A | n | scalar multiplication |
MAT PRINT M | y | print matrix |
MAT INPUT M | y | input matrix |
MAT READ M | y | fill with DATA elements |
String matrices can be used for the non-arithmetic commands above,
e.g. MAT READ M$()
.
Later versions of Wang BASIC (2200T) had even more
MAT
operations, which are too complicated to
explain here. Instead, an example of each is given. As you can see,
they are quite arcane. Personally, I never used them except experimenting
with them to see how they worked. MAT SEARCH
did give all the functionality of the MS Basic
INSTR()
function, and then some!
MAT Sort command examples:
MAT CONVERT A() TO A$()(6,8)
MAT COPY A$() <X*Y, 100/X> TO -A$()<10,20>
MAT MERGE A$ TO W1$(), W2$(), S$()
MAT MOVE A$(), L$(2,3), M TO B$(1,1)
MAT MOVE A(), L$(1) TO A1(1)
MAT SEARCH A$()<1,5>,=STR(Z$,1,5) TO B$ STEP 5
MAT SORT A$() TO W$(), L$()
Program chaining (link)
Wang has a COM
statement, which allows
defining variables that won't be cleared when the next program is run.
There are also mechanisms for clearing a section of the current program,
loading new program lines, then continuing on.
Chaining in MS BASIC has no equivalent (AFAIK).
Wang: 10 COM A, B3, C(10,10), D$ ... 1000 LOAD "MORE" 50,100 |
When line 1000 is executed, it will erase all program variables except
those listed in the COM
statement;
it will then delete program lines 50 to 100, inclusive, then merge in
the lines from the program named "MORE" before resuming operation.
Number/string conversion (link)
Wang BASIC's CONVERT
statement comes in two flavors.
Conversion from a string to a number is similar to MS BASIC's VAL statement.
Wang: 10 A$="-1.2345E+3" 20 CONVERT A$ TO A |
MS: 10 A$="-1.2345E+3" 20 A=VAL(A$) |
Wang's CONVERT
command can also be used for
converting from number to string representations. Wang's
CONVERT
from number to string was like C's
sprintf()
function. Or, another way to look at it,
it was kind of like PRINTUSING
with the output
going to a string. E.g.
10 CONVERT A TO A$,(+#.#####^^^^) |
converts A to A$ in a 12 character field, with leading sign, in exponential format, with five fraction digits. MS BASIC does not have anything like it.
Wang also has the NUM(string) function, which
returns the leading number of characters in the specified string that
form a legal number. E.g., NUM("123+6")
would
return 3
.
It is useful for validating user input before attempting a conversion.
Trig functions (link)
Wang BASIC allows setting whether trig functions deal in degrees, radians,
or grads via the SELECT
statement.
SELECT D SELECT R SELECT G |
degrees
radians grads |
MS BASIC only operates in radians.
Besides
SIN()
,
COS()
, and
TAN()
, Wang BASIC supports the
ARCSIN()
,
ARCCOS()
, and
ARCTAN()
functions. MS BASIC lacks the equivalent of
ARCSIN()
and
ARCCOS()
.
Line renumber (link)
Wang BASIC supports the RENUM
command to
renumber the program. If it can't successfully complete the job
(line number collisions or line number too big), it gives an error without
changing any of the line numbers.
Some versions of MS BASIC have this as well, but it wasn't standard on typical 70's 8-bit micros (e.g. it was a utility function, not something burned into ROM).
Debugging support (link)
While Wang BASIC and MS BASIC both have a TRACE
statements, Wang's TRACE
is more informative.
MS BASIC only shows the line number of each line as it is executed, while
Wang BASIC shows each variable assignment and change of control flow.
Wang: 10 A=0 20 TRACE 30 FOR I=1 TO 10: A=A+I:NEXT I 40 TRACE OFF |
MS: 10 A=0 20 TRON 30 FOR I=1 TO 10: A=A+I:NEXT I 40 TROFF |
Also, the Wang keyboard has a STEP/RUN
key;
after each step it lists the remainder of the current line still to
be executed.
Although the SELECT Pn
statement has a few uses,
it is particularly useful for slowing down the output while
TRACE
mode was on, otherwise all the information
would scroll past before the programmer had a chance to absorb anything.
SELECT Pn
allowed specifying an automatic
delay after each carriage return, in sixths of a second.
SELECT P0 SELECT P1 SELECT P6 |
no pause pause 1/6-th of a second after each carriage return pause one second after each carriage return |
Named subroutines, special function keys (link)
Wang has an odd "marked subroutine" feature. Perhaps an example is best:
100 GOSUB'10 110 GOSUB'5("this", 4) 120 STOP 200 DEFFN'10 210 PRINT "Hi":RETURN 300 DEFFN'5(A$, N) 310 FOR I=1 TO N:PRINT A$:NEXT I:RETURN 400 DEFFN'6(A, B) 410 PRINT SQR(A*A+B*B):RETURN 500 DEFFN'8 "PRINT A*3.14159" |
When the GOSUB'
command is seen,
a DEFFN'
with a matching value
(0 to 255) is sought out. Note that arguments may be passed, but
they aren't true dummy variables -- they change the global variable
of the same name just like an assignment.
One cool feature is that the Wang has 16 "special function" keys along the top, which can be treated as 32 in combination with the shift key. When special function key N is pushed, the marked subroutine with the matching N is performed. If the command line has a list of arguments, they are passed in as the arguments to the marked subroutine. For instance, if the command line reads
:5 6 |
and then the special function key 6 is pressed, the routine at line 400 would be executed with A set to 5 and B set to 6. This feature certainly derives from Wang's calculator heritage.
As a special case, line 500 shows how a key can be defined as a keyboard macro. Pressing special function key 8 results in the specified string being entered into the keyboard input buffer as if the user had typed the string directly.
MS BASIC had nothing similar to either feature, but I don't think anybody but a Wang BASIC user would miss them.
RETURN CLEAR (link)
The RETURN CLEAR
command allows a subroutine
to pop the pending return frame off the call stack. It wasn't used
often, but when it was, it was very handy. A typical use is for
error recovery inside a subroutine. Rather than passing
some error status back to the caller and having each caller check the return
flag, instead the subroutine would clear the return and jump to the error
handler (e.g., print a message and ask for input again).
10 GOSUB 100 ... 100 IF N>0 THEN 130 110 REM OOPS -- aborting to error handler 120 RETURN CLEAR: GOTO 200 130 PRINT "OK": A=5/N: RETURN |
Boolean vector operators (link)
Wang BASIC has a large number of boolean operator statements that operate
on bit vectors much faster than it can be done in MS BASIC. In all
the functions below, the B$ argument may be replaced by two hex digits
(e.g. 01
), and that one byte value is applied
to each byte of A$.
Command | Explanation |
---|---|
ADD(A$,B$) | adds corresponding bytes of B$ to A$ |
ADDC(A$,B$) | like ADD(A$,B$) but with interbyte carry |
AND(A$,B$) | ANDs each byte of A$ with corresponding byte of B$ |
OR(A$,B$) | ORs each byte of A$ with corresponding byte of B$ |
XOR(A$,B$) | XORs each byte of A$ with corresponding byte of B$ |
BOOLn(A$,B$) | perform boolean operation n on A$ with B$ |
INIT(B$)A$ | fill A$ with the first byte of B$ |
INIT("x")A$ | fill A$ with the byte "x" |
There are some other statements and functions that deal with bit vectors.
Command | Explanation |
---|---|
HEX(012345) | represents a 3 byte string of 01,23,45 hex |
ROTATE(A$,N) | rotate left each byte N bits (N=1 to 7) |
HEXPRINT A$ | print contents of A$ in hex |
HEXPRINT B$() | print contents of array B$() in hex |
Data packing (link)
Wang BASIC has a flexible and succinct way of packing a collection of data into a string, plus a corresponding way of unpacking it. Typical MS BASICs don't have it, although some versions of their disk basic have a more limited ability.
10 DIM M(10,10), A$6, B$(10)30 20 PACK(####) A$ FROM X,Y,Z 30 PACK(+#.##^^^^) B$() FROM M() |
Line 20 specifies that each of X
, Y
and Z
should be converted to a four digit BCD number, occupying two bytes each,
for a total of six bytes. This fits into A$
perfectly (A$
could have been larger), and the 6 byte storage cost is much less than
the native 24 byte cost of the X, Y, and Z variables.
Line 30 specifies that the 100 values in M()
are to be converted
to a signed exponential format with three digits; since each number requires
three bytes of storage in packed format, we need a total of 300 bytes.
We can't dimension a single string that large, so instead B$
is
declared as 10 strings of 30 bytes each, and this is large enough to contain
the packed image of M()
.
UNPACK
performed the inverse operation:
120 UNPACK(##.##) A$ TO X,Y,Z 130 UNPACK(+#.##^^^^) B$() TO M() |
Note that typically the pack and unpack formats would be identical,
but nothing says it must be so. It is simply a collection of nibbles
when in the packed state, with no explicit indication of the decimal point
nor of which nibbles are exponents. Line 20 and 120 use different
formats, which would result in the values in X
, Y
, and
Z
being scaled by 1/100.
These functions are probably most commonly used for packing and unpacking data when transferred between memory and a storage device, but they can also be used to advantage by compressing arrays of low precision numbers during run time.
I/O redirection (link)
Wang has various standard I/O devices, each of which could be remapped to some other I/O device. The standard I/O devices are:
SELECT Name | Device |
---|---|
CI | console input |
CO | console output |
LIST | list output |
print output | |
TAPE | tape device |
PLOT | plotter device |
E.g.:
10 SELECT CO 215 (80) |
selects device 215 for console output, 80 columns wide. It isn't very mnemonic, but Wang supports a whole family of peripherals and had a scheme for numbering them all that at least had a pattern. There is no problem putting multiple keyboards, printers, tape drives, plotters, card readers, disk drives, etc. all on one machine and switching I/O between them.
MS BASIC can do a very limited version of this, but it requires doing some magic POKEs and such. Some disk BASICs have more robust OS support for device table mapping.
Cassette operation (link)
Non-disk based MS BASIC only has CLOAD
and
CSAVE
commands for programs. Files could be
OPEN
ed and data
PRINT #n
'd to them or
INPUT #n
'd from them, but due to the low
cost cassette interface and cassette interface, it wasn't very functional
and was slow and often unreliable.
Wang BASIC's cassette I/O is richly supported with a dizzying number of I/O commands for rewinding, skipping, reading, writing, verifying, etc. The cassette interface is a high speed, high quality recording mechanism. Besides being faster than the audio cassette players adopted by most 8-bit micros, the Wang cassette drive is under direct computer control and can move the tape forwards and backwards. Tape speed was 7.5 ips and data is transferred at approximately 326 bytes/second. Each block is recorded twice for error tolerance, and each block is checksummed. Compare this to most 70's micros that used 1.825 ips cassette tapes and transferred 30-120 bytes/sec.
Because of this ability, any tape read that is in error will cause the tape mechanism to rewind a bit and retry the failing operation a few times before declaring an error. This "washing machine" noise as the tape mechanism ran forward, then backwards, then forwards, then backwards again very quickly is a greatly feared sound, anxiety mounting with each retry.
There are three concepts to the Wang tape format: the physical record, the logical record, and the file. A physical record is a 256 byte indivisible block transfer, although only 253 byte are used as data payload, with the other three used for control purposes. A logical record spans one or more physical records and corresponded to all the data specified in a single DATASAVE command. A file is a collection of logical/physical records starting with a special header record and a special trailer record.
Example command | Explanation |
---|---|
LOAD | load a program |
SAVE "FOO" | save program named as "FOO" |
SAVE "FOO" 50,100 | save just program lines 50 to 100 |
SAVE P "FOO" | save program "FOO", protected mode |
REWIND | high speed rewind to beginning of tape |
SKIP 2 | skip two logical records |
SKIP 2F | skip two files |
SKIP END | skip to end of current file |
BACKSPACE 3 | backspace three logical records |
BACKSPACE 3F | backspace three files |
BACKSPACE BEG | backspace to start of current file |
DATASAVE OPEN "FOO" | open a data file for writing (header record) |
DATASAVE A,B,C$,D() | save logical record |
DATASAVE END | terminate a file (trailer record) |
DATARESAVE A,B,C$,D() | rewrite a logical record |
DATALOAD OPEN "SAM" | open a data file for reading |
DATALOAD A,B,C$,D() | load data elements |
When reading data from a file, a program often has to determine when
the last record has been read. In Wang BASIC, the technique is to
to attempt a DATALOAD
operation and
then perform an end of file test using this syntax:
40 DATALOAD A,B,C 50 IF END THEN 110 |
Multiple tapes can be operated on by specifying the device I/O address
(if not specified, the default SELECT TAPE
device
is assumed).
20 REWIND/10B 30 DATASAVE/10C, A(), B$() |
There is a mapping of physical device to one of six logical
I/O devices via the SELECT
statement:
10 SELECT #1, 10B, #2, 10C 20 REWIND #1 30 DATASAVE #2, A(), B$() |
Minor differences (link)
- Clearing program and or data is slightly different between the
two BASICs.
Wang:
CLEAR
CLEAR V
CLEAR N
CLEAR P
CLEAR P 50,100
COM CLEAR
clear all program lines and variables
clear only variables
clear only non-COM variables
clear only program lines
clear only program lines 50 to 100
make COMmon variables not COMmonMS:
NEW
DEL -50
DEL 50-
DEL 50-100
CLEAR
CLEAR 1000
clear all program lines and variables
delete program lines up to line 50
delete program lines 50 and higher
delete program lines 50 to 100
clear all variables
clear all variables; string heap = 1000 bytes - In Wang BASIC,
RESTORE n
restores the nextDATA
pointer to the n-thDATA
element in the program source. In MS BASIC, it restores the nextDATA
pointer to be line n. - Wang BASIC uses the
BIN
function whereas MS BASIC usesCHR$
.Wang:
10 BIN(A$) = 33
20 A$ = HEX(21)
set the first char of A$ to ASCII 33 ("!")
similar: set A$ to ASCII 33 (hex 21)MS:
10 A$ = CHR$(33)
set the first char of A$ to ASCII 33 ("!") - Wang BASIC uses the
VAL()
function while MS BASIC uses theASC()
function.Wang:
10 PRINT VAL("!")MS:
10 PRINT ASC("!") - Wang has the KEYIN command whereas MS has the INKEY$ function.
Wang:
10 KEYIN A$,20,30:GOTO 10MS:
10 A$=INKEY$:IF A$="" THEN 10Wang BASIC syntax is unusual. The first number is the line where control will be transferred if a normal keystroke is detected. The second number is where control will be transferred if one of the special function keys is detected. Otherwise, if no key is detected, the next sequential statement is performed.
- The specification of the PRINT USING image is slightly different
for Wang BASIC.
Wang:
10 PRINT USING 20, 12.345
20 %The answer is ###.####MS:
10 PRINTUSING "The answer is ###.####"; 12.345I suppose that the MS form can be more powerful in that the format string can be specified by a string variable, which itself can be dynamically computed, whereas the Wang format string was static. However, that type of thing is unusual, and the benefit of the Wang approach is that it is easier to build a set of format strings that have the proper relative alignment, like the COBOL PIC statement.
Assorted other commands (link)
Wang continually enhanced Wang BASIC by adding more commands. In the last incarnation before BASIC-2, a bizarre assortment of "General I/O Statements" was added. Only a brief hint of the purpose is given here.
Group | Command | Explanation |
---|---|---|
General I/O: | ||
$GIO ... | general I/O microcommand | |
$IF ... | test ready condition of I/O device | |
$TRAN ... | translate characters | |
$PACK ... | pack data | |
$UNPACK ... | unpack data | |
Plotter: | ||
PLOT <X,Y,"Title">, <40,60,A$> | Besides a string literal, the third argument of each 3-tuple could also be one of U, D, S, C, R (pen up, pen down, set horizontal and vertical spaces, set character size, reset to zero). | |
Plotter, card reader, tape punch: | ||
DATASAVE BT ... | block-level transfer | |
DATALOAD BT ... | block-level transfer |
A further word on the $GIO instruction. This instruction defines a pseudo-microcode format for performing high-speed, low-level operations. These instructions are actually interpreted and aren't directly executed, but it is still many times faster than if such a thing were to be done using BASIC. For example, via small microcode programs one can control I/O devices that were released after the BASIC was frozen, such as reel-to-real tape devices, modems, and data loggers.
This idea is in some ways very similar to the SWEET-16 interpreter embedded into the original Apple-II ROMs, although Apple did it for reasons of code density, for neither speed nor flexibility.
Disk commands (link)
The disk commands of Wang BASIC are rather awkward. The file structure of the disk is exposed, and the programmer had the choice of operating at the sector level or using a "cataloged" disk approach. Many disk commands come in two flavors, one to operate through the catalog structure, the other specified direct sector-level requests.
Command | Explanation |
---|---|
COPY | copy sectors from one platter to another |
DATALOAD BA | read one sector into the specified array |
DATALOAD DA | read a logical record from a given sector |
DATALOAD DC | read logical record from cataloged disk file |
DATALOAD DC | OPEN F open a cataloged disk file |
DATASAVE BA | write one sector |
DATASAVE DA | write a logical record to a given sector |
DATASAVE DC | save logical record to cataloged disk file |
DATASAVE DC | CLOSE close cataloged file |
DATASAVE DC | OPEN open cataloged file |
DBACKSPACE | backspace a number of records or sectors |
DSKIP | skip the number of logical records or sectors |
LIMITS | obtain start & end addresses, number of sectors in file |
LIST DC | list contents of catalog index |
LOAD DA | load program starting from specified sector |
LOAD DC | load program from cataloged file |
MOVE | catalog manipulation |
SCRATCH | change the file status of the named disk files |
SCRATCH DISK | reserve space on disk |
VERIFY | Verify data in a given range of sectors |