packages feed

idris-0.1.7: lib/string.idr

include "list.idr";

strLen: String -> Int; [inline]
strLen str = __strlen str;

strEq: String -> String -> Bool; [inline]
strEq s1 s2 = __strEq s1 s2;

charEq : Char -> Char -> Bool; [inline]
charEq c1 c2 = __charToInt c1 == __charToInt c2;

concat: String -> String -> String; [inline]
concat s1 s2 = __concat s1 s2;

strNull: String -> Bool; [inline]
strNull s = strEq s "";

strHead: String -> Maybe Char; [inline]
strHead s = if (strNull s) then Nothing else (Just (__strHead s));

strTail: String -> Maybe String; [inline]
strTail s = if (strNull s) then Nothing else (Just (__strTail s));

strRev : String -> String; [inline]
strRev s = __strRev s;

substr : String -> Int -> Int -> String; [inline]
substr s start len = __substr s start len;

strFind : String -> Char -> Int; [inline]
strFind s c = __strFind s c;

strSplit : Char -> String -> (String & String);
strSplit c str = let idx = strFind str c in
	 if (idx == (-1)) then (str, "") else
	 (substr str 0 idx, substr str (idx+1) (strLen str - (idx+1)));

-- Some more, faster, string manipulations

strHead' : (x:String) -> (so (not (strNull x))) -> Char;
strHead' x p = __strHead x;

strTail' : (x:String) -> (so (not (strNull x))) -> String;
strTail' x p = __strTail x;

strCons: Char -> String -> String; [inline]
strCons c s = __strCons c s;

strUncons: String -> Maybe (Char & String); [inline]
strUncons s with (strHead s, strTail s) {
  | (Just h,  Just t)  = Just (h, t);
  | (Nothing, Nothing) = Nothing;
}

{-- A view of strings, for better, faster, pattern matching --}

data StrM : String -> Set where
   StrNil : StrM ""
 | StrCons : (x:Char) -> (xs:String) -> StrM (strCons x xs);

strM : (x:String) -> StrM x;
strM x with choose (strNull x) {
   | Left p ?= StrCons (strHead' x p) (strTail' x p);     [strMleft]
   | Right p ?= StrNil;                                   [strMright]
}

strMright proof {
  %intro;
  %believe value; -- it's a primitive operation, we have to believe it!
  %qed;
};

strMleft proof {
  %intro;
  %believe value; -- it's a primitive operation, we have to believe it!
  %qed;
};


charAt: Int -> String -> Maybe Char; [inline]
charAt x str =
  if (strLen str > x && x >= 0) then (Just (__strgetIdx str x))
                                else Nothing;

showInt: Int -> String; [inline]
showInt x = __toString x;

readInt: String -> Maybe Int;
readInt str = let x = __toInt str
              in  if (strEq str (showInt x))
                     then (Just x)
                     else Nothing;

showNat: Nat -> String;
showNat n = __toString (natToInt n);

readNat: String -> Maybe Nat;
readNat str with readInt str {
  | Just x  = if (x >= 0) then (Just (intToNat x)) else Nothing;
  | Nothing = Nothing;
}

showFloat: Float -> String;
showFloat n = __floatToString n;

strToList: String -> List Char;
strToList s with strUncons s {
  | Just (h, t) = Cons h (strToList t);
  | Nothing     = Nil;
}

listToStr: List Char -> String;
listToStr = foldr strCons "";

-- TODO if the change to the parser breaks things, the sigma pattern will
--      need parens around
strToVect: String -> (n ** Vect Char n);
strToVect s with strUncons s {
    | Just (c, cs) with strToVect cs {
    | <| cs' |> = <| c :: cs' |>;
  }
  | Nothing      = <| VNil |>;
}

vectToStr: Vect Char n -> String;
vectToStr (h :: t) = strCons h (vectToStr t);
vectToStr VNil     = "";


data StrCmp = StrLT | StrEQ | StrGT;
strCmp: String -> String -> StrCmp;
strCmp s t =
  if      (__strLT s t) then StrLT
  else if (strEq s t)   then StrEQ
  else                       StrGT;

strSpan' : (Char -> Bool) -> String -> String -> (String & String);
strSpan' p str acc with strM str {
  strSpan' p "" acc | StrNil 
         = (strRev acc, "");
  strSpan' p (strCons c cs) acc | StrCons _ _
         = if (p c) then (strSpan' p cs (strCons c acc))
    	      	    else (strRev acc, (strCons c cs));
}

strSpan : (Char -> Bool) -> String -> (String & String);
strSpan p str = strSpan' p str "";

-- TODO: A collection of these in a Char library.

isSpace : Char -> Bool;
isSpace ' ' = True;
isSpace '\t' = True;
isSpace '\r' = True;
isSpace '\n' = True;
isSpace _ = False;

isNL : Char -> Bool;
isNL '\r' = True;
isNL '\n' = True;
isNL _ = False;

isAlpha : Char -> Bool;
isAlpha x = let a = __charToInt 'a' in
            let z = __charToInt 'z' in
            let A = __charToInt 'A' in
            let Z = __charToInt 'Z' in
	    let x' = __charToInt x in
	    (x' >= a && x' <= z) || (x' >= A && x' <= Z);

isDigit : Char -> Bool;
isDigit x = let a = __charToInt '0' in
            let z = __charToInt '9' in
	    let x' = __charToInt x in
	    (x' >= a && x' <= z);

words : String -> List String;
words str with (strSpan (not . isSpace) str) {
   | ("", "") = Nil;
   | (word, rest) with choose (strNull rest) {
       | Left rp with choose (strNull word) {
         | Left wp = Cons word (words (strTail' rest rp));
         | Right wp = words (strTail' rest rp);
         }
       | Right rp = Cons word Nil;
   }
}

lines : String -> List String;
lines str with (strSpan (not . isNL) str) {
   | ("", "") = Nil;
   | (line, rest) with choose (strNull rest) {
       | Left rp with choose (strNull line) {
         | Left wp = Cons line (lines (strTail' rest rp));
         | Right wp = lines (strTail' rest rp);
         }
       | Right rp = Cons line Nil;
   }
}

-- Generic version of lines/words

splitBy : (Char -> Bool) -> String -> List String;
splitBy p str with (strSpan (not . p) str) {
   | ("", "") = Nil;
   | (word, rest) with choose (strNull rest) {
       | Left rp with choose (strNull word) {
         | Left wp = Cons word (splitBy p (strTail' rest rp));
         | Right wp = splitBy p (strTail' rest rp);
         }
       | Right rp = Cons word Nil;
   }
}

unlines : List String -> String;
unlines Nil = "";
unlines (Cons x xs) = x ++ "\n" ++ unlines xs;

unwords : List String -> String;
unwords Nil = "";
unwords (Cons x Nil) = x;
unwords (Cons x xs) = x ++ " " ++ unwords xs;

trimLeft : String -> String;
trimLeft str with (strSpan isSpace str) {
   | (spcs, rest) = rest;
}

trimRight : String -> String;
trimRight x = strRev (trimLeft (strRev x));

trim : String -> String;
trim x = trimLeft (strRev (trimLeft (strRev x)));

mapStr : (Char -> Char) -> String -> String;
mapStr f str with strM str {
 mapStr f ""             | StrNil      = "";
 mapStr f (strCons c cs) | StrCons _ _ = strCons (f c) (mapStr f cs);
}

toLower : Char -> Char;
toLower x = let xi = __charToInt x in
	    let Ai = __charToInt 'A' in
	    let ai = __charToInt 'a' in
	    let Zi = __charToInt 'Z' in
	    if (xi>=Ai && xi<=Zi) then (__intToChar (xi+ai-Ai)) else x;