I have the following Haskell file that contains a CPP macro.
#define FOO( x, y ) x ++ y
foo =
FOO("a",
"b"
++ "c")
bar = 1
When I call cpphs on this file, I get the following result.
#line 1 "Test.hs"
foo =
"a" ++ "b"
++ "c"
bar = 1
The line directive states that the line that is following the directive is line 1 of Test.hs. Therefore, foo is still positioned at line 3 while bar is now positioned at line 7, while it has been in line 8 in the original file. It looks like all whitespace tokens after the comma and before the first non-whitespace token are dropped, which loses the original line break. I have the following questions.
- Is this an expected behavior?
- Is there any option that I overlooked to insert a line directive to correctly fix the location of
bar? - Is there any other preprocessor that would preserve the location of
barby using a line directive or some other means?
I am not able to change the content of the file in any way.
EDIT:
To answer 3. myself, it looks like clang and gcc add additional line directives as I would have expected for cpphs as well. They yield the following output.
# 1 "<stdin>"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 417 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "<stdin>" 2
foo =
"a" ++
# 4 "<stdin>"
"b"
# 4 "<stdin>"
++ "c"
bar = 1
The additional line directives correctly pin bar to line 8 of the file.
EDIT:
To answer 1. myself, as long as I do not miss some option that fixes this behavior, it looks like it is not an expected behavior.
If I use the following variant of the example module
#define FOO( x, y ) x ++ y
foo =
FOO( "a",
"b"
++ "c"
)
bar :: String
bar = 1
and invoke ghc -cpp -pgmP cpphs -optP --cpp Test.hs I get the following error.
Test.hs:9:7: error:
• No instance for (Num String) arising from the literal ‘1’
• In the expression: 1
In an equation for ‘bar’: bar = 1
|
9 |
| ^
That is, using cpphs GHC is not able to correctly display the position of the type error.
"a" ++ "b" ++ "c". Moreover, it joins blank lines. So, this is unexpected in the C standard.barin the original file from the preprocessed file.