mirror of
https://github.com/catseye/SixtyPical.git
synced 2025-02-09 16:31:42 +00:00
Initial values for reserved tables; checks length is right.
This commit is contained in:
parent
f9d0c8173d
commit
7a3b3b1b25
@ -155,6 +155,11 @@ For more information, see the docs (which are written in the form of
|
||||
Falderal literate test suites. If you have Falderal installed, you can run
|
||||
the tests with `./test.sh`.)
|
||||
|
||||
* [Checking](https://github.com/catseye/SixtyPical/blob/master/doc/Checking.markdown)
|
||||
* [Analyzing](https://github.com/catseye/SixtyPical/blob/master/doc/Analyzing.markdown)
|
||||
* [Emitting](https://github.com/catseye/SixtyPical/blob/master/doc/Emitting.markdown)
|
||||
* [Instruction Support](https://github.com/catseye/SixtyPical/blob/master/doc/Instruction_Support.markdown)
|
||||
|
||||
Internals
|
||||
---------
|
||||
|
||||
@ -206,7 +211,6 @@ it probably won't.)
|
||||
TODO
|
||||
----
|
||||
|
||||
* Initial values for reserved tables
|
||||
* Character tables ("strings" to everybody else)
|
||||
* Addressing modes — indexed mode on more instructions
|
||||
* Rename and lift temporaries in nested blocks
|
||||
|
@ -80,6 +80,55 @@ An address declared with `reserve` may be given an initial value.
|
||||
| }
|
||||
= True
|
||||
|
||||
A byte table declared with `reserve` may be given an initial value consisting
|
||||
of a sequence of bytes.
|
||||
|
||||
| reserve byte[4] table : (0 $40 $10 20)
|
||||
| routine main {
|
||||
| ldy #0
|
||||
| lda table, y
|
||||
| }
|
||||
| routine died {
|
||||
| sta table, y
|
||||
| }
|
||||
= True
|
||||
|
||||
A byte table declared with `reserve` may be given an initial value consisting
|
||||
of a sequence of bytes represented as a character string.
|
||||
|
||||
| reserve byte[4] table : "What"
|
||||
| routine main {
|
||||
| ldy #0
|
||||
| lda table, y
|
||||
| }
|
||||
| routine died {
|
||||
| sta table, y
|
||||
| }
|
||||
= True
|
||||
|
||||
When a byte table declared with `reserve` is given an initial value consisting
|
||||
of a sequence of bytes, it must be the same length as the table is declared.
|
||||
|
||||
| reserve byte[4] table : (0 $40 $10 20 60 70 90)
|
||||
| routine main {
|
||||
| ldy #0
|
||||
| lda table, y
|
||||
| }
|
||||
| routine died {
|
||||
| sta table, y
|
||||
| }
|
||||
? initial table incorrect size
|
||||
|
||||
| reserve byte[4] table : "Hello, world!"
|
||||
| routine main {
|
||||
| ldy #0
|
||||
| lda table, y
|
||||
| }
|
||||
| routine died {
|
||||
| sta table, y
|
||||
| }
|
||||
? initial table incorrect size
|
||||
|
||||
An address may be declared with `locate`, which is like `.alias` in an
|
||||
assembler, with the understanding that the value will be treated "like an
|
||||
address." This is generally an address into the operating system or hardware
|
||||
|
@ -51,6 +51,19 @@ noUseOfUndeclaredRoutines p@(Program decls routines) =
|
||||
False -> error ("undeclared routine '" ++ routName ++ "'") -- acc + 1
|
||||
checkInstr other acc = acc
|
||||
|
||||
consistentInitialTableSizes p@(Program decls routines) =
|
||||
let
|
||||
inconsistentTableSizes = foldProgramDecls (checkDecl) 0 p
|
||||
in
|
||||
inconsistentTableSizes == 0
|
||||
where
|
||||
checkDecl (Reserve _ (ByteTable sz) []) acc = acc
|
||||
checkDecl (Reserve _ (ByteTable sz) vals) acc =
|
||||
case sz == (length vals) of
|
||||
True -> acc
|
||||
False -> acc + 1
|
||||
checkDecl _ acc = acc
|
||||
|
||||
-- - - - - - -
|
||||
|
||||
checkAndTransformProgram :: Program -> Maybe Program
|
||||
@ -60,7 +73,8 @@ checkAndTransformProgram program =
|
||||
trueOrDie "duplicate location name" (noDuplicateDecls program) &&
|
||||
trueOrDie "duplicate routine name" (noDuplicateRoutines program) &&
|
||||
trueOrDie "undeclared routine" (noUseOfUndeclaredRoutines program) &&
|
||||
trueOrDie "indexed access of non-table" (noIndexedAccessOfNonTables program)
|
||||
trueOrDie "indexed access of non-table" (noIndexedAccessOfNonTables program) &&
|
||||
trueOrDie "initial table incorrect size" (consistentInitialTableSizes program)
|
||||
then
|
||||
let
|
||||
program' = numberProgramLoops program
|
||||
|
@ -25,15 +25,21 @@ emitDecls p (decl:decls) =
|
||||
emitDecl p decl ++ "\n" ++ emitDecls p decls
|
||||
|
||||
emitDecl p (Assign name _ addr) = ".alias " ++ name ++ " " ++ (show addr)
|
||||
emitDecl p (Reserve name typ (Just val))
|
||||
emitDecl p (Reserve name typ [val])
|
||||
| typ == Byte = name ++ ": .byte " ++ (show val)
|
||||
| typ == Word = name ++ ": .word " ++ (show val)
|
||||
| typ == Vector = name ++ ": .word " ++ (show val)
|
||||
|
||||
emitDecl p (Reserve name (ByteTable size) Nothing) =
|
||||
emitDecl p (Reserve name (ByteTable size) []) =
|
||||
".space " ++ name ++ " " ++ (show size)
|
||||
|
||||
emitDecl p (Reserve name typ Nothing)
|
||||
emitDecl p (Reserve name (ByteTable size) vals) =
|
||||
name ++ ": .byte " ++ (showList vals)
|
||||
where
|
||||
showList [] = ""
|
||||
showList (val:vals) = (show val) ++ " " ++ (showList vals)
|
||||
|
||||
emitDecl p (Reserve name typ [])
|
||||
| typ == Byte = ".space " ++ name ++ " 1"
|
||||
| typ == Word = ".space " ++ name ++ " 2"
|
||||
| typ == Vector = ".space " ++ name ++ " 2"
|
||||
|
@ -47,7 +47,7 @@ data StorageLocation = A
|
||||
-- -- -- -- program model -- -- -- --
|
||||
|
||||
data Decl = Assign LocationName StorageType Address -- .alias
|
||||
| Reserve LocationName StorageType (Maybe DataValue) -- .word, .byte
|
||||
| Reserve LocationName StorageType [DataValue] -- .word, .byte
|
||||
| External RoutineName Address
|
||||
deriving (Show, Ord, Eq)
|
||||
|
||||
@ -109,8 +109,8 @@ isLocationDecl (Reserve _ _ _) = True
|
||||
isLocationDecl _ = False
|
||||
|
||||
isInitializedDecl (Assign _ _ _) = False
|
||||
isInitializedDecl (Reserve _ _ (Just _)) = True
|
||||
isInitializedDecl (Reserve _ _ Nothing) = False
|
||||
isInitializedDecl (Reserve _ _ (v:vs)) = True
|
||||
isInitializedDecl (Reserve _ _ []) = False
|
||||
|
||||
declaredLocationNames (Program decls _) =
|
||||
map (getDeclLocationName) (filter (isLocationDecl) decls)
|
||||
@ -177,6 +177,13 @@ foldProgramRoutines :: (Instruction -> a -> a) -> a -> Program -> a
|
||||
foldProgramRoutines f a (Program decls routs) =
|
||||
foldRoutines f a routs
|
||||
|
||||
foldDecls :: (Decl -> a -> a) -> a -> [Decl] -> a
|
||||
foldDecls = foldr
|
||||
|
||||
foldProgramDecls :: (Decl -> a -> a) -> a -> Program -> a
|
||||
foldProgramDecls f a (Program decls routs) =
|
||||
foldDecls f a decls
|
||||
|
||||
--
|
||||
|
||||
lookupDecl (Program decls _) name =
|
||||
|
@ -10,14 +10,15 @@ import SixtyPical.Model
|
||||
|
||||
{-
|
||||
|
||||
Toplevel := {Decl} {Routine}.
|
||||
Decl := "reserve" StorageType LocationName [":" Literal]
|
||||
| "assign" StorageType LocationName Literal
|
||||
| "external" RoutineName Address.
|
||||
StorageType := "byte" ["[" Literal "]"] | "word" | "vector".
|
||||
Routine := "routine" RoutineName ["outputs" "(" {LocationName} ")"] Block.
|
||||
Block := "{" {Decl} {Command} "}".
|
||||
Command := "if" Branch Block "else" Block
|
||||
Toplevel ::= {Decl} {Routine}.
|
||||
Decl ::= "reserve" StorageType LocationName [":" InitialValue]
|
||||
| "assign" StorageType LocationName Literal
|
||||
| "external" RoutineName Address.
|
||||
InitialValue ::= Literal | StringLiteral | "(" {Literal} ")".
|
||||
StorageType ::= "byte" ["[" Literal "]"] | "word" | "vector".
|
||||
Routine ::= "routine" RoutineName ["outputs" "(" {LocationName} ")"] Block.
|
||||
Block ::= "{" {Decl} {Command} "}".
|
||||
Command ::= "if" Branch Block "else" Block
|
||||
| "lda" (LocationName | Immediate)
|
||||
| "ldx" (LocationName | Immediate)
|
||||
| "ldy" (LocationName | Immediate)
|
||||
@ -31,7 +32,7 @@ Command := "if" Branch Block "else" Block
|
||||
| "jmp" LocationName
|
||||
| "jsr" RoutineName
|
||||
| "nop".
|
||||
Branch := "bcc" | "bcs" | "beq" | "bmi" | "bne" | "bpl" | "bvc" | "bvs".
|
||||
Branch ::= "bcc" | "bcs" | "beq" | "bmi" | "bne" | "bpl" | "bvc" | "bvs".
|
||||
|
||||
-}
|
||||
|
||||
@ -68,10 +69,10 @@ reserve = do
|
||||
nspaces
|
||||
sz <- storage_type
|
||||
name <- location_name
|
||||
value <- option Nothing (do{ string ":";
|
||||
nspaces;
|
||||
x <- literal_data_value;
|
||||
return $ Just x })
|
||||
value <- option [] (do{ string ":";
|
||||
nspaces;
|
||||
x <- initial_value;
|
||||
return x })
|
||||
return $ Reserve name sz value
|
||||
|
||||
assign :: Parser Decl
|
||||
@ -112,6 +113,24 @@ storage_type :: Parser StorageType
|
||||
storage_type = (try $ byte_table) <|> (storage "byte" Byte) <|>
|
||||
(storage "word" Word) <|> (storage "vector" Vector)
|
||||
|
||||
initial_value :: Parser [DataValue]
|
||||
initial_value =
|
||||
data_value_list <|> single_literal_data_value
|
||||
where
|
||||
single_literal_data_value = do
|
||||
a <- literal_data_value
|
||||
return [a]
|
||||
|
||||
data_value_list = do
|
||||
string "("
|
||||
nspaces
|
||||
a <- many literal_data_value
|
||||
string ")"
|
||||
nspaces
|
||||
return a
|
||||
|
||||
-- -- --
|
||||
|
||||
routine :: Parser Routine
|
||||
routine = do
|
||||
string "routine"
|
||||
@ -625,7 +644,7 @@ hex_literal = do
|
||||
|
||||
decimal_literal :: Parser Int
|
||||
decimal_literal = do
|
||||
digits <- many digit
|
||||
digits <- many1 digit
|
||||
nspaces
|
||||
return $ read digits
|
||||
|
||||
|
@ -161,7 +161,7 @@ renameRoutineDecls id ((Routine name outputs block):routs) =
|
||||
((Routine name outputs block'):rest)
|
||||
|
||||
foldDeclsRenaming [] id block = (id, block)
|
||||
foldDeclsRenaming ((Reserve name typ Nothing):decls) id block =
|
||||
foldDeclsRenaming ((Reserve name typ []):decls) id block =
|
||||
let
|
||||
newName = "_temp_" ++ (show id)
|
||||
id' = id + 1
|
||||
@ -176,8 +176,8 @@ foldDeclsRenaming ((Reserve name typ _):decls) id block =
|
||||
substDeclName n1 n2 (Block decls instrs) =
|
||||
Block (map (s) decls) instrs
|
||||
where
|
||||
s d@(Reserve name typ Nothing)
|
||||
| name == n1 = (Reserve n2 typ Nothing)
|
||||
s d@(Reserve name typ [])
|
||||
| name == n1 = (Reserve n2 typ [])
|
||||
| otherwise = d
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user