on master help sign in
Pattern matching on strings, big integers and characters
commit29c67e9ff2411141a864af0eaa783a25947900d3 authorEdwin Brady <ecb10@st-andrews.ac.uk> dateWed 31 Oct 2012, 21:17 (14 years ago) parenta52bb30
7 files changed+70−13
CHANGELOG+5 rts/idris_gmp.c+5 rts/idris_gmp.h+2 src/Core/CaseTree.hs+1−1 src/IRTS/CodegenC.hs+38−7 src/IRTS/Compiler.hs+17−4 src/Idris/Parser.hs+2−1
CHANGELOG+5
@@ -9,8 +9,13 @@ User visible changes:
99 elaborating their definitions
1010* Implicit arguments will be added automatically only if their initial
1111 letter is lower case, or they are in a using declaration
12+* Pattern matching on strings, big integers and characters
1213* Added System.Concurrency modules
1314
15+Internal changes:
16+
17+* Separate inlining methods at compile-time and run-time
18+
1419New in 0.9.5:
1520-------------
1621
rts/idris_gmp.c+5
@@ -174,6 +174,11 @@ VAL idris_bigDivide(VM* vm, VAL x, VAL y) {
174174 }
175175}
176176
177+int bigEqConst(VAL x, int c) {
178+ if (ISINT(x)) { return (GETINT(x) == c); }
179+ else { return mpz_cmp_si(GETMPZ(x), c); }
180+}
181+
177182VAL bigEq(VM* vm, VAL x, VAL y) {
178183 return MKINT((i_int)(mpz_cmp(GETMPZ(x), GETMPZ(y)) == 0));
179184}
rts/idris_gmp.h+2
@@ -11,6 +11,8 @@ VAL idris_bigMinus(VM*, VAL x, VAL y);
1111VAL idris_bigTimes(VM*, VAL x, VAL y);
1212VAL idris_bigDivide(VM*, VAL x, VAL y);
1313
14+int bigEqConst(VAL x, int c);
15+
1416VAL idris_bigEq(VM*, VAL x, VAL y);
1517VAL idris_bigLt(VM*, VAL x, VAL y);
1618VAL idris_bigLe(VM*, VAL x, VAL y);
src/Core/CaseTree.hs+1−1
@@ -217,7 +217,7 @@ toPat tc tms = evalState (mapM (\x -> toPat' x []) tms) []
217217 else do put (n : ns)
218218 return (PV n)
219219 toPat' (App f a) args = toPat' f (a : args)
220− toPat' (Constant x@(I _)) [] = return $ PConst x
220+ toPat' (Constant x) [] = return $ PConst x
221221 toPat' _ _ = return PAny
222222
223223
src/IRTS/CodegenC.hs+38−7
@@ -54,7 +54,8 @@ codegenC dump defs out exec incs objs libs dbg
5454 when (exit /= ExitSuccess) $
5555 putStrLn ("FAILURE: " ++ gcc)
5656
57−headers [] = "#include <idris_rts.h>\n#include <idris_stdfgn.h>\n#include <assert.h>\n"
57+headers [] = "#include <idris_rts.h>\n#include <idris_stdfgn.h>\n" ++
58+ "#include <gmp.h>\n#include <assert.h>\n"
5859headers (x : xs) = "#include <" ++ x ++ ">\n" ++ headers xs
5960
6061debug TRACE = "#define IDRIS_TRACE\n\n"
@@ -127,16 +128,46 @@ bcc i (CASE r code def)
127128 showDef i (Just c) = indent i ++ "default:\n"
128129 ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
129130bcc i (CONSTCASE r code def)
130− = indent i ++ "switch(GETINT(" ++ creg r ++ ")) {\n" ++
131− concatMap (showCase i) code ++
132− showDef i def ++
133− indent i ++ "}\n"
131+ | intConsts code
132+ = indent i ++ "switch(GETINT(" ++ creg r ++ ")) {\n" ++
133+ concatMap (showCase i) code ++
134+ showDef i def ++
135+ indent i ++ "}\n"
136+ | strConsts code
137+ = concatMap (strCase ("GETSTR(" ++ creg r ++ ")")) code ++
138+ indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
139+ | bigintConsts code
140+ = concatMap (biCase (creg r)) code ++
141+ indent i ++ "{\n" ++ showDefS i def ++ indent i ++ "}\n"
142+ | otherwise = error $ "Can't happen: Can't compile const case " ++ show code
134143 where
144+ intConsts ((I _, _ ) : _) = True
145+ intConsts ((Ch _, _ ) : _) = True
146+ intConsts _ = False
147+
148+ bigintConsts ((BI _, _ ) : _) = True
149+ bigintConsts _ = False
150+
151+ strConsts ((Str _, _ ) : _) = True
152+ strConsts _ = False
153+
154+ strCase sv (s, bc) =
155+ indent i ++ "if (strcmp(" ++ sv ++ ", " ++ show s ++ ") == 0) {\n" ++
156+ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
157+ biCase bv (BI b, bc) =
158+ indent i ++ "if (bigEqConst(" ++ bv ++ ", " ++ show b ++ ")) {\n"
159+ ++ concatMap (bcc (i+1)) bc ++ indent i ++ "} else\n"
160+
135161 showCase i (t, bc) = indent i ++ "case " ++ show t ++ ":\n"
136− ++ concatMap (bcc (i+1)) bc ++ indent (i + 1) ++ "break;\n"
162+ ++ concatMap (bcc (i+1)) bc ++
163+ indent (i + 1) ++ "break;\n"
137164 showDef i Nothing = ""
138165 showDef i (Just c) = indent i ++ "default:\n"
139− ++ concatMap (bcc (i+1)) c ++ indent (i + 1) ++ "break;\n"
166+ ++ concatMap (bcc (i+1)) c ++
167+ indent (i + 1) ++ "break;\n"
168+ showDefS i Nothing = ""
169+ showDefS i (Just c) = concatMap (bcc (i+1)) c
170+
140171bcc i (CALL n) = indent i ++ "CALL(" ++ cname n ++ ");\n"
141172bcc i (TAILCALL n) = indent i ++ "TAILCALL(" ++ cname n ++ ");\n"
142173bcc i (SLIDE n) = indent i ++ "SLIDE(vm, " ++ show n ++ ");\n"
src/IRTS/Compiler.hs+17−4
@@ -268,15 +268,28 @@ instance ToIR SC where
268268 mkIRAlt (ConCase n t args rhs)
269269 = do rhs' <- ir rhs
270270 return $ LConCase (-1) n args rhs'
271− mkIRAlt (ConstCase (I i) rhs)
271+ mkIRAlt (ConstCase x rhs)
272+ | matchable x
272273 = do rhs' <- ir rhs
273− return $ LConstCase (I i) rhs'
274− mkIRAlt (ConstCase IType rhs)
274+ return $ LConstCase x rhs'
275+ | matchableTy x
275276 = do rhs' <- ir rhs
276277 return $ LDefaultCase rhs'
277278 mkIRAlt (ConstCase c rhs)
278− = fail $ "Can only pattern match on integer constants (" ++ show c ++ ")"
279+ = fail $ "Can't match on (" ++ show c ++ ")"
279280 mkIRAlt (DefaultCase rhs)
280281 = do rhs' <- ir rhs
281282 return $ LDefaultCase rhs'
282283
284+ matchable (I _) = True
285+ matchable (BI _) = True
286+ matchable (Ch _) = True
287+ matchable (Str _) = True
288+ matchable _ = False
289+
290+ matchableTy IType = True
291+ matchableTy BIType = True
292+ matchableTy ChType = True
293+ matchableTy StrType = True
294+ matchableTy _ = False
295+
src/Idris/Parser.hs+2−1
@@ -751,7 +751,8 @@ modifyConst :: SyntaxInfo -> FC -> PTerm -> PTerm
751751modifyConst syn fc (PConstant (I x))
752752 | not (inPattern syn)
753753 = PApp fc (PRef fc (UN "fromInteger")) [pexp (PConstant (I x))]
754− | otherwise = PConstant (I x)
754+ | otherwise = PAlternative False
755+ [PConstant (I x), PConstant (BI (toEnum x))]
755756modifyConst syn fc x = x
756757
757758pList syn = do lchar '['; fc <- pfc; xs <- sepBy (pExpr syn) (lchar ','); lchar ']'