hslua-examples (empty) → 2.0.0
raw patch · 10 files changed
+346/−0 lines, 10 filesdep +basedep +bytestringdep +hslua
Dependencies added: base, bytestring, hslua, hslua-marshalling, lua, text
Files
- CHANGELOG.md +7/−0
- LICENSE +23/−0
- README.md +41/−0
- factorial/factorial.hs +26/−0
- hslua-examples.cabal +79/−0
- low-level-factorial/low-level-factorial.hs +41/−0
- print-version/print-version.hs +17/−0
- run-lua/run-lua.hs +30/−0
- wishlist/filter.lua +4/−0
- wishlist/wishlist.hs +78/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+## Changelog++### 2.0.0++Release pending.++Complete rewrite.
+ LICENSE view
@@ -0,0 +1,23 @@+Copyright © 1994-2020 Lua.org, PUC-Rio.+Copyright © 2007-2012 Gracjan Polak+Copyright © 2012-2015 Ömer Sinan Ağacan+Copyright © 2016-2021 Albert Krewinkel++Permission is hereby granted, free of charge, to any person obtaining a+copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ README.md view
@@ -0,0 +1,41 @@+HsLua examples+==============++[![Build status][GitHub Actions badge]][GitHub Actions]+[![AppVeyor Status]](https://ci.appveyor.com/project/tarleb/hslua-r2y18)+[![Hackage]](https://hackage.haskell.org/package/hslua-examples)++Example programs showcasing the [HsLua] framework.++[GitHub Actions badge]: https://img.shields.io/github/workflow/status/hslua/hslua/CI.svg?logo=github+[GitHub Actions]: https://github.com/hslua/hslua/actions+[AppVeyor Status]: https://ci.appveyor.com/api/projects/status/ldutrilgxhpcau94/branch/main?svg=true+[Hackage]: https://img.shields.io/hackage/v/hslua-core.svg+[HsLua]: https://hslua.org/++run-lua+-----------++A simple program which uses Lua to calculate and print Fibonacci+numbers. It demonstrates how a Lua script can be embedded and+executed.++print-version+-------------++Demonstrates the use of the the low-level C API functions from the+`lua` package. Prints the Lua version.++wishlist+----------++The code for [Santa's Little Lua Scripts][SLLS].++low-level-factorial+-------------------++Calculate integer factorials in Haskell, allowing for results+which don't fit into a normal Lua integer. Uses only the low-level+C API functions from the `lua` package.++[SLLS]: https://hslua.org/santas-little-lua-scripts.html
+ factorial/factorial.hs view
@@ -0,0 +1,26 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}+{-| Compute factorials in Haskell -}+module Main where+import Control.Monad (void)+import HsLua+import Prelude++-- | Factorial function.+factorial :: DocumentedFunction e+factorial = defun "factorial"+ ### liftPure (\n -> product [1..n] :: Prelude.Integer)+ -- get arg type of arg name description+ <#> parameter peekIntegral "integer" "n" "input number"+ =#> functionResult pushIntegral "integer|string" "factorial of n"+ #? "Computes the factorial of an integer."++main :: IO ()+main = run @HsLua.Exception $ do+ openlibs+ pushDocumentedFunction factorial *> setglobal "factorial"+ -- run a script+ void . dostring $ mconcat+ [ "print(' 5! =', factorial(5), type(factorial(5)))\n"+ , "print('30! =', factorial(30), type(factorial(30)))\n"+ ]
+ hslua-examples.cabal view
@@ -0,0 +1,79 @@+cabal-version: 2.2+name: hslua-examples+version: 2.0.0+synopsis: Examples of how to combine Haskell and Lua.+description: The HsLua modules provide wrappers of Lua language+ interpreter as described on the official+ <https://www.lua.org/ Lua website).+ .+ This package contains example programs, demonstrating+ the possibility to work with Lua from within Haskell+ and /vice versa/.+homepage: https://hslua.org/+bug-reports: https://github.com/hslua/hslua/issues+license: MIT+license-File: LICENSE+author: Albert Krewinkel+copyright: © 2020–2021 Albert Krewinkel+maintainer: Albert Krewinkel <albert+hslua@zeitkraut.de>+category: Foreign+build-type: Simple+extra-source-files: README.md+ CHANGELOG.md+ wishlist/filter.lua++source-repository head+ type: git+ location: https://github.com/hslua/hslua.git+ subdir: hslua-examples++common common-options+ default-language: Haskell2010+ build-depends: base >= 4.9 && < 5+ ghc-options: -Wall+ -Wincomplete-record-updates+ -Wnoncanonical-monad-instances+ -Wredundant-constraints+ if impl(ghc >= 8.2)+ ghc-options: -Wcpp-undef+ -Werror=missing-home-modules+ if impl(ghc >= 8.4)+ ghc-options: -Widentities+ -Wincomplete-uni-patterns+ -Wpartial-fields+ -fhide-source-paths++executable print-version+ import: common-options+ main-is: print-version.hs+ hs-source-dirs: print-version+ build-depends: lua >= 2.0 && < 2.1++executable run-lua+ import: common-options+ main-is: run-lua.hs+ hs-source-dirs: run-lua+ build-depends: bytestring+ , hslua >= 2.0 && < 2.1++executable wishlist+ import: common-options+ main-is: wishlist.hs+ hs-source-dirs: wishlist+ build-depends: bytestring+ , hslua >= 2.0 && < 2.1+ , hslua-marshalling >= 2.0 && < 2.1+ , text++executable factorial+ import: common-options+ main-is: factorial.hs+ hs-source-dirs: factorial+ build-depends: bytestring+ , hslua >= 2.0 && < 2.1++executable low-level-factorial+ import: common-options+ main-is: low-level-factorial.hs+ hs-source-dirs: low-level-factorial+ build-depends: lua >= 2.0 && < 2.1
+ low-level-factorial/low-level-factorial.hs view
@@ -0,0 +1,41 @@+-- lua_setglobal is unsafe in general and causes a compiler warning.+{-# OPTIONS_GHC -Wno-warnings-deprecations #-}+{-| Expose factorial function to Lua, using the low-level API. -}+module Main where+import Prelude+import Control.Monad (void)+import Foreign.C (withCString, withCStringLen)+import Foreign.Ptr (nullPtr)+import Lua++luaScript :: String+luaScript = unlines+ [ "print(' 5! =', factorial(5), type(factorial(5)))"+ , "print('30! =', factorial(30), type(factorial(30)))"+ ]++factorial :: PreCFunction+factorial l = do+ -- Get the first function argument as an integer.+ n <- lua_tointegerx l (nthBottom 1) nullPtr+ let result = product [1..fromIntegral n] :: Prelude.Integer+ -- push as integer if the result is small enough,+ -- and as string otherwise.+ if result <= fromIntegral (maxBound :: Lua.Integer)+ then lua_pushinteger l (fromIntegral result)+ else withCString (show result) (void . lua_pushstring l)+ -- Signal that one result value is on the top of the stack.+ return (NumResults 1)++main :: IO ()+main = void . withNewState $ \l -> do+ luaL_openlibs l+ -- expose Haskell function `factorial` as a Lua function of the same name.+ hslua_pushhsfunction l factorial+ _ <- withCString "factorial" (lua_setglobal l)+ -- Load the script.+ LUA_OK <- withCStringLen luaScript $ \(sPtr, sLen) ->+ withCString "script" $ luaL_loadbuffer l sPtr (fromIntegral sLen)+ -- Call the loaded script.+ LUA_OK <- lua_pcall l (NumArgs 0) LUA_MULTRET (StackIndex 0)+ return ()
+ print-version/print-version.hs view
@@ -0,0 +1,17 @@+-- @lua_getglobal@ is unsafe in general, but safe in this case.+{-# OPTIONS_GHC -Wno-warnings-deprecations #-}+{-| Use low-level API functions to output the Lua version. -}+module Main where+import Control.Monad (void)+import Foreign.C (withCString)+import Lua++main :: IO ()+main = void . withNewState $ \l -> do+ luaL_openlibs l+ -- Prepare call `print(_VERSION)`: first push the `print` function+ -- to the stack, then the arguments.+ LUA_TFUNCTION <- withCString "print" (lua_getglobal l)+ LUA_TSTRING <- withCString "_VERSION" (lua_getglobal l)+ -- Call the function with one argument.+ lua_pcall l (NumArgs 1) (NumResults 0) (StackIndex 0)
+ run-lua/run-lua.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE OverloadedStrings #-}+{-| Simple program running Lua code.+-}+module Main where+import HsLua.Core+import qualified Data.ByteString as B++main :: IO ()+main = do+ putStrLn "Calling Lua to output some Fibonacci numbers."+ luaStatus <- run $ do+ openlibs -- load the default Lua packages+ dostring luaProgram -- load and run the program+ putStrLn ("Lua finished with status '" ++ show luaStatus ++ "'.")+++-- | The Lua program. It uses a simple loop to calculate and print the+-- first 11 Fibonacci numbers.+--+-- Note that we are using the /OverloadedStrings/ extension. The+-- @IsString@ instance for ByteString behaves weirdly with non-ASCII+-- characters, but we don't use any here.+luaProgram :: B.ByteString+luaProgram = B.concat+ [ "local a, b = 0, 1\n"+ , "for i = 0, 10 do\n"+ , " print(i, a)\n"+ , " a, b = b, a + b\n"+ , "end\n"+ ]
+ wishlist/filter.lua view
@@ -0,0 +1,4 @@+return function (wish)+ return wish.child.nice and+ wish.toy == 'TrainSet'+end
+ wishlist/wishlist.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE OverloadedStrings #-}+{-| Santa's wishlist processor.++The program expexts the path to a filter file as its only argument.+See the blog-post for more details:+https://hslua.org/santas-little-lua-scripts.html+-}+module Main where+import Control.Monad (filterM)+import Data.Text (Text, pack)+import HsLua.Core ( Lua, NumResults (..), NumArgs (..)+ , call, dofile, newtable, nth, pop, pushvalue, run+ , setfield, top, toboolean)+import HsLua.Marshalling (pushBool, pushText)+import System.Environment (getArgs)++data Toy = Bricks | TrainSet | Doll deriving Show+data Behavior = Nice | Naughty deriving (Eq, Show)++data Wish = Wish+ { wishingChild :: Child+ , wishedToy :: Toy+ } deriving Show++data Child = Child+ { childName :: Text+ , childBehavior :: Behavior+ } deriving Show++pushToy :: Toy -> Lua ()+pushToy = pushText . pack . show++pushChild :: Child -> Lua ()+pushChild (Child name behavior) = do+ -- create new Lua table on the stack+ newtable+ -- push boolean to stack+ pushText name+ -- table now in position 2; assign string to field in table+ setfield (nth 2) "name"++ -- push boolean to stack+ pushBool (behavior == Nice)+ setfield (nth 2) "nice"++pushWish :: Wish -> Lua ()+pushWish (Wish child toy) = do+ newtable+ pushChild child+ setfield (nth 2) "child"+ pushToy toy+ setfield (nth 2) "toy"++wishes :: [Wish]+wishes =+ [ Wish (Child "Theodor" Nice) Bricks+ , Wish (Child "Philine" Nice) TrainSet+ , Wish (Child "Steve" Naughty) Doll+ ]++hasPredicate :: Wish -> Lua Bool+hasPredicate wish = do+ -- Assume filter function is at the top of the stack;+ -- create a copy so we can re-use it.+ pushvalue top+ pushWish wish+ -- Call the function. There is one argument on the stack,+ -- and we expect one result to be returned.+ call (NumArgs 1) (NumResults 1)+ toboolean top <* pop 1++main :: IO ()+main = do+ filterFile <- fmap (!! 0) getArgs -- get first argument+ result <- run $ do+ _status <- dofile filterFile+ filterM hasPredicate wishes+ print result