Is it still alive?
Is it still alive?
The last version of 6502 EhBASIC on Lee's website is 2.09, dated 2005. Is the project still under development? Any plans? Has the website moved?
-
leeeeee
- In Memoriam
- Posts: 347
- Joined: 30 Aug 2002
- Location: UK
- Contact:
DaveK wrote:
The last version of 6502 EhBASIC on Lee's website is 2.09, dated 2005. Is the project still under development? Any plans? Has the website moved?
kc5tja wrote:
I think that it's simply "mature technology."
EhBASIC as it is has gone quite a way beyond that goal. Features I'd always wanted from a BASIC such as the ability to easily use hex and binary in the code and for input and output were added. Commands were added that made coding for hardware easier as were commands that made writing code itself easier.
Version 2.xx came with the lessons learned in coding a Motorola 68K version from scratch and, while it looks outwardly very similar to 1.xx versions, internally it changed quite a bit and became a fair bit quicker. 2.09 is the last completed version and while it can probably be improved it works better than I ever expected when I started sometime in the last millenium.
I do plan a similar but expanded version for the 65816 but not having an assembler/simulator like Michal Kowalski's simulator for the 6502 and having all of my 65816 hardware in storage, along with a lot of other things, until I finally sell this place and move has precluded any real progress on that to date.
If there's any undocumented feature that needs addressing I'm always up for that, EhBASIC isn't abandoned, it's just .. resting.
Lee.
-
leeeeee
- In Memoriam
- Posts: 347
- Joined: 30 Aug 2002
- Location: UK
- Contact:
How to add a new command to EhBASIC.
As this is a primary command, it can start a statement, first insert a new entry into the list of primary command tokens. It doesn't particularly matter where in the list.
E.g.
.. becomes ..
Next put a corresponding new entry in the command vector table that starts at LAB_CTBL. This must be in the same relative location as the token value.
E.g.
.. becomes ..
Now add an entry in the keyword tables.
E.g.
.. becomes ..
In this case there are already keywords that start with "P" so it's just a case of adding this one entry but if you were adding a keyword that starts with a so far unused letter then you also need to add entries in the first character table at TAB_1STC and in the character pointers table at TAB_CHRT and make a new character table for your entry.
Next you need to add an entry in the LIST decode table, this again must be in the same relative location as the token value.
E.g.
.. becomes ..
The last thing to add is the code for the new command which should be the same as the code you used for the CALL version but without the first scan for the comma. So instead of say using LAB_SCGB, scan for "," and get byte, you could use LAB_GTBY, get byte parameter, to get the X value.
.. and that should do it.
Not that difficult but wastefull of space and speed, unless you want variable length names and then it does get more awkward. The first two significant characters give you over 3000 different variables of each type and you can append any number of other characters of your choice as long as you avoid keywords.
Lee.
As this is a primary command, it can start a statement, first insert a new entry into the list of primary command tokens. It doesn't particularly matter where in the list.
E.g.
Code: Select all
TK_DOKE = TK_POKE+1 ; DOKE token
TK_CALL = TK_DOKE+1 ; CALL token
TK_DO = TK_CALL+1 ; DO token
TK_LOOP = TK_DO+1 ; LOOP tokenCode: Select all
TK_DOKE = TK_POKE+1 ; DOKE token
TK_CALL = TK_DOKE+1 ; CALL token
TK_PLOT = TK_CALL+1 ; PLOT token new command entry
TK_DO = TK_PLOT+1 ; DO token modified entry
TK_LOOP = TK_DO+1 ; LOOP tokenE.g.
Code: Select all
.word LAB_POKE-1 ; POKE
.word LAB_DOKE-1 ; DOKE
.word LAB_CALL-1 ; CALL
.word LAB_DO-1 ; DOCode: Select all
.word LAB_POKE-1 ; POKE
.word LAB_DOKE-1 ; DOKE
.word LAB_PLOT-1 ; PLOT new command
.word LAB_CALL-1 ; CALL
.word LAB_DO-1 ; DOE.g.
Code: Select all
LBB_PI
.byte "I",TK_PI ; PI
LBB_POKE
.byte "OKE",TK_POKE ; POKECode: Select all
LBB_PI
.byte "I",TK_PI ; PI
LBB_PLOT
.byte "LOT",TK_PLOT ; PLOT new command keyword
LBB_POKE
.byte "OKE",TK_POKE ; POKENext you need to add an entry in the LIST decode table, this again must be in the same relative location as the token value.
E.g.
Code: Select all
.byte 4,'P'
.word LBB_POKE ; POKE
.byte 4,'D'
.word LBB_DOKE ; DOKE
.byte 4,'C'
.word LBB_CALL ; CALL
.byte 2,'D'
.word LBB_DO ; DOCode: Select all
.byte 4,'P'
.word LBB_POKE ; POKE
.byte 4,'D'
.word LBB_DOKE ; DOKE
.byte 4,'P' ; new keyword length and first character
.word LBB_PLOT ; PLOT new keyword pointer
.byte 4,'C'
.word LBB_CALL ; CALL
.byte 2,'D'
.word LBB_DO ; DO.. and that should do it.
Quote:
Longer variable names would be nice but probably difficult to change.
Lee.
The earliest Forth systems represented word names using the first three characters plus a length byte. This allowed a single 32-bit compare instruction to isolate the overwhelming majority of words when performing a dictionary lookup.
Maybe the same technique would apply for BASIC variable names as well. For example, you could have two variables PLOT (pointer to the graphics plot routine) and PLOTLINE (pointer to some line drawing code). Both variables would start with the PLO prefix, but they'd be further disambiguated by the length byte (4 in the former case, 8 in the latter).
A collision occurs only when you share both a common prefix and length. Hence, A=PLOXXXXX and A=PLOTLINE both assign the same value to A.
Yes, this is a very crude form of hashing the variable name.
Just an idea though.
Maybe the same technique would apply for BASIC variable names as well. For example, you could have two variables PLOT (pointer to the graphics plot routine) and PLOTLINE (pointer to some line drawing code). Both variables would start with the PLO prefix, but they'd be further disambiguated by the length byte (4 in the former case, 8 in the latter).
A collision occurs only when you share both a common prefix and length. Hence, A=PLOXXXXX and A=PLOTLINE both assign the same value to A.
Yes, this is a very crude form of hashing the variable name.
Just an idea though.
leeeeee wrote:
The first two significant characters give you over 3000 different variables of each type and you can append any number of other characters of your choice as long as you avoid keywords.
Lee.
Lee.
Thankfully, if you're crafty with arrays, you can make yourself a stack, and implement your own support for abstraction. It's wordy to do, but it works -- I had to do it for many a VisualBasic application before VB learned proper abstraction constructs.
The technique applies to multiple data types too:
Code: Select all
10 DIM S$(10),I(10)
20 SP=10:IP=10
30 SP=SP-1:S$(SP)="HELLO WORLD"
40 GOSUB 100:REM SP=10, I=9 AT THIS POINT
50 PRINT "THE LENGTH OF THE STRING IS:";I(IP)
60 IP=IP+1:END
100 IP=IP-1:I(IP)=LEN(S$(SP)):SP=SP+1:RETURN
Code: Select all
10 DIM I(30):REM a simple stack of integers (effectively infinite depth)
11 IP=29:REM Integer stack pointer
...
999 REM A trivial addition example
1000 I(IP+1)=I(IP+1)+I(IP):IP=IP+1:RETURN
1999 REM ( a b c -- z -z ) compute the quadratic formula
2000 T = (-(I(IP+1)) + sqrt((I(IP+1))**2 - 4*(I(IP+2))*(I(IP)))) / 2*(I(IP+2))
2010 I(IP+2)=T:I(IP+1)=-T:IP=IP+1:RETURN
Code: Select all
100 IP=IP-3
110 I(IP+2)=(a)
120 I(IP+1)=(b)
130 I(IP)=(c)
140 GOSUB 2000
150 REM I(IP) contains -z, I(IP+1) contains +z
I also wanted to add:
The technique can be applied to multiple data types as well.
Obviously, you'll want to use LEN() to compute the length of a string. I'm merely illustrating that using stacks like this in BASIC prove powerful enough to compute arbitrary lambda expressions.
Remember, the original version of Smalltalk was written in BASIC!
The technique can be applied to multiple data types as well.
Code: Select all
10 DIM S$(100),I(100):REM THE STACKS
20 SP=100:IP=100:REM THE STACK POINTERS
30 REM FIND THE LENGTH OF A STRING.
40 SP=SP-1:S$(SP)="HELLO WORLD!"
50 GOSUB 1000
60 PRINT "THE LENGTH OF THE STRING IS: ";I(IP)
70 IP=IP+1
80 END
1000 REM JUST TO PROVE IT CAN BE DONE, WE FIND
1001 REM THE LENGTH OF THE STRING THE HARD WAY:
1002 REM RECURSIVELY!
1003 REM THIS IMPLEMENTS THE FOLLOWING EQUATIONS:
1004 REM LEN "" = 0
1005 REM LEN S = 1+(LEN (TAIL S))
1010 IF S$(SP)="" THEN IP=IP-1:I(IP)=0:SP=SP+1:RETURN
1020 SP=SP-1:S$(SP)=MID$(S$(SP+1),1):GOSUB 1000
1030 I(IP)=I(IP)+1:RETURN
Remember, the original version of Smalltalk was written in BASIC!