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.


deprecated pragma
-----------------

The deprecated pragma is used to mark a symbol as deprecated:

.. code-block:: nimrod
  proc p() {.deprecated.}
  var x {.deprecated.}: char

It can also be used as a statement. Then it takes a list of *renamings*. The
upcoming ``nimfix`` tool can automatically update the code and perform these
renamings:

.. code-block:: nimrod
  type
    File = object
    Stream = ref object
  {.deprecated: [TFile: File, PStream: Stream].}


noSideEffect pragma
-------------------
The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
effects. This means that the proc/iterator only changes locations that are
reachable from its parameters and the return value only depends on the
arguments. If none of its parameters have the type ``var T``
or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static
error to mark a proc/iterator to have no side effect if the compiler cannot
verify this.

As a special semantic rule, the built-in `debugEcho <system.html#debugEcho>`_
pretends to be free of side effects, so that it can be used for debugging
routines marked as ``noSideEffect``.

**Future directions**: ``func`` may become a keyword and syntactic sugar for a
proc with no side effects:

.. code-block:: nim
  func `+` (x, y: int): int


destructor pragma
-----------------

The ``destructor`` pragma is used to mark a proc to act as a type destructor.
Its usage is deprecated, use the ``override`` pragma instead.
See `type bound operations`_.


override pragma
---------------

See `type bound operations`_ instead.

procvar pragma
--------------
The ``procvar`` pragma is used to mark a proc that it can be passed to a
procedural variable.


compileTime pragma
------------------
The ``compileTime`` pragma is used to mark a proc to be used at compile
time only. No code will be generated for it. Compile time procs are useful
as helpers for macros.


noReturn pragma
---------------
The ``noreturn`` pragma is used to mark a proc that never returns. 


acyclic pragma
--------------
The ``acyclic`` pragma can be used for object types to mark them as acyclic
even though they seem to be cyclic. This is an **optimization** for the garbage
collector to not consider objects of this type as part of a cycle:

.. code-block:: nim
  type
    PNode = ref TNode
    TNode {.acyclic, final.} = object
      left, right: PNode
      data: string

In the example a tree structure is declared with the ``TNode`` type. Note that
the type definition is recursive and the GC has to assume that objects of
this type may form a cyclic graph. The ``acyclic`` pragma passes the
information that this cannot happen to the GC. If the programmer uses the
``acyclic`` pragma for data types that are in reality cyclic, the GC may leak
memory, but nothing worse happens.

**Future directions**: The ``acyclic`` pragma may become a property of a
``ref`` type:

.. code-block:: nim
  type
    PNode = acyclic ref TNode
    TNode = object
      left, right: PNode
      data: string


final pragma
------------
The ``final`` pragma can be used for an object type to specify that it
cannot be inherited from.


shallow pragma
--------------
The ``shallow`` pragma affects the semantics of a type: The compiler is
allowed to make a shallow copy. This can cause serious semantic issues and
break memory safety! However, it can speed up assignments considerably, 
because the semantics of Nim require deep copying of sequences and strings. 
This can be expensive, especially if sequences are used to build a tree
structure: 

.. code-block:: nim
  type
    TNodeKind = enum nkLeaf, nkInner
    TNode {.final, shallow.} = object
      case kind: TNodeKind
      of nkLeaf: 
        strVal: string
      of nkInner: 
        children: seq[TNode]


pure pragma
-----------
An object type can be marked with the ``pure`` pragma so that its type 
field which is used for runtime type identification is omitted. This used to be
necessary for binary compatibility with other compiled languages.

An enum type can be marked as ``pure``. Then access of its fields always
requires full qualification.


asmNoStackFrame pragma
----------------------
A proc can be marked with the ``AsmNoStackFrame`` pragma to tell the compiler
it should not generate a stack frame for the proc. There are also no exit
statements like ``return result;`` generated and the generated C function is
declared as ``__declspec(naked)`` or ``__attribute__((naked))`` (depending on
the used C compiler).

**Note**: This pragma should only be used by procs which consist solely of
assembler statements.

error pragma
------------
The ``error`` pragma is used to make the compiler output an error message
with the given content. Compilation does not necessarily abort after an error
though. 

The ``error`` pragma can also be used to
annotate a symbol (like an iterator or proc). The *usage* of the symbol then
triggers a compile-time error. This is especially useful to rule out that some
operation is valid due to overloading and type conversions: 

.. code-block:: nim
  ## check that underlying int values are compared and not the pointers:
  proc `==`(x, y: ptr int): bool {.error.}


fatal pragma
------------
The ``fatal`` pragma is used to make the compiler output an error message
with the given content. In contrast to the ``error`` pragma, compilation
is guaranteed to be aborted by this pragma. Example:

.. code-block:: nim
  when not defined(objc):
    {.fatal: "Compile this program with the objc command!".}

warning pragma
--------------
The ``warning`` pragma is used to make the compiler output a warning message
with the given content. Compilation continues after the warning.

hint pragma
-----------
The ``hint`` pragma is used to make the compiler output a hint message with
the given content. Compilation continues after the hint.

line pragma
-----------
The ``line`` pragma can be used to affect line information of the annotated
statement as seen in stack backtraces:

.. code-block:: nim
  
  template myassert*(cond: expr, msg = "") =
    if not cond:
      # change run-time line information of the 'raise' statement:
      {.line: InstantiationInfo().}:
        raise newException(EAssertionFailed, msg)

If the ``line`` pragma is used with a parameter, the parameter needs be a
``tuple[filename: string, line: int]``. If it is used without a parameter,
``system.InstantiationInfo()`` is used.


linearScanEnd pragma
--------------------
The ``linearScanEnd`` pragma can be used to tell the compiler how to 
compile a Nim `case`:idx: statement. Syntactically it has to be used as a
statement:

.. code-block:: nim
  case myInt
  of 0: 
    echo "most common case"
  of 1: 
    {.linearScanEnd.}
    echo "second most common case"
  of 2: echo "unlikely: use branch table"
  else: echo "unlikely too: use branch table for ", myInt

In the example, the case branches ``0`` and ``1`` are much more common than 
the other cases. Therefore the generated assembler code should test for these 
values first, so that the CPU's branch predictor has a good chance to succeed 
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
stall. 

The ``linearScanEnd`` pragma should be put into the last branch that should be
tested against via linear scanning. If put into the last branch of the
whole ``case`` statement, the whole ``case`` statement uses linear scanning.


computedGoto pragma
-------------------
The ``computedGoto`` pragma can be used to tell the compiler how to 
compile a Nim `case`:idx: in a ``while true`` statement. 
Syntactically it has to be used as a statement inside the loop:

.. code-block:: nim

  type
    MyEnum = enum
      enumA, enumB, enumC, enumD, enumE

  proc vm() =
    var instructions: array [0..100, MyEnum]
    instructions[2] = enumC
    instructions[3] = enumD
    instructions[4] = enumA
    instructions[5] = enumD
    instructions[6] = enumC
    instructions[7] = enumA
    instructions[8] = enumB

    instructions[12] = enumE
    var pc = 0
    while true:
      {.computedGoto.}
      let instr = instructions[pc]
      case instr
      of enumA:
        echo "yeah A"
      of enumC, enumD:
        echo "yeah CD"
      of enumB:
        echo "yeah B"
      of enumE:
        break
      inc(pc)
    
  vm()

As the example shows ``computedGoto`` is mostly useful for interpreters. If
the underlying backend (C compiler) does not support the computed goto 
extension the pragma is simply ignored.


unroll pragma
-------------
The ``unroll`` pragma can be used to tell the compiler that it should unroll
a `for`:idx: or `while`:idx: loop for runtime efficiency: 

.. code-block:: nim
  proc searchChar(s: string, c: char): int = 
    for i in 0 .. s.high:
      {.unroll: 4.}
      if s[i] == c: return i
    result = -1

In the above example, the search loop is unrolled by a factor 4. The unroll
factor can be left out too; the compiler then chooses an appropriate unroll
factor.

**Note**: Currently the compiler recognizes but ignores this pragma.


immediate pragma
----------------

See `Ordinary vs immediate templates`_.


compilation option pragmas
--------------------------
The listed pragmas here can be used to override the code generation options
for a proc/method/converter.

The implementation currently provides the following possible options (various
others may be added later).

===============  ===============  ============================================
pragma           allowed values   description
===============  ===============  ============================================
checks           on|off           Turns the code generation for all runtime
                                  checks on or off.
boundChecks      on|off           Turns the code generation for array bound
                                  checks on or off.
overflowChecks   on|off           Turns the code generation for over- or
                                  underflow checks on or off.
nilChecks        on|off           Turns the code generation for nil pointer
                                  checks on or off.
assertions       on|off           Turns the code generation for assertions
                                  on or off.
warnings         on|off           Turns the warning messages of the compiler
                                  on or off.
hints            on|off           Turns the hint messages of the compiler
                                  on or off.
optimization     none|speed|size  Optimize the code for speed or size, or
                                  disable optimization.
patterns         on|off           Turns the term rewriting templates/macros
                                  on or off.
callconv         cdecl|...        Specifies the default calling convention for
                                  all procedures (and procedure types) that
                                  follow.
===============  ===============  ============================================

Example:

.. code-block:: nim
  {.checks: off, optimization: speed.}
  # compile without runtime checks and optimize for speed


push and pop pragmas
--------------------
The `push/pop`:idx: pragmas are very similar to the option directive,
but are used to override the settings temporarily. Example:

.. code-block:: nim
  {.push checks: off.}
  # compile this section without runtime checks as it is
  # speed critical
  # ... some code ...
  {.pop.} # restore old settings


register pragma
---------------
The ``register`` pragma is for variables only. It declares the variable as
``register``, giving the compiler a hint that the variable should be placed
in a hardware register for faster access. C compilers usually ignore this
though and for good reasons: Often they do a better job without it anyway.

In highly specific cases (a dispatch loop of an bytecode interpreter for
example) it may provide benefits, though.


global pragma
-------------
The ``global`` pragma can be applied to a variable within a proc to instruct
the compiler to store it in a global location and initialize it once at program
startup.

.. code-block:: nim
  proc isHexNumber(s: string): bool =
    var pattern {.global.} = re"[0-9a-fA-F]+"
    result = s.match(pattern)

When used within a generic proc, a separate unique global variable will be
created for each instantiation of the proc. The order of initialization of
the created global variables within a module is not defined, but all of them
will be initialized after any top-level variables in their originating module
and before any variable in a module that imports it.

deadCodeElim pragma
-------------------
The ``deadCodeElim`` pragma only applies to whole modules: It tells the
compiler to activate (or deactivate) dead code elimination for the module the
pragma appears in.

The ``--deadCodeElim:on`` command line switch has the same effect as marking
every module with ``{.deadCodeElim:on}``. However, for some modules such as
the GTK wrapper it makes sense to *always* turn on dead code elimination -
no matter if it is globally active or not.

Example:

.. code-block:: nim
  {.deadCodeElim: on.}


..
  NoForward pragma
  ----------------
  The ``noforward`` pragma can be used to turn on and off a special compilation
  mode that to large extent eliminates the need for forward declarations. In this
  mode, the proc definitions may appear out of order and the compiler will postpone
  their semantic analysis and compilation until it actually needs to generate code
  using the definitions. In this regard, this mode is similar to the modus operandi
  of dynamic scripting languages, where the function calls are not resolved until
  the code is executed. Here is the detailed algorithm taken by the compiler:

  1. When a callable symbol is first encountered, the compiler will only note the
  symbol callable name and it will add it to the appropriate overload set in the
  current scope. At this step, it won't try to resolve any of the type expressions
  used in the signature of the symbol (so they can refer to other not yet defined
  symbols).

  2. When a top level call is encountered (usually at the very end of the module),
  the compiler will try to determine the actual types of all of the symbols in the
  matching overload set. This is a potentially recursive process as the signatures
  of the symbols may include other call expressions, whoose types will be resolved
  at this point too.

  3. Finally, after the best overload is picked, the compiler will start compiling
  the body of the respective symbol. This in turn will lead the compiler to discover
  more call expresions that need to be resolved and steps 2 and 3 will be repeated
  as necessary.

  Please note that if a callable symbol is never used in this scenario, its body
  will never be compiled. This is the default behavior leading to best compilation
  times, but if exhaustive compilation of all definitions is required, using 
  ``nim check`` provides this option as well.

  Example:

  .. code-block:: nim

    {.noforward: on.}

    proc foo(x: int) =
      bar x

    proc bar(x: int) =
      echo x

    foo(10)


pragma pragma
-------------

The ``pragma`` pragma can be used to declare user defined pragmas. This is 
useful because Nim's templates and macros do not affect pragmas. User 
defined pragmas are in a different module-wide scope than all other symbols. 
They cannot be imported from a module.

Example:

.. code-block:: nim
  when appType == "lib":
    {.pragma: rtl, exportc, dynlib, cdecl.}
  else:
    {.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
    
  proc p*(a, b: int): int {.rtl.} = 
    result = a+b

In the example a new pragma named ``rtl`` is introduced that either imports
a symbol from a dynamic library or exports the symbol for dynamic library
generation.


Disabling certain messages
--------------------------
Nim generates some warnings and hints ("line too long") that may annoy the
user. A mechanism for disabling certain messages is provided: Each hint
and warning message contains a symbol in brackets. This is the message's
identifier that can be used to enable or disable it:

.. code-block:: Nim
  {.hint[LineTooLong]: off.} # turn off the hint about too long lines

This is often better than disabling all warnings at once.


experimental pragma
-------------------

The ``experimental`` pragma enables experimental language features. Depending
on the concrete feature this means that the feature is either considered
too unstable for an otherwise stable release or that the future of the feature
is uncertain (it may be removed any time).

Example:

.. code-block:: nim
  {.experimental.}

  proc useUsing(dest: var string) =
    using dest
    add "foo"
    add "bar"

