a bit more clarity
Getty Ritter
2 years 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" |