Binsic Is Not Sinclair Instruction Code


BINSIC – Binsic Is Not Sinclair Instruction Code – is a BASIC-like language implemented as (similar to) a domain specific language in Groovy.

Update (April 2020): I have worked on getting BINSIC back in an easily usable state and a jar file is now available at http://n4decameron.org/~adrian/binsic.jar .

BINSIC is modelled on the ROM BASICs built in to the Sinclair ZX80 and ZX81 (a manual for that can be found here) – though there are a few notable differences:

  • BINSIC supports the String functions LEFT$, MID$ (both as a string extraction and a string insertion function) and RIGHT$ which should be used instead of the string splicing methods supported in the ZX80/ZX81 (in fact string splicing is supported if used as Groovy ranges but not in a true BASIC fashion);
  • GOTO inside a loop to a line inside a loop will cause a crash (GOTO can be used to exit a loop, however), while GOSUB inside a loop works (though loop variables drop out of scope – Groovy’s scoping rules will apply in BINSIC);
  • While Sinclair BASIC only supported IF .. THEN .., BINSIC will support IF .. THEN .. ELSE ..;
  • The PLOT and UNPLOT commands are supported through a separate graphics pane;
  • Capitalised text LIKE THIS OR THIS is best avoided in string literals (and be careful with variable names) as it may get mangled by the various regular expressions that are used to parse the input BASIC script
The code is quite white space sensitive – not an issue for a real ZX80 or ZX81 as the keywords were entered in a fully formed state, but the best advice is to add whitespace where you can (though you don’t need to add two spaces where one would do).

An example: Conway’s Game of Life

With the above caveats, and with the warning that there may be others and bugs I have not yet picked up, BINSIC is a fully featured and, I am sure, Turing complete language. The example below, of a version of Conway’s “Game of Life”, hopefully illustrates the point:

10 REM Game of Life
20 PRINT "Conway's Game of Life"
30 PRINT "Copyright Adrian McMenamin, 2012"
35 PRINT "adrianmcmenamin@gmail.com"
40 PRINT "Licensed under the GPL version 3"
50 DIM A(48, 70)
60 DIM B$(24)
70 PRINT "Please enter your pattern"
75 PRINT " - up to 24 lines of 70 characters"
80 FOR I = 1 TO 24
90 INPUT B$(I)
95 LET T = 0
97 IF B$(I) = "DONE" THEN LET T = 1
98 IF T = 1 THEN LET B$(I) = ""
100 IF T = 1  THEN GOTO 150
110 PRINT B$(I)
120 NEXT I
150 REM Parse Input
160 LET P = 0
170 LET G = 0
175 LET RR = 0
177 LET NN = 0
180 FOR Y = 1 TO 24
185 LET RR = Y
190 LET Z = LEN B$(Y)
210 IF Z = 0 THEN NEXT Y
220 FOR Q = 1 TO Z
225 LET NN = Q
228 LET A(Y, Q) = 0
230 IF MID$(B$(Y), Q, 1) = " " THEN LET A(Y + 24, Q) = 0
235 IF MID$(B$(Y), Q, 1) <> " " THEN GOSUB 10000
240 NEXT Q
250 FOR Q = Z + 1 TO 70
260 LET A(Y, Q) = 0
265 LET A(Y + 24, Q) = 0
270 NEXT Q
280 NEXT Y
300 REM Display Map
310 PRINT
320 PRINT
330 PRINT
340 PRINT "Generation ", G, " Population is ", P
350 FOR M = 1 TO 24
360 FOR N = 1 TO 70
370 IF A(M + 24, N) = 1 THEN PLOT(N, M)
375 IF A(M + 24, N) <> 1 THEN UNPLOT(N, M)
380 NEXT N
390 NEXT M
400 REM Map next generation
410 FOR M = 1 TO 24
420 FOR N = 1 TO 70
430 LET A(M, N) = 0
440 IF M + 1 < 25 AND A(M + 25, N) = 1 THEN LET A(M, N) = A(M, N) + 1
450 IF M - 1 > 0 AND A(M + 23, N) = 1 THEN LET A(M, N) = A(M, N) + 1
460 IF N + 1 < 71 AND A(M + 24, N + 1) = 1 THEN LET A(M, N) = A(M, N) + 1
470 IF N - 1 > 0 AND A(M + 24, N - 1) = 1 THEN LET A(M, N) = A(M, N) + 1
480 IF M - 1 > 0 AND N - 1 > 0 AND A(M + 23, N - 1) = 1 THEN LET A(M, N) = A(M, N) + 1
490 IF M - 1 > 0 AND N + 1 < 71 AND A(M + 23, N + 1) = 1 THEN LET A(M, N) = A(M, N) + 1
500 IF M + 1 < 25 AND N - 1 > 0 AND A(M + 25, N - 1) = 1 THEN LET A(M, N) = A(M, N) + 1
510 IF M + 1 < 25 AND N + 1 < 71 AND A(M + 25, N + 1) = 1 THEN LET A(M, N) = A(M, N) + 1
520 NEXT N
530 NEXT M
540 LET P = 0
600 FOR M = 1 TO 24
610 FOR N = 1 TO 70
611 LET ZZ = 0
612 LET SC = A(M, N)
613 IF A(M + 24, N) = 1 THEN LET ZZ = 1
614 LET RES = 0
615 IF ZZ = 0 AND SC = 3 THEN LET RES = 1
616 IF ZZ = 1 AND (SC = 2 OR SC = 3) THEN LET RES = 1
617 LET A(M + 24, N) = RES
618 LET P = P + RES
650 NEXT N
660 NEXT M
700 PAUSE 50000
800 LET G = G + 1
900 GOTO 310
10000 LET A(RR, NN) = 1
10010 LET A(RR + 24, NN) = 1
10020 LET P = P + 1
10030 RETURN
BINSIC screen shot running Life

This code works well, as the screenshot (of an older version that did not use the PLOT command) hopefully proves:

Getting BINSIC

BINSIC can be downloaded from here: http://n4decameron.org/~adrian/binsic.jar and the Life code from http://88.198.44.150/life.bas. Although this was written in Groovy, Java users (not Android) should be able to run it e.g. via java -jar binsic.jar life.bas without any difficulty.

DSLs and all that

A domain-specific language (or DSL for short) is a computer language designed for use in a particular environment (as opposed for general use), typically by technically skilled non-programmers. In that sense BASIC (and BINSIC) is not really a DSL at all, in that it is a general purpose language, but Groovy, which builds on Java, is a good choice for implementing DSLs  and is often used for this – many of the same methods that would be used to create a true DSL were used to produce BINSIC (though in other ways BINSIC is closer to an interpreter than a DSL).

The two key parts of BINSIC are a preprocessor, which parses the inputted  BASIC, and either converts it into native Groovy or places a call to a method in the script which is then handled by the second major part, an interpreter class (which extends Groovy’s scripting capabilities). This means it would be possible to mix Groovy and BASIC in the input script (though that is not recommended).

My guide to doing all of this was Groovy for Domain-Specific Languages – which I would recommend as a general guide, though with the warning that the Kindle edition is poorly formatted and some of the code examples show signs of sloppy editing.

Why bother?

My initial impetus came from the thoughts outlined in the blog here – A reason why kids don’t do programming any more? – and I thought instead of just moaning about it, why didn’t I get on and do something about it? As it happens the PLOT command was quite poorly supported at the start and, in any case, building BINSIC has made me wonder if there is really much point in teaching kids how to program in such an awful language (RaspberryPi promoters please note). On the other hand some parts of BASIC are enormously expressive – the INPUT and INKEY$ primitives really struck me in this way. Indeed, now PLOT and UNPLOT more or less work as expected (albeit on a stand-lone graphics pane) I have used BINSIC to write some “quick and dirty” plotting programs. But the graphics are crude and very chunky.

Anyway, have fun and let me know about bugs and comments.

It’s important to add this is all free software (GPL version 3) and the source code is available at https://github.com/mcmenaminadrian.

8 responses to “Binsic Is Not Sinclair Instruction Code”

  1. Correct me if i’m wrong; so BINSIC is not a DSL, but a interpreter of the BASIC language? You didn’t used stuff like ASTs and all that stuff?
    It’s pretty nice, anyway! Great work!

    1. Not quite. Most of it is parsing/interpretation, but also a good bit of it is code executed through an interpreter that extends the shell class and it uses the MOP etc, but on the other hand, none of the BASIC runs natively – though the only reason for that is the way Groovy handles capitalisation: otherwise I’d have a PRINT closure and so on. If you try that it fails unless you stick the arguments in parentheses which is not what BASIC demands.

  2. Hola, no consigo ejecutar el jar, me gustaria una guia de manejo. Soy un Fan del ZX81 y me interesa su interprete de Basic para programar basic.
    Muchas gracias
    Muchas gracias

    1. I do not speak Spanish, I am afraid, so the replies will have to be in English – but what is going wrong? Best thing is to email be at adrianmcmenamin gmail com

  3. […] Binsic Is Not Sinclair Instruction Code […]

  4. […] write a clone of Sinclair BASIC as a domain-specific languageĀ (DSL) in Groovy. The end result was BINSIC, but it was much closer to an interpreter than a DSL: it turned out that strange ways that Groovy […]

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.