Changeset 8566

Show
Ignore:
Timestamp:
01/03/06 23:03:30 (3 years ago)
Author:
gaal
Message:

* beginning of .yaml emitter. "string".yaml.say segfaults, but hey,

it's a start :)

Location:
src
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • src/Data/Yaml/Syck.hsc

    r7579 r8566  
    11{-# OPTIONS_GHC -fglasgow-exts -fvia-C #-} 
    22#include "../../syck/syck.h" 
     3#include "../../cbits/fpstring.h" 
    34 
    45module Data.Yaml.Syck ( 
    5     parseYaml, 
     6    parseYaml, emitYaml, 
    67    YamlNode(..), 
    78) where 
     
    910import Control.Exception (bracket) 
    1011import Data.IORef 
     12import Data.Word                (Word8) 
     13import qualified Data.FastPackedString as P 
    1114import Foreign.Ptr 
    1215import Foreign.StablePtr 
     16import Foreign.ForeignPtr 
    1317import Foreign.C.Types 
    1418import Foreign.C.String 
     
    1721import Foreign.Storable 
    1822 
     23import Debug.Trace 
     24import Control.Monad.Trans 
     25 
    1926data YamlNode 
    2027    = YamlMap [(YamlNode, YamlNode)] 
    2128    | YamlSeq [YamlNode] 
    2229    | YamlStr String 
     30    | YamlNil 
    2331    deriving (Show, Ord, Eq) 
    2432 
     
    2937type SyckErrorHandler = SyckParser -> CString -> IO () 
    3038type SyckNodePtr = Ptr CString 
    31 data SyckKind = SyckMap | SyckSeq | SyckStr 
     39type FSPtr = Ptr CString 
     40type SyckEmitter = Ptr ()   
     41type SyckEmitterHandler = SyckEmitter -> Ptr () -> IO () 
     42type SyckOutputHandler = SyckEmitter -> CString -> CLong -> IO () 
     43data SyckKind = SyckMap | SyckSeq | SyckStr | SyckNil 
    3244    deriving (Show, Ord, Eq, Enum) 
     45 
     46-- the extra comma here is not a bug 
     47#enum CInt, , scalar_none, scalar_1quote, scalar_2quote, scalar_fold, scalar_literal, scalar_plain 
     48 
     49#def typedef struct _EmitterExtras { char * ps; int l; } EmitterExtras; 
     50type EmitterExtras = Ptr () 
     51 
     52emitYaml :: YamlNode -> IO (Either String String) 
     53emitYaml node = do 
     54    alloca $ \(emitterExtras :: Ptr EmitterExtras) -> do 
     55        bracket syck_new_emitter syck_free_emitter $ \emitter -> do 
     56            -- set up output port 
     57            let out = P.empty 
     58                (outps, _, l) = P.toForeignPtr out 
     59            outpsF <- freezeFS outps 
     60            #{poke EmitterExtras, ps}  emitterExtras outpsF 
     61            #{poke EmitterExtras, l}   emitterExtras l 
     62            #{poke SyckEmitter, bonus} emitter       emitterExtras 
     63            syck_output_handler emitter =<< mkOutputCallback outputCallback 
     64            syck_emitter_handler emitter =<< mkEmitterCallback emitterCallback 
     65            nodePtr <- freezeNode node 
     66            let nodePtr' = fromIntegral $ nodePtr `minusPtr` nullPtr 
     67            trace ("node: " ++ (show node) ++ " nodePtr': " ++ (show nodePtr')) $ return () 
     68            syck_emit emitter nodePtr' 
     69            syck_emitter_flush emitter 0 
     70            return . Right $ P.unpack out -- TODO: handle Left 
     71 
     72outputCallback :: SyckEmitter -> CString -> CLong -> IO () 
     73outputCallback emitter buf len = do 
     74    bonus <- #{peek SyckEmitter, bonus} emitter 
     75    fp    <- readFS =<< #{peek EmitterExtras, ps}  bonus 
     76    l     <- #{peek EmitterExtras, l}   bonus 
     77    let fps = P.fromForeignPtr fp l 
     78    let new = P.packCStringLen (buf, fromIntegral len) 
     79    let (catPS, _, catL) = P.toForeignPtr $ P.append fps new 
     80    catPSF <- freezeFS catPS 
     81    #{poke EmitterExtras, ps} bonus catPSF 
     82    #{poke EmitterExtras, l}  bonus catL 
     83    return () 
     84 
     85freezeFS :: ForeignPtr Word8 -> IO FSPtr 
     86freezeFS ps = do 
     87    ptr     <- newStablePtr ps 
     88    new (castPtr $ castStablePtrToPtr ptr) 
     89 
     90readFS :: FSPtr -> IO (ForeignPtr Word8) 
     91readFS fs = do 
     92    ptr     <- peek . castPtr =<< peek fs 
     93    deRefStablePtr (castPtrToStablePtr ptr) 
     94 
     95emitterCallback :: SyckEmitter -> Ptr () -> IO () 
     96emitterCallback e vp = do  
     97    node <- thawNode vp 
     98    case node of 
     99        (YamlStr str) -> do 
     100            -- return syck_emit_scalar(e, "string", scalar_none, 0, 0, 0, SvPVX(sv), SvCUR(sv)); 
     101            withCString "string" $ \string_literal ->        
     102                withCString str $ \cs ->        
     103                    syck_emit_scalar e string_literal scalarNone 0 0 0 cs (toEnum $ length str) 
    33104 
    34105parseYaml :: String -> IO (Either String (Maybe YamlNode)) 
     
    69140        ] 
    70141 
    71 freezeNode :: YamlNode -> IO SyckNodePtr 
     142--freezeNode :: YamlNode -> IO SyckNodePtr 
    72143freezeNode node = do 
    73144    ptr     <- newStablePtr node 
    74145    new (castPtr $ castStablePtrToPtr ptr) 
     146 
     147thawNode :: Ptr () -> IO YamlNode 
     148thawNode nodePtr = do 
     149    trace ("thawNode: nodePtr=" ++ show nodePtr) $ return () 
     150    --let ptr = castPtr nodePtr 
     151    --trace ("thawNode: ptr=" ++ show ptr) $ return () 
     152    -- deRefStablePtr (castPtrToStablePtr ptr) 
     153    rv <- deRefStablePtr (castPtrToStablePtr nodePtr) 
     154    rv' <- rv 
     155    trace ("thawNode: rv=" ++ show rv') $ return () 
     156    rv 
     157     
    75158 
    76159readNode :: SyckParser -> SYMID -> IO YamlNode 
     
    115198    mkErrorCallback :: SyckErrorHandler -> IO (FunPtr SyckErrorHandler) 
    116199 
     200foreign import ccall "wrapper" 
     201    mkOutputCallback :: SyckOutputHandler -> IO (FunPtr SyckOutputHandler) 
     202 
     203foreign import ccall "wrapper" 
     204    mkEmitterCallback :: SyckEmitterHandler -> IO (FunPtr SyckEmitterHandler) 
     205 
    117206foreign import ccall 
    118207    syck_new_parser :: IO SyckParser 
     
    153242foreign import ccall 
    154243    syck_map_read :: SyckNode -> CInt -> CLong -> IO SYMID 
     244 
     245foreign import ccall 
     246    syck_new_emitter :: IO SyckEmitter 
     247 
     248foreign import ccall 
     249    syck_free_emitter :: SyckEmitter -> IO () 
     250 
     251foreign import ccall 
     252    syck_emitter_handler :: SyckEmitter -> FunPtr SyckEmitterHandler -> IO () 
     253 
     254foreign import ccall 
     255    syck_output_handler :: SyckEmitter -> FunPtr SyckOutputHandler -> IO () 
     256 
     257foreign import ccall 
     258    syck_emit :: SyckEmitter -> CLong -> IO () 
     259 
     260foreign import ccall 
     261    syck_emitter_flush :: SyckEmitter -> CLong -> IO () 
     262 
     263foreign import ccall 
     264    syck_emit_scalar :: SyckEmitter -> CString -> CInt -> CInt -> CInt -> CInt -> CString -> CInt -> IO () 
     265 
  • src/Pugs/Prim.hs

    r8518 r8566  
    223223op1 "none" = op1Cast opJuncNone 
    224224op1 "perl" = fmap VStr . prettyVal 0 
     225op1 "yaml" = dumpYaml 
    225226op1 "require_haskell" = \v -> do 
    226227    name    <- fromVal v 
     
    15591560\\n   Any       pre     Pugs::Internals::eval_haskell unsafe (Str)\ 
    15601561\\n   Any       pre     Pugs::Internals::eval_yaml    safe   (Str)\ 
     1562\\n   Any       pre     yaml    safe   (Any)\ 
    15611563\\n   Any       pre     require unsafe (?Str=$_)\ 
    15621564\\n   Any       pre     use     unsafe (?Str=$_)\ 
  • src/Pugs/Prim/Yaml.hs

    r7826 r8566  
    33 
    44module Pugs.Prim.Yaml ( 
    5   evalYaml 
     5  evalYaml, dumpYaml 
    66) where 
    77import Pugs.Internals 
     
    3434    hv      <- liftSTM $ (newTVar (Map.fromList vals) :: STM IHash) 
    3535    return $ VRef (hashRef hv) 
     36 
     37dumpYaml :: Val -> Eval Val 
     38dumpYaml v = do 
     39    obj  <- toYaml =<< fromVal v 
     40    rv   <- liftIO (emitYaml obj) 
     41    case rv of 
     42        Left err  -> fail $ "YAML Emit Error: " ++ err 
     43        Right str -> return $ VStr str 
     44 
     45toYaml :: Val -> Eval YamlNode 
     46toYaml VUndef = return YamlNil 
     47toYaml (VStr str) = return $ YamlStr (encodeUTF8 str) 
     48toYaml (VList nodes) = do 
     49    fmap YamlSeq $ mapM toYaml nodes 
     50--toYaml (VHash hash) = do 
     51--    fmap YamlMap $ Map.toList hash 
     52 
     53 
     54