diff -r 5678806aafca -r 33180b479efa tools/pas2c.hs --- a/tools/pas2c.hs Fri Dec 02 15:03:27 2011 +0400 +++ b/tools/pas2c.hs Mon Dec 05 17:56:49 2011 +0400 @@ -12,6 +12,7 @@ import Control.Exception import System.IO.Error import qualified Data.Map as Map +import Control.Monad.Reader import PascalParser import PascalUnitSyntaxTree @@ -56,63 +57,74 @@ hPutStrLn stderr $ "Rendering '" ++ fn ++ "'..." toCFiles' p where - toCFiles' (fn, p@(Program {})) = writeFile (fn ++ ".c") $ (render . pascal2C) p + toCFiles' (fn, p@(Program {})) = writeFile (fn ++ ".c") $ (render2C . pascal2C) p toCFiles' (fn, (Unit _ interface implementation _ _)) = do - writeFile (fn ++ ".h") $ (render . interface2C) interface - writeFile (fn ++ ".c") $ (render . implementation2C) implementation - + writeFile (fn ++ ".h") $ "#pragma once\n" ++ (render2C . interface2C $ interface) + writeFile (fn ++ ".c") $ (render2C . implementation2C) implementation + +system :: [(String, String)] +system = [] + +render2C = render . flip runReader system + usesFiles :: PascalUnit -> [String] usesFiles (Program _ (Implementation uses _) _) = uses2List uses usesFiles (Unit _ (Interface uses1 _) (Implementation uses2 _) _ _) = uses2List uses1 ++ uses2List uses2 -pascal2C :: PascalUnit -> Doc -pascal2C (Unit _ interface implementation init fin) = - interface2C interface - $+$ - implementation2C implementation -pascal2C (Program _ implementation mainFunction) = - implementation2C implementation - $+$ - tvar2C True (FunctionDeclaration (Identifier "main" BTInt) (SimpleType $ Identifier "int" BTInt) [] (Just (TypesAndVars [], mainFunction))) +pascal2C :: PascalUnit -> Reader a Doc +pascal2C (Unit _ interface implementation init fin) = + liftM2 ($+$) (interface2C interface) (implementation2C implementation) + +pascal2C (Program _ implementation mainFunction) = do + impl <- implementation2C implementation + main <- tvar2C True + (FunctionDeclaration (Identifier "main" BTInt) (SimpleType $ Identifier "int" BTInt) [] (Just (TypesAndVars [], mainFunction))) + return $ impl $+$ main + -interface2C :: Interface -> Doc -interface2C (Interface uses tvars) = uses2C uses $+$ typesAndVars2C True tvars +interface2C :: Interface -> Reader a Doc +interface2C (Interface uses tvars) = liftM2 ($+$) (uses2C uses) (typesAndVars2C True tvars) -implementation2C :: Implementation -> Doc -implementation2C (Implementation uses tvars) = uses2C uses $+$ typesAndVars2C True tvars +implementation2C :: Implementation -> Reader a Doc +implementation2C (Implementation uses tvars) = liftM2 ($+$) (uses2C uses) (typesAndVars2C True tvars) -typesAndVars2C :: Bool -> TypesAndVars -> Doc -typesAndVars2C b (TypesAndVars ts) = vcat $ map (tvar2C b) ts +typesAndVars2C :: Bool -> TypesAndVars -> Reader a Doc +typesAndVars2C b (TypesAndVars ts) = liftM vcat $ mapM (tvar2C b) ts -uses2C :: Uses -> Doc -uses2C uses = vcat $ map (\i -> text $ "#include \"" ++ i ++ ".h\"") $ uses2List uses +uses2C :: Uses -> Reader a Doc +uses2C uses = return $ vcat . map (\i -> text $ "#include \"" ++ i ++ ".h\"") $ uses2List uses uses2List :: Uses -> [String] uses2List (Uses ids) = map (\(Identifier i _) -> i) ids -tvar2C :: Bool -> TypeVarDeclaration -> Doc -tvar2C _ (FunctionDeclaration (Identifier name _) returnType params Nothing) = - type2C returnType <+> text name <> parens (hcat $ map (tvar2C False) params) <> text ";" -tvar2C True (FunctionDeclaration (Identifier name _) returnType params (Just (tvars, phrase))) = - type2C returnType <+> text name <> parens (hcat $ map (tvar2C False) params) - $+$ - text "{" - $+$ nest 4 ( - typesAndVars2C False tvars +tvar2C :: Bool -> TypeVarDeclaration -> Reader a Doc +tvar2C _ (FunctionDeclaration (Identifier name _) returnType params Nothing) = do + t <- type2C returnType + p <- liftM hcat $ mapM (tvar2C False) params + return $ t <+> text name <> parens p <> text ";" +tvar2C True (FunctionDeclaration (Identifier name _) returnType params (Just (tvars, phrase))) = do + t <- type2C returnType + p <- liftM hcat $ mapM (tvar2C False) params + ph <- liftM2 ($+$) (typesAndVars2C False tvars) (phrase2C' phrase) + return $ + t <+> text name <> parens p $+$ - phrase2C' phrase - ) - $+$ - text "}" + text "{" + $+$ + nest 4 ph + $+$ + text "}" where - phrase2C' (Phrases p) = vcat $ map phrase2C p + phrase2C' (Phrases p) = liftM vcat $ mapM phrase2C p phrase2C' p = phrase2C p tvar2C False (FunctionDeclaration (Identifier name _) _ _ _) = error $ "nested functions not allowed: " ++ name -tvar2C _ (TypeDeclaration (Identifier i _) t) = text "type" <+> text i <+> type2C t <> text ";" +tvar2C _ (TypeDeclaration (Identifier i _) t) = do + tp <- type2C t + return $ text "type" <+> text i <+> tp <> text ";" tvar2C _ (VarDeclaration isConst (ids, t) mInitExpr) = if isConst then text "const" else empty <+> @@ -129,7 +141,7 @@ tvar2C f (OperatorDeclaration op _ ret params body) = tvar2C f (FunctionDeclaration (Identifier ("") Unknown) ret params body) -initExpr2C :: InitExpression -> Doc +initExpr2C :: InitExpression -> Reader a Doc initExpr2C (InitBinOp op expr1 expr2) = parens $ (initExpr2C expr1) <+> op2C op <+> (initExpr2C expr2) initExpr2C (InitNumber s) = text s initExpr2C (InitFloat s) = text s @@ -140,7 +152,7 @@ initExpr2C _ = text "<>" -type2C :: TypeDecl -> Doc +type2C :: TypeDecl -> Reader a Doc type2C UnknownType = text "void" type2C (String l) = text $ "string" ++ show l type2C (SimpleType (Identifier i _)) = text i @@ -152,7 +164,7 @@ type2C (Set t) = text "<>" type2C (FunctionType returnType params) = text "<>" -phrase2C :: Phrase -> Doc +phrase2C :: Phrase -> Reader a Doc phrase2C (Phrases p) = text "{" $+$ (nest 4 . vcat . map phrase2C $ p) $+$ text "}" phrase2C (ProcCall f@(FunCall {}) []) = ref2C f <> semi phrase2C (ProcCall ref params) = ref2C ref <> parens (hsep . punctuate (char ',') . map expr2C $ params) <> semi @@ -179,7 +191,7 @@ wrapPhrase p = Phrases [p] -expr2C :: Expression -> Doc +expr2C :: Expression -> Reader a Doc expr2C (Expression s) = text s expr2C (BinOp op expr1 expr2) = parens $ (expr2C expr1) <+> op2C op <+> (expr2C expr2) expr2C (NumberLiteral s) = text s @@ -193,7 +205,7 @@ expr2C _ = text "<>" -ref2C :: Reference -> Doc +ref2C :: Reference -> Reader a Doc ref2C (ArrayElement exprs ref) = ref2C ref <> (brackets . hcat) (punctuate comma $ map expr2C exprs) ref2C (SimpleReference (Identifier name _)) = text name ref2C (RecordField (Dereference ref1) ref2) = ref2C ref1 <> text "->" <> ref2C ref2