skx / gobasic
- понедельник, 29 октября 2018 г. в 00:15:41
Go
A BASIC interpreter written in golang.
This repository contains a naive implementation of BASIC, written in Golang.
If you'd prefer to see a more "real" interpreted language, implemented in Go, you might prefer monkey.
The implementation is simple for three main reasons:
Currently the following obvious primitives work:
END
GOTO
GOSUB / RETURN
IF / THEN / ELSE
INPUT
INPUT "Enter a string", a$.INPUT "Enter a number", a.LET
FOR & NEXT
PRINT
REM
Most of the maths-related primitives I'm familiar with from my days coding on a ZX Spectrum are present, for example SIN, COS, PI, ABS.
The interpreter has support for strings, and a small number of string-related primitives:
LEN "STEVE"
LEFT$ "STEVE", 2
RIGHT$ "STEVE", 2
CHR$ 42
*). (i.e. ASCII value)CODE " "
This is a quick hack, so there are some (important) limitations:
The handling of the IF statement is perhaps a little unusual, since I'm used to the BASIC provided by the ZX Spectrum which had no ELSE clause!
The general form of the IF statement is:
IF $CONDITIONAL THEN $STATEMENT1 [ELSE $STATEMENT2]
Only a single statement is permitted between "THEN" and "ELSE", and again between "ELSE" and NEWLINE. These are valid IF statements:
IF 1 > 0 THEN PRINT "OK"
IF 1 > 3 THEN PRINT "SOMETHING IS BROKEN": ELSE PRINT "Weird!"
In that second example you see that ":" was used to terminate the PRINT statement, which otherwise would have tried to consume all input until it hit a newline.
You'll also notice that the primitives which are present all suffer from the flaw (?) that they don't allow brackets around their arguments. So this is valid:
10 PRINT RND 100
But this is not:
10 PRINT RND(100)
This particular problem could be fixed, but I've not considered it significant.
Providing you have a working go-installation you should be able to install this software by running:
go get -u github.com/skx/gobasic
NOTE This will only install the command-line driver, rather than the HTTP-server, or the embedded example code.
If you don't have a golang environment setup you should be able to download various binaries from the github release page:
gobasic is very simple, and just requires the name of a BASIC-program to
execute. Write your input in a file and invoke gobasic with the path.
For example the following program was useful to test my implementation of the GOTO primitive:
10 GOTO 80
20 GOTO 70
30 GOTO 60
40 PRINT "Hello, world!\n"
50 END
60 GOTO 40
70 GOTO 30
80 GOTO 20
Execute it like this:
$ gobasic examples/10-goto.bas
NOTE: I feel nostalgic seeing keywords in upper-case, but PRINT and print are treated identically.
A traditional interpreter for a scripting/toy language would have a series of well-defined steps:
As is common with early 8-bit home-computers this implementation is a little more basic:
FOR/NEXT loops.GOSUB/RETURNAs there is no AST step errors cannot be detected prior to the execution of programs - because we only hit them after we've started running.
There are a small number of sample-programs located beneath examples/. These were written in an adhoc fashion to test various parts of the implementation.
Perhaps the best demonstration of the code are the following two samples:
The interpreter is designed to be easy to embed into your application(s) if you're crazy enough to want to do that!
You can see an example in the file embed/main.go.
The example defines several new functions which can be called by BASIC:
PEEKPOKEPLOTSAVECIRCLEWhen the script runs it does some basic variable manipulation and it also
creates a PNG file - the PLOT function allows your script to set a pixel
and the CIRCLE primitive draws an outline of a circle. Finally the
SAVE function writes out the result.
Extending this example to draw filled circles, boxes, etc, is left as an exercise ;)
Hopefully this example shows that making your own functions available to BASIC scripts is pretty simple. (This is how SIN, COS, etc are implemented in the standalone interpreter.)
Building upon the code in the embedded-example I've also implemented a simple HTTP-server which will accept BASIC code, and render images!
To run this:
cd goserver ; go build . ; ./goserver
Once running open your browser at the URL:
The view will have an area of entering code, and once you run it the result will be shown in the bottom of the screen. Something like this:
There are several included examples which you can load/launch by clicking upon them.
It is probable that bugs exist in this interpreter, but I've tried to do as much testing as I can. If you spot anything that seems wrong please do report an issue.
The project contain a number of test-cases, which you can execute like so:
$ go test ./...
Finally if our test-coverage drops beneath 90% that is also a bug. You can view coverage like so:
$ go test -coverprofile=c.out ./...
$ go tool cover -html=c.out
The interpreter has been fuzz-tested pretty extensively, which has resulted in some significant improvements. See FUZZING.md for details.