module Helium.ModuleSystem.CoreToImportEnv(getImportEnvironment) where
import Lvm.Core.Expr
import Lvm.Core.Utils
import Helium.Utils.Utils
import Helium.StaticAnalysis.Miscellaneous.TypeConversion
import Helium.Parser.ParseLibrary
import Helium.Parser.Lexer(lexer)
import Helium.Parser.Parser(type_, contextAndType)
import Helium.ModuleSystem.ImportEnvironment
import Helium.Syntax.UHA_Utils
import Lvm.Common.Id
import Helium.Syntax.UHA_Syntax
import Helium.Parser.OperatorTable
import Top.Types
import Lvm.Common.Byte(stringFromBytes)
import Helium.Syntax.UHA_Range(makeImportRange, setNameRange)
typeFromCustoms :: String -> [Custom] -> TpScheme
typeFromCustoms n [] =
internalError "CoreToImportEnv" "typeFromCustoms"
("function import without type: " ++ n)
typeFromCustoms n ( CustomDecl (DeclKindCustom ident) [CustomBytes bytes] : cs)
| stringFromId ident == "type" =
let string = filter (/= '!') (stringFromBytes bytes)
in makeTpSchemeFromType (parseFromString contextAndType string)
| otherwise =
typeFromCustoms n cs
typeFromCustoms _ _ = error "Pattern match failure in ModuleSystem.CoreToImportEnv.typeFromCustoms"
parseFromString :: HParser a -> String -> a
parseFromString p string =
case lexer [] "CoreToImportEnv" string of
Left _ -> internalError "CoreToImportEnv" "parseFromString" ("lex error in " ++ string)
Right (tokens, _) ->
case runHParser p "CoreToImportEnv" tokens True of
Left _ -> internalError "CoreToImportEnv" "parseFromString" ("parse error in " ++ string)
Right x -> x
typeSynFromCustoms :: String -> [Custom] -> (Int, Tps -> Tp)
typeSynFromCustoms n (CustomBytes bs:cs) =
let
typeSynDecl = stringFromBytes bs
ids = ( map (\x -> nameFromString [x])
. filter (' '/=)
. takeWhile ('='/=)
. drop (length n + 1)
)
typeSynDecl
rhsType = ( drop 1
. dropWhile ('='/=)
)
typeSynDecl
in
( arityFromCustoms n cs
, \ts -> makeTpFromType (zip ids ts) (parseFromString type_ rhsType)
)
typeSynFromCustoms n _ =
internalError "CoreToImportEnv" "typeSynFromCustoms"
("type synonym import missing definition: " ++ n)
arityFromCustoms :: String -> [Custom] -> Int
arityFromCustoms n [] =
internalError "CoreToImportEnv" "arityFromCustoms"
("type constructor import without kind: " ++ n)
arityFromCustoms _ ( CustomInt arity : _ ) = arity
arityFromCustoms _ ( CustomDecl (DeclKindCustom ident) [CustomBytes bytes] : _ )
| stringFromId ident == "kind" =
(length . filter ('*'==) . stringFromBytes) bytes 1
arityFromCustoms n (_:cs) = arityFromCustoms n cs
makeOperatorTable :: Name -> [Custom] -> [(Name, (Int, Assoc))]
makeOperatorTable oper (CustomInt i : CustomBytes bs : _) =
let
associativity =
case stringFromBytes bs of
"left" -> AssocLeft
"right" -> AssocRight
"none" -> AssocNone
assocStr -> intErr ("unknown associativity: " ++ assocStr)
intErr = internalError "CoreToImportEnv" "makeOperatorTable"
in
if getNameName oper == "-" then
[ (oper, (i, associativity))
, (intUnaryMinusName, (i, associativity))
, (floatUnaryMinusName, (i, associativity))
]
else
[(oper, (i, associativity))]
makeOperatorTable oper _ =
internalError "CoreToImportEnv" "makeOperatorTable"
("infix decl missing priority or associativity: " ++ show oper)
makeImportName :: String -> Id -> Id -> Name
makeImportName importedInMod importedFromMod n =
setNameRange
(nameFromId n)
(makeImportRange (idFromString importedInMod) importedFromMod)
getImportEnvironment :: String -> [CoreDecl] -> ImportEnvironment
getImportEnvironment importedInModule = foldr insert emptyEnvironment
where
insert decl =
case decl of
DeclAbstract { declName = n
, declAccess = Imported{importModule = importedFromModId}
, declCustoms = cs
} ->
addType
(makeImportName importedInModule importedFromModId n)
(typeFromCustoms (stringFromId n) cs)
DeclExtern { declName = n
, declAccess = Imported{importModule = importedFromModId}
, declCustoms = cs
} ->
addType
(makeImportName importedInModule importedFromModId n)
(typeFromCustoms (stringFromId n) cs)
DeclCon { declName = n
, declAccess = Imported{importModule = importedFromModId}
, declCustoms = cs
} ->
addValueConstructor
(makeImportName importedInModule importedFromModId n)
(typeFromCustoms (stringFromId n) cs)
DeclCustom { declName = n
, declAccess = Imported{importModule = importedFromModId}
, declKind = DeclKindCustom ident
, declCustoms = cs
}
| stringFromId ident == "data" ->
addTypeConstructor
(makeImportName importedInModule importedFromModId n)
(arityFromCustoms (stringFromId n) cs)
DeclCustom { declName = n
, declAccess = Imported{importModule = importedFromModId}
, declKind = DeclKindCustom ident
, declCustoms = cs
}
| stringFromId ident == "typedecl" ->
let typename = makeImportName importedInModule importedFromModId n
pair = typeSynFromCustoms (stringFromId n) cs
in addTypeSynonym typename pair . addTypeConstructor typename (fst pair)
DeclCustom { declName = n
, declKind = DeclKindCustom ident
, declCustoms = cs
}
| stringFromId ident == "infix" ->
flip (foldr (uncurry addOperator)) (makeOperatorTable (nameFromId n) cs)
DeclCustom { declName = _
, declKind = DeclKindCustom ident
, declCustoms = cs
}
| stringFromId ident == "strategy" ->
let (CustomDecl _ [CustomBytes bytes]) = head cs
text = stringFromBytes bytes
in case reads text of
[(rule, [])] -> addTypingStrategies rule
_ -> intErr "Could not parse typing strategy from core file"
DeclAbstract{ declName = n } ->
intErr ("don't know how to handle declared DeclAbstract: " ++ stringFromId n)
DeclExtern { declName = n } ->
intErr ("don't know how to handle declared DeclExtern: " ++ stringFromId n)
DeclCon { declName = n } ->
intErr ("don't know how to handle declared DeclCon: " ++ stringFromId n)
DeclCustom { declName = n } ->
intErr ("don't know how to handle DeclCustom: " ++ stringFromId n)
DeclValue { declName = n } ->
intErr ("don't know how to handle DeclValue: " ++ stringFromId n)
DeclImport { declName = n } ->
intErr ("don't know how to handle DeclImport: " ++ stringFromId n)
intErr = internalError "CoreToImportEnv" "getImportEnvironment"