egison-quote 0.1.1 → 0.2
raw patch · 2 files changed
+116/−81 lines, 2 filesdep ~egisonPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: egison
API changes (from Hackage documentation)
- Language.Egison.Quote: data TypeSignature
- Language.Egison.Quote: instance [incoherent] Show TypeSignature
- Language.Egison.Quote: evalEgisonTopLevel :: EgisonExpr -> [String] -> (Name -> [StmtQ]) -> ExpQ
+ Language.Egison.Quote: evalEgisonTopLevel :: EgisonExpr -> [String] -> [ExpQ] -> ExpQ
- Language.Egison.Quote: parseQuote :: Parser (EgisonExpr, TypeSignature)
+ Language.Egison.Quote: parseQuote :: Parser (EgisonExpr, Type)
- Language.Egison.Quote: parseType :: Parser TypeSignature
+ Language.Egison.Quote: parseType :: Parser Type
- Language.Egison.Quote: readQuote :: String -> ThrowsError (EgisonExpr, TypeSignature)
+ Language.Egison.Quote: readQuote :: String -> ThrowsError (EgisonExpr, Type)
- Language.Egison.Quote: toHaskellExp :: EgisonExpr -> [String] -> TypeSignature -> ExpQ
+ Language.Egison.Quote: toHaskellExp :: EgisonExpr -> [String] -> Type -> ExpQ
Files
- Language/Egison/Quote.hs +114/−79
- egison-quote.cabal +2/−2
Language/Egison/Quote.hs view
@@ -15,7 +15,6 @@ {-# Language TemplateHaskell, QuasiQuotes, TypeSynonymInstances, FlexibleInstances, UndecidableInstances, ViewPatterns, OverlappingInstances, IncoherentInstances #-} module Language.Egison.Quote(egison,- TypeSignature, parseType, pickupAntiquote, parseAntiquote,@@ -36,11 +35,9 @@ import Language.Egison.Parser import Language.Egison.Variables -import Data.Either-import Data.Ratio-import Data.Maybe-import Data.List-+import Data.Either (either)+import Data.Ratio (numerator, denominator, (%))+import Data.IORef (newIORef) import Control.Monad.Error hiding (lift) import Control.Monad.Trans hiding (lift) import Control.Arrow@@ -95,7 +92,7 @@ quoteExp = \input -> let (antiquotes, input') = pickupAntiquote input (expr, typ) = extractValue . readQuote $ input'- in+ in do toHaskellExp expr antiquotes typ, quotePat = error "Not implemented pat-quote.", quoteType = error "Not implemented type-quote.",@@ -104,61 +101,79 @@ -- * Type --- | The type of type signature of egison expression-data TypeSignature = CharTS | StringTS | BoolTS | IntTS | IntegerTS | FloatTS | DoubleTS- | TupleTS [TypeSignature] | ListTS TypeSignature - | ArrowTS [TypeSignature] TypeSignature deriving (Show)+matchAppType :: Type -> Maybe ([Type], Type)+matchAppType t@(AppT (AppT ArrowT _) _) = Just . matchAppType' $ t+ where+ matchAppType' (AppT (AppT ArrowT arg) rest) = first (++[arg]) $ matchAppType' rest+ matchAppType' ret = ([], ret)+matchAppType _ = Nothing +matchTupleType :: Type -> Maybe [Type]+matchTupleType (AppT (TupleT _) ret) = return [ret]+matchTupleType (AppT rest element) = (++[element]) <$> matchTupleType rest+matchTupleType _ = Nothing++matchListType :: Type -> Maybe Type+matchListType t = case t of {AppT ListT typ -> return typ; _ -> Nothing}++matchConstType :: Type -> Maybe String+matchConstType t= case t of {ConT t -> Just . nameBase $ t; _ -> Nothing}+ -- Generate [ EgisonVal -> (corresponding Haskell Value) ] function from TypeSignature-converter :: TypeSignature -> ExpQ-converter CharTS = [| \(Char x) -> x |]-converter StringTS = [| \(String x) -> x |]-converter BoolTS = [| \(Bool x) -> x |]-converter IntTS = [| \(Number x) -> (fromIntegral x) :: Int |]-converter IntegerTS = [| \(Number x) -> x |]-converter DoubleTS = [| \(Float x) -> x |]-converter FloatTS = [| \(Float x) -> (realToFrac x) :: Float |]-converter (TupleTS ts) = do+converter :: Type -> ExpQ+converter (matchConstType -> Just "Char") = [| \(Char x) -> x |]+converter (matchConstType -> Just "String") = [| \(String x) -> x |]+converter (matchConstType -> Just "Bool") = [| \(Bool x) -> x |]+converter (matchConstType -> Just "Int") = [| \(Number x) -> (fromIntegral x) :: Int |]+converter (matchConstType -> Just "Integer") = [| \(Number x) -> x |]+converter (matchConstType -> Just "Double") = [| \(Float x) -> x |]+converter (matchConstType -> Just "Float") = [| \(Float x) -> (realToFrac x) :: Float |]+converter (matchTupleType -> Just ts) = do patvars <- replicateM (length ts) $ newName "x" lamE [conP 'Tuple [listP $ map varP patvars]] (foldl (\acc (x, t) -> appE acc (appE (converter t) (varE x))) (conE $ tupleDataName (length ts)) (zip patvars ts))-converter (ListTS t) = [| \(Collection vs) -> map $(converter t) vs |]-converter (ArrowTS _ _) = error "Invarid return type: t1 -> t2."---- TypeSignature -> (corresponding Haskell Type)-tsToType :: TypeSignature -> TypeQ-tsToType CharTS = [t| Char |]-tsToType StringTS = [t| String |]-tsToType BoolTS = [t| Bool |]-tsToType IntTS = [t| Int |]-tsToType IntegerTS = [t| Integer |]-tsToType DoubleTS = [t| Double |]-tsToType FloatTS = [t| Float |]-tsToType (TupleTS ts) = foldl appT (tupleT (length ts)) (map tsToType ts)-tsToType (ListTS t) = appT listT (tsToType t)-tsToType (ArrowTS t1 t2) = appT (foldl appT arrowT (map tsToType t1)) (tsToType t2)+converter (matchListType -> Just t) = [| \(Collection vs) -> map $(converter t) vs |]+converter (matchAppType -> Just (args, ret)) = [| \func@(Func _ _ env) -> $(wrap 'func 'env) |]+ where+ wrap (varE -> funcVal) (varE -> env) = do+ (funcName, (func, funcP)) <- (show &&& varE &&& varP) <$> newName "func"+ argsName <- mapM newName $ map (("x"++) . show) [1..length args]+ let (args, argsP) = (map varE &&& map varP) argsName+ (lamE argsP+ (appE (converter ret)+ (appE (varE 'unsafePerformIO)+ (doE $+ bindS funcP (appE (varE 'newIORef) (appE (conE 'Value) funcVal)) :+ noBindS [| runIOThrowsError $ defineVar $(env) (funcName, []) $(func) |] :+ makeBinding (map show argsName) args env +++ [noBindS [| runIOThrowsError (eval $(env) (ApplyExpr (VarExpr funcName []) (TupleExpr (map toEgisonExpr $(listE args))))) |]]))))+converter t = error $ "Invarid type: " ++ show t -- * Parser -- | Parser for TypeSignature-parseType :: Parser TypeSignature+parseType :: Parser Type parseType = do t1_ <- many (try $ lexeme parseType' <* lexeme (string "->")) t2 <- lexeme parseType' case t1_ of [] -> return t2- t1 -> return (ArrowTS t1 t2)+ t1 -> return $ foldr AppT t2 (map (AppT ArrowT) t1) -parseType' = (string "Char" >> return CharTS)- <|> (string "String" >> return StringTS)- <|> (string "Bool" >> return BoolTS)- <|> (string "Int" >> return IntTS)- <|> (string "Integer" >> return IntegerTS)- <|> (string "Float" >> return FloatTS)- <|> (string "Double" >> return DoubleTS)- <|> parens (do thd <- lexeme parseType'- ttl <- many (lexeme (char ',') >> lexeme parseType')- return $ if null ttl then thd else TupleTS (thd:ttl))- <|> brackets (ListTS <$> lexeme parseType')+parseType' :: Parser Type+parseType' = (string "Char" >> return (ConT ''Char))+ <|> (string "String" >> return (ConT ''String))+ <|> (string "Bool" >> return (ConT ''Bool))+ <|> (string "Int" >> return (ConT ''Int))+ <|> (string "Integer" >> return (ConT ''Integer))+ <|> (string "Float" >> return (ConT ''Float))+ <|> (string "Double" >> return (ConT ''Double))+ <|> (try $ parens $ do thd <- lexeme parseType'+ ttl <- many (lexeme (char ',') >> lexeme parseType')+ return $ if null ttl+ then thd+ else foldl AppT (TupleT (length $ thd:ttl)) (thd:ttl))+ <|> brackets (AppT ListT <$> lexeme parseType')+ <|> parens parseType -- | Pick up antiquoted variables and delete notation @#{~}@ -- @@ -180,7 +195,7 @@ <|> (eof >> return ([], "")) -- | Parser for egison-quote-parseQuote :: Parser (EgisonExpr, TypeSignature)+parseQuote :: Parser (EgisonExpr, Type) parseQuote = do spaces expr <- lexeme parseExpr@@ -189,7 +204,7 @@ return (expr, typ) -- | Read function for egison-quote-readQuote :: String -> ThrowsError (EgisonExpr, TypeSignature)+readQuote :: String -> ThrowsError (EgisonExpr, Type) readQuote = readOrThrow parseQuote instance Lift InnerExpr where@@ -215,9 +230,9 @@ (litE (integerL n)), (litE (integerL d))]))) lift (VarExpr x l) = appsE [conE 'VarExpr, lift x, lift l]- lift (MacroVarExpr x l) = appsE [conE 'MacroVarExpr, lift x, lift l]- lift (PatVarOmitExpr x) = appE (conE 'PatVarOmitExpr) (lift x)- lift (VarOmitExpr x) = appE (conE 'VarOmitExpr) (lift x)+ lift (MacroVarExpr x) = appsE [conE 'MacroVarExpr, lift x]+ lift (PatVarOmitExpr x l) = appsE [conE 'PatVarOmitExpr, lift x, lift l]+ lift (VarOmitExpr x l) = appsE [conE 'VarOmitExpr, lift x, lift l] lift (PatVarExpr x l) = appsE [conE 'PatVarExpr, lift x, lift l] lift WildCardExpr = conE 'WildCardExpr lift (ValuePatExpr x) = appE (conE 'ValuePatExpr) (lift x)@@ -249,15 +264,26 @@ -- * Construction Exp +-- | make do-binding+makeBinding :: [String] -- ^ variable names+ -> [ExpQ] -- ^ binding expressions+ -> ExpQ -- ^ environmental name+ -> [StmtQ]+makeBinding names exprs env = zipWith (\name expr -> noBindS [|runIOThrowsError $ defineVar $(env) (name, []) =<< (liftIO $ makeClosure $(env) (toEgisonExpr $(expr)))|]) names exprs++nameExprWithType :: String -> TypeQ -> ExpQ+nameExprWithType name typ = sigE (varE (mkName name)) typ+ -- | construct Exp from Egison-expression and type signature-toHaskellExp :: EgisonExpr -> [String] -> TypeSignature -> ExpQ-toHaskellExp (FuncExpr (TupleExpr args) expr) antiquotes (ArrowTS t1 t2) | length args == length t1 = do+toHaskellExp :: EgisonExpr -> [String] -> Type -> ExpQ+toHaskellExp (FuncExpr (TupleExpr args) expr) antiquotes (nArgsApp (length args) -> (t1, t2)) = do let (argsName, argsType) = unzip . concat $ zipWith argsExpand args t1- argsExpr = zipWith (\aname atype -> sigE (varE (mkName aname)) atype) argsName argsType- bindExprs envName = zipWith (\aname aexpr -> noBindS [|runIOThrowsError $ defineVar $(varE envName) (aname, []) =<< (liftIO $ makeClosure $(varE envName) (toEgisonExpr $(aexpr)))|]) argsName argsExpr+ argsExpr = zipWith nameExprWithType argsName argsType+ bindnames = antiquotes ++ argsName+ bindexprs = map (varE . mkName) antiquotes ++ argsExpr (lamE (map toHaskellArgsPat args)- (appE (converter t2) (evalEgisonTopLevel expr antiquotes bindExprs)))-toHaskellExp expr antiquotes typ = appE (converter typ) (evalEgisonTopLevel expr antiquotes (const []))+ (appE (converter t2) (evalEgisonTopLevel expr bindnames bindexprs)))+toHaskellExp expr antiquotes typ = appE (converter typ) (evalEgisonTopLevel expr antiquotes (map (varE . mkName) antiquotes)) childExpr :: EgisonExpr -> [EgisonExpr] childExpr (CharExpr _) = []@@ -266,9 +292,9 @@ childExpr (NumberExpr _) = [] childExpr (FloatExpr _) = [] childExpr (VarExpr _ cs) = cs-childExpr (MacroVarExpr _ cs) = cs-childExpr (PatVarOmitExpr c) = [c]-childExpr (VarOmitExpr c) = [c]+childExpr (MacroVarExpr _) = []+childExpr (PatVarOmitExpr _ cs) = cs+childExpr (VarOmitExpr _ cs) = cs childExpr (PatVarExpr _ cs) = cs childExpr WildCardExpr = [] childExpr (ValuePatExpr c) = [c]@@ -304,27 +330,36 @@ childExpr SomethingExpr = [] childExpr UndefinedExpr = [] -argsExpand :: EgisonExpr -> TypeSignature -> [(String, TypeQ)]-argsExpand (PatVarExpr a _) t = [(a, tsToType t)]-argsExpand (TupleExpr as) (TupleTS ts) = concat $ zipWith argsExpand as ts-argsExpand _ _ = error "Invarid type."+nArgsApp :: Int -> Type -> ([Type], Type)+nArgsApp 0 ret = ([], ret)+nArgsApp n (AppT (AppT ArrowT arg) rest) = first (arg:) $ nArgsApp (n-1) rest+nArgsApp _ _ = error "Invarid Args." +-- | Expand binding+--+-- > [a1 [a2 a3]] :: (Int, (Char, Char)) --> [(a1, Int), (a2, Char), (a3, Char)]+argsExpand :: EgisonExpr -> Type -> [(String, TypeQ)]+argsExpand (PatVarExpr a _) t = [(a, return t)]+argsExpand (TupleExpr as) (matchTupleType -> Just ts) | length as == length ts = concat $ zipWith argsExpand as ts+ | otherwise = error "Wrong number of args."+argsExpand e t = error $ "Invarid argument: \n" ++ show e ++ "\n" ++ show t++-- | Egison binding to Haskell binding+--+-- > [a1 [a2 a3]] --> (a1, (a2, a3)) toHaskellArgsPat :: EgisonExpr -> PatQ toHaskellArgsPat (PatVarExpr a _) = varP (mkName a) toHaskellArgsPat (TupleExpr as) = tupP $ map toHaskellArgsPat as -evalEgison :: EgisonExpr -> Env -> EgisonVal-evalEgison expr env = unsafePerformIO $ runIOThrowsError $ eval env expr--evalEgisonTopLevel :: EgisonExpr -> [String] -> (Name -> [StmtQ]) -> ExpQ-evalEgisonTopLevel expr vars binds = do- env <- newName "env"- let exprs = map (varE . mkName) vars+evalEgisonTopLevel :: EgisonExpr -- ^ evaluated expression+ -> [String] -- ^ variable names+ -> [ExpQ] -- ^ binding expressions+ -> ExpQ+evalEgisonTopLevel expr bindvars bindexprs = do+ (env, envP) <- (varE &&& varP) <$> newName "env" (appE (varE 'unsafePerformIO) (doE (- [(varP env) `bindS` (varE 'primitiveBindings),- noBindS (appE (varE 'loadLibraries) (varE env))] ++ - zipWith (\vname vexpr -> noBindS [|runIOThrowsError $ defineVar $(varE env) (vname, []) =<< (liftIO $ makeClosure $(varE env) (toEgisonExpr $(vexpr)))|]) vars exprs ++- binds env ++- [noBindS (appE (varE 'runIOThrowsError) (appsE [varE 'eval, varE env, [|expr|]]))]- )))+ envP `bindS` (varE 'primitiveBindings) : + noBindS (appE (varE 'loadLibraries) env) :+ makeBinding bindvars bindexprs env +++ [noBindS [| runIOThrowsError $ eval $(env) expr |] ])))
egison-quote.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version: 0.1.1+Version: 0.2 -- A short (one-line) description of the package. Synopsis: A quasi quotes for using Egison expression in Haskell code@@ -53,7 +53,7 @@ Exposed-modules: Language.Egison.Quote -- Packages needed in order to build this package.- Build-depends: base < 5, mtl >= 2.0, egison >= 2.4.0, parsec, template-haskell+ Build-depends: base < 5, mtl >= 2.0, egison >= 2.4.3, parsec, template-haskell -- Modules not exported by this package. -- Other-modules: