@@ -33,243 +33,244 @@ StackValue instances for pandoc types.
3333module Text.Pandoc.Lua.StackInstances () where
3434
3535import Control.Applicative ((<|>))
36−import Scripting.Lua (LTYPE (..), LuaState, StackValue (..), ltype, newtable,
37− objlen)
36+import Foreign.Lua (Lua, Type (..), FromLuaStack (peek), ToLuaStack (push),
37+ StackIndex, peekEither, throwLuaError)
38+import Foreign.Lua.Api (getfield, ltype, newtable, pop, rawlen)
3839import Text.Pandoc.Definition
3940import Text.Pandoc.Lua.SharedInstances ()
4041import Text.Pandoc.Lua.Util (addValue, getTable, pushViaConstructor)
4142import Text.Pandoc.Shared (safeRead)
4243
43−instance StackValue Pandoc where
44− push lua (Pandoc meta blocks) = do
45− newtable lua
46− addValue lua "blocks" blocks
47− addValue lua "meta" meta
48− peek lua idx = do
49− blocks <- getTable lua idx "blocks"
50− meta <- getTable lua idx "meta"
51− return $ Pandoc <$> meta <*> blocks
52− valuetype _ = TTABLE
53−
54−instance StackValue Meta where
55− push lua (Meta mmap) = push lua mmap
56− peek lua idx = fmap Meta <$> peek lua idx
57− valuetype _ = TTABLE
58−
59−instance StackValue MetaValue where
44+instance ToLuaStack Pandoc where
45+ push (Pandoc meta blocks) = do
46+ newtable
47+ addValue "blocks" blocks
48+ addValue "meta" meta
49+instance FromLuaStack Pandoc where
50+ peek idx = do
51+ blocks <- getTable idx "blocks"
52+ meta <- getTable idx "meta"
53+ return $ Pandoc meta blocks
54+
55+instance ToLuaStack Meta where
56+ push (Meta mmap) = push mmap
57+instance FromLuaStack Meta where
58+ peek idx = Meta <$> peek idx
59+
60+instance ToLuaStack MetaValue where
6061 push = pushMetaValue
62+instance FromLuaStack MetaValue where
6163 peek = peekMetaValue
62− valuetype = \case
63− MetaBlocks _ -> TTABLE
64− MetaBool _ -> TBOOLEAN
65− MetaInlines _ -> TTABLE
66− MetaList _ -> TTABLE
67− MetaMap _ -> TTABLE
68− MetaString _ -> TSTRING
69−
70−instance StackValue Block where
64+
65+instance ToLuaStack Block where
7166 push = pushBlock
67+
68+instance FromLuaStack Block where
7269 peek = peekBlock
73− valuetype _ = TTABLE
7470
75−instance StackValue Inline where
71+-- Inline
72+instance ToLuaStack Inline where
7673 push = pushInline
74+
75+instance FromLuaStack Inline where
7776 peek = peekInline
78− valuetype _ = TTABLE
79−
80−instance StackValue Citation where
81− push lua (Citation cid prefix suffix mode noteNum hash) =
82− pushViaConstructor lua "Citation" cid mode prefix suffix noteNum hash
83− peek lua idx = do
84− id' <- getTable lua idx "citationId"
85− prefix <- getTable lua idx "citationPrefix"
86− suffix <- getTable lua idx "citationSuffix"
87− mode <- getTable lua idx "citationMode"
88− num <- getTable lua idx "citationNoteNum"
89− hash <- getTable lua idx "citationHash"
90− return $ Citation <$> id' <*> prefix <*> suffix <*> mode <*> num <*> hash
91− valuetype _ = TTABLE
92−
93−instance StackValue Alignment where
94− push lua = push lua . show
95− peek lua idx = (>>= safeRead) <$> peek lua idx
96− valuetype _ = TSTRING
97−
98−instance StackValue CitationMode where
99− push lua = push lua . show
100− peek lua idx = (>>= safeRead) <$> peek lua idx
101− valuetype _ = TSTRING
102−
103−instance StackValue Format where
104− push lua (Format f) = push lua f
105− peek lua idx = fmap Format <$> peek lua idx
106− valuetype _ = TSTRING
107−
108−instance StackValue ListNumberDelim where
109− push lua = push lua . show
110− peek lua idx = (>>= safeRead) <$> peek lua idx
111− valuetype _ = TSTRING
112−
113−instance StackValue ListNumberStyle where
114− push lua = push lua . show
115− peek lua idx = (>>= safeRead) <$> peek lua idx
116− valuetype _ = TSTRING
117−
118−instance StackValue MathType where
119− push lua = push lua . show
120− peek lua idx = (>>= safeRead) <$> peek lua idx
121− valuetype _ = TSTRING
122−
123−instance StackValue QuoteType where
124− push lua = push lua . show
125− peek lua idx = (>>= safeRead) <$> peek lua idx
126− valuetype _ = TSTRING
77+
78+-- Citation
79+instance ToLuaStack Citation where
80+ push (Citation cid prefix suffix mode noteNum hash) =
81+ pushViaConstructor "Citation" cid mode prefix suffix noteNum hash
82+
83+instance FromLuaStack Citation where
84+ peek idx = do
85+ id' <- getTable idx "citationId"
86+ prefix <- getTable idx "citationPrefix"
87+ suffix <- getTable idx "citationSuffix"
88+ mode <- getTable idx "citationMode"
89+ num <- getTable idx "citationNoteNum"
90+ hash <- getTable idx "citationHash"
91+ return $ Citation id' prefix suffix mode num hash
92+
93+instance ToLuaStack Alignment where
94+ push = push . show
95+instance FromLuaStack Alignment where
96+ peek idx = safeRead' =<< peek idx
97+
98+instance ToLuaStack CitationMode where
99+ push = push . show
100+instance FromLuaStack CitationMode where
101+ peek idx = safeRead' =<< peek idx
102+
103+instance ToLuaStack Format where
104+ push (Format f) = push f
105+instance FromLuaStack Format where
106+ peek idx = Format <$> peek idx
107+
108+instance ToLuaStack ListNumberDelim where
109+ push = push . show
110+instance FromLuaStack ListNumberDelim where
111+ peek idx = safeRead' =<< peek idx
112+
113+instance ToLuaStack ListNumberStyle where
114+ push = push . show
115+instance FromLuaStack ListNumberStyle where
116+ peek idx = safeRead' =<< peek idx
117+
118+instance ToLuaStack MathType where
119+ push = push . show
120+instance FromLuaStack MathType where
121+ peek idx = safeRead' =<< peek idx
122+
123+instance ToLuaStack QuoteType where
124+ push = push . show
125+instance FromLuaStack QuoteType where
126+ peek idx = safeRead' =<< peek idx
127+
128+safeRead' :: Read a => String -> Lua a
129+safeRead' s = case safeRead s of
130+ Nothing -> throwLuaError ("Could not read: " ++ s)
131+ Just x -> return x
127132
128133-- | Push an meta value element to the top of the lua stack.
129−pushMetaValue :: LuaState -> MetaValue -> IO ()
130−pushMetaValue lua = \case
131− MetaBlocks blcks -> pushViaConstructor lua "MetaBlocks" blcks
132− MetaBool bool -> push lua bool
133− MetaInlines inlns -> pushViaConstructor lua "MetaInlines" inlns
134− MetaList metalist -> pushViaConstructor lua "MetaList" metalist
135− MetaMap metamap -> pushViaConstructor lua "MetaMap" metamap
136− MetaString str -> push lua str
134+pushMetaValue :: MetaValue -> Lua ()
135+pushMetaValue = \case
136+ MetaBlocks blcks -> pushViaConstructor "MetaBlocks" blcks
137+ MetaBool bool -> push bool
138+ MetaInlines inlns -> pushViaConstructor "MetaInlines" inlns
139+ MetaList metalist -> pushViaConstructor "MetaList" metalist
140+ MetaMap metamap -> pushViaConstructor "MetaMap" metamap
141+ MetaString str -> push str
137142
138143-- | Interpret the value at the given stack index as meta value.
139−peekMetaValue :: LuaState -> Int -> IO (Maybe MetaValue)
140−peekMetaValue lua idx = do
144+peekMetaValue :: StackIndex -> Lua MetaValue
145+peekMetaValue idx = do
141146 -- Get the contents of an AST element.
142− let elementContent :: StackValue a => IO (Maybe a)
143− elementContent = peek lua idx
144− luatype <- ltype lua idx
147+ let elementContent :: FromLuaStack a => Lua a
148+ elementContent = peek idx
149+ luatype <- ltype idx
145150 case luatype of
146− TBOOLEAN -> fmap MetaBool <$> peek lua idx
147− TSTRING -> fmap MetaString <$> peek lua idx
148− TTABLE -> do
149− tag <- getTable lua idx "t"
151+ TypeBoolean -> MetaBool <$> peek idx
152+ TypeString -> MetaString <$> peek idx
153+ TypeTable -> do
154+ tag <- getfield idx "t" *> peekEither (-1) <* pop 1
150155 case tag of
151− Just "MetaBlocks" -> fmap MetaBlocks <$> elementContent
152− Just "MetaBool" -> fmap MetaBool <$> elementContent
153− Just "MetaMap" -> fmap MetaMap <$> elementContent
154− Just "MetaInlines" -> fmap MetaInlines <$> elementContent
155− Just "MetaList" -> fmap MetaList <$> elementContent
156− Just "MetaString" -> fmap MetaString <$> elementContent
157− Nothing -> do
156+ Right "MetaBlocks" -> MetaBlocks <$> elementContent
157+ Right "MetaBool" -> MetaBool <$> elementContent
158+ Right "MetaMap" -> MetaMap <$> elementContent
159+ Right "MetaInlines" -> MetaInlines <$> elementContent
160+ Right "MetaList" -> MetaList <$> elementContent
161+ Right "MetaString" -> MetaString <$> elementContent
162+ Right t -> throwLuaError ("Unknown meta tag: " ++ t)
163+ Left _ -> do
158164 -- no meta value tag given, try to guess.
159− len <- objlen lua idx
165+ len <- rawlen idx
160166 if len <= 0
161− then fmap MetaMap <$> peek lua idx
162− else (fmap MetaInlines <$> peek lua idx)
163− <|> (fmap MetaBlocks <$> peek lua idx)
164− <|> (fmap MetaList <$> peek lua idx)
165− _ -> return Nothing
166− _ -> return Nothing
167+ then MetaMap <$> peek idx
168+ else (MetaInlines <$> peek idx)
169+ <|> (MetaBlocks <$> peek idx)
170+ <|> (MetaList <$> peek idx)
171+ _ -> throwLuaError ("could not get meta value")
167172
168173-- | Push an block element to the top of the lua stack.
169−pushBlock :: LuaState -> Block -> IO ()
170−pushBlock lua = \case
171− BlockQuote blcks -> pushViaConstructor lua "BlockQuote" blcks
172− BulletList items -> pushViaConstructor lua "BulletList" items
173− CodeBlock attr code -> pushViaConstructor lua "CodeBlock" code (LuaAttr attr)
174− DefinitionList items -> pushViaConstructor lua "DefinitionList" items
175− Div attr blcks -> pushViaConstructor lua "Div" blcks (LuaAttr attr)
176− Header lvl attr inlns -> pushViaConstructor lua "Header" lvl inlns (LuaAttr attr)
177− HorizontalRule -> pushViaConstructor lua "HorizontalRule"
178− LineBlock blcks -> pushViaConstructor lua "LineBlock" blcks
179− OrderedList lstAttr list -> pushViaConstructor lua "OrderedList" list lstAttr
180− Null -> pushViaConstructor lua "Null"
181− Para blcks -> pushViaConstructor lua "Para" blcks
182− Plain blcks -> pushViaConstructor lua "Plain" blcks
183− RawBlock f cs -> pushViaConstructor lua "RawBlock" f cs
174+pushBlock :: Block -> Lua ()
175+pushBlock = \case
176+ BlockQuote blcks -> pushViaConstructor "BlockQuote" blcks
177+ BulletList items -> pushViaConstructor "BulletList" items
178+ CodeBlock attr code -> pushViaConstructor "CodeBlock" code (LuaAttr attr)
179+ DefinitionList items -> pushViaConstructor "DefinitionList" items
180+ Div attr blcks -> pushViaConstructor "Div" blcks (LuaAttr attr)
181+ Header lvl attr inlns -> pushViaConstructor "Header" lvl inlns (LuaAttr attr)
182+ HorizontalRule -> pushViaConstructor "HorizontalRule"
183+ LineBlock blcks -> pushViaConstructor "LineBlock" blcks
184+ OrderedList lstAttr list -> pushViaConstructor "OrderedList" list lstAttr
185+ Null -> pushViaConstructor "Null"
186+ Para blcks -> pushViaConstructor "Para" blcks
187+ Plain blcks -> pushViaConstructor "Plain" blcks
188+ RawBlock f cs -> pushViaConstructor "RawBlock" f cs
184189 Table capt aligns widths headers rows ->
185− pushViaConstructor lua "Table" capt aligns widths headers rows
190+ pushViaConstructor "Table" capt aligns widths headers rows
186191
187192-- | Return the value at the given index as block if possible.
188−peekBlock :: LuaState -> Int -> IO (Maybe Block)
189−peekBlock lua idx = do
190− tag <- getTable lua idx "t"
193+peekBlock :: StackIndex -> Lua Block
194+peekBlock idx = do
195+ tag <- getTable idx "t"
191196 case tag of
192− Nothing -> return Nothing
193− Just t -> case t of
194− "BlockQuote" -> fmap BlockQuote <$> elementContent
195− "BulletList" -> fmap BulletList <$> elementContent
196− "CodeBlock" -> fmap (withAttr CodeBlock) <$> elementContent
197− "DefinitionList" -> fmap DefinitionList <$> elementContent
198− "Div" -> fmap (withAttr Div) <$> elementContent
199− "Header" -> fmap (\(lvl, LuaAttr attr, lst) -> Header lvl attr lst)
197+ "BlockQuote" -> BlockQuote <$> elementContent
198+ "BulletList" -> BulletList <$> elementContent
199+ "CodeBlock" -> (withAttr CodeBlock) <$> elementContent
200+ "DefinitionList" -> DefinitionList <$> elementContent
201+ "Div" -> (withAttr Div) <$> elementContent
202+ "Header" -> (\(lvl, LuaAttr attr, lst) -> Header lvl attr lst)
200203 <$> elementContent
201− "HorizontalRule" -> return (Just HorizontalRule)
202− "LineBlock" -> fmap LineBlock <$> elementContent
203− "OrderedList" -> fmap (uncurry OrderedList) <$> elementContent
204− "Null" -> return (Just Null)
205− "Para" -> fmap Para <$> elementContent
206− "Plain" -> fmap Plain <$> elementContent
207− "RawBlock" -> fmap (uncurry RawBlock) <$> elementContent
208− "Table" -> fmap (\(capt, aligns, widths, headers, body) ->
204+ "HorizontalRule" -> return HorizontalRule
205+ "LineBlock" -> LineBlock <$> elementContent
206+ "OrderedList" -> (uncurry OrderedList) <$> elementContent
207+ "Null" -> return Null
208+ "Para" -> Para <$> elementContent
209+ "Plain" -> Plain <$> elementContent
210+ "RawBlock" -> (uncurry RawBlock) <$> elementContent
211+ "Table" -> (\(capt, aligns, widths, headers, body) ->
209212 Table capt aligns widths headers body)
210213 <$> elementContent
211− _ -> return Nothing
214+ _ -> throwLuaError ("Unknown block type: " ++ tag)
212215 where
213216 -- Get the contents of an AST element.
214− elementContent :: StackValue a => IO (Maybe a)
215− elementContent = getTable lua idx "c"
217+ elementContent :: FromLuaStack a => Lua a
218+ elementContent = getTable idx "c"
216219
217220-- | Push an inline element to the top of the lua stack.
218−pushInline :: LuaState -> Inline -> IO ()
219−pushInline lua = \case
220− Cite citations lst -> pushViaConstructor lua "Cite" lst citations
221− Code attr lst -> pushViaConstructor lua "Code" lst (LuaAttr attr)
222− Emph inlns -> pushViaConstructor lua "Emph" inlns
223− Image attr alt (src,tit) -> pushViaConstructor lua "Image" alt src tit (LuaAttr attr)
224− LineBreak -> pushViaConstructor lua "LineBreak"
225− Link attr lst (src,tit) -> pushViaConstructor lua "Link" lst src tit (LuaAttr attr)
226− Note blcks -> pushViaConstructor lua "Note" blcks
227− Math mty str -> pushViaConstructor lua "Math" mty str
228− Quoted qt inlns -> pushViaConstructor lua "Quoted" qt inlns
229− RawInline f cs -> pushViaConstructor lua "RawInline" f cs
230− SmallCaps inlns -> pushViaConstructor lua "SmallCaps" inlns
231− SoftBreak -> pushViaConstructor lua "SoftBreak"
232− Space -> pushViaConstructor lua "Space"
233− Span attr inlns -> pushViaConstructor lua "Span" inlns (LuaAttr attr)
234− Str str -> pushViaConstructor lua "Str" str
235− Strikeout inlns -> pushViaConstructor lua "Strikeout" inlns
236− Strong inlns -> pushViaConstructor lua "Strong" inlns
237− Subscript inlns -> pushViaConstructor lua "Subscript" inlns
238− Superscript inlns -> pushViaConstructor lua "Superscript" inlns
221+pushInline :: Inline -> Lua ()
222+pushInline = \case
223+ Cite citations lst -> pushViaConstructor "Cite" lst citations
224+ Code attr lst -> pushViaConstructor "Code" lst (LuaAttr attr)
225+ Emph inlns -> pushViaConstructor "Emph" inlns
226+ Image attr alt (src,tit) -> pushViaConstructor "Image" alt src tit (LuaAttr attr)
227+ LineBreak -> pushViaConstructor "LineBreak"
228+ Link attr lst (src,tit) -> pushViaConstructor "Link" lst src tit (LuaAttr attr)
229+ Note blcks -> pushViaConstructor "Note" blcks
230+ Math mty str -> pushViaConstructor "Math" mty str
231+ Quoted qt inlns -> pushViaConstructor "Quoted" qt inlns
232+ RawInline f cs -> pushViaConstructor "RawInline" f cs
233+ SmallCaps inlns -> pushViaConstructor "SmallCaps" inlns
234+ SoftBreak -> pushViaConstructor "SoftBreak"
235+ Space -> pushViaConstructor "Space"
236+ Span attr inlns -> pushViaConstructor "Span" inlns (LuaAttr attr)
237+ Str str -> pushViaConstructor "Str" str
238+ Strikeout inlns -> pushViaConstructor "Strikeout" inlns
239+ Strong inlns -> pushViaConstructor "Strong" inlns
240+ Subscript inlns -> pushViaConstructor "Subscript" inlns
241+ Superscript inlns -> pushViaConstructor "Superscript" inlns
239242
240243-- | Return the value at the given index as inline if possible.
241−peekInline :: LuaState -> Int -> IO (Maybe Inline)
242−peekInline lua idx = do
243− tag <- getTable lua idx "t"
244+peekInline :: StackIndex -> Lua Inline
245+peekInline idx = do
246+ tag <- getTable idx "t"
244247 case tag of
245− Nothing -> return Nothing
246− Just t -> case t of
247− "Cite" -> fmap (uncurry Cite) <$> elementContent
248− "Code" -> fmap (withAttr Code) <$> elementContent
249− "Emph" -> fmap Emph <$> elementContent
250− "Image" -> fmap (\(LuaAttr attr, lst, tgt) -> Image attr lst tgt)
251− <$> elementContent
252− "Link" -> fmap (\(LuaAttr attr, lst, tgt) -> Link attr lst tgt)
253− <$> elementContent
254− "LineBreak" -> return (Just LineBreak)
255− "Note" -> fmap Note <$> elementContent
256− "Math" -> fmap (uncurry Math) <$> elementContent
257− "Quoted" -> fmap (uncurry Quoted) <$> elementContent
258− "RawInline" -> fmap (uncurry RawInline) <$> elementContent
259− "SmallCaps" -> fmap SmallCaps <$> elementContent
260− "SoftBreak" -> return (Just SoftBreak)
261− "Space" -> return (Just Space)
262− "Span" -> fmap (withAttr Span) <$> elementContent
263− "Str" -> fmap Str <$> elementContent
264− "Strikeout" -> fmap Strikeout <$> elementContent
265− "Strong" -> fmap Strong <$> elementContent
266− "Subscript" -> fmap Subscript <$> elementContent
267− "Superscript"-> fmap Superscript <$> elementContent
268− _ -> return Nothing
248+ "Cite" -> (uncurry Cite) <$> elementContent
249+ "Code" -> (withAttr Code) <$> elementContent
250+ "Emph" -> Emph <$> elementContent
251+ "Image" -> (\(LuaAttr attr, lst, tgt) -> Image attr lst tgt)
252+ <$> elementContent
253+ "Link" -> (\(LuaAttr attr, lst, tgt) -> Link attr lst tgt)
254+ <$> elementContent
255+ "LineBreak" -> return LineBreak
256+ "Note" -> Note <$> elementContent
257+ "Math" -> (uncurry Math) <$> elementContent
258+ "Quoted" -> (uncurry Quoted) <$> elementContent
259+ "RawInline" -> (uncurry RawInline) <$> elementContent
260+ "SmallCaps" -> SmallCaps <$> elementContent
261+ "SoftBreak" -> return SoftBreak
262+ "Space" -> return Space
263+ "Span" -> (withAttr Span) <$> elementContent
264+ "Str" -> Str <$> elementContent
265+ "Strikeout" -> Strikeout <$> elementContent
266+ "Strong" -> Strong <$> elementContent
267+ "Subscript" -> Subscript <$> elementContent
268+ "Superscript"-> Superscript <$> elementContent
269+ _ -> throwLuaError ("Unknown inline type: " ++ tag)
269270 where
270271 -- Get the contents of an AST element.
271− elementContent :: StackValue a => IO (Maybe a)
272− elementContent = getTable lua idx "c"
272+ elementContent :: FromLuaStack a => Lua a
273+ elementContent = getTable idx "c"
273274
274275withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b
275276withAttr f (attributes, x) = f (fromLuaAttr attributes) x
@@ -277,8 +278,8 @@ withAttr f (attributes, x) = f (fromLuaAttr attributes) x
277278-- | Wrapper for Attr
278279newtype LuaAttr = LuaAttr { fromLuaAttr :: Attr }
279280
280−instance StackValue LuaAttr where
281− push lua (LuaAttr (id', classes, kv)) =
282− pushViaConstructor lua "Attr" id' classes kv
283− peek lua idx = fmap LuaAttr <$> peek lua idx
284− valuetype _ = TTABLE
281+instance ToLuaStack LuaAttr where
282+ push (LuaAttr (id', classes, kv)) =
283+ pushViaConstructor "Attr" id' classes kv
284+instance FromLuaStack LuaAttr where
285+ peek idx = LuaAttr <$> peek idx