1013 lines
31 KiB
Text
1013 lines
31 KiB
Text
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:: nim
|
|
proc p() {.deprecated.}
|
|
var x {.deprecated.}: char
|
|
|
|
It can also be used as a statement, in that case it takes a list of *renamings*.
|
|
|
|
.. code-block:: nim
|
|
type
|
|
File = object
|
|
Stream = ref object
|
|
{.deprecated: [TFile: File, PStream: Stream].}
|
|
|
|
The ``nimfix`` tool can be used to, without effort, automatically update your
|
|
code and refactor it by performing these renamings.
|
|
|
|
|
|
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, see `type bound operations`_ instead.
|
|
|
|
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 or variable to be used at
|
|
compile time only. No code will be generated for it. Compile time procs are
|
|
useful as helpers for macros. Since version 0.12.0 of the language, a proc
|
|
that uses ``system.NimNode`` within its parameter types is implictly declared
|
|
``compileTime``:
|
|
|
|
.. code-block:: nim
|
|
proc astHelper(n: NimNode): NimNode =
|
|
result = n
|
|
|
|
Is the same as:
|
|
|
|
.. code-block:: nim
|
|
proc astHelper(n: NimNode): NimNode {.compileTime.} =
|
|
result = n
|
|
|
|
|
|
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
|
|
Node = ref NodeObj
|
|
NodeObj {.acyclic, final.} = object
|
|
left, right: Node
|
|
data: string
|
|
|
|
In the example a tree structure is declared with the ``Node`` 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
|
|
Node = acyclic ref NodeObj
|
|
NodeObj = object
|
|
left, right: Node
|
|
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
|
|
NodeKind = enum nkLeaf, nkInner
|
|
Node {.final, shallow.} = object
|
|
case kind: NodeKind
|
|
of nkLeaf:
|
|
strVal: string
|
|
of nkInner:
|
|
children: seq[Node]
|
|
|
|
|
|
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 a 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, whose 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 expressions 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.}
|
|
type
|
|
FooId = distinct int
|
|
BarId = distinct int
|
|
using
|
|
foo: FooId
|
|
bar: BarId
|
|
|
|
proc useUsing(bar, foo) =
|
|
echo "bar is of type BarId"
|
|
echo "foo is of type FooId"
|
|
|
|
|
|
Implementation Specific Pragmas
|
|
===============================
|
|
|
|
This section describes additional pragmas that the current Nim implementation
|
|
supports but which should not be seen as part of the language specification.
|
|
|
|
Bitsize pragma
|
|
--------------
|
|
|
|
The ``bitsize`` pragma is for object field members. It declares the field as
|
|
a bitfield in C/C++.
|
|
|
|
.. code-block:: Nim
|
|
type
|
|
mybitfield = object
|
|
flag {.bitsize:1.}: cuint
|
|
|
|
generates:
|
|
|
|
.. code-block:: C
|
|
struct mybitfield {
|
|
unsigned int flag:1;
|
|
};
|
|
|
|
|
|
Volatile pragma
|
|
---------------
|
|
The ``volatile`` pragma is for variables only. It declares the variable as
|
|
``volatile``, whatever that means in C/C++ (its semantics are not well defined
|
|
in C/C++).
|
|
|
|
**Note**: This pragma will not exist for the LLVM backend.
|
|
|
|
|
|
NoDecl pragma
|
|
-------------
|
|
The ``noDecl`` pragma can be applied to almost any symbol (variable, proc,
|
|
type, etc.) and is sometimes useful for interoperability with C:
|
|
It tells Nim that it should not generate a declaration for the symbol in
|
|
the C code. For example:
|
|
|
|
.. code-block:: Nim
|
|
var
|
|
EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
|
|
# Nim does not know its value
|
|
|
|
However, the ``header`` pragma is often the better alternative.
|
|
|
|
**Note**: This will not work for the LLVM backend.
|
|
|
|
|
|
Header pragma
|
|
-------------
|
|
The ``header`` pragma is very similar to the ``noDecl`` pragma: It can be
|
|
applied to almost any symbol and specifies that it should not be declared
|
|
and instead the generated code should contain an ``#include``:
|
|
|
|
.. code-block:: Nim
|
|
type
|
|
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
|
|
# import C's FILE* type; Nim will treat it as a new pointer type
|
|
|
|
The ``header`` pragma always expects a string constant. The string contant
|
|
contains the header file: As usual for C, a system header file is enclosed
|
|
in angle brackets: ``<>``. If no angle brackets are given, Nim
|
|
encloses the header file in ``""`` in the generated C code.
|
|
|
|
**Note**: This will not work for the LLVM backend.
|
|
|
|
|
|
IncompleteStruct pragma
|
|
-----------------------
|
|
The ``incompleteStruct`` pragma tells the compiler to not use the
|
|
underlying C ``struct`` in a ``sizeof`` expression:
|
|
|
|
.. code-block:: Nim
|
|
type
|
|
DIR* {.importc: "DIR", header: "<dirent.h>",
|
|
final, pure, incompleteStruct.} = object
|
|
|
|
|
|
Compile pragma
|
|
--------------
|
|
The ``compile`` pragma can be used to compile and link a C/C++ source file
|
|
with the project:
|
|
|
|
.. code-block:: Nim
|
|
{.compile: "myfile.cpp".}
|
|
|
|
**Note**: Nim computes a SHA1 checksum and only recompiles the file if it
|
|
has changed. You can use the ``-f`` command line option to force recompilation
|
|
of the file.
|
|
|
|
|
|
Link pragma
|
|
-----------
|
|
The ``link`` pragma can be used to link an additional file with the project:
|
|
|
|
.. code-block:: Nim
|
|
{.link: "myfile.o".}
|
|
|
|
|
|
PassC pragma
|
|
------------
|
|
The ``passC`` pragma can be used to pass additional parameters to the C
|
|
compiler like you would using the commandline switch ``--passC``:
|
|
|
|
.. code-block:: Nim
|
|
{.passC: "-Wall -Werror".}
|
|
|
|
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
|
embed parameters from an external command at compile time:
|
|
|
|
.. code-block:: Nim
|
|
{.passC: gorge("pkg-config --cflags sdl").}
|
|
|
|
PassL pragma
|
|
------------
|
|
The ``passL`` pragma can be used to pass additional parameters to the linker
|
|
like you would using the commandline switch ``--passL``:
|
|
|
|
.. code-block:: Nim
|
|
{.passL: "-lSDLmain -lSDL".}
|
|
|
|
Note that you can use ``gorge`` from the `system module <system.html>`_ to
|
|
embed parameters from an external command at compile time:
|
|
|
|
.. code-block:: Nim
|
|
{.passL: gorge("pkg-config --libs sdl").}
|
|
|
|
|
|
Emit pragma
|
|
-----------
|
|
The ``emit`` pragma can be used to directly affect the output of the
|
|
compiler's code generator. So it makes your code unportable to other code
|
|
generators/backends. Its usage is highly discouraged! However, it can be
|
|
extremely useful for interfacing with `C++`:idx: or `Objective C`:idx: code.
|
|
|
|
Example:
|
|
|
|
.. code-block:: Nim
|
|
{.emit: """
|
|
static int cvariable = 420;
|
|
""".}
|
|
|
|
{.push stackTrace:off.}
|
|
proc embedsC() =
|
|
var nimVar = 89
|
|
# use backticks to access Nim symbols within an emit section:
|
|
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimVar`);""".}
|
|
{.pop.}
|
|
|
|
embedsC()
|
|
|
|
As can be seen from the example, to Nim symbols can be referred via backticks.
|
|
Use two backticks to produce a single verbatim backtick.
|
|
|
|
For a toplevel emit statement the section where in the generated C/C++ file
|
|
the code should be emitted can be influenced via the
|
|
prefixes ``/*TYPESECTION*/`` or ``/*VARSECTION*/`` or ``/*INCLUDESECTION*/``:
|
|
|
|
.. code-block:: Nim
|
|
{.emit: """/*TYPESECTION*/
|
|
struct Vector3 {
|
|
public:
|
|
Vector3(): x(5) {}
|
|
Vector3(float x_): x(x_) {}
|
|
float x;
|
|
};
|
|
""".}
|
|
|
|
type Vector3 {.importcpp: "Vector3", nodecl} = object
|
|
x: cfloat
|
|
|
|
proc constructVector3(a: cfloat): Vector3 {.importcpp: "Vector3(@)", nodecl}
|
|
|
|
|
|
ImportCpp pragma
|
|
----------------
|
|
|
|
**Note**: `c2nim <c2nim.html>`_ can parse a large subset of C++ and knows
|
|
about the ``importcpp`` pragma pattern language. It is not necessary
|
|
to know all the details described here.
|
|
|
|
|
|
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the
|
|
``importcpp`` pragma can be used to import `C++`:idx: methods or C++ symbols
|
|
in general. The generated code then uses the C++ method calling
|
|
syntax: ``obj->method(arg)``. In combination with the ``header`` and ``emit``
|
|
pragmas this allows *sloppy* interfacing with libraries written in C++:
|
|
|
|
.. code-block:: Nim
|
|
# Horrible example of how to interface with a C++ engine ... ;-)
|
|
|
|
{.link: "/usr/lib/libIrrlicht.so".}
|
|
|
|
{.emit: """
|
|
using namespace irr;
|
|
using namespace core;
|
|
using namespace scene;
|
|
using namespace video;
|
|
using namespace io;
|
|
using namespace gui;
|
|
""".}
|
|
|
|
const
|
|
irr = "<irrlicht/irrlicht.h>"
|
|
|
|
type
|
|
IrrlichtDeviceObj {.final, header: irr,
|
|
importcpp: "IrrlichtDevice".} = object
|
|
IrrlichtDevice = ptr IrrlichtDeviceObj
|
|
|
|
proc createDevice(): IrrlichtDevice {.
|
|
header: irr, importcpp: "createDevice(@)".}
|
|
proc run(device: IrrlichtDevice): bool {.
|
|
header: irr, importcpp: "#.run(@)".}
|
|
|
|
The compiler needs to be told to generate C++ (command ``cpp``) for
|
|
this to work. The conditional symbol ``cpp`` is defined when the compiler
|
|
emits C++ code.
|
|
|
|
|
|
Namespaces
|
|
~~~~~~~~~~
|
|
|
|
The *sloppy interfacing* example uses ``.emit`` to produce ``using namespace``
|
|
declarations. It is usually much better to instead refer to the imported name
|
|
via the ``namespace::identifier`` notation:
|
|
|
|
.. code-block:: nim
|
|
type
|
|
IrrlichtDeviceObj {.final, header: irr,
|
|
importcpp: "irr::IrrlichtDevice".} = object
|
|
|
|
|
|
Importcpp for enums
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
When ``importcpp`` is applied to an enum type the numerical enum values are
|
|
annotated with the C++ enum type, like in this example: ``((TheCppEnum)(3))``.
|
|
(This turned out to be the simplest way to implement it.)
|
|
|
|
|
|
Importcpp for procs
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Note that the ``importcpp`` variant for procs uses a somewhat cryptic pattern
|
|
language for maximum flexibility:
|
|
|
|
- A hash ``#`` symbol is replaced by the first or next argument.
|
|
- A dot following the hash ``#.`` indicates that the call should use C++'s dot
|
|
or arrow notation.
|
|
- An at symbol ``@`` is replaced by the remaining arguments, separated by
|
|
commas.
|
|
|
|
For example:
|
|
|
|
.. code-block:: nim
|
|
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "#.CppMethod(@)".}
|
|
var x: ptr CppObj
|
|
cppMethod(x[], 1, 2, 3)
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x->CppMethod(1, 2, 3)
|
|
|
|
As a special rule to keep backwards compatibility with older versions of the
|
|
``importcpp`` pragma, if there is no special pattern
|
|
character (any of ``# ' @``) at all, C++'s
|
|
dot or arrow notation is assumed, so the above example can also be written as:
|
|
|
|
.. code-block:: nim
|
|
proc cppMethod(this: CppObj, a, b, c: cint) {.importcpp: "CppMethod".}
|
|
|
|
Note that the pattern language naturally also covers C++'s operator overloading
|
|
capabilities:
|
|
|
|
.. code-block:: nim
|
|
proc vectorAddition(a, b: Vec3): Vec3 {.importcpp: "# + #".}
|
|
proc dictLookup(a: Dict, k: Key): Value {.importcpp: "#[#]".}
|
|
|
|
|
|
- An apostrophe ``'`` followed by an integer ``i`` in the range 0..9
|
|
is replaced by the i'th parameter *type*. The 0th position is the result
|
|
type. This can be used to pass types to C++ function templates. Between
|
|
the ``'`` and the digit an asterisk can be used to get to the base type
|
|
of the type. (So it "takes away a star" from the type; ``T*`` becomes ``T``.)
|
|
Two stars can be used to get to the element type of the element type etc.
|
|
|
|
For example:
|
|
|
|
.. code-block:: nim
|
|
|
|
type Input {.importcpp: "System::Input".} = object
|
|
proc getSubsystem*[T](): ptr T {.importcpp: "SystemManager::getSubsystem<'*0>()", nodecl.}
|
|
|
|
let x: ptr Input = getSubsystem[Input]()
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x = SystemManager::getSubsystem<System::Input>()
|
|
|
|
|
|
- ``#@`` is a special case to support a ``cnew`` operation. It is required so
|
|
that the call expression is inlined directly, without going through a
|
|
temporary location. This is only required to circumvent a limitation of the
|
|
current code generator.
|
|
|
|
For example C++'s ``new`` operator can be "imported" like this:
|
|
|
|
.. code-block:: nim
|
|
proc cnew*[T](x: T): ptr T {.importcpp: "(new '*0#@)", nodecl.}
|
|
|
|
# constructor of 'Foo':
|
|
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)".}
|
|
|
|
let x = cnew constructFoo(3, 4)
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
x = new Foo(3, 4)
|
|
|
|
However, depending on the use case ``new Foo`` can also be wrapped like this
|
|
instead:
|
|
|
|
.. code-block:: nim
|
|
proc newFoo(a, b: cint): ptr Foo {.importcpp: "new Foo(@)".}
|
|
|
|
let x = newFoo(3, 4)
|
|
|
|
|
|
Wrapping constructors
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Sometimes a C++ class has a private copy constructor and so code like
|
|
``Class c = Class(1,2);`` must not be generated but instead ``Class c(1,2);``.
|
|
For this purpose the Nim proc that wraps a C++ constructor needs to be
|
|
annotated with the `constructor`:idx: pragma. This pragma also helps to generate
|
|
faster C++ code since construction then doesn't invoke the copy constructor:
|
|
|
|
.. code-block:: nim
|
|
# a better constructor of 'Foo':
|
|
proc constructFoo(a, b: cint): Foo {.importcpp: "Foo(@)", constructor.}
|
|
|
|
|
|
Wrapping destructors
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Since Nim generates C++ directly, any destructor is called implicitly by the
|
|
C++ compiler at the scope exits. This means that often one can get away with
|
|
not wrapping the destructor at all! However when it needs to be invoked
|
|
explicitly, it needs to be wrapped. But the pattern language already provides
|
|
everything that is required for that:
|
|
|
|
.. code-block:: nim
|
|
proc destroyFoo(this: var Foo) {.importcpp: "#.~Foo()".}
|
|
|
|
|
|
Importcpp for objects
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Generic ``importcpp``'ed objects are mapped to C++ templates. This means that
|
|
you can import C++'s templates rather easily without the need for a pattern
|
|
language for object types:
|
|
|
|
.. code-block:: nim
|
|
type
|
|
StdMap {.importcpp: "std::map", header: "<map>".} [K, V] = object
|
|
proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {.
|
|
importcpp: "#[#] = #", header: "<map>".}
|
|
|
|
var x: StdMap[cint, cdouble]
|
|
x[6] = 91.4
|
|
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
std::map<int, double> x;
|
|
x[6] = 91.4;
|
|
|
|
|
|
- If more precise control is needed, the apostrophe ``'`` can be used in the
|
|
supplied pattern to denote the concrete type parameters of the generic type.
|
|
See the usage of the apostrophe operator in proc patterns for more details.
|
|
|
|
.. code-block:: nim
|
|
|
|
type
|
|
VectorIterator {.importcpp: "std::vector<'0>::iterator".} [T] = object
|
|
|
|
var x: VectorIterator[cint]
|
|
|
|
|
|
Produces:
|
|
|
|
.. code-block:: C
|
|
|
|
std::vector<int>::iterator x;
|
|
|
|
|
|
ImportObjC pragma
|
|
-----------------
|
|
Similar to the `importc pragma for C <manual.html#importc-pragma>`_, the
|
|
``importobjc`` pragma can be used to import `Objective C`:idx: methods. The
|
|
generated code then uses the Objective C method calling syntax: ``[obj method
|
|
param1: arg]``. In addition with the ``header`` and ``emit`` pragmas this
|
|
allows *sloppy* interfacing with libraries written in Objective C:
|
|
|
|
.. code-block:: Nim
|
|
# horrible example of how to interface with GNUStep ...
|
|
|
|
{.passL: "-lobjc".}
|
|
{.emit: """
|
|
#include <objc/Object.h>
|
|
@interface Greeter:Object
|
|
{
|
|
}
|
|
|
|
- (void)greet:(long)x y:(long)dummy;
|
|
@end
|
|
|
|
#include <stdio.h>
|
|
@implementation Greeter
|
|
|
|
- (void)greet:(long)x y:(long)dummy
|
|
{
|
|
printf("Hello, World!\n");
|
|
}
|
|
@end
|
|
|
|
#include <stdlib.h>
|
|
""".}
|
|
|
|
type
|
|
Id {.importc: "id", header: "<objc/Object.h>", final.} = distinct int
|
|
|
|
proc newGreeter: Id {.importobjc: "Greeter new", nodecl.}
|
|
proc greet(self: Id, x, y: int) {.importobjc: "greet", nodecl.}
|
|
proc free(self: Id) {.importobjc: "free", nodecl.}
|
|
|
|
var g = newGreeter()
|
|
g.greet(12, 34)
|
|
g.free()
|
|
|
|
The compiler needs to be told to generate Objective C (command ``objc``) for
|
|
this to work. The conditional symbol ``objc`` is defined when the compiler
|
|
emits Objective C code.
|
|
|
|
|
|
CodegenDecl pragma
|
|
------------------
|
|
|
|
The ``codegenDecl`` pragma can be used to directly influence Nim's code
|
|
generator. It receives a format string that determines how the variable or
|
|
proc is declared in the generated code:
|
|
|
|
.. code-block:: nim
|
|
var
|
|
a {.codegenDecl: "$# progmem $#".}: int
|
|
|
|
proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} =
|
|
echo "realistic interrupt handler"
|
|
|
|
|
|
InjectStmt pragma
|
|
-----------------
|
|
|
|
The ``injectStmt`` pragma can be used to inject a statement before every
|
|
other statement in the current module. It is only supposed to be used for
|
|
debugging:
|
|
|
|
.. code-block:: nim
|
|
{.injectStmt: gcInvariants().}
|
|
|
|
# ... complex code here that produces crashes ...
|
|
|