inline-c 0.9.1.4 → 0.9.1.5
raw patch · 5 files changed
+54/−41 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Language.C.Types.Parse: Template :: CIdentifier -> [TypeSpecifier] -> TypeSpecifier
+ Language.C.Types.Parse: Template :: CIdentifier -> [[TypeSpecifier]] -> TypeSpecifier
Files
- changelog.md +1/−0
- inline-c.cabal +1/−1
- src/Language/C/Types.hs +39/−35
- src/Language/C/Types/Parse.hs +9/−5
- test/Language/C/Inline/ContextSpec.hs +4/−0
changelog.md view
@@ -1,3 +1,4 @@+- 0.9.1.5: Support multi-token types in C++ template arguments, see issue #125 and PR #126. - 0.9.1.4: Support GHC 8.10, including better C++ flags handling, see PR #121. - 0.9.1.3: Work around spurious test failures, see PR #118. - 0.9.1.2: Update haddock for `Language.C.Inline.Interruptible.pure`.
inline-c.cabal view
@@ -1,5 +1,5 @@ name: inline-c-version: 0.9.1.4+version: 0.9.1.5 synopsis: Write Haskell source files including C code inline. No FFI required. description: See <https://github.com/fpco/inline-c/blob/master/README.md>. license: MIT
src/Language/C/Types.hs view
@@ -179,37 +179,43 @@ P.TypeSpecifier x -> modify $ \(a, b, c, d) -> (a, x:b, c, d) P.TypeQualifier x -> modify $ \(a, b, c, d) -> (a, b, x:c, d) P.FunctionSpecifier x -> modify $ \(a, b, c, d) -> (a, b, c, x:d)- -- Split data type and specifiers- let (dataTypes, specs) =- partition (\x -> not (x `elem` [P.SIGNED, P.UNSIGNED, P.LONG, P.SHORT])) pTySpecs- let illegalSpecifiers s = failConversion $ IllegalSpecifiers s specs- -- Find out sign, if present- mbSign0 <- case filter (== P.SIGNED) specs of- [] -> return Nothing- [_] -> return $ Just Signed- _:_ -> illegalSpecifiers "conflicting/duplicate sign information"- mbSign <- case (mbSign0, filter (== P.UNSIGNED) specs) of- (Nothing, []) -> return Nothing- (Nothing, [_]) -> return $ Just Unsigned- (Just b, []) -> return $ Just b- _ -> illegalSpecifiers "conflicting/duplicate sign information"- let sign = fromMaybe Signed mbSign- -- Find out length- let longs = length $ filter (== P.LONG) specs- let shorts = length $ filter (== P.SHORT) specs- when (longs > 0 && shorts > 0) $ illegalSpecifiers "both long and short"- -- Find out data type- dataType <- case dataTypes of- [x] -> return x- [] | longs > 0 || shorts > 0 -> return P.INT- [] -> failConversion $ NoDataTypes declSpecs- _:_ -> failConversion $ MultipleDataTypes declSpecs- -- Check if things are compatible with one another- let checkNoSpecs =- unless (null specs) $ illegalSpecifiers "expecting no specifiers"- let checkNoLength =- when (longs > 0 || shorts > 0) $ illegalSpecifiers "unexpected long/short"- let type2type dat = case dat of+ tySpec <- type2type pTySpecs+ return (Specifiers pStorage pTyQuals pFunSpecs, tySpec)+ where+ type2type pTySpecs = do+ -- Split data type and specifiers+ let (dataTypes, specs) =+ partition (\x -> not (x `elem` [P.SIGNED, P.UNSIGNED, P.LONG, P.SHORT])) pTySpecs+ let illegalSpecifiers s = failConversion $ IllegalSpecifiers s specs+ -- Find out sign, if present+ mbSign0 <- case filter (== P.SIGNED) specs of+ [] -> return Nothing+ [_] -> return $ Just Signed+ _:_ -> illegalSpecifiers "conflicting/duplicate sign information"+ mbSign <- case (mbSign0, filter (== P.UNSIGNED) specs) of+ (Nothing, []) -> return Nothing+ (Nothing, [_]) -> return $ Just Unsigned+ (Just b, []) -> return $ Just b+ _ -> illegalSpecifiers "conflicting/duplicate sign information"+ let sign = fromMaybe Signed mbSign+ -- Find out length+ let longs = length $ filter (== P.LONG) specs+ let shorts = length $ filter (== P.SHORT) specs+ when (longs > 0 && shorts > 0) $ illegalSpecifiers "both long and short"+ -- Find out data type+ dataType <- case dataTypes of+ [x] -> return x+ [] | mbSign0 == Just Signed -> return P.INT -- "The Case of 'signed' not including 'signed int'"+ [] | mbSign == Just Unsigned -> return P.INT -- "The Case of 'unsigned' not including 'unsigned int'"+ [] | longs > 0 || shorts > 0 -> return P.INT+ [] -> failConversion $ NoDataTypes declSpecs+ _:_ -> failConversion $ MultipleDataTypes declSpecs+ -- Check if things are compatible with one another+ let checkNoSpecs =+ unless (null specs) $ illegalSpecifiers "expecting no specifiers"+ let checkNoLength =+ when (longs > 0 || shorts > 0) $ illegalSpecifiers "unexpected long/short"+ case dataType of P.Template s args -> do checkNoSpecs args' <- forM args type2type@@ -219,7 +225,7 @@ return $ TemplateConst s P.TemplatePointer s -> do checkNoSpecs- s' <- type2type s+ s' <- type2type [s] return $ TemplatePointer s' P.TypeName s -> do checkNoSpecs@@ -260,8 +266,6 @@ return Double _ -> do error $ "untangleDeclarationSpecifiers impossible: " ++ show dataType- tySpec <- type2type dataType- return (Specifiers pStorage pTyQuals pFunSpecs, tySpec) untangleDeclarator :: forall i. Type i -> P.Declarator i -> Either UntangleErr (i, Type i)@@ -409,7 +413,7 @@ TypeName s -> [P.TypeName s] Struct s -> [P.Struct s] Enum s -> [P.Enum s]- Template s types -> [P.Template s (concat (map pTySpecs types))]+ Template s types -> [P.Template s (map pTySpecs types)] TemplateConst s -> [P.TemplateConst s] TemplatePointer type' -> [P.TemplatePointer (head (pTySpecs type'))] in map P.StorageClassSpecifier storages ++
src/Language/C/Types/Parse.hs view
@@ -298,7 +298,7 @@ | Struct CIdentifier | Enum CIdentifier | TypeName CIdentifier- | Template CIdentifier [TypeSpecifier]+ | Template CIdentifier [[TypeSpecifier]] | TemplateConst String | TemplatePointer TypeSpecifier deriving (Typeable, Eq, Show)@@ -380,14 +380,14 @@ cidentParserWithNamespace = try (concat <$> sequence [cidentParser, (string "::"), cidentParserWithNamespace]) <|> cidentParser- templateArgType = try ((TemplatePointer <$> (type_specifier)) <* (string "*")) <|> try type_specifier <|> (TemplateConst <$> (many $ oneOf ['0'..'9']))+ templateArgType = try ((TemplatePointer <$> (type_specifier)) <* (string "*")) <|> try type_specifier <|> (TemplateConst <$> (some $ oneOf ['0'..'9'])) templateArgParser' = do- t <- templateArgType+ t <- some (token templateArgType) _ <- string "," tt <- templateArgParser return $ t:tt templateArgParser =- try (templateArgParser') <|> ((:) <$> templateArgType <*> return [])+ try (templateArgParser') <|> ((:) <$> some (token templateArgType) <*> return []) template_parser :: CParser i m => m TypeSpecifier template_parser = try $ templateParser cIdentStyle <?> "template name"@@ -563,7 +563,11 @@ Struct x -> "struct" <+> pretty x Enum x -> "enum" <+> pretty x TypeName x -> pretty x- Template x args -> pretty x <+> "<" <+> mconcat (intersperse "," (map pretty args)) <+> ">"+ Template x args ->+ -- This code generates a c++ code of "template-identifier<template-argument1,template-argument2,..>" like "std::vector<int>".+ -- concat_with_space is used to concat multiple terms like "unsigned int".+ let concat_with_space = mconcat . (intersperse " ") . (map pretty)+ in pretty x <+> "<" <+> mconcat (intersperse "," (map concat_with_space args)) <+> ">" TemplateConst x -> pretty x TemplatePointer x -> pretty x <+> "*"
test/Language/C/Inline/ContextSpec.hs view
@@ -41,6 +41,10 @@ shouldBeType (cty "bool") [t| CBool |] Hspec.it "converts void" $ do shouldBeType (cty "void") [t| () |]+ Hspec.it "converts signed" $ do+ shouldBeType (cty "signed") [t| CInt |]+ Hspec.it "converts unsigned" $ do+ shouldBeType (cty "unsigned") [t| CUInt |] Hspec.it "converts standard library types (1)" $ do shouldBeType (cty "FILE") [t| CFile |] Hspec.it "converts standard library types (2)" $ do