Handle tilde expansion in pattern matching (fixes #1769)

This commit is contained in:
Vidar Holen 2020-07-27 18:34:42 -07:00
parent 14e6806092
commit 34885142e7
2 changed files with 25 additions and 17 deletions

View File

@ -463,30 +463,35 @@ data PseudoGlob = PGAny | PGMany | PGChar Char
-- Turn a word into a PG pattern, replacing all unknown/runtime values with -- Turn a word into a PG pattern, replacing all unknown/runtime values with
-- PGMany. -- PGMany.
wordToPseudoGlob :: Token -> [PseudoGlob] wordToPseudoGlob :: Token -> [PseudoGlob]
wordToPseudoGlob word = wordToPseudoGlob = fromMaybe [PGMany] . wordToPseudoGlob' False
simplifyPseudoGlob . concatMap f $ getWordParts word
where
f x = case x of
T_Literal _ s -> map PGChar s
T_SingleQuoted _ s -> map PGChar s
T_Glob _ "?" -> [PGAny]
T_Glob _ ('[':_) -> [PGAny]
_ -> [PGMany]
-- Turn a word into a PG pattern, but only if we can preserve -- Turn a word into a PG pattern, but only if we can preserve
-- exact semantics. -- exact semantics.
wordToExactPseudoGlob :: Token -> Maybe [PseudoGlob] wordToExactPseudoGlob :: Token -> Maybe [PseudoGlob]
wordToExactPseudoGlob word = wordToExactPseudoGlob = wordToPseudoGlob' True
simplifyPseudoGlob . concat <$> mapM f (getWordParts word)
wordToPseudoGlob' :: Bool -> Token -> Maybe [PseudoGlob]
wordToPseudoGlob' exact word =
simplifyPseudoGlob <$> toGlob word
where where
toGlob :: Token -> Maybe [PseudoGlob]
toGlob word =
case word of
T_NormalWord _ (T_Literal _ ('~':str):rest) -> do
guard $ not exact
let this = (PGMany : (map PGChar $ dropWhile (/= '/') str))
tail <- concat <$> (mapM f $ concatMap getWordParts rest)
return $ this ++ tail
_ -> concat <$> (mapM f $ getWordParts word)
f x = case x of f x = case x of
T_Literal _ s -> return $ map PGChar s T_Literal _ s -> return $ map PGChar s
T_SingleQuoted _ s -> return $ map PGChar s T_SingleQuoted _ s -> return $ map PGChar s
T_Glob _ "?" -> return [PGAny] T_Glob _ "?" -> return [PGAny]
T_Glob _ "*" -> return [PGMany] T_Glob _ "*" -> return [PGMany]
_ -> fail "Unknown token type" T_Glob _ ('[':_) | not exact -> return [PGAny]
_ -> if exact then fail "" else return [PGMany]
-- Reorder a PseudoGlob for more efficient matching, e.g. -- Reorder a PseudoGlob for more efficient matching, e.g.
-- f?*?**g -> f??*g -- f?*?**g -> f??*g

View File

@ -1211,6 +1211,9 @@ prop_checkConstantIfs6 = verifyNot checkConstantIfs "[[ a -ot b ]]"
prop_checkConstantIfs7 = verifyNot checkConstantIfs "[ a -nt b ]" prop_checkConstantIfs7 = verifyNot checkConstantIfs "[ a -nt b ]"
prop_checkConstantIfs8 = verifyNot checkConstantIfs "[[ ~foo == '~foo' ]]" prop_checkConstantIfs8 = verifyNot checkConstantIfs "[[ ~foo == '~foo' ]]"
prop_checkConstantIfs9 = verify checkConstantIfs "[[ *.png == [a-z] ]]" prop_checkConstantIfs9 = verify checkConstantIfs "[[ *.png == [a-z] ]]"
prop_checkConstantIfs10 = verifyNot checkConstantIfs "[[ ~me == ~+ ]]"
prop_checkConstantIfs11 = verifyNot checkConstantIfs "[[ ~ == ~+ ]]"
prop_checkConstantIfs12 = verify checkConstantIfs "[[ '~' == x ]]"
checkConstantIfs _ (TC_Binary id typ op lhs rhs) | not isDynamic = checkConstantIfs _ (TC_Binary id typ op lhs rhs) | not isDynamic =
if isConstant lhs && isConstant rhs if isConstant lhs && isConstant rhs
then warn id 2050 "This expression is constant. Did you forget the $ on a variable?" then warn id 2050 "This expression is constant. Did you forget the $ on a variable?"