' ABCD interpr etor
' Coded by Larry R. Lowe in QB64 for windows 10
' Original ABC Esoteric Programming language created by orange, a user from the esolang wiki at https://esolangs.org/wiki/ABC
' This interpretor is the original ABC programming language with different 1 single character commands, and a few extra ones thrown in
' This version has among other things a second independant accumulator, and choice blocks.
' ! - Toggle remark mode on or off. When on everything between the first ! and the second ! is a comment
' # - runs the file specified between the % signs
' $ - Toggle ASCII output mode. When on, the c instruction prints the first accumulator as an ASCII character, if it is >0 and <256.
' % - toggle the next filename to run block on or off
' & - Toggle the direction of the multiplication or division of the first accumulator.
' * - Toggle direction of first accumulator. When on, a + command decreases the first accumulatorm and when off a + command increases the first accumulator
' ; - Debug. Prints out first accumulator as a number and ascii character.
' ? - Set first accumulator to a random number between 0 and first accumulator
' ^ - prints a space
' | - clear the screen
' + - Increase or decrease the value of the first accumulator
' < - Invert first accumulator
' > - Output the first accumulator
' 0 - Begin/ end choice0 block containing a file name to begin interpreting if 0 is pressed
' 1 - Begin/ end choice1 block containing a file name to begin interpreting if 1 is pressed
' 2 - Begin/ end choice2 block containing a file name to begin interpreting if 2 is pressed
' 3 - Begin/ end choice3 block containing a file name to begin interpreting if 3 is pressed
' 4 - Begin/ end choice4 block containing a file name to begin interpreting if 4 is pressed
' 5 - Begin/ end choice5 block containing a file name to begin interpreting if 5 is pressed
' 6 - Begin/ end choice6 block containing a file name to begin interpreting if 6 is pressed
' 7 - Begin/ end choice7 block containing a file name to begin interpreting if 7 is pressed
' 8 - Begin/ end choice8 block containing a file name to begin interpreting if 8 is pressed
' 9 - Begin/ end choice9 block containing a file name to begin interpreting if 9 is pressed
' a - Increase or decrease the value of the second accumulator
' b - Increrment the background color number by 1
' c - decrerment the background color number by 1
' d - multiply the second accumulator by 1, 5 or 10
' e - toggle the amount to increase or decrease the first accumulator by 1, 5 orf 10
' f - Increrment the foreground color number by 1
' g - decrerment the foreground color number by 1
' h - Toggle ASCII output mode. When on, the c instruction prints the second accumulator as an ASCII character, if it is >0 and <256.
' i - Set second accumulator to a random number between 0 and second accumulator
' k - resets the foreground color to 0
' l - Loop back to the beginning of the program. first accumulator and ASCII mode does not reset.
' m - resets the background color to 0
' n - prints a newline
' o - changes the foreground and background to the colors specified by the k, m, f, g, b and c commands
' p - Toggle direction of second accumulator. When on, an a command decreases the second accumulatorm and when off an a command increases the second accumulator
' r - Set first accumulator to 0
' t - Output the second accumulator
' u - Invert second accumulator
' v - Toggle the direction of the multiplication or division of the second accumulator. When off the x command multiplies the first accumulator by 1, 5 or 10, when on it divides it by 1, 5 or 10
' w - toggle the amount to increase or decrease the second accumulator by 1, 5 orf 10
' x - multiply the first accumulator by 1, 5 or 10
' z - Set second accumulator to 0
' H - Print Hello World
' ) - starts a cat block for use in writing a cat pgogram
' K - waits until ther user presses 0 througgh 9. It works with the above listed choice blocks. At least 1 choice block must be in the source code to use the K command.
' j - move the source code pointer up 1 line
' J - move the source code pointer down 1 line
' s - move the source code pointer left 1 character
' S - move the source code pointer right 1 character
' A -
' B -
' C -
' D -
' E -
' F -
' G -
' H -
' I -
' L -
' M -
' B -
' O -
' P -
' Q -
' q -
' R -
' T -
' U -
' V -
' W -
' X -
' Y -
begin:
' Here we mak it full screen. If it looks like it is going to be unstable, or if it screws up, just remove these 2 lines
'_FULLSCREEN
DIM prog$
(50000), a$
(50000)
row = 1: col = 1
fc = 7 ' foreground color variable
bc = 0 ' bsackground color variable
x = 0 ' index for an array to load in the prgoram 1 line at a time
ln = 1 ' starting line of code to begin interpreting
acc = 0 ' first accumulator variable
acc2 = 0 ' second accumulator variable
aom = 0 ' variable to hold first accumulator output mode
aom2 = 0 ' variable to hold second accumulator output mode
p = 1 ' variable to hold the number representing which character in the line we are interpreting
plus = 1 ' variable to hold the amount added to or subtracted from the first accumulator
plus2 = 1 ' variable to hold the amount added to or subtracted from the second accumulator
ad = 0 ' sets the first accumulator direction mode 0 =add 1 = subtract
ad2 = 0 ' sets the second accumulator direction mode 0 =add 1 = subtract
mul = 0
mul2 = 0
fm = 0
lem = 0
lem2 = 0
c0 = 0
c1 = 0
c2 = 0
c3 = 0
c4 = 0
c5 = 0
c6 = 0
c7 = 0
c8 = 0
c9 = 0
cat = 0
ptjt = 0
ltjt = 0
cm = 0 ' variable to hold the comment mode 0 = not the beginning of a comment 1 = beginning of comment
'The "!" toggles this cm variable
' This routine is where we get the command line to determine if the user gave the interpretor a file name to work with.
filename$ = "hello world-6.abcd"
load:
' here we load a systems file coded in ABCD itself, to tell the user that a file name is required on the command line.
' it is for that reason, you can't just click on the ABCD icon and expect to get results.
' We will open the file in sequential access mode and read it in one line at a time
x = x + 1
tlns = x
x = 1
' now that we have the source code read into the computer's memory,
' we start at line 1 and we go from the beginning of it to the end of it
' one character at a time because all commands are single characters in length.
' We now parse each character so it does not matter if our source code is all
' on one line, or if it is broken up into many lines.
parse:
m$
= MID$(prog$
(ln
), p
, 1)
' Here we do what is necessary if we find a block.
' The !, @, 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9 characters
' are block commands. A block must contain one of these
' commands followed by the required information, and then
' end with the same command. A comment block starts and
' ends with the ! character. Everything between the two
' exclamation points is ignored by the interpretor as it
' is a comment.
IF c0
= 1 AND m$
<> "0" THEN choice0$
= choice0$
+ m$:
GOTO advance
IF c1
= 1 AND m$
<> "1" THEN choice1$
= choice1$
+ m$:
GOTO advance
IF c2
= 1 AND m$
<> "2" THEN choice2$
= choice2$
+ m$:
GOTO advance
IF c3
= 1 AND m$
<> "3" THEN choice3$
= choice3$
+ m$:
GOTO advance
IF c4
= 1 AND m$
<> "4" THEN choice4$
= choice4$
+ m$:
GOTO advance
IF c5
= 1 AND m$
<> "5" THEN choice5$
= choice5$
+ m$:
GOTO advance
IF c6
= 1 AND m$
<> "6" THEN choice6$
= choice6$
+ m$:
GOTO advance
IF c7
= 1 AND m$
<> "7" THEN choice7$
= choice7$
+ m$:
GOTO advance
IF c8
= 1 AND m$
<> "8" THEN choice8$
= choice8$
+ m$:
GOTO advance
IF c9
= 1 AND m$
<> "9" THEN choice9$
= choice9$
+ m$:
GOTO advance
IF cat
= 0 AND m$
= ")" THEN cat
= 1: cat$
= cat$
+ m$:
GOTO advance
acc = acc + plus
acc = acc - plus
acc = acc * plus
acc = acc / plus
acc2 = acc2 + plus
acc2 = acc2 - plus
acc2 = acc2 * plus2
acc2 = acc2 / plus2
tmp$
= tmp$
+ MID$(acc$
, i
, 1)
tmp$
= tmp$
+ MID$(acc$
, i
, 1)
plus = 5
plus = 10
plus = 1
plus2 = 5: 'GOTO advance
plus2 = 10: 'GOTO advance
plus2 = 1: 'GOTO advance
getnum:
acc = ntg
getnum2:
acc2 = ntg2
getnum3:
acc = ntg
' This is the routine where we wait for the user to press only the keys 0-9, nad thehn we load a new source code based on what they chose.
' There must be at least one choice block in your code, otherwise the interpretor does not have any source code file to interpret at that
' point and will crash.
_LIMIT 30 'play nice with your CPU and other apps while waiting on the user to press their key IF z$
= "0" THEN filename$
= choice0$
IF z$
= "1" THEN filename$
= choice1$
IF z$
= "2" THEN filename$
= choice2$
IF z$
= "3" THEN filename$
= choice3$
IF z$
= "4" THEN filename$
= choice4$
IF z$
= "5" THEN filename$
= choice5$
IF z$
= "6" THEN filename$
= choice6$
IF z$
= "7" THEN filename$
= choice7$
IF z$
= "8" THEN filename$
= choice8$
IF z$
= "9" THEN filename$
= choice9$
' go up a line of code
' this is a cursor command
' IF ln = 1 THEN
' GOTO advance2
' END IF
' IF ptmt = 0 AND ltmt = 0 THEN
' ptmt = p
' ltmt = ln
' END IF
' ltmt = ltmt - 1
' go down a line of code
' CASE "J"
' this is a cursor command
' IF ln = tlns THEN
' GOTO advance2
' END IF
' IF ln = 50000 THEN
' GOTO advance2
' END IF
' IF ptmt = 0 AND ltmt = 0 THEN
' ptmt = p
' ltmt = ln
' END IF
' ltmt = ltmt + 1
' go left one character within the current line
' CASE "s"
' this is a cursor command
' IF p = 1 THEN
' GOTO advance
' END IF
' IF ptmt = 0 AND ltmt = 0 THEN
' ptmt = p
' ltmt = ln
' END IF
' ptmt = ptmt - 1
' go right one character within the current line
' CASE "S"
' this is a cursor command
' IF p = LEN(prog$(ln)) THEN
' GOTO advance
' END IF
' IF ptmt = 0 AND ltmt = 0 THEN
' ptmt = p
' ltmt = ln
' END IF
' ptmt = ptmt + 1
p = ptmt
ln = ltmt
CASE ELSE ' This routine ignores everytthing else that is not a command and just moves on.
' The routines advance is where we move to the next character in the string that is the current line of code
' When we reach the end of the line, the advance2 routine moves to the next line and reset the position to the
' first character and start from there.
advance:
p = p + 1
advance2:
ln = ln + 1: p = 1
filename$
= nfn$: nfn$
= "": x
= 0: p
= 1: ln
= 1:
GOTO load
filename$
= nfn$: nfn$
= "": x
= 0: p
= 1: ln
= 1:
GOTO load
END ' this is only a logic end because the previouse line of code never arrives here!
FUNCTION MovingCursor
(ln
, p
, LC$
, TLines
) ' parser of cursor metacommand
MovingCursor = 0 ' no moving commands
' we preserve the value of parameters
cursor = p
lines = ln
Codex$ = LC$
lCursor = 0 'local cursor of line of moving commands
'parsing the line of code for command of move cursor
lCursor = lCursor + 1
MoveCursor$
= MID$(Codex$
, lCursor
, 1) ' these commands don't let go out of range as showed in the main
' so if you have the cursor at point 30 and you go back for 32 times
' you'll be at position 1 of the line and not to the previous line of code
' in the same manner for going up or down the lines of code
IF lines
> 1 THEN lines
= lines
- 1 IF lines
< 50000 AND lines
< TLines
THEN lines
= lines
+ 1 IF cursor
> 1 THEN cursor
= cursor
- 1 cursor = cursor + 1
' we put back the value of cursor to execut normal commands
p = cursor
ln = lines
MovingCursor = -1 ' function has worked without error