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 `_ 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. 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: "".} = 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: "", 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 `_ 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 `_ 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 `_ 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 `_, 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 = "" 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() - ``#@`` 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: "".} [K, V] = object proc `[]=`[K, V](this: var StdMap[K, V]; key: K; val: V) {. importcpp: "#[#] = #", header: "".} var x: StdMap[cint, cdouble] x[6] = 91.4 Produces: .. code-block:: C std::map 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::iterator x; ImportObjC pragma ----------------- Similar to the `importc pragma for C `_, 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 @interface Greeter:Object { } - (void)greet:(long)x y:(long)dummy; @end #include @implementation Greeter - (void)greet:(long)x y:(long)dummy { printf("Hello, World!\n"); } @end #include """.} type Id {.importc: "id", header: "", 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 ... 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 Reads in a build-time define as an integer strdefine 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.