{-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Oden.Go.Packages ( PackageImportError(..), UnsupportedTypesWarning(..), Name, PackageName, PackageObject(..), nameOf, typeOf, getPackageDefinitions ) where import Oden.Go.Types as G import Control.Applicative hiding (Const) import Data.Aeson import Data.ByteString.Lazy.Char8 (pack) import Data.List (intercalate) import Foreign.C.String foreign import ccall "GetPackageObjects" c_GetPackageObjects :: CString -> IO CString type Name = String type PackageName = [String] data PackageObject = Func Name Type | Var Name Type | Const Name Type deriving (Show, Eq) nameOf :: PackageObject -> Name nameOf (Func n _) = n nameOf (Var n _) = n nameOf (Const n _) = n typeOf :: PackageObject -> Type typeOf (Func _ t) = t typeOf (Var _ t) = t typeOf (Const _ t) = t instance FromJSON PackageObject where parseJSON (Object o) = do t :: String <- o .: "objectType" case t of "func" -> Func <$> o .: "name" <*> o .: "type" "var" -> Var <$> o .: "name" <*> o .: "type" "const" -> Const <$> o .: "name" <*> o .: "type" _ -> fail ("Unknown object type: " ++ t) parseJSON v = fail $ "Expected JSON object for PackageObject but got: " ++ show v data PackageImportError = PackageImportError PackageName String deriving (Show, Eq) data PackageObjectsResponse = ErrorResponse String | ObjectsResponse [PackageObject] deriving (Show, Eq) instance FromJSON PackageObjectsResponse where parseJSON (Object o) = ErrorResponse <$> o .: "error" <|> ObjectsResponse <$> o .: "objects" parseJSON v = fail $ "Expected JSON object for PackageObjectsResponse but got: " ++ show v decodeResponse :: PackageName -> String -> Either PackageImportError [PackageObject] decodeResponse pkgName s = either (Left . PackageImportError pkgName) Right $ do value <- eitherDecode (pack s) case value of ErrorResponse err -> Left err ObjectsResponse objs -> Right objs data UnsupportedTypesWarning = UnsupportedTypesWarning { pkg :: PackageName , messages :: [(Name, String)] } deriving (Show, Eq) getPackageDefinitions :: PackageName -> IO (Either PackageImportError [PackageObject]) getPackageDefinitions pkgName = do cs <- newCString (intercalate "/" pkgName) decodeResponse pkgName <$> (c_GetPackageObjects cs >>= peekCString)