curry-frontend-0.2.3: src/SyntaxColoring.hs
module SyntaxColoring (Program,Code(..),TypeKind(..),ConstructorKind(..),
IdentifierKind(..),FunctionKind(..), genProgram,
code2string,getQualIdent, position2code,
area2codes) where
import Debug.Trace
import Data.Function(on)
import Data.Maybe
import Data.Either
import Data.List
import Data.Char hiding(Space)
import Curry.Base.Position
import Curry.Base.Ident
import Curry.Base.MessageMonad
import Curry.Syntax
import Curry.Syntax.Lexer
debug = False -- mergen von Token und Codes
trace' s x = if debug then trace s x else x
debug' = False -- messages
trace'' s x = if debug' then trace s x else x
type Program = [(Int,Int,Code)]
data Code = Keyword String
| Space Int
| NewLine
| ConstructorName ConstructorKind QualIdent
| TypeConstructor TypeKind QualIdent
| Function FunctionKind QualIdent
| ModuleName ModuleIdent
| Commentary String
| NumberCode String
| StringCode String
| CharCode String
| Symbol String
| Identifier IdentifierKind QualIdent
| CodeWarning [WarnMsg] Code
| NotParsed String
deriving Show
data TypeKind = TypeDecla
| TypeUse
| TypeExport deriving Show
data ConstructorKind = ConstrPattern
| ConstrCall
| ConstrDecla
| OtherConstrKind deriving Show
data IdentifierKind = IdDecl
| IdOccur
| UnknownId deriving Show
data FunctionKind = InfixFunction
| TypSig
| FunDecl
| FunctionCall
| OtherFunctionKind deriving Show
--- @param plaintext
--- @param list with parse-Results with descending quality e.g. [typingParse,fullParse,parse]
--- @param lex-Result
--- @return program
genProgram :: String -> [MsgMonad Module] -> MsgMonad [(Position,Token)] -> Program
genProgram plainText parseResults m
= case runMsg m of
(Left e, msgs) -> buildMessagesIntoPlainText (e : msgs) plainText
(Right posNtokList, mess)
-> let messages = (prepareMessages (concatMap getMessages parseResults ++ mess))
mergedMessages = (mergeMessages' (trace' ("Messages: " ++ show messages) messages) posNtokList)
(nameList,codes) = catIdentifiers parseResults
in tokenNcodes2codes nameList 1 1 mergedMessages codes
--- @param Program
--- @param line
--- @param col
--- @return Code at this Position
position2code :: Program -> Int -> Int -> Maybe Code
position2code [] _ _ = Nothing
position2code [_] _ _ = Nothing
position2code ((l,c,code):xs@((_,c2,_):_)) line col
| line == l && col >= c && col < c2 = Just code
| l > line = Nothing
| otherwise = position2code xs line col
area2codes :: Program -> Position -> Position -> [Code]
area2codes [] _ _ = []
area2codes xxs@((l,c,code):xs) p1@Position{file=file} p2
| p1 > p2 = area2codes xxs p2 p1
| posEnd >= p1 && posBegin <= p2 = code : area2codes xs p1 p2
| posBegin > p2 = []
| otherwise = area2codes xs p1 p2
where
posBegin = Position file l c noRef
posEnd = Position file l (c + length (code2string code)) noRef
--- @param code
--- @return qualIdent if available
getQualIdent :: Code -> Maybe QualIdent
getQualIdent (ConstructorName _ qualIdent) = Just qualIdent
getQualIdent (Function _ qualIdent) = Just qualIdent
getQualIdent (Identifier _ qualIdent) = Just qualIdent
getQualIdent (TypeConstructor _ qualIdent) = Just qualIdent
getQualIdent _ = Nothing
-- DEBUGGING----------- wird bald nicht mehr gebraucht
setMessagePosition :: WarnMsg -> WarnMsg
setMessagePosition m@(WarnMsg (Just p) _) = trace'' ("pos:" ++ show p ++ ":" ++ show m) m
setMessagePosition (WarnMsg _ m) =
let mes@(WarnMsg pos _) = (WarnMsg (getPositionFromString m) m) in
trace'' ("pos:" ++ show pos ++ ":" ++ show mes) mes
getPositionFromString :: String -> Maybe Position
getPositionFromString message =
if line > 0 && col > 0
then Just Position{file=file,line=line,column=col,astRef=noRef}
else Nothing
where
file = takeWhile (/= '"') (tail (dropWhile (/= '"') message))
line = readInt (takeWhile (/= '.') (drop 7 (dropWhile (/= ',') message)))
col = readInt (takeWhile (/= ':') (tail (dropWhile (/= '.') (drop 7 (dropWhile (/= ',') message)))))
readInt :: String -> Int
readInt s =
let onlyNum = filter isDigit s in
if null onlyNum
then 0
else read onlyNum :: Int
-- -------------------------
-- -------------------------
flatCode :: Code -> Code
flatCode (CodeWarning _ code) = code
flatCode code = code
-- ----------Message---------------------------------------
getMessages :: MsgMonad a -> [WarnMsg]
getMessages = snd . runMsg --(Result mess _) = mess
-- getMessages (Failure mess) = mess
lessMessage :: WarnMsg -> WarnMsg -> Bool
lessMessage (WarnMsg mPos1 _) (WarnMsg mPos2 _) = mPos1 < mPos2
nubMessages :: [WarnMsg] -> [WarnMsg]
nubMessages = nubBy eqMessage
eqMessage :: WarnMsg -> WarnMsg -> Bool
eqMessage (WarnMsg p1 s1) (WarnMsg p2 s2) = (p1 == p2) && (s1 == s2)
prepareMessages :: [WarnMsg] -> [WarnMsg]
prepareMessages = qsort lessMessage . map setMessagePosition . nubMessages
buildMessagesIntoPlainText :: [WarnMsg] -> String -> Program
buildMessagesIntoPlainText messages text =
buildMessagesIntoPlainText' messages (lines text) [] 1
where
buildMessagesIntoPlainText' :: [WarnMsg] -> [String] -> [String] -> Int -> Program
buildMessagesIntoPlainText' _ [] [] _ =
[]
buildMessagesIntoPlainText' _ [] postStrs line =
[(line,1,NotParsed (unlines postStrs))]
buildMessagesIntoPlainText' [] preStrs postStrs line =
[(line,1,NotParsed (unlines (preStrs ++ postStrs)))]
buildMessagesIntoPlainText' messages (str:preStrs) postStrs ln =
let (pre,post) = partition isLeq messages in
if null pre
then buildMessagesIntoPlainText' post preStrs (postStrs ++ [str]) (ln + 1)
else (ln,1,NotParsed (unlines postStrs)) :
(ln,1,CodeWarning pre (NotParsed str)) :
(ln,1,NewLine) :
buildMessagesIntoPlainText' post preStrs [] (ln + 1)
where
isLeq (WarnMsg (Just p) _) = line p <= ln
isLeq _ = True
--- @param parse-Modules [typingParse,fullParse,parse]
catIdentifiers :: [MsgMonad Module] -> ([(ModuleIdent,ModuleIdent)],[Code])
catIdentifiers = catIds . rights_sc . map (fst . runMsg)
where
catIds [] = ([],[])
catIds [m] =
catIdentifiers' m Nothing
catIds rs@(m:y:ys) =
catIdentifiers' (last rs) (Just m)
-- not in base befoer base4
rights_sc xs = [ x | Right x <- xs]
--- @param parse-Module
--- @param Maybe betterParse-Module
catIdentifiers' :: Module -> Maybe Module -> ([(ModuleIdent,ModuleIdent)],[Code])
catIdentifiers' (Module moduleIdent maybeExportSpec decls)
Nothing =
let codes = (concatMap decl2codes (qsort lessDecl decls)) in
(concatMap renamedImports decls,
ModuleName moduleIdent :
maybe [] exportSpec2codes maybeExportSpec ++ codes)
catIdentifiers' (Module moduleIdent maybeExportSpec1 _)
(Just (Module _ maybeExportSpec2 decls)) =
let codes = (concatMap decl2codes (qsort lessDecl decls)) in
(concatMap renamedImports decls,
replaceFunctionCalls $
map (addModuleIdent moduleIdent)
([ModuleName moduleIdent] ++
mergeExports2codes
(maybe [] (\(Exporting _ i) -> i) maybeExportSpec1)
(maybe [] (\(Exporting _ i) -> i) maybeExportSpec2) ++
codes))
renamedImports :: Decl -> [(ModuleIdent,ModuleIdent)]
renamedImports decl =
case decl of
(ImportDecl _ oldName _ (Just newName) _) -> [(oldName,newName)]
_ -> []
replaceFunctionCalls :: [Code] -> [Code]
replaceFunctionCalls codes = map (idOccur2functionCall qualIdents) codes
where
qualIdents = findFunctionDecls codes
findFunctionDecls :: [Code] -> [QualIdent]
findFunctionDecls = mapMaybe getQualIdent .
filter isFunctionDecl .
map flatCode
isFunctionDecl :: Code -> Bool
isFunctionDecl (Function FunDecl _) = True
isFunctionDecl _ = False
idOccur2functionCall :: [QualIdent] -> Code -> Code
idOccur2functionCall qualIdents ide@(Identifier IdOccur qualIdent)
| isQualified qualIdent = Function FunctionCall qualIdent
| elem qualIdent qualIdents = Function FunctionCall qualIdent
| otherwise = ide
idOccur2functionCall qualIdents (CodeWarning mess code) =
CodeWarning mess (idOccur2functionCall qualIdents code)
idOccur2functionCall _ code = code
addModuleIdent :: ModuleIdent -> Code -> Code
addModuleIdent moduleIdent c@(Function x qualIdent)
| uniqueId (unqualify qualIdent) == 0 =
Function x (qualQualify moduleIdent qualIdent)
| otherwise = c
addModuleIdent moduleIdent cn@(ConstructorName x qualIdent)
| not $ isQualified qualIdent =
ConstructorName x (qualQualify moduleIdent qualIdent)
| otherwise = cn
addModuleIdent moduleIdent tc@(TypeConstructor TypeDecla qualIdent)
| not $ isQualified qualIdent =
TypeConstructor TypeDecla (qualQualify moduleIdent qualIdent)
| otherwise = tc
addModuleIdent moduleIdent (CodeWarning mess code) =
CodeWarning mess (addModuleIdent moduleIdent code)
addModuleIdent _ c = c
-- ----------------------------------------
mergeMessages' :: [WarnMsg] -> [(Position,Token)] -> [([WarnMsg],Position,Token)]
mergeMessages' _ [] = []
mergeMessages' [] ((p,t):ps) = ([],p,t) : mergeMessages' [] ps
mergeMessages' mss@(m@(WarnMsg mPos x):ms) ((p,t):ps)
| mPos <= Just p = trace' (show mPos ++ " <= " ++ show (Just p) ++ " Message: " ++ x) ([m],p,t) : mergeMessages' ms ps
| otherwise = ([],p,t) : mergeMessages' mss ps
tokenNcodes2codes :: [(ModuleIdent,ModuleIdent)] -> Int -> Int -> [([WarnMsg],Position,Token)] -> [Code] -> [(Int,Int,Code)]
tokenNcodes2codes _ _ _ [] _ = []
tokenNcodes2codes nameList currLine currCol toks@((messages,pos@Position{line=line,column=col},token):ts) codes
| currLine < line =
trace' " NewLine: "
((currLine,currCol,NewLine) :
tokenNcodes2codes nameList (currLine + 1) 1 toks codes)
| currCol < col =
trace' (" Space " ++ show (col - currCol))
((currLine,currCol,Space (col - currCol)) :
tokenNcodes2codes nameList currLine col toks codes)
| isTokenIdentifier token && null codes =
trace' ("empty Code-List, Token: " ++ show (line,col) ++ show token)
(addMessage [(currLine,currCol,NotParsed tokenStr)] ++ tokenNcodes2codes nameList newLine newCol ts codes)
| not (isTokenIdentifier token) =
trace' (" Token ist kein Identifier: " ++ tokenStr )
(addMessage [(currLine,currCol,token2code token)] ++ tokenNcodes2codes nameList newLine newCol ts codes)
| tokenStr == code2string (head codes) =
trace' (" Code wird genommen: " ++ show (head codes) )
(addMessage [(currLine,currCol,head codes)] ++ tokenNcodes2codes nameList newLine newCol ts (tail codes))
| tokenStr == code2qualString (renameModuleIdents nameList (head codes)) =
let mIdent = maybe Nothing rename (getModuleIdent (head codes))
lenMod = maybe 0 (length . moduleName) mIdent
startPos = maybe currCol (const (currCol + lenMod + 1)) mIdent
symbol = [(currLine,currCol + lenMod,Symbol ".")]
prefix = maybe []
( (: symbol) .
( \i -> (currLine,
currCol,
ModuleName i)))
mIdent in
trace' (" Code wird genommen: " ++ show (head codes) )
(addMessage (prefix ++ [(currCol,startPos,head codes)]) ++ tokenNcodes2codes nameList newLine newCol ts (tail codes))
| elem tokenStr (codeQualifiers (head codes)) =
trace' (" Token: "++ tokenStr ++" ist Modulname von: " ++ show (head codes) )
(addMessage [(currLine,currCol,ModuleName (mkMIdent [tokenStr]))] ++
tokenNcodes2codes nameList newLine newCol ts codes)
| otherwise =
trace' (" Token: "++
tokenStr ++
",Code faellt weg:" ++
code2string (head codes) ++
"|" ++
code2qualString (head codes))
(tokenNcodes2codes nameList currLine currCol toks (tail codes))
where
tokenStr = token2string token
newLine = (currLine + length (lines tokenStr)) - 1
newCol = currCol + length tokenStr
rename mid = Just $ fromMaybe mid (lookup mid nameList)
addMessage [] = []
addMessage ((l,c,code):cs)
| null messages = (l,c,code):cs
| otherwise = trace' ("Warning bei code: " ++ show codes ++ ":" ++ show messages)
((l,c,CodeWarning messages code): addMessage cs)
renameModuleIdents :: [(ModuleIdent,ModuleIdent)] -> Code -> Code
renameModuleIdents nameList c =
case c of
Function x qualIdent -> Function x (rename qualIdent (qualidMod qualIdent))
Identifier x qualIdent -> Identifier x (rename qualIdent (qualidMod qualIdent))
_ -> c
where
rename x (Nothing) = x
rename x (Just m) = maybe x (\ m' -> qualifyWith m' (qualidId x)) (lookup m nameList)
{-
codeWithoutUniqueID :: Code -> String
codeWithoutUniqueID code = maybe (code2string code) (name . unqualify) $ getQualIdent code
codeUnqualify :: Code -> Code
codeUnqualify code = maybe code (setQualIdent code . qualify . unqualify) $ getQualIdent code
-}
codeQualifiers :: Code -> [String]
codeQualifiers = maybe [] moduleQualifiers . getModuleIdent
getModuleIdent :: Code -> Maybe ModuleIdent
getModuleIdent (ConstructorName _ qualIdent) = qualidMod qualIdent
getModuleIdent (Function _ qualIdent) = qualidMod qualIdent
getModuleIdent (ModuleName moduleIdent) = Just moduleIdent
getModuleIdent (Identifier _ qualIdent) = qualidMod qualIdent
getModuleIdent (TypeConstructor _ qualIdent) = qualidMod qualIdent
getModuleIdent _ = Nothing
{-
setQualIdent :: Code -> QualIdent -> Code
setQualIdent (Keyword str) _ = (Keyword str)
setQualIdent (Space i) _ = (Space i)
setQualIdent NewLine _ = NewLine
setQualIdent (ConstructorName kind _) qualIdent = (ConstructorName kind qualIdent)
setQualIdent (Function kind _) qualIdent = (Function kind qualIdent)
setQualIdent (ModuleName moduleIdent) _ = (ModuleName moduleIdent)
setQualIdent (Commentary str) _ = (Commentary str)
setQualIdent (NumberCode str) _ = (NumberCode str)
setQualIdent (Symbol str) _ = (Symbol str)
setQualIdent (Identifier kind _) qualIdent = (Identifier kind qualIdent)
setQualIdent (TypeConstructor kind _) qualIdent = (TypeConstructor kind qualIdent)
setQualIdent (StringCode str) _ = (StringCode str)
setQualIdent (CharCode str) _ = (CharCode str)
-}
code2string (Keyword str) = str
code2string (Space i)= concat (replicate i " ")
code2string NewLine = "\n"
code2string (ConstructorName _ qualIdent) = name $ unqualify qualIdent
code2string (Function _ qualIdent) = name $ unqualify qualIdent
code2string (ModuleName moduleIdent) = moduleName moduleIdent
code2string (Commentary str) = str
code2string (NumberCode str) = str
code2string (Symbol str) = str
code2string (Identifier _ qualIdent) = name $ unqualify qualIdent
code2string (TypeConstructor _ qualIdent) = name $ unqualify qualIdent
code2string (StringCode str) = str
code2string (CharCode str) = str
code2string (NotParsed str) = str
code2string _ = "" -- error / warning
code2qualString (ConstructorName _ qualIdent) = qualName qualIdent
code2qualString (Function _ qualIdent) = qualName qualIdent
code2qualString (Identifier _ qualIdent) = qualName qualIdent
code2qualString (TypeConstructor _ qualIdent) = qualName qualIdent
code2qualString x = code2string x
token2code :: Token -> Code
token2code tok@(Token cat _)
| elem cat [IntTok,FloatTok,IntegerTok]
= NumberCode (token2string tok)
| elem cat [KW_case,KW_choice,KW_data,KW_do,KW_else,KW_eval,KW_external,
KW_free,KW_if,KW_import,KW_in,KW_infix,KW_infixl,KW_infixr,
KW_let,KW_module,KW_newtype,KW_of,KW_rigid,KW_then,KW_type,
KW_where,Id_as,Id_ccall,Id_forall,Id_hiding,Id_interface,Id_primitive,
Id_qualified]
= Keyword (token2string tok)
| elem cat [LeftParen,RightParen,Semicolon,LeftBrace,RightBrace,LeftBracket,
RightBracket,Comma,Underscore,Backquote,
At,Colon,DotDot,DoubleColon,Equals,Backslash,Bar,LeftArrow,RightArrow,
Tilde]
= Symbol (token2string tok)
| elem cat [LineComment, NestedComment]
= Commentary (token2string tok)
| isTokenIdentifier tok
= Identifier UnknownId $ qualify $ mkIdent $ token2string tok
| cat == StringTok
= StringCode (token2string tok)
| cat == CharTok
= CharCode (token2string tok)
| elem cat [EOF,VSemicolon,VRightBrace] = Space 0
isTokenIdentifier :: Token -> Bool
isTokenIdentifier (Token cat _) =
elem cat [Id,QId,Sym,QSym,Sym_Dot,Sym_Minus,Sym_MinusDot]
-- DECL Position
getPosition :: Decl -> Position
getPosition (ImportDecl pos _ _ _ _) = pos
getPosition (InfixDecl pos _ _ _) = pos
getPosition (DataDecl pos _ _ _) = pos
getPosition (NewtypeDecl pos _ _ _) = pos
getPosition (TypeDecl pos _ _ _) = pos
getPosition (TypeSig pos _ _) = pos
getPosition (EvalAnnot pos _ _) = pos
getPosition (FunctionDecl pos _ _) = pos
getPosition (ExternalDecl pos _ _ _ _) = pos
getPosition (FlatExternalDecl pos _) = pos
getPosition (PatternDecl pos _ _) = pos
getPosition (ExtraVariables pos _) = pos
lessDecl :: Decl -> Decl -> Bool
lessDecl = (<) `on` getPosition
qsort _ [] = []
qsort less (x:xs) = qsort less [y | y <- xs, less y x] ++ [x] ++ qsort less [y | y <- xs, not $ less y x]
-- DECL TO CODE --------------------------------------------------------------------
exportSpec2codes :: ExportSpec -> [Code]
exportSpec2codes (Exporting _ exports) = concatMap (export2codes []) exports
--- @param parse-Exports
--- @param betterParse-Exports
mergeExports2codes :: [Export] -> [Export] -> [Code]
mergeExports2codes [] _ = []
mergeExports2codes (e:es) xs = concatMap (export2codes xs) (e:es)
export2codes :: [Export] -> Export -> [Code]
export2codes exports e@(Export qualIdent)
| length (filter checkDouble exports) /= 1 =
[Identifier UnknownId qualIdent]
| otherwise =
let [export] = (filter checkDouble exports) in
export2c export
where
checkDouble (ExportTypeWith q _) = eqQualIdent qualIdent q
checkDouble (Export q) = eqQualIdent qualIdent q
checkDouble _ = False
eqQualIdent q1 q2
| q1 == q2 = True
| not (isQualified q1) = unqualify q1 == unqualify q2
| otherwise = False
export2c (Export qualIdent) =
[Function OtherFunctionKind qualIdent]
export2c _ =
[TypeConstructor TypeExport qualIdent]
export2codes _ (ExportTypeWith qualIdent idents) =
TypeConstructor TypeExport qualIdent : map (Function OtherFunctionKind . qualify) idents
export2codes _ (ExportTypeAll qualIdent) =
[TypeConstructor TypeExport qualIdent]
export2codes _ (ExportModule moduleIdent) =
[ModuleName moduleIdent]
decl2codes :: Decl -> [Code]
decl2codes (ImportDecl _ moduleIdent xQualified mModuleIdent importSpec) =
[ModuleName moduleIdent] ++
maybe [] ((:[]) . ModuleName) mModuleIdent ++
maybe [] (importSpec2codes moduleIdent) importSpec
decl2codes (InfixDecl _ _ _ idents) =
map (Function InfixFunction . qualify) idents
decl2codes (DataDecl _ ident idents constrDecls) =
TypeConstructor TypeDecla (qualify ident) :
map (Identifier UnknownId . qualify) idents ++
concatMap constrDecl2codes constrDecls
decl2codes (NewtypeDecl xPosition xIdent yIdents xNewConstrDecl) =
[]
decl2codes (TypeDecl _ ident idents typeExpr) =
TypeConstructor TypeDecla (qualify ident) :
map (Identifier UnknownId . qualify) idents ++
typeExpr2codes typeExpr
decl2codes (TypeSig _ idents typeExpr) =
map (Function TypSig . qualify) idents ++ typeExpr2codes typeExpr
decl2codes (EvalAnnot xPosition idents xEvalAnnotation) =
map (Function FunDecl . qualify) idents
decl2codes (FunctionDecl _ _ equations) =
concatMap equation2codes equations
decl2codes (ExternalDecl xPosition xCallConv xString xIdent xTypeExpr) =
[]
decl2codes (FlatExternalDecl _ idents) =
map (Function FunDecl . qualify) idents
decl2codes (PatternDecl xPosition constrTerm rhs) =
constrTerm2codes constrTerm ++ rhs2codes rhs
decl2codes (ExtraVariables _ idents) =
map (Identifier IdDecl . qualify) idents
equation2codes :: Equation -> [Code]
equation2codes (Equation _ lhs rhs) =
lhs2codes lhs ++ rhs2codes rhs
lhs2codes :: Lhs -> [Code]
lhs2codes (FunLhs ident constrTerms) =
Function FunDecl (qualify ident) : concatMap constrTerm2codes constrTerms
lhs2codes (OpLhs constrTerm1 ident constrTerm2) =
constrTerm2codes constrTerm1 ++ [Function FunDecl $ qualify ident] ++ constrTerm2codes constrTerm2
lhs2codes (ApLhs lhs constrTerms) =
lhs2codes lhs ++ concatMap constrTerm2codes constrTerms
rhs2codes :: Rhs -> [Code]
rhs2codes (SimpleRhs _ expression decls) =
expression2codes expression ++ concatMap decl2codes decls
rhs2codes (GuardedRhs condExprs decls) =
concatMap condExpr2codes condExprs ++ concatMap decl2codes decls
condExpr2codes :: CondExpr -> [Code]
condExpr2codes (CondExpr _ expression1 expression2) =
expression2codes expression1 ++ expression2codes expression2
constrTerm2codes :: ConstrTerm -> [Code]
constrTerm2codes (LiteralPattern literal) = []
constrTerm2codes (NegativePattern ident literal) = []
constrTerm2codes (VariablePattern ident) = [Identifier IdDecl (qualify ident)]
constrTerm2codes (ConstructorPattern qualIdent constrTerms) =
ConstructorName ConstrPattern qualIdent : concatMap constrTerm2codes constrTerms
constrTerm2codes (InfixPattern constrTerm1 qualIdent constrTerm2) =
constrTerm2codes constrTerm1 ++ [ConstructorName ConstrPattern qualIdent] ++ constrTerm2codes constrTerm2
constrTerm2codes (ParenPattern constrTerm) = constrTerm2codes constrTerm
constrTerm2codes (TuplePattern _ constrTerms) = concatMap constrTerm2codes constrTerms
constrTerm2codes (ListPattern _ constrTerms) = concatMap constrTerm2codes constrTerms
constrTerm2codes (AsPattern ident constrTerm) =
Function OtherFunctionKind (qualify ident) : constrTerm2codes constrTerm
constrTerm2codes (LazyPattern _ constrTerm) = constrTerm2codes constrTerm
constrTerm2codes (FunctionPattern qualIdent constrTerms) =
Function OtherFunctionKind qualIdent : concatMap constrTerm2codes constrTerms
constrTerm2codes (InfixFuncPattern constrTerm1 qualIdent constrTerm2) =
constrTerm2codes constrTerm1 ++ [Function InfixFunction qualIdent] ++ constrTerm2codes constrTerm2
expression2codes :: Expression -> [Code]
expression2codes (Literal literal) = []
expression2codes (Variable qualIdent) =
[Identifier IdOccur qualIdent]
expression2codes (Constructor qualIdent) =
[ConstructorName ConstrCall qualIdent]
expression2codes (Paren expression) =
expression2codes expression
expression2codes (Typed expression typeExpr) =
expression2codes expression ++ typeExpr2codes typeExpr
expression2codes (Tuple _ expressions) =
concatMap expression2codes expressions
expression2codes (List _ expressions) =
concatMap expression2codes expressions
expression2codes (ListCompr _ expression statements) =
expression2codes expression ++ concatMap statement2codes statements
expression2codes (EnumFrom expression) =
expression2codes expression
expression2codes (EnumFromThen expression1 expression2) =
expression2codes expression1 ++ expression2codes expression2
expression2codes (EnumFromTo expression1 expression2) =
expression2codes expression1 ++ expression2codes expression2
expression2codes (EnumFromThenTo expression1 expression2 expression3) =
expression2codes expression1 ++
expression2codes expression2 ++
expression2codes expression3
expression2codes (UnaryMinus ident expression) =
Symbol (name ident) : expression2codes expression
expression2codes (Apply expression1 expression2) =
expression2codes expression1 ++ expression2codes expression2
expression2codes (InfixApply expression1 infixOp expression2) =
expression2codes expression1 ++ infixOp2codes infixOp ++ expression2codes expression2
expression2codes (LeftSection expression infixOp) =
expression2codes expression ++ infixOp2codes infixOp
expression2codes (RightSection infixOp expression) =
infixOp2codes infixOp ++ expression2codes expression
expression2codes (Lambda _ constrTerms expression) =
concatMap constrTerm2codes constrTerms ++ expression2codes expression
expression2codes (Let decls expression) =
concatMap decl2codes decls ++ expression2codes expression
expression2codes (Do statements expression) =
concatMap statement2codes statements ++ expression2codes expression
expression2codes (IfThenElse _ expression1 expression2 expression3) =
expression2codes expression1 ++ expression2codes expression2 ++ expression2codes expression3
expression2codes (Case _ expression alts) =
expression2codes expression ++ concatMap alt2codes alts
infixOp2codes :: InfixOp -> [Code]
infixOp2codes (InfixOp qualIdent) = [Function InfixFunction qualIdent]
infixOp2codes (InfixConstr qualIdent) = [ConstructorName OtherConstrKind qualIdent]
statement2codes :: Statement -> [Code]
statement2codes (StmtExpr _ expression) =
expression2codes expression
statement2codes (StmtDecl decls) =
concatMap decl2codes decls
statement2codes (StmtBind _ constrTerm expression) =
constrTerm2codes constrTerm ++ expression2codes expression
alt2codes :: Alt -> [Code]
alt2codes (Alt _ constrTerm rhs) =
constrTerm2codes constrTerm ++ rhs2codes rhs
constrDecl2codes :: ConstrDecl -> [Code]
constrDecl2codes (ConstrDecl _ idents ident typeExprs) =
ConstructorName ConstrDecla (qualify ident) : concatMap typeExpr2codes typeExprs
constrDecl2codes (ConOpDecl _ idents typeExpr1 ident typeExpr2) =
typeExpr2codes typeExpr1 ++ [ConstructorName ConstrDecla $ qualify ident] ++ typeExpr2codes typeExpr2
importSpec2codes :: ModuleIdent -> ImportSpec -> [Code]
importSpec2codes moduleIdent (Importing _ imports) = concatMap (import2codes moduleIdent) imports
importSpec2codes moduleIdent (Hiding _ imports) = concatMap (import2codes moduleIdent) imports
import2codes :: ModuleIdent -> Import -> [Code]
import2codes moduleIdent (Import ident) =
[Function OtherFunctionKind $ qualifyWith moduleIdent ident]
import2codes moduleIdent (ImportTypeWith ident idents) =
ConstructorName OtherConstrKind (qualifyWith moduleIdent ident) :
map (Function OtherFunctionKind . qualifyWith moduleIdent) idents
import2codes moduleIdent (ImportTypeAll ident) =
[ConstructorName OtherConstrKind $ qualifyWith moduleIdent ident]
typeExpr2codes :: TypeExpr -> [Code]
typeExpr2codes (ConstructorType qualIdent typeExprs) =
TypeConstructor TypeUse qualIdent : concatMap typeExpr2codes typeExprs
typeExpr2codes (VariableType ident) =
[Identifier IdOccur (qualify ident)]
typeExpr2codes (TupleType typeExprs) =
concatMap typeExpr2codes typeExprs
typeExpr2codes (ListType typeExpr) =
typeExpr2codes typeExpr
typeExpr2codes (ArrowType typeExpr1 typeExpr2) =
typeExpr2codes typeExpr1 ++ typeExpr2codes typeExpr2
-- TOKEN TO STRING ------------------------------------------------------------
token2string (Token Id a) = attributes2string a
token2string (Token QId a) = attributes2string a
token2string (Token Sym a) = attributes2string a
token2string (Token QSym a) = attributes2string a
token2string (Token IntTok a) = attributes2string a
token2string (Token FloatTok a) = attributes2string a
token2string (Token CharTok a) = attributes2string a
token2string (Token IntegerTok a) = attributes2string a
token2string (Token StringTok a) = attributes2string a
token2string (Token LeftParen _) = "("
token2string (Token RightParen _) = ")"
token2string (Token Semicolon _) = ";"
token2string (Token LeftBrace _) = "{"
token2string (Token RightBrace _) = "}"
token2string (Token LeftBracket _) = "["
token2string (Token RightBracket _) = "]"
token2string (Token Comma _) = ","
token2string (Token Underscore _) = "_"
token2string (Token Backquote _) = "`"
token2string (Token VSemicolon _) = ""
token2string (Token VRightBrace _) = ""
token2string (Token At _) = "@"
token2string (Token Colon _) = ":"
token2string (Token DotDot _) = ".."
token2string (Token DoubleColon _) = "::"
token2string (Token Equals _) = "="
token2string (Token Backslash _) = "\\"
token2string (Token Bar _) = "|"
token2string (Token LeftArrow _) = "<-"
token2string (Token RightArrow _) = "->"
token2string (Token Tilde _) = "~"
token2string (Token Sym_Dot _) = "."
token2string (Token Sym_Minus _) = "-"
token2string (Token Sym_MinusDot _) = "-."
token2string (Token KW_case _) = "case"
token2string (Token KW_choice _) = "choice"
token2string (Token KW_data _) = "data"
token2string (Token KW_do _) = "do"
token2string (Token KW_else _) = "else"
token2string (Token KW_eval _) = "eval"
token2string (Token KW_external _) = "external"
token2string (Token KW_free _) = "free"
token2string (Token KW_if _) = "if"
token2string (Token KW_import _) = "import"
token2string (Token KW_in _) = "in"
token2string (Token KW_infix _) = "infix"
token2string (Token KW_infixl _) = "infixl"
token2string (Token KW_infixr _) = "infixr"
token2string (Token KW_let _) = "let"
token2string (Token KW_module _) = "module"
token2string (Token KW_newtype _) = "newtype"
token2string (Token KW_of _) = "of"
token2string (Token KW_rigid _) = "rigid"
token2string (Token KW_then _) = "then"
token2string (Token KW_type _) = "type"
token2string (Token KW_where _) = "where"
token2string (Token Id_as _) = "as"
token2string (Token Id_ccall _) = "ccall"
token2string (Token Id_forall _) = "forall"
token2string (Token Id_hiding _) = "hiding"
token2string (Token Id_interface _) = "interface"
token2string (Token Id_primitive _) = "primitive"
token2string (Token Id_qualified _) = "qualified"
token2string (Token EOF _) = ""
token2string (Token LineComment (StringAttributes sval _)) = sval
token2string (Token NestedComment (StringAttributes sval _)) = sval
attributes2string NoAttributes = ""
attributes2string (CharAttributes cval _) = showCh cval
attributes2string (IntAttributes ival _) = show ival
attributes2string (FloatAttributes fval _) = show fval
attributes2string (IntegerAttributes intval _) = show intval
attributes2string (StringAttributes sval _) = showSt sval
attributes2string (IdentAttributes mIdent ident) =concat (intersperse "." (mIdent ++ [ident]))
showCh c
| c == '\\' = "'\\\\'"
| elem c ('\127' : ['\001' .. '\031']) = show c
| otherwise = toString c
where
toString c = '\'' : c : "'"
showSt = addQuotes . concatMap toGoodChar
where
addQuotes x = "\"" ++ x ++ "\""
toGoodChar c
| c == '\\' = "\\\\"
| elem c ('\127' : ['\001' .. '\031']) = justShow c
| c == '"' = "\\\""
| otherwise = c : ""
where
justShow = init . tail . show