In bare metal assembly, structures don't exist. There are only addresses and offsets you keep in your head. Add a field at the start — now you get to hunt down every `LD (IX+2)` and turn it into `(IX+4)`. On a good day, you'll only miss a few. The debugger won't care.
We made structures real.
Here's how it works. Define the type:
```lisp
(deftype vec3 (structure)
((x int16)
(y int16)
(z int16))
(:methods
(clear () none)))
```
Use it like you mean it:
```lisp
(defmethod clear ((self vec3))
(rlet ((v :reg ix :source self))
(zasm
(.ld (-> v x) 0)
(.ld (-> v y) 0)
(.ld (-> v z) 0))))
```
No magic numbers. The language knows `y` lives at offset 2, and `ix` currently points at the object. Compiler plugs in the right addresses, spits this out:
```
DD 36 00 00 | LD (IX+0), $00
DD 36 02 00 | LD (IX+2), $00
DD 36 04 00 | LD (IX+4), $00
```
**What you actually get:**
- **No offset bookkeeping.** Write `(-> v y)`, compiler handles the math.
- **Errors where they belong.** Typo in field name? Assembly fails right there, not after three hours of debugging.
- **Register independence.** Want `iy` instead of `ix`? Change one line in `rlet`, the whole block retargets.
This isn't about making Z80 look like Lisp. It's about using macros to bridge the gap between how humans think about code and what the CPU actually executes. Names, types, checks — without leaving the metal.
h2w
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.