Skip to content

Commit b5415ab

Browse files
author
Guilherme G. Azzi
committed
Improve handling errors from Lua
1 parent d48350d commit b5415ab

File tree

7 files changed

+123
-107
lines changed

7 files changed

+123
-107
lines changed

src/repl/GrLang.hs

Lines changed: 78 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,37 @@
44
module GrLang (initialize) where
55

66
import Control.Monad
7-
import Control.Monad.Except (ExceptT (..), runExceptT)
8-
import qualified Control.Monad.Except as ExceptT
7+
import Control.Monad.Except (ExceptT (..), runExceptT)
8+
import qualified Control.Monad.Except as ExceptT
99
import Control.Monad.Reader
10-
import Control.Monad.Trans (lift)
10+
import Control.Monad.Trans (lift)
1111
import Data.Array.IO
1212
import Data.IORef
13-
import Data.Map (Map)
14-
import qualified Data.Map as Map
13+
import Data.Map (Map)
14+
import qualified Data.Map as Map
1515
import Data.Monoid
16-
import Data.Set (Set)
17-
import qualified Data.Set as Set
18-
import Data.Text (Text)
19-
import qualified Data.Text as Text
20-
import qualified Data.Text.Encoding as Text
21-
import Data.Text.Prettyprint.Doc (Pretty (..))
22-
import Foreign.Lua (Lua)
23-
import qualified Foreign.Lua as Lua
16+
import Data.Set (Set)
17+
import qualified Data.Set as Set
18+
import Data.Text (Text)
19+
import qualified Data.Text as Text
20+
import qualified Data.Text.Encoding as Text
21+
import Data.Text.Prettyprint.Doc (Pretty (..))
22+
import Foreign.Lua (FromLuaStack, Lua, ToLuaStack)
23+
import qualified Foreign.Lua as Lua
2424

2525
import Abstract.Category
26+
import Abstract.Category.Adhesive
2627
import Abstract.Category.Limit
27-
import Abstract.Category.Adhesive
28-
import Abstract.Rewriting.DPO
29-
import Base.Annotation (Annotated (..))
30-
import qualified Data.Graphs as TypeGraph
31-
import Data.TypedGraph (EdgeId, Node (..), NodeId)
32-
import qualified GrLang.Compiler as GrLang
33-
import GrLang.Monad (MonadGrLang)
34-
import qualified GrLang.Monad as GrLang
35-
import qualified GrLang.Parser as GrLang
28+
import Abstract.Rewriting.DPO
29+
import Base.Annotation (Annotated (..))
30+
import qualified Data.Graphs as TypeGraph
31+
import Data.TypedGraph (EdgeId, Node (..), NodeId)
32+
import qualified GrLang.Compiler as GrLang
33+
import GrLang.Monad (MonadGrLang)
34+
import qualified GrLang.Monad as GrLang
35+
import qualified GrLang.Parser as GrLang
3636
import GrLang.Value
37-
import qualified Image.Dot.TypedGraph as Dot
37+
import qualified Image.Dot.TypedGraph as Dot
3838
import Util.Lua
3939

4040
data GrLangState = GrLangState
@@ -116,12 +116,12 @@ instance MonadGrLang (ReaderT GrLangState Lua) where
116116

117117
getValue (A _ name) = do
118118
liftLua $ Lua.getglobal (Text.unpack name)
119-
hasTable <- liftLua $ Lua.istable (-1)
119+
hasTable <- liftLua $ Lua.istable Lua.stackTop
120120
if not hasTable
121121
then GrLang.throwError Nothing "Value is not a table"
122122
else do
123-
liftLua $ Lua.getfield (-1) indexKey
124-
result <- liftLua $ Lua.tointegerx (-1)
123+
liftLua $ Lua.getfield Lua.stackTop indexKey
124+
result <- liftLua $ Lua.tointegerx Lua.stackTop
125125
liftLua $ Lua.pop 2
126126
case result of
127127
Nothing -> GrLang.throwError Nothing "Value has no index"
@@ -247,79 +247,80 @@ grLangNamingContext = Dot.Ctx
247247
initGrLang :: GrLangState -> Lua ()
248248
initGrLang globalState = do
249249
setNative "GrLang"
250-
[ ("getNodeTypes", Lua.pushHaskellFunction
251-
(map Text.unpack . Map.keys <$> liftIO (readIORef $ nodeTypes globalState) :: Lua [String])
250+
[ ("getNodeTypes", haskellFn0 globalState $ do
251+
types <- get nodeTypes
252+
return . map Text.unpack $ Map.keys types
252253
)
253-
, ("getEdgeTypes", Lua.pushHaskellFunction . runGrLang' globalState $ do
254-
types <- Map.keys <$> get edgeTypes
255-
forM types $ \(name, srcId, tgtId) -> do
256-
tgraph <- get typeGraph
257-
let Just srcType = TypeGraph.lookupNode srcId tgraph
258-
Just tgtType = TypeGraph.lookupNode tgtId tgraph
259-
return . Text.unpack $ formatEdgeType name (nodeName srcType) (nodeName tgtType)
254+
, ("getEdgeTypes", haskellFn0 globalState $ do
255+
types <- Map.keys <$> get edgeTypes
256+
forM types $ \(name, srcId, tgtId) -> do
257+
tgraph <- get typeGraph
258+
let Just srcType = TypeGraph.lookupNode srcId tgraph
259+
Just tgtType = TypeGraph.lookupNode tgtId tgraph
260+
return . Text.unpack $ formatEdgeType name (nodeName srcType) (nodeName tgtType)
260261
)
261-
, ("addNodeType", Lua.pushHaskellFunction $ \name -> runGrLang' globalState $
262+
, ("addNodeType", haskellFn1 globalState $ \name ->
262263
GrLang.addNodeType (A Nothing name)
263264
)
264-
, ("addEdgeType", Lua.pushHaskellFunction $ \name srcName tgtName -> runGrLang' globalState $
265+
, ("addEdgeType", haskellFn3 globalState $ \name srcName tgtName ->
265266
GrLang.addEdgeType (A Nothing name) (A Nothing srcName) (A Nothing tgtName)
266267
)
267-
, ("toString", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $
268+
, ("toString", haskellFn1 globalState $ \idx ->
268269
show . pretty <$> lookupGrLangValue idx
269270
)
270-
, ("equals", Lua.pushHaskellFunction $ \idxA idxB -> runGrLang' globalState $ do
271+
, ("equals", haskellFn2 globalState $ \idxA idxB -> do
271272
valA <- lookupGrLangValue idxA
272273
valB <- lookupGrLangValue idxB
273274
return (valA == valB)
274275
)
275-
, ("deallocate", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $
276+
, ("deallocate", haskellFn1 globalState $ \idx ->
276277
freeGrLang idx
277278
)
278-
, ("toDot", Lua.pushHaskellFunction $ \idx name -> runGrLang' globalState $ do
279+
, ("toDot", haskellFn2 globalState $ \idx name -> do
279280
VGraph graph <- lookupGrLangValue idx
280281
return . show $ Dot.typedGraph grLangNamingContext (pretty $ Text.decodeUtf8 name) graph
281282
)
282-
, ("compileFile", Lua.pushHaskellFunction $ \path -> runGrLang' globalState $
283+
, ("compileFile", haskellFn1 globalState $ \path ->
283284
GrLang.compileFile path
284285
)
285286
]
286287

287288
setNative "Graph"
288-
[ ("parse", Lua.pushHaskellFunction $ \string -> runGrLang' globalState $ do
289+
[ ("parse", haskellFn1 globalState $ \string -> do
289290
graph <- GrLang.compileGraph =<< GrLang.parseGraph "<repl>" (string :: String)
290291
allocateGrLang (VGraph graph)
291292
),
292-
("identity", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $ do
293+
("identity", haskellFn1 globalState $ \idx -> do
293294
VGraph graph <- lookupGrLangValue idx
294295
allocateGrLang (VMorph $ identity graph)
295296
)
296297
]
297298

298299
setNative "Morphism"
299-
[ ("parse", Lua.pushHaskellFunction $ \domIdx codIdx string -> runGrLang' globalState $ do
300+
[ ("parse", haskellFn3 globalState $ \domIdx codIdx string -> do
300301
VGraph dom <- lookupGrLangValue domIdx
301302
VGraph cod <- lookupGrLangValue codIdx
302303
morphism <- GrLang.compileMorphism Nothing dom cod =<< GrLang.parseMorphism "<repl>" (string :: String)
303304
allocateGrLang (VMorph morphism)
304305
),
305-
("compose", Lua.pushHaskellFunction $ \idF idG -> runGrLang' globalState $ do
306+
("compose", haskellFn2 globalState $ \idF idG -> do
306307
VMorph f <- lookupGrLangValue idF
307308
VMorph g <- lookupGrLangValue idG
308309
allocateGrLang (VMorph $ f <&> g)
309310
),
310-
("isMonic", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $ do
311+
("isMonic", haskellFn1 globalState $ \idx -> do
311312
VMorph f <- lookupGrLangValue idx
312313
return (isMonic f)
313314
),
314-
("isEpic", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $ do
315+
("isEpic", haskellFn1 globalState $ \idx -> do
315316
VMorph f <- lookupGrLangValue idx
316317
return (isEpic f)
317318
),
318-
("isIsomorphism", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $ do
319+
("isIsomorphism", haskellFn1 globalState $ \idx -> do
319320
VMorph f <- lookupGrLangValue idx
320321
return (isIsomorphism f)
321322
),
322-
("calculatePullback", Lua.pushHaskellFunction $ \idF idG -> runGrLang' globalState $ do
323+
("calculatePullback", haskellFn2 globalState $ \idF idG -> do
323324
VMorph f <- lookupGrLangValue idF
324325
VMorph g <- lookupGrLangValue idG
325326
let (f', g') = calculatePullback f g
@@ -328,7 +329,7 @@ initGrLang globalState = do
328329
<*> allocateGrLang (VMorph f')
329330
<*> allocateGrLang (VMorph g')
330331
),
331-
("calculateInitialPushout", Lua.pushHaskellFunction $ \idx -> runGrLang' globalState $ do
332+
("calculateInitialPushout", haskellFn1 globalState $ \idx -> do
332333
VMorph f <- lookupGrLangValue idx
333334
let (b, f', c) = calculateMInitialPushout f
334335
(,,,,)
@@ -338,15 +339,15 @@ initGrLang globalState = do
338339
<*> allocateGrLang (VMorph f')
339340
<*> allocateGrLang (VMorph c)
340341
),
341-
("subobjectIntersection", Lua.pushHaskellFunction $ \idA idB -> runGrLang' globalState $ do
342+
("subobjectIntersection", haskellFn2 globalState $ \idA idB -> do
342343
VMorph a <- lookupGrLangValue idA
343344
VMorph b <- lookupGrLangValue idB
344345
let c = subobjectIntersection a b
345346
(,)
346347
<$> (allocateGrLang . VGraph $ domain c)
347348
<*> (allocateGrLang . VMorph $ c)
348349
),
349-
("subobjectUnion", Lua.pushHaskellFunction $ \idA idB -> runGrLang' globalState $ do
350+
("subobjectUnion", haskellFn2 globalState $ \idA idB -> do
350351
VMorph a <- lookupGrLangValue idA
351352
VMorph b <- lookupGrLangValue idB
352353
let c = subobjectUnion a b
@@ -357,27 +358,27 @@ initGrLang globalState = do
357358
]
358359

359360
setNative "Rule"
360-
[ ("parse", Lua.pushHaskellFunction $ \string -> runGrLang' globalState $ do
361+
[ ("parse", haskellFn1 globalState $ \string -> do
361362
rule <- GrLang.compileRule =<< GrLang.parseRule "<repl>" (string :: String)
362363
allocateGrLang (VRule rule)
363364
)
364-
, ("getLeftObject", Lua.pushHaskellFunction $ \idRule -> runGrLang' globalState $ do
365+
, ("getLeftObject", haskellFn1 globalState $ \idRule -> do
365366
VRule rule <- lookupGrLangValue idRule
366367
allocateGrLang (VGraph $ leftObject rule)
367368
)
368-
, ("getRightObject", Lua.pushHaskellFunction $ \idRule -> runGrLang' globalState $ do
369+
, ("getRightObject", haskellFn1 globalState $ \idRule -> do
369370
VRule rule <- lookupGrLangValue idRule
370371
allocateGrLang (VGraph $ rightObject rule)
371372
)
372-
, ("getInterface", Lua.pushHaskellFunction $ \idRule -> runGrLang' globalState $ do
373+
, ("getInterface", haskellFn1 globalState $ \idRule -> do
373374
VRule rule <- lookupGrLangValue idRule
374375
allocateGrLang (VGraph $ interfaceObject rule)
375376
)
376-
, ("getLeftMorphism", Lua.pushHaskellFunction $ \idRule -> runGrLang' globalState $ do
377+
, ("getLeftMorphism", haskellFn1 globalState $ \idRule -> do
377378
VRule rule <- lookupGrLangValue idRule
378379
allocateGrLang (VMorph $ leftMorphism rule)
379380
)
380-
, ("getRightMorphism", Lua.pushHaskellFunction $ \idRule -> runGrLang' globalState $ do
381+
, ("getRightMorphism", haskellFn1 globalState $ \idRule -> do
381382
VRule rule <- lookupGrLangValue idRule
382383
allocateGrLang (VMorph $ rightMorphism rule)
383384
)
@@ -391,6 +392,24 @@ initGrLang globalState = do
391392
Lua.setfield tableIdx "native"
392393
Lua.pop 1
393394

395+
haskellFn0 :: ToLuaStack a => GrLangState -> ExceptT GrLang.Error LuaGrLang a -> Lua ()
396+
haskellFn0 globalState f = pushFunction (runGrLang' globalState f)
397+
398+
haskellFn1 ::
399+
(FromLuaStack a, ToLuaStack b) =>
400+
GrLangState -> (a -> ExceptT GrLang.Error LuaGrLang b) -> Lua ()
401+
haskellFn1 globalState f = pushFunction (runGrLang' globalState . f)
402+
403+
haskellFn2 ::
404+
(FromLuaStack a, FromLuaStack b, ToLuaStack c) =>
405+
GrLangState -> (a -> b -> ExceptT GrLang.Error LuaGrLang c) -> Lua ()
406+
haskellFn2 globalState f = pushFunction (\x y -> runGrLang' globalState (f x y))
407+
408+
haskellFn3 ::
409+
(FromLuaStack a, FromLuaStack b, FromLuaStack c, ToLuaStack d) =>
410+
GrLangState -> (a -> b -> c -> ExceptT GrLang.Error LuaGrLang d) -> Lua ()
411+
haskellFn3 globalState f = pushFunction (\x y z -> runGrLang' globalState (f x y z))
412+
394413
createTable :: Foldable t => t (String, Lua ()) -> Lua ()
395414
createTable contents = do
396415
Lua.createtable 0 (length contents)

src/repl/Main.hs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,16 @@ main = runLua $ do
7171

7272
addingToPath dir action = do
7373
Lua.getglobal "package"
74-
Lua.getfield (-1) "path"
75-
oldPath <- Lua.tostring (-1)
74+
Lua.getfield Lua.stackTop "path"
75+
oldPath <- Lua.tostring Lua.stackTop
7676
let newPath = stringToByteString (dir ++ "/?.lua;") <> oldPath
7777
Lua.pushstring newPath
78-
Lua.setfield (-3) "path"
78+
Lua.setfield (Lua.nthFromTop 3) "path"
7979
Lua.pop 2
8080
result <- action
8181
Lua.getglobal "package"
8282
Lua.pushstring oldPath
83-
Lua.setfield (-2) "path"
83+
Lua.setfield (Lua.nthFromTop 2) "path"
8484
return result
8585

8686
stringToByteString :: String -> BS.ByteString
@@ -120,7 +120,7 @@ read' = do
120120
else checkStatus status >> return RError
121121
_ -> checkStatus status >> return RError
122122

123-
testIfIncomplete = ("<eof>" `ByteString.isSuffixOf`) <$> Lua.tostring (-1)
123+
testIfIncomplete = ("<eof>" `ByteString.isSuffixOf`) <$> Lua.tostring Lua.stackTop
124124

125125
eval' :: Lua Bool
126126
eval' = Lua.pcall 0 Lua.multret Nothing >>= checkStatus
@@ -131,7 +131,7 @@ print' = do
131131
let numValues = fromIntegral (fromEnum stackTop)
132132
when (numValues > 0) $ do
133133
Lua.getglobal "print"
134-
Lua.insert 1
134+
Lua.insert Lua.stackBottom
135135
status <- Lua.pcall numValues 0 Nothing
136136
case status of
137137
Lua.OK -> return ()

src/repl/Util/Lua.hs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Control.Monad.Trans
55
import qualified Data.ByteString as ByteString
66
import Foreign.Lua
77
import qualified Foreign.Lua as Lua
8+
import System.IO (hPutStr, hPutStrLn, stderr)
89

910
checkStatus :: Lua.Status -> Lua Bool
1011
checkStatus Lua.OK = return True
@@ -15,17 +16,23 @@ checkStatus status = showError prefix >> return False
1516
Lua.ErrRun -> "Error: "
1617
_ -> "Critical error: "
1718

19+
pushFunction :: ToHaskellFunction a => a -> Lua ()
20+
pushFunction f =
21+
Lua.pushHaskellFunction f >> Lua.wrapHaskellFunction
22+
1823
showError :: String -> Lua ()
1924
showError prefix = do
20-
msg <- Lua.tostring (-1)
21-
liftIO $ putStr prefix >> ByteString.putStr msg >> putStrLn ""
25+
msg <- Lua.tostring Lua.stackTop
26+
liftIO $ do
27+
hPutStr stderr prefix
28+
ByteString.hPutStr stderr msg
29+
hPutStrLn stderr ""
2230
Lua.pop 1
2331

2432
luaError :: String -> Lua NumResults
2533
luaError msg = do
26-
Lua.push "_HASKELLERR"
2734
Lua.push msg
28-
return 2
35+
fromIntegral <$> Lua.lerror
2936

3037
execLua :: String -> Lua ()
3138
execLua code = do

0 commit comments

Comments
 (0)