SkillAgentSearch skills...

PuffinBASIC

BASIC interpreter written in Java

Install / Use

/learn @mayuropensource/PuffinBASIC
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<img src="puffin.png" width="64"/>

PuffinBASIC

A cross-platform modern BASIC compiler/interpreter written in Java.

BASIC (Beginners' All-purpose Symbolic Instruction Code) is a general-purpose high-level language from the 1960s. PuffinBASIC is an implementation of the BASIC language specification. PuffinBASIC conforms most closely to GWBASIC.

Show Case

2D Scrolling Game (Teaser)

YouTube Video: <a href="https://youtu.be/m3snkPVhhVo"><img src="samples/nextGame.png"></a> Source: Under development, not committed yet

TESSEL - A 2D Tile Game

YouTube Video: <a href="https://youtu.be/L8xkM-g3Zms"><img src="samples/tessel/images/tesselsnap1.png" width="64"></a> Source: <a href="samples/tessel/tessel.bas">tessel.bas</a>

FlyPuffinFly - A Scrolling Game

YouTube Video: <a href="https://youtu.be/bIIamQp9N3o"><img src="samples/puffingame/images/flypuffinflysnap.png" width="64"></a> Source: <a href="samples/puffingame/flypuffinfly.bas">flypuffinfly.bas</a>

Conway's Game of Life

YouTube Video: <a href="https://youtu.be/TpsxQrxKqdg"><img src="samples/gameoflife/images/gameoflifesnap.png" width="64"></a> <a href="https://youtu.be/A5tN6cBqoAc">#2</a> Source: <a href="samples/gameoflife/gameoflife.bas">gameoflife.bas</a>

Mandelbrot Set

YouTube Video: <a href="https://youtu.be/7CukYv9tfXA"><img src="samples/mandelbrotsnap.png" width="64"></a> <a href="https://youtu.be/xKp9U2BXTHM">Zoomed</a> Source: <a href="samples/mandelbrot.bas">mandelbrot.bas</a>

Why Implement BASIC?

  1. Love and Familiarity: GWBASIC was my first programming language, I loved it and made many games in it.
  2. Interpreter language: BASIC is simple and an interpreted language and hence a good choice for implementing this interpreter.
  3. Learn antlr4: I was learning antlr4 and BASIC was the perfect language to try because of its simple instruction set.
  4. Resurrect BASIC: Implementations such as GWBASIC don't work on most modern platforms. My goal is to make PuffinBASIC work anywhere Java can work.
  5. Improve BASIC: I wanted to add modern graphics, better data types, etc., to make it easier to write games.

Version

0.1 experimental (NOT YET READY FOR PRODUCTION USE!)

  • The interpreter is not yet thoroughly tested and is likely to have bugs.
  • This is an active project so expect large changes at frequent intervals.

Code Samples

Print multiplication tables

10 FOR I% = 1 TO 10
20   PRINT "Multiplication table of ", I%
30   FOR J% = 1 TO 10
40     PRINT I%, "x", J%, "=", I%*J%
50   NEXT J%
60 NEXT I%

Print prime numbers between 1 and 100

Line numbers are optional in PuffinBASIC.

FOR I% = 1 TO 100
  J% = 3
  N% = I% \ 2
  ISPRIME% = (I% > 1) AND ((I% MOD 2 <> 0) OR (I% = 2))
  WHILE J% <= N% AND ISPRIME% = -1
    ISPRIME% = I% MOD J% <> 0
    J% = J% + 2
  WEND
  IF ISPRIME% THEN PRINT STR$(I%), " is prime"
NEXT I%

Print Fibonacci Series

10 A@ = 0 : B@ = 1
20 FOR I% = 1 TO 20
30   C@ = A@ + B@
40   PRINT C@,
50   A@ = B@ : B@ = C@
60 NEXT I%
70 PRINT ""

Print trigonometric function graph

10 PRINT SPACE$(40), "0"
20 FOR D = 0 TO 360 STEP 10
30   x# = 3.14159 * D / 180.0
40   y# = SIN(x#)
50   PRINT SPACE$(40 + CINT(y# * 40)), "*"
60 NEXT D

Graphics

10 SCREEN "PuffinBASIC 2D Graphics", 800, 600
20 LINE (100, 100) - (200, 200), "B"
30 FOR I% = 10 TO 50 STEP 10
40   CIRCLE (150, 150), I%, I%
50 NEXT I%
60 COLOR 255, 0, 0
70 LINE (200, 200) - (250, 300), "BF"
80 COLOR 0, 255, 255
90 FONT "Georgia", "bi", 32
100 DRAWSTR "Graphics with PuffinBASIC", 10, 400
110 DIM A%(101, 101)
120 GET (100, 100) - (201, 201), A%
130 PUT (250, 250), A%
140 DIM B%(32, 32)
150 LOADIMG "samples/enemy1.png", B%
160 FOR I% = 1 TO 5
170   PUT (400, 100 * I%), B%
180 NEXT
190 COLOR 255, 255, 0
200 DRAW "M600,400; UN50; RN50; DB50; F100"
210 COLOR 255, 255, 255
220 CIRCLE (700, 100), 10, 20
230 COLOR 255, 0, 255
240 PAINT (700, 100), 255, 255, 255
250 CIRCLE (700, 400), 50, 50, 0, 90
260 CIRCLE (700, 500), 50, 50, 90, 180, "F"
1000 SLEEP 5000
<img src="samples/puffin_graphics.png" width="512"/>

Dependencies

JDK 11+, Maven, antlr4

Build and test

$ mvn compile
$ mvn test

Run using Maven

$ mvn exec:java -D"exec.args"="samples/graph.bas"

Graphics mode:

$ mvn exec:java -D"exec.args"="-g samples/graphics.bas"

Working with Intellij

Import the pom.xml file in Intellij. After importing, if you make a change to the antlr4 grammar, regenerate the antlr4 code using following command and then reload the changes.

$ mvn generate-sources

How it works?

  1. PuffinBASIC's grammar is defined using antlr4.
  2. The user source code is parsed using antlr4 lexer+parser.
  3. An intermediate representation (IR) is generated. A symbol table keeps track of variables, scalars, arrays, etc. objects.
  4. The interpreter runtime processes the IR instructions and executes them in a single thread. For graphics, an optional Runtime is used.

Since PuffinBASIC generates IR from source code and the runtime executes the IR, we can say PuffinBASIC is both a compiler and an interpreter.

Planned Improvements

  1. Android port, requires a rewrite of Graphics runtime.
  2. ...

Performance

PuffinBASIC is an interpreter, and it should not be expected to have very good performance characteristics. Certain operations such as PRINT USING, INPUT, etc are not optimized for performance. PuffinBASIC primitives have not been benchmarked. That being said, games containing 2D graphics work reasonably well.

Memory

PuffinBASIC runs within a JVM and can use as much memory as available for the JVM process.

Reference

Mode of operation

Indirect Mode

  1. Write a program in your favorite editor.
  2. Save it in a text file with a '.bas' extension (not a requirement).
  3. Use maven or PuffinBasicInterpreterMain to run the program.

PuffinBASIC supports indirect mode only.

Line-number and No-line-number modes

PuffinBASIC programs can have one of two modes:

  1. Line-number mode: All lines must start with a line number. GOTO/GOSUB statements can use both line number and label.
  2. No-line-number mode: No line should start with a line number. GOTO/GOSUB statements can use label only.

Compatibility

PuffinBASIC is mostly compatible with Microsoft's GWBASIC. Graphics is supported using Java 2D graphics.

PuffinBASIC will not support assembly instructions.

Input

PuffinBASIC aims for cross-platform compatibility and doesn't support platform specific features. Input statements and functions are line based and require 'ENTER' key to be pressed. Same applies for the sequential file writes, print statements always output a line and input statements read the whole line.

Case sensitivity

Operators, Statements and Standard Functions are case-insensitive. Constants, variables and user defined functions are case-sensitive.

Graphics

Graphics uses platform-independent Swing window. Graphics functions are slightly different and more general than GWBASIC. Graphics statements/functions require a '-g' flag to be set at runtime. See Graphics section in reference. PRINT/WRITE statements are displayed on standard out only. For displaying text on Swing window, new statements are added.

DIM

DIM statement declares size of each dimension (rather than maximum value of the dimension).

Data Types

PuffinBASIC supports scalar, array, struct, list, set and dict types. Int32, Int4, Float32, Float64, and String are the scalar types. Each scalar type has a corresponding array type.

Commands

PuffinBASIC does not support BASIC Commands, such as LIST, RUN, etc.

Errors

PuffinBASIC can raise following kind of errors:

  1. PuffinBasicSyntaxError: if source code has lexical or parsing error, e.g. missing parenthesis.
  2. PuffinBasicSemanticError: if source code has a semantic error, e.g. data type mismatch.
  3. PuffinBasicRuntimeError: if a runtime error happens, e.g. division by zero, IO error, etc.
  4. PuffinBasicInternalError: if there is a problem with PuffinBASIC implementation.

Data Types

Scalar Types

  1. Int32 (32-bit signed integer): Int32 constants can have an optional '%' suffix. Int32 constants can be decimal, octal or hexadecimal. Octal numbers must have '&' or '&O' prefix, e.g. &12 or &O12. Hexadecimal numbers must have '&H' prefix, e.g. &HFF.

  2. Int64 (64-bit signed integer): Int64 constants must have '@' suffix. Int64 constants can be decimal, octal or hexadecimal.

  3. Float32 (32-bit signed IEEE-754 floating-point): Float32 constants can have an optional '!' suffix. Float32 constants can use a decimal format or scientific notations, e.g. 1.2 or 1.2E-2.

  4. Float64 (64-bit signed IEEE-754 floating-point): Float64 constants can have an optional '#' suffix. Float32 constants can use a decimal format or scientific notations, e.g. 1.2 or 1.2E-2.

  5. String: String stores any non-newline (or carriage return) ASCII character. A string must be enclosed within double-quotes, e.g. "A TEST, STRING". There is no limit on the length of a string.

Array Types

  1. N-dimensional Int32 Array
  2. N-dimensional Int64 Array
  3. N-dimensional Float32 Array
  4. N-dimensional Float64 Array
  5. N-dimensional String Array

Composite Types

  1. Struct: User defined type composed of scalar, array, struct, list, set and dict types.
  2. List: Variable length list of scalar and struct values.
  3. Set: Unordered open hash-set of scalar values.
  4. Dict: Unordered open hash-map of scalar to scalar and struct values.

Type conversion

Numeric types are converted into one another via implicit type conversion. String and numeric types are not implicitly converted. Use STR$ or VAL functions for conversion between String and numeric values.

Variables

A variable name must start with a letter followed by one or more letters or numeric digits. A variable name must not start with 'FN' because it is reserved for user defined functions.

A variable name has an optional suffix which

Related Skills

View on GitHub
GitHub Stars35
CategoryDevelopment
Updated1mo ago
Forks6

Languages

Java

Security Score

90/100

Audited on Feb 21, 2026

No findings