git @ Cat's Eye Technologies SixtyPical / 9532a93
`byte table` -> `byte[SIZE]`, and you can `reserve` them. Cat's Eye Technologies 7 years ago
8 changed file(s) with 86 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
8989 (Same should apply for `repeat` and `with` and, really, many other cases
9090 which there just aren't enough test cases for yet.)
9191
92 ### "It's a Partial Solution" ###
93
94 SixtyPical does not attempt to force your typed, abstractly interpreted
95 program to be absolutely watertight. In assembly language on an 8-bit
96 microprocessor, you will sometimes _need_ to do dangerous and tricky things,
97 like self-modifying code and cycle-counting, in order to accomplish a
98 sophisticated effect, like a raster interrupt trick.
99
100 For that reason, `sixtypical` does not attempt to emit a fully-formed
101 Ophis assembler source. Instead, it expects you to mix its output with
102 some raw Ophis assembler to make a complete program. This "mixin" may contain
103 as much unchecked assembler code as you like. An example is provided in the
104 `lib` directory which adds a prelude that makes the resulting program
105 runnable from Commodore BASIC 2.0 and stores uninitialized data at `$C000`.
106
107 In addition, various checks are not attempted (such as tracking the usage
108 of an indirect indexed table) and other checks may be subverted (for example
109 by `locate`ing two variables with two different types of storage at the same
110 address.)
111
112 In summary, SixtyPical helps you write a very-nearly-assembly-level program
113 which is a bit more "solid" than raw assembly, but it still expects you to
114 know what you're doing down there.
115
92116 For More Information
93117 --------------------
94118
122146 ----
123147
124148 * Initial values for reserved tables
125 * give length for tables, must be there for reserved, if no init val
126149 * Character tables ("strings" to everybody else)
127150 * Addressing modes — indexed mode on more instructions
128151 * `jsr (vector)`
115115 | assign word memstr 641
116116 | reserve vector v
117117 | assign vector cinv 788
118 | reserve byte table frequencies
119 | assign byte table screen 1024
118 | reserve byte[16] frequencies
119 | assign byte[256] screen 1024
120120 | routine main {
121121 | nop
122122 | }
222222
223223 We can absolute-indexed a byte table.
224224
225 | assign byte table screen 1024
225 | assign byte[256] screen 1024
226226 | routine main {
227227 | sta screen, x
228228 | }
295295 * `jsr`'ing indirectly to a vector (which is done with a fun
296296 generated trick (NYI))
297297
298 * `byte table`: a series of `byte`s contiguous in memory starting from the
299 address. This is the only kind of address that can be used in
300 indexed addressing.
298 * `byte [SIZE]`: a series of `SIZE` `byte`s contiguous in memory starting
299 from the address. This is the only kind of address that can be used in
300 indexed addressing. `SIZE` has a minimum of 1 and a maximum of 256.
301301
302302 ### Blocks ###
303303
188188 =
189189 = .data
190190 = .space position 2
191
192 Reserving and assigning byte tables.
193
194 | reserve byte[16] frequencies
195 | assign byte[256] screen $0400
196 | routine main {
197 | lda #0
198 | ldy #0
199 | sta frequencies, y
200 | sta screen, y
201 | }
202 = main:
203 = lda #0
204 = ldy #0
205 = sta frequencies, y
206 = sta screen, y
207 = rts
208 =
209 = .data
210 = .space frequencies 16
211 = .alias screen 1024
212
149149
150150 | reserve word vword
151151 | reserve byte vbyte
152 | assign byte table table 1024
152 | assign byte[256] table 1024
153153 | routine main {
154154 | lda #4
155155 | ldx #0
262262
263263 | reserve word vword
264264 | reserve byte vbyte
265 | assign byte table table 1024
265 | assign byte[256] table 1024
266266 | routine main {
267267 | asl .a
268268 | asl vbyte
2929 where
3030 checkInstr j@(COPY _ (Indexed (NamedLocation sz g) reg)) =
3131 case lookupDecl p g of
32 Just (Assign _ ByteTable _) -> j
33 Just (Reserve _ ByteTable _) -> j
32 Just (Assign _ (ByteTable _) _) -> j
33 Just (Reserve _ (ByteTable _) _) -> j
3434 Just _ -> (COPY A A)
3535 Nothing -> (COPY A A)
3636 checkInstr other = other
157157 in
158158 case (typeRx == typeRy, typeRx, typeRy) of
159159 (True, _, _) -> constructor rx ry
160 (_, Byte, ByteTable) -> constructor rx ry
161 (_, ByteTable, Byte) -> constructor rx ry
160 (_, Byte, (ByteTable _)) -> constructor rx ry
161 (_, (ByteTable _), Byte) -> constructor rx ry
162162 _ -> error ("incompatible types '" ++ (show typeRx) ++ "' and '" ++ (show typeRy) ++ "'")
163163 resolve (NamedLocation Nothing name) =
164164 case lookupDecl p name of
2929 | typ == Word = name ++ ": .word " ++ (show val)
3030 | typ == Vector = name ++ ": .word " ++ (show val)
3131
32 emitDecl p (Reserve name (ByteTable size) Nothing) =
33 ".space " ++ name ++ " " ++ (show size)
34
3235 emitDecl p (Reserve name typ Nothing)
3336 | typ == Byte = ".space " ++ name ++ " 1"
3437 | typ == Word = ".space " ++ name ++ " 2"
7881 emitInstr p r (COPY X A) = "txa"
7982 emitInstr p r (COPY Y A) = "tya"
8083
81 emitInstr p r (COPY A (Indexed (NamedLocation (Just ByteTable) label) X)) = "sta " ++ label ++ ", x"
82 emitInstr p r (COPY A (Indexed (NamedLocation (Just ByteTable) label) Y)) = "sta " ++ label ++ ", y"
83
84 emitInstr p r (COPY (Indexed (NamedLocation (Just ByteTable) label) X) A) = "lda " ++ label ++ ", x"
85 emitInstr p r (COPY (Indexed (NamedLocation (Just ByteTable) label) Y) A) = "lda " ++ label ++ ", y"
84 emitInstr p r (COPY A (Indexed (NamedLocation (Just (ByteTable _)) label) X)) = "sta " ++ label ++ ", x"
85 emitInstr p r (COPY A (Indexed (NamedLocation (Just (ByteTable _)) label) Y)) = "sta " ++ label ++ ", y"
86
87 emitInstr p r (COPY (Indexed (NamedLocation (Just (ByteTable _)) label) X) A) = "lda " ++ label ++ ", x"
88 emitInstr p r (COPY (Indexed (NamedLocation (Just (ByteTable _)) label) Y) A) = "lda " ++ label ++ ", y"
8689
8790 emitInstr p r (COPY A (IndirectIndexed (NamedLocation st label) Y)) = "sta (" ++ label ++ "), y"
8891 emitInstr p r (COPY (IndirectIndexed (NamedLocation st label) Y) A) = "lda (" ++ label ++ "), y"
2222 data StorageType = Byte
2323 | Word
2424 | Vector
25 | ByteTable
25 | ByteTable DataValue
2626 deriving (Show, Ord, Eq)
2727
2828 data StorageLocation = A
1313 Decl := "reserve" StorageType LocationName [":" Literal]
1414 | "assign" StorageType LocationName Literal
1515 | "external" RoutineName Address.
16 StorageType := "byte" | "word" | "byte table" | "vector".
16 StorageType := "byte" ["[" Literal "]"] | "word" | "vector".
1717 Routine := "routine" RoutineName ["outputs" "(" {LocationName} ")"] Block.
1818 Block := "{" {Command} "}".
1919 Command := "if" Branch Block "else" Block
9090 addr <- literal_address
9191 return $ External name addr
9292
93 get_storage "byte" = Byte
94 get_storage "word" = Word
95 get_storage "vector" = Vector
96 get_storage "byte table" = ByteTable
93 storage :: String -> StorageType -> Parser StorageType
94 storage s t = do
95 string s
96 nspaces
97 return t
98
99 byte_table :: Parser StorageType
100 byte_table = do
101 string "byte"
102 nspaces
103 string "["
104 nspaces
105 size <- literal_data_value
106 string "]"
107 nspaces
108 return $ ByteTable size
97109
98110 storage_type :: Parser StorageType
99 storage_type = do
100 s <- (try $ string "byte table") <|> (string "byte") <|>
101 (string "word") <|> (string "vector")
102 nspaces
103 return $ get_storage s
111 storage_type = (try $ byte_table) <|> (storage "byte" Byte) <|>
112 (storage "word" Word) <|> (storage "vector" Vector)
104113
105114 routine :: Parser Routine
106115 routine = do