PL/SW (Programming Language for Software Wrighter) compiler for the COR24 24-bit RISC ISA.
A freestanding, PL/I-inspired systems language with compile-time macro metaprogramming, BASED record templates, and controlled inline assembly. Transpiles to human-readable COR24 assembler source (.s) with interleaved source-line comments.
All 40 implementation steps complete across 12 phases:
- Lexer -- tokenizer with keywords, operators, string/number literals
- Parser -- recursive descent for DCL, PROC, IF, DO WHILE, DO count
- AST -- 256-node pool with 18 node kinds
- Symbol table -- scoped (global + per-procedure), type tracking
- Type system -- INT(8/16/24), BYTE, CHAR, PTR, WORD, BIT, RECORD
- Storage layout -- stack frames, static data, record field offsets
- Code generation -- COR24 assembly for all constructs
- Inline assembly -- ASM DO blocks, NAKED procedures
- Macros -- MACRODEF/GEN, %INCLUDE, ?MACRO() invocation
- Conditionals -- %IF/%DEFINE/%ELSE/%ENDIF, %DEFINE value substitution
- Built-ins -- ADDR(), SIZEOF(), string literal assignment to ptr->field
- Listing -- source lines as assembly comments, line numbers in errors
- Pipeline -- FILE: protocol for multi-file compilation via UART
# Build the compiler (requires tc24r, cor24-asm, cor24-emu)
just build # produces build/plsw.s
just build-lgo # produces build/plsw.lgo (canonical shippable)
# Compile and run hello world
just pipeline examples/hello.plsw
# Output: Hello from PL/SW!
# Compile with .msw includes and memory dump
just chain
# Output: build/chain.s, build/chain.lgo, build/chain-dump.txt,
# build/chain-combined.plsw
# Compile macro demo
just hello-macro
# Output: Hello from macros!After just build-lgo, the canonical shippable is build/plsw.lgo.
Downstream consumers run the compiler directly without re-assembling:
cor24-emu --lgo path/to/plsw.lgo --terminal --echo --speed 0Layer 1 native binaries (link24 and meta-gen, used for separate
compilation and FIXUP-based linking) build with just install-layer1:
just install-layer1
# -> dist/bin/link24
# -> dist/bin/meta-genBoth targets are gitignored. The shared toolchain orchestrator
(tools/build-all) installs them into the canonical toolchain
location post-relay.
| File | Description |
|---|---|
examples/hello.plsw |
Hello world via UART_PUTS |
examples/led.plsw |
LED MMIO toggle with inline ASM |
examples/loop.plsw |
DO I = 1 TO 10 with PRINT_INT |
examples/record.plsw |
Record fields and pointer dereference |
examples/chain.plsw |
Control block chain (CVT/ASCB/ASXB/TCB) with arena allocator |
examples/macro.plsw |
?LED_SET and ?NOP macro invocation |
examples/hello_macro.plsw |
?GREET macro via %INCLUDE |
The compiler runs on the COR24 emulator. Source is fed via UART:
.plsw + .msw files --> pipeline.sh --> compiler on emulator
|
.s assembly
|
cor24-run --run --> program output
For multi-file compilation, the FILE:/SOURCE: protocol registers
named include files so %INCLUDE name; resolves them:
./scripts/pipeline-dump.sh include/cvt.msw include/ascb.msw examples/chain.plswOutput files: build/<name>.s, build/<name>-dump.txt, build/<name>-combined.plsw
just build # Compile the PL/SW compiler itself (.s)
just build-lgo # Assemble compiler to .lgo (canonical shippable)
just run # Interactive mode (terminal)
just smoke # Run compiler with cycle limit (binary smoke)
just pipeline <f> # Compile and run a .plsw
just pipeline-dump <files> # Compile, run with memory dump
just chain # Control block chain demo
just hello-macro # Macro demo
just install-layer1 # Stage link24 + meta-gen for the toolchain orchestrator
just test # Run the reg-rs regression suite
just test-bootstrap-goldens # (Re)create reg-rs goldens; commit the result
just test-linker # Run the components/linker integration demos
just clean # Remove build artifactsRegression testing details: see docs/testing.md.
- Usage Guide & Language Reference
- Product Requirements
- Architecture
- Design Decisions
- Implementation Plan
- Research Notes
- Assembler Directive Report
- Testing & Regression Suite
- 24-bit RISC, 8 registers (r0-r2 GP, fp, sp, z, iv, ir)
- 1 MB SRAM + 8 KB EBR stack
- UART at 0xFF0100 (data), 0xFF0101 (status)
- LED at 0xFF0000 (active-low)
- Variable-length instructions (1, 2, or 4 bytes)
- Calling convention: args on stack R-to-L, return in r0
- sw-cor24-snobol4 -- SNOBOL4 interpreter for COR24
Note: SNOBOL was originally implemented in SIL (SNOBOL Implementation Language) which had macros, much like PL/SW does.
- Blog: Software Wrighter Lab
- Discord: Join the community
- YouTube: Software Wrighter
Copyright (c) 2026 Michael A Wright. MIT-licensed; see LICENSE.