Markdown code blocks part 5 (#20236)

No logic was added, just a few more `*.md` files have been migrated.
This commit is contained in:
Andrey Makarov 2022-08-17 22:20:22 +03:00 • committed by GitHub
commit 1c31de361d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 486 additions and 413 deletions

View file

@ -198,8 +198,7 @@ static C library.
Create a ``host.html`` file with the following content: Create a ``host.html`` file with the following content:
.. code-block:: ```
<html><body> <html><body>
<script type="text/javascript"> <script type="text/javascript">
function addTwoIntegers(a, b) function addTwoIntegers(a, b)
@ -209,6 +208,7 @@ Create a ``host.html`` file with the following content:
</script> </script>
<script type="text/javascript" src="calculator.js"></script> <script type="text/javascript" src="calculator.js"></script>
</body></html> </body></html>
```
Create a ``calculator.nim`` file with the following content (or reuse the one Create a ``calculator.nim`` file with the following content (or reuse the one
from the previous section): from the previous section):

View file

@ -67,11 +67,12 @@ Basic Markdown syntax is also supported inside the doc comments.
Example: Example:
.. code-block:: nim ```nim
type Person* = object type Person* = object
## This type contains a description of a person ## This type contains a description of a person
name: string name: string
age: int age: int
```
Outputs:: Outputs::
Person* = object Person* = object
@ -82,9 +83,10 @@ Outputs::
Field documentation comments can be added to fields like so: Field documentation comments can be added to fields like so:
.. code-block:: nim ```nim
var numValues: int ## \ var numValues: int ## \
## `numValues` stores the number of values ## `numValues` stores the number of values
```
Note that without the `*` following the name of the type, the documentation for Note that without the `*` following the name of the type, the documentation for
this type would not be generated. Documentation will only be generated for this type would not be generated. Documentation will only be generated for
@ -102,12 +104,13 @@ won't influence RST formatting.
If you still need to add an additional indentation at the very beginning If you still need to add an additional indentation at the very beginning
(for RST block quote syntax) use backslash \\ before it: (for RST block quote syntax) use backslash \\ before it:
.. code-block:: nim ```nim
## \ ## \
## ##
## Block quote at the first line. ## Block quote at the first line.
## ##
## Paragraph. ## Paragraph.
```
Document Types Document Types

View file

@ -72,12 +72,12 @@ Whenever an example of usage would be helpful to the user, you should include on
## truncating the result. ## truncating the result.
## ##
## ``` ## ```
## # things that aren't suitable for a `runnableExamples` go in code-block: ## # things that aren't suitable for a `runnableExamples` go in code block:
## echo execCmdEx("git pull") ## echo execCmdEx("git pull")
## drawOnScreen() ## drawOnScreen()
## ``` ## ```
runnableExamples: runnableExamples:
# `runnableExamples` is usually preferred to ``code-block``, when possible. # `runnableExamples` is usually preferred to code blocks, when possible.
doAssert addThree(3, 125, 6) == -122 doAssert addThree(3, 125, 6) == -122
result = x +% y +% z result = x +% y +% z
```` ````

View file

@ -5083,10 +5083,7 @@ exception tracking.
There is also a way which can be used to forbid certain effects: There is also a way which can be used to forbid certain effects:
.. code-block:: nim ```nim test = "nim c --warningAsError:Effect:on $1" status = 1
:test: "nim c --warningAsError:Effect:on $1"
:status: 1
type IO = object ## input/output effect type IO = object ## input/output effect
proc readLine(): string {.tags: [IO].} = discard proc readLine(): string {.tags: [IO].} = discard
proc echoLine(): void = discard proc echoLine(): void = discard
@ -5096,13 +5093,14 @@ There is also a way which can be used to forbid certain effects:
echoLine() echoLine()
# the compiler prevents this: # the compiler prevents this:
let y = readLine() let y = readLine()
```
The `forbids` pragma defines a list of illegal effects - if any statement The `forbids` pragma defines a list of illegal effects - if any statement
invokes any of those effects, the compilation will fail. invokes any of those effects, the compilation will fail.
Procedure types with any disallowed effect are the subtypes of equal Procedure types with any disallowed effect are the subtypes of equal
procedure types without such lists: procedure types without such lists:
.. code-block:: nim ```nim
type MyEffect = object type MyEffect = object
type ProcType1 = proc (i: int): void {.forbids: [MyEffect].} type ProcType1 = proc (i: int): void {.forbids: [MyEffect].}
type ProcType2 = proc (i: int): void type ProcType2 = proc (i: int): void
@ -5123,6 +5121,7 @@ procedure types without such lists:
## these are OK because ProcType2 doesn't have any effect requirement: ## these are OK because ProcType2 doesn't have any effect requirement:
caller2(toBeCalled1) caller2(toBeCalled1)
caller2(toBeCalled2) caller2(toBeCalled2)
```
`ProcType2` is a subtype of `ProcType1`. Unlike with tags, the parent context - the function which calls other functions with forbidden effects - doesn't inherit the forbidden list of effects. `ProcType2` is a subtype of `ProcType1`. Unlike with tags, the parent context - the function which calls other functions with forbidden effects - doesn't inherit the forbidden list of effects.
@ -8079,18 +8078,20 @@ from C. The optional argument is a string containing the C identifier. If
the argument is missing, the C name is the Nim identifier *exactly as the argument is missing, the C name is the Nim identifier *exactly as
spelled*: spelled*:
.. code-block:: ```nim
proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.} proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
```
When `importc` is applied to a `let` statement it can omit its value which When `importc` is applied to a `let` statement it can omit its value which
will then be expected to come from C. This can be used to import a C `const`:c:\: will then be expected to come from C. This can be used to import a C `const`:c:\:
.. code-block:: ```nim
{.emit: "const int cconst = 42;".} {.emit: "const int cconst = 42;".}
let cconst {.importc, nodecl.}: cint let cconst {.importc, nodecl.}: cint
assert cconst == 42 assert cconst == 42
```
Note that this pragma has been abused in the past to also work in the Note that this pragma has been abused in the past to also work in the
JS backend for JS objects and functions. Other backends do provide JS backend for JS objects and functions. Other backends do provide

View file

@ -6,7 +6,7 @@ rule: If `result` does not refer to a location pointing to the heap
(that is in `result = X` the `X` involves a `ptr` or `ref` access) (that is in `result = X` the `X` involves a `ptr` or `ref` access)
then it has to be derived from the routine's first parameter: then it has to be derived from the routine's first parameter:
.. code-block:: nim ```nim
proc forward[T](x: var T): var T = proc forward[T](x: var T): var T =
result = x # ok, derived from the first parameter. result = x # ok, derived from the first parameter.
@ -17,6 +17,7 @@ then it has to be derived from the routine's first parameter:
result = forward(x) # Error: location is derived from `x` result = forward(x) # Error: location is derived from `x`
# which is not p's first parameter and lives # which is not p's first parameter and lives
# on the stack. # on the stack.
```
In other words, the lifetime of what `result` points to is attached to the In other words, the lifetime of what `result` points to is attached to the
lifetime of the first parameter and that is enough knowledge to verify lifetime of the first parameter and that is enough knowledge to verify

View file

@ -6,13 +6,15 @@ Strict not nil checking
**Note:** This feature is experimental, you need to enable it with **Note:** This feature is experimental, you need to enable it with
.. code-block:: nim ```nim
{.experimental: "strictNotNil".} {.experimental: "strictNotNil".}
```
or or
.. code-block:: cmd ```cmd
nim c --experimental:strictNotNil <program> nim c --experimental:strictNotNil <program>
```
In the second case it would check builtin and imported modules as well. In the second case it would check builtin and imported modules as well.
@ -39,7 +41,7 @@ not nil
You can annotate a type where nil isn't a valid value with `not nil`. You can annotate a type where nil isn't a valid value with `not nil`.
.. code-block:: nim ```nim
type type
NilableObject = ref object NilableObject = ref object
a: int a: int
@ -57,6 +59,7 @@ You can annotate a type where nil isn't a valid value with `not nil`.
p(x) p(x)
else: else:
p(x) # ok p(x) # ok
```
@ -118,14 +121,16 @@ call args rules
When we call with arguments, we have two cases when we might change the nilability. When we call with arguments, we have two cases when we might change the nilability.
.. code-block:: nim ```nim
callByVar(a) callByVar(a)
```
Here `callByVar` can re-assign `a`, so this might change `a`'s nilability, so we change it to `MaybeNil`. Here `callByVar` can re-assign `a`, so this might change `a`'s nilability, so we change it to `MaybeNil`.
This is also a possible aliasing `move out` (moving out of a current alias set). This is also a possible aliasing `move out` (moving out of a current alias set).
.. code-block:: nim ```nim
call(a) call(a)
```
Here `call` can change a field or element of `a`, so if we have a dependant expression of `a` : e.g. `a.field`. Dependants become `MaybeNil`. Here `call` can change a field or element of `a`, so if we have a dependant expression of `a` : e.g. `a.field`. Dependants become `MaybeNil`.
@ -141,13 +146,14 @@ When branches "join" we usually unify their expression maps or/and nilabilities.
Merging usually merges maps and alias sets: nilabilities are merged like this: Merging usually merges maps and alias sets: nilabilities are merged like this:
.. code-block:: nim ```nim
template union(l: Nilability, r: Nilability): Nilability = template union(l: Nilability, r: Nilability): Nilability =
## unify two states ## unify two states
if l == r: if l == r:
l l
else: else:
MaybeNil MaybeNil
```
Special handling is for `.isNil` and `== nil`, also for `not`, `and` and `or`. Special handling is for `.isNil` and `== nil`, also for `not`, `and` and `or`.
@ -183,8 +189,9 @@ element tracking
When we assign an object construction, we should track the fields as well: When we assign an object construction, we should track the fields as well:
.. code-block:: nim ```nim
var a = Nilable(field: Nilable()) # a : Safe, a.field: Safe var a = Nilable(field: Nilable()) # a : Safe, a.field: Safe
```
Usually we just track the result of an expression: probably this should apply for elements in other cases as well. Usually we just track the result of an expression: probably this should apply for elements in other cases as well.
Also related to tracking initialization of expressions/fields. Also related to tracking initialization of expressions/fields.
@ -195,12 +202,13 @@ unstructured control flow rules
Unstructured control flow keywords as `return`, `break`, `continue`, `raise` mean that we jump from a branch out. Unstructured control flow keywords as `return`, `break`, `continue`, `raise` mean that we jump from a branch out.
This means that if there is code after the finishing of the branch, it would be run if one hasn't hit the direct parent branch of those: so it is similar to an `else`. In those cases we should use the reverse nilabilities for the local to the condition expressions. E.g. This means that if there is code after the finishing of the branch, it would be run if one hasn't hit the direct parent branch of those: so it is similar to an `else`. In those cases we should use the reverse nilabilities for the local to the condition expressions. E.g.
.. code-block:: nim ```nim
for a in c: for a in c:
if not a.isNil: if not a.isNil:
b() b()
break break
code # here a: Nil , because if not, we would have breaked code # here a: Nil , because if not, we would have breaked
```
aliasing aliasing
@ -214,17 +222,19 @@ Assignments and other changes to nilability can move / move out expressions of s
`move`: Moving `left` to `right` means we remove `left` from its current set and unify it with the `right`'s set. `move`: Moving `left` to `right` means we remove `left` from its current set and unify it with the `right`'s set.
This means it stops being aliased with its previous aliases. This means it stops being aliased with its previous aliases.
.. code-block:: nim ```nim
var left = b var left = b
left = right # moving left to right left = right # moving left to right
```
`move out`: Moving out `left` might remove it from the current set and ensure that it's in its own set as a single element. `move out`: Moving out `left` might remove it from the current set and ensure that it's in its own set as a single element.
e.g. e.g.
.. code-block:: nim ```nim
var left = b var left = b
left = nil # moving out left = nil # moving out
```
initialization of non nilable and nilable values initialization of non nilable and nilable values

View file

@ -49,7 +49,7 @@ Spacing and Whitespace Conventions
Not all editors support automatic alignment of code sections, and re-aligning Not all editors support automatic alignment of code sections, and re-aligning
long sections of code by hand can quickly become tedious. long sections of code by hand can quickly become tedious.
.. code-block:: nim ```nim
# This is bad, as the next time someone comes # This is bad, as the next time someone comes
# to edit this code block, they # to edit this code block, they
# must re-align all the assignments again: # must re-align all the assignments again:
@ -60,6 +60,7 @@ Spacing and Whitespace Conventions
CalId* = int CalId* = int
LongLong* = int64 LongLong* = int64
LongLongPtr* = ptr LongLong LongLongPtr* = ptr LongLong
```
Naming Conventions Naming Conventions
@ -69,7 +70,7 @@ Naming Conventions
camelCase with the exception of constants which **may** use PascalCase but camelCase with the exception of constants which **may** use PascalCase but
are not required to. are not required to.
.. code-block:: nim ```nim
# Constants can start with either a lower case or upper case letter. # Constants can start with either a lower case or upper case letter.
const aConstant = 42 const aConstant = 42
const FooBar = 4.2 const FooBar = 4.2
@ -79,6 +80,7 @@ Naming Conventions
# Types must start with an uppercase letter. # Types must start with an uppercase letter.
type type
FooBar = object FooBar = object
```
For constants coming from a C/C++ wrapper, ALL_UPPERCASE are allowed, but ugly. For constants coming from a C/C++ wrapper, ALL_UPPERCASE are allowed, but ugly.
(Why shout CONSTANT? Constants do no harm, variables do!) (Why shout CONSTANT? Constants do no harm, variables do!)
@ -89,41 +91,45 @@ Naming Conventions
that will be used the most, add the suffixes to the pointer variants only. The that will be used the most, add the suffixes to the pointer variants only. The
same applies to C/C++ wrappers. same applies to C/C++ wrappers.
.. code-block:: nim ```nim
type type
Handle = object # Will be used most often Handle = object # Will be used most often
fd: int64 fd: int64
HandleRef = ref Handle # Will be used less often HandleRef = ref Handle # Will be used less often
```
- Exception and Error types should have the "Error" or "Defect" suffix. - Exception and Error types should have the "Error" or "Defect" suffix.
.. code-block:: nim ```nim
type type
ValueError = object of CatchableError ValueError = object of CatchableError
AssertionDefect = object of Defect AssertionDefect = object of Defect
Foo = object of Exception # bad style, try to inherit CatchableError or Defect Foo = object of Exception # bad style, try to inherit CatchableError or Defect
```
- Unless marked with the `{.pure.}` pragma, members of enums should have an - Unless marked with the `{.pure.}` pragma, members of enums should have an
identifying prefix, such as an abbreviation of the enum's name. identifying prefix, such as an abbreviation of the enum's name.
.. code-block:: nim ```nim
type type
PathComponent = enum PathComponent = enum
pcDir pcDir
pcLinkToDir pcLinkToDir
pcFile pcFile
pcLinkToFile pcLinkToFile
```
- Non-pure enum values should use camelCase whereas pure enum values should use - Non-pure enum values should use camelCase whereas pure enum values should use
PascalCase. PascalCase.
.. code-block:: nim ```nim
type type
PathComponent {.pure.} = enum PathComponent {.pure.} = enum
Dir Dir
LinkToDir LinkToDir
File File
LinkToFile LinkToFile
```
- In the age of HTTP, HTML, FTP, TCP, IP, UTF, WWW it is foolish to pretend - In the age of HTTP, HTML, FTP, TCP, IP, UTF, WWW it is foolish to pretend
these are somewhat special words requiring all uppercase. Instead treat them these are somewhat special words requiring all uppercase. Instead treat them
@ -230,12 +236,13 @@ Coding Conventions
are required. Use a procedure's implicit `result` variable whenever possible. are required. Use a procedure's implicit `result` variable whenever possible.
This improves readability. This improves readability.
.. code-block:: nim ```nim
proc repeat(text: string, x: int): string = proc repeat(text: string, x: int): string =
result = "" result = ""
for i in 0..x: for i in 0..x:
result.add($i) result.add($i)
```
- Use a proc when possible, only using the more powerful facilities of macros, - Use a proc when possible, only using the more powerful facilities of macros,
templates, iterators, and converters when necessary. templates, iterators, and converters when necessary.
@ -252,15 +259,16 @@ Conventions for multi-line statements and expressions
- Tuples which are longer than one line should indent their parameters to - Tuples which are longer than one line should indent their parameters to
align with the parameters above it. align with the parameters above it.
.. code-block:: nim ```nim
type type
LongTupleA = tuple[wordyTupleMemberOne: int, wordyTupleMemberTwo: string, LongTupleA = tuple[wordyTupleMemberOne: int, wordyTupleMemberTwo: string,
wordyTupleMemberThree: float] wordyTupleMemberThree: float]
```
- Similarly, any procedure and procedure type declarations that are longer - Similarly, any procedure and procedure type declarations that are longer
than one line should do the same thing. than one line should do the same thing.
.. code-block:: nim ```nim
type type
EventCallback = proc (timeReceived: Time, errorCode: int, event: Event, EventCallback = proc (timeReceived: Time, errorCode: int, event: Event,
output: var string) output: var string)
@ -268,13 +276,15 @@ Conventions for multi-line statements and expressions
proc lotsOfArguments(argOne: string, argTwo: int, argThree: float, proc lotsOfArguments(argOne: string, argTwo: int, argThree: float,
argFour: proc(), argFive: bool): int argFour: proc(), argFive: bool): int
{.heyLookALongPragma.} = {.heyLookALongPragma.} =
```
- Multi-line procedure calls should continue on the same column as the opening - Multi-line procedure calls should continue on the same column as the opening
parenthesis (like multi-line procedure declarations). parenthesis (like multi-line procedure declarations).
.. code-block:: nim ```nim
startProcess(nimExecutable, currentDirectory, compilerArguments startProcess(nimExecutable, currentDirectory, compilerArguments
environment, processOptions) environment, processOptions)
```
Miscellaneous Miscellaneous
------------- -------------
@ -290,18 +300,20 @@ Miscellaneous
use this: use this:
.. code-block:: nim ```nim
let a = """ let a = """
foo foo
bar bar
""" """
```
instead of: instead of:
.. code-block:: nim ```nim
let a = """foo let a = """foo
bar bar
""" """
```
- A getter API for a private field `foo` should preferably be named `foo`, not `getFoo`. - A getter API for a private field `foo` should preferably be named `foo`, not `getFoo`.
A getter-like API should preferably be named `getFoo`, not `foo` if: A getter-like API should preferably be named `getFoo`, not `foo` if:

View file

@ -219,15 +219,15 @@ Command-line settings have priority over configuration file settings.
The default build of a project is a `debug build`:idx:. To compile a The default build of a project is a `debug build`:idx:. To compile a
`release build`:idx: define the `release` symbol: `release build`:idx: define the `release` symbol:
.. code:: cmd ```cmd
nim c -d:release myproject.nim nim c -d:release myproject.nim
```
To compile a `dangerous release build`:idx: define the `danger` symbol: To compile a `dangerous release build`:idx: define the `danger` symbol:
.. code:: cmd ```cmd
nim c -d:danger myproject.nim nim c -d:danger myproject.nim
```
Search path handling Search path handling
@ -281,9 +281,9 @@ Compiler Selection
To change the compiler from the default compiler (at the command line): To change the compiler from the default compiler (at the command line):
.. code:: cmd ```cmd
nim c --cc:llvm_gcc --compile_only myfile.nim nim c --cc:llvm_gcc --compile_only myfile.nim
```
This uses the configuration defined in ``config\nim.cfg`` for `llvm_gcc`:cmd:. This uses the configuration defined in ``config\nim.cfg`` for `llvm_gcc`:cmd:.
@ -303,18 +303,18 @@ Cross-compilation
To cross compile, use for example: To cross compile, use for example:
.. code:: cmd ```cmd
nim c --cpu:i386 --os:linux --compileOnly --genScript myproject.nim nim c --cpu:i386 --os:linux --compileOnly --genScript myproject.nim
```
Then move the C code and the compile script `compile_myproject.sh`:cmd: to your Then move the C code and the compile script `compile_myproject.sh`:cmd: to your
Linux i386 machine and run the script. Linux i386 machine and run the script.
Another way is to make Nim invoke a cross compiler toolchain: Another way is to make Nim invoke a cross compiler toolchain:
.. code:: cmd ```cmd
nim c --cpu:arm --os:linux myproject.nim nim c --cpu:arm --os:linux myproject.nim
```
For cross compilation, the compiler invokes a C compiler named For cross compilation, the compiler invokes a C compiler named
like `$cpu.$os.$cc` (for example arm.linux.gcc) and the configuration like `$cpu.$os.$cc` (for example arm.linux.gcc) and the configuration
@ -330,22 +330,22 @@ Cross-compilation for Windows
To cross-compile for Windows from Linux or macOS using the MinGW-w64 toolchain: To cross-compile for Windows from Linux or macOS using the MinGW-w64 toolchain:
.. code:: cmd ```cmd
nim c -d:mingw myproject.nim nim c -d:mingw myproject.nim
# `nim r` also works, running the binary via `wine` or `wine64`: # `nim r` also works, running the binary via `wine` or `wine64`:
nim r -d:mingw --eval:'import os; echo "a" / "b"' nim r -d:mingw --eval:'import os; echo "a" / "b"'
```
Use `--cpu:i386`:option: or `--cpu:amd64`:option: to switch the CPU architecture. Use `--cpu:i386`:option: or `--cpu:amd64`:option: to switch the CPU architecture.
The MinGW-w64 toolchain can be installed as follows: The MinGW-w64 toolchain can be installed as follows:
.. code:: cmd ```cmd
apt install mingw-w64 # Ubuntu apt install mingw-w64 # Ubuntu
yum install mingw32-gcc yum install mingw32-gcc
yum install mingw64-gcc # CentOS - requires EPEL yum install mingw64-gcc # CentOS - requires EPEL
brew install mingw-w64 # OSX brew install mingw-w64 # OSX
```
Cross-compilation for Android Cross-compilation for Android
@ -380,11 +380,11 @@ stuff is done, it's very important to call `NimMain()`:c: in order to
initialize Nim's garbage collector and to run the top level statements initialize Nim's garbage collector and to run the top level statements
of your program. of your program.
.. code-block:: Nim ```Nim
proc NimMain() {.importc.} proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} = proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
NimMain() # initialize garbage collector memory, types and stack NimMain() # initialize garbage collector memory, types and stack
```
The name `NimMain` can be influenced via the `--nimMainPrefix:prefix` switch. The name `NimMain` can be influenced via the `--nimMainPrefix:prefix` switch.
@ -410,11 +410,11 @@ the iOS setup is done, it's very important to call `NimMain()`:c: to
initialize Nim's garbage collector and to run the top-level statements initialize Nim's garbage collector and to run the top-level statements
of your program. of your program.
.. code-block:: Nim ```Nim
proc NimMain() {.importc.} proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} = proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
NimMain() # initialize garbage collector memory, types and stack NimMain() # initialize garbage collector memory, types and stack
```
Note: XCode's "make clean" gets confused about the generated nim.c files, Note: XCode's "make clean" gets confused about the generated nim.c files,
so you need to clean those files manually to do a clean build. so you need to clean those files manually to do a clean build.
@ -430,9 +430,10 @@ Simply add `--os:nintendoswitch`:option:
to your usual `nim c`:cmd: or `nim cpp`:cmd: command and set the `passC`:option: to your usual `nim c`:cmd: or `nim cpp`:cmd: command and set the `passC`:option:
and `passL`:option: command line switches to something like: and `passL`:option: command line switches to something like:
.. code-block:: cmd ```cmd
nim c ... --d:nimAllocPagesViaMalloc --mm:orc --passC="-I$DEVKITPRO/libnx/include" ... nim c ... --d:nimAllocPagesViaMalloc --mm:orc --passC="-I$DEVKITPRO/libnx/include" ...
--passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx" --passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx"
```
or setup a ``nim.cfg`` file like so:: or setup a ``nim.cfg`` file like so::
@ -448,9 +449,9 @@ The devkitPro setup must be the same as the default with their new installer
For example, with the above-mentioned config: For example, with the above-mentioned config:
.. code:: cmd ```cmd
nim c --os:nintendoswitch switchhomebrew.nim nim c --os:nintendoswitch switchhomebrew.nim
```
This will generate a file called ``switchhomebrew.elf`` which can then be turned into This will generate a file called ``switchhomebrew.elf`` which can then be turned into
an nro file with the `elf2nro`:cmd: tool in the devkitPro release. Examples can be found at an nro file with the `elf2nro`:cmd: tool in the devkitPro release. Examples can be found at
@ -475,15 +476,15 @@ instance of the GC per process/address space. This instance is contained in
``nimrtl.dll``. This means that every generated Nim DLL depends ``nimrtl.dll``. This means that every generated Nim DLL depends
on ``nimrtl.dll``. To generate the "nimrtl.dll" file, use the command: on ``nimrtl.dll``. To generate the "nimrtl.dll" file, use the command:
.. code:: cmd ```cmd
nim c -d:release lib/nimrtl.nim nim c -d:release lib/nimrtl.nim
```
To link against ``nimrtl.dll`` use the command: To link against ``nimrtl.dll`` use the command:
.. code:: cmd ```cmd
nim c -d:useNimRtl myprog.nim nim c -d:useNimRtl myprog.nim
```
**Note**: Currently the creation of ``nimrtl.dll`` with thread support has **Note**: Currently the creation of ``nimrtl.dll`` with thread support has
never been tested and is unlikely to work! never been tested and is unlikely to work!
@ -578,9 +579,9 @@ can be prevented and then via `--passL`:option: the static library can be linked
against. For instance, to link statically against Lua this command might work against. For instance, to link statically against Lua this command might work
on Linux: on Linux:
.. code:: cmd ```cmd
nim c --dynlibOverride:lua --passL:liblua.lib program.nim nim c --dynlibOverride:lua --passL:liblua.lib program.nim
```
Backend language options Backend language options
@ -635,9 +636,9 @@ embedded microprocessors with only a few kilobytes of memory.
A good start is to use the `any` operating target together with the A good start is to use the `any` operating target together with the
`malloc` memory allocator and the `arc` garbage collector. For example: `malloc` memory allocator and the `arc` garbage collector. For example:
.. code:: cmd ```cmd
nim c --os:any --mm:arc -d:useMalloc [...] x.nim nim c --os:any --mm:arc -d:useMalloc [...] x.nim
```
- `--mm:arc`:option: will enable the reference counting memory management instead - `--mm:arc`:option: will enable the reference counting memory management instead
of the default garbage collector. This enables Nim to use heap memory which of the default garbage collector. This enables Nim to use heap memory which
@ -760,28 +761,32 @@ passed to subroutines. The compiler does not copy strings that are a result of
a procedure call, because the callee returns a new string anyway. a procedure call, because the callee returns a new string anyway.
Thus it is efficient to do: Thus it is efficient to do:
.. code-block:: Nim ```Nim
var s = procA() # assignment will not copy the string; procA allocates a new var s = procA() # assignment will not copy the string; procA allocates a new
# string already # string already
```
However, it is not efficient to do: However, it is not efficient to do:
.. code-block:: Nim ```Nim
var s = varA # assignment has to copy the whole string into a new buffer! var s = varA # assignment has to copy the whole string into a new buffer!
```
For `let` symbols a copy is not always necessary: For `let` symbols a copy is not always necessary:
.. code-block:: Nim ```Nim
let s = varA # may only copy a pointer if it safe to do so let s = varA # may only copy a pointer if it safe to do so
```
If you know what you're doing, you can also mark single-string (or sequence) If you know what you're doing, you can also mark single-string (or sequence)
objects as `shallow`:idx:\: objects as `shallow`:idx:\:
.. code-block:: Nim ```Nim
var s = "abc" var s = "abc"
shallow(s) # mark 's' as a shallow string shallow(s) # mark 's' as a shallow string
var x = s # now might not copy the string! var x = s # now might not copy the string!
```
Usage of `shallow` is always safe once you know the string won't be modified Usage of `shallow` is always safe once you know the string won't be modified
anymore, similar to Ruby's `freeze`:idx:. anymore, similar to Ruby's `freeze`:idx:.
@ -791,7 +796,7 @@ The compiler optimizes string case statements: A hashing scheme is used for them
if several different string constants are used. So code like this is reasonably if several different string constants are used. So code like this is reasonably
efficient: efficient:
.. code-block:: Nim ```Nim
case normalize(k.key) case normalize(k.key)
of "name": c.name = v of "name": c.name = v
of "displayname": c.displayName = v of "displayname": c.displayName = v
@ -807,3 +812,4 @@ efficient:
else: quit(errorStr(p, "expected: console or gui")) else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = UnixToNativePath(k.value) of "license": c.license = UnixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key)) else: quit(errorStr(p, "unknown variable: " & k.key))
```

View file

@ -22,8 +22,9 @@ Installation
Compile nimgrep with the command: Compile nimgrep with the command:
.. code:: cmd ```cmd
nim c -d:release tools/nimgrep.nim nim c -d:release tools/nimgrep.nim
```
And copy the executable somewhere in your ``$PATH``. And copy the executable somewhere in your ``$PATH``.
@ -40,9 +41,10 @@ All examples below use default PCRE Regex patterns:
+ To search recursively in Nim files using style-insensitive identifiers: + To search recursively in Nim files using style-insensitive identifiers:
.. code:: cmd ```cmd
nimgrep --recursive --ext:'nim|nims' --ignoreStyle nimgrep --recursive --ext:'nim|nims' --ignoreStyle
# short: -r --ext:'nim|nims' -y # short: -r --ext:'nim|nims' -y
```
.. Note:: we used `'` quotes to avoid special treatment of `|` symbol .. Note:: we used `'` quotes to avoid special treatment of `|` symbol
for shells like Bash for shells like Bash
@ -50,15 +52,17 @@ All examples below use default PCRE Regex patterns:
+ To exclude version control directories (Git, Mercurial=hg, Subversion=svn) + To exclude version control directories (Git, Mercurial=hg, Subversion=svn)
from the search: from the search:
.. code:: cmd ```cmd
nimgrep --excludeDir:'^\.git$' --excludeDir:'^\.hg$' --excludeDir:'^\.svn$' nimgrep --excludeDir:'^\.git$' --excludeDir:'^\.hg$' --excludeDir:'^\.svn$'
# short: --ed:'^\.git$' --ed:'^\.hg$' --ed:'^\.svn$' # short: --ed:'^\.git$' --ed:'^\.hg$' --ed:'^\.svn$'
```
+ To search only in paths containing the `tests` sub-directory recursively: + To search only in paths containing the `tests` sub-directory recursively:
.. code:: cmd ```cmd
nimgrep --recursive --includeDir:'(^|/)tests($|/)' nimgrep --recursive --includeDir:'(^|/)tests($|/)'
# short: -r --id:'(^|/)tests($|/)' # short: -r --id:'(^|/)tests($|/)'
```
.. Attention:: note the subtle difference between `--excludeDir`:option: and .. Attention:: note the subtle difference between `--excludeDir`:option: and
`--includeDir`:option:\: the former is applied to relative directory entries `--includeDir`:option:\: the former is applied to relative directory entries

View file

@ -118,22 +118,24 @@ NimScript. Similarly, command-line `--FOO:VAL`:option: translates to
Here are few examples of using the `switch` proc: Here are few examples of using the `switch` proc:
.. code-block:: nim ```nim
# command-line: --opt:size # command-line: --opt:size
switch("opt", "size") switch("opt", "size")
# command-line: --define:release or -d:release # command-line: --define:release or -d:release
switch("define", "release") switch("define", "release")
# command-line: --forceBuild # command-line: --forceBuild
switch("forceBuild") switch("forceBuild")
```
NimScripts also support `--`:option: templates for convenience, which look NimScripts also support `--`:option: templates for convenience, which look
like command-line switches written as-is in the NimScript file. So the like command-line switches written as-is in the NimScript file. So the
above example can be rewritten as: above example can be rewritten as:
.. code-block:: nim ```nim
--opt:size --opt:size
--define:release --define:release
--forceBuild --forceBuild
```
**Note**: In general, the *define* switches can also be set in **Note**: In general, the *define* switches can also be set in
NimScripts using `switch` or `--`, as shown in above examples. Few NimScripts using `switch` or `--`, as shown in above examples. Few
@ -148,9 +150,10 @@ The `task` template that the `system` module defines allows a NimScript
file to be used as a build tool. The following example defines a file to be used as a build tool. The following example defines a
task `build` that is an alias for the `c`:option: command: task `build` that is an alias for the `c`:option: command:
.. code-block:: nim ```nim
task build, "builds an example": task build, "builds an example":
setCommand "c" setCommand "c"
```
In fact, as a convention the following tasks should be available: In fact, as a convention the following tasks should be available:
@ -184,8 +187,7 @@ NimScript can also be used directly as a portable replacement for Bash and
Batch files. Use `nim myscript.nims`:cmd: to run ``myscript.nims``. For example, Batch files. Use `nim myscript.nims`:cmd: to run ``myscript.nims``. For example,
installation of Nimble could be accomplished with this simple script: installation of Nimble could be accomplished with this simple script:
.. code-block:: nim ```nim
mode = ScriptMode.Verbose mode = ScriptMode.Verbose
var id = 0 var id = 0
@ -198,16 +200,17 @@ installation of Nimble could be accomplished with this simple script:
exec "nim c nimble" exec "nim c nimble"
mvFile "nimble" & $id & "/src/nimble".toExe, "bin/nimble".toExe mvFile "nimble" & $id & "/src/nimble".toExe, "bin/nimble".toExe
```
On Unix, you can also use the shebang `#!/usr/bin/env nim`, as long as your filename On Unix, you can also use the shebang `#!/usr/bin/env nim`, as long as your filename
ends with ``.nims``: ends with ``.nims``:
.. code-block:: nim ```nim
#!/usr/bin/env nim #!/usr/bin/env nim
mode = ScriptMode.Silent mode = ScriptMode.Silent
echo "hello world" echo "hello world"
```
Use `#!/usr/bin/env -S nim --hints:off` to disable hints. Use `#!/usr/bin/env -S nim --hints:off` to disable hints.
@ -229,8 +232,7 @@ allowing the same script to support a lot of systems.
See the following (incomplete) example: See the following (incomplete) example:
.. code-block:: nim ```nim
import std/distros import std/distros
# Architectures. # Architectures.
@ -256,6 +258,7 @@ See the following (incomplete) example:
echo "Distro is ArchLinux" echo "Distro is ArchLinux"
elif detectOs(Debian): elif detectOs(Debian):
echo "Distro is Debian" echo "Distro is Debian"
```
Uniform Syntax Uniform Syntax
@ -277,21 +280,21 @@ making it ideal for functional scripting metaprogramming.
This is an example of a third party module that uses macros and templates to This is an example of a third party module that uses macros and templates to
translate text strings on unmodified NimScript: translate text strings on unmodified NimScript:
.. code-block:: nim ```nim
import nimterlingua import nimterlingua
nimterlingua("translations.cfg") nimterlingua("translations.cfg")
echo "cat" # Run with -d:RU becomes "kot", -d:ES becomes "gato", ... echo "cat" # Run with -d:RU becomes "kot", -d:ES becomes "gato", ...
```
translations.cfg translations.cfg
.. code-block:: none ```none
[cat] [cat]
ES = gato ES = gato
IT = gatto IT = gatto
RU = kot RU = kot
FR = chat FR = chat
```
* `Nimterlingua <https://nimble.directory/pkg/nimterlingua>`_ * `Nimterlingua <https://nimble.directory/pkg/nimterlingua>`_
@ -305,8 +308,7 @@ but often a graceful and seamless fallback degradation is used.
See the following NimScript: See the following NimScript:
.. code-block:: nim ```nim
if likely(true): if likely(true):
discard discard
elif unlikely(false): elif unlikely(false):
@ -316,6 +318,7 @@ See the following NimScript:
static: static:
echo CompileDate echo CompileDate
```
`likely()`, `unlikely()`, `static:` and `{.compiletime.}` `likely()`, `unlikely()`, `static:` and `{.compiletime.}`

View file

@ -29,8 +29,9 @@ Installation
Nimsuggest is part of Nim's core. Build it via: Nimsuggest is part of Nim's core. Build it via:
.. code:: cmd ```cmd
koch nimsuggest koch nimsuggest
```
Nimsuggest invocation Nimsuggest invocation

View file

@ -48,8 +48,7 @@ The Debian package ships bash and ksh completion and manpages that can be reused
Hints on the build process: Hints on the build process:
.. code:: cmd ```cmd
# build from C sources and then using koch # build from C sources and then using koch
make -j # supports parallel build make -j # supports parallel build
# alternatively: ./build.sh --os $os_type --cpu $cpu_arch # alternatively: ./build.sh --os $os_type --cpu $cpu_arch
@ -66,6 +65,7 @@ Hints on the build process:
# also include the tools # also include the tools
for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn <tempdir>/nim/bin/; done for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn <tempdir>/nim/bin/; done
```
What to install: What to install:

View file

@ -175,8 +175,9 @@ The PEG parser implements this grammar (written in PEG syntax)::
expression, identifiers are not interpreted as non-terminals, but are expression, identifiers are not interpreted as non-terminals, but are
interpreted as verbatim string: interpreted as verbatim string:
.. code-block:: nim ```nim
abc =~ peg"abc" # is true abc =~ peg"abc" # is true
```
So it is not necessary to write ``peg" 'abc' "`` in the above example. So it is not necessary to write ``peg" 'abc' "`` in the above example.
@ -186,22 +187,25 @@ Examples
Check if `s` matches Nim's "while" keyword: Check if `s` matches Nim's "while" keyword:
.. code-block:: nim ```nim
s =~ peg" y'while'" s =~ peg" y'while'"
```
Exchange (key, val)-pairs: Exchange (key, val)-pairs:
.. code-block:: nim ```nim
"key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1") "key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1")
```
Determine the ``#include``'ed files of a C file: Determine the ``#include``'ed files of a C file:
.. code-block:: nim ```nim
for line in lines("myfile.c"): for line in lines("myfile.c"):
if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws
comment <- '/*' @ '*/' / '//' .* comment <- '/*' @ '*/' / '//' .*
ws <- (comment / \s+)* """: ws <- (comment / \s+)* """:
echo matches[0] echo matches[0]
```
PEG vs regular expression PEG vs regular expression
------------------------- -------------------------

View file

@ -16,9 +16,10 @@ defined via `--define:useRealtimeGC`:option: (you can put this into your config
file as well). file as well).
With this switch the garbage collector supports the following operations: With this switch the garbage collector supports the following operations:
.. code-block:: nim ```nim
proc GC_setMaxPause*(maxPauseInUs: int) proc GC_setMaxPause*(maxPauseInUs: int)
proc GC_step*(us: int, strongAdvice = false, stackSize = -1) proc GC_step*(us: int, strongAdvice = false, stackSize = -1)
```
The unit of the parameters `maxPauseInUs` and `us` is microseconds. The unit of the parameters `maxPauseInUs` and `us` is microseconds.
@ -98,9 +99,9 @@ As long as you don't use the threadvar emulation Nim uses native thread
variables, of which you get a fresh version whenever you create a thread. You variables, of which you get a fresh version whenever you create a thread. You
can then attach a GC to this thread via can then attach a GC to this thread via
.. code-block:: nim ```nim
system.setupForeignThreadGc() system.setupForeignThreadGc()
```
It is **not** safe to disable the garbage collector and enable it after the It is **not** safe to disable the garbage collector and enable it after the
call from your background thread even if the code you are calling is short call from your background thread even if the code you are calling is short
@ -109,10 +110,9 @@ lived.
Before the thread exits, you should tear down the thread's GC to prevent memory Before the thread exits, you should tear down the thread's GC to prevent memory
leaks by calling leaks by calling
.. code-block:: nim ```nim
system.tearDownForeignThreadGc() system.tearDownForeignThreadGc()
```
Keeping track of memory Keeping track of memory

View file

@ -13,9 +13,9 @@ range `0 .. MaxSetElements-1` where `MaxSetElements` is currently always
The reason is that sets are implemented as high performance bit vectors. The reason is that sets are implemented as high performance bit vectors.
Attempting to declare a set with a larger type will result in an error: Attempting to declare a set with a larger type will result in an error:
.. code-block:: nim ```nim
var s: set[int64] # Error: set is too large var s: set[int64] # Error: set is too large
```
**Note:** Nim also offers `hash sets <sets.html>`_ (which you need to import **Note:** Nim also offers `hash sets <sets.html>`_ (which you need to import
with `import sets`), which have no such restrictions. with `import sets`), which have no such restrictions.
@ -24,7 +24,7 @@ Sets can be constructed via the set constructor: `{}` is the empty set. The
empty set is type compatible with any concrete set type. The constructor empty set is type compatible with any concrete set type. The constructor
can also be used to include elements (and ranges of elements): can also be used to include elements (and ranges of elements):
.. code-block:: nim ```nim
type type
CharSet = set[char] CharSet = set[char]
var var
@ -32,6 +32,7 @@ can also be used to include elements (and ranges of elements):
x = {'a'..'z', '0'..'9'} # This constructs a set that contains the x = {'a'..'z', '0'..'9'} # This constructs a set that contains the
# letters from 'a' to 'z' and the digits # letters from 'a' to 'z' and the digits
# from '0' to '9' # from '0' to '9'
```
These operations are supported by sets: These operations are supported by sets:
@ -60,8 +61,7 @@ constants that have to be `or`'ed together.
Enum, sets and casting can be used together as in: Enum, sets and casting can be used together as in:
.. code-block:: nim ```nim
type type
MyFlag* {.size: sizeof(cint).} = enum MyFlag* {.size: sizeof(cint).} = enum
A A
@ -79,6 +79,7 @@ Enum, sets and casting can be used together as in:
assert toNum({A, C}) == 5 assert toNum({A, C}) == 5
assert toFlags(0) == {} assert toFlags(0) == {}
assert toFlags(7) == {A, B, C} assert toFlags(7) == {A, B, C}
```
Note how the set turns enum values into powers of 2. Note how the set turns enum values into powers of 2.

View file

@ -28,7 +28,7 @@ the passed expression on the thread pool and returns a `data flow variable`:idx:
**blocking**. However, one can use ``blockUntilAny`` to wait on multiple flow **blocking**. However, one can use ``blockUntilAny`` to wait on multiple flow
variables at the same time: variables at the same time:
.. code-block:: nim ```nim
import std/threadpool, ... import std/threadpool, ...
# wait until 2 out of 3 servers received the update: # wait until 2 out of 3 servers received the update:
@ -40,6 +40,7 @@ variables at the same time:
assert index >= 0 assert index >= 0
responses.del(index) responses.del(index)
discard blockUntilAny(responses) discard blockUntilAny(responses)
```
Data flow variables ensure that no data races Data flow variables ensure that no data races
are possible. Due to technical limitations not every type ``T`` is possible in are possible. Due to technical limitations not every type ``T`` is possible in
@ -54,7 +55,7 @@ Parallel statement
Example: Example:
.. code-block:: nim ```nim
# Compute PI in an inefficient way # Compute PI in an inefficient way
import std/[strutils, math, threadpool] import std/[strutils, math, threadpool]
@ -69,6 +70,7 @@ Example:
result += ch[k] result += ch[k]
echo formatFloat(pi(5000)) echo formatFloat(pi(5000))
```
The parallel statement is the preferred mechanism to introduce parallelism The parallel statement is the preferred mechanism to introduce parallelism

View file

@ -47,8 +47,7 @@ Notation meaning
Examples Examples
======== ========
.. code-block:: nim ```nim
subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)" subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)"
subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied" subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied"
@ -57,5 +56,5 @@ Examples
subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [ subex("type\n TEnum = enum\n $', '40c'\n '{..}") % [
"fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"]
```

View file

@ -53,29 +53,29 @@ Running a single test
This is a minimal example to understand the basics, This is a minimal example to understand the basics,
not very useful for production, but easy to understand: not very useful for production, but easy to understand:
.. code:: console ```console
$ mkdir tests $ mkdir tests
$ echo "assert 42 == 42" > tests/test0.nim $ echo "assert 42 == 42" > tests/test0.nim
$ testament run test0.nim $ testament run test0.nim
PASS: tests/test0.nim C ( 0.2 sec) PASS: tests/test0.nim C ( 0.2 sec)
$ testament r test0 $ testament r test0
PASS: tests/test0.nim C ( 0.2 sec) PASS: tests/test0.nim C ( 0.2 sec)
```
Running all tests from a directory Running all tests from a directory
================================== ==================================
.. code:: console ```console
$ testament pattern "tests/*.nim" $ testament pattern "tests/*.nim"
```
To search for tests deeper in a directory, use To search for tests deeper in a directory, use
.. code:: console ```console
$ testament pattern "tests/**/*.nim" # one level deeper $ testament pattern "tests/**/*.nim" # one level deeper
$ testament pattern "tests/**/**/*.nim" # two levels deeper $ testament pattern "tests/**/**/*.nim" # two levels deeper
```
HTML Reports HTML Reports
============ ============
@ -83,9 +83,9 @@ HTML Reports
Generate HTML Reports ``testresults.html`` from unittests, Generate HTML Reports ``testresults.html`` from unittests,
you have to run at least 1 test *before* generating a report: you have to run at least 1 test *before* generating a report:
.. code:: console ```console
$ testament html $ testament html
```
Writing Unit tests Writing Unit tests
@ -93,8 +93,7 @@ Writing Unit tests
Example "template" **to edit** and write a Testament unittest: Example "template" **to edit** and write a Testament unittest:
.. code-block:: nim ```nim
discard """ discard """
# What actions to expect completion on. # What actions to expect completion on.
@ -182,6 +181,7 @@ Example "template" **to edit** and write a Testament unittest:
""" """
assert true assert true
assert 42 == 42, "Assert error message" assert 42 == 42, "Assert error message"
```
* As you can see the "Spec" is just a `discard """ """`. * As you can see the "Spec" is just a `discard """ """`.
@ -197,26 +197,25 @@ Unit test Examples
Expected to fail: Expected to fail:
.. code-block:: nim ```nim
discard """ discard """
errormsg: "undeclared identifier: 'not_defined'" errormsg: "undeclared identifier: 'not_defined'"
""" """
assert not_defined == "not_defined", "not_defined is not defined" assert not_defined == "not_defined", "not_defined is not defined"
```
Non-Zero exit code: Non-Zero exit code:
.. code-block:: nim ```nim
discard """ discard """
exitcode: 1 exitcode: 1
""" """
quit "Non-Zero exit code", 1 quit "Non-Zero exit code", 1
```
Standard output checking: Standard output checking:
.. code-block:: nim ```nim
discard """ discard """
output: ''' output: '''
@ -230,32 +229,33 @@ Standard output checking:
""" """
for i in 0..5: echo i for i in 0..5: echo i
```
JavaScript tests: JavaScript tests:
.. code-block:: nim ```nim
discard """ discard """
targets: "js" targets: "js"
""" """
when defined(js): when defined(js):
import std/jsconsole import std/jsconsole
console.log("My Frontend Project") console.log("My Frontend Project")
```
Compile-time tests: Compile-time tests:
.. code-block:: nim ```nim
discard """ discard """
action: "compile" action: "compile"
""" """
static: assert 9 == 9, "Compile time assert" static: assert 9 == 9, "Compile time assert"
```
Tests without Spec: Tests without Spec:
.. code-block:: nim ```nim
assert 1 == 1 assert 1 == 1
```
See also: See also:

File diff suppressed because it is too large Load diff

View file

@ -53,8 +53,7 @@ types with inheritance are also marked as `ref` types even though
this isn't strictly enforced. To check at runtime if an object is of a certain this isn't strictly enforced. To check at runtime if an object is of a certain
type, the `of` operator can be used. type, the `of` operator can be used.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
Person = ref object of RootObj Person = ref object of RootObj
name*: string # the * means that `name` is accessible from other modules name*: string # the * means that `name` is accessible from other modules
@ -70,6 +69,7 @@ type, the `of` operator can be used.
# object construction: # object construction:
student = Student(name: "Anton", age: 5, id: 2) student = Student(name: "Anton", age: 5, id: 2)
echo student[] echo student[]
```
Inheritance is done with the `object of` syntax. Multiple inheritance is Inheritance is done with the `object of` syntax. Multiple inheritance is
currently not supported. If an object type has no suitable ancestor, `RootObj` currently not supported. If an object type has no suitable ancestor, `RootObj`
@ -97,8 +97,7 @@ would require arbitrary symbol lookahead which slows down compilation.)
Example: Example:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
Node = ref object # a reference to an object with the following field: Node = ref object # a reference to an object with the following field:
le, ri: Node # left and right subtrees le, ri: Node # left and right subtrees
@ -108,6 +107,7 @@ Example:
name: string # the symbol's name name: string # the symbol's name
line: int # the line the symbol was declared in line: int # the line the symbol was declared in
code: Node # the symbol's abstract syntax tree code: Node # the symbol's abstract syntax tree
```
Type conversions Type conversions
@ -124,9 +124,10 @@ raised.
The syntax for type conversions is `destination_type(expression_to_convert)` The syntax for type conversions is `destination_type(expression_to_convert)`
(like an ordinary call): (like an ordinary call):
.. code-block:: nim ```nim
proc getID(x: Person): int = proc getID(x: Person): int =
Student(x).id Student(x).id
```
The `InvalidObjectConversionDefect` exception is raised if `x` is not a The `InvalidObjectConversionDefect` exception is raised if `x` is not a
`Student`. `Student`.
@ -139,9 +140,7 @@ variant types are needed.
An example: An example:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
# This is an example how an abstract syntax tree could be modelled in Nim # This is an example how an abstract syntax tree could be modelled in Nim
type type
NodeKind = enum # the different node types NodeKind = enum # the different node types
@ -165,6 +164,7 @@ An example:
# the following statement raises an `FieldDefect` exception, because # the following statement raises an `FieldDefect` exception, because
# n.kind's value does not fit: # n.kind's value does not fit:
n.strVal = "" n.strVal = ""
```
As can been seen from the example, an advantage to an object hierarchy is that As can been seen from the example, an advantage to an object hierarchy is that
no conversion between different object types is needed. Yet, access to invalid no conversion between different object types is needed. Yet, access to invalid
@ -183,27 +183,27 @@ If there are no remaining arguments, the parentheses can be omitted:
This method call syntax is not restricted to objects, it can be used This method call syntax is not restricted to objects, it can be used
for any type: for any type:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/strutils import std/strutils
echo "abc".len # is the same as echo len("abc") echo "abc".len # is the same as echo len("abc")
echo "abc".toUpperAscii() echo "abc".toUpperAscii()
echo({'a', 'b', 'c'}.card) echo({'a', 'b', 'c'}.card)
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo") stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
```
(Another way to look at the method call syntax is that it provides the missing (Another way to look at the method call syntax is that it provides the missing
postfix notation.) postfix notation.)
So "pure object oriented" code is easy to write: So "pure object oriented" code is easy to write:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/[strutils, sequtils] import std/[strutils, sequtils]
stdout.writeLine("Give a list of numbers (separated by spaces): ") stdout.writeLine("Give a list of numbers (separated by spaces): ")
stdout.write(stdin.readLine.splitWhitespace.map(parseInt).max.`$`) stdout.write(stdin.readLine.splitWhitespace.map(parseInt).max.`$`)
stdout.writeLine(" is the maximum!") stdout.writeLine(" is the maximum!")
```
Properties Properties
@ -213,9 +213,7 @@ Ordinary get-procedures that are called with the *method call syntax* achieve
the same. But setting a value is different; for this a special setter syntax the same. But setting a value is different; for this a special setter syntax
is needed: is needed:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
Socket* = ref object of RootObj Socket* = ref object of RootObj
h: int # cannot be accessed from the outside of the module due to missing star h: int # cannot be accessed from the outside of the module due to missing star
@ -231,6 +229,7 @@ is needed:
var s: Socket var s: Socket
new s new s
s.host = 34 # same as `host=`(s, 34) s.host = 34 # same as `host=`(s, 34)
```
(The example also shows `inline` procedures.) (The example also shows `inline` procedures.)
@ -238,8 +237,7 @@ is needed:
The `[]` array access operator can be overloaded to provide The `[]` array access operator can be overloaded to provide
`array properties`:idx:\ : `array properties`:idx:\ :
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
Vector* = object Vector* = object
x, y, z: float x, y, z: float
@ -259,6 +257,7 @@ The `[]` array access operator can be overloaded to provide
of 1: result = v.y of 1: result = v.y
of 2: result = v.z of 2: result = v.z
else: assert(false) else: assert(false)
```
The example is silly, since a vector is better modelled by a tuple which The example is silly, since a vector is better modelled by a tuple which
already provides `v[]` access. already provides `v[]` access.
@ -270,8 +269,7 @@ Dynamic dispatch
Procedures always use static dispatch. For dynamic dispatch replace the Procedures always use static dispatch. For dynamic dispatch replace the
`proc` keyword by `method`: `proc` keyword by `method`:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
Expression = ref object of RootObj ## abstract base class for an expression Expression = ref object of RootObj ## abstract base class for an expression
Literal = ref object of Expression Literal = ref object of Expression
@ -291,6 +289,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b) proc newPlus(a, b: Expression): PlusExpr = PlusExpr(a: a, b: b)
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4))) echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
```
Note that in the example the constructors `newLit` and `newPlus` are procs Note that in the example the constructors `newLit` and `newPlus` are procs
because it makes more sense for them to use static binding, but `eval` is a because it makes more sense for them to use static binding, but `eval` is a
@ -302,9 +301,7 @@ method because it requires dynamic binding.
In a multi-method all parameters that have an object type are used for the In a multi-method all parameters that have an object type are used for the
dispatching: dispatching:
.. code-block:: nim ```nim test = "nim c --multiMethods:on $1"
:test: "nim c --multiMethods:on $1"
type type
Thing = ref object of RootObj Thing = ref object of RootObj
Unit = ref object of Thing Unit = ref object of Thing
@ -323,6 +320,7 @@ dispatching:
new a new a
new b new b
collide(a, b) # output: 2 collide(a, b) # output: 2
```
As the example demonstrates, invocation of a multi-method cannot be ambiguous: As the example demonstrates, invocation of a multi-method cannot be ambiguous:
@ -355,20 +353,21 @@ Raise statement
--------------- ---------------
Raising an exception is done with the `raise` statement: Raising an exception is done with the `raise` statement:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
var var
e: ref OSError e: ref OSError
new(e) new(e)
e.msg = "the request to the OS failed" e.msg = "the request to the OS failed"
raise e raise e
```
If the `raise` keyword is not followed by an expression, the last exception If the `raise` keyword is not followed by an expression, the last exception
is *re-raised*. For the purpose of avoiding repeating this common code pattern, is *re-raised*. For the purpose of avoiding repeating this common code pattern,
the template `newException` in the `system` module can be used: the template `newException` in the `system` module can be used:
.. code-block:: nim ```nim
raise newException(OSError, "the request to the OS failed") raise newException(OSError, "the request to the OS failed")
```
Try statement Try statement
@ -376,8 +375,7 @@ Try statement
The `try` statement handles exceptions: The `try` statement handles exceptions:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
from std/strutils import parseInt from std/strutils import parseInt
# read the first two lines of a text file that should contain numbers # read the first two lines of a text file that should contain numbers
@ -401,6 +399,7 @@ The `try` statement handles exceptions:
raise raise
finally: finally:
close(f) close(f)
```
The statements after the `try` are executed unless an exception is The statements after the `try` are executed unless an exception is
raised. Then the appropriate `except` part is executed. raised. Then the appropriate `except` part is executed.
@ -423,7 +422,7 @@ If you need to *access* the actual exception object or message inside an
<system.html#getCurrentExceptionMsg>`_ procs from the `system <system.html>`_ <system.html#getCurrentExceptionMsg>`_ procs from the `system <system.html>`_
module. Example: module. Example:
.. code-block:: nim ```nim
try: try:
doSomethingHere() doSomethingHere()
except: except:
@ -431,6 +430,7 @@ module. Example:
e = getCurrentException() e = getCurrentException()
msg = getCurrentExceptionMsg() msg = getCurrentExceptionMsg()
echo "Got exception ", repr(e), " with message ", msg echo "Got exception ", repr(e), " with message ", msg
```
Annotating procs with raised exceptions Annotating procs with raised exceptions
@ -443,12 +443,13 @@ instance, if you specify that a proc raises `IOError`, and at some point it
(or one of the procs it calls) starts raising a new exception the compiler will (or one of the procs it calls) starts raising a new exception the compiler will
prevent that proc from compiling. Usage example: prevent that proc from compiling. Usage example:
.. code-block:: nim ```nim
proc complexProc() {.raises: [IOError, ArithmeticDefect].} = proc complexProc() {.raises: [IOError, ArithmeticDefect].} =
... ...
proc simpleProc() {.raises: [].} = proc simpleProc() {.raises: [].} =
... ...
```
Once you have code like this in place, if the list of raised exception changes Once you have code like this in place, if the list of raised exception changes
the compiler will stop with an error specifying the line of the proc which the compiler will stop with an error specifying the line of the proc which
@ -474,8 +475,7 @@ with `type parameters`:idx:. Generic parameters are written within square
brackets, for example `Foo[T]`. They are most useful for efficient type safe brackets, for example `Foo[T]`. They are most useful for efficient type safe
containers: containers:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
type type
BinaryTree*[T] = ref object # BinaryTree is a generic type with BinaryTree*[T] = ref object # BinaryTree is a generic type with
# generic param `T` # generic param `T`
@ -530,6 +530,7 @@ containers:
add(root, "world") # instantiates the second `add` proc add(root, "world") # instantiates the second `add` proc
for str in preorder(root): for str in preorder(root):
stdout.writeLine(str) stdout.writeLine(str)
```
The example shows a generic binary tree. Depending on context, the brackets are The example shows a generic binary tree. Depending on context, the brackets are
used either to introduce type parameters or to instantiate a generic proc, used either to introduce type parameters or to instantiate a generic proc,
@ -539,8 +540,7 @@ is not hidden and is used in the `preorder` iterator.
There is a special `[:T]` syntax when using generics with the method call syntax: There is a special `[:T]` syntax when using generics with the method call syntax:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
proc foo[T](i: T) = proc foo[T](i: T) =
discard discard
@ -549,6 +549,7 @@ There is a special `[:T]` syntax when using generics with the method call syntax
# i.foo[int]() # Error: expression 'foo(i)' has no type (or is ambiguous) # i.foo[int]() # Error: expression 'foo(i)' has no type (or is ambiguous)
i.foo[:int]() # Success i.foo[:int]() # Success
```
Templates Templates
@ -563,12 +564,13 @@ To *invoke* a template, call it like a procedure.
Example: Example:
.. code-block:: nim ```nim
template `!=` (a, b: untyped): untyped = template `!=` (a, b: untyped): untyped =
# this definition exists in the System module # this definition exists in the System module
not (a == b) not (a == b)
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6)) assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
```
The `!=`, `>`, `>=`, `in`, `notin`, `isnot` operators are in fact The `!=`, `>`, `>=`, `in`, `notin`, `isnot` operators are in fact
templates: this has the benefit that if you overload the `==` operator, templates: this has the benefit that if you overload the `==` operator,
@ -582,8 +584,7 @@ for IEEE floating point numbers - NaN breaks basic boolean logic.)
Templates are especially useful for lazy evaluation purposes. Consider a Templates are especially useful for lazy evaluation purposes. Consider a
simple proc for logging: simple proc for logging:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
const const
debug = true debug = true
@ -593,6 +594,7 @@ simple proc for logging:
var var
x = 4 x = 4
log("x has the value: " & $x) log("x has the value: " & $x)
```
This code has a shortcoming: if `debug` is set to false someday, the quite This code has a shortcoming: if `debug` is set to false someday, the quite
expensive `$` and `&` operations are still performed! (The argument expensive `$` and `&` operations are still performed! (The argument
@ -600,8 +602,7 @@ evaluation for procedures is *eager*).
Turning the `log` proc into a template solves this problem: Turning the `log` proc into a template solves this problem:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
const const
debug = true debug = true
@ -611,6 +612,7 @@ Turning the `log` proc into a template solves this problem:
var var
x = 4 x = 4
log("x has the value: " & $x) log("x has the value: " & $x)
```
The parameters' types can be ordinary types or the meta types `untyped`, The parameters' types can be ordinary types or the meta types `untyped`,
`typed`, or `type`. `type` suggests that only a type symbol may be given `typed`, or `type`. `type` suggests that only a type symbol may be given
@ -622,9 +624,7 @@ If the template has no explicit return type,
To pass a block of statements to a template, use `untyped` for the last parameter: To pass a block of statements to a template, use `untyped` for the last parameter:
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
template withFile(f: untyped, filename: string, mode: FileMode, template withFile(f: untyped, filename: string, mode: FileMode,
body: untyped) = body: untyped) =
let fn = filename let fn = filename
@ -640,6 +640,7 @@ To pass a block of statements to a template, use `untyped` for the last paramete
withFile(txt, "ttempl3.txt", fmWrite): withFile(txt, "ttempl3.txt", fmWrite):
txt.writeLine("line 1") txt.writeLine("line 1")
txt.writeLine("line 2") txt.writeLine("line 2")
```
In the example the two `writeLine` statements are bound to the `body` In the example the two `writeLine` statements are bound to the `body`
parameter. The `withFile` template contains boilerplate code and helps to parameter. The `withFile` template contains boilerplate code and helps to
@ -650,8 +651,7 @@ once.
Example: Lifting Procs Example: Lifting Procs
---------------------- ----------------------
.. code-block:: nim `````nim test = "nim c $1"
:test: "nim c $1"
import std/math import std/math
template liftScalarProc(fname) = template liftScalarProc(fname) =
@ -660,9 +660,10 @@ Example: Lifting Procs
## to provide templated procs that can handle a single ## to provide templated procs that can handle a single
## parameter of seq[T] or nested seq[seq[]] or the same type ## parameter of seq[T] or nested seq[seq[]] or the same type
## ##
## .. code-block:: Nim ## ```Nim
## liftScalarProc(abs) ## liftScalarProc(abs)
## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]] ## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]
## ```
proc fname[T](x: openarray[T]): auto = proc fname[T](x: openarray[T]): auto =
var temp: T var temp: T
type outType = typeof(fname(temp)) type outType = typeof(fname(temp))
@ -672,6 +673,7 @@ Example: Lifting Procs
liftScalarProc(sqrt) # make sqrt() work for sequences liftScalarProc(sqrt) # make sqrt() work for sequences
echo sqrt(@[4.0, 16.0, 25.0, 36.0]) # => @[2.0, 4.0, 5.0, 6.0] echo sqrt(@[4.0, 16.0, 25.0, 36.0]) # => @[2.0, 4.0, 5.0, 6.0]
`````
Compilation to JavaScript Compilation to JavaScript
========================= =========================

View file

@ -91,14 +91,14 @@ in the expression `foo(x)`, `x` needs to be an integer constant,
but in the macro body `arg` is just like a normal parameter of type but in the macro body `arg` is just like a normal parameter of type
`int`. `int`.
.. code-block:: nim ```nim
import std/macros import std/macros
macro myMacro(arg: static[int]): untyped = macro myMacro(arg: static[int]): untyped =
echo arg # just an int (7), not `NimNode` echo arg # just an int (7), not `NimNode`
myMacro(1 + 2 * 3) myMacro(1 + 2 * 3)
```
Code Blocks as Arguments Code Blocks as Arguments
@ -108,12 +108,12 @@ It is possible to pass the last argument of a call expression in a
separate code block with indentation. For example, the following code separate code block with indentation. For example, the following code
example is a valid (but not a recommended) way to call `echo`: example is a valid (but not a recommended) way to call `echo`:
.. code-block:: nim ```nim
echo "Hello ": echo "Hello ":
let a = "Wor" let a = "Wor"
let b = "ld!" let b = "ld!"
a & b a & b
```
For macros this way of calling is very useful; syntax trees of arbitrary For macros this way of calling is very useful; syntax trees of arbitrary
complexity can be passed to macros with this notation. complexity can be passed to macros with this notation.
@ -134,8 +134,7 @@ and for debug printing of generated syntax tree. `dumpTree` is a
predefined macro that just prints its argument in a tree representation, predefined macro that just prints its argument in a tree representation,
but does nothing else. Here is an example of such a tree representation: but does nothing else. Here is an example of such a tree representation:
.. code-block:: nim ```nim
dumpTree: dumpTree:
var mt: MyType = MyType(a:123.456, b:"abcdef") var mt: MyType = MyType(a:123.456, b:"abcdef")
@ -153,6 +152,7 @@ but does nothing else. Here is an example of such a tree representation:
# ExprColonExpr # ExprColonExpr
# Ident "b" # Ident "b"
# StrLit "abcdef" # StrLit "abcdef"
```
Custom Semantic Checking Custom Semantic Checking
@ -166,10 +166,10 @@ macro evaluation should be caught and create a nice error message.
the checks need to be more complex, arbitrary error messages can the checks need to be more complex, arbitrary error messages can
be created with the `macros.error` proc. be created with the `macros.error` proc.
.. code-block:: nim ```nim
macro myAssert(arg: untyped): untyped = macro myAssert(arg: untyped): untyped =
arg.expectKind nnkInfix arg.expectKind nnkInfix
```
Generating Code Generating Code
@ -187,36 +187,36 @@ tree with calls to `newTree` and `newLit` the macro
Backticks are used to insert code from `NimNode` symbols into the Backticks are used to insert code from `NimNode` symbols into the
generated expression. generated expression.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
macro a(i) = quote do: macro a(i) = quote do:
let `i` = 0 let `i` = 0
a b a b
doAssert b == 0 doAssert b == 0
```
A custom prefix operator can be defined whenever backticks are needed. A custom prefix operator can be defined whenever backticks are needed.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
macro a(i) = quote("@") do: macro a(i) = quote("@") do:
assert @i == 0 assert @i == 0
let b = 0 let b = 0
a b a b
```
The injected symbol needs accent quoted when it resolves to a symbol. The injected symbol needs accent quoted when it resolves to a symbol.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
macro a(i) = quote("@") do: macro a(i) = quote("@") do:
let `@i` = 0 let `@i` = 0
a b a b
doAssert b == 0 doAssert b == 0
```
Make sure to inject only symbols of type `NimNode` into the generated syntax Make sure to inject only symbols of type `NimNode` into the generated syntax
tree. You can use `newLit` to convert arbitrary values into tree. You can use `newLit` to convert arbitrary values into
@ -224,9 +224,7 @@ expressions trees of type `NimNode` so that it is safe to inject
them into the tree. them into the tree.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
type type
@ -246,12 +244,14 @@ them into the tree.
echo `mtLit` echo `mtLit`
myMacro("Hallo") myMacro("Hallo")
```
The call to `myMacro` will generate the following code: The call to `myMacro` will generate the following code:
.. code-block:: nim ```nim
echo "Hallo" echo "Hallo"
echo MyType(a: 123.456'f64, b: "abcdef") echo MyType(a: 123.456'f64, b: "abcdef")
```
Building Your First Macro Building Your First Macro
@ -263,9 +263,7 @@ do is to build a simple example of the macro usage, and then just
print the argument. This way it is possible to get an idea of what a print the argument. This way it is possible to get an idea of what a
correct argument should look like. correct argument should look like.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
macro myAssert(arg: untyped): untyped = macro myAssert(arg: untyped): untyped =
@ -275,13 +273,14 @@ correct argument should look like.
let b = 2 let b = 2
myAssert(a != b) myAssert(a != b)
```
.. code-block:: ```
Infix Infix
Ident "!=" Ident "!="
Ident "a" Ident "a"
Ident "b" Ident "b"
```
From the output, it is possible to see that the argument is an infix From the output, it is possible to see that the argument is an infix
@ -289,9 +288,7 @@ operator (node kind is "Infix"), as well as that the two operands are
at index 1 and 2. With this information, the actual macro can be at index 1 and 2. With this information, the actual macro can be
written. written.
.. code-block:: nim ```nim test = "nim c $1"
:test: "nim c $1"
import std/macros import std/macros
macro myAssert(arg: untyped): untyped = macro myAssert(arg: untyped): untyped =
@ -312,6 +309,7 @@ written.
myAssert(a != b) myAssert(a != b)
myAssert(a == b) myAssert(a == b)
```
This is the code that will be generated. To debug what the macro This is the code that will be generated. To debug what the macro
@ -319,9 +317,10 @@ actually generated, the statement `echo result.repr` can be used, in
the last line of the macro. It is also the statement that has been the last line of the macro. It is also the statement that has been
used to get this output. used to get this output.
.. code-block:: nim ```nim
if not (a != b): if not (a != b):
raise newException(AssertionDefect, $a & " != " & $b) raise newException(AssertionDefect, $a & " != " & $b)
```
With Power Comes Responsibility With Power Comes Responsibility
------------------------------- -------------------------------