; ops ; - [ ] nat (positive integers) ; - [ ] * mult (i think anything bigger than 16 bits just gets cut off, george does not need big numbers rite) ; - [ ] / div (what do we do w fractions/remainders) ; - [ ] + add (same w *) ; - [ ] - sub (what should happen when y > x & x - y? ) ; - [ ] int (pos/neg 2s complement numbers) (lots of the above applies) ; - [ ] * mult ; - [ ] / div ; - [ ] + add ; - [ ] - sub ; - [ ] bool ; - [ ] & and ; - [ ] | or ; ; literals (these will be macros here, meaning when i implement them in the compiler they will depend on what literals r being pushed) ; - [ ] bool ; - [ ] num ; - [ ] str ; - [ ] char ; ; i/o ; - [ ] write (pop off an address and some data and store it) ; - [ ] read (pop off an address and push the data at that address onto the stack) ; - [ ] key (stealing algo from forth: pause execution until there's a key pressed, then push that key on the stack, i don't think this breaks anything, this could probably be written easily in fuzzy w/ write and read words) ; ; control flow ; - [ ] if (pop off a bool and jump to word, this will also depend on compiler, so writing as macro) ; for example ; a is nat: 5 ; b is nat: 3 ; c bool is nat: if[a | b] *we'll figure out syntax later* ; true c ; ; (assuming c gets inlined since it's only referenced in the body) ; compiles to ; a: ; lda 5 ; dex ; dex ; sta 0, x ; rts ; ; b: ; lda 3 ; dex ; dex ; sta 0, x ; rts ; ; main: ; lda #1 ; dex ; dex ; sta 0, x ; stz 1,x ; lda #1 ; inx ; inx ; bit 2, x ; beq .falsy ; jsr a ; .falsy: ; jsr b ; stp ; or whatever here ; literals - the important thing is what the actual value is, each of these functions/macros are the same for any type, since the val is always just a 16 bit number .macro lit, val lda val dex dex sta 0, x stz 1, x .endm ; control flow .macro if, bool, addr ; condition, where to jump if true; pops a bool off the stack lda #1 ; in either case we pop a cell off the top inx inx ; but still need to check the bool on top ; TODO: make sure this works bit 2, x beq .falsy ; TODO: words will be defined as subroutines ig, ; and will be returned from after execution jsr addr .falsy: .endm ; ops nat_plus: clc lda 0, x adc 2, x sta 2, x lda 1, x adc 3, x sta 3, x inx inx rts nat_mult_2: asl 0, x rol 1, x rts ; after a silly escapade plotting u16 overflow charts ; i am making the executive decision that the vast majority ; of results (those that overflow 2 bytes) will be wrong :) ; for the sake of all results being 1 cell wide :) ; see this plot: ./overflow.png ; algo here: https://www.llx.com/Neil/a2/mult.html nat_mult: result = $200 lda #0 ; initialize result to 0 sta result+2 ldy #16 ; 16 bits in NUM2 .1: lsr 0, x ; low byte of first number ror 1, x bcc .2 ; 0 or 1? phy ; some register shuffling so we don't lose x stack pointer tay clc lda 2, x ; low byte of second number adc result + 2 ; add it to low byte of result sta result + 2 tya ply adc 3, x ; .2: ror ror result + 2 ror result + 1 ror result dey bne .1 sta result + 3 dex dex ; TODO: double check endianness of result lda result + 3 ; store high byte of result sta 0, x lda result + 2 ; store low byte of result sta 1, x rts ; i/o read: lda (0, x) sta 0, x stz 1, x rts write: lda 0, x sta (2, x) inx inx inx inx rts key: ;TODO