Apple BASIC (BYTE 1977:5 p34) Apple-II BASIC is implemented as a translator-interpreter combination. When a line is read from the input device, the translator analyzes it and generates a more efficient internal language facsimile. Syntax errors are detected at this time. The "nouns" of this internal language are variable names, integer constants (preconverted to binary for execution speed enhancement), and string constants. The "verbs" are 1 byte tokens substituted for keywords, operators and delimiters. Because the translator distinguishes syntax, different verbs are assigned to different usages of the same symbol. For example, three distinct verbs represent the word PRINT, depending on whether it is immediately followed by a string stource, an arithmetic expression or nothing. Thus this distinction need not be made at execution time. For each verb there exists a subroutine to perform that specific action. Listing a program actually involves decompiling the internal language back to BASIC source code. Those statements with line numbers are stored as part of the user program, while those without line numbers are executed immediately. If desired, the Apple BASIC interpreter's editing functions can be set to generate line numbers automatically. Although some commands are valid only for immediate execution and others only for programmed execution, most can be employed in both ways. In the BASIC source programs, multiple statements may reside on the same line, separated by colons (':'). BASIC language statements are stored in user memory as they are accepted and variables are allocated space the first time they are encountered during immediate or programmed execution. When a program terminates, whether by completion, interruption or error conditions, all variables are preserved. Programs may be interrupted in execution by typing an ASCII control C; it is then possible to examine and modify a few variables in immediate mode, then continue execution at the point of interruption by typing the CONtinue command. BASIC provides the line number of the statement as the point of interruption when this sequence is used. The entire variable space is cleared to zero when BASIC is initialized by the CLR command, and prior to executing the RUN command. (It is possible to carry variables from one program to another, but to initiate the second program a GOTO command must be used instead of RUN in order to override the automatic clear at the beginning of execution of a new program.) The interpreter consists of a standard expression evaluator and a symbol table routine for allocating variable storage similar to those described by Prof Maurer in his 2 part series in the February and March 1976 issues of BYTE. As statements are scanned, nouns and verbs are encountered. Variable names result in calls to the symbol table routine which pushes address and length information on the noun stack (operand stack). Constants are pushed directly onto this stack. Verbs are pushed onto the verb stack (operator stack) after popping and executing any verbs of greater priority. A verb is executed by calling its associated subroutine. Tables define priorities and routine entry addresses for all verbs. Keywords such as THEN or STEP, and delimiters such as commas and parentheses, are dealt with just as though they were arithmetic operators. Verb routines obtain their arguments from the noun stack. Because verbs such as parentheses tend sometimes to be of low, and other times of high prioritiy, each verb is actually assigned two priorities (left hand-right hand). One represents its tendency to force execution of other verbs, the second its tendency to be executed. www.woz.org: Woz: My own BASIC was the hardest task of developing the Apple I and ][ computers. I'd never studied compiler/interpreter writing and had only practiced my ideas on paper before. I'd read some good books on the subject. I'd never programmed in BASIC before the Apple I. I just sniffed the air and decided that the games that would drive personal computers were written in BASIC. I picked up a manual at Hewlett Packard and used their variant of BASIC as my model. Either they had good substring syntax or I evolved my own based on theirs, but I much preferred it to the DEC style that Microsoft went with, using LEFT$ and MID$ and RIGHT$ functions. I laid out my syntax charts and made a decision to take floating point out so that I could finish slightly sooner and have the first BASIC for the 6502 processor ever. I mainly wanted it to be able to play games. Then I knew it was good enough for whatever else. I also wanted to program solutions to my Hewlett Packard engineering problems. That's where I worked as an engineer designing calculators. I could go on. The BASIC turned out extremely modular, so I could easily add something by adding some syntax descriptions in near-text form, and write routines for the new functions or ops that were needed. The language didn't have to be rewritten. Woz: I wrote the original Apple Integer BASIC. I had wanted it to be the very first BASIC for the 6502 microprocessor. I might then have something to be recognized for. I decided that it had to play games and let me solve engineering problems. I first wrote out a syntax with floating point but then figured that it might be done a few weeks sooner with just integers. I had to write it in the evenings as I worked at Hewlett Packard then. So I cut back to an integer BASIC that I called "Game BASIC". I'd never programmed in BASIC. My college had encountered Fortran, several machine languages, Algol, and a couple of special languages. But you could buy a book called "101 BASIC Games". Plus, the Gates/Allen BASIC was becoming the standard thing to get for your Altair computer, although very few people had these computers yet. I'd never writting a computer language or taken a course in it, although I'd studied books on my own touching on the topic. I have no idea to this day if I wrote it as anyone else would. I broke the entire language down into a syntax table that was stored in memory, in modified text form. A word like "PRINT" was stored as the 5 letters. If you were allowed an unsigned expression after some word, I stored a pointer to the syntax of that type of expression, which specified what it could be made of. Each line was compared, letter by letter, through this syntax table to see if there was any valid BASIC statement. I gave each symbol in the syntax table a particular code as on operator. The word "PRINT" might be operator number 5 and "FOR" might be operator number 13, etc. A plus sign had it's code too. A symbol like a minus sign might have two different codes depending on whether it was prefix (like -5) or infix (like 9-6). A variable or a number was an operand. I pushed the operand references onto one stack and operator codes onto another. But the operator codes each had 2 different priorities telling my BASIC whether to push them on top of the topmost operator already on the stack, or to pop that one off and generate the output program from it. Each operator had a value for it's tendency to push others off, and a value for it's resistance to being pushed off. For example, plus tends to push divide off, causing the division to happen first. Strangely all this works. Then I had to write one short routine for each of perhaps 100 operators. These included keywords like "PRINT", mathematical operators like 'plus', parenthesis, and other grammar symbols of BASIC. It took a couple of months to get the BASIC to this shape, with an engine that ran the whole thing. Then I would define a Syntax sentence in the syntax table, along with any routines for any new operator symbols. I would test it, get it working, and move on to the next syntax sentence for the next BASIC statement. From this point on, things were very modular and I was only writing very short programs. Well, the BASIC was a very big success. Especially when I was able to easily add statements and corresponding routines for color graphics and game commands in the Apple ][. Woz: I wrote it all in machine language without an assembler. It was the only way that I could afford. I looked at the sort of software that I wanted - games and puzzle solvers and logic simulators. Floating point wasn't the way to go here. My first syntax table was for floating point but I saw that I could make the language faster and tighter, and I could complete it perhaps a couple of weeks sooner, if I went integer only, so I backed off. Just because of this I did include some floating point routines in the Apple ][ ROM. Anyway, I used a condensed syntax chart to scan lines that were typed in, to allocate tokens corresponding the syntax elements of a good statement. The interpreted collection of tokens would be executed from left to right, with a couple of tables holding 'push' and 'pull' priorities for each token (operators, parens, etc.). Numbers and variable names weren't tokenized. This way I could just add commands or other items to a near-ASCII syntax table and then write small routines for each new token added. It was a very efficient approach that broke up a large task in a very orderly way. I'd never studied compiler writing. I'd just worked out ideas on my own back in college days. I had read some papers and books on it, but never wrote one before or did any homework or other exercises in this regard. I feel very lucky that I was able to do it. For me it was a larger task by far than both the Apple I and Apple ][ combined. The original version of this BASIC is in a binder in my own handwriting.