packages feed

KiCS-prophecy-0.1.0: Curry/Module/Oracle.curry

--- Provides the interface that is used to generate and send events.
---
--- @version Feb, 2007
---
module Oracle (
  Ref, 

  partCons, partFunc, partCall,
  apply, ($!) ,($!!), ($#), ($##), (>>=),
  compose, unknown,

  oracle, oracleIO,

  fresh, replace, collapse, closeRef, expand

  )where

import IOExts (getAssoc)
import CEventOracle
import qualified Meta
import qualified Unsafe (unsafePerformIO)
--import Global

--extFileName :: Global String
--extFileName = global "" Temporary

infixr 0 $!, $!!, $#, $##

--- Wrapper for constructor with one missing argument.
--  We have to close the reference here, since
--  a value is constructed
partCons :: (a -> b) -> Ref -> a -> b
partCons c r x = closeRef r (c x)
-- partCons c r = collapse r c

--- Wrapper for function with one missing argument.
--  We should not count a step here, since
--  the wrapper is not part of the original program.
partFunc :: (a -> Ref -> b) -> Ref -> a -> b
partFunc f r x = f x r

--- Wrapper for call with more than one missing argument.
partCall :: a -> Ref -> a
partCall x r = closeRef r x

--- Wrapper for apply function.
apply :: (Ref -> a -> b) -> a -> Ref -> b
apply f x r = CEventOracle.apply f x r

--- Wrapper for hnf apply function.
($!) :: (Ref -> a -> b) -> a -> Ref -> b
(f $! x) r = (f CEventOracle.$! x) r 

--- Wrapper for nf apply function.
($!!) :: (Ref -> a -> b) -> a -> Ref -> b
($!!) f x r = (f CEventOracle.$!! x) r 

--- Wrapper for ghnf apply function.
($#) :: (Ref -> a -> b) -> a -> Ref -> b
($#) f x r = (f CEventOracle.$# x) r 

--- Wrapper for gnf apply function.
($##) :: (Ref -> a -> b) -> a -> Ref -> b
($##) f x r = (f CEventOracle.$## x) r 

headNormalFormIO :: (Ref -> a -> Ref -> () -> IO b) -> a -> Ref -> Ref -> () -> IO b
headNormalFormIO f x r = error "headNormalFormIO"

prim_unsafePerformIO :: (Ref -> () -> IO a) -> Ref -> a
prim_unsafePerformIO act ref = replace ref (Unsafe.unsafePerformIO (act ref ()))


lambda_world :: IO a -> Ref -> () -> IO a
lambda_world act ref _ = collapse ref act

--- Wrapper for bind in io monad
(>>=) :: (Ref -> () -> IO a) -> (Ref -> a -> Ref -> () -> IO b) -> Ref -> Ref -> () -> IO b
(>>=) act cont ref = collapse ref (partFunc (bind act cont))

bind :: (Ref -> () -> IO a) -> (Ref -> a -> Ref -> () -> IO b) -> () -> Ref -> IO b
bind act cont world ref = 
  let ref2 = fresh () 
   in expand ref [ref2] (apply act world ref Prelude.>>= bind2 cont world ref2)

bind2 :: (Ref -> a -> Ref -> () -> IO b) -> () -> Ref -> a -> IO b 
bind2 cont world ref2 x =
      let ref3 = fresh () 
       in expand ref2 [ref3] (apply (apply cont x ref2) world ref3)

-- catchFail is also an external higher order function
catchFail :: (Ref -> () -> IO a) -> (Ref -> () -> IO a) -> Ref -> Ref -> () -> IO a
catchFail act1 act2 ref = 
  collapse ref (partFunc (catch act1 act2))

catch :: (Ref -> () -> IO a) -> (Ref -> () -> IO a) -> () -> Ref -> IO a
catch act1 act2 world ref = let ref' = fresh () in
  expand ref [ref'] 
    (Prelude.catchFail 
      (apply act1 world ref  Prelude.>>= return . (,) True)
      (apply act2 world ref' Prelude.>>= return . (,) False) Prelude.>>=
      \ (b,res) -> safeIOResult (return b) >> return res)
    

--- Function composition (Prelude version may be transformed)
compose :: (b -> c) -> (a -> b) -> a -> c
compose f g x = f (g x)

--- Computes the oracle for a computation. 
oracle :: (Ref -> a) -> IO ()
oracle expr = initialize (return . expr)

oracleIO :: (Ref -> Ref -> () -> IO a) -> IO ()
oracleIO app = initialize (\ mainR -> 
  let appRef = fresh () 
   in expand mainR [appRef] (app mainR appRef ()))


safeIOResult :: IO a -> IO a
safeIOResult act = do 
  Just fn <- getAssoc "extfn"
  x <- act
  let sx = show x
  appendFile fn (show (length sx)++'\n':sx)
  return x


unknown :: Ref -> a
unknown r = CEventOracle.unknown r