fuzzy's compiler is written in assembly now :)
This commit is contained in:
parent
2d4df76be7
commit
c0e7f4024c
24
README.md
24
README.md
|
@ -16,16 +16,26 @@ fuzzy is part of george, and shouldn't run anywhere else.
|
||||||
|
|
||||||
#### low-level
|
#### low-level
|
||||||
|
|
||||||
(most of) fuzzy could be made with assembler macros, but that's no fun
|
(most of) fuzzy could be written as assembler macros, but that's no fun
|
||||||
|
|
||||||
#### reliable
|
#### reliable
|
||||||
|
|
||||||
if fuzzy says it can run, george can run it
|
if fuzzy says it can run, george can run it
|
||||||
|
|
||||||
## feature progress
|
## how to work on fuzzy
|
||||||
|
|
||||||
- [x] parser
|
edit `program.asm` and run `./run.sh`. the program gets included in the fuzzy compiler `fuzzy.asm` and is assembled with `vasm6502_oldstyle`, then george runs the program, reading out her system image when she reaches `stp` or `brk`
|
||||||
- roughly complete, but want to finish the whole pipeline before adding things to the parser
|
|
||||||
- [x] typechecker
|
then the program she compiled gets formatted as a standard 32k rom, and she reads it again, and then shows her system image again when the program finishes (hits `stp` or `brk`).
|
||||||
- generates a "type stack" from parsed input and checks that word definition types match their body
|
|
||||||
- [ ] code generation
|
since fuzzy works on a zero-page data stack, it's pretty easy to read the results of a program from the hexdump.
|
||||||
|
|
||||||
|
for now this loop only works on apple silicon, but eventually i'll compile a `george` binary for x86 linux and switch based on the host platform.
|
||||||
|
|
||||||
|
## reference help
|
||||||
|
|
||||||
|
i wrote [syntax](./syntax.md) and [semantics](./semantics.md) docs to keep track of how fuzzy works before starting work on the compiler implementation in assembly. they're the _official_ source of truth for how fuzzy works. assume that the compiler implementation is always in flux :)
|
||||||
|
|
||||||
|
## a note on implementation
|
||||||
|
|
||||||
|
i was writing fuzzy's compiler in rust for a sec, but then i realized that it would be a fun challenge to write it in assembly. it's been wayyy easier! and fun! and so rewarding :) this feels like a flex but i'm genuinely just so happy to see george & fuzzy playing together in this little computer world i've made <3
|
||||||
|
|
46
fuzzy.asm
46
fuzzy.asm
|
@ -12,7 +12,7 @@ binary_subroutine_address = binary_base_index + 1 ; pointer to a subroutine to b
|
||||||
.include "./subroutines.inc"
|
.include "./subroutines.inc"
|
||||||
|
|
||||||
program_text:
|
program_text:
|
||||||
.asciiz '2 3 +'
|
.include "./program.inc"
|
||||||
|
|
||||||
reset:
|
reset:
|
||||||
sei
|
sei
|
||||||
|
@ -74,6 +74,9 @@ compile_values_op:
|
||||||
; cmp #"#"
|
; cmp #"#"
|
||||||
|
|
||||||
; a holds character value, y program text index, only iny if you find a matching character & consume it
|
; a holds character value, y program text index, only iny if you find a matching character & consume it
|
||||||
|
; TODO:
|
||||||
|
; 1-3 digit decimal values
|
||||||
|
; 1-2 digit hex values
|
||||||
compile_values_nat:
|
compile_values_nat:
|
||||||
; TODO:
|
; TODO:
|
||||||
; cmp #"$" ; is hex?
|
; cmp #"$" ; is hex?
|
||||||
|
@ -84,14 +87,20 @@ compile_values_nat:
|
||||||
bcc .not_nat
|
bcc .not_nat
|
||||||
cmp #57 ; greater than end of 0-9 georgescii range?
|
cmp #57 ; greater than end of 0-9 georgescii range?
|
||||||
bcs .not_nat
|
bcs .not_nat
|
||||||
|
pha
|
||||||
|
lda #$a9 ; $a9: lda imm
|
||||||
|
jsr store_binary
|
||||||
|
pla
|
||||||
jsr georgescii_decimal_to_value
|
jsr georgescii_decimal_to_value
|
||||||
jsr store_binary
|
jsr store_binary
|
||||||
|
lda #2 ; push
|
||||||
|
jsr store_subroutine
|
||||||
iny
|
iny
|
||||||
rts
|
rts
|
||||||
.not_nat:
|
.not_nat:
|
||||||
rts
|
rts
|
||||||
|
|
||||||
; georgescii decmal value in a register, return equivalent plain value in a register
|
; georgescii decimal value in a register, return equivalent plain value in a register
|
||||||
georgescii_decimal_to_value:
|
georgescii_decimal_to_value:
|
||||||
clc
|
clc
|
||||||
sbc #$30 ; decimal digits start at georgescii $30
|
sbc #$30 ; decimal digits start at georgescii $30
|
||||||
|
@ -113,11 +122,9 @@ store_binary:
|
||||||
; the first byte at the subroutine's address is its length
|
; the first byte at the subroutine's address is its length
|
||||||
store_contiguous_binary:
|
store_contiguous_binary:
|
||||||
pha ; just to be safe
|
pha ; just to be safe
|
||||||
phy
|
|
||||||
phx
|
|
||||||
lda (binary_subroutine_address) ; get the subroutine length
|
lda (binary_subroutine_address) ; get the subroutine length
|
||||||
tax ; loop counter
|
tax ; loop counter
|
||||||
ldy #0 ; index into subroutine
|
ldy #1 ; index into subroutine, offset by one to skip subroutine length
|
||||||
.loop:
|
.loop:
|
||||||
lda (binary_subroutine_address), y
|
lda (binary_subroutine_address), y
|
||||||
jsr store_binary
|
jsr store_binary
|
||||||
|
@ -125,8 +132,6 @@ store_contiguous_binary:
|
||||||
dex
|
dex
|
||||||
bne .loop
|
bne .loop
|
||||||
.end:
|
.end:
|
||||||
phx
|
|
||||||
ply
|
|
||||||
pla
|
pla
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
@ -136,6 +141,7 @@ store_contiguous_binary:
|
||||||
; for now, pass the index of the subroutine (in subroutines.asm)
|
; for now, pass the index of the subroutine (in subroutines.asm)
|
||||||
; to a and it will get written to binary_subroutine_address
|
; to a and it will get written to binary_subroutine_address
|
||||||
get_subroutine_address:
|
get_subroutine_address:
|
||||||
|
pha
|
||||||
tax ; set up counter
|
tax ; set up counter
|
||||||
bne .loop ; first subrotine?
|
bne .loop ; first subrotine?
|
||||||
stz binary_subroutine_address ; yes, store its address
|
stz binary_subroutine_address ; yes, store its address
|
||||||
|
@ -155,16 +161,42 @@ get_subroutine_address:
|
||||||
.no_carry:
|
.no_carry:
|
||||||
dex ; is this our address?
|
dex ; is this our address?
|
||||||
bne .loop ; yes, we're done
|
bne .loop ; yes, we're done
|
||||||
|
pla
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
|
||||||
; pass subroutine index to a and it will get written into the binary
|
; pass subroutine index to a and it will get written into the binary
|
||||||
; TODO: stabilize subroutine location & just write a `jsr $subroutine` to the binary
|
; TODO: stabilize subroutine location & just write a `jsr $subroutine` to the binary
|
||||||
store_subroutine:
|
store_subroutine:
|
||||||
|
pha
|
||||||
|
phy
|
||||||
|
phx
|
||||||
jsr get_subroutine_address
|
jsr get_subroutine_address
|
||||||
jsr store_contiguous_binary
|
jsr store_contiguous_binary
|
||||||
|
; reset subroutine address
|
||||||
|
stz binary_subroutine_address
|
||||||
|
lda #$80
|
||||||
|
sta binary_subroutine_address + 1
|
||||||
|
plx
|
||||||
|
ply
|
||||||
|
pla
|
||||||
rts
|
rts
|
||||||
|
|
||||||
|
; write error message and stop execution
|
||||||
|
error:
|
||||||
|
ldy #0
|
||||||
|
.loop:
|
||||||
|
lda .message, y
|
||||||
|
sta $4000, y
|
||||||
|
beq .end
|
||||||
|
iny
|
||||||
|
bra .loop
|
||||||
|
.end:
|
||||||
|
stp
|
||||||
|
.message:
|
||||||
|
.asciiz "ruh roh! fuzzy couldn't compile"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
isr: ; interrupt service routine
|
isr: ; interrupt service routine
|
||||||
pha
|
pha
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
.asciiz '2 3 +'
|
13
run.sh
13
run.sh
|
@ -2,6 +2,15 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
vasm6502_oldstyle fuzzy.asm -dotdir -wdc02 -ldots -Fbin -o fuzzy.rom;
|
rm *.bin *.rom
|
||||||
cat fuzzy.rom | ./george > result.bin;
|
vasm6502_oldstyle fuzzy.asm -dotdir -wdc02 -ldots -Fbin -o fuzzy.rom &> /dev/null;
|
||||||
|
echo -e "\nʕ·ᴥ·ʔ- source text:\n";
|
||||||
|
cat program.inc;
|
||||||
|
cat fuzzy.rom | ./george > compiled.bin;
|
||||||
|
dd skip=16384 count=500 if=compiled.bin of=compiled.rom bs=1 &> /dev/null;
|
||||||
|
truncate -s 32k compiled.rom &> /dev/null;
|
||||||
|
printf '\x80\x00\x00' | dd of=compiled.rom bs=1 seek=32765 count=3 conv=notrunc &> /dev/null;
|
||||||
|
cat compiled.rom | ./george > result.bin;
|
||||||
|
echo -e "\n\nʕ·ᴥ·ʔ- compiled program result:\n";
|
||||||
hexdump -C ./result.bin;
|
hexdump -C ./result.bin;
|
||||||
|
echo -e "";
|
||||||
|
|
|
@ -4,4 +4,12 @@ test_contiguous_binary:
|
||||||
|
|
||||||
; 1 - assembled from "plus.asm"
|
; 1 - assembled from "plus.asm"
|
||||||
subroutine_plus:
|
subroutine_plus:
|
||||||
.byte 17,$b5,$18,$75,$00,$95,$02,$b5,$02,$75,$01,$95,$03,$e8,$03,$60,$e8,$60
|
.byte 15, $18,$b5,$00,$75,$02,$95, $02, $b5, $01, $75, $03, $95, $03, $ca, $ca
|
||||||
|
|
||||||
|
; 2
|
||||||
|
subroutine_push:
|
||||||
|
.byte 6,$ca,$ca,$95,$0,$74,$1
|
||||||
|
; dex
|
||||||
|
; dex
|
||||||
|
; sta 0, x
|
||||||
|
; stz 1, x
|
||||||
|
|
Loading…
Reference in New Issue