packages feed

idris-0.1.4: lib/io.idr

include "list.idr";

-- FAny is to allow C functions to build up Idris data
-- types. Obviously this needs care...

data FType = FUnit | FInt | FStr | FPtr | FAny #;

i_ftype : FType -> #;
i_ftype FInt = Int;
i_ftype FStr = String;
i_ftype FPtr = Ptr;
i_ftype FUnit = ();
i_ftype (FAny ty) = ty;

data ForeignFun = FFun String (List FType) FType;

f_retType : ForeignFun -> FType;
f_retType (FFun nm args ret) = ret;

f_args : ForeignFun -> (List FType);
f_args (FFun nm args ret) = args;

f_name : ForeignFun -> String;
f_name (FFun nm args ret) = nm;

data FArgList : (List FType) -> # where
    fNil : FArgList Nil
  | fCons : {x:FType} -> (fx:i_ftype x) -> (fxs:FArgList xs) ->
			 (FArgList (Cons x xs));

fapp : {xs,ys:List FType} -> 
       (FArgList xs) -> (FArgList ys) -> (FArgList (app xs ys));
fapp fNil fxs = fxs;
fapp (fCons fx fxs) fys = fCons fx (fapp fxs fys);

namespace IO {

  data IO : # -> #;

  data Command : # where
      PutStr : String -> Command
    | GetStr : Command
    | Fork : {A:#} -> A -> Command
    | NewLock : Int -> Command
    | DoLock : Lock -> Command
    | DoUnlock : Lock -> Command
    | NewRef : Command
    | ReadRef : # -> Int -> Command
    | WriteRef : {A:#} -> Int -> A -> Command
    | While : (IO Bool) -> (IO ()) -> Command
    | WhileAcc : {A:#} -> (IO Bool) -> A -> (A -> IO A) -> Command
    | Within : Int -> (IO A) -> (IO A) -> Command
    | IOLift : {A:#} -> (IO A) -> Command 
    | Foreign : (f:ForeignFun) -> 
  	        (args:FArgList (f_args f)) -> Command;

  Response : Command -> #;
  Response (PutStr s) = ();
  Response GetStr = String;
  Response (Fork proc) = ();
  Response (NewLock i) = Lock;
  Response (DoLock l) = ();
  Response (DoUnlock l) = ();
  Response NewRef = Int;
  Response (ReadRef A i) = A;
  Response (WriteRef i val) = ();
  Response (While test body) = ();
  Response (WhileAcc {A} test acc body) = A;
  Response (Within {A} time body failure) = A;
  Response (IOLift {A} f) = A;
  Response (Foreign t args) = i_ftype (f_retType t);


  data IO : # -> # where
     IOReturn : A -> (IO A)
   | IODo : (c:Command) -> ((Response c) -> (IO A)) -> (IO A);

  data IORef A = MkIORef Int;

  bind : (IO a) -> (a -> (IO b)) -> (IO b);
  bind (IOReturn a) k = k a;
  -- bind (IODo (IOLift {A} c) p) k = bind (bind c p) k;
  bind (IODo c p) k = IODo c (\x => (bind (p x) k));
  -- bind (IOError str) k = IOError str;

  ret : a -> IO a;
  ret x = IOReturn x;
}

kbind : (IO a) -> (a -> b) -> (IO b);
kbind (IOReturn a) k = IOReturn (k a);
kbind (IODo c p) k = IODo c (\x => (kbind (p x) k));

while : |(test:IO Bool) -> |(body: IO ()) -> IO ();
while test body = IODo (While test body) (\a => (IOReturn II));

while_accTR : Bool -> 
            |(test:IO Bool) -> acc -> |(body: acc -> IO acc) -> IO acc;

while_acc : |(test:IO Bool) -> acc -> |(body: acc -> IO acc) -> IO acc;
{-
while_acc test acc body = do { test' <- test;
	       	   	       while_accTR test' test acc body; };

while_accTR True test acc body = do { acc' <- body acc;
	    	      	       	      test' <- test;
	       	       	              while_accTR test' test acc' body; };
while_accTR False test acc body = return acc;
-}
while_acc test acc body = IODo (WhileAcc test acc body) (\a => (IOReturn a));

{-
ioReturn : a -> (IO a);
ioReturn x = IOReturn x;
-}

apply : IO (a -> b) -> IO a -> IO b;
apply {a} {b} fn arg = do { f : (a->b) <- fn; -- grr
                            x <- arg;
              		    return (f x); };

data IOException = IOExcept String; 

data IOe : # -> # where
   IOK : (IO A) -> (IOe A)
 | IOError : String -> (IOe A);

{-
catch : (IOe A) -> (IOException -> (IO A)) -> (IO A);
catch (IOK action) = action;
catch (IOError str) handler = handler (IOExcept str);
-}

-- No code for this - only works in compiled code, certainly shouldn't
-- be evaluted in pure code!
unsafePerformIO : (IO A) -> A;

-- get the rts representation of a value
unsafeNative : A -> Ptr;

putStr : String -> (IO ());
putStr str = IODo (PutStr str) (\a => (IOReturn a));

getStr : IO String;
getStr = IODo GetStr (\b => (IOReturn b));

getInt : IO Int;
getInt = do { inp <- getStr;
              let val = __toInt inp;
	      return val; };

putStrLn : String -> (IO ());
putStrLn str = do { putStr str;
		    putStr "\n"; };

fork : |(proc:IO ()) -> (IO ());
fork proc = IODo (Fork proc) (\a => (IOReturn a));

newLock : Int -> (IO Lock);
newLock i = IODo (NewLock i) (\l => (IOReturn l));

lock : Lock -> (IO ());
lock l = IODo (DoLock l) (\a => (IOReturn a));

unlock : Lock -> (IO ());
unlock l = IODo (DoUnlock l) (\a => (IOReturn a));

-- Perform an action within "time" milliseconds, execute failure
-- routine if it doesn't complete

within : Int -> |(action : IO a) -> |(failure : IO a) -> IO a;
within time act fail = IODo (Within time act fail) (\a => (IOReturn a));

newIORefPrim : IO Int;
newIORefPrim = IODo (NewRef) (\i => (IOReturn i));

readIORefPrim : Int -> (IO A);
readIORefPrim {A} i = IODo (ReadRef A i) (\a => (IOReturn a));

writeIORefPrim : Int -> A -> (IO ());
writeIORefPrim {A} i val = IODo (WriteRef {A} i val) (\a => (IOReturn a));

newIORef : A -> (IO (IORef A));
newIORef val = do { i <- newIORefPrim;
		    writeIORefPrim i val;
		    return (MkIORef i);
		  };

readIORef : (IORef A) -> (IO A);
readIORef (MkIORef i) = readIORefPrim i;

writeIORef : (IORef A) -> A -> (IO ());
writeIORef (MkIORef i) val = writeIORefPrim i val;

mkFType' : (List FType) -> FType -> #   %nocg;

mkFType' Nil rt = IO (i_ftype rt);
mkFType' (Cons t ts) rt = #((i_ftype t) -> (mkFType' ts rt));

mkFType : ForeignFun -> #    %nocg;
mkFType (FFun fn args rt) = mkFType' args rt;

mkFDef : String -> (ts:List FType) -> (xs:List FType) -> (FArgList xs) ->
	 (rt:FType) -> (mkFType' ts rt)   %nocg;
mkFDef nm Nil accA fs rt 
   = IODo (Foreign (FFun nm accA rt) fs)
				 (\a => (IOReturn a));
mkFDef nm (Cons t ts) accA fs rt 
   = \x:i_ftype t => mkFDef nm ts (app accA (Cons t Nil)) 
				   (fapp fs (fCons x fNil)) rt;

mkForeign : (f:ForeignFun) -> (mkFType f)   %nocg;
mkForeign (FFun fn args rt) = mkFDef fn args Nil fNil rt;

_isNull = mkForeign (FFun "isNull" (Cons FPtr Nil) FInt) %eval;

isNull : Ptr -> Bool;
isNull ptr = if_then_else ((unsafePerformIO (_isNull ptr))==0) False True;

data File = FHandle Ptr;

_fopen
  = mkForeign (FFun "fileOpen" (Cons FStr (Cons FStr Nil)) FPtr) %eval;
_fclose 
  = mkForeign (FFun "fileClose" (Cons FPtr Nil) FUnit) %eval;
_fread
  = mkForeign (FFun "freadStr" (Cons FPtr Nil) (FAny String)) %eval;
_fwrite
  = mkForeign (FFun "fputStr" (Cons FPtr (Cons FStr Nil)) FUnit) %eval;
_feof
  = mkForeign (FFun "feof" (Cons FPtr Nil) FInt) %eval;

gc_details
  = mkForeign (FFun "epicMemInfo" Nil FUnit) %eval;

gc_collect
  = mkForeign (FFun "epicGC" Nil FUnit) %eval;

fopen : String -> String -> IO File;
fopen str mode = do { h <- _fopen str mode;
		      return (FHandle h); };

fclose : File -> IO ();
fclose (FHandle h) = _fclose h;

fread : File -> IO String;
fread (FHandle h) = _fread h;

fwrite : File -> String -> IO ();
fwrite (FHandle h) str = _fwrite h str;

feof : File -> IO Bool;
feof (FHandle h) = do { eof <- _feof h;
     	      	      	return (not (eof==0)); };

sequence : (List (IO a)) -> (IO (List a));
sequence Nil = return Nil;
sequence (Cons x xs) = do { a <- x;
			    as <- sequence xs;
			    return (Cons a as); };

sleep = mkForeign (FFun "sleep" (Cons FInt Nil) FUnit) %eval;

-- Return time in microseconds since some unspecified starting point

utime = mkForeign (FFun "do_utime" Nil FInt) %eval;