A Microsoft QBasic-compatible BASIC compiler implemented in Go. Compiles BASIC source code to native executables via LLVM IR emission.
Source (.bas) -> Lexer -> Parser -> AST -> Semantic Analyzer -> LLVM IR -> Object -> Link -> Executable
# Build
go build -o finn-basic ./cmd/finn-basic
# Compile a BASIC program
./finn-basic compile program.bas -o program
# Run the compiled program
./program
finn-basic compile <file.bas> # Compile to native executable
finn-basic compile --emit-ir <file.bas> # Emit LLVM IR (.ll file)
finn-basic compile --dump-ast <file.bas> # Print AST and exit
finn-basic lint <files...> # Lint BASIC source files
finn-basic lsp --stdio # Start language server
finn-basic version # Print compiler version
finn-basic help # Show usage
| Flag |
Description |
| -o <name> |
Output executable name (default: a.out) |
| --emit-ir |
Write .ll file instead of compiling |
| --dump-ast |
Print AST and exit |
| --trace |
Enable trace output |
finn-basic/
├── cmd/finn-basic/
│ ├── main.go # CLI entry point
│ └── compile.go # compile subcommand
├── internal/
│ ├── lexer/ # Tokenizer
│ ├── parser/ # Recursive descent parser
│ ├── ast/ # AST node definitions
│ ├── analyzer/ # Semantic analysis
│ ├── types/ # Type system
│ ├── lsp/ # Language server protocol
│ └── lint/ # Linter rules
└── testdata/ # Example programs and golden files
- Line numbers (optional)
- PRINT, INPUT, READ/DATA/RESTORE
- LET (implicit and explicit)
- IF/THEN/ELSE (single and multi-line)
- FOR/NEXT, WHILE/WEND, DO/LOOP
- GOTO, GOSUB/RETURN
- ON...GOTO / ON...GOSUB
- SELECT CASE
- DIM, REDIM, REDIM PRESERVE
- SUB/FUNCTION declarations
- DEF FN (single-line functions)
- DEFINT/DEFDBL/DEFSTR type declarations
- SWAP, POKE/PEEK
- CLS, SCREEN, COLOR, LINE, CIRCLE, LOCATE
- REM comments and nested (* ... *) comments
- String functions: LEN, LEFT$, RIGHT$, MID$, STR$, VAL, CHR$, ASC, etc.
- Math functions: ABS, SIN, COS, TAN, SQR, INT, RND, etc.
- Conversion functions: CDBL, CSNG, CINT, CLNG, CSTR
- ON ERROR GOTO / RESUME NEXT
| ID |
Description |
Severity |
| W001 |
Variable assigned but never used |
warning |
| W002 |
Line number declared but never referenced |
warning |
| W004 |
GOTO jumps to the next line (no-op) |
warning |
| W005 |
IF statement has empty body |
warning |
| S003 |
Line numbers have gaps |
style |
| S004 |
No REM header at top of file |
style |
# Run all tests
go test ./...
# Run tests with verbose output
go test ./... -v
# Build and test manually
go build -o finn-basic ./cmd/finn-basic/
./finn-basic compile testdata/hello.bas -o /tmp/hello
/tmp/hello
The LSP server provides IDE features for BASIC source files:
- Diagnostics: Real-time error and warning reporting
- Completion: Keywords, built-in functions, and variables
- Hover: Type and declaration info
- Definition: Jump to variable/subroutine declarations
# Start the server (for editor integration)
./finn-basic lsp --stdio
{
"basic.languageServer.command": "finn-basic",
"basic.languageServer.args": ["lsp", "--stdio"],
"files.associations": {
"*.bas": "basic",
"*.BAS": "basic"
}
}
# Lint and vet (required between development steps)
go vet ./...
go fix ./...
# Run linter
golangci-lint run
# Run tests
go test ./...
10 REM Fibonacci sequence
20 a = 0
30 b = 1
40 FOR i = 1 TO 10
50 PRINT a
60 c = a + b
70 a = b
80 b = c
90 NEXT i
100 END
See LICENSE file for details.