packages feed

haskelisp 0.1.0.1 → 0.1.0.2

raw patch · 7 files changed

+55/−139 lines, 7 filesdep −logging-effect

Dependencies removed: logging-effect

Files

haskelisp.cabal view
@@ -1,5 +1,5 @@ name: haskelisp-version: 0.1.0.1+version: 0.1.0.2 cabal-version: >=1.10 build-type: Simple license: GPL-3@@ -9,7 +9,29 @@ homepage: http://github.com/githubuser/haskelisp#readme synopsis: Write Emacs module in Haskell, using Emacs 25's Dynamic Module feature description:-    Please see README.md+    EXPERIMENTAL+    Write Emacs module in Haskell, using Emacs 25's Dynamic Module feature.+    .+    * Only tested with linux.+    * You need to build emacs with --with-modules configuration options+    * You need to specify some ghc-options+    .+    >+    -# LANGUAGE ForeignFunctionInterface,OverloadedStrings #-+    > module Main where+    >+    > import Emacs+    >+    > foreign export ccall "emacs_module_init" emacsModuleInit :: EmacsModule+    >+    > emacsModuleInit :: EmacsModule+    > emacsModuleInit = defmodule "sample-module" $ do+    >+    >   setVal "foo" (Symbol "bar")+    >+    >   defun "square" $ \i -> do+    >     message "haskell squre function called"+    >     return $ (i*i :: Int) category: Editor, Emacs author: Takenari Shinohara @@ -24,7 +46,6 @@         Emacs.Internal         Emacs.Symbol         Emacs.Core-        Emacs.Variable         Emacs.Function         Emacs.Command     build-depends:@@ -32,8 +53,7 @@         protolude <0.2,         containers <0.6,         mtl <2.3,-        text <1.3,-        logging-effect <1.1+        text <1.3     c-sources:         cbits/stab.c     default-language: Haskell2010
src/Emacs.hs view
@@ -1,13 +1,11 @@ module Emacs   ( module Emacs.Core   , module Emacs.Symbol-  , module Emacs.Variable   , module Emacs.Function   , module Emacs.Command   ) where  import Emacs.Core import Emacs.Symbol-import Emacs.Variable import Emacs.Function import Emacs.Command
src/Emacs/Core.hs view
@@ -1,10 +1,7 @@ {-# LANGUAGE ForeignFunctionInterface,OverloadedStrings,DataKinds,TypeFamilies,KindSignatures,FlexibleInstances,UndecidableInstances #-} {-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE KindSignatures #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE DataKinds #-}  module Emacs.Core (     module Emacs.Internal,@@ -33,7 +30,7 @@ import Emacs.Internal  -- emacsModuleInit に渡す関数-defmodule :: Text -> EmacsM a -> Ptr () -> IO CInt+defmodule :: Text -> EmacsM a -> EmacsModule defmodule name mod ert = do   env <- getEmacsEnvFromRT ert   errorHandle env $ do@@ -41,8 +38,6 @@     runEmacsM ctx $ mod >> funcall1 "provide" (Symbol name)   return 0 --- | Haskell -> EmacsValue への変換--- 利便性だけのためかな? class ToEmacsValue h where   toEv :: h -> EmacsM EmacsValue @@ -75,52 +70,25 @@     bv <- toEv b     mkCons av bv --- シンボルを渡す場所は多いので。ただ ToEmacsValue と関係持たせていは--- いけない。------ 通常は Text の引数でいいと思うんだけ(いちいち)文字列ではなく、シン--- ボルにするよと明示したいところでは利用するのがいいかな?後は関数か--- らのシンボルの返値を利用する場合とかかな(Text だと、一旦--- symbol-name で文字列表現を取り出す必要が出てくる)。------ ああ、やはりどうだろう。そもそもシンボルという概念がhaskellには必要--- ないか?objectではなく、eq で等価性が判定されるので文字列と同義にな--- るのかな?(ただ空文字列は駄目かな)。--- ESymbol でも動作させたい関数は ' バージョンを作るのがいいかな。--- class ToESymbol h where---   toESymbol  :: h -> EmacsM ESymbol---   toESymbol' :: h -> EmacsM EmacsValue---   toESymbol' = fmap (untag) . toESymbol--- instance ToESymbol Symbol where---   toESymbol (Symbol name) = mkESymbol name--- instance ToESymbol ESymbol where---   toESymbol = pure--- instance ToESymbol (EmacsM ESymbol) where---   toESymbol = id---- for internal usage.--- 関数名は ToESymbol ではなく、Text で受け取っているのは利便性のため。 funcall1 :: (ToEmacsValue a)          => Text -> a -> EmacsM EmacsValue funcall1 fname ev0 =   join $ funcall <$> intern fname-                   <*> sequence [toEv ev0]+                 <*> sequence [toEv ev0]  funcall2 :: (ToEmacsValue a, ToEmacsValue b)          => Text -> a -> b -> EmacsM EmacsValue funcall2 fname ev0 ev1 =   join $ funcall <$> intern fname-                   <*> sequence [toEv ev0, toEv ev1]+                 <*> sequence [toEv ev0, toEv ev1]  funcall3 :: (ToEmacsValue a, ToEmacsValue b, ToEmacsValue c)          => Text -> a -> b -> c -> EmacsM EmacsValue funcall3 fname ev0 ev1 ev2 =   join $ funcall <$> intern fname-                   <*> sequence [toEv ev0, toEv ev1, toEv ev2]+                 <*> sequence [toEv ev0, toEv ev1, toEv ev2]  --- | Haskell <- EmacsValue--- これは mkEFunction のために? class FromEmacsValue h where   fromEv :: EmacsValue -> EmacsM (Maybe h) @@ -131,7 +99,6 @@ instance FromEmacsValue EmacsValue where   fromEv = pure . Just --- hack -- 多相的な関数は駄目らしい(具体的な関数ならokらしい) class Callable a where     call :: a -> [EmacsValue] -> EmacsM (Either Text EmacsValue)@@ -166,9 +133,7 @@   call _ [] = pure $ Left "Too less arguments"   arity f = arity (f undefined) + 1 --- |--- 多層的な関数は怒られるはず。---+-- 多相的な関数は怒られるはず。 mkFunctionFromCallable :: Callable f => f -> EmacsM EmacsValue mkFunctionFromCallable f = do   let a = arity f
src/Emacs/Internal.hs view
@@ -1,9 +1,4 @@-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE DataKinds #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE TemplateHaskell #-} module Emacs.Internal (     module Emacs.Type,     initState,@@ -35,11 +30,6 @@     errorHandle     ) where -{--emacs-modue.h の関数。-型は EmacsValue しか扱わない。基本、このレベルの関数は使うべきではない。--}- import Prelude() import Protolude hiding (mkInteger) import Control.Exception (displayException)@@ -56,7 +46,6 @@ import GHC.Ptr import qualified GHC.Foreign as GHC import GHC.IO.Encoding.UTF8 (utf8)-import Control.Monad.Log  initState :: MonadIO m => m PState initState = do@@ -84,9 +73,8 @@ -- Logging here is not a good idea. When passing high order function, -- which could be invoked manytimes, its get quite slow. runEmacsM :: MonadIO m => Ctx -> EmacsM a -> m a-runEmacsM ctx action = do-  let logHandler t = pure ()-  liftIO $ runReaderT (runLoggingT action logHandler) ctx+runEmacsM ctx action =+  liftIO $ runReaderT action ctx  foreign import ccall _get_emacs_env_from_rt   :: Ptr ()@@ -96,8 +84,6 @@ getEmacsEnvFromRT =   _get_emacs_env_from_rt --- TODO: シンボル のキャッシュしないと毎回シンボルを取得するのは遅い気--- がする。 foreign import ccall _type_of   :: EmacsEnv   -> EmacsValue@@ -120,12 +106,6 @@   t <- typeOf ev   return $ t == ty --- | EmacsVAlue -> Haskell の変換------ ただし可能なのは限られている。例えば バッファとかは Haskell 側で対--- 応する型を持たないので EBuffer(もしくは EmacsValue)のままで扱う必要--- がある。- -- 引数が integer じゃない場合多分 signal が投げられる foreign import ccall _extract_integer   :: EmacsEnv@@ -145,7 +125,7 @@     then (Just <$> extractInteger v)     else return Nothing --- 使い方が今イチ曖昧だが、コード見たら分かりやすい。+-- emacs-module.c 参照 -- --  * Can throw signals(その場合 false が返る) --  * もし Buffer が null の場合、Length に文字列のutf8で格納する際の@@ -179,9 +159,9 @@             else pure ""       else pure "" --- | どうなんだ?--- eq は bool 返すのだが、haskell では CBool は用意していないので int にして返している。--- module_eq は珍しく MODULE_FUNCTION_BEGIN を使っていない。+-- eq は bool 返すのだが、haskell では CBool は用意していないので int+-- にして返している。module_eq は珍しく MODULE_FUNCTION_BEGIN を使って+-- いない。 foreign import ccall _eq   :: EmacsEnv   -> EmacsValue@@ -208,10 +188,7 @@ isNil :: EmacsValue -> EmacsM Bool isNil = (fmap . fmap) not isNotNil --- TODO: castFunPtrToPtr はまずいかな?inline-c 自体にFunPtrを作る機能--- が備わっている?$fun:(...) 何故か使えない。。 -- TODO: arity と doc は Arity と Doc 型にするべきかな。- foreign import ccall _make_function   :: EmacsEnv   -> CPtrdiff@@ -405,14 +382,6 @@  -- そもそも list という型は emacs側には存在しない。 -- listp という関数があるが、これは cons もしくは nil かどうかを判定している。------ 以下のナイーブな実装だと大量に emacs 側の関数呼び出しが必要になり、遅い。------ mkList :: [EmacsValue] -> EmacsM EmacsValue--- mkList evs = do---   nil <- mkNil---   foldrM mkCons nil evs- mkList :: [EmacsValue] -> EmacsM EmacsValue mkList evs = do   listQ <- intern "list"@@ -439,8 +408,6 @@   env <- getEnv   toEnum . fromIntegral <$> liftIO (_non_local_exit_check env) ------ Emacs に戻ったときに signal を投げる。 foreign import ccall _non_local_exit_signal   :: EmacsEnv   -> EmacsValue@@ -491,9 +458,6 @@     free a0'     free a1'     return (toEnum (fromIntegral fe), a0, a1)---- | Emacs の--- 呼び出しは symbol に限らないのか。関数の直接起動とか。  foreign import ccall _funcall   :: EmacsEnv
src/Emacs/Symbol.hs view
@@ -21,6 +21,21 @@  -- | Symbol has four slots? +setVal :: ToEmacsValue a => Text -> a -> EmacsM EmacsValue+setVal name val =+  funcall2 "set" (Symbol name) val++isBounded :: Text -> EmacsM Bool+isBounded name =+  isNotNil =<< funcall1 "boundp" (Symbol name)++getVal :: Text -> EmacsM (Maybe EmacsValue)+getVal name = do+  bounded <- isNotNil =<< funcall1 "boundp" (Symbol name)+  if bounded+    then Just <$> funcall1 "symbol-value" (Symbol name)+    else pure Nothing+ -- | Keyword Symbol  -- | シンボルは任意の属性を持つことができる。
src/Emacs/Type.hs view
@@ -1,8 +1,5 @@-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} module Emacs.Type where @@ -12,7 +9,6 @@ import GHC.Ptr import Foreign.C.Types import Foreign.StablePtr-import Control.Monad.Log import Control.Monad.Reader import Data.Data hiding(typeOf) @@ -27,8 +23,7 @@   }  type EmacsM =-  LoggingT Text (ReaderT Ctx IO)-+  ReaderT Ctx IO  -- | nil について --@@ -62,38 +57,21 @@ emacsTypes :: [EmacsType] emacsTypes = fromConstr <$> dataTypeConstrs (dataTypeOf ESymbol) --- Singlton Types テクニック--- 値と型を結び付けている--- 現在は tagAs のところでしか使っていないのでオーバーキルかな。。--- export しないほうがいいかも。internal だけに留めるかな?--- data SEmacsType (et :: EmacsType) where---     SESymbol  :: SEmacsType 'ESymbol---     SEInteger :: SEmacsType 'EInteger---     SECons    :: SEmacsType 'ECons---     SENil     :: SEmacsType 'ENil --- emacsTypeValue :: SEmacsType b -> EmacsType--- emacsTypeValue SESymbol = ESymbol--- emacsTypeValue SEInteger = EInteger-+type EmacsModule = Ptr () -> IO CInt  newtype EmacsEnv   = EmacsEnv (Ptr ())   deriving (Storable)+ newtype EmacsValue = EmacsValue (Ptr ())   deriving (Storable)+ newtype GlobalEmacsValue = GlobalEmacsValue (Ptr ())   deriving (Storable)  castGlobalToEmacsValue :: GlobalEmacsValue -> EmacsValue castGlobalToEmacsValue (GlobalEmacsValue p) =   EmacsValue p---- type ESymbol       = Tagged 'ESymbol EmacsValue--- type EInteger      = Tagged 'EInteger EmacsValue--- type EFunction     = Tagged 'EFunction EmacsValue--- type EString       = Tagged 'EString EmacsValue--- type ECons         = Tagged 'ECons EmacsValue--- type ENil          = Tagged 'ENil EmacsValue  -- | Emacs の値に対する Haskell の型 -- 数値や文字列は素直なんだけど、他
− src/Emacs/Variable.hs
@@ -1,24 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-module Emacs.Variable-  ( setVariable-  , variableValue-  , isVariableBounded-  ) where--import Emacs.Core-import Data.Text--setVariable :: ToEmacsValue a => Text -> a -> EmacsM EmacsValue-setVariable name val =-  funcall2 "set" (Symbol name) val--isVariableBounded :: Text -> EmacsM Bool-isVariableBounded name =-  isNotNil =<< funcall1 "boundp" (Symbol name)--variableValue :: Text -> EmacsM (Maybe EmacsValue)-variableValue name = do-  bounded <- isNotNil =<< funcall1 "boundp" (Symbol name)-  if bounded-    then Just <$> funcall1 "symbol-value" (Symbol name)-    else pure Nothing