mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-01-25 08:30:07 +00:00
byte table
-> byte[SIZE]
, and you can reserve
them.
This commit is contained in:
parent
9a0896c90f
commit
9532a9399c
@ -90,6 +90,30 @@ poisoned in the result context.
|
||||
(Same should apply for `repeat` and `with` and, really, many other cases
|
||||
which there just aren't enough test cases for yet.)
|
||||
|
||||
### "It's a Partial Solution" ###
|
||||
|
||||
SixtyPical does not attempt to force your typed, abstractly interpreted
|
||||
program to be absolutely watertight. In assembly language on an 8-bit
|
||||
microprocessor, you will sometimes _need_ to do dangerous and tricky things,
|
||||
like self-modifying code and cycle-counting, in order to accomplish a
|
||||
sophisticated effect, like a raster interrupt trick.
|
||||
|
||||
For that reason, `sixtypical` does not attempt to emit a fully-formed
|
||||
Ophis assembler source. Instead, it expects you to mix its output with
|
||||
some raw Ophis assembler to make a complete program. This "mixin" may contain
|
||||
as much unchecked assembler code as you like. An example is provided in the
|
||||
`lib` directory which adds a prelude that makes the resulting program
|
||||
runnable from Commodore BASIC 2.0 and stores uninitialized data at `$C000`.
|
||||
|
||||
In addition, various checks are not attempted (such as tracking the usage
|
||||
of an indirect indexed table) and other checks may be subverted (for example
|
||||
by `locate`ing two variables with two different types of storage at the same
|
||||
address.)
|
||||
|
||||
In summary, SixtyPical helps you write a very-nearly-assembly-level program
|
||||
which is a bit more "solid" than raw assembly, but it still expects you to
|
||||
know what you're doing down there.
|
||||
|
||||
For More Information
|
||||
--------------------
|
||||
|
||||
@ -123,7 +147,6 @@ TODO
|
||||
----
|
||||
|
||||
* Initial values for reserved tables
|
||||
* give length for tables, must be there for reserved, if no init val
|
||||
* Character tables ("strings" to everybody else)
|
||||
* Addressing modes — indexed mode on more instructions
|
||||
* `jsr (vector)`
|
||||
|
@ -116,8 +116,8 @@ Test for many combinations of `reserve` and `assign`.
|
||||
| assign word memstr 641
|
||||
| reserve vector v
|
||||
| assign vector cinv 788
|
||||
| reserve byte table frequencies
|
||||
| assign byte table screen 1024
|
||||
| reserve byte[16] frequencies
|
||||
| assign byte[256] screen 1024
|
||||
| routine main {
|
||||
| nop
|
||||
| }
|
||||
@ -223,7 +223,7 @@ We can't jump indirectly through a byte.
|
||||
|
||||
We can absolute-indexed a byte table.
|
||||
|
||||
| assign byte table screen 1024
|
||||
| assign byte[256] screen 1024
|
||||
| routine main {
|
||||
| sta screen, x
|
||||
| }
|
||||
@ -296,9 +296,9 @@ An address knows what kind of data is stored at the address:
|
||||
* `jsr`'ing indirectly to a vector (which is done with a fun
|
||||
generated trick (NYI))
|
||||
|
||||
* `byte table`: a series of `byte`s contiguous in memory starting from the
|
||||
address. This is the only kind of address that can be used in
|
||||
indexed addressing.
|
||||
* `byte [SIZE]`: a series of `SIZE` `byte`s contiguous in memory starting
|
||||
from the address. This is the only kind of address that can be used in
|
||||
indexed addressing. `SIZE` has a minimum of 1 and a maximum of 256.
|
||||
|
||||
### Blocks ###
|
||||
|
||||
|
@ -189,3 +189,25 @@ Copy command: immediate -> word
|
||||
=
|
||||
= .data
|
||||
= .space position 2
|
||||
|
||||
Reserving and assigning byte tables.
|
||||
|
||||
| reserve byte[16] frequencies
|
||||
| assign byte[256] screen $0400
|
||||
| routine main {
|
||||
| lda #0
|
||||
| ldy #0
|
||||
| sta frequencies, y
|
||||
| sta screen, y
|
||||
| }
|
||||
= main:
|
||||
= lda #0
|
||||
= ldy #0
|
||||
= sta frequencies, y
|
||||
= sta screen, y
|
||||
= rts
|
||||
=
|
||||
= .data
|
||||
= .space frequencies 16
|
||||
= .alias screen 1024
|
||||
|
||||
|
@ -150,7 +150,7 @@ Big test for parsing and emitting instructions.
|
||||
|
||||
| reserve word vword
|
||||
| reserve byte vbyte
|
||||
| assign byte table table 1024
|
||||
| assign byte[256] table 1024
|
||||
| routine main {
|
||||
| lda #4
|
||||
| ldx #0
|
||||
@ -263,7 +263,7 @@ Big test for parsing and emitting instructions.
|
||||
|
||||
| reserve word vword
|
||||
| reserve byte vbyte
|
||||
| assign byte table table 1024
|
||||
| assign byte[256] table 1024
|
||||
| routine main {
|
||||
| asl .a
|
||||
| asl vbyte
|
||||
|
@ -30,8 +30,8 @@ noIndexedAccessOfNonTables p@(Program decls routines) =
|
||||
where
|
||||
checkInstr j@(COPY _ (Indexed (NamedLocation sz g) reg)) =
|
||||
case lookupDecl p g of
|
||||
Just (Assign _ ByteTable _) -> j
|
||||
Just (Reserve _ ByteTable _) -> j
|
||||
Just (Assign _ (ByteTable _) _) -> j
|
||||
Just (Reserve _ (ByteTable _) _) -> j
|
||||
Just _ -> (COPY A A)
|
||||
Nothing -> (COPY A A)
|
||||
checkInstr other = other
|
||||
@ -158,8 +158,8 @@ fillOutNamedLocationTypes p@(Program decls routines) =
|
||||
in
|
||||
case (typeRx == typeRy, typeRx, typeRy) of
|
||||
(True, _, _) -> constructor rx ry
|
||||
(_, Byte, ByteTable) -> constructor rx ry
|
||||
(_, ByteTable, Byte) -> constructor rx ry
|
||||
(_, Byte, (ByteTable _)) -> constructor rx ry
|
||||
(_, (ByteTable _), Byte) -> constructor rx ry
|
||||
_ -> error ("incompatible types '" ++ (show typeRx) ++ "' and '" ++ (show typeRy) ++ "'")
|
||||
resolve (NamedLocation Nothing name) =
|
||||
case lookupDecl p name of
|
||||
|
@ -30,6 +30,9 @@ emitDecl p (Reserve name typ (Just val))
|
||||
| typ == Word = name ++ ": .word " ++ (show val)
|
||||
| typ == Vector = name ++ ": .word " ++ (show val)
|
||||
|
||||
emitDecl p (Reserve name (ByteTable size) Nothing) =
|
||||
".space " ++ name ++ " " ++ (show size)
|
||||
|
||||
emitDecl p (Reserve name typ Nothing)
|
||||
| typ == Byte = ".space " ++ name ++ " 1"
|
||||
| typ == Word = ".space " ++ name ++ " 2"
|
||||
@ -79,11 +82,11 @@ emitInstr p r (COPY A Y) = "tay"
|
||||
emitInstr p r (COPY X A) = "txa"
|
||||
emitInstr p r (COPY Y A) = "tya"
|
||||
|
||||
emitInstr p r (COPY A (Indexed (NamedLocation (Just ByteTable) label) X)) = "sta " ++ label ++ ", x"
|
||||
emitInstr p r (COPY A (Indexed (NamedLocation (Just ByteTable) label) Y)) = "sta " ++ label ++ ", y"
|
||||
emitInstr p r (COPY A (Indexed (NamedLocation (Just (ByteTable _)) label) X)) = "sta " ++ label ++ ", x"
|
||||
emitInstr p r (COPY A (Indexed (NamedLocation (Just (ByteTable _)) label) Y)) = "sta " ++ label ++ ", y"
|
||||
|
||||
emitInstr p r (COPY (Indexed (NamedLocation (Just ByteTable) label) X) A) = "lda " ++ label ++ ", x"
|
||||
emitInstr p r (COPY (Indexed (NamedLocation (Just ByteTable) label) Y) A) = "lda " ++ label ++ ", y"
|
||||
emitInstr p r (COPY (Indexed (NamedLocation (Just (ByteTable _)) label) X) A) = "lda " ++ label ++ ", x"
|
||||
emitInstr p r (COPY (Indexed (NamedLocation (Just (ByteTable _)) label) Y) A) = "lda " ++ label ++ ", y"
|
||||
|
||||
emitInstr p r (COPY A (IndirectIndexed (NamedLocation st label) Y)) = "sta (" ++ label ++ "), y"
|
||||
emitInstr p r (COPY (IndirectIndexed (NamedLocation st label) Y) A) = "lda (" ++ label ++ "), y"
|
||||
|
@ -23,7 +23,7 @@ type LocationName = String
|
||||
data StorageType = Byte
|
||||
| Word
|
||||
| Vector
|
||||
| ByteTable
|
||||
| ByteTable DataValue
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
data StorageLocation = A
|
||||
|
@ -14,7 +14,7 @@ Toplevel := {Decl} {Routine}.
|
||||
Decl := "reserve" StorageType LocationName [":" Literal]
|
||||
| "assign" StorageType LocationName Literal
|
||||
| "external" RoutineName Address.
|
||||
StorageType := "byte" | "word" | "byte table" | "vector".
|
||||
StorageType := "byte" ["[" Literal "]"] | "word" | "vector".
|
||||
Routine := "routine" RoutineName ["outputs" "(" {LocationName} ")"] Block.
|
||||
Block := "{" {Command} "}".
|
||||
Command := "if" Branch Block "else" Block
|
||||
@ -91,17 +91,26 @@ external = do
|
||||
addr <- literal_address
|
||||
return $ External name addr
|
||||
|
||||
get_storage "byte" = Byte
|
||||
get_storage "word" = Word
|
||||
get_storage "vector" = Vector
|
||||
get_storage "byte table" = ByteTable
|
||||
storage :: String -> StorageType -> Parser StorageType
|
||||
storage s t = do
|
||||
string s
|
||||
nspaces
|
||||
return t
|
||||
|
||||
byte_table :: Parser StorageType
|
||||
byte_table = do
|
||||
string "byte"
|
||||
nspaces
|
||||
string "["
|
||||
nspaces
|
||||
size <- literal_data_value
|
||||
string "]"
|
||||
nspaces
|
||||
return $ ByteTable size
|
||||
|
||||
storage_type :: Parser StorageType
|
||||
storage_type = do
|
||||
s <- (try $ string "byte table") <|> (string "byte") <|>
|
||||
(string "word") <|> (string "vector")
|
||||
nspaces
|
||||
return $ get_storage s
|
||||
storage_type = (try $ byte_table) <|> (storage "byte" Byte) <|>
|
||||
(storage "word" Word) <|> (storage "vector" Vector)
|
||||
|
||||
routine :: Parser Routine
|
||||
routine = do
|
||||
|
Loading…
x
Reference in New Issue
Block a user