ログ日記

作業ログと日記とメモ

GHCJSのスタブを使うのは大変っぽい

昨日のghc-base-stubを使う方式だと上手くいかなかった。
GHCJSに再度トライ - ログ日記


例えばghcjs-domを使いたい場合、GHCJSだと ghcjs-dom, ghcjs-dom-jsffi を使うところが
GHC版だと ghcjs-base-stub, ghcjs-dom, ghcjs-dom-jsaddle, jsaddle-dom, jsaddle を使うことになる。

これで一旦はコンパイルが通るんだけども、GHCJS版とGHC版でDOMの型が違うっぽい。


GHCJS版
https://raw.githubusercontent.com/ghcjs/ghcjs-dom/master/ghcjs-dom-jsffi/src/GHCJS/DOM/Types.hs

type JSM = IO

-- | This is the same as 'JSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
type DOM = IO

-- | The 'MonadJSM' is to 'JSM' what 'MonadIO' is to 'IO'.
--   When using GHCJS it is 'MonadIO'.
type MonadJSM = MonadIO

-- | This is the same as 'MonadJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
type MonadDOM = MonadIO

-- | The 'liftJSM' is to 'JSM' what 'liftIO' is to 'IO'.
--   When using GHCJS it is 'liftIO'.
liftJSM :: MonadJSM m => JSM a -> m a
liftJSM = liftIO

-- | This is the same as 'liftJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
liftDOM :: MonadDOM m => DOM a -> m a
liftDOM = liftIO

こんな感じで普通のIOになっている。


ghcjs-dom-jsaddleでは

JSDOM.Types as GHCJS.DOM.Types

のようになっていて、その定義は

https://raw.githubusercontent.com/ghcjs/jsaddle-dom/master/src/JSDOM/Types.hs

-- | This is the same as 'JSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
type DOM = JSM
-- | This is the same as 'JSContextRef' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
type DOMContext = JSContextRef
-- | This is the same as 'MonadJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
type MonadDOM = MonadJSM

-- | This is the same as 'liftJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
liftDOM :: MonadDOM m => DOM a -> m a
liftDOM = liftJSM

-- | This is the same as 'askJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
askDOM :: MonadDOM m => m DOMContext
askDOM = askJSM

-- | This is the same as 'runJSM' except when using ghcjs-dom-webkit with GHC (instead of ghcjs-dom-jsaddle)
runDOM :: MonadIO m => DOM a -> DOMContext -> m a
runDOM = runJSM

全てJSMを使うようになっている。


JSMは
https://github.com/ghcjs/jsaddle/blob/master/jsaddle/src/Language/Javascript/JSaddle/Types.hs
ここで GHCJSの場合はIOにしているけれども、GHCの場合はIOと似ているが異なる型になるようだ。
GHCを使う場合には、JSMとIOは変換できないっぽい。



もしかすると、ghcjs-base-stubのように、ghcjs-dom-stubとかを作っていけば良いのかもしれないが、大量に型があって自分で作るのはつらい。
別の方法を考える。


ーーーー

ここまで書いて、ちょっとサンプルを作った。
github.com
type JSM = IO 版。

自動生成されたコードが何万行もあってつらい…。
正規表現置換で一気にいけるところは変更して、無理なところは手動でぽちぽちやった。
折角なので開発中にJSMをprintしたら分かりやすいメッセージを出すようなスタブが出来れば良かったんだけど、自動生成じゃないと無理そう。普通にjsaddleを使うかね…。
少ししか(と言っても数万行)書いてないのに既にコンパイル重くなってきたしね。



型だけ見るなら

{-# LANGUAGE CPP #-}
module FormSample where

import           Control.Monad
import           Control.Monad.IO.Class            (MonadIO (..))
import           Control.Monad.Trans.Class         (lift)
import           Control.Monad.Trans.Maybe         (MaybeT (..), runMaybeT)
import           GHCJS.DOM
import           GHCJS.DOM.Document
import           GHCJS.DOM.HTMLCollection
import           GHCJS.DOM.Types
import           Language.Javascript.JSaddle.Debug


formEl :: MaybeT JSM Element
formEl = do
  doc <- MaybeT currentDocument
  forms <- getForms doc
  form <- MaybeT $ namedItem forms "form"
  return form

someProcess = undefined

app :: JSM ()
app = do
  mform <- runMaybeT formEl
  case mform of
    Just a  -> someProcess a
    Nothing -> undefined
  return ()


#ifdef MIN_VERSION_ghcjs_dom_jsffi

runForm :: IO ()
runForm = app

#else


runForm :: IO ()
runForm =  runOnAll_ app

#endif

jsaddleのデバッグ用関数(?)runOnALLが使える。実行しても特に何も起こらない。