mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-17 16:38:33 +00:00
Markdown code blocks part 5 (#20236)
No logic was added, just a few more `*.md` files have been migrated.
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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`:
|
||||
|
||||
|
||||
@@ -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
|
||||
````
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
36
doc/nep1.md
36
doc/nep1.md
@@ -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:
|
||||
|
||||
76
doc/nimc.md
76
doc/nimc.md
@@ -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))
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
33
doc/nims.md
33
doc/nims.md
@@ -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.}`
|
||||
|
||||
@@ -29,8 +29,9 @@ Installation
|
||||
|
||||
Nimsuggest is part of Nim's core. Build it via:
|
||||
|
||||
.. code:: cmd
|
||||
```cmd
|
||||
koch nimsuggest
|
||||
```
|
||||
|
||||
|
||||
Nimsuggest invocation
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
-------------------------
|
||||
|
||||
12
doc/refc.md
12
doc/refc.md
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
357
doc/tut1.md
357
doc/tut1.md
File diff suppressed because it is too large
Load Diff
94
doc/tut2.md
94
doc/tut2.md
@@ -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
|
||||
=========================
|
||||
|
||||
83
doc/tut3.md
83
doc/tut3.md
@@ -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
|
||||
-------------------------------
|
||||
|
||||
Reference in New Issue
Block a user