packages feed

file-location 0.4.2 → 0.4.3

raw patch · 13 files changed

+268/−48 lines, 13 filesdep +containersPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

API changes (from Hackage documentation)

+ FileLocation: err' :: Q Exp
+ FileLocation: indx :: Q Exp
+ FileLocation: indxShow :: Q Exp

Files

Control/Exception/FileLocation.hs view
@@ -16,13 +16,13 @@ thrwIO = do   loc <- qLocation   let locStr = locationToString loc-  [|(\mkEx -> throwIO (mkEx locStr))|]+  [|(\_mkEx -> throwIO (_mkEx locStr))|]  thrwsIO :: String -> Q Exp thrwsIO errMsg = do   loc <- qLocation   let locStr = locationToString loc-  [|(\mkEx -> throwIO (mkEx (locStr ++ " " ++ errMsg)))|]+  [|(\_mkEx -> throwIO (_mkEx (locStr ++ " " ++ errMsg)))|]  {- usually want to make a located vesion of a function rather than use this.  - perhaps it could be used to quickly make a located version
Debug/FileLocation.hs view
@@ -16,7 +16,7 @@ dbg = do   loc <- qLocation   let pre = "DEBUG: " ++ (locationToString loc)-  [|(\x -> ltrace pre x)|]+  [|(\_x -> ltrace pre _x)|]  -- | TH version  of Debug.Trace.trace that prints a value and a message -- prefix.@@ -24,7 +24,7 @@ dbgMsg msg = do   loc <- qLocation   let pre = "DEBUG: " ++ (locationToString loc) ++ ' ' : msg-  [|(\x -> ltrace pre x)|]+  [|(\_x -> ltrace pre _x)|]  -- | A TH version of Debug.Trace.trace that prints location information trc :: String -> Q Exp@@ -38,4 +38,4 @@ dbgM = do   loc <- qLocation   let prefix = "DEBUG: " ++ (locationToString loc) ++ " "-  [|(\x -> ltraceM (prefix ++ show x) x)|]+  [|(\_x -> ltraceM (prefix ++ show _x) _x)|]
Debug/Util.hs view
@@ -1,5 +1,5 @@--- | functions that help you with debugging.--- Most would make sense in the Debug.Trace module+-- | Functions that help you with debugging.+-- Most would make sense in the Debug.Trace module. module Debug.Util    (debug, debugM, debugMsg, debugMsgIf, ltrace, ltraceM, strace, traceId)   where@@ -21,26 +21,31 @@ debugMsgIf :: Show a => String -> (a -> Bool) -> a -> a debugMsgIf msg cond x = if cond x then ltrace ("DEBUG: " ++ msg) x else x --- | monadic debug - like debug, but works as a standalone line in a monad+-- | Monadic debug - like debug, but works as a standalone line in a monad.+-- -- TODO: TH version with error loaction info debugM :: (Monad m, Show a) => a -> m a debugM a = debug a `seq` return a --- | trace (print on stdout at runtime) a showable expression--- like debug, but does not print "DEBUG: "--- traceId is an alias for strace--- strace stands for "show trace"--- traceId means it returns itself after tracing like the id function-strace, traceId :: Show a => a -> a+-- | Trace (print on stderr at runtime) a showable expression+-- like 'debug', but do not print \"DEBUG: \".+--+-- \"strace\" stands for \"show trace\".+strace :: Show a => a -> a strace a = trace (show a) a +-- Alias for 'strace'.+--+-- \"traceId\" means it returns itself after tracing like the 'id' function.+traceId :: Show a => a -> a traceId = strace --- | labelled trace - like strace, with a label prepended+-- | Labelled trace - like 'strace', but with a label prepended. ltrace :: Show a => String -> a -> a ltrace l a = trace (l ++ ": " ++ show a) a --- | monadic debug - like debug, but works as a standalone line in a monad+-- | Monadic debug - like debug, but works as a standalone line in a monad.+-- -- TODO: TH version with error loaction info ltraceM :: (Monad m, Show a) => String -> a -> m a ltraceM str a = ltrace str a `seq` return a
FileLocation.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TemplateHaskell #-} -- | see Debug.FileLocation module for more definitions module FileLocation-  ( err, undef, fromJst, fromRht+  ( err, err', undef, fromJst, fromRht, indx, indxShow   , debug, debugM, debugMsg, debugMsgIf, dbg, dbgMsg, trc, ltrace, ltraceM, strace   , locationToString   , thrwIO, thrwsIO@@ -14,10 +14,13 @@ import Control.Exception.FileLocation (thrwIO, thrwsIO) import Debug.Trace (trace) import Language.Haskell.TH.Syntax+import Language.Haskell.TH(varE)+import Data.Maybe(fromMaybe)+import qualified Data.Map as M (lookup) --- | like Prelude.error, but gives the file location+-- | Like Prelude.error, but gives the file location. ----- > $(err "OH NO!)+-- > $(err "OH NO!") -- > main:Main main.hs:4:10 OH NO! err :: String -> Q Exp err str = do@@ -25,10 +28,20 @@   let prefix = (locationToString loc) ++ " "   [|error (prefix ++ str)|] --- | like Prelude.undefined, but gives the file location--- use trace to output the location.--- this way we still use undefined instead of calling error+-- | Like 'err', but the error message (to be appended to the location) is an argument of the generated expression. --+-- > $(err) "OH NO!"+-- > main:Main main.hs:4:10 OH NO!+err' :: Q Exp+err' = do+  loc <- qLocation+  let prefix = (locationToString loc) ++ " "+  [| error . (prefix ++) |]++-- | Like Prelude.undefined, but gives the file location.+--+-- Uses trace to output the location (this way we still use undefined instead of calling error).+-- -- > $(undef) -- > main:Main main.hs:4:10 undefined -- > err: Prelude.undefined@@ -38,20 +51,43 @@   let prefix = (locationToString loc) ++ " "   [|trace (prefix ++ "undefined") undefined|] --- | like fromJust, but also shows the file location+-- | Like 'fromJust', but also shows the file location. fromJst :: Q Exp fromJst = do   loc <- qLocation   let msg = (locationToString loc) ++ " fromJst: Nothing"-  [|\m -> case m of-            Just v -> v+  [|\_m -> case _m of+            Just _v -> _v             Nothing -> error msg|] --- | like fromRight, but also show the file location+-- | Like 'fromRight', but also show the file location. fromRht :: Q Exp fromRht = do   loc <- qLocation   let msg = (locationToString loc) ++ " fromRht: Left: "-  [|\m -> case m of-            Right v -> v-            Left e -> error (msg ++ show e)|]+  [|\_m -> case _m of+            Right _v -> _v+            Left _e -> error (msg ++ show _e)|]++-- | Like @(flip ('Data.Map.!')@, but also shows the file location in case the element isn't found.+indx :: Q Exp+indx = indx_common False++-- | Like 'indx', but also 'show's the looked-up element in case it isn't found.+indxShow :: Q Exp+indxShow = indx_common True++indx_common :: Bool -> Q Exp+indx_common = indxWith_common [| M.lookup |]++indxWith_common :: Q Exp -> Bool -> Q Exp+indxWith_common lookupE showElt = do+  loc <- qLocation+  let msg = (locationToString loc) ++ " indx: Element not in the map"++      msgE varName = if showElt+                        then [| msg ++ ": " ++ show $(varE varName) |]+                        else [| msg |]+++  [| \_x _m -> fromMaybe (error $(msgE '_x)) ($(lookupE) _x _m) |]
file-location.cabal view
@@ -1,5 +1,5 @@ Name:                file-location-Version:             0.4.2+Version:             0.4.3 Synopsis:            common functions that show file location information Homepage:            https://github.com/gregwebs/FileLocation.hs License:             BSD3@@ -10,39 +10,53 @@ Build-type:          Simple Cabal-version:       >=1.6 Description: -    Common debugging/error/exception functions that give file location information+    Common debugging\/error\/exception functions that give file location information     .-    > $(err "OH NO!")-    >-    > main:Main main.hs:16:1 OH NO!+    @+    $(err \"OH NO!\")+       +    main:Main main.hs:16:1 OH NO!+    @     .     Notice how it displays package:module file:line:character+    .     It exposes the functions err (error), undef (undefined), and trc (Debug.Trace.trace). All of these behave the same as their normal counterpart but also spit out a location.     .     Here is my favorite helper, debug, which is like trace but just show the value.     .-    > debug [1,2,3]-    >-    > DEBUG: [1,2,3]-    > [1,2,3]+    @+    debug [1,2,3]+    +    DEBUG: [1,2,3]+    [1,2,3]+    @     .     And The Template Haskell version.     .-    > $(dbg) [1,2,3]-    >-    > DEBUG main:Main main.hs:1:3 [1,2,3]-    > [1,2,3]+    @+    $(dbg) [1,2,3]+    +    DEBUG main:Main main.hs:1:3 [1,2,3]+    [1,2,3]+    @     .     Also there is a version of thrwIO that gives location information-    > ($(thrwIO) $ AException) `catch` \e -> putStrLn ("Caught " ++ show (e :: AException))-    >-    > Caught AException "main:Main test/main.hs:25:6"     .+    @+    ($(thrwIO) $ AException) `catch` \e -> putStrLn (\"Caught \" ++ show (e :: AException))+    +    Caught AException \"main:Main test/main.hs:25:6\"+    @+    .     See module for a listing of all the functions with short descriptions, and the homepage for some more examples https://github.com/gregwebs/ErrorLocation.hs -Source-Repository head-  type: git-  location:    https://github.com/gregwebs/FileLocation.hs+extra-source-files:+    test/*.sh+    test/*.hs+    test/*.shelltest+    test/bench/*.hs+    test/bench/*.md+    test/bench/*.h  Library   Exposed-modules: FileLocation,@@ -55,4 +69,8 @@   Build-depends:  base >= 4 && < 5                 , template-haskell                 , transformers     >= 0.2 && < 0.3+                , containers +Source-Repository head+  type: git+  location:    https://github.com/gregwebs/FileLocation.hs
+ test/bench/bench.hs view
@@ -0,0 +1,13 @@+import Criterion.Main++import qualified System.Process as Proc++-- NOT IN USE!++readProcess ""+ main = defaultMain [+        bgroup "fib" [ bench "10" $ +                     , bench "35" $ whnf fib 35+                     , bench "37" $ whnf fib 37+                     ]+                    ]
+ test/bench/bench.md view
@@ -0,0 +1,33 @@+A benchmarking attempt to compare CPP macros to template haskell functions.+A very simple macro- add file and line number information to an error function.++    cpp: FATAL ERROR: Oh no!AT: cpp.hs:7++    hs: main:Main hs.hs:7:5 Oh no!++# Running++## running the CPP file++    rm -f cpp cpp.o cpp.hi && time ghc --make -O2 cpp.hs++## running the hs file++    rm -f hs hs.o hs.hi && time ghc --make -O2 hs.hs++# Comparison++These are difficutl to compare directly to eachother. Template haskell requires dependencies that take time to link- dependencies you probably already have in your application. So instead we compare the times of calling one macro/TH function versus calling 26.++This benching was good enough for me that I didn't feel the need to actually use Criterion.++Data:++    CPP 1    CPP 30    HS 1     HS 30+    -------  -------  -------  -------+    .35-.37  .43-.46  .57-.59  .61-.64++Results++CPP line macros appear to take more time to compile than Error-Location TH functions.+It is still possible that there is more per-file invocation overead for TH than CPP (that this benchmark ignrores), even if you are already using TH in your application.
+ test/bench/consts.h view
@@ -0,0 +1,16 @@+#define LOGLEVEL DEBUG+#define LOG_NAME "server"+#define LOG(p) liftIO . Log.logM LOG_NAME Log.p $ \+  (( __BASE_FILE__ ++ ":" ++ show ( __LINE__ :: Int ) ++ ":") ++)++#define _UNDEF error ( "UNDEFINED AT: " ++ __FILE__ ++ ":" ++ show (__LINE__ :: Int) )+#define _ERROR(msg) error ( "FATAL ERROR: " ++ msg ++ "AT: " ++ __FILE__ ++ ":" ++ show (__LINE__ :: Int) )+#define _THROW(e) Control.throwIO $ e $ "AT: " ++ __FILE__ ++ ":" ++ show ( __LINE__ :: Int)+#define _THROWS(e,s) (( LOG(ERROR) (show (e (s)) ) ) >> (Control.throwIO $ e $ (s) ++ " AT: " ++ __FILE__ ++":" ++ show ( __LINE__ :: Int) ))++#if GHC7+#define HAMLET hamlet+#else+#define HAMLET $hamlet+#endif+
+ test/bench/cpp.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE CPP, TemplateHaskell #-}+-- import FileLocation+#include "consts.h"++main = do+    -- $(undef) -- make sure this also loads TH for a different comparison+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")+  _ERROR("Oh no!")
+ test/bench/hs.hs view
@@ -0,0 +1,7 @@+{-# LANGUAGE CPP, TemplateHaskell #-}+import FileLocation+#include "consts.h"++main = do+  -- $(undef)+  $(err "Oh no!")
+ test/file-location.shelltest view
@@ -0,0 +1,24 @@++./test/main+>>>+[1,2,3]+Caught AException "main:Main test/main.hs:25:4"+Caught AException "main:Main test/main.hs:26:6 doh!"+Caught main:Main test/main.hs:27:4 fromJst: Nothing+Caught main:Main test/main.hs:28:4 fromRht: Left: "Lefty"+Caught Prelude.undefined+>>>2+TRACE: main:Main test/main.hs:22:84 trc+DEBUG: debugMsgIf: [1,2,3]+DEBUG: [1,2,3]+DEBUG: main:Main test/main.hs:22:67: [1,2,3]+DEBUG: Msg plain: [1,2,3]+DEBUG: main:Main test/main.hs:22:23 Msg TH: [1,2,3]+traceM: [1,2,3]+DEBUG: [1,2,3]+main:Main test/main.hs:29:3 undefined+main: main:Main test/main.hs:30:5 Oh no!+>>>= 1++rm ./test/main ./test/main.hi ./test/main.o+>>>= 0
+ test/main.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE TemplateHaskell, DeriveDataTypeable  #-}++import Data.Data (Data, Typeable)+import FileLocation+import Control.Exception.Base (SomeException, Exception(..))+import Prelude hiding (catch)+import Control.Exception.Control (catch)+++++data AException = AException String+     deriving (Show, Typeable)++instance Exception AException++++main = do+  let _ = debugMsgIf "Not Visble" id False+  let x = debugMsgIf "debugMsgIf" (\xs -> head xs == 1) [1,2,3]+  putStrLn . show $ $(dbgMsg "Msg TH") $ debugMsg "Msg plain" $ $(dbg) $ debug $ $(trc "trc") x+  ltraceM "traceM" x+  debugM x+  ($thrwIO AException) `catch` \e -> putStrLn ("Caught " ++ show (e :: AException))+  ($(thrwsIO "doh!") AException) `catch` \e -> putStrLn ("Caught " ++ show (e :: AException))+  ($fromJst Nothing) `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeException))+  ($fromRht (Left "Lefty")) `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeException))+  $undef `catch` \e -> putStrLn ("Caught " ++ show (e :: SomeException))+  $(err "Oh no!")
+ test/run.sh view
@@ -0,0 +1,2 @@+#!/bin/bash -x+ghc --make test/main.hs && shelltest test/file-location.shelltest