6.3 KiB
6.3 KiB
i swear this is what fuzzy actually does
the stack
fuzzy works on a 16-bit cell-width, zero-page data stack indexed with the x register, as documented in Garth Wilson's stack treatise
to push a byte onto the data stack, we just:
dex ; decrement the stack pointer
lda some_value ; load the byte we want on the stack into a
sta 0, x ; put the byte on the stack!
and to pop a byte off it:
lda 0, x ; pop the top of stack off into a
inx ; increment the stack pointer
types
these are used in word definitions, and refer to the type of an individual stack cell:
| type | desc |
|---|---|
| bool | a boolean value, represented by $0000 or $ffff |
| nat | an unsigned 16-bit integer |
| int | a signed 16-bit integer |
| char | an 8-bit george-ascii character, padded with leading zeroes |
| string | a 16-bit pointer to a string in memory |
word dangerous |
a 16-bit pointer to a fuzzy word or quotation |
operators
!NOT: applies NOT to tos&AND: pops 2 off the stack and pushes the AND'ed result|OR: pops 2 off the stack and pushes the OR'ed result+add: pops 2 off the stack and pushes the sum-subtract: pops 2 off the stack and pushes the difference*multiply: pops 2 off the stack and pushes the result, truncating if it's >$FFFF/divide: pops 2 off the stack and pushes the remainder and quotient=equality: pushes true/false if the top 2 stack cells do/don't match>greater than: pushes true/false if tos-1 is/isn't greater than tos<less than: pushes true/false if tos-1 is/isn't greater than tos#quotedangerous: pops tos and pushes a word that produces its value
supported types (this will need to be more clearly laid out later)
| operator | input type | output type | notes |
|---|---|---|---|
! |
bool, nat, int |
bool, nat, int |
|
& |
bool, nat, int |
bool, nat, int |
|
| |
bool, nat, int |
bool, nat, int |
|
+ |
nat nat, int int |
nat, int |
|
- |
nat nat, int int |
nat, int |
subtracting two nats |
* |
nat nat, int int |
nat, int |
most products will be truncated, since most 16 bit multiplications result in a >16 bit product, but in practice that shouldn't matter cause we're not doing science |
/ |
nat nat, int int |
nat nat, int int |
produces two cells, the quotient and remainder |
= |
any any | bool |
equality/order is checked based on stack cell value, not type (e.g. a word pointing to $abcd and a nat with the value $abcd are equivalent) |
> |
any any | bool |
see above |
< |
any any | bool |
see above |
# |
any | word |
dangerous |
danger!
the danger! keyword marks a word as being dangerous. certain language features can only be used in dangerous words, such as:
- inline assembly
- quotations
- typechecking quotations is a difficult problem & probably too complex too implement on george if we ever want to fully self-host fuzzy
- unchecked operator usage
- applying
+to two chars, applying&to two strings, etc - this does not mean that dangerous words are untyped! just the type of the result of an operation is asserted to be the word result type
danger! dangerous_word num num is char: +can't be used on anum charstack, and any words used afterdangerous_wordtreat the top of the stack as having acharand don't care that it was made with twonums
- applying
the program body cannot use any dangerous features. this makes it so that dangerous behavior is contained to specific words.
memory layout
| start | end | use |
|---|---|---|
$200 |
$300 |
|
| core language implementation | ||
| core language implementation |