This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
LeDark Lua's profile picture

CCBASIC - C64 type BASIC in ComputerCraft!

Started by LeDark Lua, 04 December 2017 - 08:09 PM
LeDark Lua #1
Posted 04 December 2017 - 09:09 PM
ComputerCraft BASIC

What is BASIC?

BASIC( Beginner's All-purpose Symbolic Instruction Code ) is an interpreted programming language created in 1964 and was widely used in mid-1970s. For more information click on BASIC link above.

What kind of BASIC I am emulating?

Well I am emulating Commodore 64's BASIC

From where did I get the Idea to create one?

Well check this post then!


Okay Let's get started!

Typical BASIC Functions and Keywords

So to see all C64 functions, see this website: link.

Not implemented functions:
  • FRE
  • JOY
  • USR
  • VAL
  • PEEK
  • PEN
  • POS
  • POT
New Implemented Functions
  • BTN
  • CLEAR
  • COLOR
  • CURSOR
  • WRITE
  • STOREN
  • HEX
  • HIRES
  • LORES
  • PIXEL
  • SPRITE
  • REBOOT
  • SHUTDOWN
  • LABEL
  • FOPEN
  • FREAD
  • FREADLN
  • FWRITE
  • FWRITELN
  • FCLOSE
  • FEXISTS
  • FLIST
  • FRDONLY
  • FDEL
  • FISDIR
  • FLOAD
  • FCONEXT
  • FCOPREV
  • EXIT
  • DISPOSE
  • CREATETIMER
  • SETTIMER
  • GETTIMER
  • NETCREATE
  • NETOPEN
  • NETMYIP
  • NETRECEIVE
  • NETSEND
  • NETCLEARBUFFER
  • NETTYPE
  • NETMESSAGE
  • NETGETTYPE
  • NETGETMESSAGE
  • NETGETID
  • NETGETIP
  • NETCLOSE
BASIC Keywords:
  • LET –assigns a value (which may be the result of an expression) to a variable.
  • DATA –holds a list of values which are assigned sequentially using the WRITE command.
  • IF … THEN –used to perform comparisons or make decisions.
  • FOR .. TO … {STEP} … NEXT –repeat a section of code a given number of times. A variable that acts as a counter is available within the loop.
  • GOTO –jumps to a numbered or labelled line in the program.
  • GOSUB –jumps to a numbered or labelled line, executes the code it finds there until it reaches a RETURN keyword.
  • PRINT –displays a message on the screen.
  • INPUT –asks the user to enter the value.
  • STORE –store a value to a defined data array.
  • READ –read from the defined data array.
  • RETURN –return from a subroutine.
  • DEF –makes a lambda function
Stock BASIC function descriptionsGOTO( number/label position )
  • jumps to a numbered or labelled line in the program
GOSUB( number/label position )
  • jumps to a numbered or labelled line, executes the code it finds there until it reaches a RETURN keyword
PRINT( string message, … )
  • displays a message on the screen
INPUT( string message )
  • asks the user to enter the value
STORE( array array, number/string index, any value )
  • write to a defined data array
STOREN( array data, any value )
  • store a number to a growing array
READ( array array, number/string index )
  • read from the defined data array
  • returns a value at that index in that array
RETURN
  • return from a subroutine
DEF COMMANDDEF name( vararg ) = expression
  • makes a lambda function
  • Example:

print func( 2 )

def func( x ) = x * x

Rem OUTPUTS 4

let y = 0
set 18
print y

def set( x ) = y = x

Rem OUTPUTS 18
Implemented variable descriptionscycles
  • returns executed cycles per CCFrame
keystr
  • holds the current typed keyboard input!
Implemented function descriptionsBTN( number value )
  • returns (1) if a button is pressed or (0) if not pressed.
  • 1 - arrow left
  • 2 - arrow right
  • 3 - arrow up
  • 4 - arrow down
  • 5 - Z
  • 6 - X
CLEAR
  • clears the screen.
COLOR( number background, number foreground )
  • sets the current colors
CURSOR( number x, number y )
  • sets built-in terminal cursor position.
WRITE( string message )
  • prints a message on the screen, without the new line.
HEX( string hexadecimal_number )
  • converts hexadecimal to decimal value
HIRES
  • Switches from Low Resolution Mode ( char column graphics ) to High Resolution Mode ( char pixel graphics ).
LORES
  • Switches from High Resolution Mode ( char pixel graphics ) to Low Resolution Mode ( char column graphics ).
PIXEL( number x, number y {, string char } )
  • Puts a character on the screen in Low Resolution Mode ( char is optional ) or
  • Puts a pixel on the screen ( High Resolution Mode )
SPRITE( array data, number x, number y, number width, number height )
  • Displays the sprite on the screen at the given location
REBOOT
  • Reboots the system
SHUTDOWN
  • Shutdown the system
LABEL( string label )
  • Sets the computers name( label )
FOPEN( string filename, string type )
  • Opens a file return (1) if succeeded or (0) if failed
FREAD
  • Reads all of current opened file
FREADLN
  • Reads a line of current opened file returns (0) if end of file
FWRITE( string data )
  • Writes data to current opened file
FWRITELN( string data )
  • Writes a line of data to the current file
FCLOSE
  • Closes current opened file
FEXISTS( string filename )
  • Checks if the file is present on the computer, returns (1) if it is otherwise returns (0)
FLIST( string path )
  • Returns an array list of files and folders present in that path
FDEL( string filename )
  • Deletes the file specified from the computer
FISDIR( string path )
  • Returns (1) if the path is a directory or (0) if not
EXIT
  • Stops the program and exits to SHELL or BASIC Terminal
DISPOSE
  • Simple garbage collection
FLOAD( string filename )
  • Load a file to the program memory!
  • Compatible extensions: *.o | *.bas
CREATETIMER( number time )
  • Returns the ID of the timer
SETTIMER( number id, number time )
  • Sets the time to the current timer
GETTIMER( number id )
  • Gets current timers time
FCONEXT
  • Increments the file stack by one, next time you read or write it will write to a different file buffer!
FCOPREV
  • Decrements the file stack by one
NETCREATE( number autoCheck )
  • Creates a network object
NETOPEN( netObject )
  • Initializes and opens the network to work on
NETCLOSE( netObject )
  • Closes and frees the network
NETMYIP( netObject )
  • Returns your IP adress, use it only when you open the network
NETRECEIVE( netObject )
  • Receives any messages sent and stores to a buffer
NETGETID( net )
  • Returns senders ID
NETGETIP( net )
  • Returns senders IP
NETGETTYPE( net )
  • Returns senders Message Type
NETGETMESSAGE( net )
  • Returns senders Message
NETCLEARBUFFER
  • Clears the send buffer
NETTYPE( number/string type )
  • Stores the type of the message to send buffer
NETMESSAGE( number/string message )
  • Stores the message to the send buffer
NETSEND( netObject obj, string IPADRESS )
  • Sends a message to that IP adress( computer )

BASIC programs
Hello World
Prints Hello, world on the screen


10 print "Hello, world"
20 goto 10
Or


10 print "Hello, world" : goto 10
For Loop
This will step until reaches 10


10 for x = 1 to 10
20 print "I farted", x, "times!"
30 next
This will step 2 times because we add 5 to x every iteration.


10 for x = 0 to 10 step 5
20 print "I farted", x, "times!"
30 next
Input Program
Asks for your name and displays a message


10 let name = input( "What is your name?" )
20 print "Nice to meet you,", name
Rectangle Program
Draws a rectangle


10 for y = 1 to 9
20 for x = 1 to 21
30 pixel x, y, " "
40 next
50 next
60 goto 10
Sprite Program
Draws a sprite


05 rem VARIABLE DECLARATIONS
10 let back = hex( "f" )
20 let front = 0
30 let canClear = 1
35 hires
39 rem INIT SPRITE
40 gosub 100
49 rem DRAW SPRITE
50 if canClear = 0 then goto 80
60 color back, front
70 clear
75 canClear = 0
80 sprite spr, 5, 5, 8, 8
90 goto 50
99 rem SPRITE DATA
100 data spr
110 storen spr, back
111 storen spr, back
112 storen spr, front
113 storen spr, front
114 storen spr, front
115 storen spr, front
116 storen spr, back
117 storen spr, back
118 storen spr, back
119 storen spr, front
120 storen spr, front
121 storen spr, front
122 storen spr, front
123 storen spr, front
124 storen spr, front
125 storen spr, back
126 storen spr, front
127 storen spr, front
128 storen spr, back
129 storen spr, front
130 storen spr, front
131 storen spr, front
132 storen spr, front
133 storen spr, front
134 storen spr, front
135 storen spr, front
136 storen spr, front
137 storen spr, front
138 storen spr, front
139 storen spr, front
140 storen spr, front
141 storen spr, front
142 storen spr, front
143 storen spr, front
144 storen spr, front
145 storen spr, front
146 storen spr, back
147 storen spr, back
148 storen spr, back
159 storen spr, back
150 storen spr, front
151 storen spr, front
152 storen spr, front
153 storen spr, front
154 storen spr, front
155 storen spr, front
156 storen spr, front
157 storen spr, front
158 storen spr, back
159 storen spr, front
160 storen spr, front
161 storen spr, front
162 storen spr, front
163 storen spr, front
164 storen spr, front
165 storen spr, back
166 storen spr, back
167 storen spr, back
168 storen spr, front
169 storen spr, front
170 storen spr, front
171 storen spr, front
172 storen spr, back
173 storen spr, back
180 return
Guess game
A simple guess game


10 let y = rnd( 1, 10 )
20 let x
30 x = num( input( "Guess the number?" ) )
40 if x = y then goto 70
50 print "Wrong!"
60 goto 30
70 print "RIGHT!"
80 if input( "Want to play again?" ) = "y" then goto 10
90 print "BYE!"
Moving pixel
Moving a pixel


1 Rem VARIABLE DECLARATIONS
5 Let timer = createTimer()
10 Let x = 1
20 Let y = 1
21 Rem MAIN LOOP
30 Color 15, 0
40 Clear
41 Rem USERS INPUT
50 If Btn( 1 ) = 1 Then x = x - 1
60 If Btn( 2 ) = 1 Then x = x + 1
70 If Btn( 3 ) = 1 Then y = y - 1
80 If Btn( 4 ) = 1 Then y = y + 1
81 Rem DRAW THE PIXEL
90 Color 5, 0
100 Pixel x, y, " "
101 Rem SKIP SOME CYCLES
110 setTimer timer, cycles
120 If getTimer( timer ) <= 0 Then Goto 30
130 Goto 120
BASIC Loader
Make a new file and paste this:


Rem Made By: LeDark Lua
Rem NOTE: all programs that will run from
Rem this program share same Enviroment!

__Init:

Rem INITIALIZE HELPER VARIABLES

Let __currSelected = 1
Let __tempFiles
Data __files
Let __fileLen
Let __TempFn
Let __Timer = createTimer()
Let timer = createTimer()

__FetchFiles:

Rem FETCH AND STORE FILES

__tempFiles = FList( "/" )
For i=1 To Len( __tempFiles )
__TempFn = Read( __tempFiles, i )
If __TempFn = "loader.bas" Then Goto __SkipLoaderFile
If Right( __TempFn, 3 ) = "bas" Then Storen __files, __TempFn
If Right( __TempFn, 1 ) = "o" Then Storen __files, __TempFn
__SkipLoaderFile:
Next
__fileLen = Len( __files )

__MainLoop:

Rem MAIN PROGRAM LOOP

Cursor 1, 1
Clear
If Btn( 3 ) = 1 Then __currSelected = __currSelected - 1
If Btn( 4 ) = 1 Then __currSelected = __currSelected + 1
If __currSelected > __fileLen Then __currSelected = 1
If __currSelected < 1 Then __currSelected = __fileLen
For i = 1 To __fileLen
Color 15, 0
if __currSelected = i then Color 15, 5
Print Read( __files, i )
Next
If Btn( 5 ) = 1 then GoSub __RunSelected

setTimer __Timer, 250 - cycles

__Sleep:

Rem SLEEPER

if getTimer( __Timer ) <= 0 then goto __MainLoop
goto __Sleep

__RunSelected:

Rem RUNS A SELECTED PROGRAM!

Color 15, 0
Cursor 1, 1
Clear
GoSub FLoad( Read( __files, __currSelected ) )
Dispose
Return

subSleep:

Rem HELPER SUBROUTINE FOR PROGRAMS

If getTimer( timer ) <= 0 Then Return
Goto subSleep
Compatible files should look like this:



Rem Prints a hello world onto the screen, waits a bit and returns to the loader program!

Print "Hello, world!"

Rem Sleep a bit ( calls other programs subroutine )
timer = 1000
GoSub subSleep

Rem Return to the loader
Return
How to get and run BASIC
To download BASIC, type this:

pastebin get nsMdcH6L BASIC

To compile BASIC file:

BASIC c <in> <out> --compiles the file and spits out bytecode file
To run the compiled BASIC file:

BASIC r <in> --runs the compiled file
To run just the BASIC file:

BASIC <filename> --runs a file
To run a BASIC terminal:

BASIC --runs a terminal
Terminal commandsnew
  • creates a new file
clear
  • clears the screen
load {path/}$
  • fetch all files and directories
  • to see then type list in the terminal
load (filename)
  • loads a file
save (filename)
  • saves a file
list {start, end}
  • list all contents of a file or list all loaded files and directories
  • or if you want just a block of code to be displayed use:
  • list 10 50
  • displays all code from line 10 to line 50
list bc
  • list compiled data of the contents typed in ( DEBUG only )
run
  • runs typed contents
exit
  • exits BASIC terminal
Some pictures of BASICThere are BASIC terminal pictures



If you found a BUG or you have any suggestions or I left out something, post it here :)/>


Thanks in advance,
LeDark Lua
Edited on 07 January 2018 - 11:23 AM
SquidDev #2
Posted 04 December 2017 - 09:44 PM
I'm stuck between "why would anyone want to recreate BASIC?" and "this is pretty impressive". Seriously though, good job!
LeDark Lua #3
Posted 04 December 2017 - 10:50 PM
I'm stuck between "why would anyone want to recreate BASIC?" and "this is pretty impressive". Seriously though, good job!
Much Thanks! Well I got the idea from that post where a guy asked for BASIC to be implemented in ComputerCraft, and in my opinion, it gives more of a retro feel, Dan wants to emulate that retro(ness) but Lua is a bit modern, so I used what suited the best, to give that full RETRO feeling.

OffTopic:
If you think that making an interpreted language in an interpreted language is bad, then think of this way, Lua is machine code and BASIC is just a program for the machine, like 6502 processor has the machine code and BASIC is a program for that CPU.
Edited on 04 December 2017 - 10:31 PM
Lupus590 #4
Posted 05 December 2017 - 09:18 PM
If you think that making an interpreted language in an interpreted language is bad

*cough* Lua in Java *cough* (not quite the same but vm in a vm thing)
Edited on 05 December 2017 - 08:19 PM
LeDark Lua #5
Posted 05 December 2017 - 09:25 PM
If you think that making an interpreted language in an interpreted language is bad

*cough* Lua in Java *cough* (not quite the same but vm in a vm thing)
True :lol:/>
Exerro #6
Posted 05 December 2017 - 09:30 PM
I got excited and made a 'decompiler' that shows the bytecode of a compiled program. It's quite interesting to see how things compile (and how they can be optimised!)

Download
pastebin get sqsPm71U decompiler

Example
Spoiler

10 for y = 1 to 9
20 for x = 1 to 21
30 pixel x, y, " "
40 next
50 next
60 goto 10


vardef "y"
push 1
varset "y"
vardef "x"
push 1
varset "x"
varget "x"
varget "y"
push " "
args 3
call "pixel"
varget "x"
push 1
add
dup
varset "x"
push 21
compare 2
condjmp 0 13
varfree "x"
varget "y"
push 1
add
dup
varset "y"
push 9
compare 2
condjmp 0 7
varfree "y"
jump 1
halt
SquidDev #7
Posted 05 December 2017 - 09:39 PM
*cough* Lua in Java *cough* (not quite the same but vm in a vm thing)
Depending on your JVM, it's quite likely that the Lua VM will be interpreted before JITing occurs.

That being said, I wonder how hard it'd be to compile BASIC/the bytecode to Lua instead - this way you shave one level of this interpreter stack and so make things much faster.
Edited on 05 December 2017 - 08:39 PM
Exerro #8
Posted 05 December 2017 - 09:49 PM
That being said, I wonder how hard it'd be to compile BASIC/the bytecode to Lua instead - this way you shave one level of this interpreter stack and so make things much faster.

Heh, this is what I was going for with the decompiler. I was just gonna use that to analyse the bytecode then make an actual compiler to Lua source.
LeDark Lua #9
Posted 05 December 2017 - 10:11 PM
I got excited and made a 'decompiler' that shows the bytecode of a compiled program. It's quite interesting to see how things compile (and how they can be optimised!)

Download
pastebin get sqsPm71U decompiler

Example
Spoiler

10 for y = 1 to 9
20 for x = 1 to 21
30 pixel x, y, " "
40 next
50 next
60 goto 10


vardef "y"
push 1
varset "y"
vardef "x"
push 1
varset "x"
varget "x"
varget "y"
push " "
args 3
call "pixel"
varget "x"
push 1
add
dup
varset "x"
push 21
compare 2
condjmp 0 13
varfree "x"
varget "y"
push 1
add
dup
varset "y"
push 9
compare 2
condjmp 0 7
varfree "y"
jump 1
halt
Yeah I know, I need to work now on optimizing the compiled bytecode, working on some solutions, but for now I just wanted to push out a stable version :P/>
And I got excited when I saw that you are excited, glad to see that people are interested in this :D/>
LeDark Lua #10
Posted 05 December 2017 - 10:16 PM
That being said, I wonder how hard it'd be to compile BASIC/the bytecode to Lua instead - this way you shave one level of this interpreter stack and so make things much faster.
Not that hard really, simple and easy, but you would need to work around jumps ( wrap the compiled line in a function maybe? )
LeDark Lua #11
Posted 08 December 2017 - 07:31 PM
***UPDATE***

Added:
  • Basic optimization
  • Fixed some bugs
How optimization works:
Spoiler

10 print 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
Originally compiles to:

push 1
push 2
push 3
push 4
push 5
push 6
push 7
push 8
push 9
add
add
add
add
add
add
add
add
args 1
call "print"
halt
But with optimization it compiles to:

push 45
args 1
call "print"
halt

NOTE: This is just basic Pre-Processed binary operations, more optimization will be added soon!

To download the new version, use the old link!
Edited on 08 December 2017 - 06:33 PM
Exerro #12
Posted 08 December 2017 - 11:32 PM
Looks like I broke the optimiser:

print 1 + 2 - 3 + 4 - 5 + 6 - 7 + 8 - 9
Turns out this also breaks it:

print 2 - 1
By break I mean an infinite loop somewhere - it just freezes until the computer shuts off. Note I'm using ccemux but I doubt that would affect anything.

Tested with the older version too and it didn't break then.

Edit: quick fix:
Spoiler


v.type = "num"
v.value = l - r
Edited on 08 December 2017 - 10:36 PM
LeDark Lua #13
Posted 08 December 2017 - 11:54 PM
Oh thanks! Fixed it, and fixed some other bugs that may cause an infinite loop, now should be fine and dandy!
LeDark Lua #14
Posted 10 December 2017 - 12:57 PM
***UPDATE***

Added:
  • New function: SPRITE, COLOR, STOREN
  • Improved LIST command in terminal, now you can display blocks of code
  • Added a new program to tinker around
  • Fixed some minor bugs
To download the new version, use the old link!
Edited on 22 December 2017 - 05:35 PM
LeDark Lua #15
Posted 22 December 2017 - 06:24 PM
***UPDATE***

Added:
  • Interpreters speed is increased!
  • Variables: cycles, timer
  • Variables are case sensitive but Keywords and Functions are not
  • Another program to check out: Moving Pixel ( uses new features )
  • Fixed some bugs!
To download the new version, use the old link!
Edited on 22 December 2017 - 06:22 PM
LeDark Lua #16
Posted 26 December 2017 - 01:19 PM
***UPDATE***

Added:
  • New functions: FLOAD, EXIT, DISPOSE
  • Added a new program: BASIC Loader ( uses new features )
  • A bit of bug fixes
OPCODE CHANGE:
  • GOSUB opcode no longer accepts an argument, instead it pops a value from the stack!
Compiler CHANGE:
  • Labels define as variables, so your programs may be larger if you have a lot of labels! But that will not impact the performance of your program!
  • Fixed binary operations a bit, added precedence over other operations.
NOTE:

Older COMPILED programs that use GoSub command are not compatible with the new version, text based programs are fine! Just recompile your code!

To download the new version, use the old link!
Edited on 26 December 2017 - 05:25 PM
LeDark Lua #17
Posted 31 December 2017 - 09:00 AM
***UPDATE***

Added:
  • Added lambda function as DEF ( check OP )
  • Added more optimization!
  • New opcode: EXPECT
  • Fixed a lot of bugs!
NOTE:


Older COMPILED programs that use EXPECT opcode are not compatible with the new version, text based programs are fine! Just recompile your code!


To download the new version, use the old link!
Edited on 31 December 2017 - 08:01 AM
LeDark Lua #18
Posted 07 January 2018 - 09:20 AM
***BIG UPDATE***

Added:
  • Added NETWORKING! And some new functions. Check the OP.
  • Changed timer functionality a bit, check the OP.
  • Fixed and/or bugs, always evaluating 1, now they're working properly
  • Fixed optimize bugs and errors
  • Fixed parsing a bit
  • And fixed some minor bugs.
To download the new version, use the old link!
Edited on 07 January 2018 - 08:21 AM