packages feed

oughta 0.1.1.0 → 0.2.0.0

raw patch · 9 files changed

+87/−18 lines, 9 filesdep ~basedep ~exceptionsdep ~file-embedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, exceptions, file-embed, hslua, oughta, text

API changes (from Hackage documentation)

+ Oughta: Hooks :: Lua () -> Lua () -> Hooks
+ Oughta: [postHook] :: Hooks -> Lua ()
+ Oughta: [preHook] :: Hooks -> Lua ()
+ Oughta: data Hooks
+ Oughta: defaultHooks :: Hooks
- Oughta: check :: LuaProgram -> Output -> IO Result
+ Oughta: check :: Hooks -> LuaProgram -> Output -> IO Result
- Oughta: check' :: HasCallStack => LuaProgram -> Output -> IO ()
+ Oughta: check' :: HasCallStack => Hooks -> LuaProgram -> Output -> IO ()

Files

CHANGELOG.md view
@@ -1,3 +1,11 @@+# [0.2.0.0] -- 2025-05-02++[0.2.0.0]: https://github.com/GaloisInc/oughta/releases/tag/v0.2.0.0++- Add hooks, `Lua` actions that run before or after Lua programs. To upgrade+  from v0.1, just add `defaultHooks` as the first argument to `check{,'}`.+- Add the `reset` function to the Lua API.+ # [0.1.1.0] -- 2025-04-22  [0.1.1.0]: https://github.com/GaloisInc/oughta/releases/tag/v0.1.1.0
README.md view
@@ -21,8 +21,11 @@ check "world" ``` -Oughta draws inspiration from LLVM's [FileCheck] and Rust's [compiletest].+Oughta draws inspiration from [DejaGNU] (which is used to test [GCC]), LLVM's+[FileCheck], and Rust's [compiletest]. +[DejaGNU]: https://www.gnu.org/software/dejagnu/+[GCC]: https://gcc.gnu.org/ [FileCheck]: https://llvm.org/docs/CommandGuide/FileCheck.html [compiletest]: https://rustc-dev-guide.rust-lang.org/tests/compiletest.html @@ -193,12 +196,14 @@ Checking functions:  - `check(s: String)`: Find `s` in `text`. Seek to after the end of `s`. Like-  LLVM FileCheck's `CHECK`.+  LLVM FileCheck's `CHECK`, or [Expect's][expect] `expect`. - `checkln(s: String)`: `checkln(s)` is equivalent to `check(s .. "\n")`. - `here(s: String)`: Check that `text` beings with `s`. Seek to after the end   of `s`. - `hereln(String)`: `hereln(s)` is equivalent to `here(s .. "\n")`. +[expect]: https://core.tcl-lang.org/expect/index+ Other utilities:  - `col() -> Int`: Get the current line number of `text` in the output.@@ -212,6 +217,9 @@ - `fail()`: Fail to match at this point in `text`. - `match(n: Integer)`: Consume `n` bytes of `text`, treating them as a match. - `seek(n: Integer)`: Seek forward `n` bytes in `text`.+- `reset(name: String, s: String)`: Set `text` to `s` and reset the program+  state (e.g., location tracking). Treat `name` as the file name for `s` in+  user-facing output.  ## Motivation 
oughta.cabal view
@@ -1,6 +1,6 @@-cabal-version: 2.4+cabal-version: 3.0 name: oughta-version: 0.1.1.0+version: 0.2.0.0 author: Galois, Inc. maintainer: grease@galois.com copyright: Galois, Inc. 2025@@ -26,7 +26,7 @@  common shared   default-language: GHC2021-  build-depends: base >= 4.17 && < 5+  build-depends: base ^>= { 4.17, 4.18, 4.19, 4.20, 4.21 },    -- Specifying -Wall and -Werror can cause the project to fail to build on   -- newer versions of GHC simply due to new warnings being added to -Wall. To@@ -135,16 +135,17 @@   build-depends:     bytestring,     containers,-    exceptions >= 0.10 && < 0.11,-    file-embed >= 0.0.16 && < 0.1,-    hslua >= 2.3 && < 2.4,-    text,+    exceptions ^>= 0.10,+    file-embed ^>= 0.0.15,+    hslua ^>= 2.3,+    text ^>= { 2, 2.1 },    exposed-modules:     Oughta   other-modules:     Oughta.Exception     Oughta.Extract+    Oughta.Hooks     Oughta.Lua     Oughta.LuaApi     Oughta.Pos@@ -157,7 +158,7 @@   hs-source-dirs: test   main-is: Test.hs   build-depends:-    oughta+    oughta >= 0.2.0.0,   build-depends:     bytestring,     directory,
src/Oughta.hs view
@@ -21,12 +21,16 @@   , Loc(..)   , Pos(..)   , OP.Span(..)+    -- * Hooks+  , OH.Hooks(..)+  , OH.defaultHooks   ) where  import Control.Exception qualified as X import Data.ByteString (ByteString) import Oughta.Extract (LuaProgram) import Oughta.Extract qualified as OE+import Oughta.Hooks qualified as OH import Oughta.LuaApi qualified as FCLA import Oughta.Pos (Loc(..), Pos(..)) import Oughta.Pos qualified as OP@@ -39,19 +43,21 @@  -- | Check some program output against a Oughta Lua program. check ::+  OH.Hooks ->   LuaProgram ->   Output ->   IO OR.Result-check prog (Output out) = FCLA.check prog out+check hooks prog (Output out) = FCLA.check hooks prog out  -- | Like 'check', but throws an exception on failure. check' ::   HasCallStack =>+  OH.Hooks ->   LuaProgram ->   Output ->   IO ()-check' prog out = do-  OR.Result r <- check prog out+check' hooks prog out = do+  OR.Result r <- check hooks prog out   case r of     Left f -> X.throwIO f     Right {} -> pure ()
+ src/Oughta/Hooks.hs view
@@ -0,0 +1,21 @@+module Oughta.Hooks+  ( Hooks(..)+  , defaultHooks+  ) where++import HsLua (Lua)++data Hooks+  = Hooks+    { -- | Hook that runs before execution of the Lua program+      preHook :: Lua ()+      -- | Hook that runs after successful execution of the Lua program+    , postHook :: Lua ()+    }++defaultHooks :: Hooks+defaultHooks =+  Hooks+  { preHook = pure ()+  , postHook = pure ()+  }
src/Oughta/LuaApi.hs view
@@ -17,6 +17,7 @@ import Oughta.Exception (Exception) import Oughta.Exception qualified as OE import Oughta.Extract (LuaProgram, SourceMap, lookupSourceMap, programText, sourceMap, sourceMapFile)+import Oughta.Hooks qualified as OH import Oughta.Lua qualified as OL import Oughta.Pos qualified as OP import Oughta.Result (Progress, Result)@@ -85,6 +86,13 @@           }     pure (OR.updateProgress m p) +-- | Implementation of @reset@. Not exported.+reset :: IORef Progress -> String -> ByteString -> Lua.LuaE Exception ()+reset stateRef name txt = do+  setText txt+  let p0 = OR.newProgress name txt+  liftIO (IORef.writeIORef stateRef p0)+ -- | Implementation of @seek@. Not exported. seek :: IORef Progress -> Int -> Lua.LuaE Exception () seek stateRef chars =@@ -123,13 +131,14 @@  -- | Load user and Oughta Lua code. Helper, not exported. luaSetup ::+  OH.Hooks ->   IORef Progress ->   -- | User code   LuaProgram ->   -- | Initial content of @text@ global   ByteString ->   Lua.LuaE Exception ()-luaSetup stateRef prog txt = do+luaSetup hooks stateRef prog txt = do   Lua.openlibs   setText txt @@ -150,6 +159,9 @@   Lua.pushHaskellFunction (Lua.toHaskellFunction (match sm stateRef))   Lua.setglobal (Lua.Name "match") +  Lua.pushHaskellFunction (Lua.toHaskellFunction (reset stateRef))+  Lua.setglobal (Lua.Name "reset")+   Lua.pushHaskellFunction (Lua.toHaskellFunction (seek stateRef))   Lua.setglobal (Lua.Name "seek") @@ -159,20 +171,25 @@   _ <- Lua.loadbuffer OL.luaCode (Lua.Name "oughta.lua")   Lua.call 0 0 +  Lua.changeErrorType (OH.preHook hooks)+   let nm = Lua.Name (Text.encodeUtf8 (sourceMapFile sm))   _ <- Lua.loadbuffer (Text.encodeUtf8 (programText prog)) nm   Lua.call 0 0 +  Lua.changeErrorType (OH.postHook hooks)+ -- | Check some text against a Lua program using the API. check ::+  OH.Hooks ->   LuaProgram ->   -- | Text to check   ByteString ->   IO Result-check prog txt = do+check hooks prog txt = do   let p0 = OR.newProgress "<out>" txt   stateRef <- IORef.newIORef p0-  result <- Lua.run (Lua.try (luaSetup stateRef prog txt))+  result <- Lua.run (Lua.try (luaSetup hooks stateRef prog txt))   case result of     Left (OE.LuaException e) -> X.throwIO e     Left (OE.Failure noMatch) ->
+ test-data/fail/reset.txt view
@@ -0,0 +1,4 @@+# reset("<out>", "bar")+# check "foo"+foo+; check "❌"
+ test-data/pass/reset.txt view
@@ -0,0 +1,4 @@+# reset("<out>", "bar")+# check "bar"+foo+; match_on_line(1)
test/Test.hs view
@@ -51,14 +51,14 @@    let prog0 = Ota.fromLineComments file comment content   let prog = Ota.addPrefix (Text.decodeUtf8Lenient prelude) prog0-  result <- Ota.check prog (clearComments content)+  result <- Ota.check Ota.defaultHooks prog (clearComments content)   TTH.assertBool file (not (Ota.resultNull result))    let prog0' = Ota.fromLineComments file comment' content   let prog' = Ota.addPrefix (Text.decodeUtf8Lenient prelude) prog0'   let output'@(Ota.Output out) = clearComments (Ota.printResult result)   BS.writeFile (FilePath.replaceExtension file "out") out-  Ota.check' prog' output'+  Ota.check' Ota.defaultHooks prog' output'  discover :: FilePath -> IO [TT.TestTree] discover dir = do