AI agent guidance for this codebase. For project docs, build instructions, and architecture, see README.md.
ACE is a BASIC compiler for Amiga. It compiles BASIC source code (.b files) into native Amiga executables by generating Motorola 68000 assembly. The compiler is written in K&R C.
Build Pipeline:
Source (.b) → Preprocess (yap) → Compile (ace) → Assemble (vasmm68k_mot) → Link (vlink) → Executable
The bas wrapper script in bin/ orchestrates this full pipeline.
| Directory | Purpose |
|---|---|
src/ace/c/ |
Compiler source (lexer, parser, code generator) |
src/lib/c/ |
Runtime library C sources |
src/lib/asm/ |
Runtime library assembly sources |
src/make/ |
Build from here - Makefiles and build scripts |
bin/ |
Compiler binaries and bas wrapper script |
lib/ |
Built libraries (db.lib, startup.lib) |
bmaps/ |
Binary maps for Amiga shared libraries |
include/ |
Amiga system headers and submodule headers |
submods/ |
Submodules (reusable BASIC libraries) |
verify/tests/ |
Test suite (cases/, expected/, results/) |
verify/scripts/otherthenamiga/ |
Emulator and Amiga system files |
docs/ |
Documentation (ref.txt for language reference, quickref.txt) |
examples/ |
Example programs by category |
IDE/CubicIDE-ACE/ |
CubicIDE integration (syntax highlighting, autocase, quickinfo) |
Work in small, incremental steps. Only proceed when the previous step is verified working.
- Think test-driven: create a test first that specifies the implementation
- Make ONE change at a time
- Verify it works (build, test, or run)
- Only then proceed to the next change
- Every plan/spec is to be implemented in a separate git branch
Why: The Amiga environment is fragile - path handling, toolchain differences, and AmigaOS quirks mean changes interact unexpectedly. Small steps make debugging and rollback feasible.
- Build changes: Run a build, check executable exists
- Script changes: Execute the script, check output
- Test changes: Run the test suite
- Compiler/library changes: Build and run relevant tests (must run on emulator)
Note: Compiler/runtime rebuild is only necessary when its source files were changed.
- Emulator app:
verify/scripts/otherthenamiga/FS-UAE.app - Config file:
verify/scripts/otherthenamiga/ace-verify.fs-uae - Amiga system:
verify/scripts/otherthenamiga/aos3 - Startup script:
verify/scripts/otherthenamiga/call-on-ustartup- edit this to run commands on boot (called fromaos3/S/user-startup)
# Start the emulator
open verify/scripts/otherthenamiga/FS-UAE.app --args verify/scripts/otherthenamiga/ace-verify.fs-uae- Edit
verify/scripts/otherthenamiga/call-on-ustartupto run your test commands - Write output/logs to
ace:(maps to project root on host) - Start/restart emulator
- Periodically check for result files (every 30 secs)
- Runs take 5-10 min when recompiling, <1 min otherwise
IMPORTANT: The emulator MUST be restarted after every change to call-on-ustartup. The startup script is only read once at boot time.
; In verify/scripts/otherthenamiga/call-on-ustartup
cd ace:submods/mui
bas test_minimal >ace:test-output.txt
test_minimal >>ace:test-output.txt
It may be necessary to call the commands of bas individually, i.e. to get the assembler source code .s.
A module must be compiled using -m switch: bas -m mymod.
bas -E myfile makes ace write compiler errors to ace.err in the current directory. IMPORTANT: ace.err is overwritten on each bas -E call. When compiling multiple files, save or append the errors after each compilation:
; Compile module, save errors
bas -mEO mymod >ace:build-output.txt
type ace.err >>ace:build-output.txt
; Compile test, save errors separately
bas -E test_foo >>ace:build-output.txt
type ace.err >>ace:build-output.txt
Without this, only the last file's errors will remain in ace.err.
Full reference: docs/ref.txt
Key points:
- Comments:
REMor' - Variables:
DIM x AS INTEGER,DIM s AS STRING - Strings end with
$:name$,DIM text$ AS STRING - Arrays:
DIM arr(10) AS SINGLE - Structures:
DECLARE STRUCT mystruct, access with-> - Library calls:
LIBRARY "library.library",DECLARE FUNCTION - Labels for GOTO/GOSUB:
label: - Subprograms:
SUB name ... END SUB,FUNCTION name ... END FUNCTION - External modules:
EXTERNAL modulename - calling SUBs needs parenthesis
- don't use END inside IF blocks, use STOP.
- No stderr redirect:
2>&1doesn't work on AmigaDOS - No .b extension: Call
bas myprognotbas myprog.b(on emulator) - Debug build phases: Split bas phases (ace, vasm, vlink) and redirect each to separate files to see what's happening
- Amiga uses
:not/for device paths:ACE:bin/acenotACE/bin/ace - Case-sensitive on Unix, case-insensitive on Amiga - be consistent
- Makefiles must run from
src/make/- relative paths are based there - Required assigns:
ACE:(repo root),ACElib:,ACEbmaps:,ACEinclude:
- K&R C style throughout - no ANSI C, no modern features
- Use Amiga types:
BYTE,SHORT,LONG,BOOL,BPTR(not standard C types) - Single header
acedef.hincluded everywhere - Always read
acedef.hfirst when modifying the compiler
- Run make from
src/make/, not project root - AmigaDOS scripts use
.keydirectives, not bash syntax - Use
make -f <Makefile> cleanto rebuild completely - Stack requirement: 40000-65000 bytes for compiler operations
- Error tests (
cases/errors/) are expected to FAIL compilation - Test results in
verify/tests/results/- don't commit these - Test runner is ARexx:
rx verify/tests/runner.rexx <category> - Categories: syntax, arithmetic, floats, control, errors
cd src/make
make -f Makefile-ace # Build compiler
make -f Makefile-ace clean all # Clean rebuild
make -f Makefile-ace V=1 # Verbose outputcd src/make
make -f Makefile-lib # Build db.lib and startup.lib
make -f Makefile-lib clean # Clean first if neededIMPORTANT: compiling the ace compiler takes time, remove recompiling from call-on-ustartup when not needed.
- Read
acedef.hfirst - contains all type definitions and prototypes - Find the relevant module:
lex.c- Lexical analysis (tokenizer)parse.c,parsevar.c- Recursive descent parserexpr.c,factor.c- Expression evaluationstatement.c,control.c,assign.c- Statement handlingsym.c,symvar.c- Symbol table managementmisc.c- Code generation (emits 68000 assembly)opt.c- Peephole optimizer
- Make minimal K&R C changes
- Build and test after each change
- Verify generated
.sassembly is correct
- Identify if C (
src/lib/c/) or assembly (src/lib/asm/) - Rebuild:
make -f Makefile-libfromsrc/make/ - Test with example programs - runtime changes affect all compiled programs
When adding or removing keywords, commands, or functions from the language, the following CubicIDE IDE files must also be updated:
IDE/CubicIDE-ACE/add-ons/ace/autocase/basic- auto-case rulesIDE/CubicIDE-ACE/add-ons/ace/syntax/dictionaries/commands- syntax highlighting (commands)IDE/CubicIDE-ACE/add-ons/ace/syntax/dictionaries/functions- syntax highlighting (functions)docs/quickref.txt- quick reference documentation
Additionally, IDE/CubicIDE-ACE/add-ons/ace/quickinfo/ace.words is a copy of docs/quickref.txt and should be updated whenever quickref.txt changes.
- Choose category: syntax, arithmetic, floats, control, errors
- Create
.bfile in appropriatecases/subdirectory - Add
expected/<testname>.expectedif runtime verification needed - Run:
rx verify/tests/runner.rexx <category>
# On Amiga/emulator
bas myprogram # Compile myprogram.b to executable
bas -E myprogram # Same, but write compiler errors to ace.err in same folder
bas -m mymodule # Compile a submodule (.b -> .o)
bas -mE mymodule # Same, but write compiler errors to ace.err
# To debug compilation issues, run phases separately:
ace myprogram.b # Just compile to .s
vasmm68k_mot -Fhunk -o myprogram.o myprogram.s # Assemble
vlink -o myprogram myprogram.o ACElib:db.lib ACElib:startup.lib # Link- Check if it's a compiler bug or source code issue
- Look at generated
.sassembly file for clues - Run compiler phases separately to isolate the problem
- Check
call-on-ustartupsyntax (AmigaDOS, not bash) - Verify assigns are set correctly
- Check output file on host system (written to
ace:) - Restart emulator if you changed call-on-ustartup
- Ensure you're running from
src/make/directory - Run
make -f <Makefile> cleanfirst - Check for K&R vs ANSI C style issues in compiler changes
Submodules are reusable BASIC libraries in submods/. Each has:
.bsource file (the library code)- Optional
.hheader ininclude/submods/ - Test files for verification
To link a submodule's .o file automatically, add REM #using module.o at the top of the main program. Otherwise, pass the .o file as the last parameter to bas.