Are they implementation details? As you said in another thread, pragmas are not
something the compiler can discard and still get the same thing implemented
differently as they are in other languages. I can understad the drive for
consistency however.
There is a way to implement this in a way that is even more consistent however.
Making pragmas operate on their current scope like so:
proc foo(x: int): string =
+[exportc: "int3_tostring"]
...
Run
That way its obvious what file level pragmas are. They are _inside_ the file,
therefore they belong to the _scope_ of the file.
The inline syntax would be clear in meaning too:
foo(callback = proc() = +[closure, gcsafe] echo "baa")
Run
The rule is simple: apply to current scope. As things stand, pragmas that are a
part of the function signature (but not the function content) apply to a
function, while pragmas that are a part of the file _contents_ apply to the
file.
And the improvement in readability is still quite significant I feel. Compare:
proc foo(x: int): string =
+[exportc: "int3_tostring"]
...
# or
proc foo(x: int): string =
+[exportc: "int3_tostring"]
...
# vs.
proc foo(x: int): string {.exportc: "int3_tostring.} =
...
# or
proc foo(x: int): string
{.exportc: "int3_tostring.} =
...
Run
If anyone is skimming through a file, I doubt the last two options win out,
especially as the number of arguments grows. Placing pragmas above is still
better IMHO, and expressiveness is above elegance in the nim priority list, but
ultimately you are the BDFL.