diff --git a/doc/backends.md b/doc/backends.md index 1347314614..4f94e82b1e 100644 --- a/doc/backends.md +++ b/doc/backends.md @@ -198,8 +198,7 @@ static C library. Create a ``host.html`` file with the following content: -.. code-block:: - + ``` + ``` Create a ``calculator.nim`` file with the following content (or reuse the one from the previous section): diff --git a/doc/docgen.md b/doc/docgen.md index 5f5c4ecc0d..a651d0a10d 100644 --- a/doc/docgen.md +++ b/doc/docgen.md @@ -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`: diff --git a/doc/docstyle.md b/doc/docstyle.md index 79f7b4e105..1651a6e03f 100644 --- a/doc/docstyle.md +++ b/doc/docstyle.md @@ -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 ```` diff --git a/doc/manual.md b/doc/manual.md index 7605a8b823..44f6ff7cb7 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -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: "", 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 diff --git a/doc/manual/var_t_return.md b/doc/manual/var_t_return.md index f5c5bc4c0b..15d908c74b 100644 --- a/doc/manual/var_t_return.md +++ b/doc/manual/var_t_return.md @@ -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 diff --git a/doc/manual_experimental_strictnotnil.md b/doc/manual_experimental_strictnotnil.md index 047fc916f7..b6d8e796e2 100644 --- a/doc/manual_experimental_strictnotnil.md +++ b/doc/manual_experimental_strictnotnil.md @@ -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 + ``` 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 diff --git a/doc/nep1.md b/doc/nep1.md index 9627071bf5..ea928b82e1 100644 --- a/doc/nep1.md +++ b/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: diff --git a/doc/nimc.md b/doc/nimc.md index 28a917d923..cd980a37bd 100644 --- a/doc/nimc.md +++ b/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)) + ``` diff --git a/doc/nimgrep.md b/doc/nimgrep.md index ff2bf3a8d3..e000efb464 100644 --- a/doc/nimgrep.md +++ b/doc/nimgrep.md @@ -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 diff --git a/doc/nims.md b/doc/nims.md index 4141c3bdc0..5870f7bb61 100644 --- a/doc/nims.md +++ b/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 `_ @@ -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.}` diff --git a/doc/nimsuggest.md b/doc/nimsuggest.md index 82693da0eb..f542cab197 100644 --- a/doc/nimsuggest.md +++ b/doc/nimsuggest.md @@ -29,8 +29,9 @@ Installation Nimsuggest is part of Nim's core. Build it via: -.. code:: cmd + ```cmd koch nimsuggest + ``` Nimsuggest invocation diff --git a/doc/packaging.md b/doc/packaging.md index 7976dfe92f..6445017271 100644 --- a/doc/packaging.md +++ b/doc/packaging.md @@ -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 - # extract files to be really installed - ./install.sh - - # also include the tools - for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn /nim/bin/; done + # also include the tools + for fn in nimble nimsuggest nimgrep; do cp ./bin/$fn /nim/bin/; done + ``` What to install: diff --git a/doc/pegdocs.txt b/doc/pegdocs.txt index 2ef4e2c152..99d9d784cf 100644 --- a/doc/pegdocs.txt +++ b/doc/pegdocs.txt @@ -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 ------------------------- diff --git a/doc/refc.md b/doc/refc.md index 766097f23b..504ba386c8 100644 --- a/doc/refc.md +++ b/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 diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt index 1929a7b919..bc81897322 100644 --- a/doc/sets_fragment.txt +++ b/doc/sets_fragment.txt @@ -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 `_ (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. diff --git a/doc/spawn.txt b/doc/spawn.txt index c437e8aa32..6c80d292b2 100644 --- a/doc/spawn.txt +++ b/doc/spawn.txt @@ -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 diff --git a/doc/subexes.txt b/doc/subexes.txt index 62ddd1ec8f..1bfd602131 100644 --- a/doc/subexes.txt +++ b/doc/subexes.txt @@ -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"] - + ``` diff --git a/doc/testament.md b/doc/testament.md index 140e444421..89e3da44d6 100644 --- a/doc/testament.md +++ b/doc/testament.md @@ -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: diff --git a/doc/tut1.md b/doc/tut1.md index f3584a423b..de671577e0 100644 --- a/doc/tut1.md +++ b/doc/tut1.md @@ -12,10 +12,7 @@ Nim Tutorial (Part I) Introduction ============ -.. raw:: html -

- "Der Mensch ist doch ein Augentier -- schöne Dinge wünsch ich mir." -

+> "Der Mensch ist doch ein Augentier -- Schöne Dinge wünsch' ich mir." This document is a tutorial for the programming language *Nim*. @@ -40,12 +37,12 @@ The first program We start the tour with a modified "hello world" program: -.. code-block:: Nim - :test: "nim c $1" + ```Nim test = "nim c $1" # This is a comment echo "What's your name? " var name: string = readLine(stdin) echo "Hi, ", name, "!" + ``` Save this code to the file "greetings.nim". Now compile and run it:: @@ -89,9 +86,9 @@ compiler knows that `readLine `_ returns a string, you can leave out the type in the declaration (this is called `local type inference`:idx:). So this will work too: -.. code-block:: Nim - :test: "nim c $1" + ```Nim test = "nim c $1" var name = readLine(stdin) + ``` Note that this is basically the only form of type inference that exists in Nim: it is a good compromise between brevity and readability. @@ -117,8 +114,9 @@ String literals are enclosed in double-quotes; character literals in single quotes. Special characters are escaped with ``\``: ``\n`` means newline, ``\t`` means tabulator, etc. There are also *raw* string literals: -.. code-block:: Nim + ```Nim r"C:\program files\nim" + ``` In raw literals, the backslash is not an escape character. @@ -134,11 +132,11 @@ Comments Comments start anywhere outside a string or character literal with the hash character `#`. Documentation comments start with `##`: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" # A comment. var myVariable: int ## a documentation comment + ``` Documentation comments are tokens; they are only allowed at certain places in @@ -148,8 +146,7 @@ documentation generators. Multiline comments are started with `#[` and terminated with `]#`. Multiline comments can also be nested. -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" #[ You can have any Nim code text commented out inside this with no indentation restrictions. @@ -158,6 +155,7 @@ comments can also be nested. Note: these can be nested!! ]# ]# + ``` Numbers @@ -175,18 +173,19 @@ The var statement ================= The var statement declares a new local or global variable: -.. code-block:: + ```nim var x, y: int # declares x and y to have the type `int` + ``` Indentation can be used after the `var` keyword to list a whole section of variables: -.. code-block:: - :test: "nim c $1" + ```nim test = "nim c $1" var x, y: int # a comment can occur here too a, b, c: string + ``` Constants @@ -196,20 +195,20 @@ Constants are symbols which are bound to a value. The constant's value cannot change. The compiler must be able to evaluate the expression in a constant declaration at compile time: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" const x = "abc" # the constant x contains the string "abc" + ``` Indentation can be used after the `const` keyword to list a whole section of constants: -.. code-block:: - :test: "nim c $1" + ```nim test = "nim c $1" const x = 1 # a comment can occur here too y = 2 z = y + 5 # computations are possible + ``` The let statement @@ -218,20 +217,22 @@ The `let` statement works like the `var` statement but the declared symbols are *single assignment* variables: After the initialization their value cannot change: -.. code-block:: + ```nim let x = "abc" # introduces a new variable `x` and binds a value to it x = "xyz" # Illegal: assignment to `x` + ``` The difference between `let` and `const` is: `let` introduces a variable that can not be re-assigned, `const` means "enforce compile time evaluation and put it into a data section": -.. code-block:: + ```nim const input = readLine(stdin) # Error: constant expression expected + ``` -.. code-block:: - :test: "nim c $1" + ```nim test = "nim c $1" let input = readLine(stdin) # works + ``` The assignment statement @@ -240,22 +241,23 @@ The assignment statement The assignment statement assigns a new value to a variable or more generally to a storage location: -.. code-block:: + ```nim var x = "abc" # introduces a new variable `x` and assigns a value to it x = "xyz" # assigns a new value to `x` + ``` `=` is the *assignment operator*. The assignment operator can be overloaded. You can declare multiple variables with a single assignment statement and all the variables will have the same value: -.. code-block:: - :test: "nim c $1" + ```nim test = "nim c $1" var x, y = 3 # assigns 3 to the variables `x` and `y` echo "x ", x # outputs "x 3" echo "y ", y # outputs "y 3" x = 42 # changes `x` to 42 without changing `y` echo "x ", x # outputs "x 42" echo "y ", y # outputs "y 3" + ``` Control flow statements @@ -271,8 +273,7 @@ If statement The if statement is one way to branch the control flow: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" let name = readLine(stdin) if name == "": echo "Poor soul, you lost your name?" @@ -280,6 +281,7 @@ The if statement is one way to branch the control flow: echo "Very funny, your name is name." else: echo "Hi, ", name, "!" + ``` There can be zero or more `elif` parts, and the `else` part is optional. The keyword `elif` is short for `else if`, and is useful to avoid @@ -293,8 +295,7 @@ Case statement Another way to branch is provided by the case statement. A case statement allows for multiple branches: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" let name = readLine(stdin) case name of "": @@ -305,6 +306,7 @@ for multiple branches: echo "Cool name!" else: echo "Hi, ", name, "!" + ``` As it can be seen, for an `of` branch a comma-separated list of values is also allowed. @@ -313,7 +315,7 @@ The case statement can deal with integers, other ordinal types, and strings. (What an ordinal type is will be explained soon.) For integers or other ordinal types value ranges are also possible: -.. code-block:: nim + ```nim # this statement will be explained later: from std/strutils import parseInt @@ -322,6 +324,7 @@ For integers or other ordinal types value ranges are also possible: case n of 0..2, 4..7: echo "The number is in the set: {0, 1, 2, 4, 5, 6, 7}" of 3, 8: echo "The number is 3 or 8" + ``` However, the above code **does not compile**: the reason is that you have to cover every value that `n` may contain, but the code only handles the values @@ -329,12 +332,13 @@ every value that `n` may contain, but the code only handles the values (though it is possible thanks to the range notation), we fix this by telling the compiler that for every other value nothing should be done: -.. code-block:: nim + ```nim ... case n of 0..2, 4..7: echo "The number is in the set: {0, 1, 2, 4, 5, 6, 7}" of 3, 8: echo "The number is 3 or 8" else: discard + ``` The empty `discard statement <#procedures-discard-statement>`_ is a *do nothing* statement. The compiler knows that a case statement with an else part @@ -352,14 +356,13 @@ While statement The while statement is a simple looping construct: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" echo "What's your name? " var name = readLine(stdin) while name == "": echo "Please tell me your name: " name = readLine(stdin) # no `var`, because we do not declare a new variable here + ``` The example uses a while loop to keep asking the users for their name, as long as the user types in nothing (only presses RETURN). @@ -372,73 +375,79 @@ The `for` statement is a construct to loop over any element an *iterator* provides. The example uses the built-in `countup `_ iterator: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines + ``` The variable `i` is implicitly declared by the `for` loop and has the type `int`, because that is what `countup `_ returns. `i` runs through the values 1, 2, .., 10. Each value is `echo`-ed. This code does the same: -.. code-block:: nim + ```nim echo "Counting to 10: " var i = 1 while i <= 10: echo i inc i # increment i by 1 # --> Outputs 1 2 3 4 5 6 7 8 9 10 on different lines + ``` Since counting up occurs so often in programs, Nim also has a `.. `_ iterator that does the same: -.. code-block:: nim + ```nim for i in 1 .. 10: ... + ``` Counting down can be achieved as easily (but is less often needed): -.. code-block:: nim + ```nim echo "Counting down from 10 to 1: " for i in countdown(10, 1): echo i # --> Outputs 10 9 8 7 6 5 4 3 2 1 on different lines + ``` Zero-indexed counting has two shortcuts `..<` and `.. ^1` (`backward index operator `_) to simplify counting to one less than the higher index: -.. code-block:: nim + ```nim for i in 0 ..< 10: ... # the same as 0 .. 9 + ``` or -.. code-block:: nim + ```nim var s = "some string" for i in 0 ..< s.len: ... + ``` or -.. code-block:: nim + ```nim var s = "some string" for idx, c in s[0 .. ^1]: ... # ^1 is the last element, ^2 would be one before it, and so on + ``` Other useful iterators for collections (like arrays and sequences) are * `items` and `mitems`, which provides immutable and mutable elements respectively, and * `pairs` and `mpairs` which provides the element and an index number (immutable and mutable respectively) -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" for index, item in ["a","b"].pairs: echo item, " at index ", index # => a at index 0 # => b at index 1 + ``` Scopes and the block statement ------------------------------ @@ -447,23 +456,21 @@ Control flow statements have a feature not covered yet: they open a new scope. This means that in the following example, `x` is not accessible outside the loop: -.. code-block:: nim - :test: "nim c $1" - :status: 1 + ```nim test = "nim c $1" status = 1 while false: var x = "hi" echo x # does not work + ``` A while (for) statement introduces an implicit block. Identifiers are only visible within the block they have been declared. The `block` statement can be used to open a new block explicitly: -.. code-block:: nim - :test: "nim c $1" - :status: 1 + ```nim test = "nim c $1" status = 1 block myblock: var x = "hi" echo x # does not work either + ``` The block's *label* (`myblock` in the example) is optional. @@ -475,8 +482,7 @@ A block can be left prematurely with a `break` statement. The break statement can leave a `while`, `for`, or a `block` statement. It leaves the innermost construct, unless a label of a block is given: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" block myblock: echo "entering block" while true: @@ -492,6 +498,7 @@ innermost construct, unless a label of a block is given: break myblock2 # leaves the block (and the loop) echo "still in block" # it won't be printed echo "outside the block" + ``` Continue statement @@ -500,11 +507,11 @@ Continue statement Like in many other programming languages, a `continue` statement starts the next iteration immediately: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" for i in 1 .. 5: if i <= 3: continue echo i # will only print 4 and 5 + ``` When statement @@ -512,9 +519,7 @@ When statement Example: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" when system.hostOS == "windows": echo "running on Windows!" elif system.hostOS == "linux": @@ -523,6 +528,7 @@ Example: echo "running on Mac OS X!" else: echo "unknown operating system" + ``` The `when` statement is almost identical to the `if` statement, but with these differences: @@ -550,7 +556,7 @@ statements. *Complex statements* like `if`, `when`, `for`, `while` can contain other statements. To avoid ambiguities, complex statements must always be indented, but single simple statements do not: -.. code-block:: nim + ```nim # no indentation needed for single-assignment statement: if x: x = false @@ -565,18 +571,19 @@ be indented, but single simple statements do not: if x: x = false y = false + ``` *Expressions* are parts of a statement that usually result in a value. The condition in an if statement is an example of an expression. Expressions can contain indentation at certain places for better readability: -.. code-block:: nim - + ```nim if thisIsaLongCondition() and thisIsAnotherLongCondition(1, 2, 3, 4): x = true + ``` As a rule of thumb, indentation within expressions is allowed after operators, an open parenthesis and after commas. @@ -584,10 +591,10 @@ an open parenthesis and after commas. With parenthesis and semicolons `(;)` you can use statements where only an expression is allowed: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" # computes fac(4) at compile time: const fac4 = (var x = 1; for i in 1..4: x *= i; x) + ``` Procedures @@ -600,8 +607,7 @@ and `readLine `_ in the examples, the concept of a `differentiates these concepts `_. In Nim, new procedures are defined with the `proc` keyword: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc yes(question: string): bool = echo question, " (y/n)" while true: @@ -614,6 +620,7 @@ Nim, new procedures are defined with the `proc` keyword: echo "I'm sorry Dave, I'm afraid I can't do that." else: echo "I think you know what the problem is just as well as I do." + ``` This example shows a procedure named `yes` that asks the user a `question` and returns true if they answered "yes" (or something similar) and returns @@ -638,8 +645,7 @@ shorthand for `return result`. The `result` value is always returned automatically at the end of a procedure if there is no `return` statement at the exit. -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc sumTillNegative(x: varargs[int]): int = for i in x: if i < 0: @@ -649,6 +655,7 @@ the exit. echo sumTillNegative() # echoes 0 echo sumTillNegative(3, 4, 5) # echoes 12 echo sumTillNegative(3, 4 , -1 , 6) # echoes 7 + ``` The `result` variable is already implicitly declared at the start of the function, so declaring it again with 'var result', for example, would shadow it @@ -661,10 +668,10 @@ A procedure that does not have any `return` statement and does not use the special `result` variable returns the value of its last expression. For example, this procedure -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc helloWorld(): string = "Hello, World!" + ``` returns the string "Hello, World!". @@ -677,18 +684,17 @@ most efficient way. If a mutable variable is needed inside the procedure, it has to be declared with `var` in the procedure body. Shadowing the parameter name is possible, and actually an idiom: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc printSeq(s: seq, nprinted: int = -1) = var nprinted = if nprinted == -1: s.len else: min(nprinted, s.len) for i in 0 ..< nprinted: echo s[i] + ``` If the procedure needs to modify the argument for the caller, a `var` parameter can be used: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc divmod(a, b: int; res, remainder: var int) = res = a div b # integer division remainder = a mod b # integer modulo operation @@ -698,6 +704,7 @@ caller, a `var` parameter can be used: divmod(8, 5, x, y) # modifies x and y echo x echo y + ``` In the example, `res` and `remainder` are `var parameters`. Var parameters can be modified by the procedure and the changes are @@ -712,19 +719,20 @@ To call a procedure that returns a value just for its side effects and ignoring its return value, a `discard` statement **must** be used. Nim does not allow silently throwing away a return value: -.. code-block:: nim + ```nim discard yes("May I ask a pointless question?") + ``` The return value can be ignored implicitly if the called proc/iterator has been declared with the `discardable` pragma: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc p(x, y: int): int {.discardable.} = return x + y p(3, 4) # now valid + ``` Named arguments @@ -735,21 +743,23 @@ parameters appear. This is especially true for procedures that construct a complex data type. Therefore, the arguments to a procedure can be named, so that it is clear which argument belongs to which parameter: -.. code-block:: nim + ```nim proc createWindow(x, y, width, height: int; title: string; show: bool): Window = ... var w = createWindow(show = true, title = "My Application", x = 0, y = 0, height = 600, width = 800) + ``` Now that we use named arguments to call `createWindow` the argument order does not matter anymore. Mixing named arguments with ordered arguments is also possible, but not very readable: -.. code-block:: nim + ```nim var w = createWindow(0, 0, title = "My Application", height = 600, width = 800, true) + ``` The compiler checks that each parameter receives exactly one argument. @@ -761,13 +771,14 @@ To make the `createWindow` proc easier to use it should provide `default values`; these are values that are used as arguments if the caller does not specify them: -.. code-block:: nim + ```nim proc createWindow(x = 0, y = 0, width = 500, height = 700, title = "unknown", show = true): Window = ... var w = createWindow(title = "My Application", height = 600, width = 800) + ``` Now the call to `createWindow` only needs to set the values that differ from the defaults. @@ -781,7 +792,7 @@ Overloaded procedures Nim provides the ability to overload procedures similar to C++: -.. code-block:: nim + ```nim proc toString(x: int): string = result = if x < 0: "negative" @@ -795,6 +806,7 @@ Nim provides the ability to overload procedures similar to C++: assert toString(13) == "positive" # calls the toString(x: int) proc assert toString(true) == "yep" # calls the toString(x: bool) proc + ``` (Note that `toString` is usually the `$ `_ operator in Nim.) The compiler chooses the most appropriate proc for the `toString` @@ -825,17 +837,18 @@ can be `found in the manual `_. To define a new operator enclose the operator in backticks "`": -.. code-block:: nim + ```nim proc `$` (x: myDataType): string = ... # now the $ operator also works with myDataType, overloading resolution # ensures that $ works for built-in types just like before + ``` The "`" notation can also be used to call an operator just like any other procedure: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" if `==`( `+`(3, 4), 7): echo "true" + ``` Forward declarations @@ -846,11 +859,12 @@ Every variable, procedure, etc. needs to be declared before it can be used. language that supports metaprogramming as extensively as Nim does.) However, this cannot be done for mutually recursive procedures: -.. code-block:: nim + ```nim # forward declaration: proc even(n: int): bool + ``` -.. code-block:: nim + ```nim proc odd(n: int): bool = assert(n >= 0) # makes sure we don't run into negative recursion if n == 0: false @@ -862,6 +876,7 @@ However, this cannot be done for mutually recursive procedures: if n == 1: false else: n == 0 or odd(n-1) + ``` Here `odd` depends on `even` and vice versa. Thus `even` needs to be introduced to the compiler before it is completely defined. The syntax for @@ -906,21 +921,22 @@ Iterators Let's return to the simple counting example: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" echo "Counting to ten: " for i in countup(1, 10): echo i + ``` Can a `countup `_ proc be written that supports this loop? Let's try: -.. code-block:: nim + ```nim proc countup(a, b: int): int = var res = a while res <= b: return res inc(res) + ``` However, this does not work. The problem is that the procedure should not only `return`, but return and **continue** after an iteration has @@ -928,13 +944,13 @@ finished. This *return and continue* is called a `yield` statement. Now the only thing left to do is to replace the `proc` keyword by `iterator` and here it is -- our first iterator: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" iterator countup(a, b: int): int = var res = a while res <= b: yield res inc(res) + ``` Iterators look very similar to procedures, but there are several important differences: @@ -973,11 +989,11 @@ The operators `not, and, or, xor, <, <=, >, >=, !=, ==` are defined for the bool type. The `and` and `or` operators perform short-circuit evaluation. For example: -.. code-block:: nim - + ```nim while p != nil and p.name != "xyz": # p.name is not evaluated if p == nil p = p.next + ``` Characters @@ -1029,13 +1045,13 @@ The default integer type is `int`. Integer literals can have a *type suffix* to specify a non-default integer type: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" let x = 0 # x is of type `int` y = 0'i8 # y is of type `int8` z = 0'i32 # z is of type `int32` u = 0'u # u is of type `uint` + ``` Most often integers are used for counting objects that reside in memory, so `int` has the same size as a pointer. @@ -1067,12 +1083,12 @@ The default float type is `float`. In the current implementation, Float literals can have a *type suffix* to specify a non-default float type: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" var x = 0.0 # x is of type `float` y = 0.0'f32 # y is of type `float32` z = 0.0'f64 # z is of type `float64` + ``` The common operators `+ - * / < <= == != > >=` are defined for floats and follow the IEEE-754 standard. @@ -1089,13 +1105,13 @@ Type Conversion Conversion between numerical types is performed by using the type as a function: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" var x: int32 = 1.int32 # same as calling int32(1) y: int8 = int8('a') # 'a' == 97'i8 z: float = 2.5 # int(2.5) rounds down to 2 sum: int = int(x) + int(y) + int(z) # sum == 100 + ``` Internal type representation @@ -1111,8 +1127,7 @@ having to write its `$` operator. You can use then the `repr graphs with cycles. The following example shows that even for basic types there is a difference between the `$` and `repr` outputs: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" var myBool = true myCharacter = 'n' @@ -1129,6 +1144,7 @@ there is a difference between the `$` and `repr` outputs: # --> 42:42 echo myFloat, ":", repr(myFloat) # --> 3.14:3.14 + ``` Advanced types @@ -1136,11 +1152,11 @@ Advanced types In Nim new types can be defined within a `type` statement: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" type biggestInt = int64 # biggest integer type that is available biggestFloat = float64 # biggest float type that is available + ``` Enumeration and object types may only be defined within a `type` statement. @@ -1154,15 +1170,14 @@ These values are a set of ordered symbols. Each symbol is mapped to an integer value internally. The first symbol is represented at runtime by 0, the second by 1, and so on. For example: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" type Direction = enum north, east, south, west var x = south # `x` is of type `Direction`; its value is `south` echo x # prints "south" + ``` All the comparison operators can be used with enumeration types. @@ -1213,10 +1228,10 @@ Subranges A subrange type is a range of values from an integer or enumeration type (the base type). Example: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" type MySubrange = range[0..5] + ``` `MySubrange` is a subrange of `int` which can only hold the values 0 @@ -1245,9 +1260,7 @@ an array has the same type. The array's index type can be any ordinal type. Arrays can be constructed using `[]`: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 var @@ -1255,6 +1268,7 @@ Arrays can be constructed using `[]`: x = [1, 2, 3, 4, 5, 6] for i in low(x) .. high(x): echo x[i] + ``` The notation `x[i]` is used to access the i-th element of `x`. Array access is always bounds checked (at compile-time or at runtime). These @@ -1269,8 +1283,7 @@ length. `low(a) `_ returns the lowest valid index for the array `a` and `high(a) `_ the highest valid index. -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" type Direction = enum north, east, south, west @@ -1286,6 +1299,7 @@ valid index. echo low(level) # --> north echo len(level) # --> 4 echo high(level) # --> west + ``` The syntax for nested arrays (multidimensional) in other languages is a matter of appending more brackets because usually each dimension is restricted to the @@ -1295,7 +1309,7 @@ the previous example where a level is defined as an array of enums indexed by yet another enum, we can add the following lines to add a light tower type subdivided into height levels accessed through their integer index: -.. code-block:: nim + ```nim type LightTower = array[1..10, LevelSetting] var @@ -1308,21 +1322,22 @@ subdivided into height levels accessed through their integer index: # The following lines don't compile due to type mismatch errors #tower[north][east] = on #tower[0][1] = on + ``` Note how the built-in `len` proc returns only the array's first dimension length. Another way of defining the `LightTower` to better illustrate its nested nature would be to omit the previous definition of the `LevelSetting` type and instead write it embedded directly as the type of the first dimension: -.. code-block:: nim + ```nim type LightTower = array[1..10, array[north..west, BlinkLights]] + ``` It is quite common to have arrays start at zero, so there's a shortcut syntax to specify a range from zero to the specified index minus one: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" type IntArray = array[0..5, int] # an array that is indexed with 0..5 QuickArray = array[6, int] # an array that is indexed with 0..5 @@ -1333,6 +1348,7 @@ to specify a range from zero to the specified index minus one: y = x for i in low(x) .. high(x): echo x[i], y[i] + ``` Sequences @@ -1355,12 +1371,11 @@ A sequence may be passed to an openarray parameter. Example: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" var x: seq[int] # a reference to a sequence of integers x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap + ``` Sequence variables are initialized with `@[]`. @@ -1374,8 +1389,7 @@ value. Here the `for` statement is looping over the results from the `pairs() `_ iterator from the `system `_ module. Examples: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" for value in @[3, 4, 5]: echo value # --> 3 @@ -1387,6 +1401,7 @@ value. Here the `for` statement is looping over the results from the # --> index: 0, value:3 # --> index: 1, value:4 # --> index: 2, value:5 + ``` Open arrays @@ -1402,8 +1417,7 @@ and `high `_ operations are available for open arrays too. Any array with a compatible base type can be passed to an openarray parameter, the index type does not matter. -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" var fruits: seq[string] # reference to a sequence of strings that is initialized with '@[]' capitals: array[3, string] # array of strings with a fixed size @@ -1417,6 +1431,7 @@ openarray parameter, the index type does not matter. assert openArraySize(fruits) == 2 # procedure accepts a sequence as parameter assert openArraySize(capitals) == 3 # but also an array type + ``` The openarray type cannot be nested: multidimensional openarrays are not supported because this is seldom needed and cannot be done efficiently. @@ -1430,8 +1445,7 @@ also a means to implement passing a variable number of arguments to a procedure. The compiler converts the list of arguments to an array automatically: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc myWriteln(f: File, a: varargs[string]) = for s in items(a): write(f, s) @@ -1440,13 +1454,13 @@ to an array automatically: myWriteln(stdout, "abc", "def", "xyz") # is transformed by the compiler to: myWriteln(stdout, ["abc", "def", "xyz"]) + ``` This transformation is only done if the varargs parameter is the last parameter in the procedure header. It is also possible to perform type conversions in this context: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc myWriteln(f: File, a: varargs[string, `$`]) = for s in items(a): write(f, s) @@ -1455,6 +1469,7 @@ type conversions in this context: myWriteln(stdout, 123, "abc", 4.0) # is transformed by the compiler to: myWriteln(stdout, [$123, $"abc", $4.0]) + ``` In this example `$ `_ is applied to any argument that is passed to the parameter `a`. Note that `$ `_ applied to strings is a @@ -1469,9 +1484,7 @@ context. A slice is just an object of type Slice which contains two bounds, `a` and `b`. By itself a slice is not very useful, but other collection types define operators which accept Slice objects to define ranges. -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" var a = "Nim is a programming language" b = "Slices are useless." @@ -1479,6 +1492,7 @@ define operators which accept Slice objects to define ranges. echo a[7 .. 12] # --> 'a prog' b[11 .. ^2] = "useful" echo b # --> 'Slices are useful.' + ``` In the previous example slices are used to modify a part of a string. The slice's bounds can hold any value supported by @@ -1492,12 +1506,12 @@ zero-based indices. So the string `b` is of length 19, and two different ways of specifying the indices are -.. code-block:: nim - + ```nim "Slices are useless." | | | 0 11 17 using indices ^19 ^8 ^2 using ^ syntax + ``` where `b[0 .. ^1]` is equivalent to `b[0 .. b.len-1]` and `b[0 ..< b.len]`, and it can be seen that the `^1` provides a shorthand way of specifying the `b.len-1`. See @@ -1528,7 +1542,7 @@ Each object type `Foo` has a constructor `Foo(field: value, ...)` where all of its fields can be initialized. Unspecified fields will get their default value. -.. code-block:: nim + ```nim type Person = object name: string @@ -1555,18 +1569,18 @@ get their default value. # unspecified members will be initialized with their default # values. In this case it is the empty string. doAssert person4.name == "" + ``` Object fields that should be visible from outside the defining module have to be marked with `*`. -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" type Person* = object # the type is visible from other modules name*: string # the field of this type is visible from other modules age*: int + ``` Tuples ------ @@ -1588,8 +1602,7 @@ tuple's field. Another notation that is not available for objects is `t[i]` to access the `i`'th field. Here `i` must be a constant integer. -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" type # type representing a person: # A person consists of a name and an age. @@ -1638,6 +1651,7 @@ integer. #person = building # --> Error: type mismatch: got (tuple[street: string, number: int]) # but expected 'Person' + ``` Even though you don't need to declare a type for a tuple to use it, tuples created with different field names will be considered different objects despite @@ -1652,9 +1666,7 @@ use parentheses around the values you want to assign the unpacking to, otherwise, you will be assigning the same value to all the individual variables! For example: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" import std/os let @@ -1669,11 +1681,11 @@ variables! For example: echo baddir echo badname echo badext + ``` Tuple unpacking is also supported in for-loops: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" let a = [(10, 'a'), (20, 'b'), (30, 'c')] for (x, c) in a: @@ -1684,6 +1696,7 @@ Tuple unpacking is also supported in for-loops: for i, (x, c) in a: echo i, c # This will output: 0a; 1b; 2c + ``` Fields of tuples are always public, they don't need to be explicitly marked to be exported, unlike for example fields in an object type. @@ -1711,9 +1724,7 @@ meaning to retrieve the item the reference points to. The `.` (access a tuple/object field operator) and `[]` (array/string/sequence index operator) operators perform implicit dereferencing operations for reference types: -.. code-block:: nim - :test: "nim c $1" - + ```nim test = "nim c $1" type Node = ref object le, ri: Node @@ -1722,13 +1733,14 @@ operators perform implicit dereferencing operations for reference types: var n = Node(data: 9) echo n.data # no need to write n[].data; in fact n[].data is highly discouraged! + ``` To allocate a new traced object, the built-in procedure `new` can be used: -.. code-block:: nim - - var n: Node - new(n) + ```nim + var n: Node + new(n) + ``` To deal with untraced memory, the procedures `alloc`, `dealloc` and `realloc` can be used. The `system `_ @@ -1747,8 +1759,7 @@ techniques. Example: -.. code-block:: nim - :test: "nim c $1" + ```nim test = "nim c $1" proc greet(name: string): string = "Hello, " & name & "!" @@ -1760,6 +1771,7 @@ Example: communicate(greet, "John") communicate(bye, "Mary") + ``` A subtle issue with procedural types is that the calling convention of the procedure influences the type compatibility: procedural types are only compatible @@ -1785,7 +1797,7 @@ Each module is in its own file. Modules enable `information hiding`:idx: and module by using the `import`:idx: statement. Only top-level symbols that are marked with an asterisk (`*`) are exported: -.. code-block:: nim + ```nim # Module A var x*, y: int @@ -1799,6 +1811,7 @@ with an asterisk (`*`) are exported: when isMainModule: # test the new `*` operator for sequences: assert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9]) + ``` The above module exports `x` and `*`, but not `y`. @@ -1814,15 +1827,17 @@ a symbol is ambiguous, it *must* be qualified. A symbol is ambiguous if it is defined in two (or more) different modules and both modules are imported by a third one: -.. code-block:: nim + ```nim # Module A var x*: string + ``` -.. code-block:: nim + ```nim # Module B var x*: int + ``` -.. code-block:: nim + ```nim # Module C import A, B write(stdout, x) # error: x is ambiguous @@ -1830,20 +1845,23 @@ imported by a third one: var x = 4 write(stdout, x) # not ambiguous: uses the module C's x + ``` But this rule does not apply to procedures or iterators. Here the overloading rules apply: -.. code-block:: nim + ```nim # Module A proc x*(a: int): string = $a + ``` -.. code-block:: nim + ```nim # Module B proc x*(a: string): string = $a + ``` -.. code-block:: nim + ```nim # Module C import A, B write(stdout, x(3)) # no error: A.x is called @@ -1851,6 +1869,7 @@ rules apply: proc x*(a: int): string = discard write(stdout, x(3)) # ambiguous: which `x` is to call? + ``` Excluding symbols @@ -1860,8 +1879,9 @@ The normal `import` statement will bring in all exported symbols. These can be limited by naming symbols that should be excluded using the `except` qualifier. -.. code-block:: nim + ```nim import mymodule except y + ``` From statement @@ -1871,32 +1891,36 @@ We have already seen the simple `import` statement that just imports all exported symbols. An alternative that only imports listed symbols is the `from import` statement: -.. code-block:: nim + ```nim from mymodule import x, y, z + ``` The `from` statement can also force namespace qualification on symbols, thereby making symbols available, but needing to be qualified in order to be used. -.. code-block:: nim + ```nim from mymodule import x, y, z x() # use x without any qualification + ``` -.. code-block:: nim + ```nim from mymodule import nil mymodule.x() # must qualify x with the module name as prefix x() # using x here without qualification is a compile error + ``` Since module names are generally long to be descriptive, you can also define a shorter alias to use when qualifying symbols. -.. code-block:: nim + ```nim from mymodule as m import nil m.x() # m is aliasing mymodule + ``` Include statement @@ -1906,8 +1930,9 @@ The `include` statement does something fundamentally different than importing a module: it merely includes the contents of a file. The `include` statement is useful to split up a large module into several files: -.. code-block:: nim + ```nim include fileA, fileB, fileC + ``` diff --git a/doc/tut2.md b/doc/tut2.md index d37d6a16a0..762d1cef56 100644 --- a/doc/tut2.md +++ b/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 `_ procs from the `system `_ 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 ========================= diff --git a/doc/tut3.md b/doc/tut3.md index 2fcfd4220c..4c9b359b8c 100644 --- a/doc/tut3.md +++ b/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 -------------------------------