Markdown code blocks part 3 (#20117)

No logic was added, just 4 more files migrated.
This commit is contained in:
Andrey Makarov
2022-08-04 10:32:23 +03:00
committed by GitHub
parent 2aeb0d516b
commit a34dd3d77a
5 changed files with 409 additions and 283 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -57,11 +57,11 @@ project. This allows you to take the generated code and place it directly
into a project using any of these languages. Here are some typical command-
line invocations:
.. code:: cmd
nim c hallo.nim
nim cpp hallo.nim
nim objc hallo.nim
```cmd
nim c hallo.nim
nim cpp hallo.nim
nim objc hallo.nim
```
The compiler commands select the target backend, but if needed you can
`specify additional switches for cross-compilation
@@ -99,9 +99,9 @@ default is a ``.js`` file that is supposed to be referenced in an ``.html``
file. However, you can also run the code with `nodejs`:idx:
(`<http://nodejs.org>`_):
.. code:: cmd
```cmd
nim js -d:nodejs -r examples/hallo.nim
```
If you experience errors saying that `globalThis` is not defined, be
sure to run a recent version of Node.js (at least 12.0).
@@ -159,21 +159,22 @@ interface.
Create a ``logic.c`` file with the following content:
.. code-block:: c
```c
int addTwoIntegers(int a, int b)
{
return a + b;
}
```
Create a ``calculator.nim`` file with the following content:
.. code-block:: nim
```nim
{.compile: "logic.c".}
proc addTwoIntegers(a, b: cint): cint {.importc.}
when isMainModule:
echo addTwoIntegers(3, 7)
```
With these two files in place, you can run `nim c -r calculator.nim`:cmd: and
the Nim compiler will compile the ``logic.c`` file in addition to
@@ -182,11 +183,11 @@ run. Another way to link the C file statically and get the same effect would
be to remove the line with the `compile` pragma and run the following
typical Unix commands:
.. code:: cmd
gcc -c logic.c
ar rvs mylib.a logic.o
nim c --passL:mylib.a -r calculator.nim
```cmd
gcc -c logic.c
ar rvs mylib.a logic.o
nim c --passL:mylib.a -r calculator.nim
```
Just like in this example we pass the path to the ``mylib.a`` library (and we
could as well pass ``logic.o``) we could be passing switches to link any other
@@ -212,12 +213,12 @@ Create a ``host.html`` file with the following content:
Create a ``calculator.nim`` file with the following content (or reuse the one
from the previous section):
.. code-block:: nim
```nim
proc addTwoIntegers(a, b: int): int {.importc.}
when isMainModule:
echo addTwoIntegers(3, 7)
```
Compile the Nim code to JavaScript with `nim js -o:calculator.js
calculator.nim`:cmd: and open ``host.html`` in a browser. If the browser supports
@@ -253,18 +254,17 @@ Use `--nimMainPrefix:MyLib` and the function to call is named `MyLibNimMain`.
Create a ``fib.nim`` file with the following content:
.. code-block:: nim
```nim
proc fib(a: cint): cint {.exportc.} =
if a <= 2:
result = 1
else:
result = fib(a - 1) + fib(a - 2)
```
Create a ``maths.c`` file with the following content:
.. code-block:: c
```c
#include <stdio.h>
int fib(int a);
@@ -277,15 +277,16 @@ Create a ``maths.c`` file with the following content:
printf("Fib of %d is %d\n", f, fib(f));
return 0;
}
```
Now you can run the following Unix like commands to first generate C sources
from the Nim code, then link them into a static binary along your main C
program:
.. code:: cmd
```cmd
nim c --noMain --noLinking fib.nim
gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
```
The first command runs the Nim compiler with three special options to avoid
generating a `main()`:c: function in the generated files and to avoid linking the
@@ -297,10 +298,10 @@ have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
Instead of depending on the generation of the individual ``.c`` files you can
also ask the Nim compiler to generate a statically linked library:
.. code:: cmd
```cmd
nim c --app:staticLib --noMain fib.nim
gcc -o m -Inimcache -Ipath/to/nim/lib maths.c libfib.nim.a
```
The Nim compiler will handle linking the source files generated in the
``nimcache`` directory into the ``libfib.nim.a`` static library, which you can
@@ -313,25 +314,25 @@ use `-ldl`:option: too to link in required dlopen functionality.
Create a ``mhost.html`` file with the following content:
.. code-block::
```
<html><body>
<script type="text/javascript" src="fib.js"></script>
<script type="text/javascript">
alert("Fib for 9 is " + fib(9));
</script>
</body></html>
```
Create a ``fib.nim`` file with the following content (or reuse the one
from the previous section):
.. code-block:: nim
```nim
proc fib(a: cint): cint {.exportc.} =
if a <= 2:
result = 1
else:
result = fib(a - 1) + fib(a - 2)
```
Compile the Nim code to JavaScript with `nim js -o:fib.js fib.nim`:cmd: and
open ``mhost.html`` in a browser. If the browser supports javascript, you
@@ -378,10 +379,10 @@ from being freed with `GC_ref <system.html#GC_ref,string>`_ and `GC_unref
A similar thing happens with C code invoking Nim code which returns a
`cstring`. Consider the following proc:
.. code-block:: nim
```nim
proc gimme(): cstring {.exportc.} =
result = "Hey there C code! " & $rand(100)
```
Since Nim's reference counting mechanism is not aware of the C code, once the
`gimme` proc has finished it can reclaim the memory of the `cstring`.

View File

@@ -59,8 +59,7 @@ things like `echo "done"`. Don't use `unittest.suite` and `unittest.test`.
Sample test:
.. code-block:: nim
```nim
block: # foo
doAssert foo(1) == 10
@@ -76,6 +75,7 @@ Sample test:
@[false, false], @[false, false]]
# doAssert with `not` can now be done as follows:
doAssert not (1 == 2)
```
Always refer to a GitHub issue using the following exact syntax: ``bug #1234`` as shown
above, so that it's consistent and easier to search or for tooling. Some browser
@@ -110,8 +110,7 @@ For a full spec, see here: ``testament/specs.nim``
An example of a test:
.. code-block:: nim
```nim
discard """
errormsg: "type mismatch: got (PTest)"
"""
@@ -123,6 +122,7 @@ An example of a test:
var buf: PTest
buf.test()
```
Running tests
@@ -130,9 +130,9 @@ Running tests
You can run the tests with
.. code-block:: cmd
```cmd
./koch tests
```
which will run a good subset of tests. Some tests may fail. If you
only want to see the output of failing tests, go for
@@ -145,17 +145,17 @@ You can also run only a single category of tests. A category is a subdirectory
in the ``tests/`` directory. There are a couple of special categories; for a
list of these, see ``testament/categories.nim``, at the bottom.
.. code:: cmd
```cmd
./koch tests c lib # compiles / runs stdlib modules, including `isMainModule` tests
./koch tests c megatest # runs a set of tests that can be combined into 1
```
To run a single test:
.. code:: cmd
```cmd
./koch test run <category>/<name> # e.g.: tuples/ttuples_issues
./koch test run tests/stdlib/tos.nim # can also provide relative path
```
For reproducible tests (to reproduce an environment more similar to the one
run by Continuous Integration on github actions/azure pipelines), you may want to disable your
@@ -174,25 +174,25 @@ The tester can compare two test runs. First, you need to create a
reference test. You'll also need to the commit id, because that's what
the tester needs to know in order to compare the two.
.. code:: cmd
```cmd
git checkout devel
DEVEL_COMMIT=$(git rev-parse HEAD)
./koch tests
```
Then switch over to your changes and run the tester again.
.. code:: cmd
```cmd
git checkout your-changes
./koch tests
```
Then you can ask the tester to create a ``testresults.html`` which will
tell you if any new tests passed/failed.
.. code:: cmd
```cmd
./koch tests --print html $DEVEL_COMMIT
```
Deprecation
@@ -201,8 +201,7 @@ Deprecation
Backward compatibility is important, so instead of a rename you need to deprecate
the old name and introduce a new name:
.. code-block:: nim
```nim
# for routines (proc/template/macro/iterator) and types:
proc oldProc(a: int, b: float): bool {.deprecated:
"deprecated since v1.2.3; use `newImpl: string -> int` instead".} = discard
@@ -214,6 +213,7 @@ the old name and introduce a new name:
# (likewise with object types and their fields):
type Bar {.deprecated.} = enum bar0, bar1
type Barz = enum baz0, baz1 {.deprecated.}, baz2
```
See also `Deprecated <manual.html#pragmas-deprecated-pragma>`_
@@ -234,12 +234,13 @@ test cases (typically 1 to 3 `assert` statements, depending on complexity).
These `runnableExamples` are automatically run by `nim doc mymodule.nim`:cmd:
as well as `testament`:cmd: and guarantee they stay in sync.
.. code-block:: nim
```nim
proc addBar*(a: string): string =
## Adds "Bar" to `a`.
runnableExamples:
assert "baz".addBar == "bazBar"
result = a & "Bar"
```
See `parentDir <os.html#parentDir,string>`_ example.
@@ -247,47 +248,49 @@ The RestructuredText Nim uses has a special syntax for including code snippets
embedded in documentation; these are not run by `nim doc`:cmd: and therefore are
not guaranteed to stay in sync, so `runnableExamples` is almost always preferred:
.. code-block:: nim
````nim
proc someProc*(): string =
## Returns "something"
##
## .. code-block::
## echo someProc() # "something"
## ```
## echo someProc() # "something"
## ```
result = "something" # single-hash comments do not produce documentation
````
The ``.. code-block:: nim`` followed by a newline and an indentation instructs the
The \`\`\` followed by a newline and an indentation instructs the
`nim doc`:cmd: command to produce syntax-highlighted example code with the
documentation (``.. code-block::`` is sufficient from inside a nim module).
documentation (\`\`\` is sufficient inside a ``.nim`` module, while from
a ``.md`` one needs to set the language explicitly as \`\`\`nim).
When forward declaration is used, the documentation should be included with the
first appearance of the proc.
.. code-block:: nim
```nim
proc hello*(): string
## Put documentation here
proc nothing() = discard
proc hello*(): string =
## ignore this
echo "hello"
```
The preferred documentation style is to begin with a capital letter and use
the third-person singular. That is, between:
.. code-block:: nim
```nim
proc hello*(): string =
## Returns "hello"
result = "hello"
```
or
.. code-block:: nim
```nim
proc hello*(): string =
## say hello
result = "hello"
```
the first is preferred.
@@ -296,8 +299,9 @@ in the postfix form for uniformity, that is after \`text in backticks\`.
For example an ``:idx:`` role for referencing a topic ("SQLite" in the
example below) from `Nim Index`_ can be used in doc comment this way:
.. code-block:: nim
```nim
## A higher level `SQLite`:idx: database wrapper.
```
.. _`Nim Index`: https://nim-lang.org/docs/theindex.html
@@ -355,50 +359,50 @@ New `defined(foo)` symbols need to be prefixed by the nimble package name, or
by `nim` for symbols in nim sources (e.g. compiler, standard library). This is
to avoid name conflicts across packages.
.. code-block:: nim
```nim
# if in nim sources
when defined(allocStats): discard # bad, can cause conflicts
when defined(nimAllocStats): discard # preferred
# if in a package `cligen`:
when defined(debug): discard # bad, can cause conflicts
when defined(cligenDebug): discard # preferred
```
.. _noimplicitbool:
Take advantage of no implicit bool conversion
.. code-block:: nim
```nim
doAssert isValid() == true
doAssert isValid() # preferred
```
.. _design_for_mcs:
Design with method call syntax chaining in mind
.. code-block:: nim
```nim
proc foo(cond: bool, lines: seq[string]) # bad
proc foo(lines: seq[string], cond: bool) # preferred
# can be called as: `getLines().foo(false)`
```
.. _avoid_quit:
Use exceptions (including `assert` / `doAssert`) instead of `quit`
rationale: https://forum.nim-lang.org/t/4089
.. code-block:: nim
```nim
quit() # bad in almost all cases
doAssert() # preferred
```
.. _tests_use_doAssert:
Use `doAssert` (or `unittest.check`, `unittest.require`), not `assert` in all
tests so they'll be enabled even with `--assertions:off`:option:.
.. code-block:: nim
```nim
block: # foo
assert foo() # bad
doAssert foo() # preferred
```
.. _runnableExamples_use_assert:
An exception to the above rule is `runnableExamples` and ``code-block`` rst blocks
@@ -407,33 +411,33 @@ instead of `doAssert`. Note that `nim doc -d:danger main`:cmd: won't pass `-d:da
`runnableExamples`, but `nim doc --doccmd:-d:danger main`:cmd: would, and so would the
second example below:
.. code-block:: nim
```nim
runnableExamples:
doAssert foo() # bad
assert foo() # preferred
runnableExamples("-d:danger"):
doAssert foo() # `assert` would be disabled here, so `doAssert` makes more sense
```
.. _delegate_printing:
Delegate printing to caller: return `string` instead of calling `echo`
rationale: it's more flexible (e.g. allows the caller to call custom printing,
including prepending location info, writing to log files, etc).
.. code-block:: nim
```nim
proc foo() = echo "bar" # bad
proc foo(): string = "bar" # preferred (usually)
```
.. _use_Option:
[Ongoing debate] Consider using Option instead of return bool + var argument,
unless stack allocation is needed (e.g. for efficiency).
.. code-block:: nim
```nim
proc foo(a: var Bar): bool
proc foo(): Option[Bar]
```
.. _use_doAssert_not_echo:
Tests (including in testament) should always prefer assertions over `echo`,
@@ -441,10 +445,10 @@ except when that's not possible. It's more precise, easier for readers and
maintainers to where expected values refer to. See for example
https://github.com/nim-lang/Nim/pull/9335 and https://forum.nim-lang.org/t/4089
.. code-block:: nim
```nim
echo foo() # adds a line for testament in `output:` block inside `discard`.
doAssert foo() == [1, 2] # preferred, except when not possible to do so.
```
The `git`:cmd: stuff
@@ -480,10 +484,10 @@ General commit rules
Always check your changes for whitespace errors using `git diff --check`:cmd:
or add the following ``pre-commit`` hook:
.. code:: cmd
#!/bin/sh
git diff --check --cached || exit $?
```cmd
#!/bin/sh
git diff --check --cached || exit $?
```
5. Describe your commit and use your common sense.
Example commit message::
@@ -565,10 +569,10 @@ Code reviews
doesn't help much as it doesn't highlight moves. Instead, you can use something
like this, see visual results `here <https://github.com/nim-lang/Nim/pull/10431#issuecomment-456968196>`_:
.. code:: cmd
git fetch origin pull/10431/head && git checkout FETCH_HEAD
git diff --color-moved-ws=allow-indentation-change --color-moved=blocks HEAD^
```cmd
git fetch origin pull/10431/head && git checkout FETCH_HEAD
git diff --color-moved-ws=allow-indentation-change --color-moved=blocks HEAD^
```
3. In addition, you can view GitHub-like diffs locally to identify what was changed
within a code block using `diff-highlight`:cmd: or `diff-so-fancy`:cmd:, e.g.:

View File

@@ -30,8 +30,7 @@ Motivating example
With the language mechanisms described here, a custom seq could be
written as:
.. code-block:: nim
```nim
type
myseq*[T] = object
len, cap: int
@@ -91,7 +90,7 @@ written as:
for i in 0..<result.len: result.data[i] = elems[i]
proc len*[T](x: myseq[T]): int {.inline.} = x.len
```
Lifetime-tracking hooks
@@ -119,20 +118,18 @@ to return.
The prototype of this hook for a type `T` needs to be:
.. code-block:: nim
```nim
proc `=destroy`(x: var T)
```
The general pattern in `=destroy` looks like:
.. code-block:: nim
```nim
proc `=destroy`(x: var T) =
# first check if 'x' was moved to somewhere else:
if x.field != nil:
freeResource(x.field)
```
`=sink` hook
@@ -149,20 +146,19 @@ provide `=destroy` and `=copy`, the compiler will take care of the rest.
The prototype of this hook for a type `T` needs to be:
.. code-block:: nim
```nim
proc `=sink`(dest: var T; source: T)
```
The general pattern in `=sink` looks like:
.. code-block:: nim
```nim
proc `=sink`(dest: var T; source: T) =
`=destroy`(dest)
wasMoved(dest)
dest.field = source.field
```
**Note**: `=sink` does not need to check for self-assignments.
How self-assignments are handled is explained later in this document.
@@ -177,29 +173,27 @@ operations.
The prototype of this hook for a type `T` needs to be:
.. code-block:: nim
```nim
proc `=copy`(dest: var T; source: T)
```
The general pattern in `=copy` looks like:
.. code-block:: nim
```nim
proc `=copy`(dest: var T; source: T) =
# protect against self-assignments:
if dest.field != source.field:
`=destroy`(dest)
wasMoved(dest)
dest.field = duplicateResource(source.field)
```
The `=copy` proc can be marked with the `{.error.}` pragma. Then any assignment
that otherwise would lead to a copy is prevented at compile-time. This looks like:
.. code-block:: nim
```nim
proc `=copy`(dest: var T; source: T) {.error.}
```
but a custom error message (e.g., `{.error: "custom error".}`) will not be emitted
by the compiler. Notice that there is no `=` before the `{.error.}` pragma.
@@ -215,9 +209,9 @@ memory or resources, but memory safety is not compromised.
The prototype of this hook for a type `T` needs to be:
.. code-block:: nim
```nim
proc `=trace`(dest: var T; env: pointer)
```
`env` is used by ORC to keep track of its internal state, it should be passed around
to calls of the built-in `=trace` operation.
@@ -233,8 +227,7 @@ prevent the automatic creation.
The general pattern in using `=destroy` with `=trace` looks like:
.. code-block:: nim
```nim
type
Test[T] = object
size: Natural
@@ -255,6 +248,7 @@ The general pattern in using `=destroy` with `=trace` looks like:
for i in 0 ..< dest.size: `=trace`(dest.arr[i], env)
# following may be other custom "hooks" as required...
```
**Note**: The `=trace` hooks (which are only used by `--mm:orc`) are currently more experimental and less refined
than the other hooks.
@@ -307,8 +301,7 @@ not a linear type system.
The employed static analysis is limited and only concerned with local variables;
however, object and tuple fields are treated as separate entities:
.. code-block:: nim
```nim
proc consume(x: sink Obj) = discard "no implementation"
proc main =
@@ -316,16 +309,16 @@ however, object and tuple fields are treated as separate entities:
consume tup[0]
# ok, only tup[0] was consumed, tup[1] is still alive:
echo tup[1]
```
Sometimes it is required to explicitly `move` a value into its final position:
.. code-block:: nim
```nim
proc main =
var dest, src: array[10, string]
# ...
for i in 0..high(dest): dest[i] = move(src[i])
```
An implementation is allowed, but not required to implement even more move
optimizations (and the current implementation does not).
@@ -344,11 +337,10 @@ use `{.push sinkInference: on.}` ... `{.pop.}`.
The `.nosinks`:idx: pragma can be used to disable this inference
for a single routine:
.. code-block:: nim
```nim
proc addX(x: T; child: T) {.nosinks.} =
x.s.add child
```
The details of the inference algorithm are currently undocumented.
@@ -456,8 +448,7 @@ The complex case looks like a variant of `x = f(x)`, we consider
`x = select(rand() < 0.5, x, y)` here:
.. code-block:: nim
```nim
proc select(cond: bool; a, b: sink string): string =
if cond:
result = a # moves a into result
@@ -469,13 +460,11 @@ The complex case looks like a variant of `x = f(x)`, we consider
var y = "xyz"
# possible self-assignment:
x = select(true, x, y)
```
Is transformed into:
.. code-block:: nim
```nim
proc select(cond: bool; a, b: sink string): string =
try:
if cond:
@@ -506,6 +495,7 @@ Is transformed into:
finally:
`=destroy`(y)
`=destroy`(x)
```
As can be manually verified, this transformation is correct for
self-assignments.
@@ -527,8 +517,7 @@ that the pointer does not outlive its origin. No destructor call is injected
for expressions of type `lent T` or of type `var T`.
.. code-block:: nim
```nim
type
Tree = object
kids: seq[Tree]
@@ -553,6 +542,7 @@ for expressions of type `lent T` or of type `var T`.
# everything turned into moves:
let t = construct(@[construct(@[]), construct(@[])])
echo t[0] # accessor does not copy the element!
```
The cursor pragma
@@ -564,12 +554,12 @@ This means that cyclic structures cannot be freed
immediately (`--mm:orc`:option: ships with a cycle collector).
With the `cursor` pragma one can break up cycles declaratively:
.. code-block:: nim
```nim
type
Node = ref object
left: Node # owning ref
right {.cursor.}: Node # non-owning ref
```
But please notice that this is not C++'s weak_ptr, it means the right field is not
involved in the reference counting, it is a raw pointer without runtime checks.
@@ -578,13 +568,12 @@ Automatic reference counting also has the disadvantage that it introduces overhe
when iterating over linked structures. The `cursor` pragma can also be used
to avoid this overhead:
.. code-block:: nim
```nim
var it {.cursor.} = listRoot
while it != nil:
use(it)
it = it.next
```
In fact, `cursor` more generally prevents object construction/destruction pairs
and so can also be useful in other contexts. The alternative solution would be to
@@ -609,13 +598,13 @@ words, we do a compile-time copy-on-write analysis.
This means that "borrowed" views can be written naturally and without explicit pointer
indirections:
.. code-block:: nim
```nim
proc main(tab: Table[string, string]) =
let v = tab["key"] # inferred as cursor because 'tab' is not mutated.
# no copy into 'v', no destruction of 'v'.
use(v)
useItAgain(v)
```
Hook lifting
@@ -639,8 +628,7 @@ Hook generation
The ability to override a hook leads to a phase ordering problem:
.. code-block:: nim
```nim
type
Foo[T] = object
@@ -651,7 +639,7 @@ The ability to override a hook leads to a phase ordering problem:
proc `=destroy`[T](f: var Foo[T]) =
discard
```
The solution is to define ``proc `=destroy`[T](f: var Foo[T])`` before
it is used. The compiler generates implicit
@@ -674,8 +662,7 @@ The experimental `nodestroy`:idx: pragma inhibits hook injections. This can be
used to specialize the object traversal in order to avoid deep recursions:
.. code-block:: nim
```nim
type Node = ref object
x, y: int32
left, right: Node
@@ -695,6 +682,7 @@ used to specialize the object traversal in order to avoid deep recursions:
# notice how even the destructor for 's' is not called implicitly
# anymore thanks to .nodestroy, so we have to call it on our own:
`=destroy`(s)
```
As can be seen from the example, this solution is hardly sufficient and
@@ -712,19 +700,20 @@ The copy operation is deferred until the first write.
For example:
.. code-block:: nim
```nim
var x = "abc" # no copy
var y = x # no copy
y[0] = 'h' # copy
```
The abstraction fails for `addr x` because whether the address is going to be used for mutations is unknown.
`prepareMutation` needs to be called before the "address of" operation. For example:
.. code-block:: nim
```nim
var x = "abc"
var y = x
prepareMutation(y)
moveMem(addr y[0], addr x[0], 3)
assert y == "abc"
```

View File

@@ -1306,12 +1306,12 @@ as `MyEnum.value`:
OtherEnum {.pure.} = enum
valueX, valueY, valueZ, amb
```
echo valueA # MyEnum.valueA
echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb
echo MyEnum.amb # OK.
```
To implement bit fields with enums see `Bit fields <#set-type-bit-fields>`_
@@ -2186,7 +2186,7 @@ Unfortunately, `d + 12.Dollar` is not allowed either,
because `+` is defined for `int` (among others), not for `Dollar`. So
a `+` for dollars needs to be defined:
```
```nim
proc `+` (x, y: Dollar): Dollar =
result = Dollar(int(x) + int(y))
```
@@ -2194,7 +2194,7 @@ a `+` for dollars needs to be defined:
It does not make sense to multiply a dollar with a dollar, but with a
number without unit; and the same holds for division:
```
```nim
proc `*` (x: Dollar, y: int): Dollar =
result = Dollar(int(x) * y)