I'm discovering Nim and I'm in the learning phase reading the documentation. I'm impressed by the language that combines elegance and power, without sacrificing security. But I've strange feeling regarding the use of pragmas in Nim. This preamble is to justify my naive view of the language and the following comment.
According to the [documentation](http://nim-lang.org/docs/manual.html#pragmas), "Pragmas are Nim's method to give the compiler additional information / commands without introducing a massive number of new keywords. Pragmas are processed on the fly during semantic checking. Pragmas are enclosed in the special `{.` and `.}` curly brackets. Pragmas are also often used as a first implementation to play with a language feature before a nicer syntax to access the feature becomes available." So one can see pragmas in Nim as temporary syntax before definite language syntax but also as compiler directives. And according to [Wikipedia](https://en.wikipedia.org/wiki/Directive_\(programming\)), "Directives are not part of the grammar of a programming language, and may vary from compiler to compiler". Analyzing how pragmas are used in Nim, from the documentation and some source files from the compiler, I can extract the following taxonomy: * Nim Pragmas * Pure pragmas: hints to the compiler/linker with no semantic effects on the source code. A different compiler could decide to not support the pragma and give the same results. [`noInit, requiresInit, deprecated, noReturn, acyclic, shallow...`] * Semantic or syntax effects pragmas: these don't respect the pragma rule (no side semantic effect to the source code) * Syntax pragmas: Change the semantic of the source code. The compiler **must** respect these pragmas. * Core language [`global, discardable, borrow, raises, tags, compileTime, ...`] * OOP [`final, base, inheritable, ...`] * Concurrency [`thread, threadvar, guard, locks, ...`] * Templates * Foreign language interfaces [`union, packed, importC, exportC, importCpp, importObjC...`] * Debug [`breakpoint, watchpoint, debugger, profiler...`] For instance, why introduce `{.pure.}` with enums to require full qualification? If the compiler does not respect the pragma, there are syntax errors in the code. Typing and naming should be enough to avoid enums names clashes. Another example with `{.procvar.}` used to qualify a proc that can be passed to a procedural variable. This should be the default or the compiler should deduce it from analyze of the source, shouldn't it? Or the `{.global.}` to qualify a global variable or `{.borrow.}` to borrow code from overloaded proc. An important set of pragmas is used for foreign functions interfaces, importing headers or injecting code. Why not define a domain specific sublanguage to manage this? I suspect that this pragmas abuse is related to the fact that a macro statement can be called using a pragma. That's a simpler way to extend the language syntax without touching the compiler and doing tests. But this large amount of semantic pragmas is breaking the simplicity of the language. And one can't always replace a pragma by a macro statement: compileTime: proc compile(code: string): NimNode = is not a replacement for proc compile(code: string): {.compileTime.} NimNode = and gives a syntax error... There are 11488 lines containing pragmas of all kinds in the compiler for 199605 non-empty lines, meaning that almost 6% contain pragmas. For comparison, comments represent 19%. So pragmas have a big place in the language. Am I misunderstanding how pragmas are used in Nim? Is there a model logic behind all these pragmas? And will these "syntax" pragmas replaced by language keywords before version 1.0? Thanks \-- Pierre
