123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080 |
- 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].}
- 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: untyped, 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.
- used pragma
- -----------
- Nim produces a warning for symbols that are not exported and not used either.
- The ``used`` pragma can be attached to a symbol to suppress this warning. This
- is particularly useful when the symbol was generated by a macro:
- .. code-block:: nim
- template implementArithOps(T) =
- proc echoAdd(a, b: T) {.used.} =
- echo a + b
- proc echoSub(a, b: T) {.used.} =
- echo a - b
- # no warning produced for the unused 'echoSub'
- implementArithOps(int)
- echoAdd 3, 5
- 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
- # access Nim symbols within an emit section outside of string literals:
- {.emit: ["""fprintf(stdout, "%d\n", cvariable + (int)""", nimVar, ");"].}
- {.pop.}
- embedsC()
- For backwards compatibility, if the argument to the ``emit`` statement
- is a single string literal, Nim symbols can be referred to via backticks.
- This usage is however deprecated.
- 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.
- For variables $1 in the format string represents the type of the variable
- and $2 is the name of the variable.
- The following Nim code:
- .. code-block:: nim
- var
- a {.codegenDecl: "$# progmem $#".}: int
-
- will generate this C code:
- .. code-block:: c
- int progmem a
- For procedures $1 is the return type of the procedure, $2 is the name of
- the procedure and $3 is the parameter list.
- The following nim code:
- .. code-block:: nim
- proc myinterrupt() {.codegenDecl: "__interrupt $# $#$#".} =
- echo "realistic interrupt handler"
- will generate this code:
- .. code-block:: c
- __interrupt void myinterrupt()
- 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 ...
- compile time define pragmas
- ---------------------------
- The pragmas listed here can be used to optionally accept values from
- the -d/--define option at compile time.
- The implementation currently provides the following possible options (various
- others may be added later).
- ================= ============================================
- pragma description
- ================= ============================================
- `intdefine`:idx: Reads in a build-time define as an integer
- `strdefine`:idx: Reads in a build-time define as a string
- ================= ============================================
- .. code-block:: nim
- const FooBar {.intdefine.}: int = 5
- echo FooBar
- .. code-block:: bash
- nim c -d:FooBar=42 foobar.c
- In the above example, providing the -d flag causes the symbol
- ``FooBar`` to be overwritten at compile time, printing out 42. If the
- ``-d:FooBar=42`` were to be omitted, the default value of 5 would be
- used.
|