module Curry.RunTimeSystem (
  module Curry.RunTimeSystem.BaseCurry,
  module Curry.RunTimeSystem
  ) where
import System.IO
import Curry.RunTimeSystem.BaseCurry
import System.IO.Unsafe
import Data.IORef
nfCTC :: (BaseCurry a,BaseCurry b) => (b -> Result a) -> b -> Result a
nfCTC cont = ctcStore False (nf cont)
hnfCTC :: (BaseCurry a,BaseCurry b) => (b -> Result a) -> b -> Result a 
hnfCTC = ctcStore False 
gnfCTC :: (BaseCurry a,BaseCurry b) => (b -> Result a) -> b -> Result a
gnfCTC cont = ctcStore True (gnf cont)
ghnfCTC :: (BaseCurry a,BaseCurry b) => (b -> Result a) -> b -> Result a 
ghnfCTC = ctcStore True
patternFail :: (BaseCurry a,BaseCurry b) => String -> a -> b
patternFail s x = case consKind x of
  Failed -> addException (curryError s) x
  _      -> failed (PatternMatchFail s)
withRef :: (Int -> a) -> Int -> a 
withRef f 0 = f 0
withRef f i = f $! nextRef i
storeRefCounter :: IORef Int
storeRefCounter = unsafePerformIO (newIORef 1)
nextRef :: Int -> Int 
nextRef i = unsafePerformIO (do 
               v <- readIORef storeRefCounter
               writeIORef storeRefCounter (v+i+1)
               return v)
data RunTimeOptions = RTO {currentModule :: String}
runTimeDefaults :: RunTimeOptions
runTimeDefaults = RTO {currentModule = ""} 
runTimeOptions :: IORef RunTimeOptions
runTimeOptions = unsafePerformIO (newIORef runTimeDefaults)
setRunTimeOptions :: RunTimeOptions -> IO ()
setRunTimeOptions = writeIORef runTimeOptions 
freeF :: (BaseCurry b, BaseCurry a) => (b -> a) -> a
freeF = freeOrBased
orF :: BaseCurry a => a -> a -> a
orF = orCTC
setProgName :: String -> IO ()
setProgName n = do 
  opts <- readIORef runTimeOptions
  writeIORef runTimeOptions (opts{currentModule=n})
setProgNameAndOrBased :: String -> IO ()
setProgNameAndOrBased = setProgName
getProgName :: IO String
getProgName = readIORef runTimeOptions >>= return . currentModule
orCTC :: BaseCurry a => a -> a -> a
orCTC x y = branching (mkRefWithGenInfo NoGenerator (nextRef 0)) [x,y]
freeOrBased :: (BaseCurry b, BaseCurry a) => (b -> a) -> a
freeOrBased f = f (generator (nextRef 0))
ten,eleven,zero :: Int
ten    = 10
eleven = 11
zero   = 0
readQualified :: String -> String -> String -> [((),String)]
readQualified mod name r =  [((),s)  | (name',s)  <- lex r, name' == name] 
                         ++ [((),s3) | (mod',s1)  <- lex r
                                     , mod' == mod
                                     , (".",s2)   <- lex s1
                                     , (name',s3) <- lex s2
                                     , name' == name]