Skip to content

Commit

Permalink
Add basic constants support. Fix broken non-decimal integer literals.
Browse files Browse the repository at this point in the history
  • Loading branch information
bshepherdson committed Aug 25, 2012
1 parent 598e0da commit 7b8ddbe
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 5 deletions.
6 changes: 3 additions & 3 deletions Alex.x
Expand Up @@ -39,9 +39,9 @@ $blank+ ; -- ignore non-newline whitespace
\' ($graphical # [\'\\] | \\\' | @escape) \' { LChar . head . tail . escape charEscapes } -- first character inside the quotes
-- integer literals
0 $octdigit+ { mkInt readOct }
0 $octdigit+ { mkInt readOct . tail }
0x $hexdigit+ { mkInt readHex . drop 2 }
$digit+ { mkInt reads }
0x $hexdigit+ { mkInt readHex }
-- boolean literals
true { const $ LBool True }
Expand Down Expand Up @@ -157,7 +157,7 @@ data Token = LNewline
mkInt :: ReadS Int -> String -> Token
mkInt f s = case f s of
[(x,"")] -> LInt x
_ -> error "Broken integer literal"
_ -> error $ "Broken integer literal: '" ++ s ++ "'"
keyword = const
Expand Down
19 changes: 18 additions & 1 deletion Compiler.hs
Expand Up @@ -65,6 +65,7 @@ data CompilerState = CS {
data Location = LocReg String
| LocStack Int -- places above the frame pointer, J
| LocLabel String -- in the given label
| LocConstant Int
deriving (Show)


Expand Down Expand Up @@ -175,6 +176,7 @@ doCompile (SourceFile thePackage imports statements_) libdirs = do
allImports <- evalStateT (importsClosure imports (if null libdirs then ["."] else libdirs)) []
let statements = allImports ++ fixSelectors statements_
let allGlobals = findVariables statements
allConstants = findConstants statements
allTypes = M.fromList $ findTypes statements ++ builtinTypes
globalCode = flip concatMap allGlobals $ \(QualIdent mp i, t) -> [LabelDef (mkLabelInternal (fromMaybe thePackage mp) i)] ++ replicate (typeSizeInternal allTypes t) (DAT "0") -- include the label and enough space for the global
-- a function called main becomes the start point.
Expand All @@ -193,7 +195,7 @@ doCompile (SourceFile thePackage imports statements_) libdirs = do
types = allTypes,
args = [],
locals = [],
globals = map (\(g@(QualIdent mp i), _) -> (g, LocLabel (mkLabelInternal (fromMaybe thePackage mp) i))) allGlobals,
globals = map (\(g@(QualIdent mp i), _) -> (g, LocLabel (mkLabelInternal (fromMaybe thePackage mp) i))) allGlobals ++ allConstants,
this = "",
unique = 1,
packageName = thePackage
Expand Down Expand Up @@ -240,6 +242,7 @@ exportedStatements :: String -> [Statement] -> [Statement]
exportedStatements _ [] = []
exportedStatements pkg (StmtTypeDecl (QualIdent Nothing i) t : rest) | isUpper (head i) = StmtTypeDecl (QualIdent (Just pkg) i) t : exportedStatements pkg rest
exportedStatements pkg (StmtVarDecl (QualIdent Nothing i) t x : rest) | isUpper (head i) = StmtVarDecl (QualIdent (Just pkg) i) t x : exportedStatements pkg rest
exportedStatements pkg (StmtConstDecl (QualIdent Nothing i) mt x : rest) | isUpper (head i) = StmtConstDecl (QualIdent (Just pkg) i) mt x : exportedStatements pkg rest
exportedStatements pkg (StmtShortVarDecl (QualIdent Nothing i) x : rest) | isUpper (head i) = StmtShortVarDecl (QualIdent (Just pkg) i) x : exportedStatements pkg rest
exportedStatements pkg (StmtFunction (QualIdent Nothing i) args ret _ : rest) | isUpper (head i) = StmtFunction (QualIdent (Just pkg) i) args ret Nothing : exportedStatements pkg rest
exportedStatements pkg (_:rest) = exportedStatements pkg rest
Expand Down Expand Up @@ -303,6 +306,7 @@ findLocals (_:rest) = findLocals rest
findSymbols :: [Statement] -> [(QualIdent, Type)]
findSymbols [] = []
findSymbols (StmtVarDecl s t _ : rest) = (s, t) : findSymbols rest
findSymbols (StmtConstDecl s t _ : rest) = (s, t) : findSymbols rest
findSymbols (StmtFunction name args ret _ : rest) = (name, TypeFunction (map snd args) ret) : findSymbols rest
findSymbols (_:rest) = findSymbols rest

Expand All @@ -312,6 +316,15 @@ findVariables [] = []
findVariables (StmtVarDecl i@(QualIdent Nothing _) t _ : rest) = (i, t) : findVariables rest
findVariables (_:rest) = findVariables rest

-- finds constants with a shallow search. intended to find global constants in the whole file.
findConstants :: [Statement] -> [(QualIdent, Location)]
findConstants [] = []
findConstants (StmtConstDecl i@(QualIdent Nothing _) _ (Just (LitInt x)) : rest) = (i, LocConstant x) : findConstants rest
findConstants (StmtConstDecl i@(QualIdent Nothing _) _ (Just _) : rest) = compileError $ "Only integer literals are supported as contants."
findConstants (StmtConstDecl _ _ Nothing : rest) = compileError $ "const declarations must include a value"
findConstants (_:rest) = findConstants rest


-- finds type declarations in a list of statements, intended for use on a whole file.
findTypes :: [Statement] -> [(QualIdent, Type)]
findTypes [] = []
Expand Down Expand Up @@ -680,6 +693,7 @@ compile (StmtTypeDecl name t) = return [] -- nothing to compile for typedecls.
-- note that this doesn't add the symbol, but rather expects it to already exist. this does compile initializers, though.
compile (StmtVarDecl name t Nothing) = addSymbol name t >> return [] -- nothing to do for a plain declaration
compile (StmtVarDecl name t (Just x)) = addSymbol name t >> setVar name x
compile (StmtConstDecl name t _) = addSymbol name t >> return [] -- nothing to do in code for constants.
compile (StmtShortVarDecl name x) = do
t <- typeCheck x
addSymbol name t
Expand Down Expand Up @@ -900,6 +914,7 @@ compileLocation :: Location -> Compiler Arg
compileLocation (LocReg r) = return $ Reg r
compileLocation (LocStack n) = return $ AddrRegLit "J" n -- can't use PICK or SP, unknown levels of saved values piled on top. Use J, the frame pointer.
compileLocation (LocLabel s) = return $ AddrLabel s
compileLocation (LocConstant i) = return $ Lit i


-- compiles an expression, storing the result in the given register.
Expand Down Expand Up @@ -1056,6 +1071,7 @@ compileExpr (UnOp (LOp "&") x) r = do
loc <- lookupLocation i
case loc of
LocReg _ -> typeError $ "Attempt to take address of value contained in a register " ++ show i
LocConstant _ -> typeError $ "Attempt to take address of constant " ++ show i
LocStack n -> return [SET (Reg r) (Reg "J"), ADD (Reg r) (Lit n)]
(Index x i) -> do
xt <- typeCheck x
Expand Down Expand Up @@ -1207,6 +1223,7 @@ setVar i x = do
LocReg s -> return [SET (Reg s) (Reg r)]
LocStack n -> return [SET (AddrRegLit "J" n) (Reg r)]
LocLabel l -> return [SET (AddrLabel l) (Reg r)]
LocConstant _ -> typeError $ "Attempt to assign a value to constant " ++ show i

freeReg r
return $ exprCode ++ storeCode
Expand Down
15 changes: 15 additions & 0 deletions Happy.y
Expand Up @@ -192,6 +192,7 @@ NonPointerType : TypeName { $1 }

Declaration :: { [Statement] }
Declaration : TypeDecl { $1 }
| ConstDecl { $1 }
| VarDecl { $1 }
| ShortVarDecl { $1 }

Expand All @@ -217,6 +218,19 @@ TypeSpec :: { [Statement] }
TypeSpec : ident Type { [StmtTypeDecl (QualIdent Nothing $1) $2] }


ConstDecl :: { [Statement] }
ConstDecl : const ConstSpec { $2 }
| const OP ConstSpecs CP { $3 }

ConstSpecs :: { [Statement] }
ConstSpecs : ConstSpecs eol ConstSpec { $3 ++ $1 }
| ConstSpecs eol { $1 }
| ConstSpec { $1 }

ConstSpec :: { [Statement] }
ConstSpec : IdentifierList Type '=' ExpressionList { zipWith (\i x -> StmtConstDecl (QualIdent Nothing i) $2 x) $1 (map Just $4 ++ repeat Nothing) }


VarDecl :: { [Statement] }
VarDecl : var VarSpec { reverse $2 }
| var OP VarSpecs CP { reverse $3 }
Expand Down Expand Up @@ -567,6 +581,7 @@ instance Eq Type where
data Statement = StmtTypeDecl QualIdent Type
| StmtVarDecl QualIdent Type (Maybe Expr)
| StmtConstDecl QualIdent Type (Maybe Expr)
| StmtShortVarDecl QualIdent Expr
| StmtFunction QualIdent [(String, Type)] Type (Maybe [Statement])
| StmtLabel String
Expand Down
5 changes: 4 additions & 1 deletion README.md
Expand Up @@ -34,7 +34,10 @@ go10c is a compiler from a dialect of Google Go to DCPU-16 assembly. It is writt
* Newly allocated values, local and global values **are not** set to 0. Do not rely on them.
* Global variables may not have initializers; they will be ignored.
* Execution begins at `main()`. A file may be compiled that has no `main()`; in that case it is a library, and an attempt to execute the file will make the DCPU halt and catch fire.
* Constants are unsupported for now.
* Constants:
- Top-level constants only; no constants defined in functions are allowed.
- The type of the constants must be specified.
- Only simple constant values (integer literals, currently) are supported.
* Struct changes:
- Tags are not supported.
- Anonymous fields are not supported.
Expand Down

0 comments on commit 7b8ddbe

Please sign in to comment.