Yet another small BASIC interpreter for the 6502

Programming the 6502 microprocessor and its relatives in assembly and other languages.
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Yet another small BASIC interpreter for the 6502

Post by BillG »

While some of you were talking about the tiniest Tiny BASIC, I have been busy paraphrasing TSC Micro BASIC Plus to the 6502.

https://ia903409.us.archive.org/34/item ... asic_a.pdf

It is a relatively powerful integer BASIC running on the SWTPC 6800 computer. It was designed to be loaded from tape. User programs may be saved or loaded by escaping to the system monitor and using its "punch" and "load" capabilities, then warm starting back into the interpreter.

I am happy to be able to report that enough progress has been made that it is an ongoing project instead of a speculative experiment.

The following features have been implemented:

* Enter, list, delete and replace program lines
* Run program
* Print a number, variable or a constant text string (it does not support string variables)
* Assign a number or a variable to a variable including "implied" LET
* GOTO, GOSUB, RETURN, ON GOTO and ON GOSUB

I am currently working on FOR and NEXT.

Features still to be implemented:

* Most of expression handling including operators and the functions RND, ABS and SGN
* DIM for arrays
* IF
* DATA, READ and RESTORE
* INPUT

The original 6800 version utilizes self-modifying code in several places so it cannot reside in ROM. I do not do any of that.

Micro BASIC Plus allows use of a variable or expression as the target of a GOTO or GOSUB. You can write code like:

Code: Select all

100 A = 1000
200 GOTO A
300 END
1000 PRINT 1000
As far as I know, no other BASIC can do this. Not even Microsoft.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by GARTHWILSON »

This line was kind of funny:
"Spaces are not permitted i nternal to numbers or keywor ds but may be used freel y el sewhere."

BillG wrote:
Micro BASIC Plus allows use of a variable or expression as the target of a GOTO or GOSUB. You can write code like:

Code: Select all

100 A = 1000
200 GOTO A
300 END
1000 PRINT 1000
As far as I know, no other BASIC can do this. Not even Microsoft.
I had to check the reference manual for my HP-71's BASIC.  It does not have that, but I normally used labels anyway rather than line numbers, and for a GOTO's label identifier, you can use anything that evaluates to a string.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
gilhad
Posts: 86
Joined: 26 Jan 2024
Location: Prague; Czech Republic; Europe; Earth
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by gilhad »

BillG wrote:
As far as I know, no other BASIC can do this. Not even Microsoft.
BBC Micro BASIC had it and when I was lookin for it online, I found this manual

https://www.4corn.co.uk/archive/docs/BB ... al-opt.pdf see here, on page numbered 84 (95. page of the PDF, but it is counting preface and index too)
Quote:
GOTO instructions send the control of the program either forwards or backwards
The specified line number may be given as an expression For example

10 Start:% = 100
20 GOTO (start%+10)
30 PRINT " This line should not be executed "
100 REM start of the action
110 PRINT " Hello"
120 END

Using a variable, however, as the destination for a GOTO is not recommended
because while RENUMBER changes the line numbers. it does not alter GOTO
destinalions that are given as anything other than a simple number. lf you must
use an expression. it is best to put in inside brackets since BASIC may get
confused if the expression starts with a number.
User avatar
BigDumbDinosaur
Posts: 9426
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by BigDumbDinosaur »

GARTHWILSON wrote:
BillG wrote:
Micro BASIC Plus allows use of a variable or expression as the target of a GOTO or GOSUB. You can write code like:

Code: Select all

100 A = 1000
200 GOTO A
300 END
1000 PRINT 1000
As far as I know, no other BASIC can do this. Not even Microsoft.
I had to check the reference manual for my HP-71's BASIC.  It does not have that, but I normally used labels anyway rather than line numbers, and for a GOTO's label identifier, you can use anything that evaluates to a string.
Most dialects of business BASIC from the later 1980s and onward, such as the Thoroughbred Dictionary-IV environment in which I’ve done a lot of development, allow the use of labels as GOTO and GOSUB targets.  Writing GOSUB PRINT is not only more informative than writing GOSUB 1000, it’s faster-executing.

Thoroughbred, in particular, builds several alphanumerically-sorted symbol tables at the end of the program text, one of which is a lookup table for statement labels—these tables are saved as part of the program, so they only get built while entering/editing program code.  When a GOSUB PRINT statement is encountered, the Thoroughbred P-code engine does a binary search on the statement symbol table.  Needless to say, that is a much faster process than in a typical micro-BASIC interpreter that has to scan program text to find a line number.  If in a Thoroughbred program, the statement GOSUB 1000 is encountered, the P-code engine has to search the program text for the actual line number, which perceptively slows down a program that makes a lot of such calls.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by drogon »

BillG wrote:
Micro BASIC Plus allows use of a variable or expression as the target of a GOTO or GOSUB. You can write code like:

Code: Select all

100 A = 1000
200 GOTO A
300 END
1000 PRINT 1000
As far as I know, no other BASIC can do this. Not even Microsoft.
It's pretty standard in TinyBasics - my own one works like this too. Here is a example from my xmas tree lights on the 6507:

Code: Select all

2IF L<0 OR L >17 RETURN
3GOTO10+L

5IF L<0 OR L >17 RETURN
6GOTO30+L

REM On

10?A=?A OR&10:RETURN
11?A=?A OR&01:RETURN
12?A=?A OR&40:RETURN
13?A=?A OR&08:RETURN

14?A=?A OR&04:RETURN
15?A=?A OR&02:RETURN
16?A=?A OR&20:RETURN
17?A=?A OR&80:RETURN

18?B=?B OR&80:RETURN
19?B=?B OR&02:RETURN
20?B=?B OR&10:RETURN
21?P=?P AND&F1OR&0E:RETURN

22?B=?B OR&04:RETURN
23?B=?B OR&40:RETURN
24?B=?B OR&20:RETURN
25?B=?B OR&08:RETURN

26?P=?P AND&1EOR&E0:RETURN
27?B=?B OR&01:RETURN
It works in the main program as:

Code: Select all

  L = 5 : REM Set Lamp 5 ON
  GOSUB 2
-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: Yet another small BASIC interpreter for the 6502

Post by BillG »

Got bogged down in NEXT as it makes use of the ADD and SUB parts of the complex and voluminous expressions and operators package.

Took a detour and implemented INPUT then DATA, READ and RESTORE.

The Micro BASIC Plus rendering of DATA statements is quite different from other BASICs.

In most of the others, all of the DATA statements within a program are treated as if they were one data pool.

Micro BASIC Plus remembers the most recently encountered DATA statement as the "current" data pool. An error results if READ is used before any DATA statement has been encountered. Reading more values than exists in the current statement restarts at the first item in the statement. RESTORE also sets the next READ to get that first item.

It is not clear why it was done this way. Existing code to search the program for a line number can be easily modified to search for DATA statements. Maybe they were tight on code space and could not afford that.

The only advantage I can see is that data can be localized to the code which uses it. Some other BASICs allow specifying a line number with the RESTORE statement to indicate where the next READ picks up. That would be an equivalent way to do the same thing.
dmsc
Posts: 154
Joined: 17 Sep 2018

Re: Yet another small BASIC interpreter for the 6502

Post by dmsc »

Hi!
BillG wrote:
Micro BASIC Plus allows use of a variable or expression as the target of a GOTO or GOSUB. You can write code like:

Code: Select all

100 A = 1000
200 GOTO A
300 END
1000 PRINT 1000
As far as I know, no other BASIC can do this. Not even Microsoft.
This is standard in Atari BASIC, where you even see code like GOTO STICK(0)*10+200 for processing the joystick. In Atari BASIC each number is encoded in 6 bytes, so doing "L1000=1000" and then multiple "GOTO L1000" used less memory, this technique was used in a lot of BASIC games.

Have Fun!
Uncle Warthog
Posts: 14
Joined: 24 Oct 2017

Re: Yet another small BASIC interpreter for the 6502

Post by Uncle Warthog »

Apple integer BASIC (and, I assume Apple 1 basic which it was derived from) allows this as well.
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: Yet another small BASIC interpreter for the 6502

Post by BillG »

Thank you for enlightening me as to which BASICs also allow specifying a target with a variable expression.

Now why do some prohibit that? Clearly it is slower than an absolute line number. Why not just document that fact and allow it anyway?

The compiler writer in me says that compiling a variable target is much more difficult. Essentially, a list of the addresses corresponding to the set of line numbers much be stored and searched when the jump is made.

By the way, FOR/NEXT now works for the simple case. More testing is needed. I can see the finish line from here...
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by drogon »

BillG wrote:
Thank you for enlightening me as to which BASICs also allow specifying a target with a variable expression.

Now why do some prohibit that? Clearly it is slower than an absolute line number. Why not just document that fact and allow it anyway?
I suspect it's explicitly tested for - ie. when you parse a GOTO/GOSUB then you either look for a number explicitly, or almost lazily just call your generic expression evaluator to get that number. Once you have then number the rest of the processing is the same.

And if you can GOTO an expression then it eliminates the need for ON x GOTO a,b,c ...

Or conversely if you really want ON x GOTO, then deliberately block GOTO expression...
Quote:
The compiler writer in me says that compiling a variable target is much more difficult. Essentially, a list of the addresses corresponding to the set of line numbers much be stored and searched when the jump is made.
But in BASICs you have a generic expression evaluator, so you save space by just calling it to get the number. There are very few BASICs that store a separate list of line numbers -> addresses. Most (at least in the 8-bit world) have just a line number and end of line token, or line number + length. The latter is in my TinyBasic - so GOTO/GOSUB involves a linear search, but at least it can skip lines as it knows their length.

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: Yet another small BASIC interpreter for the 6502

Post by BillG »

drogon wrote:
BillG wrote:
Thank you for enlightening me as to which BASICs also allow specifying a target with a variable expression.

Now why do some prohibit that? Clearly it is slower than an absolute line number. Why not just document that fact and allow it anyway?
I suspect it's explicitly tested for - ie. when you parse a GOTO/GOSUB then you either look for a number explicitly, or almost lazily just call your generic expression evaluator to get that number. Once you have then number the rest of the processing is the same.

And if you can GOTO an expression then it eliminates the need for ON x GOTO a,b,c ...
ON GOTO is arguably a bit more "structured" because the number of possible targets is limited. GOTO X can go anywhere...
drogon wrote:
Quote:
The compiler writer in me says that compiling a variable target is much more difficult. Essentially, a list of the addresses corresponding to the set of line numbers much be stored and searched when the jump is made.
But in BASICs you have a generic expression evaluator, so you save space by just calling it to get the number. There are very few BASICs that store a separate list of line numbers -> addresses. Most (at least in the 8-bit world) have just a line number and end of line token, or line number + length. The latter is in my TinyBasic - so GOTO/GOSUB involves a linear search, but at least it can skip lines as it knows their length.
I was talking about compiling the program into a binary image. There is no source code, even in tokenized form, to search.

Another of my many projects is a BASIC compiler to translate a program written in the TSC FLEX BASIC or XBASIC dialect into 6800 or 6502 assembly language.

The initial prototype generated code at the beginning of each line of source to store the line number into a variable for error reporting. Later versions quit doing that, but generated a list of line number/address couplets which is binary searched in case of error reporting. The run-time overhead is moved from normal execution to only in case there is an error.
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Yet another small BASIC interpreter for the 6502

Post by barrym95838 »

Run-time error reporting in an 8-bit compiled binary? That's very fancy, at least in my limited experience. How common is that, really?
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Yet another small BASIC interpreter for the 6502

Post by barrym95838 »

drogon wrote:
Most (at least in the 8-bit world) have just a line number and end of line token, or line number + length. The latter is in my TinyBasic - so GOTO/GOSUB involves a linear search, but at least it can skip lines as it knows their length.
I added the length feature to VTL02, and included a condition that would allow "find" to start the linear search at the next line rather than the first line, making forward "GOTO"s less clunky. It worked so well that I decided to re-use it to find the next line during normal execution as well, at the expense of a handful of clocks.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
BillG
Posts: 710
Joined: 12 Mar 2020
Location: North Tejas

Re: Yet another small BASIC interpreter for the 6502

Post by BillG »

barrym95838 wrote:
Run-time error reporting in an 8-bit compiled binary? That's very fancy, at least in my limited experience. How common is that, really?
ON ERROR needs to know the number of the line executing when an error occurs so that it can RESUME back to the correct line. Since that information is already available, an unhandled error is reported with the error number along with the number of the line.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: Yet another small BASIC interpreter for the 6502

Post by drogon »

barrym95838 wrote:
drogon wrote:
Most (at least in the 8-bit world) have just a line number and end of line token, or line number + length. The latter is in my TinyBasic - so GOTO/GOSUB involves a linear search, but at least it can skip lines as it knows their length.
I added the length feature to VTL02, and included a condition that would allow "find" to start the linear search at the next line rather than the first line, making forward "GOTO"s less clunky. It worked so well that I decided to re-use it to find the next line during normal execution as well, at the expense of a handful of clocks.
It might be interesting to know just how many forward references there are in a program - however this may vary during writing of that program. Would the overhead of saying "is the target greater than the current line number, or less than or equal?" and picking the appropriate algorithm worth the time to do the test and the extra RAM needed (in a minimal RAM system) ?

I think you might need a good selection of old BASIC programs to find out...

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
Post Reply