a bit more clarity
Getty Ritter
1 year, 11 months ago
4 | 4 | module Main (main) where |
5 | 5 | |
6 | 6 | import qualified Control.Exception.Base as Exn |
7 | import qualified Control.Monad as Monad | |
7 | 8 | import qualified Data.ByteString.Char8 as BS |
8 | 9 | import qualified Data.TeLML as TeLML |
9 | 10 | import qualified Data.Text as Text |
29 | 30 | Left err -> do |
30 | 31 | putStrLn err |
31 | 32 | Sys.exitFailure |
32 | -- read the Lua source file, if provided | |
33 | luaSource <- case optTagFile options of | |
34 | Nothing -> return "" | |
35 | Just f -> BS.readFile f | |
36 | 33 | -- run everything needed in the Lua context (i.e. evaluating the |
37 | 34 | -- source and then using it to interpret tags) |
38 |
result <- Lua.runEither (luaMain options |
|
35 | result <- Lua.runEither (luaMain options telml) | |
39 | 36 | -- either print the result or print the error nicely |
40 | 37 | case result of |
41 | 38 | Right msg -> Text.putStr msg |
51 | 48 | |
52 | 49 | -- | Evaluate the provided Lua source code and then use it to |
53 | 50 | -- interpret the `TeLML.Document`. |
54 | luaMain :: Options -> BS.ByteString -> TeLML.Document -> LuaM Text.Text | |
55 | luaMain opts luaSource doc = do | |
51 | luaMain :: Options -> TeLML.Document -> LuaM Text.Text | |
52 | luaMain opts doc = do | |
56 | 53 | -- load the basic libraries so we have access to stuff like `ipairs` |
57 | 54 | Lua.openbase |
58 | 55 | Lua.pop 1 |
61 | 58 | Lua.newtable |
62 | 59 | Lua.setglobal "telml" |
63 | 60 | |
64 | -- evaluate the source file. (We don't care what it evaluates to.) | |
65 | _ <- Lua.dostring luaSource | |
61 | -- evaluate the source file. | |
62 | case optTagFile opts of | |
63 | Nothing -> return () | |
64 | Just f -> do | |
65 | status <- Lua.dofile f | |
66 | case status of | |
67 | -- if it ran fine, then return | |
68 | Lua.OK -> return () | |
69 | -- if it produced a runtime or syntax error, say so | |
70 | Lua.ErrRun -> do | |
71 | msg <- Lua.tostring (-1) | |
72 | throw (LuaEvaluationError msg) | |
73 | Lua.ErrSyntax -> do | |
74 | msg <- Lua.tostring (-1) | |
75 | throw (LuaEvaluationError msg) | |
76 | _ -> | |
77 | throw (BadEvaluationStatus status) | |
66 | 78 | |
67 | 79 | -- make sure that the user didn't do something funky like redefine |
68 | 80 | -- the global `telml` to a string. |
69 | 81 | telml <- Lua.getglobal "telml" |
70 | if telml /= Lua.TypeTable | |
71 | then throw (RedefinedTable telml) | |
72 |
|
|
82 | Monad.when (telml /= Lua.TypeTable) $ | |
83 | throw (RedefinedTable telml) | |
73 | 84 | |
74 | 85 | -- walk over the document, evaluating as we go |
75 | 86 | handleDoc opts doc |
241 | 252 | " instead" |
242 | 253 | ] |
243 | 254 | |
255 | -- | Whatever | |
256 | data BadEvaluationStatus = BadEvaluationStatus { besStatus :: Lua.Status } deriving (Show) | |
257 | ||
258 | instance Exn.Exception BadEvaluationStatus where | |
259 | displayException bes = case besStatus bes of | |
260 | Lua.Yield -> "Tag file yielded instead of exiting" | |
261 | Lua.ErrMem -> "Tag file ran out of memory" | |
262 | Lua.ErrErr -> "Tag file failed when running message handler" | |
263 | Lua.ErrFile -> "Failed to open or read tag file" | |
264 | rs -> error "[unreachable: should have handled status " ++ show rs ++" elsewhere]" | |
265 | ||
266 | -- | An error for when running the tag file failed | |
267 | data LuaEvaluationError = LuaEvaluationError { leeMessage :: Maybe BS.ByteString } deriving (Show) | |
268 | ||
269 | instance Exn.Exception LuaEvaluationError where | |
270 | displayException (LuaEvaluationError (Just m)) = | |
271 | "Error loading tags: " ++ BS.unpack m | |
272 | displayException (LuaEvaluationError Nothing) = | |
273 | "Error loading tags, but could not get error message" | |
274 | ||
275 | ||
244 | 276 | -- | Print a Lua type nicely (for error message purposes) |
245 | 277 | ppType :: Lua.Type -> String |
246 | 278 | ppType Lua.TypeNil = "nil" |