Main.hs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. {-# LANGUAGE NamedFieldPuns #-}
  2. module Main where
  3. import qualified Control.Exception as Exn
  4. import qualified Foreign.Lua as Lua
  5. data Config = Config
  6. { cfgHost :: String,
  7. cfgPort :: Int,
  8. cfgFiles :: [String]
  9. }
  10. deriving (Show)
  11. readConfig :: FilePath -> IO Config
  12. readConfig configPath =
  13. -- set up a new Lua state, and make sure we close it at the end
  14. Exn.bracket Lua.newstate Lua.close $ \st ->
  15. -- we should set up a mechanism to convert Lua/Haskell errors into
  16. -- one another, but that seems like a lot of work here, so this
  17. -- just panics whenever any errors happen, hence `unsafeRunWith`
  18. Lua.unsafeRunWith st $ do
  19. -- this loads the stdlib into Lua, but you probably don't
  20. -- actually want this in a config file! (it allows e.g. file IO
  21. -- and stuff)
  22. Lua.openlibs
  23. -- load the actual config path. this should check error
  24. -- conditions, but eh.
  25. _ <- Lua.loadfile configPath
  26. -- that simply loads the code as a zero-argument function: now
  27. -- call it
  28. Lua.call 0 0
  29. -- use the `readGlobal` helper to extract the globals defined by
  30. -- the config file...
  31. cfgHost <- readGlobal "host"
  32. cfgPort <- readGlobal "port"
  33. cfgFiles <- readGlobal "files"
  34. -- and return the values
  35. return Config {cfgHost, cfgPort, cfgFiles}
  36. -- | Read the global variable @name@ into a Haskell value
  37. readGlobal :: Lua.Peekable t => String -> Lua.Lua t
  38. readGlobal name = do
  39. -- this pushes the global named `name` onto the top of the stack
  40. Lua.getglobal name
  41. -- this finds out what index is at the top of the stack
  42. idx <- Lua.gettop
  43. -- this uses the `peek` functionality, already parameterized by a
  44. -- typeclass, to convert the value at the given index into the
  45. -- appropriate Haskell type
  46. value <- Lua.peek idx
  47. -- pop the global, now that we've already got it in Haskell-land
  48. Lua.pop 1
  49. -- ...and return it
  50. return value
  51. main :: IO ()
  52. main = do
  53. cfg <- readConfig "sample.lua"
  54. print cfg