Updated docs to describe new SCRIPT blocks including macros
This commit is contained in:
parent
83a0a20393
commit
104e950d63
3 changed files with 256 additions and 1 deletions
|
|
@ -39,6 +39,8 @@ ENDSCRIPT
|
|||
// SCRIPT MACRO: Named macros with parameters
|
||||
//-----------------------------------------------------------
|
||||
SCRIPT MACRO delay(cycles)
|
||||
if cycles < 2:
|
||||
fail("Cannot delay less than 2 cycles")
|
||||
emit_delay(cycles)
|
||||
ENDSCRIPT
|
||||
|
||||
|
|
|
|||
110
language.md
110
language.md
|
|
@ -495,6 +495,101 @@ SCRIPT
|
|||
ENDSCRIPT
|
||||
```
|
||||
|
||||
### SCRIPT LIBRARY Blocks
|
||||
|
||||
Define reusable Starlark functions that persist across all subsequent SCRIPT blocks:
|
||||
|
||||
```c65
|
||||
SCRIPT LIBRARY
|
||||
def emit_nops(count):
|
||||
for i in range(count):
|
||||
print(" nop")
|
||||
|
||||
def emit_delay(cycles):
|
||||
for i in range(cycles // 4):
|
||||
print(" nop")
|
||||
print(" nop")
|
||||
remainder = cycles % 4
|
||||
if remainder >= 3:
|
||||
print(" bit $ea")
|
||||
remainder -= 3
|
||||
for i in range(remainder // 2):
|
||||
print(" nop")
|
||||
ENDSCRIPT
|
||||
|
||||
// Later, use the library functions:
|
||||
SCRIPT
|
||||
emit_nops(5)
|
||||
emit_delay(10)
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
Library functions are typically placed in include files for reuse across projects. Multiple SCRIPT LIBRARY blocks accumulate.
|
||||
|
||||
### SCRIPT MACRO Blocks
|
||||
|
||||
Define named, parameterized macros that expand inline when invoked:
|
||||
|
||||
```c65
|
||||
SCRIPT MACRO delay(cycles)
|
||||
if cycles < 2:
|
||||
fail("Cannot delay less than 2 cycles")
|
||||
emit_delay(cycles)
|
||||
ENDSCRIPT
|
||||
|
||||
SCRIPT MACRO set_irq(handler)
|
||||
print(" lda #<%s" % handler)
|
||||
print(" sta $fffe")
|
||||
print(" lda #>%s" % handler)
|
||||
print(" sta $ffff")
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
#### Invoking Macros
|
||||
|
||||
Outside ASM blocks, use `@name(args)`:
|
||||
|
||||
```c65
|
||||
BYTE CONST CYCLES_PER_LINE = 63
|
||||
|
||||
@delay(10)
|
||||
@delay(CYCLES_PER_LINE-20)
|
||||
@set_irq(my_handler)
|
||||
```
|
||||
|
||||
Inside ASM blocks, use `|@name(args)|`:
|
||||
|
||||
```c65
|
||||
ASM
|
||||
lda #$00
|
||||
|@delay(8)|
|
||||
sta $d020
|
||||
ENDASM
|
||||
```
|
||||
|
||||
#### Parameter Types
|
||||
|
||||
- **Integer expressions**: Numbers, constants, arithmetic - passed as int
|
||||
- **Labels**: Bare identifiers that aren't constants - passed as string
|
||||
|
||||
```c65
|
||||
@delay(10) // 10 passed as int
|
||||
@delay(CYCLES_PER_LINE-20) // Evaluated, passed as int
|
||||
@set_irq(my_handler) // "my_handler" passed as string
|
||||
```
|
||||
|
||||
#### Error Handling
|
||||
|
||||
Use `fail()` to stop compilation with an error:
|
||||
|
||||
```c65
|
||||
SCRIPT MACRO delay(cycles)
|
||||
if cycles < 2:
|
||||
fail("Cannot delay less than 2 cycles")
|
||||
emit_delay(cycles)
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Preprocessor
|
||||
|
|
@ -975,6 +1070,19 @@ ASM
|
|||
ENDASM
|
||||
|
||||
SCRIPT
|
||||
# Python code
|
||||
# Starlark code
|
||||
ENDSCRIPT
|
||||
|
||||
SCRIPT LIBRARY
|
||||
def my_func():
|
||||
print(" nop")
|
||||
ENDSCRIPT
|
||||
|
||||
SCRIPT MACRO name(param)
|
||||
my_func()
|
||||
ENDSCRIPT
|
||||
|
||||
// Macro invocation
|
||||
@name(10) // Outside ASM
|
||||
|@name(10)| // Inside ASM
|
||||
```
|
||||
|
|
|
|||
145
syntax.md
145
syntax.md
|
|
@ -366,6 +366,151 @@ ENDSCRIPT
|
|||
|
||||
---
|
||||
|
||||
### SCRIPT LIBRARY...ENDSCRIPT
|
||||
|
||||
Defines reusable Starlark functions that persist across all subsequent SCRIPT blocks.
|
||||
|
||||
**Syntax:**
|
||||
```
|
||||
SCRIPT LIBRARY
|
||||
<starlark function definitions>
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
|
||||
**Defining reusable functions:**
|
||||
```
|
||||
SCRIPT LIBRARY
|
||||
def emit_nops(count):
|
||||
for i in range(count):
|
||||
print(" nop")
|
||||
|
||||
def emit_delay(cycles):
|
||||
for i in range(cycles // 4):
|
||||
print(" nop")
|
||||
print(" nop")
|
||||
remainder = cycles % 4
|
||||
if remainder >= 3:
|
||||
print(" bit $ea")
|
||||
remainder -= 3
|
||||
for i in range(remainder // 2):
|
||||
print(" nop")
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Using library functions in SCRIPT blocks:**
|
||||
```
|
||||
SCRIPT
|
||||
emit_nops(5)
|
||||
emit_delay(10)
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- Functions defined in SCRIPT LIBRARY are available to all subsequent SCRIPT, SCRIPT LIBRARY, and SCRIPT MACRO blocks
|
||||
- Multiple SCRIPT LIBRARY blocks accumulate - later blocks can use functions from earlier ones
|
||||
- Typically placed in include files for reuse across projects
|
||||
- The library block itself can also use `print()` to emit code, but this is uncommon
|
||||
|
||||
---
|
||||
|
||||
### SCRIPT MACRO...ENDSCRIPT
|
||||
|
||||
Defines a named, parameterized macro that expands inline when invoked.
|
||||
|
||||
**Syntax:**
|
||||
```
|
||||
SCRIPT MACRO name(param1, param2, ...)
|
||||
<starlark code>
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Invocation:**
|
||||
```
|
||||
@name(arg1, arg2, ...) // Outside ASM blocks
|
||||
|@name(arg1, arg2, ...)| // Inside ASM blocks
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
|
||||
**Defining macros:**
|
||||
```
|
||||
SCRIPT MACRO delay(cycles)
|
||||
if cycles < 2:
|
||||
fail("Cannot delay less than 2 cycles")
|
||||
emit_delay(cycles)
|
||||
ENDSCRIPT
|
||||
|
||||
SCRIPT MACRO set_irq(handler)
|
||||
print(" lda #<%s" % handler)
|
||||
print(" sta $fffe")
|
||||
print(" lda #>%s" % handler)
|
||||
print(" sta $ffff")
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Invoking macros outside ASM blocks:**
|
||||
```
|
||||
BYTE CONST CYCLES_PER_LINE = 63
|
||||
|
||||
@delay(10)
|
||||
@delay(CYCLES_PER_LINE-20)
|
||||
@set_irq(my_handler)
|
||||
```
|
||||
|
||||
**Invoking macros inside ASM blocks:**
|
||||
```
|
||||
ASM
|
||||
lda #$00
|
||||
|@delay(8)|
|
||||
sta $d020
|
||||
ENDASM
|
||||
```
|
||||
|
||||
**Parameter Types:**
|
||||
|
||||
1. **Integer expressions** - Evaluated at compile time:
|
||||
- Literal numbers: `10`, `$FF`, `%11110000`
|
||||
- Constants: `CYCLES_PER_LINE`, `MAX_VALUE`
|
||||
- Arithmetic: `CYCLES_PER_LINE-20`, `BASE+OFFSET`
|
||||
- Passed to macro as Starlark `int`
|
||||
|
||||
2. **Labels/Identifiers** - Passed as strings:
|
||||
- Bare identifiers that don't resolve to constants: `my_handler`, `loop_start`
|
||||
- Passed to macro as Starlark `string`
|
||||
- Use in generated assembly: `print(" jmp %s" % label)`
|
||||
|
||||
**Checking parameter types in macros:**
|
||||
```
|
||||
SCRIPT MACRO flexible(value)
|
||||
if type(value) == "int":
|
||||
print(" lda #%d" % value)
|
||||
else:
|
||||
print(" lda %s" % value)
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
**Error handling with fail():**
|
||||
```
|
||||
SCRIPT MACRO delay(cycles)
|
||||
if cycles < 2:
|
||||
fail("Cannot delay less than 2 cycles")
|
||||
emit_delay(cycles)
|
||||
ENDSCRIPT
|
||||
```
|
||||
|
||||
The `fail()` function stops compilation with an error message pointing to the macro invocation site.
|
||||
|
||||
**Notes:**
|
||||
- Macros are NOT executed at definition time - only when invoked
|
||||
- Macros have access to all SCRIPT LIBRARY functions
|
||||
- `print()` output replaces the macro invocation site
|
||||
- Everything expands inline - no JSR/RTS overhead
|
||||
- Use for cycle-critical code like raster timing
|
||||
|
||||
---
|
||||
|
||||
## Expression Syntax
|
||||
|
||||
Expressions evaluate left to right with no operator precedence.
|
||||
|
|
|
|||
Loading…
Reference in a new issue