packages feed

hpc-tracer-0.3.0: src/AjaxAPI.hs

module AjaxAPI 
       ( module AjaxAPI
       , AjaxCallback
       ) where

import Network.AjaxServer
import Common
import Trace.Hpc.Util (HpcPos, toHpcPos, fromHpcPos)
import Trace.Hpc.Mix  
import qualified Data.JSON as JSON
import Debug.Trace
import Data.Maybe
import Utils

-- The new API

setCounter :: Integer -> AjaxCallback
setCounter counter = 
	  ajaxCallback "setCounter"
	    <@> showWithCommas counter

	    -- Start using Strings, for when we can name threads
setThreadID :: Int -> AjaxCallback
setThreadID tid = 
	  ajaxCallback "setThreadID"
 	    <@> show tid
	    
setEvent :: Event -> AjaxCallback
setEvent event      = ajaxCallback "setEvent" <@> event

------------------------------------------------------------------------------

setTracerState :: TracerState -> [AjaxCallback]
setTracerState state =
  [ setCounter 		$ tracerCounter state
  , setThreadID		$ tracerThreadID state
  , setEvent		$ tracerEvent state
  , setRunning		$ tracerRunning state
  ] ++
    (setBreakPoints	$ tracerBreakPoints state)

setTicked :: Maybe TickBoxInfo -> AjaxCallback
setTicked Nothing       = ajaxCallback "setTicked" <@> JSON.Null
setTicked (Just ticked) = ajaxCallback "setTicked" <@> ticked

setBreakPoints :: BreakPoints -> [AjaxCallback]
setBreakPoints bps = 
  [ ajaxCallback "clearBreakPoints" 
  ] ++ 
  [ setBreakPoint bp 
  | bp <- bps 
  ]

setBreakPoint :: BreakPoint -> AjaxCallback
setBreakPoint bp = ajaxCallback "setBreakPoint2" <@> bp

setBreakPointLights :: [Bool] -> AjaxCallback
setBreakPointLights bps = ajaxCallback "setBreakPointLights" <@> bps

setRunning :: Maybe Direction ->  AjaxCallback
setRunning Nothing         = ajaxCallback "setRunning" <@> "Stopped"
setRunning (Just Forward)  = ajaxCallback "setRunning" <@> "Forward"
setRunning (Just Backward) = ajaxCallback "setRunning" <@> "Backward"

------------------------------------------------------------------------------
--

sendTracerResponse :: TracerResponse -> [AjaxCallback]
sendTracerResponse (TracerStateResponse state) = setGUIState state
sendTracerResponse (MultiResponse responses)   = concatMap sendTracerResponse responses
sendTracerResponse (ModuleListResponse mods)   = [ ajaxCallback "setModules" <@> mods ]
sendTracerResponse (RunResponse count)         = [ ajaxCallback "running" <@> showWithCommas count ]

------------------------------------------------------------------------------

setGUIState :: GUIState -> [AjaxCallback]
setGUIState (GUIState state ticked bps) =
  setTracerState state ++ 
  [setTicked ticked,
  setBreakPointLights bps]

------------------------------------------------------------------------------
-- These encodings have to be respected by the JavaScript.
-- This code is the cannonical specification of encodings.

instance JSON BreakPoint where
  toJSON (AllExceptions)      = JSON.String "AllExceptions"
  toJSON (ThreadChange)       = JSON.String "ThreadChange"
  toJSON (ThreadTermination)  = JSON.String "ThreadTermination"
  toJSON (ThreadChangeTo n)        = JSON.Object $ JSON.fromList 
  	 	    	      	   [ ("tag",JSON.String "ThreadChangeTo")
				   , ("tid", JSON.String $ show n) -- yes, a string
				   ]
  toJSON (CounterAt n)        = JSON.Object $ JSON.fromList 
  	 	    	      	   [ ("tag",JSON.String "CounterAt")
				   , ("count", JSON.String $ showWithCommas n) -- yes, a string
				   ]
  toJSON (TickBox tInfo)  = JSON.Object $ JSON.fromList 
  	 	    	      	   [ ("tag",JSON.String "TickBox")
  	 	    	      	   , ("tickInfo",toJSON tInfo)
				   ]
  toJSON (ReqTickBox mod' id')  = JSON.Object $ JSON.fromList 
  	 	    	      	   [ ("tag",JSON.String "ReqTickBox")
  	 	    	      	   , ("module",JSON.String $ mod')
				   , ("id", JSON.Int $ id')
				   ]
  fromJSON (JSON.String "AllExceptions") = return AllExceptions
  fromJSON (JSON.String "ThreadChange") = return ThreadChange
  fromJSON (JSON.String "ThreadTermination") = return ThreadTermination
  fromJSON (JSON.Object o) = listToMaybe $ catMaybes 
      [ do JSON.String "CounterAt" <- JSON.lookup "tag" o
	   JSON.String n           <- JSON.lookup "count" o
	   () <- trace (show n) $ return ()
	   case reads (filter (/= ',') n)  of
	     [(v,"")] -> return (CounterAt v)
	     _ -> Nothing
      , do JSON.String "ThreadChangeTo" <- JSON.lookup "tag" o
	   JSON.String n                <- JSON.lookup "tid" o
	   () <- trace (show n) $ return ()
	   case reads n of
	     [(v,"")] -> return (ThreadChangeTo v)
	     _ -> Nothing
      , do JSON.String "TickBox"    <- JSON.lookup "tag" o
	   tickInfoJSON             <- JSON.lookup "tickInfo" o

	   tickInfo 	            <- fromJSON tickInfoJSON
	   return $ TickBox tickInfo
      , do JSON.String "ReqTickBox" <- JSON.lookup "tag" o
	   JSON.String mod'          <- JSON.lookup "module" o
	   JSON.Int id'              <- JSON.lookup "id" o
	   return $ ReqTickBox mod' id'
      ]
  fromJSON _ = Nothing


instance JSON TickBoxInfo where
  toJSON (TickBoxInfo mod' loc local_no global_no ty) = JSON.Object $ JSON.fromList 
  		    	      	   [ ("module",   JSON.String mod')
  	 	    	      	   , ("location", toJSON loc)
  	 	    	      	   , ("local",     JSON.Int local_no)
  	 	    	      	   , ("global",   JSON.Int global_no)
				   , ("tickType", toJSON ty)
				   ]

  fromJSON (JSON.Object o) = do
  	   mod'      <- findJSON "module" o
	   loc       <- findJSON "location" o
	   local_no  <- findJSON "local" o
	   global_no <- findJSON "global" o
	   ty        <- findJSON "tickType" o
	   return $ TickBoxInfo mod' loc local_no global_no ty
  fromJSON _ = Nothing

instance JSON HpcPos where 
  toJSON pos = JSON.Object $ JSON.fromList 
  		    	      	   [ ("startLine",JSON.Int startLine)
  	 	    	      	   , ("startCol", JSON.Int startCol)
  	 	    	      	   , ("endLine",  JSON.Int endLine)
				   , ("endCol",   JSON.Int endCol)
				   ]
     where (startLine,startCol,endLine,endCol) = fromHpcPos pos
  fromJSON (JSON.Object o) = do
           startLine <- findJSON "startLine" o
           startCol <- findJSON "startCol" o
           endLine <- findJSON "endLine" o
           endCol <- findJSON "endCol" o
	   return $ toHpcPos (startLine,startCol,endLine,endCol)
  fromJSON _ = Nothing

instance JSON BoxLabel where 
  toJSON (ExpBox False) = JSON.String "ExpBox"
  toJSON (ExpBox True)  = JSON.String "AltBox"
  toJSON (TopLevelBox path) = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",  JSON.String "TopLevelBox")
				   , ("path", toJSON $ path)
				   ]
  toJSON (LocalBox path) = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",  JSON.String "LocalBox")
				   , ("path", toJSON $ path)
				   ]
  toJSON (BinBox GuardBinBox bool) = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",  JSON.String "GuardBinBox")
				   , ("value", toJSON $ bool)
				   ]
  toJSON (BinBox CondBinBox bool) = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",  JSON.String "CondBinBox")
				   , ("value", toJSON $ bool)
				   ]
  toJSON (BinBox QualBinBox bool) = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",  JSON.String "QualBinBox")
				   , ("value", toJSON $ bool)
				   ]
  toJSON _ = error "toJSON"  	 	             

  fromJSON (JSON.String "ExpBox") = return $ ExpBox False
  fromJSON (JSON.String "AltBox") = return $ ExpBox True
  fromJSON (JSON.Object o) = altsJSON 
    [ do "TopLevelBox" <- findJSON "tag" o
         path <- findJSON "path" o
         return $ TopLevelBox path
    , do "LocalBox" <- findJSON "tag" o
         path <- findJSON "path" o
         return $ LocalBox path
    , do "GuardBinBox" <- findJSON "tag" o
         value <- findJSON "value" o
         return $ BinBox GuardBinBox value
    , do "CondBinBox" <- findJSON "tag" o
         value <- findJSON "value" o
         return $ BinBox CondBinBox value
    , do "QualBinBox" <- findJSON "tag" o
         value <- findJSON "value" o
         return $ BinBox QualBinBox value
   ]
  fromJSON _ = error "fromJSON"

instance JSON Event where 
  toJSON (Tick tick)       = JSON.Object $ JSON.fromList 
  	 	      	           [ ("tag",   JSON.String "Tick")
				   , ("tick",  JSON.Int tick)
				   ]
  toJSON (Raise)           = JSON.String "Raise"
  toJSON (ThreadFinished)  = JSON.String "ThreadFinished"
  toJSON (Finished)        = JSON.String "Finished"
  fromJSON _ = error "fromJSON"