1

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.

  1. Is this an expected behavior?
  2. Is there any option that I overlooked to insert a line directive to correctly fix the location of bar?
  3. Is there any other preprocessor that would preserve the location of bar by 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.

4
  • "While foo is still positioned in line 3" - I see the foo is on the line 4. Commented Nov 29, 2024 at 20:59
  • Sorry, the word "positioned" is misleading here. The line directive resets the line count. Ich have edited the question to clarify this aspect. Commented Nov 30, 2024 at 5:58
  • Why is that important? It smells like the XY-problem. A real C preprocessor expands macros into single lines and you would get "a" ++ "b" ++ "c". Moreover, it joins blank lines. So, this is unexpected in the C standard. Commented Nov 30, 2024 at 19:24
  • I would like to highlight identifiers in the original source file. The source code positions of these identifiers are extracted from an abstract syntax tree, therefore, I have to preprocess the file first. I was under the impression that line directives are used to correctly identify entities in the original file, therefore, I would have expected, that there is a way to correctly extract the source code position of bar in the original file from the preprocessed file. Commented Nov 30, 2024 at 20:34

1 Answer 1

1

You have to write own simple preprocessor for input files, your pre-processor will insert line directives before each line.

Input:

#define FOO( x, y ) x ++ y

foo =
  FOO("a",
       "b"
       ++ "c")

bar = 1

Output:

#line 1
#define FOO( x, y ) x ++ y
#line 2

#line 3
foo =
#line 4
  FOO("a",
#line 5
       "b"
#line 6
       ++ "c")
#line 7

#line 8
bar = 1

Then this output can be passed to cpphs. You will get what you want but quite verbose.

#line 1 "Test.hs"

#line 2 "Test.hs"

#line 3 "Test.hs"
foo =
#line 4 "Test.hs"
#line 5 "Test.hs"
  "a" ++ "b"
#line 6 "Test.hs"
       ++ "c"
#line 7 "Test.hs"

#line 8 "Test.hs"
bar = 1
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.