tools/pas2c.hs
changeset 7042 de20086a6bcc
parent 7040 4aff2da0d0b3
child 7043 7c080e5ac8d0
equal deleted inserted replaced
7041:76a9274f280f 7042:de20086a6bcc
    22 
    22 
    23 
    23 
    24 data InsertOption = 
    24 data InsertOption = 
    25     IOInsert
    25     IOInsert
    26     | IOLookup
    26     | IOLookup
       
    27     | IOLookupLast
    27     | IOLookupFunction Int
    28     | IOLookupFunction Int
    28     | IODeferred
    29     | IODeferred
    29 
    30 
    30 type Records = Map.Map String [(String, BaseType)]
    31 type Record = (String, BaseType)
       
    32 type Records = Map.Map String [Record]
    31 data RenderState = RenderState 
    33 data RenderState = RenderState 
    32     {
    34     {
    33         currentScope :: Records,
    35         currentScope :: Records,
    34         lastIdentifier :: String,
    36         lastIdentifier :: String,
    35         lastType :: BaseType,
    37         lastType :: BaseType,
   244             _ -> i
   246             _ -> i
   245     modify (\s -> s{currentScope = Map.insertWith (++) n [(i', t)] (currentScope s), lastIdentifier = n})
   247     modify (\s -> s{currentScope = Map.insertWith (++) n [(i', t)] (currentScope s), lastIdentifier = n})
   246     return $ text i'
   248     return $ text i'
   247     where
   249     where
   248         n = map toLower i
   250         n = map toLower i
   249 id2C IOLookup (Identifier i t) = do
   251 id2C IOLookup i = id2CLookup head i
   250     let i' = map toLower i
   252 id2C IOLookupLast i = id2CLookup last i
   251     v <- gets $ Map.lookup i' . currentScope
       
   252     lt <- gets lastType
       
   253     if isNothing v then 
       
   254         error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt
       
   255         else 
       
   256         let vv = head $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv)
       
   257 id2C (IOLookupFunction params) (Identifier i t) = do
   253 id2C (IOLookupFunction params) (Identifier i t) = do
   258     let i' = map toLower i
   254     let i' = map toLower i
   259     v <- gets $ Map.lookup i' . currentScope
   255     v <- gets $ Map.lookup i' . currentScope
   260     lt <- gets lastType
   256     lt <- gets lastType
   261     if isNothing v then 
   257     if isNothing v then 
   272     if (isNothing v) then
   268     if (isNothing v) then
   273         modify (\s -> s{lastType = BTUnknown, lastIdentifier = i}) >> return (text i)
   269         modify (\s -> s{lastType = BTUnknown, lastIdentifier = i}) >> return (text i)
   274         else
   270         else
   275         let vv = head $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv)
   271         let vv = head $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv)
   276 
   272 
       
   273 id2CLookup :: ([Record] -> Record) -> Identifier -> State RenderState Doc
       
   274 id2CLookup f (Identifier i _) = do
       
   275     let i' = map toLower i
       
   276     v <- gets $ Map.lookup i' . currentScope
       
   277     lt <- gets lastType
       
   278     if isNothing v then 
       
   279         error $ "Not defined: '" ++ i' ++ "'\n" ++ show lt
       
   280         else 
       
   281         let vv = f $ fromJust v in modify (\s -> s{lastType = snd vv, lastIdentifier = fst vv}) >> (return . text . fst $ vv)
       
   282         
       
   283         
   277 id2CTyped :: TypeDecl -> Identifier -> State RenderState Doc
   284 id2CTyped :: TypeDecl -> Identifier -> State RenderState Doc
   278 id2CTyped t (Identifier i _) = do
   285 id2CTyped t (Identifier i _) = do
   279     tb <- resolveType t
   286     tb <- resolveType t
   280     case tb of 
   287     case (t, tb) of 
   281         BTUnknown -> do
   288         (_, BTUnknown) -> do
   282             error $ "id2CTyped: type BTUnknown for " ++ show i ++ "\ntype: " ++ show t
   289             error $ "id2CTyped: type BTUnknown for " ++ show i ++ "\ntype: " ++ show t
   283         _ -> return ()
   290         (SimpleType {}, BTRecord _ r) -> do
   284     id2C IOInsert (Identifier i tb)
   291             ts <- type2C t
       
   292             id2C IOInsert (Identifier i (BTRecord (render $ ts empty) r))
       
   293         (_, BTRecord _ r) -> do
       
   294             ts <- type2C t
       
   295             id2C IOInsert (Identifier i (BTRecord i r))
       
   296         _ -> id2C IOInsert (Identifier i tb)
       
   297     
   285 
   298 
   286 
   299 
   287 resolveType :: TypeDecl -> State RenderState BaseType
   300 resolveType :: TypeDecl -> State RenderState BaseType
   288 resolveType st@(SimpleType (Identifier i _)) = do
   301 resolveType st@(SimpleType (Identifier i _)) = do
   289     let i' = map toLower i
   302     let i' = map toLower i
   299     f _ = error $ "Unknown system type: " ++ show st
   312     f _ = error $ "Unknown system type: " ++ show st
   300 resolveType (PointerTo (SimpleType (Identifier i _))) = return . BTPointerTo $ BTUnresolved (map toLower i)
   313 resolveType (PointerTo (SimpleType (Identifier i _))) = return . BTPointerTo $ BTUnresolved (map toLower i)
   301 resolveType (PointerTo t) = liftM BTPointerTo $ resolveType t
   314 resolveType (PointerTo t) = liftM BTPointerTo $ resolveType t
   302 resolveType (RecordType tv mtvs) = do
   315 resolveType (RecordType tv mtvs) = do
   303     tvs <- mapM f (concat $ tv : fromMaybe [] mtvs)
   316     tvs <- mapM f (concat $ tv : fromMaybe [] mtvs)
   304     return . BTRecord . concat $ tvs
   317     return . BTRecord "" . concat $ tvs
   305     where
   318     where
   306         f :: TypeVarDeclaration -> State RenderState [(String, BaseType)]
   319         f :: TypeVarDeclaration -> State RenderState [(String, BaseType)]
   307         f (VarDeclaration _ (ids, td) _) = mapM (\(Identifier i _) -> liftM ((,) i) $ resolveType td) ids
   320         f (VarDeclaration _ (ids, td) _) = mapM (\(Identifier i _) -> liftM ((,) i) $ resolveType td) ids
   308 resolveType (ArrayDecl (Just i) t) = do
   321 resolveType (ArrayDecl (Just i) t) = do
   309     t' <- resolveType t
   322     t' <- resolveType t
   418     
   431     
   419 op2CTyped :: String -> [TypeDecl] -> State RenderState Identifier
   432 op2CTyped :: String -> [TypeDecl] -> State RenderState Identifier
   420 op2CTyped op t = do
   433 op2CTyped op t = do
   421     t' <- liftM (render . hcat . punctuate (char '_') . map (\t -> t empty)) $ mapM type2C t
   434     t' <- liftM (render . hcat . punctuate (char '_') . map (\t -> t empty)) $ mapM type2C t
   422     bt <- gets lastType
   435     bt <- gets lastType
   423     return $ case bt of
   436     return $ Identifier (t' ++ "_op_" ++ opStr) bt
   424          BTRecord {} -> Identifier (t' ++ "_op_" ++ opStr) bt
       
   425          _ -> Identifier t' bt
       
   426     where 
   437     where 
   427     opStr = case op of
   438     opStr = case op of
   428                     "+" -> "add"
   439                     "+" -> "add"
   429                     "-" -> "sub"
   440                     "-" -> "sub"
   430                     "*" -> "mul"
   441                     "*" -> "mul"
   431                     "/" -> "div"
   442                     "/" -> "div"
   432                     "=" -> "eq"
   443                     "=" -> "eq"
   433                     "<" -> "lt"
   444                     "<" -> "lt"
   434                     ">" -> "gt"
   445                     ">" -> "gt"
       
   446                     "<>" -> "neq"
   435                     _ -> error $ "op2CTyped: unknown op '" ++ op ++ "'"
   447                     _ -> error $ "op2CTyped: unknown op '" ++ op ++ "'"
   436     
   448     
   437 extractTypes :: [TypeVarDeclaration] -> [TypeDecl]
   449 extractTypes :: [TypeVarDeclaration] -> [TypeDecl]
   438 extractTypes = concatMap f
   450 extractTypes = concatMap f
   439     where
   451     where
   517     type2C' (String l) = return (text "string255" <+>)--return (text ("string" ++ show l) <+>)
   529     type2C' (String l) = return (text "string255" <+>)--return (text ("string" ++ show l) <+>)
   518     type2C' (PointerTo (SimpleType i)) = do
   530     type2C' (PointerTo (SimpleType i)) = do
   519         i' <- id2C IODeferred i
   531         i' <- id2C IODeferred i
   520         lt <- gets lastType
   532         lt <- gets lastType
   521         case lt of
   533         case lt of
   522              BTRecord _ -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a
   534              BTRecord _ _ -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a
   523              BTUnknown -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a
   535              BTUnknown -> return $ \a -> text "struct __" <> i' <+> text "*" <+> a
   524              _ -> return $ \a -> i' <+> text "*" <+> a
   536              _ -> return $ \a -> i' <+> text "*" <+> a
   525     type2C' (PointerTo t) = liftM (\t a -> t (parens $ text "*" <> a)) $ type2C t
   537     type2C' (PointerTo t) = liftM (\t a -> t (parens $ text "*" <> a)) $ type2C t
   526     type2C' (RecordType tvs union) = do
   538     type2C' (RecordType tvs union) = do
   527         t <- withState' f $ mapM (tvar2C False) tvs
   539         t <- withState' f $ mapM (tvar2C False) tvs
   616                                          
   628                                          
   617 phrase2C wb@(WithBlock ref p) = do
   629 phrase2C wb@(WithBlock ref p) = do
   618     r <- ref2C ref 
   630     r <- ref2C ref 
   619     t <- gets lastType
   631     t <- gets lastType
   620     case t of
   632     case t of
   621         (BTRecord rs) -> withRecordNamespace (render r ++ ".") rs $ phrase2C $ wrapPhrase p
   633         (BTRecord _ rs) -> withRecordNamespace (render r ++ ".") rs $ phrase2C $ wrapPhrase p
   622         a -> do
   634         a -> do
   623             error $ "'with' block referencing non-record type " ++ show a ++ "\n" ++ show wb
   635             error $ "'with' block referencing non-record type " ++ show a ++ "\n" ++ show wb
   624 phrase2C (ForCycle i' e1' e2' p) = do
   636 phrase2C (ForCycle i' e1' e2' p) = do
   625     i <- id2C IOLookup i'
   637     i <- id2C IOLookup i'
   626     e1 <- expr2C e1'
   638     e1 <- expr2C e1'
   636     return $ text "do" <+> p <+> text "while" <> parens (text "!" <> parens e) <> semi
   648     return $ text "do" <+> p <+> text "while" <> parens (text "!" <> parens e) <> semi
   637 phrase2C NOP = return $ text ";"
   649 phrase2C NOP = return $ text ";"
   638 
   650 
   639 phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "exit" BTUnknown))) = return $ text "return" <> semi
   651 phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "exit" BTUnknown))) = return $ text "return" <> semi
   640 phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "break" BTUnknown))) = return $ text "break" <> semi
   652 phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "break" BTUnknown))) = return $ text "break" <> semi
       
   653 phrase2C (BuiltInFunctionCall [] (SimpleReference (Identifier "continue" BTUnknown))) = return $ text "continue" <> semi
   641 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "exit" BTUnknown))) = liftM (\e -> text "return" <+> e <> semi) $ expr2C e
   654 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "exit" BTUnknown))) = liftM (\e -> text "return" <+> e <> semi) $ expr2C e
   642 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "dec" BTUnknown))) = liftM (\e -> text "--" <> e <> semi) $ expr2C e
   655 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "dec" BTUnknown))) = liftM (\e -> text "--" <> e <> semi) $ expr2C e
   643 phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "dec" BTUnknown))) = liftM2 (\a b -> a <> text " -= " <> b <> semi) (expr2C e1) (expr2C e2)
   656 phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "dec" BTUnknown))) = liftM2 (\a b -> a <> text " -= " <> b <> semi) (expr2C e1) (expr2C e2)
   644 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "inc" BTUnknown))) = liftM (\e -> text "++" <> e <> semi) $ expr2C e
   657 phrase2C (BuiltInFunctionCall [e] (SimpleReference (Identifier "inc" BTUnknown))) = liftM (\e -> text "++" <> e <> semi) $ expr2C e
   645 phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "inc" BTUnknown))) = liftM2 (\a b -> a <+> text "+=" <+> b <> semi) (expr2C e1) (expr2C e2)
   658 phrase2C (BuiltInFunctionCall [e1, e2] (SimpleReference (Identifier "inc" BTUnknown))) = liftM2 (\a b -> a <+> text "+=" <+> b <> semi) (expr2C e1) (expr2C e2)
   661         ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (BTFunction 2 BTString))
   674         ("+", BTChar, BTString) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strprepend" (BTFunction 2 BTString))
   662         ("==", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (BTFunction 2 BTBool))
   675         ("==", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strcompare" (BTFunction 2 BTBool))
   663         ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (BTFunction 2 BTBool))
   676         ("!=", BTString, _) -> expr2C $ BuiltInFunCall [expr1, expr2] (SimpleReference $ Identifier "_strncompare" (BTFunction 2 BTBool))
   664         ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2
   677         ("&", BTBool, _) -> return $ parens e1 <+> text "&&" <+> parens e2
   665         ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2
   678         ("|", BTBool, _) -> return $ parens e1 <+> text "||" <+> parens e2
       
   679         (_, BTRecord t1 _, BTRecord t2 _) -> do
       
   680             i <- op2CTyped op [SimpleType (Identifier t1 undefined), SimpleType (Identifier t2 undefined)]
       
   681             ref2C $ FunCall [expr1, expr2] (SimpleReference i)
   666         (o, _, _) | o `elem` boolOps -> do
   682         (o, _, _) | o `elem` boolOps -> do
   667                         modify(\s -> s{lastType = BTBool})
   683                         modify(\s -> s{lastType = BTBool})
   668                         return $ parens e1 <+> text o <+> parens e2
   684                         return $ parens e1 <+> text o <+> parens e2
   669                   | otherwise -> return $ parens e1 <+> text o <+> parens e2
   685                   | otherwise -> return $ parens e1 <+> text o <+> parens e2
   670     where
   686     where
   671         boolOps = ["==", "!=", "<", ">", "<=", ">="]
   687         boolOps = ["==", "!=", "<", ">", "<=", ">="]
   672 expr2C (NumberLiteral s) = return $ text s
   688 expr2C (NumberLiteral s) = do
       
   689     modify(\s -> s{lastType = BTInt})
       
   690     return $ text s
   673 expr2C (FloatLiteral s) = return $ text s
   691 expr2C (FloatLiteral s) = return $ text s
   674 expr2C (HexNumber s) = return $ text "0x" <> (text . map toLower $ s)
   692 expr2C (HexNumber s) = return $ text "0x" <> (text . map toLower $ s)
   675 expr2C (StringLiteral [a]) = do
   693 expr2C (StringLiteral [a]) = do
   676     modify(\s -> s{lastType = BTChar})
   694     modify(\s -> s{lastType = BTChar})
   677     return . quotes $ text [a]
   695     return . quotes $ text [a]
   678 expr2C (StringLiteral s) = addStringConst s
   696 expr2C (StringLiteral s) = addStringConst s
   679 expr2C (Reference ref) = ref2CF ref
   697 expr2C (Reference ref) = ref2CF ref
   680 expr2C (PrefixOp op expr) = liftM (text (op2C op) <>) (expr2C expr)
   698 expr2C (PrefixOp op expr) = do
       
   699     e <- expr2C expr
       
   700     lt <- gets lastType
       
   701     case lt of
       
   702         BTRecord t _ -> do
       
   703             i <- op2CTyped op [SimpleType (Identifier t undefined)]
       
   704             ref2C $ FunCall [expr] (SimpleReference i)
       
   705         _ -> return $ text (op2C op) <> e
   681 expr2C Null = return $ text "NULL"
   706 expr2C Null = return $ text "NULL"
   682 expr2C (CharCode a) = do
   707 expr2C (CharCode a) = do
   683     modify(\s -> s{lastType = BTChar})
   708     modify(\s -> s{lastType = BTChar})
   684     return $ quotes $ text "\\x" <> text (showHex (read a) "")
   709     return $ quotes $ text "\\x" <> text (showHex (read a) "")
   685 expr2C (HexCharCode a) = return $ quotes $ text "\\x" <> text (map toLower a)
   710 expr2C (HexCharCode a) = return $ quotes $ text "\\x" <> text (map toLower a)
   757 ref2C (SimpleReference name) = id2C IOLookup name
   782 ref2C (SimpleReference name) = id2C IOLookup name
   758 ref2C rf@(RecordField (Dereference ref1) ref2) = do
   783 ref2C rf@(RecordField (Dereference ref1) ref2) = do
   759     r1 <- ref2C ref1 
   784     r1 <- ref2C ref1 
   760     t <- fromPointer (show ref1) =<< gets lastType
   785     t <- fromPointer (show ref1) =<< gets lastType
   761     r2 <- case t of
   786     r2 <- case t of
   762         BTRecord rs -> withRecordNamespace "" rs $ ref2C ref2
   787         BTRecord _ rs -> withRecordNamespace "" rs $ ref2C ref2
   763         BTUnit -> withLastIdNamespace $ ref2CF ref2
   788         BTUnit -> withLastIdNamespace $ ref2CF ref2
   764         a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf
   789         a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf
   765     return $ 
   790     return $ 
   766         r1 <> text "->" <> r2
   791         r1 <> text "->" <> r2
   767 ref2C rf@(RecordField ref1 ref2) = do
   792 ref2C rf@(RecordField ref1 ref2) = do
   768     r1 <- ref2C ref1
   793     r1 <- ref2C ref1
   769     t <- gets lastType
   794     t <- gets lastType
   770     case t of
   795     case t of
   771         BTRecord rs -> do
   796         BTRecord _ rs -> do
   772             r2 <- withRecordNamespace "" rs $ ref2C ref2
   797             r2 <- withRecordNamespace "" rs $ ref2C ref2
   773             return $ r1 <> text "." <> r2
   798             return $ r1 <> text "." <> r2
   774         BTUnit -> withLastIdNamespace $ ref2CF ref2        
   799         BTUnit -> withLastIdNamespace $ ref2CF ref2        
   775         a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf
   800         a -> error $ "dereferencing from " ++ show a ++ "\n" ++ show rf
   776 ref2C d@(Dereference ref) = do
   801 ref2C d@(Dereference ref) = do