mulang-4.2.1: src/Language/Mulang/Parsers/Haskell.hs
module Language.Mulang.Parsers.Haskell (hs, parseHaskell) where
import Language.Mulang.Ast
import Language.Mulang.Builder (compact, normalizeWith, defaultNormalizationOptions, NormalizationOptions(..), SequenceSortMode(..))
import Language.Mulang.Parsers
import Language.Haskell.Syntax
import Language.Haskell.Parser
import Language.Haskell.Pretty (prettyPrint)
import Data.List (intercalate)
import Control.Fallible
instance Fallible ParseResult where
failure (ParseOk v) = Left v
failure (ParseFailed _ m) = Right m
hs :: Parser
hs = orFail . parseHaskell'
parseHaskell :: EitherParser
parseHaskell = orLeft . parseHaskell'
parseHaskell' :: String -> ParseResult Expression
parseHaskell' = fmap (normalize . mu) . parseModule . (++"\n")
where normalize = normalizeWith (defaultNormalizationOptions { sortSequenceDeclarations = SortAll })
mu :: HsModule -> Expression
mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls)
where
mergeDecls decls exp = compact (decls ++ [exp])
muDecls (HsTypeDecl _ name args t) = [TypeAlias (unwords . map muName $ name : args) (muTypeId t)]
muDecls (HsDataDecl _ _ name _ _ _ ) = [Record (muName name)]
muDecls (HsTypeSig _ names (HsQualType constraints t))
= map (muTypeSignature constraints t) names
muDecls (HsFunBind equations) | (HsMatch _ name _ _ _) <- head equations =
[Function (muName name) (map muEquation equations)]
muDecls (HsPatBind _ (HsPVar name) (HsUnGuardedRhs exp) _) = [Variable (muName name) (muExp exp)]
muDecls _ = []
muEquation :: HsMatch -> Equation
muEquation (HsMatch _ _ patterns rhs decls) =
Equation (map muPat patterns) (muRhs (concatMap muDecls decls) rhs)
muRhs decls (HsUnGuardedRhs body) = UnguardedBody (mergeDecls decls (muBody body))
muRhs decls (HsGuardedRhss guards) = GuardedBody (map (muGuardedRhs decls) guards )
muGuardedRhs decls (HsGuardedRhs _ condition body) = (mergeDecls decls (muExp condition), muBody body)
muBody = Return . muExp
muPat (HsPVar name) = VariablePattern (muName name)
muPat (HsPLit literal) = LiteralPattern (prettyPrint literal)
muPat (HsPInfixApp e1 name e2) = InfixApplicationPattern (muPat e1) (muQName name) (muPat e2)
muPat (HsPApp name elements) = ApplicationPattern (muQName name) (map muPat elements)
muPat (HsPTuple elements) = TuplePattern (map muPat elements)
muPat (HsPList elements) = ListPattern (map muPat elements)
muPat (HsPParen pattern) = muPat pattern
muPat (HsPAsPat name pattern) = AsPattern (muName name) (muPat pattern)
muPat HsPWildCard = WildcardPattern
muPat p = debugPattern p
muExp (HsVar (UnQual (HsIdent "undefined"))) = Raise (MuString "undefined")
muExp (HsVar name) = muVar (muQName name)
muExp (HsCon (UnQual (HsIdent "True"))) = MuTrue
muExp (HsCon (UnQual (HsIdent "False"))) = MuFalse
muExp (HsCon name) = Reference (muQName name)
muExp (HsLit lit) = muLit lit
muExp (HsInfixApp e1 op e2) = Application ((muVar.muQOp) op) [muExp e1, muExp e2]
muExp (HsApp (HsVar (UnQual (HsIdent "error"))) e1) = Raise (muExp e1)
muExp (HsApp (HsApp (HsApp (HsApp e1 e2) e3) e4) e5) = Application (muExp e1) [muExp e2, muExp e3, muExp e4, muExp e5]
muExp (HsApp (HsApp (HsApp e1 e2) e3) e4) = Application (muExp e1) [muExp e2, muExp e3, muExp e4]
muExp (HsApp (HsApp e1 e2) e3) = Application (muExp e1) [muExp e2, muExp e3]
muExp (HsApp e1 e2) = Application (muExp e1) [muExp e2]
muExp (HsLeftSection e1 e2) = Application (muVar $ muQOp e2) [muExp e1]
muExp (HsRightSection e1 e2) = Application (Reference "flip") [muVar $ muQOp e1, muExp e2]
muExp (HsNegApp e) = Application (Reference "-") [muExp e]
muExp (HsLambda _ args body) = Lambda (map muPat args) (muBody body)
--muExp HsLet = Let [Declaration] Expression -- ^ local declarations with @let@
muExp (HsIf e1 e2 e3) = If (muExp e1) (muExp e2) (muExp e3)
--muExp HsMatch = Match Expression [Alternative] -- ^ @case@ /exp/ @of@ /alts/
muExp (HsTuple elements) = MuTuple (map muExp elements) -- ^ tuple Expression
muExp (HsList elements) = MuList (map muExp elements)
muExp (HsParen e) = (muExp e)
muExp (HsEnumFrom from) = Application (Reference "enumFrom") [(muExp from)]
muExp (HsEnumFromTo from to) = Application (Reference "enumFromTo") [(muExp from), (muExp to)]
muExp (HsEnumFromThen from thn) = Application (Reference "enumFromThen") [(muExp from), (muExp thn)]
muExp (HsEnumFromThenTo from thn to) = Application (Reference "enumFromThenTo") [(muExp from), (muExp thn), (muExp to)]
muExp (HsListComp exp stmts) = For (map muStmt stmts) (Yield (muExp exp))
muExp (HsDo stmts) | (HsQualifier exp) <- last stmts = For (map muStmt stmts) (Yield (muExp exp))
muExp (HsExpTypeSig _ exp (HsQualType cs t)) = TypeCast (muExp exp) (muType t cs)
muExp e = debug e
muLit (HsCharPrim v) = MuChar v
muLit (HsStringPrim v) = MuString v
muLit (HsChar v) = MuChar v
muLit (HsString v) = MuString v
muLit (HsIntPrim v) = MuNumber . fromIntegral $ v
muLit (HsInt v) = MuNumber . fromIntegral $ v
muLit (HsFrac v) = MuNumber . fromRational $ v
muLit (HsFloatPrim v) = MuNumber . fromRational $ v
muLit (HsDoublePrim v) = MuNumber . fromRational $ v
muVar :: String -> Expression
muVar "==" = Equal
muVar "/=" = NotEqual
muVar v = Reference v
muName :: HsName -> String
muName (HsSymbol n) = n
muName (HsIdent n) = n
muQName (Qual _ n) = muName n
muQName (UnQual n) = muName n
muQName (Special HsUnitCon) = "()"
muQName (Special HsListCon) = "[]"
muQName (Special HsFunCon) = "->"
muQName (Special (HsTupleCon times)) = intercalate "" . replicate times $ ","
muQName (Special (HsCons)) = ":"
muQOp (HsQVarOp name) = muQName name
muQOp (HsQConOp name) = muQName name
muStmt (HsGenerator _ pat exp) = Generator (muPat pat) (muExp exp)
muStmt (HsQualifier exp) = Guard (muExp exp)
muTypeSignature :: [HsAsst] -> HsType -> HsName -> Expression
muTypeSignature cs t name = TypeSignature (muName name) (muType t cs)
muType :: HsType -> [HsAsst] -> Type
muType t cs | null initTypes = SimpleType lastType constraints
| otherwise = ParameterizedType initTypes lastType constraints
where
initTypes = init topTypes
lastType = last topTypes
topTypes = muTopTypes t
constraints = map muConstraint cs
muConstraint :: HsAsst -> Identifier
muConstraint (constraint, targets) =
intercalate " " (muQName constraint : map muTypeId targets)
muTopTypes (HsTyFun i o) = muTypeId i : muTopTypes o
muTopTypes t = [muTypeId t]
muTypeId :: HsType -> Identifier
muTypeId (HsTyFun i o) = muTypeId i ++ " -> " ++ muTypeId o
muTypeId (HsTyCon name) = muQName name
muTypeId (HsTyVar name) = muName name
muTypeId (HsTyTuple ts) = "(" ++ (intercalate ", " . map muTypeId $ ts) ++ ")"
muTypeId (HsTyApp (HsTyCon (Special HsListCon)) t2) = "[" ++ muTypeId t2 ++ "]"
muTypeId (HsTyApp t1 t2) = muTypeId t1 ++ " " ++ muTypeId t2