fpco / inline-c

284 stars 51 forks source link

Blocks returning template types can't refer to any numeric type but "int" #125

Closed phlummox closed 3 years ago

phlummox commented 3 years ago

When using inline-c-cpp and returning a template type from a block, it seems the code responsible for parsing types chokes on any numeric type other than an "int"; it apparently can't handle a "long int", "unsigned int", "short int", "long long", etc.

For instance, the following code

returns_vec_of_long = do
   [C.block| std::vector<long>* {
                 return ( (std::vector<long>*) NULL);
             }
   |] :: IO (Ptr (CppVector CLong))

gives a compilation error message along the lines of:

test.hs:33:3: error:
    - Exception when trying to run compile-time code:
        untangleDeclarationSpecifiers impossible: Template (CIdentifier {unCIdentifier = "std::vector"}) [LONG]
CallStack (from HasCallStack):
  error, called at src/Language/C/Types.hs:262:11 in inline-c-0.9.1.4-5L455evJlNk7IUFiXU89Hr:Language.C.Types

but the same code works if we change the long to int (and correspondingly change the CLong to a CInt).

Minimal-ish working example:

1. Create a Cabal file bogus.cabal.

`bogus.cabal` contents ``` cabal-version: 1.12 name: bogus version: 0.1.0.0 build-type: Simple library exposed-modules: Lib hs-source-dirs: src build-depends: base >=4.7 && <5 , inline-c , inline-c-cpp default-language: Haskell2010 ```

and add a minimal src/Lib.hs file:

module Lib
  where

If using stack (which I am), then you can add a stack.yaml file with the latest versions of inline-c and inline-c-cpp:

`stack.yaml` contents ``` resolver: lts-13.30 # or whatever you like packages: - . extra-deps: - inline-c-cpp-0.4.0.3 - inline-c-0.9.1.4 ```

Build it (e.g. with stack build or cabal new-build).

2. Create a file test.hs:

{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverloadedStrings #-}

module Main where

import qualified Language.C.Inline.Cpp as C
import qualified Language.C.Inline.Context as CC
import qualified Language.C.Types as CT
import           Foreign
import           Foreign.C
import           Data.Monoid

data CppVector a

C.context $
  C.cppCtx
  <>
    C.cppTypePairs [
        ("std::vector" :: CT.CIdentifier, [t|CppVector|])
     ]

C.include "<cstdlib>"
C.include "<vector>"

-- compiles: we can return std::vector<int>*
returns_vec_of_int = do
  [C.block| std::vector<int>* {
                return ( (std::vector<int>*) NULL);
            }
  |] :: IO (Ptr (CppVector CInt))

-- compiles: we can return long*
returns_ptr_to_long = do
  [C.block| long* {
                return ( (long*) NULL);
            }
  |] :: IO (Ptr CLong)

-- compiles: we can return unsigned long*
returns_ptr_to_unsigned_long = do
  [C.block| unsigned long* {
                return ( (unsigned long*) NULL);
            }
  |] :: IO (Ptr CULong)

{-
Fails to compile.

Other types that don't work:

- "long int"
- "short"
- "short int"
- "unsigned"
- "unsigned int"
-}
returns_vec_of_long = do
  [C.block| std::vector<long>* {
                return ( (std::vector<long>*) NULL);
            }
  |] :: IO (Ptr (CppVector CLong))

main = return ()

3. Try to compile it, e.g. with stack ghc -- --make test.hs

Expected result

The file should compile with no errors.

Actual result

Compilation fails, with the error message

[1 of 1] Compiling Main             ( test.hs, test.o )

test.hs:55:3: error:
    • Exception when trying to run compile-time code:
        untangleDeclarationSpecifiers impossible: Template (CIdentifier {unCIdentifier = "std::vector"}) [LONG]
CallStack (from HasCallStack):
  error, called at src/Language/C/Types.hs:262:11 in inline-c-0.9.1.4-5L455evJlNk7IUFiXU89Hr:Language.C.Types
      Code: Language.Haskell.TH.Quote.quoteExp
              C.block
              " std::vector<long>* {\n\
              \                return ( (std::vector<long>*) NULL);\n\
              \            }\n\
              \  "
    • In the quasi-quotation:
        [C.block| std::vector<long>* {
                return ( (std::vector<long>*) NULL);
            }
  |]
   |
55 |   [C.block| std::vector<long>* {

I also tried using the current HEAD of the GitHub repository, and got the same results.

phlummox commented 3 years ago

By the way, I'd be interested to know - is there a quick and easy way of running the parsers in src/Language/C/Types/Parse.hs on a code fragment to see whether and how the code is parsed? I had a very quick look at the file, but it wasn't obvious to me where to start, and unfortunately I couldn't spend too much more time looking. I realize that code will be parsed differently depending on what sort of context it appears in -- but if this is something that could be easily provided, it might save developers some of the time they'd otherwise spend in boiling code down to a minimal example and experimenting with it. (I initially thought problems I was having were due to a templated struct I was using, and it took me a while to establish that that wasn't the issue at all; it was the use of long.)

bitonic commented 3 years ago

@junjihashimoto could you take a look at this?

@phlummox regarding testing the parser, you can use https://hackage.haskell.org/package/inline-c-0.9.1.4/docs/Language-C-Types.html#v:quickCParser to run one of those parsers easily.

phlummox commented 3 years ago

Ah, I missed quickCParser! Many thanks for that.

junjihashimoto commented 3 years ago

The parser for template is here. https://github.com/fpco/inline-c/blob/b37b60f1712b12b43c86493cafb9ac324443d22e/inline-c/src/Language/C/Types/Parse.hs#L383

type_specifier parses each argument like long. It seems that one term is supported, but it does not seem to support multiple terms like long long. https://github.com/fpco/inline-c/blob/b37b60f1712b12b43c86493cafb9ac324443d22e/inline-c/src/Language/C/Types/Parse.hs#L306-L322

junjihashimoto commented 3 years ago

untangleDeclarationSpecifiers's error is around here. https://github.com/fpco/inline-c/blob/b37b60f1712b12b43c86493cafb9ac324443d22e/inline-c/src/Language/C/Types.hs#L212-L262

It may not be just a parser issue.

junjihashimoto commented 3 years ago

I will check the cause of untangleDeclarationSpecifiers's error later.

junjihashimoto commented 3 years ago

I am fixing it like this draft. https://github.com/fpco/inline-c/pull/126

bitonic commented 3 years ago

Released as 0.9.1.5.