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
parent 60f6724b70
commit 1c31de361d
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:
.. code-block::
```
<html><body>
<script type="text/javascript">
function addTwoIntegers(a, b)
@@ -209,6 +208,7 @@ Create a ``host.html`` file with the following content:
</script>
<script type="text/javascript" src="calculator.js"></script>
</body></html>
```
Create a ``calculator.nim`` file with the following content (or reuse the one
from the previous section):

View File

@@ -67,11 +67,12 @@ Basic Markdown syntax is also supported inside the doc comments.
Example:
.. code-block:: nim
```nim
type Person* = object
## This type contains a description of a person
name: string
age: int
```
Outputs::
Person* = object
@@ -82,9 +83,10 @@ Outputs::
Field documentation comments can be added to fields like so:
.. code-block:: nim
```nim
var numValues: int ## \
## `numValues` stores the number of values
```
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
@@ -102,12 +104,13 @@ won't influence RST formatting.
If you still need to add an additional indentation at the very beginning
(for RST block quote syntax) use backslash \\ before it:
.. code-block:: nim
## \
##
## Block quote at the first line.
##
## Paragraph.
```nim
## \
##
## Block quote at the first line.
##
## Paragraph.
```
Document Types
@@ -248,9 +251,9 @@ the anchor [*]_ of Nim symbol that corresponds to link text.
If you have a constant:
```Nim
const pi* = 3.14
```
```Nim
const pi* = 3.14
```
then it should be referenced in one of the 2 forms:
@@ -261,9 +264,9 @@ B. qualified (with symbol kind specification)::
For routine kinds there are more options. Consider this definition:
```Nim
proc foo*(a: int, b: float): string
```
```Nim
proc foo*(a: int, b: float): string
```
Generally following syntax is allowed for referencing `foo`:

View File

@@ -72,12 +72,12 @@ Whenever an example of usage would be helpful to the user, you should include on
## 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")
## drawOnScreen()
## ```
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
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:
.. code-block:: nim
:test: "nim c --warningAsError:Effect:on $1"
:status: 1
```nim test = "nim c --warningAsError:Effect:on $1" status = 1
type IO = object ## input/output effect
proc readLine(): string {.tags: [IO].} = discard
proc echoLine(): void = discard
@@ -5096,13 +5093,14 @@ There is also a way which can be used to forbid certain effects:
echoLine()
# the compiler prevents this:
let y = readLine()
```
The `forbids` pragma defines a list of illegal effects - if any statement
invokes any of those effects, the compilation will fail.
Procedure types with any disallowed effect are the subtypes of equal
procedure types without such lists:
.. code-block:: nim
```nim
type MyEffect = object
type ProcType1 = proc (i: int): void {.forbids: [MyEffect].}
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:
caller2(toBeCalled1)
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.
@@ -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
spelled*:
.. code-block::
```nim
proc printf(formatstr: cstring) {.header: "<stdio.h>", importc: "printf", varargs.}
```
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:\:
.. code-block::
```nim
{.emit: "const int cconst = 42;".}
let cconst {.importc, nodecl.}: cint
assert cconst == 42
```
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

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)
then it has to be derived from the routine's first parameter:
.. code-block:: nim
```nim
proc forward[T](x: var T): var T =
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`
# which is not p's first parameter and lives
# on the stack.
```
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

View File

@@ -6,13 +6,15 @@ Strict not nil checking
**Note:** This feature is experimental, you need to enable it with
.. code-block:: nim
```nim
{.experimental: "strictNotNil".}
```
or
.. code-block:: cmd
```cmd
nim c --experimental:strictNotNil <program>
```
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`.
.. code-block:: nim
```nim
type
NilableObject = ref object
a: int
@@ -57,6 +59,7 @@ You can annotate a type where nil isn't a valid value with `not nil`.
p(x)
else:
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.
.. code-block:: nim
```nim
callByVar(a)
```
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).
.. code-block:: nim
```nim
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`.
@@ -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:
.. code-block:: nim
```nim
template union(l: Nilability, r: Nilability): Nilability =
## unify two states
if l == r:
l
else:
MaybeNil
```
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:
.. code-block:: nim
```nim
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.
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.
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:
if not a.isNil:
b()
break
code # here a: Nil , because if not, we would have breaked
```
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.
This means it stops being aliased with its previous aliases.
.. code-block:: nim
```nim
var left = b
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.
e.g.
.. code-block:: nim
```nim
var left = b
left = nil # moving out
```
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
long sections of code by hand can quickly become tedious.
.. code-block:: nim
```nim
# This is bad, as the next time someone comes
# to edit this code block, they
# must re-align all the assignments again:
@@ -60,6 +60,7 @@ Spacing and Whitespace Conventions
CalId* = int
LongLong* = int64
LongLongPtr* = ptr LongLong
```
Naming Conventions
@@ -69,7 +70,7 @@ Naming Conventions
camelCase with the exception of constants which **may** use PascalCase but
are not required to.
.. code-block:: nim
```nim
# Constants can start with either a lower case or upper case letter.
const aConstant = 42
const FooBar = 4.2
@@ -79,6 +80,7 @@ Naming Conventions
# Types must start with an uppercase letter.
type
FooBar = object
```
For constants coming from a C/C++ wrapper, ALL_UPPERCASE are allowed, but ugly.
(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
same applies to C/C++ wrappers.
.. code-block:: nim
```nim
type
Handle = object # Will be used most often
fd: int64
HandleRef = ref Handle # Will be used less often
```
- Exception and Error types should have the "Error" or "Defect" suffix.
.. code-block:: nim
```nim
type
ValueError = object of CatchableError
AssertionDefect = object of 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
identifying prefix, such as an abbreviation of the enum's name.
.. code-block:: nim
```nim
type
PathComponent = enum
pcDir
pcLinkToDir
pcFile
pcLinkToFile
```
- Non-pure enum values should use camelCase whereas pure enum values should use
PascalCase.
.. code-block:: nim
```nim
type
PathComponent {.pure.} = enum
Dir
LinkToDir
File
LinkToFile
```
- 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
@@ -230,12 +236,13 @@ Coding Conventions
are required. Use a procedure's implicit `result` variable whenever possible.
This improves readability.
.. code-block:: nim
```nim
proc repeat(text: string, x: int): string =
result = ""
for i in 0..x:
result.add($i)
```
- Use a proc when possible, only using the more powerful facilities of macros,
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
align with the parameters above it.
.. code-block:: nim
```nim
type
LongTupleA = tuple[wordyTupleMemberOne: int, wordyTupleMemberTwo: string,
wordyTupleMemberThree: float]
```
- Similarly, any procedure and procedure type declarations that are longer
than one line should do the same thing.
.. code-block:: nim
```nim
type
EventCallback = proc (timeReceived: Time, errorCode: int, event: Event,
output: var string)
@@ -268,13 +276,15 @@ Conventions for multi-line statements and expressions
proc lotsOfArguments(argOne: string, argTwo: int, argThree: float,
argFour: proc(), argFive: bool): int
{.heyLookALongPragma.} =
```
- Multi-line procedure calls should continue on the same column as the opening
parenthesis (like multi-line procedure declarations).
.. code-block:: nim
```nim
startProcess(nimExecutable, currentDirectory, compilerArguments
environment, processOptions)
```
Miscellaneous
-------------
@@ -290,18 +300,20 @@ Miscellaneous
use this:
.. code-block:: nim
```nim
let a = """
foo
bar
"""
```
instead of:
.. code-block:: nim
```nim
let a = """foo
bar
"""
```
- 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:

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
`release build`:idx: define the `release` symbol:
.. code:: cmd
```cmd
nim c -d:release myproject.nim
```
To compile a `dangerous release build`:idx: define the `danger` symbol:
.. code:: cmd
```cmd
nim c -d:danger myproject.nim
```
Search path handling
@@ -281,9 +281,9 @@ Compiler Selection
To change the compiler from the default compiler (at the command line):
.. code:: cmd
```cmd
nim c --cc:llvm_gcc --compile_only myfile.nim
```
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:
.. code:: cmd
```cmd
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
Linux i386 machine and run the script.
Another way is to make Nim invoke a cross compiler toolchain:
.. code:: cmd
```cmd
nim c --cpu:arm --os:linux myproject.nim
```
For cross compilation, the compiler invokes a C compiler named
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:
.. code:: cmd
```cmd
nim c -d:mingw myproject.nim
# `nim r` also works, running the binary via `wine` or `wine64`:
nim r -d:mingw --eval:'import os; echo "a" / "b"'
```
Use `--cpu:i386`:option: or `--cpu:amd64`:option: to switch the CPU architecture.
The MinGW-w64 toolchain can be installed as follows:
.. code:: cmd
```cmd
apt install mingw-w64 # Ubuntu
yum install mingw32-gcc
yum install mingw64-gcc # CentOS - requires EPEL
brew install mingw-w64 # OSX
```
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
of your program.
.. code-block:: Nim
```Nim
proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
NimMain() # initialize garbage collector memory, types and stack
```
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
of your program.
.. code-block:: Nim
```Nim
proc NimMain() {.importc.}
proc glfmMain*(display: ptr GLFMDisplay) {.exportc.} =
NimMain() # initialize garbage collector memory, types and stack
```
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.
@@ -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:
and `passL`:option: command line switches to something like:
.. code-block:: cmd
```cmd
nim c ... --d:nimAllocPagesViaMalloc --mm:orc --passC="-I$DEVKITPRO/libnx/include" ...
--passL="-specs=$DEVKITPRO/libnx/switch.specs -L$DEVKITPRO/libnx/lib -lnx"
```
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:
.. code:: cmd
```cmd
nim c --os:nintendoswitch switchhomebrew.nim
```
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
@@ -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
on ``nimrtl.dll``. To generate the "nimrtl.dll" file, use the command:
.. code:: cmd
```cmd
nim c -d:release lib/nimrtl.nim
```
To link against ``nimrtl.dll`` use the command:
.. code:: cmd
```cmd
nim c -d:useNimRtl myprog.nim
```
**Note**: Currently the creation of ``nimrtl.dll`` with thread support has
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
on Linux:
.. code:: cmd
```cmd
nim c --dynlibOverride:lua --passL:liblua.lib program.nim
```
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
`malloc` memory allocator and the `arc` garbage collector. For example:
.. code:: cmd
nim c --os:any --mm:arc -d:useMalloc [...] x.nim
```cmd
nim c --os:any --mm:arc -d:useMalloc [...] x.nim
```
- `--mm:arc`:option: will enable the reference counting memory management instead
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.
Thus it is efficient to do:
.. code-block:: Nim
```Nim
var s = procA() # assignment will not copy the string; procA allocates a new
# string already
```
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!
```
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
```
If you know what you're doing, you can also mark single-string (or sequence)
objects as `shallow`:idx:\:
.. code-block:: Nim
```Nim
var s = "abc"
shallow(s) # mark 's' as a shallow 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
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
efficient:
.. code-block:: Nim
```Nim
case normalize(k.key)
of "name": c.name = v
of "displayname": c.displayName = v
@@ -807,3 +812,4 @@ efficient:
else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = UnixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key))
```

View File

@@ -22,8 +22,9 @@ Installation
Compile nimgrep with the command:
.. code:: cmd
```cmd
nim c -d:release tools/nimgrep.nim
```
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:
.. code:: cmd
```cmd
nimgrep --recursive --ext:'nim|nims' --ignoreStyle
# short: -r --ext:'nim|nims' -y
```
.. Note:: we used `'` quotes to avoid special treatment of `|` symbol
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)
from the search:
.. code:: cmd
```cmd
nimgrep --excludeDir:'^\.git$' --excludeDir:'^\.hg$' --excludeDir:'^\.svn$'
# short: --ed:'^\.git$' --ed:'^\.hg$' --ed:'^\.svn$'
```
+ To search only in paths containing the `tests` sub-directory recursively:
.. code:: cmd
```cmd
nimgrep --recursive --includeDir:'(^|/)tests($|/)'
# short: -r --id:'(^|/)tests($|/)'
```
.. Attention:: note the subtle difference between `--excludeDir`:option: and
`--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:
.. code-block:: nim
```nim
# command-line: --opt:size
switch("opt", "size")
# command-line: --define:release or -d:release
switch("define", "release")
# command-line: --forceBuild
switch("forceBuild")
```
NimScripts also support `--`:option: templates for convenience, which look
like command-line switches written as-is in the NimScript file. So the
above example can be rewritten as:
.. code-block:: nim
```nim
--opt:size
--define:release
--forceBuild
```
**Note**: In general, the *define* switches can also be set in
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
task `build` that is an alias for the `c`:option: command:
.. code-block:: nim
```nim
task build, "builds an example":
setCommand "c"
```
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,
installation of Nimble could be accomplished with this simple script:
.. code-block:: nim
```nim
mode = ScriptMode.Verbose
var id = 0
@@ -198,16 +200,17 @@ installation of Nimble could be accomplished with this simple script:
exec "nim c nimble"
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
ends with ``.nims``:
.. code-block:: nim
```nim
#!/usr/bin/env nim
mode = ScriptMode.Silent
echo "hello world"
```
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:
.. code-block:: nim
```nim
import std/distros
# Architectures.
@@ -256,6 +258,7 @@ See the following (incomplete) example:
echo "Distro is ArchLinux"
elif detectOs(Debian):
echo "Distro is Debian"
```
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
translate text strings on unmodified NimScript:
.. code-block:: nim
```nim
import nimterlingua
nimterlingua("translations.cfg")
echo "cat" # Run with -d:RU becomes "kot", -d:ES becomes "gato", ...
```
translations.cfg
.. code-block:: none
```none
[cat]
ES = gato
IT = gatto
RU = kot
FR = chat
```
* `Nimterlingua <https://nimble.directory/pkg/nimterlingua>`_
@@ -305,8 +308,7 @@ but often a graceful and seamless fallback degradation is used.
See the following NimScript:
.. code-block:: nim
```nim
if likely(true):
discard
elif unlikely(false):
@@ -316,6 +318,7 @@ See the following NimScript:
static:
echo CompileDate
```
`likely()`, `unlikely()`, `static:` and `{.compiletime.}`

View File

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

View File

@@ -48,24 +48,24 @@ The Debian package ships bash and ksh completion and manpages that can be reused
Hints on the build process:
.. code:: cmd
```cmd
# build from C sources and then using koch
make -j # supports parallel build
# alternatively: ./build.sh --os $os_type --cpu $cpu_arch
./bin/nim c -d:release koch
./koch boot -d:release
# build from C sources and then using koch
make -j # supports parallel build
# alternatively: ./build.sh --os $os_type --cpu $cpu_arch
./bin/nim c -d:release koch
./koch boot -d:release
# optionally generate docs into doc/html
./koch docs
# optionally generate docs into doc/html
./koch docs
./koch tools
./koch tools
# extract files to be really installed
./install.sh <tempdir>
# extract files to be really installed
./install.sh <tempdir>
# also include the tools
for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn <tempdir>/nim/bin/; done
# also include the tools
for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn <tempdir>/nim/bin/; done
```
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
interpreted as verbatim string:
.. code-block:: nim
```nim
abc =~ peg"abc" # is true
```
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:
.. code-block:: nim
```nim
s =~ peg" y'while'"
```
Exchange (key, val)-pairs:
.. code-block:: nim
```nim
"key: val; key2: val2".replacef(peg"{\ident} \s* ':' \s* {\ident}", "$2: $1")
```
Determine the ``#include``'ed files of a C file:
.. code-block:: nim
```nim
for line in lines("myfile.c"):
if line =~ peg"""s <- ws '#include' ws '"' {[^"]+} '"' ws
comment <- '/*' @ '*/' / '//' .*
ws <- (comment / \s+)* """:
echo matches[0]
```
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).
With this switch the garbage collector supports the following operations:
.. code-block:: nim
```nim
proc GC_setMaxPause*(maxPauseInUs: int)
proc GC_step*(us: int, strongAdvice = false, stackSize = -1)
```
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
can then attach a GC to this thread via
.. code-block:: nim
```nim
system.setupForeignThreadGc()
```
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
@@ -109,10 +110,9 @@ lived.
Before the thread exits, you should tear down the thread's GC to prevent memory
leaks by calling
.. code-block:: nim
```nim
system.tearDownForeignThreadGc()
```
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.
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
```
**Note:** Nim also offers `hash sets <sets.html>`_ (which you need to import
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
can also be used to include elements (and ranges of elements):
.. code-block:: nim
```nim
type
CharSet = set[char]
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
# letters from 'a' to 'z' and the digits
# from '0' to '9'
```
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:
.. code-block:: nim
```nim
type
MyFlag* {.size: sizeof(cint).} = enum
A
@@ -79,6 +79,7 @@ Enum, sets and casting can be used together as in:
assert toNum({A, C}) == 5
assert toFlags(0) == {}
assert toFlags(7) == {A, B, C}
```
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
variables at the same time:
.. code-block:: nim
```nim
import std/threadpool, ...
# wait until 2 out of 3 servers received the update:
@@ -40,6 +40,7 @@ variables at the same time:
assert index >= 0
responses.del(index)
discard blockUntilAny(responses)
```
Data flow variables ensure that no data races
are possible. Due to technical limitations not every type ``T`` is possible in
@@ -54,7 +55,7 @@ Parallel statement
Example:
.. code-block:: nim
```nim
# Compute PI in an inefficient way
import std/[strutils, math, threadpool]
@@ -69,6 +70,7 @@ Example:
result += ch[k]
echo formatFloat(pi(5000))
```
The parallel statement is the preferred mechanism to introduce parallelism

View File

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

View File

@@ -53,29 +53,29 @@ Running a single test
This is a minimal example to understand the basics,
not very useful for production, but easy to understand:
.. code:: console
```console
$ mkdir tests
$ echo "assert 42 == 42" > tests/test0.nim
$ testament run test0.nim
PASS: tests/test0.nim C ( 0.2 sec)
$ testament r test0
PASS: tests/test0.nim C ( 0.2 sec)
```
Running all tests from a directory
==================================
.. code:: console
```console
$ testament pattern "tests/*.nim"
```
To search for tests deeper in a directory, use
.. code:: console
```console
$ testament pattern "tests/**/*.nim" # one level deeper
$ testament pattern "tests/**/**/*.nim" # two levels deeper
```
HTML Reports
============
@@ -83,9 +83,9 @@ HTML Reports
Generate HTML Reports ``testresults.html`` from unittests,
you have to run at least 1 test *before* generating a report:
.. code:: console
```console
$ testament html
```
Writing Unit tests
@@ -93,8 +93,7 @@ Writing Unit tests
Example "template" **to edit** and write a Testament unittest:
.. code-block:: nim
```nim
discard """
# What actions to expect completion on.
@@ -182,6 +181,7 @@ Example "template" **to edit** and write a Testament unittest:
"""
assert true
assert 42 == 42, "Assert error message"
```
* As you can see the "Spec" is just a `discard """ """`.
@@ -197,26 +197,25 @@ Unit test Examples
Expected to fail:
.. code-block:: nim
```nim
discard """
errormsg: "undeclared identifier: 'not_defined'"
"""
assert not_defined == "not_defined", "not_defined is not defined"
```
Non-Zero exit code:
.. code-block:: nim
```nim
discard """
exitcode: 1
"""
quit "Non-Zero exit code", 1
```
Standard output checking:
.. code-block:: nim
```nim
discard """
output: '''
@@ -230,32 +229,33 @@ Standard output checking:
"""
for i in 0..5: echo i
```
JavaScript tests:
.. code-block:: nim
```nim
discard """
targets: "js"
"""
when defined(js):
import std/jsconsole
console.log("My Frontend Project")
```
Compile-time tests:
.. code-block:: nim
```nim
discard """
action: "compile"
"""
static: assert 9 == 9, "Compile time assert"
```
Tests without Spec:
.. code-block:: nim
```nim
assert 1 == 1
```
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
type, the `of` operator can be used.
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
Person = ref object of RootObj
name*: string # the * means that `name` is accessible from other modules
@@ -70,6 +69,7 @@ type, the `of` operator can be used.
# object construction:
student = Student(name: "Anton", age: 5, id: 2)
echo student[]
```
Inheritance is done with the `object of` syntax. Multiple inheritance is
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:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
Node = ref object # a reference to an object with the following field:
le, ri: Node # left and right subtrees
@@ -108,6 +107,7 @@ Example:
name: string # the symbol's name
line: int # the line the symbol was declared in
code: Node # the symbol's abstract syntax tree
```
Type conversions
@@ -124,9 +124,10 @@ raised.
The syntax for type conversions is `destination_type(expression_to_convert)`
(like an ordinary call):
.. code-block:: nim
```nim
proc getID(x: Person): int =
Student(x).id
```
The `InvalidObjectConversionDefect` exception is raised if `x` is not a
`Student`.
@@ -139,9 +140,7 @@ variant types are needed.
An example:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
# This is an example how an abstract syntax tree could be modelled in Nim
type
NodeKind = enum # the different node types
@@ -165,6 +164,7 @@ An example:
# the following statement raises an `FieldDefect` exception, because
# n.kind's value does not fit:
n.strVal = ""
```
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
@@ -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
for any type:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
import std/strutils
echo "abc".len # is the same as echo len("abc")
echo "abc".toUpperAscii()
echo({'a', 'b', 'c'}.card)
stdout.writeLine("Hallo") # the same as writeLine(stdout, "Hallo")
```
(Another way to look at the method call syntax is that it provides the missing
postfix notation.)
So "pure object oriented" code is easy to write:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
import std/[strutils, sequtils]
stdout.writeLine("Give a list of numbers (separated by spaces): ")
stdout.write(stdin.readLine.splitWhitespace.map(parseInt).max.`$`)
stdout.writeLine(" is the maximum!")
```
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
is needed:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
Socket* = ref object of RootObj
h: int # cannot be accessed from the outside of the module due to missing star
@@ -231,6 +229,7 @@ is needed:
var s: Socket
new s
s.host = 34 # same as `host=`(s, 34)
```
(The example also shows `inline` procedures.)
@@ -238,8 +237,7 @@ is needed:
The `[]` array access operator can be overloaded to provide
`array properties`:idx:\ :
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
Vector* = object
x, y, z: float
@@ -259,6 +257,7 @@ The `[]` array access operator can be overloaded to provide
of 1: result = v.y
of 2: result = v.z
else: assert(false)
```
The example is silly, since a vector is better modelled by a tuple which
already provides `v[]` access.
@@ -270,8 +269,7 @@ Dynamic dispatch
Procedures always use static dispatch. For dynamic dispatch replace the
`proc` keyword by `method`:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
Expression = ref object of RootObj ## abstract base class for an 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)
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
```
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
@@ -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
dispatching:
.. code-block:: nim
:test: "nim c --multiMethods:on $1"
```nim test = "nim c --multiMethods:on $1"
type
Thing = ref object of RootObj
Unit = ref object of Thing
@@ -323,6 +320,7 @@ dispatching:
new a
new b
collide(a, b) # output: 2
```
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:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
var
e: ref OSError
new(e)
e.msg = "the request to the OS failed"
raise e
```
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,
the template `newException` in the `system` module can be used:
.. code-block:: nim
```nim
raise newException(OSError, "the request to the OS failed")
```
Try statement
@@ -376,8 +375,7 @@ Try statement
The `try` statement handles exceptions:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
from std/strutils import parseInt
# read the first two lines of a text file that should contain numbers
@@ -401,6 +399,7 @@ The `try` statement handles exceptions:
raise
finally:
close(f)
```
The statements after the `try` are executed unless an exception is
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>`_
module. Example:
.. code-block:: nim
```nim
try:
doSomethingHere()
except:
@@ -431,6 +430,7 @@ module. Example:
e = getCurrentException()
msg = getCurrentExceptionMsg()
echo "Got exception ", repr(e), " with message ", msg
```
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
prevent that proc from compiling. Usage example:
.. code-block:: nim
```nim
proc complexProc() {.raises: [IOError, ArithmeticDefect].} =
...
proc simpleProc() {.raises: [].} =
...
```
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
@@ -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
containers:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
type
BinaryTree*[T] = ref object # BinaryTree is a generic type with
# generic param `T`
@@ -530,6 +530,7 @@ containers:
add(root, "world") # instantiates the second `add` proc
for str in preorder(root):
stdout.writeLine(str)
```
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,
@@ -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:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
proc foo[T](i: T) =
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]() # Success
```
Templates
@@ -563,12 +564,13 @@ To *invoke* a template, call it like a procedure.
Example:
.. code-block:: nim
```nim
template `!=` (a, b: untyped): untyped =
# this definition exists in the System module
not (a == b)
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
```
The `!=`, `>`, `>=`, `in`, `notin`, `isnot` operators are in fact
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
simple proc for logging:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
const
debug = true
@@ -593,6 +594,7 @@ simple proc for logging:
var
x = 4
log("x has the value: " & $x)
```
This code has a shortcoming: if `debug` is set to false someday, the quite
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:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
const
debug = true
@@ -611,6 +612,7 @@ Turning the `log` proc into a template solves this problem:
var
x = 4
log("x has the value: " & $x)
```
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
@@ -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:
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
template withFile(f: untyped, filename: string, mode: FileMode,
body: untyped) =
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):
txt.writeLine("line 1")
txt.writeLine("line 2")
```
In the example the two `writeLine` statements are bound to the `body`
parameter. The `withFile` template contains boilerplate code and helps to
@@ -650,8 +651,7 @@ once.
Example: Lifting Procs
----------------------
.. code-block:: nim
:test: "nim c $1"
`````nim test = "nim c $1"
import std/math
template liftScalarProc(fname) =
@@ -660,9 +660,10 @@ Example: Lifting Procs
## to provide templated procs that can handle a single
## parameter of seq[T] or nested seq[seq[]] or the same type
##
## .. code-block:: Nim
## liftScalarProc(abs)
## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]
## ```Nim
## liftScalarProc(abs)
## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]
## ```
proc fname[T](x: openarray[T]): auto =
var temp: T
type outType = typeof(fname(temp))
@@ -672,6 +673,7 @@ Example: Lifting Procs
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]
`````
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
`int`.
.. code-block:: nim
```nim
import std/macros
macro myMacro(arg: static[int]): untyped =
echo arg # just an int (7), not `NimNode`
myMacro(1 + 2 * 3)
```
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
example is a valid (but not a recommended) way to call `echo`:
.. code-block:: nim
```nim
echo "Hello ":
let a = "Wor"
let b = "ld!"
a & b
```
For macros this way of calling is very useful; syntax trees of arbitrary
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,
but does nothing else. Here is an example of such a tree representation:
.. code-block:: nim
```nim
dumpTree:
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
# Ident "b"
# StrLit "abcdef"
```
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
be created with the `macros.error` proc.
.. code-block:: nim
```nim
macro myAssert(arg: untyped): untyped =
arg.expectKind nnkInfix
```
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
generated expression.
.. code-block:: nim
:test: "nim c $1"
import std/macros
macro a(i) = quote do:
let `i` = 0
```nim test = "nim c $1"
import std/macros
macro a(i) = quote do:
let `i` = 0
a b
doAssert b == 0
a b
doAssert b == 0
```
A custom prefix operator can be defined whenever backticks are needed.
.. code-block:: nim
:test: "nim c $1"
import std/macros
macro a(i) = quote("@") do:
assert @i == 0
```nim test = "nim c $1"
import std/macros
macro a(i) = quote("@") do:
assert @i == 0
let b = 0
a b
let b = 0
a b
```
The injected symbol needs accent quoted when it resolves to a symbol.
.. code-block:: nim
:test: "nim c $1"
import std/macros
macro a(i) = quote("@") do:
let `@i` = 0
```nim test = "nim c $1"
import std/macros
macro a(i) = quote("@") do:
let `@i` = 0
a b
doAssert b == 0
a b
doAssert b == 0
```
Make sure to inject only symbols of type `NimNode` into the generated syntax
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.
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
import std/macros
type
@@ -246,12 +244,14 @@ them into the tree.
echo `mtLit`
myMacro("Hallo")
```
The call to `myMacro` will generate the following code:
.. code-block:: nim
```nim
echo "Hallo"
echo MyType(a: 123.456'f64, b: "abcdef")
```
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
correct argument should look like.
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
import std/macros
macro myAssert(arg: untyped): untyped =
@@ -275,13 +273,14 @@ correct argument should look like.
let b = 2
myAssert(a != b)
```
.. code-block::
```
Infix
Ident "!="
Ident "a"
Ident "b"
```
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
written.
.. code-block:: nim
:test: "nim c $1"
```nim test = "nim c $1"
import std/macros
macro myAssert(arg: untyped): untyped =
@@ -312,6 +309,7 @@ written.
myAssert(a != b)
myAssert(a == b)
```
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
used to get this output.
.. code-block:: nim
```nim
if not (a != b):
raise newException(AssertionDefect, $a & " != " & $b)
```
With Power Comes Responsibility
-------------------------------