forked from GitHub/gf-core
a light API in the Haskell binding for accessing the internal data structures
This commit is contained in:
@@ -28,10 +28,12 @@ data GuKind
|
|||||||
data GuType
|
data GuType
|
||||||
data GuString
|
data GuString
|
||||||
data GuStringBuf
|
data GuStringBuf
|
||||||
|
data GuMap
|
||||||
data GuMapItor
|
data GuMapItor
|
||||||
data GuOut
|
data GuOut
|
||||||
data GuSeq
|
data GuSeq
|
||||||
data GuPool
|
data GuPool
|
||||||
|
type GuVariant = Ptr ()
|
||||||
|
|
||||||
foreign import ccall fopen :: CString -> CString -> IO (Ptr ())
|
foreign import ccall fopen :: CString -> CString -> IO (Ptr ())
|
||||||
|
|
||||||
@@ -96,6 +98,19 @@ foreign import ccall unsafe "gu/utf8.h gu_utf8_encode"
|
|||||||
foreign import ccall unsafe "gu/seq.h gu_make_seq"
|
foreign import ccall unsafe "gu/seq.h gu_make_seq"
|
||||||
gu_make_seq :: CInt -> CInt -> Ptr GuPool -> IO (Ptr GuSeq)
|
gu_make_seq :: CInt -> CInt -> Ptr GuPool -> IO (Ptr GuSeq)
|
||||||
|
|
||||||
|
foreign import ccall unsafe "gu/map.h gu_map_find_default"
|
||||||
|
gu_map_find_default :: Ptr GuMap -> Ptr a -> IO (Ptr b)
|
||||||
|
|
||||||
|
foreign import ccall "gu/map.h gu_map_iter"
|
||||||
|
gu_map_iter :: Ptr GuMap -> Ptr GuMapItor -> Ptr GuExn -> IO ()
|
||||||
|
|
||||||
|
foreign import ccall unsafe "gu/variant.h gu_variant_tag"
|
||||||
|
gu_variant_tag :: GuVariant -> IO CInt
|
||||||
|
|
||||||
|
foreign import ccall unsafe "gu/variant.h gu_variant_data"
|
||||||
|
gu_variant_data :: GuVariant -> IO (Ptr a)
|
||||||
|
|
||||||
|
|
||||||
withGuPool :: (Ptr GuPool -> IO a) -> IO a
|
withGuPool :: (Ptr GuPool -> IO a) -> IO a
|
||||||
withGuPool f = bracket gu_new_pool gu_pool_free f
|
withGuPool f = bracket gu_new_pool gu_pool_free f
|
||||||
|
|
||||||
|
|||||||
217
src/runtime/haskell-bind/PGF2/Internal.hsc
Normal file
217
src/runtime/haskell-bind/PGF2/Internal.hsc
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
module PGF2.Internal(FId,isPredefFId,
|
||||||
|
FunId,Token,Production(..),PArg(..),Symbol(..),
|
||||||
|
concrTotalCats, concrCategories, concrProductions,
|
||||||
|
concrTotalFuns, concrFunction,
|
||||||
|
concrTotalSeqs, concrSequence) where
|
||||||
|
|
||||||
|
#include <pgf/data.h>
|
||||||
|
|
||||||
|
import PGF2
|
||||||
|
import PGF2.FFI
|
||||||
|
import System.IO.Unsafe(unsafePerformIO)
|
||||||
|
import Foreign
|
||||||
|
import Foreign.C
|
||||||
|
import Data.IORef
|
||||||
|
|
||||||
|
type Token = String
|
||||||
|
data Symbol
|
||||||
|
= SymCat {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex
|
||||||
|
| SymLit {-# UNPACK #-} !Int {-# UNPACK #-} !LIndex
|
||||||
|
| SymVar {-# UNPACK #-} !Int {-# UNPACK #-} !Int
|
||||||
|
| SymKS Token
|
||||||
|
| SymKP [Symbol] [([Symbol],[String])]
|
||||||
|
| SymBIND -- the special BIND token
|
||||||
|
| SymNE -- non exist
|
||||||
|
| SymSOFT_BIND -- the special SOFT_BIND token
|
||||||
|
| SymSOFT_SPACE -- the special SOFT_SPACE token
|
||||||
|
| SymCAPIT -- the special CAPIT token
|
||||||
|
| SymALL_CAPIT -- the special ALL_CAPIT token
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
data Production
|
||||||
|
= PApply {-# UNPACK #-} !FunId [PArg]
|
||||||
|
| PCoerce {-# UNPACK #-} !FId
|
||||||
|
deriving (Eq,Ord,Show)
|
||||||
|
data PArg = PArg [FId] {-# UNPACK #-} !FId deriving (Eq,Ord,Show)
|
||||||
|
type FunId = Int
|
||||||
|
type SeqId = Int
|
||||||
|
|
||||||
|
|
||||||
|
concrTotalCats :: Concr -> FId
|
||||||
|
concrTotalCats c = unsafePerformIO $ do
|
||||||
|
c_total_cats <- (#peek PgfConcr, total_cats) (concr c)
|
||||||
|
touchConcr c
|
||||||
|
return (fromIntegral (c_total_cats :: CInt))
|
||||||
|
|
||||||
|
concrCategories :: Concr -> [(CId,FId,FId,[String])]
|
||||||
|
concrCategories c =
|
||||||
|
unsafePerformIO $
|
||||||
|
withGuPool $ \tmpPl ->
|
||||||
|
allocaBytes (#size GuMapItor) $ \itor -> do
|
||||||
|
exn <- gu_new_exn tmpPl
|
||||||
|
ref <- newIORef []
|
||||||
|
fptr <- wrapMapItorCallback (getCategories ref)
|
||||||
|
(#poke GuMapItor, fn) itor fptr
|
||||||
|
c_cnccats <- (#peek PgfConcr, cnccats) (concr c)
|
||||||
|
gu_map_iter c_cnccats itor exn
|
||||||
|
touchConcr c
|
||||||
|
freeHaskellFunPtr fptr
|
||||||
|
cs <- readIORef ref
|
||||||
|
return (reverse cs)
|
||||||
|
where
|
||||||
|
getCategories ref itor key value exn = do
|
||||||
|
names <- readIORef ref
|
||||||
|
name <- peekUtf8CString (castPtr key)
|
||||||
|
c_cnccat <- peek (castPtr value)
|
||||||
|
c_cats <- (#peek PgfCncCat, cats) c_cnccat
|
||||||
|
c_len <- (#peek GuSeq, len) c_cats
|
||||||
|
first <- peek (c_cats `plusPtr` (#offset GuSeq, data)) >>= peekFId
|
||||||
|
last <- peek (c_cats `plusPtr` ((#offset GuSeq, data) + (fromIntegral (c_len-1::CInt))*(#size PgfCCat*))) >>= peekFId
|
||||||
|
c_n_lins <- (#peek PgfCncCat, n_lins) c_cnccat
|
||||||
|
arr <- peekArray (fromIntegral (c_n_lins :: CInt)) (c_cnccat `plusPtr` (#offset PgfCncCat, labels))
|
||||||
|
labels <- mapM peekUtf8CString arr
|
||||||
|
writeIORef ref ((name,first,last,labels) : names)
|
||||||
|
|
||||||
|
concrProductions :: Concr -> FId -> [Production]
|
||||||
|
concrProductions c fid = unsafePerformIO $ do
|
||||||
|
c_ccats <- (#peek PgfConcr, ccats) (concr c)
|
||||||
|
res <- alloca $ \pfid -> do
|
||||||
|
poke pfid (fromIntegral fid :: CInt)
|
||||||
|
gu_map_find_default c_ccats pfid >>= peek
|
||||||
|
if res == nullPtr
|
||||||
|
then do touchConcr c
|
||||||
|
return []
|
||||||
|
else do c_prods <- (#peek PgfCCat, prods) res
|
||||||
|
if c_prods == nullPtr
|
||||||
|
then do touchConcr c
|
||||||
|
return []
|
||||||
|
else do res <- peekSequence (deRef peekProduction) (#size GuVariant) c_prods
|
||||||
|
touchConcr c
|
||||||
|
return res
|
||||||
|
where
|
||||||
|
peekProduction p = do
|
||||||
|
tag <- gu_variant_tag p
|
||||||
|
dt <- gu_variant_data p
|
||||||
|
case tag of
|
||||||
|
(#const PGF_PRODUCTION_APPLY) -> do { c_cncfun <- (#peek PgfProductionApply, fun) dt ;
|
||||||
|
c_funid <- (#peek PgfCncFun, funid) c_cncfun ;
|
||||||
|
c_args <- (#peek PgfProductionApply, args) dt ;
|
||||||
|
pargs <- peekSequence peekPArg (#size PgfPArg) c_args ;
|
||||||
|
return (PApply (fromIntegral (c_funid :: CInt)) pargs) }
|
||||||
|
(#const PGF_PRODUCTION_COERCE)-> do { c_coerce <- (#peek PgfProductionCoerce, coerce) dt ;
|
||||||
|
fid <- peekFId c_coerce ;
|
||||||
|
return (PCoerce fid) }
|
||||||
|
_ -> error "Unknown production type in the grammar"
|
||||||
|
where
|
||||||
|
peekPArg ptr = do
|
||||||
|
c_hypos <- (#peek PgfPArg, hypos) ptr
|
||||||
|
hypos <- peekSequence (deRef peekFId) (#size int) c_hypos
|
||||||
|
c_ccat <- (#peek PgfPArg, ccat) ptr
|
||||||
|
fid <- peekFId c_ccat
|
||||||
|
return (PArg hypos fid)
|
||||||
|
|
||||||
|
peekFId c_ccat = do
|
||||||
|
c_fid <- (#peek PgfCCat, fid) c_ccat
|
||||||
|
return (fromIntegral (c_fid :: CInt))
|
||||||
|
|
||||||
|
concrTotalFuns :: Concr -> FunId
|
||||||
|
concrTotalFuns c = unsafePerformIO $ do
|
||||||
|
c_cncfuns <- (#peek PgfConcr, cncfuns) (concr c)
|
||||||
|
c_len <- (#peek GuSeq, len) c_cncfuns
|
||||||
|
touchConcr c
|
||||||
|
return (fromIntegral (c_len :: CInt))
|
||||||
|
|
||||||
|
concrFunction :: Concr -> FunId -> (Fun,[SeqId])
|
||||||
|
concrFunction c funid = unsafePerformIO $ do
|
||||||
|
c_cncfuns <- (#peek PgfConcr, cncfuns) (concr c)
|
||||||
|
c_cncfun <- peek (c_cncfuns `plusPtr` ((#offset GuSeq, data)+funid*(#size PgfCncFun*)))
|
||||||
|
c_absfun <- (#peek PgfCncFun, absfun) c_cncfun
|
||||||
|
c_name <- (#peek PgfAbsFun, name) c_absfun
|
||||||
|
name <- peekUtf8CString c_name
|
||||||
|
c_n_lins <- (#peek PgfCncFun, n_lins) c_cncfun
|
||||||
|
arr <- peekArray (fromIntegral (c_n_lins :: CInt)) (c_cncfun `plusPtr` (#offset PgfCncFun, lins))
|
||||||
|
seqs_seq <- (#peek PgfConcr, sequences) (concr c)
|
||||||
|
touchConcr c
|
||||||
|
let seqs = seqs_seq `plusPtr` (#offset GuSeq, data)
|
||||||
|
return (name, map (toSeqId seqs) arr)
|
||||||
|
where
|
||||||
|
toSeqId seqs seq = minusPtr seq seqs `div` (#size PgfSequence)
|
||||||
|
|
||||||
|
concrTotalSeqs :: Concr -> SeqId
|
||||||
|
concrTotalSeqs c = unsafePerformIO $ do
|
||||||
|
seq <- (#peek PgfConcr, sequences) (concr c)
|
||||||
|
c_len <- (#peek GuSeq, len) seq
|
||||||
|
touchConcr c
|
||||||
|
return (fromIntegral (c_len :: CInt))
|
||||||
|
|
||||||
|
concrSequence :: Concr -> SeqId -> [Symbol]
|
||||||
|
concrSequence c seqid = unsafePerformIO $ do
|
||||||
|
c_sequences <- (#peek PgfConcr, sequences) (concr c)
|
||||||
|
let c_sequence = c_sequences `plusPtr` ((#offset GuSeq, data)+seqid*(#size PgfSequence))
|
||||||
|
c_syms <- (#peek PgfSequence, syms) c_sequence
|
||||||
|
res <- peekSequence (deRef peekSymbol) (#size GuVariant) c_syms
|
||||||
|
touchConcr c
|
||||||
|
return res
|
||||||
|
where
|
||||||
|
peekSymbol p = do
|
||||||
|
tag <- gu_variant_tag p
|
||||||
|
dt <- gu_variant_data p
|
||||||
|
case tag of
|
||||||
|
(#const PGF_SYMBOL_CAT) -> peekSymbolIdx SymCat dt
|
||||||
|
(#const PGF_SYMBOL_LIT) -> peekSymbolIdx SymLit dt
|
||||||
|
(#const PGF_SYMBOL_VAR) -> peekSymbolIdx SymVar dt
|
||||||
|
(#const PGF_SYMBOL_KS) -> peekSymbolKS dt
|
||||||
|
(#const PGF_SYMBOL_KP) -> peekSymbolKP dt
|
||||||
|
(#const PGF_SYMBOL_BIND) -> return SymBIND
|
||||||
|
(#const PGF_SYMBOL_SOFT_BIND) -> return SymSOFT_BIND
|
||||||
|
(#const PGF_SYMBOL_NE) -> return SymNE
|
||||||
|
(#const PGF_SYMBOL_SOFT_SPACE) -> return SymSOFT_SPACE
|
||||||
|
(#const PGF_SYMBOL_CAPIT) -> return SymCAPIT
|
||||||
|
(#const PGF_SYMBOL_ALL_CAPIT) -> return SymALL_CAPIT
|
||||||
|
_ -> error "Unknown symbol type in the grammar"
|
||||||
|
|
||||||
|
peekSymbolIdx constr dt = do
|
||||||
|
c_d <- (#peek PgfSymbolIdx, d) dt
|
||||||
|
c_r <- (#peek PgfSymbolIdx, r) dt
|
||||||
|
return (constr (fromIntegral (c_d :: CInt)) (fromIntegral (c_r :: CInt)))
|
||||||
|
|
||||||
|
peekSymbolKS dt = do
|
||||||
|
token <- peekUtf8CString (dt `plusPtr` (#offset PgfSymbolKS, token))
|
||||||
|
return (SymKS token)
|
||||||
|
|
||||||
|
peekSymbolKP dt = do
|
||||||
|
c_default_form <- (#peek PgfSymbolKP, default_form) dt
|
||||||
|
default_form <- peekSequence (deRef peekSymbol) (#size GuVariant) c_default_form
|
||||||
|
c_n_forms <- (#peek PgfSymbolKP, n_forms) dt
|
||||||
|
forms <- peekForms (c_n_forms :: CInt) (dt `plusPtr` (#offset PgfSymbolKP, forms))
|
||||||
|
return (SymKP default_form forms)
|
||||||
|
|
||||||
|
peekForms 0 ptr = return []
|
||||||
|
peekForms len ptr = do
|
||||||
|
c_form <- (#peek PgfAlternative, form) ptr
|
||||||
|
form <- peekSequence (deRef peekSymbol) (#size GuVariant) c_form
|
||||||
|
c_prefixes <- (#peek PgfAlternative, prefixes) ptr
|
||||||
|
prefixes <- peekSequence (deRef peekUtf8CString) (#size GuString*) c_prefixes
|
||||||
|
forms <- peekForms (len-1) (ptr `plusPtr` (#size PgfAlternative))
|
||||||
|
return ((form,prefixes):forms)
|
||||||
|
|
||||||
|
peekSequence peekElem size ptr = do
|
||||||
|
c_len <- (#peek GuSeq, len) ptr
|
||||||
|
peekElems (c_len :: CInt) (ptr `plusPtr` (#offset GuSeq, data))
|
||||||
|
where
|
||||||
|
peekElems 0 ptr = return []
|
||||||
|
peekElems len ptr = do
|
||||||
|
e <- peekElem ptr
|
||||||
|
es <- peekElems (len-1) (ptr `plusPtr` size)
|
||||||
|
return (e:es)
|
||||||
|
|
||||||
|
deRef peekValue ptr = peek ptr >>= peekValue
|
||||||
|
|
||||||
|
fidString, fidInt, fidFloat, fidVar, fidStart :: FId
|
||||||
|
fidString = (-1)
|
||||||
|
fidInt = (-2)
|
||||||
|
fidFloat = (-3)
|
||||||
|
fidVar = (-4)
|
||||||
|
fidStart = (-5)
|
||||||
|
|
||||||
|
isPredefFId :: FId -> Bool
|
||||||
|
isPredefFId = (`elem` [fidString, fidInt, fidFloat, fidVar])
|
||||||
@@ -14,11 +14,11 @@ extra-source-files: README
|
|||||||
cabal-version: >=1.10
|
cabal-version: >=1.10
|
||||||
|
|
||||||
library
|
library
|
||||||
exposed-modules: PGF2, SG,
|
exposed-modules: PGF2, PGF2.Internal, SG,
|
||||||
-- backwards compatibility API:
|
-- backwards compatibility API:
|
||||||
PGF, PGF.Internal
|
PGF, PGF.Internal
|
||||||
other-modules: PGF2.FFI, PGF2.Expr, PGF2.Type, SG.FFI
|
other-modules: PGF2.FFI, PGF2.Expr, PGF2.Type, SG.FFI
|
||||||
build-depends: base >=4.3, bytestring >=0.9,
|
build-depends: base >=4.3,
|
||||||
containers, pretty
|
containers, pretty
|
||||||
-- hs-source-dirs:
|
-- hs-source-dirs:
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|||||||
Reference in New Issue
Block a user