123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- <?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <!-- This file is generated by Nim. -->
- <html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en" data-theme="auto">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Contributing</title>
- <!-- Google fonts -->
- <link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
- <link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
- <!-- Favicon -->
- <link rel="shortcut icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAUAAAAF////AP///wD///8A////AP///wD///8A////AP///wD///8A////AAAAAAIAAABbAAAAlQAAAKIAAACbAAAAmwAAAKIAAACVAAAAWwAAAAL///8A////AP///wD///8A////AAAAABQAAADAAAAAYwAAAA3///8A////AP///wD///8AAAAADQAAAGMAAADAAAAAFP///wD///8A////AP///wAAAACdAAAAOv///wD///8A////AP///wD///8A////AP///wD///8AAAAAOgAAAJ3///8A////AP///wAAAAAnAAAAcP///wAAAAAoAAAASv///wD///8A////AP///wAAAABKAAAAKP///wAAAABwAAAAJ////wD///8AAAAAgQAAABwAAACIAAAAkAAAAJMAAACtAAAAFQAAABUAAACtAAAAkwAAAJAAAACIAAAAHAAAAIH///8A////AAAAAKQAAACrAAAAaP///wD///8AAAAARQAAANIAAADSAAAARf///wD///8AAAAAaAAAAKsAAACk////AAAAADMAAACcAAAAnQAAABj///8A////AP///wAAAAAYAAAAGP///wD///8A////AAAAABgAAACdAAAAnAAAADMAAAB1AAAAwwAAAP8AAADpAAAAsQAAAE4AAAAb////AP///wAAAAAbAAAATgAAALEAAADpAAAA/wAAAMMAAAB1AAAAtwAAAOkAAAD/AAAA/wAAAP8AAADvAAAA3gAAAN4AAADeAAAA3gAAAO8AAAD/AAAA/wAAAP8AAADpAAAAtwAAAGUAAAA/AAAA3wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAADfAAAAPwAAAGX///8A////AAAAAEgAAADtAAAAvwAAAL0AAADGAAAA7wAAAO8AAADGAAAAvQAAAL8AAADtAAAASP///wD///8A////AP///wD///8AAAAAO////wD///8A////AAAAAIcAAACH////AP///wD///8AAAAAO////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A//8AAP//AAD4HwAA7/cAAN/7AAD//wAAoYUAAJ55AACf+QAAh+EAAAAAAADAAwAA4AcAAP5/AAD//wAA//8AAA=="/>
- <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH4QQQEwksSS9ZWwAAAk1JREFUWMPtll2ITVEUx39nn/O7Y5qR8f05wtCUUr6ZIS++8pEnkZInPImneaCQ5METNdOkeFBKUhMPRIkHKfEuUZSUlGlKPN2TrgfncpvmnntnmlEyq1Z7t89/rf9a6+y99oZxGZf/XeIq61EdtgKXgdXA0xrYAvBjOIF1AI9zvjcC74BSpndrJPkBWDScTF8Aa4E3wDlgHbASaANmVqlcCnwHvgDvgVfAJ+AikAAvgfVZwLnSVZHZaOuKoQi3ZOMi4NkYkpe1p4J7A8BpYAD49hfIy/oqG0+hLomiKP2L5L+1ubn5115S+3OAn4EnwBlgMzCjyt6ZAnQCJ4A7wOs88iRJHvw50HoujuPBoCKwHWiosy8MdfZnAdcHk8dxXFJ3VQbQlCTJvRBCGdRbD4M6uc5glpY3eAihpN5S5w12diSEcCCEcKUO4ljdr15T76ur1FDDLIQQ3qv71EdDOe3Kxj3leRXyk+pxdWnFWod6Wt2bY3de3aSuUHcPBVimHs7mK9WrmeOF6lR1o9qnzskh2ar2qm1qizpfXaPeVGdlmGN5pb09qMxz1Xb1kLqgzn1RyH7JUXW52lr5e/Kqi9qpto7V1atuUzfnARrV7jEib1T76gG2qxdGmXyiekkt1GswPTtek0aBfJp6YySGBfWg2tPQ0FAYgf1stUfdmdcjarbYJEniKIq6gY/Aw+zWHAC+p2labGpqiorFYgGYCEzN7oQdQClN07O1/EfDyGgC0ALMBdYAi4FyK+4H3gLPsxfR1zRNi+NP7nH5J+QntnXe5B5mpfQAAAAASUVORK5CYII=">
- <!-- CSS -->
- <link rel="stylesheet" type="text/css" href="nimdoc.out.css?v=2.3.1">
- <!-- JS -->
- <script type="text/javascript" src="dochack.js?v=2.3.1"></script>
- </head>
- <body>
- <div class="document" id="documentId">
- <div class="container">
- <h1 class="title">Contributing</h1>
- <div class="row">
- <div class="three columns">
- <div class="theme-select-wrapper">
- <label for="theme-select">Theme: </label>
- <select id="theme-select" onchange="setTheme(this.value)">
- <option value="auto">🌗 Match OS</option>
- <option value="dark">🌑 Dark</option>
- <option value="light">🌕 Light</option>
- </select>
- </div>
- <div id="global-links">
- <ul class="simple-boot">
- <li><a href="manual.html">Manual</a></li>
- <li><a href="lib.html">Standard library</a></li>
- <li> <a id="indexLink" href="theindex.html">Index</a></li>
- <li><a href="compiler/theindex.html">Compiler docs</a></li>
- <li><a href="https://nim-lang.github.io/fusion/theindex.html">Fusion docs</a></li>
- <li><a href="https://nim-lang.github.io/Nim/">devel</a>, <a href="https://nim-lang.org/documentation.html">stable</a></li>
- </ul>
- </div>
- <div id="searchInputDiv">
- Search: <input type="search" id="searchInput"
- oninput="search()" />
- </div>
- <div class="search-groupby">
- Group by:
- <select onchange="groupBy(this.value)">
- <option value="section">Section</option>
- <option value="type">Type</option>
- </select>
- </div>
- <ul class="simple simple-toc" id="toc-list">
- <li><a class="reference" id="writing-tests_toc" href="#writing-tests">Writing tests</a></li>
- <ul class="simple"><li><a class="reference" id="writing-tests-stdlib_toc" href="#writing-tests-stdlib">Stdlib</a></li>
- <li><a class="reference" id="writing-tests-compiler_toc" href="#writing-tests-compiler">Compiler</a></li>
- </ul><li><a class="reference" id="running-tests_toc" href="#running-tests">Running tests</a></li>
- <li><a class="reference" id="comparing-tests_toc" href="#comparing-tests">Comparing tests</a></li>
- <li><a class="reference" id="deprecation_toc" href="#deprecation">Deprecation</a></li>
- <li><a class="reference" id="documentation_toc" href="#documentation">Documentation</a></li>
- <li><a class="reference" id="best-practices_toc" href="#best-practices">Best practices</a></li>
- <li><a class="reference" id="the-cmdgit-stuff_toc" href="#the-cmdgit-stuff">The <tt class="docutils literal"><span class="pre"><span class="program">git</span></span></tt> stuff</a></li>
- <ul class="simple"><li><a class="reference" id="the-cmdgit-stuff-general-commit-rules_toc" href="#the-cmdgit-stuff-general-commit-rules">General commit rules</a></li>
- <li><a class="reference" id="the-cmdgit-stuff-continuous-integration-ci_toc" href="#the-cmdgit-stuff-continuous-integration-ci">Continuous Integration (CI)</a></li>
- <li><a class="reference" id="the-cmdgit-stuff-debugging-ci-failures-flaky-tests-etc_toc" href="#the-cmdgit-stuff-debugging-ci-failures-flaky-tests-etc">Debugging CI failures, flaky tests, etc</a></li>
- <li><a class="reference" id="the-cmdgit-stuff-code-reviews_toc" href="#the-cmdgit-stuff-code-reviews">Code reviews</a></li>
- </ul><li><a class="reference" id="documentation-style_toc" href="#documentation-style">Documentation Style</a></li>
- <ul class="simple"><li><a class="reference" id="documentation-style-general-guidelines_toc" href="#documentation-style-general-guidelines">General Guidelines</a></li>
- <li><a class="reference" id="documentation-style-moduleminuslevel-documentation_toc" href="#documentation-style-moduleminuslevel-documentation">Module-level documentation</a></li>
- <li><a class="reference" id="documentation-style-procs-templates-macros-converters-and-iterators_toc" href="#documentation-style-procs-templates-macros-converters-and-iterators">Procs, Templates, Macros, Converters, and Iterators</a></li>
- <li><a class="reference" id="documentation-style-types_toc" href="#documentation-style-types">Types</a></li>
- <li><a class="reference" id="documentation-style-var-let-and-const_toc" href="#documentation-style-var-let-and-const">Var, Let, and Const</a></li>
- </ul><li><a class="reference" id="evolving-the-stdlib_toc" href="#evolving-the-stdlib">Evolving the stdlib</a></li>
- <ul class="simple"><li><a class="reference" id="evolving-the-stdlib-what-the-compiler-itself-needs-must-be-part-of-the-stdlib_toc" href="#evolving-the-stdlib-what-the-compiler-itself-needs-must-be-part-of-the-stdlib">What the compiler itself needs must be part of the stdlib</a></li>
- <li><a class="reference" id="evolving-the-stdlib-vocabulary-types-must-be-part-of-the-stdlib_toc" href="#evolving-the-stdlib-vocabulary-types-must-be-part-of-the-stdlib">Vocabulary types must be part of the stdlib</a></li>
- <li><a class="reference" id="evolving-the-stdlib-existing-battleminustested-modules-stay_toc" href="#evolving-the-stdlib-existing-battleminustested-modules-stay">Existing, battle-tested modules stay</a></li>
- <li><a class="reference" id="evolving-the-stdlib-syntactic-helpers-can-start-as-experimental-stdlib-modules_toc" href="#evolving-the-stdlib-syntactic-helpers-can-start-as-experimental-stdlib-modules">Syntactic helpers can start as experimental stdlib modules</a></li>
- <li><a class="reference" id="evolving-the-stdlib-other-new-stdlib-modules-do-not-start-as-stdlib-modules_toc" href="#evolving-the-stdlib-other-new-stdlib-modules-do-not-start-as-stdlib-modules">Other new stdlib modules do not start as stdlib modules</a></li>
- <li><a class="reference" id="evolving-the-stdlib-little-additions-are-acceptable_toc" href="#evolving-the-stdlib-little-additions-are-acceptable">Little additions are acceptable</a></li>
- <li><a class="reference" id="evolving-the-stdlib-conventions_toc" href="#evolving-the-stdlib-conventions">Conventions</a></li>
- </ul><li><a class="reference" id="breaking-changes_toc" href="#breaking-changes">Breaking Changes</a></li>
- <ul class="simple"><li><a class="reference" id="breaking-changes-runminustime-breaking-changes_toc" href="#breaking-changes-runminustime-breaking-changes">Run-time breaking changes</a></li>
- <li><a class="reference" id="breaking-changes-compileminustime-breaking-changes_toc" href="#breaking-changes-compileminustime-breaking-changes">Compile-time breaking changes</a></li>
- <li><a class="reference" id="breaking-changes-compilerslashlanguage-spec-bugfixes_toc" href="#breaking-changes-compilerslashlanguage-spec-bugfixes">Compiler/language spec bugfixes</a></li>
- <li><a class="reference" id="breaking-changes-nonminusbreaking-changes_toc" href="#breaking-changes-nonminusbreaking-changes">Non-breaking changes</a></li>
- </ul>
- </ul>
- </div>
- <div class="nine columns" id="content">
- <a href="https://github.com/nim-lang/Nim/tree/devel/doc/contributing.md#L1" class="link-seesrc" target="_blank">Source</a>
- <a href="https://github.com/nim-lang/Nim/edit/devel/doc/contributing.md#L1" class="link-seesrc" target="_blank" >Edit</a>
- <div id="tocRoot"></div>
-
- <p class="module-desc"><p>Contributing happens via "Pull requests" (PR) on GitHub. Every PR needs to be reviewed before it can be merged and the Continuous Integration should be green. The title of a PR should contain a brief description. If it fixes an issue, in addition to the number of the issue, the title should also contain a description of the issue.</p>
- <p>The PR has to be approved by two core developers or by Araq.</p>
- <h1><a class="toc-backref" id="writing-tests" href="#writing-tests">Writing tests</a></h1><p>There are 4 types of tests:</p>
- <ol class="simple"><li><tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt> documentation comment tests, ran by <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="Identifier">mymod.nim</span></span></tt> These end up in documentation and ensure documentation stays in sync with code.</li>
- <li>separate test files, e.g.: <tt class="docutils literal"><span class="pre">tests/stdlib/tos.nim</span></tt>. In nim repo, <tt class="docutils literal"><span class="pre"><span class="program">testament</span></span></tt> (see below) runs all <tt class="docutils literal"><span class="pre">$nim/tests/*/t*.nim</span></tt> test files; for nimble packages, see <a class="reference external" href="https://github.com/nim-lang/nimble#tests">https://github.com/nim-lang/nimble#tests</a>.</li>
- <li>(deprecated) tests in <tt class="docutils literal"><span class="pre"><span class="Keyword">when</span> <span class="Identifier">isMainModule</span><span class="Punctuation">:</span></span></tt> block, ran by <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">r</span> <span class="Identifier">mymod.nim</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="program">nimble</span> <span class="option">test</span></span></tt> can run those in nimble packages when specified in a <tt class="docutils literal"><span class="pre"><span class="Identifier">task</span> <span class="StringLit">"test"</span></span></tt>.</li>
- <li>(not preferred) <tt class="docutils literal"><span class="pre">.. code-block:: nim</span></tt> RST snippets; these should only be used in rst sources, in nim sources <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt> should now always be preferred to those for several reasons (cleaner syntax, syntax highlights, batched testing, and parameter <tt class="docutils literal"><span class="pre"><span class="Identifier">rdoccmd</span></span></tt> allows customization).</li>
- </ol>
- <p>Not all the tests follow the convention here, feel free to change the ones that don't. Always leave the code cleaner than you found it.</p>
- <h2><a class="toc-backref" id="writing-tests-stdlib" href="#writing-tests-stdlib">Stdlib</a></h2><p>Each stdlib module (anything under <tt class="docutils literal"><span class="pre">lib/</span></tt>, e.g. <tt class="docutils literal"><span class="pre">lib/pure/os.nim</span></tt>) should preferably have a corresponding separate test file, e.g. <tt class="docutils literal"><span class="pre">tests/stdlib/tos.nim</span></tt>. The old convention was to add a <tt class="docutils literal"><span class="pre"><span class="Keyword">when</span> <span class="Identifier">isMainModule</span><span class="Punctuation">:</span></span></tt> block in the source file, which only gets executed when the tester is building the file.</p>
- <p>Each test should be in a separate <tt class="docutils literal"><span class="pre"><span class="Keyword">block</span><span class="Punctuation">:</span></span></tt> statement, such that each has its own scope. Use boolean conditions and <tt class="docutils literal"><span class="pre"><span class="Identifier">doAssert</span></span></tt> for the testing by itself, don't rely on echo statements or similar; in particular, avoid things like <tt class="docutils literal"><span class="pre"><span class="Identifier">echo</span> <span class="StringLit">"done"</span></span></tt>. Don't use <tt class="docutils literal"><span class="pre"><span class="Identifier">unittest</span><span class="Operator">.</span><span class="Identifier">suite</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">unittest</span><span class="Operator">.</span><span class="Identifier">test</span></span></tt>.</p>
- <p>Sample test:</p>
- <p><pre class="listing"><span class="Keyword">block</span><span class="Punctuation">:</span> <span class="Comment"># foo</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="DecNumber">1</span><span class="Punctuation">)</span> <span class="Operator">==</span> <span class="DecNumber">10</span>
- <span class="Keyword">block</span><span class="Punctuation">:</span> <span class="Comment"># bug #1234</span>
- <span class="Keyword">static</span><span class="Punctuation">:</span> <span class="Identifier">doAssert</span> <span class="DecNumber">1</span><span class="Operator">+</span><span class="DecNumber">1</span> <span class="Operator">==</span> <span class="DecNumber">2</span>
- <span class="Keyword">block</span><span class="Punctuation">:</span> <span class="Comment"># bug #1235</span>
- <span class="Keyword">var</span> <span class="Identifier">seq2D</span> <span class="Operator">=</span> <span class="Identifier">newSeqWith</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">,</span> <span class="Identifier">newSeq</span><span class="Punctuation">[</span><span class="Identifier">bool</span><span class="Punctuation">]</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span><span class="Punctuation">)</span>
- <span class="Identifier">seq2D</span><span class="Punctuation">[</span><span class="DecNumber">0</span><span class="Punctuation">]</span><span class="Punctuation">[</span><span class="DecNumber">0</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Identifier">true</span>
- <span class="Identifier">seq2D</span><span class="Punctuation">[</span><span class="DecNumber">1</span><span class="Punctuation">]</span><span class="Punctuation">[</span><span class="DecNumber">0</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Identifier">true</span>
- <span class="Identifier">seq2D</span><span class="Punctuation">[</span><span class="DecNumber">0</span><span class="Punctuation">]</span><span class="Punctuation">[</span><span class="DecNumber">1</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Identifier">true</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">seq2D</span> <span class="Operator">==</span> <span class="Operator">@</span><span class="Punctuation">[</span><span class="Operator">@</span><span class="Punctuation">[</span><span class="Identifier">true</span><span class="Punctuation">,</span> <span class="Identifier">true</span><span class="Punctuation">]</span><span class="Punctuation">,</span> <span class="Operator">@</span><span class="Punctuation">[</span><span class="Identifier">true</span><span class="Punctuation">,</span> <span class="Identifier">false</span><span class="Punctuation">]</span><span class="Punctuation">,</span>
- <span class="Operator">@</span><span class="Punctuation">[</span><span class="Identifier">false</span><span class="Punctuation">,</span> <span class="Identifier">false</span><span class="Punctuation">]</span><span class="Punctuation">,</span> <span class="Operator">@</span><span class="Punctuation">[</span><span class="Identifier">false</span><span class="Punctuation">,</span> <span class="Identifier">false</span><span class="Punctuation">]</span><span class="Punctuation">]</span>
- <span class="Comment"># doAssert with `not` can now be done as follows:</span>
- <span class="Identifier">doAssert</span> <span class="Keyword">not</span> <span class="Punctuation">(</span><span class="DecNumber">1</span> <span class="Operator">==</span> <span class="DecNumber">2</span><span class="Punctuation">)</span></pre></p>
- <p>Always refer to a GitHub issue using the following exact syntax: <tt class="docutils literal"><span class="pre">bug #1234</span></tt> as shown above, so that it's consistent and easier to search or for tooling. Some browser extensions (e.g. <a class="reference external" href="https://github.com/sindresorhus/refined-github">https://github.com/sindresorhus/refined-github</a>) will even turn those in clickable links when it works.</p>
- <p>Rationale for using a separate test file instead of <tt class="docutils literal"><span class="pre"><span class="Keyword">when</span> <span class="Identifier">isMainModule</span><span class="Punctuation">:</span></span></tt> block:</p>
- <ul class="simple"><li>allows custom compiler flags or testing options (see details below)</li>
- <li>faster CI since they can be joined in <tt class="docutils literal"><span class="pre">megatest</span></tt> (combined into a single test)</li>
- <li>avoids making the parser do un-necessary work when a source file is merely imported</li>
- <li>avoids mixing source and test code when reporting line of code statistics or code coverage</li>
- </ul>
- <h2><a class="toc-backref" id="writing-tests-compiler" href="#writing-tests-compiler">Compiler</a></h2><p>The tests for the compiler use a testing tool called <tt class="docutils literal"><span class="pre"><span class="program">testament</span></span></tt>. They are all located in <tt class="docutils literal"><span class="pre">tests/</span></tt> (e.g.: <tt class="docutils literal"><span class="pre">tests/destructor/tdestructor3.nim</span></tt>). Each test has its own file. All test files are prefixed with <tt class="docutils literal"><span class="pre"><span class="Identifier">t</span></span></tt>. If you want to create a file for import into another test only, use the prefix <tt class="docutils literal"><span class="pre"><span class="Identifier">m</span></span></tt>.</p>
- <p>At the beginning of every test is the expected behavior of the test. Possible keys are:</p>
- <ul class="simple"><li><tt class="docutils literal"><span class="pre"><span class="Identifier">cmd</span></span></tt>: A compilation command template e.g. <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">$target</span> <span class="option">--threads:on</span> <span class="option">$options</span> <span class="option">$file</span></span></tt></li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">output</span></span></tt>: The expected output (stdout + stderr), most likely via <tt class="docutils literal"><span class="pre"><span class="Identifier">echo</span></span></tt></li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">exitcode</span></span></tt>: Exit code of the test (via <tt class="docutils literal"><span class="pre"><span class="Identifier">exit</span><span class="Punctuation">(</span><span class="Identifier">number</span><span class="Punctuation">)</span></span></tt>)</li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">errormsg</span></span></tt>: The expected compiler error message</li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">file</span></span></tt>: The file the errormsg was produced at</li>
- <li><tt class="docutils literal"><span class="pre"><span class="Identifier">line</span></span></tt>: The line the errormsg was produced at</li>
- </ul>
- <p>For a full spec, see here: <tt class="docutils literal"><span class="pre">testament/specs.nim</span></tt></p>
- <p>An example of a test:</p>
- <p><pre class="listing"><span class="Keyword">discard</span> <span class="LongStringLit">"""
- errormsg: "type mismatch: got (PTest)"
- """</span>
- <span class="Keyword">type</span>
- <span class="Identifier">PTest</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span>
- <span class="Keyword">proc</span> <span class="Identifier">test</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">PTest</span><span class="Punctuation">,</span> <span class="Identifier">y</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span> <span class="Operator">=</span> <span class="Keyword">nil</span>
- <span class="Keyword">var</span> <span class="Identifier">buf</span><span class="Punctuation">:</span> <span class="Identifier">PTest</span>
- <span class="Identifier">buf</span><span class="Operator">.</span><span class="Identifier">test</span><span class="Punctuation">(</span><span class="Punctuation">)</span></pre></p>
- <h1><a class="toc-backref" id="running-tests" href="#running-tests">Running tests</a></h1><p>You can run the tests with</p>
- <p><pre class="listing"><span class="program">./koch</span> <span class="option">tests</span></pre></p>
- <p>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</p>
- <p><pre class="listing"><span class="program">./koch</span> <span class="option">tests</span> <span class="option">--failing</span> <span class="option">all</span></pre></p>
- <p>You can also run only a single category of tests. A category is a subdirectory in the <tt class="docutils literal"><span class="pre">tests/</span></tt> directory. There are a couple of special categories; for a list of these, see <tt class="docutils literal"><span class="pre">testament/categories.nim</span></tt>, at the bottom.</p>
- <p><pre class="listing"><span class="program">./koch</span> <span class="option">tests</span> <span class="option">c</span> <span class="option">lib</span> <span class="Comment"># compiles / runs stdlib modules, including `isMainModule` tests</span>
- <span class="program">./koch</span> <span class="option">tests</span> <span class="option">c</span> <span class="option">megatest</span> <span class="Comment"># runs a set of tests that can be combined into 1</span></pre></p>
- <p>To run a single test:</p>
- <p><pre class="listing"><span class="program">./koch</span> <span class="option">test</span> <span class="option">run</span> <span class="Identifier"><category>/<name></span> <span class="Comment"># e.g.: tuples/ttuples_issues</span>
- <span class="program">./koch</span> <span class="option">test</span> <span class="option">run</span> <span class="Identifier">tests/stdlib/tos.nim</span> <span class="Comment"># can also provide relative path</span></pre></p>
- <p>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 local configuration (e.g. in <tt class="docutils literal"><span class="pre">~/.config/nim/nim.cfg</span></tt>) which may affect some tests; this can also be achieved by using <tt class="docutils literal"><span class="pre"><span class="program">export</span> <span class="option">XDG_CONFIG_HOME=pathtoAlternateConfig</span></span></tt> before running <tt class="docutils literal"><span class="pre"><span class="program">./koch</span></span></tt> commands.</p>
- <h1><a class="toc-backref" id="comparing-tests" href="#comparing-tests">Comparing tests</a></h1><p>Test failures can be grepped using <tt class="docutils literal"><span class="pre">Failure:</span></tt>.</p>
- <p>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.</p>
- <p><pre class="listing"><span class="program">git</span> <span class="option">checkout</span> <span class="option">devel</span>
- <span class="Identifier">DEVEL_COMMIT=$</span><span class="Operator">(</span><span class="program">git</span> <span class="option">rev-parse</span> <span class="option">HEAD</span><span class="Operator">)</span>
- <span class="program">./koch</span> <span class="option">tests</span></pre></p>
- <p>Then switch over to your changes and run the tester again.</p>
- <p><pre class="listing"><span class="program">git</span> <span class="option">checkout</span> <span class="option">your-changes</span>
- <span class="program">./koch</span> <span class="option">tests</span></pre></p>
- <p>Then you can ask the tester to create a <tt class="docutils literal"><span class="pre">testresults.html</span></tt> which will tell you if any new tests passed/failed.</p>
- <p><pre class="listing"><span class="program">./koch</span> <span class="option">tests</span> <span class="option">--print</span> <span class="option">html</span> <span class="option">$DEVEL_COMMIT</span></pre></p>
- <h1><a class="toc-backref" id="deprecation" href="#deprecation">Deprecation</a></h1><p>Backwards compatibility is important. When renaming types, procedures, etc. the old name must be marked as deprecated using the <tt class="docutils literal"><span class="pre"><span class="Identifier">deprecated</span></span></tt> pragma:</p>
- <p><pre class="listing"><span class="Comment"># for routines (proc/template/macro/iterator) and types:</span>
- <span class="Keyword">proc</span> <span class="Identifier">oldProc</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">,</span> <span class="Identifier">b</span><span class="Punctuation">:</span> <span class="Identifier">float</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">bool</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">deprecated</span><span class="Punctuation">:</span>
- <span class="StringLit">"deprecated since v1.2.3; use `newImpl: string -> int` instead"</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span> <span class="Keyword">discard</span>
- <span class="Comment"># for (const/var/let/fields) the msg is not yet supported:</span>
- <span class="Keyword">const</span> <span class="Identifier">Foo</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">deprecated</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span> <span class="DecNumber">1</span>
- <span class="Comment"># for enum types, you can deprecate the type or some elements</span>
- <span class="Comment"># (likewise with object types and their fields):</span>
- <span class="Keyword">type</span> <span class="Identifier">Bar</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">deprecated</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span> <span class="Keyword">enum</span> <span class="Identifier">bar0</span><span class="Punctuation">,</span> <span class="Identifier">bar1</span>
- <span class="Keyword">type</span> <span class="Identifier">Barz</span> <span class="Operator">=</span> <span class="Keyword">enum</span> <span class="Identifier">baz0</span><span class="Punctuation">,</span> <span class="Identifier">baz1</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">deprecated</span><span class="Operator">.</span><span class="Punctuation">}</span><span class="Punctuation">,</span> <span class="Identifier">baz2</span></pre></p>
- <p>See also <a class="reference external" href="manual.html#pragmas-deprecated-pragma">Deprecated</a> pragma in the manual.</p>
- <h1><a class="toc-backref" id="documentation" href="#documentation">Documentation</a></h1><p>When contributing new procs, be sure to add documentation, especially if the proc is public. Even private procs benefit from documentation and can be viewed using <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="option">--docInternal</span> <span class="Identifier">foo.nim</span></span></tt>. Documentation begins on the line following the <tt class="docutils literal"><span class="pre"><span class="Keyword">proc</span></span></tt> definition, and is prefixed by <tt class="docutils literal"><span class="pre"><span class="Comment">##</span></span></tt> on each line.</p>
- <p>Runnable code examples are also encouraged, to show typical behavior with a few test cases (typically 1 to 3 <tt class="docutils literal"><span class="pre"><span class="Identifier">assert</span></span></tt> statements, depending on complexity). These <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt> are automatically run by <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="Identifier">mymodule.nim</span></span></tt> as well as <tt class="docutils literal"><span class="pre"><span class="program">testament</span></span></tt> and guarantee they stay in sync.</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">addBar</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Identifier">string</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span>
- <span class="Comment">## Adds "Bar" to `a`.</span>
- <span class="Identifier">runnableExamples</span><span class="Punctuation">:</span>
- <span class="Identifier">assert</span> <span class="StringLit">"baz"</span><span class="Operator">.</span><span class="Identifier">addBar</span> <span class="Operator">==</span> <span class="StringLit">"bazBar"</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">a</span> <span class="Operator">&</span> <span class="StringLit">"Bar"</span></pre></p>
- <p>See <a class="reference external" href="os.html#parentDir,string">parentDir</a> example.</p>
- <p>The RestructuredText Nim uses has a special syntax for including code snippets embedded in documentation; these are not run by <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span></span></tt> and therefore are not guaranteed to stay in sync, so <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt> is almost always preferred:</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">someProc</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span>
- <span class="Comment">## Returns "something"</span>
- <span class="Comment">##</span>
- <span class="Comment">## ```</span>
- <span class="Comment">## echo someProc() # "something"</span>
- <span class="Comment">## ```</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="StringLit">"something"</span> <span class="Comment"># single-hash comments do not produce documentation</span></pre></p>
- <p>The ``` followed by a newline and an indentation instructs the <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span></span></tt> command to produce syntax-highlighted example code with the documentation (``` is sufficient inside a <tt class="docutils literal"><span class="pre">.nim</span></tt> module, while from a <tt class="docutils literal"><span class="pre">.md</span></tt> one needs to set the language explicitly as ```nim).</p>
- <p>When forward declaration is used, the documentation should be included with the first appearance of the proc.</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">hello</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span>
- <span class="Comment">## Put documentation here</span>
- <span class="Keyword">proc</span> <span class="Identifier">nothing</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Operator">=</span> <span class="Keyword">discard</span>
- <span class="Keyword">proc</span> <span class="Identifier">hello</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span>
- <span class="Comment">## ignore this</span>
- <span class="Identifier">echo</span> <span class="StringLit">"hello"</span></pre></p>
- <p>The preferred documentation style is to begin with a capital letter and use the third-person singular. That is, between:</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">hello</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span>
- <span class="Comment">## Returns "hello"</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="StringLit">"hello"</span></pre></p>
- <p>or</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">hello</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span>
- <span class="Comment">## say hello</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="StringLit">"hello"</span></pre></p>
- <p>the first is preferred.</p>
- <p>When you specify an <em>RST role</em> (highlighting/interpretation marker) do it in the postfix form for uniformity, that is after `text in backticks`. For example an <tt class="docutils literal"><span class="pre">:idx:</span></tt> role for referencing a topic ("SQLite" in the example below) from <a class="reference external" href="https://nim-lang.org/docs/theindex.html">Nim Index</a> can be used in doc comment this way:</p>
- <p><pre class="listing"><span class="Comment">## A higher level `SQLite`:idx: database wrapper.</span></pre></p>
- <p>Inline monospaced text can be input using `single backticks` or ``double backticks``. The former are syntactically highlighted, the latter are not. To avoid accidental highlighting follow this rule in <tt class="docutils literal"><span class="pre">*.nim</span></tt> files:</p>
- <ul class="simple"><li><p>Use single backticks for fragments of code in Nim and other programming languages, including identifiers, in <tt class="docutils literal"><span class="pre">*.nim</span></tt> files.</p>
- <p>For languages other than Nim add a role after final backtick, e.g. for C++ inline highlighting:</p>
- <pre>`#include <stdio.h>`:cpp:</pre>
- <p>For a currently unsupported language add the <tt class="docutils literal"><span class="pre"><span class="Punctuation">:</span><span class="Identifier">code</span><span class="Punctuation">:</span></span></tt> role, like for SQL in this example:</p>
- <pre>`SELECT * FROM <table_name>;`:code:</pre>
- <p>Highlight shell commands by <tt class="docutils literal"><span class="pre">:cmd:</span></tt> role; for command line options use <tt class="docutils literal"><span class="pre">:option:</span></tt> role, e.g.: `--docInternal`:option:.</p>
- </li>
- <li>Use double backticks:<ul class="simple"><li>For file names: ``os.nim``</li>
- <li>For fragments of strings <strong>not</strong> enclosed by <tt class="docutils literal"><span class="pre"><span class="StringLit">"</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="StringLit">"</span></span></tt> and not related to code, e.g. text of compiler messages</li>
- <li>When code ends with a standalone <tt class="docutils literal"><span class="pre">\</span></tt> (otherwise a combination of <tt class="docutils literal"><span class="pre">\</span></tt> and a final ` would get escaped)</li>
- </ul>
- </li>
- </ul>
- <div class="admonition admonition-info"><span class="admonition-info-text"><b>Note:</b></span>
- <tt class="docutils literal"><span class="pre">*.rst</span></tt> files have <tt class="docutils literal"><span class="pre">:literal:</span></tt> as their default role. So for them the rule above is only applicable if the <tt class="docutils literal"><span class="pre">:nim:</span></tt> role is set up manually as the default <sup><strong><a class="reference internal" href="#footnote-1">[1]</a></strong></sup>:<pre>.. role:: nim(code)
- :language: nim
- .. default-role:: nim</pre>
- <p>The first 2 lines are for other RST implementations, including Github one.</p>
- <hr class="footnote"><div class="footnote-group">
- <div id="footnote-1"><div class="footnote-label"><sup><strong><a href="#footnote-1">[1]</a></strong></sup></div>   this is fulfilled when <tt class="docutils literal"><span class="pre">doc/rstcommon.rst</span></tt> is included.
- </div>
- </div>
- </div>
- <h1><a class="toc-backref" id="best-practices" href="#best-practices">Best practices</a></h1><p>Note: these are general guidelines, not hard rules; there are always exceptions. Code reviews can just point to a specific section here to save time and propagate best practices.</p>
- <p id="define-needs-prefix">New <tt class="docutils literal"><span class="pre"><span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">foo</span><span class="Punctuation">)</span></span></tt> symbols need to be prefixed by the nimble package name, or by <tt class="docutils literal"><span class="pre"><span class="Identifier">nim</span></span></tt> for symbols in nim sources (e.g. compiler, standard library). This is to avoid name conflicts across packages.</p>
- <p><pre class="listing"><span class="Comment"># if in nim sources</span>
- <span class="Keyword">when</span> <span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">allocStats</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">discard</span> <span class="Comment"># bad, can cause conflicts</span>
- <span class="Keyword">when</span> <span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">nimAllocStats</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">discard</span> <span class="Comment"># preferred</span>
- <span class="Comment"># if in a package `cligen`:</span>
- <span class="Keyword">when</span> <span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">debug</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">discard</span> <span class="Comment"># bad, can cause conflicts</span>
- <span class="Keyword">when</span> <span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">cligenDebug</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">discard</span> <span class="Comment"># preferred</span></pre></p>
- <p id="noimplicitbool">Take advantage of no implicit bool conversion</p>
- <p><pre class="listing"><span class="Identifier">doAssert</span> <span class="Identifier">isValid</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Operator">==</span> <span class="Identifier">true</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">isValid</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># preferred</span></pre></p>
- <p id="design-for-mcs">Design with method call syntax chaining in mind</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">cond</span><span class="Punctuation">:</span> <span class="Identifier">bool</span><span class="Punctuation">,</span> <span class="Identifier">lines</span><span class="Punctuation">:</span> <span class="Identifier">seq</span><span class="Punctuation">[</span><span class="Identifier">string</span><span class="Punctuation">]</span><span class="Punctuation">)</span> <span class="Comment"># bad</span>
- <span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">lines</span><span class="Punctuation">:</span> <span class="Identifier">seq</span><span class="Punctuation">[</span><span class="Identifier">string</span><span class="Punctuation">]</span><span class="Punctuation">,</span> <span class="Identifier">cond</span><span class="Punctuation">:</span> <span class="Identifier">bool</span><span class="Punctuation">)</span> <span class="Comment"># preferred</span>
- <span class="Comment"># can be called as: `getLines().foo(false)`</span></pre></p>
- <p id="avoid-quit">Use exceptions (including <tt class="docutils literal"><span class="pre"><span class="Identifier">assert</span></span></tt> / <tt class="docutils literal"><span class="pre"><span class="Identifier">doAssert</span></span></tt>) instead of <tt class="docutils literal"><span class="pre"><span class="Identifier">quit</span></span></tt> rationale: <a class="reference external" href="https://forum.nim-lang.org/t/4089">https://forum.nim-lang.org/t/4089</a></p>
- <p><pre class="listing"><span class="Identifier">quit</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># bad in almost all cases</span>
- <span class="Identifier">doAssert</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># preferred</span></pre></p>
- <p id="tests-use-doassert">Use <tt class="docutils literal"><span class="pre"><span class="Identifier">doAssert</span></span></tt> (or <tt class="docutils literal"><span class="pre"><span class="Identifier">unittest</span><span class="Operator">.</span><span class="Identifier">check</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">unittest</span><span class="Operator">.</span><span class="Identifier">require</span></span></tt>), not <tt class="docutils literal"><span class="pre"><span class="Identifier">assert</span></span></tt> in all tests, so they'll be enabled even with <tt class="docutils literal"><span class="pre option">--assertions:off</span></tt>.</p>
- <p><pre class="listing"><span class="Keyword">block</span><span class="Punctuation">:</span> <span class="Comment"># foo</span>
- <span class="Identifier">assert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># bad</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># preferred</span></pre></p>
- <p id="runnableexamples-use-assert">An exception to the above rule is <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt> and <tt class="docutils literal"><span class="pre">code-block</span></tt> rst blocks intended to be used as <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt>, which for brevity use <tt class="docutils literal"><span class="pre"><span class="Identifier">assert</span></span></tt> instead of <tt class="docutils literal"><span class="pre"><span class="Identifier">doAssert</span></span></tt>. Note that <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="option">-d:danger</span> <span class="option">main</span></span></tt> won't pass <tt class="docutils literal"><span class="pre option">-d:danger</span></tt> to the <tt class="docutils literal"><span class="pre"><span class="Identifier">runnableExamples</span></span></tt>, but <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="option">--doccmd:-d:danger</span> <span class="option">main</span></span></tt> would, and so would the second example below:</p>
- <p><pre class="listing"><span class="Identifier">runnableExamples</span><span class="Punctuation">:</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># bad</span>
- <span class="Identifier">assert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># preferred</span>
- <span class="Identifier">runnableExamples</span><span class="Punctuation">(</span><span class="StringLit">"-d:danger"</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># `assert` would be disabled here, so `doAssert` makes more sense</span></pre></p>
- <p id="delegate-printing">Delegate printing to caller: return <tt class="docutils literal"><span class="pre"><span class="Identifier">string</span></span></tt> instead of calling <tt class="docutils literal"><span class="pre"><span class="Identifier">echo</span></span></tt> rationale: it's more flexible (e.g. allows the caller to call custom printing, including prepending location info, writing to log files, etc.).</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Operator">=</span> <span class="Identifier">echo</span> <span class="StringLit">"bar"</span> <span class="Comment"># bad</span>
- <span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">string</span> <span class="Operator">=</span> <span class="StringLit">"bar"</span> <span class="Comment"># preferred (usually)</span></pre></p>
- <p id="use-option">(Ongoing debate) Consider using Option instead of return bool + var argument, unless stack allocation is needed (e.g. for efficiency).</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">a</span><span class="Punctuation">:</span> <span class="Keyword">var</span> <span class="Identifier">Bar</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">bool</span>
- <span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">Option</span><span class="Punctuation">[</span><span class="Identifier">Bar</span><span class="Punctuation">]</span></pre></p>
- <p id="use-doassert-not-echo">Tests (including in testament) should always prefer assertions over <tt class="docutils literal"><span class="pre"><span class="Identifier">echo</span></span></tt>, except when that's not possible. It's more precise, easier for readers and maintainers to where expected values refer to. See for example <a class="reference external" href="https://github.com/nim-lang/Nim/pull/9335">https://github.com/nim-lang/Nim/pull/9335</a> and <a class="reference external" href="https://forum.nim-lang.org/t/4089">https://forum.nim-lang.org/t/4089</a></p>
- <p><pre class="listing"><span class="Identifier">echo</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Comment"># adds a line for testament in `output:` block inside `discard`.</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Operator">==</span> <span class="Punctuation">[</span><span class="DecNumber">1</span><span class="Punctuation">,</span> <span class="DecNumber">2</span><span class="Punctuation">]</span> <span class="Comment"># preferred, except when not possible to do so.</span></pre></p>
- <h1><a class="toc-backref" id="the-cmdgit-stuff" href="#the-cmdgit-stuff">The <tt class="docutils literal"><span class="pre"><span class="program">git</span></span></tt> stuff</a></h1>
- <h2><a class="toc-backref" id="the-cmdgit-stuff-general-commit-rules" href="#the-cmdgit-stuff-general-commit-rules">General commit rules</a></h2><ol class="simple"><li>Important, critical bugfixes that have a tiny chance of breaking somebody's code should be backported to the latest stable release branch (currently 1.4.x) and maybe also all the way back to the 1.0.x branch. The commit message should contain the tag <tt class="docutils literal"><span class="pre">[backport]</span></tt> for "backport to the latest stable release" and the tag <tt class="docutils literal"><span class="pre">[backport:$VERSION]</span></tt> for backporting back to the given $VERSION (and all newer releases).</li>
- <li>If you introduce changes which affect backward compatibility, make breaking changes, or have PR which is tagged as <tt class="docutils literal"><span class="pre">[feature]</span></tt>, the changes should be mentioned in <a class="reference external" href=" https://github.com/nim-lang/Nim/blob/devel/changelog.md">the changelog</a>.</li>
- <li><p>All changes introduced by the commit (diff lines) must be related to the subject of the commit.</p>
- <p>If you change something unrelated to the subject parts of the file, because your editor reformatted automatically the code or whatever different reason, this should be excluded from the commit.</p>
- <p><em>Tip:</em> Never commit everything as-is using <tt class="docutils literal"><span class="pre"><span class="program">git</span> <span class="option">commit</span> <span class="option">-a</span></span></tt>, but review carefully your changes with <tt class="docutils literal"><span class="pre"><span class="program">git</span> <span class="option">add</span> <span class="option">-p</span></span></tt>.</p>
- </li>
- <li><p>Changes should not introduce any trailing whitespace.</p>
- <p>Always check your changes for whitespace errors using <tt class="docutils literal"><span class="pre"><span class="program">git</span> <span class="option">diff</span> <span class="option">--check</span></span></tt> or add the following <tt class="docutils literal"><span class="pre">pre-commit</span></tt> hook:</p>
- <p><pre class="listing"><span class="Comment">#!/bin/sh</span>
- <span class="program">git</span> <span class="option">diff</span> <span class="option">--check</span> <span class="option">--cached</span> <span class="Operator">||</span> <span class="program">exit</span> <span class="option">$?</span></pre></p>
- </li>
- <li>Describe your commit and use your common sense. Example commit message:<pre>Fixes #123; refs #124</pre>
- <p>indicates that issue <tt class="docutils literal"><span class="pre">#123</span></tt> is completely fixed (GitHub may automatically close it when the PR is committed), whereas issue <tt class="docutils literal"><span class="pre">#124</span></tt> is referenced (e.g.: partially fixed) and won't close the issue when committed.</p>
- </li>
- <li>PR body (not just PR title) should contain references to fixed/referenced GitHub issues, e.g.: <tt class="docutils literal"><span class="pre">fix #123</span></tt> or <tt class="docutils literal"><span class="pre">refs #123</span></tt>. This is so that you get proper cross-referencing from linked issue to the PR (GitHub won't make those links with just a PR title, and commit messages aren't always sufficient to ensure that, e.g. can't be changed after a PR is merged).</li>
- <li><p>Commits should be always be rebased against devel (so a fast-forward merge can happen)</p>
- <p>e.g.: use <tt class="docutils literal"><span class="pre"><span class="program">git</span> <span class="option">pull</span> <span class="option">--rebase</span> <span class="option">origin</span> <span class="option">devel</span></span></tt>. This is to avoid messing up git history. Exceptions should be very rare: when rebase gives too many conflicts, simply squash all commits using the script shown in <a class="reference external" href="https://github.com/nim-lang/Nim/pull/9356">https://github.com/nim-lang/Nim/pull/9356</a></p>
- </li>
- <li>Do not mix pure formatting changes (e.g. whitespace changes, nimpretty) or automated changes with other code changes: these should be in separate commits (and the merge on GitHub should not squash these into 1).</li>
- </ol>
- <h2><a class="toc-backref" id="the-cmdgit-stuff-continuous-integration-ci" href="#the-cmdgit-stuff-continuous-integration-ci">Continuous Integration (CI)</a></h2><ol class="simple"><li>Continuous Integration is by default run on every push in a PR; this clogs the CI pipeline and affects other PR's; if you don't need it (e.g. for WIP or documentation only changes), add <tt class="docutils literal"><span class="pre">[skip ci]</span></tt> to your commit message title. This convention is supported by our GitHub actions pipelines and our azure pipeline (using custom logic, which should complete in < 1mn) as well as our former other pipelines: <a class="reference external" href=" https://www.appveyor.com/docs/how-to/filtering-commits/#skip-directive-in-commit-message">Appveyor</a> and <a class="reference external" href=" https://docs.travis-ci.com/user/customizing-the-build/#skipping-a-build">Travis</a>.</li>
- <li>Consider enabling CI (azure, GitHub actions and builds.sr.ht) in your own Nim fork, and waiting for CI to be green in that fork (fixing bugs as needed) before opening your PR in the original Nim repo, to reduce CI congestion. Same applies for updates on a PR: you can test commits on a separate private branch before updating the main PR.</li>
- </ol>
- <h2><a class="toc-backref" id="the-cmdgit-stuff-debugging-ci-failures-flaky-tests-etc" href="#the-cmdgit-stuff-debugging-ci-failures-flaky-tests-etc">Debugging CI failures, flaky tests, etc</a></h2><ol class="simple"><li>First check the CI logs and search for <tt class="docutils literal"><span class="pre"><span class="Identifier">FAIL</span></span></tt> to find why CI failed; if the failure seems related to your PR, try to fix the code instead of restarting CI.</li>
- <li>If CI failure seems unrelated to your PR, it could be caused by a flaky test. File a bug for it if it isn't already reported. A PR push (or opening/closing PR) will re-trigger all CI jobs (even successful ones, which can be wasteful). Instead, request collaboration from the Nim team. The Nim team should follow these instructions to only restart the jobs that failed:<ul class="simple"><li>Azure: if on your own fork, it's possible from inside azure console (e.g. <tt class="docutils literal"><span class="pre">dev.azure.com/username/username/_build/results?buildId=1430&view=results</span></tt>) via <tt class="docutils literal"><span class="pre">rerun failed jobs</span></tt> on top. If either on you own fork or in Nim repo, it's possible from inside GitHub UI under checks tab, see <a class="reference external" href="https://github.com/timotheecour/Nim/issues/211#issuecomment-629751569">https://github.com/timotheecour/Nim/issues/211#issuecomment-629751569</a></li>
- <li>GitHub actions: under "Checks" tab, click "Re-run jobs" in the right.</li>
- <li>builds.sr.ht: create a SourceHut account so that you can restart a PR job as illustrated. builds.sr.ht also allows you to ssh to a CI machine which can help a lot for debugging issues, see docs in <a class="reference external" href="https://man.sr.ht/builds.sr.ht/build-ssh.md">https://man.sr.ht/builds.sr.ht/build-ssh.md</a> and <a class="reference external" href="https://drewdevault.com/2019/08/19/Introducing-shell-access-for-builds.html">https://drewdevault.com/2019/08/19/Introducing-shell-access-for-builds.html</a>; see <a class="reference external" href="https://man.sr.ht/tutorials/set-up-account-and-git.md">https://man.sr.ht/tutorials/set-up-account-and-git.md</a> to generate and upload ssh keys.</li>
- </ul>
- </li>
- </ol>
- <h2><a class="toc-backref" id="the-cmdgit-stuff-code-reviews" href="#the-cmdgit-stuff-code-reviews">Code reviews</a></h2><ol class="simple"><li>Whenever possible, use GitHub's new 'Suggested change' in code reviews, which saves time explaining the change or applying it; see also <a class="reference external" href="https://forum.nim-lang.org/t/4317">https://forum.nim-lang.org/t/4317</a></li>
- <li><p>When reviewing large diffs that may involve code moving around, GitHub's interface doesn't help much, as it doesn't highlight moves. Instead, you can use something like this, see visual results <a class="reference external" href=" https://github.com/nim-lang/Nim/pull/10431#issuecomment-456968196">here</a>:</p>
- <p><pre class="listing"><span class="program">git</span> <span class="option">fetch</span> <span class="option">origin</span> <span class="Identifier">pull/10431/head</span> <span class="Operator">&&</span> <span class="program">git</span> <span class="option">checkout</span> <span class="option">FETCH_HEAD</span>
- <span class="program">git</span> <span class="option">diff</span> <span class="option">--color-moved-ws=allow-indentation-change</span> <span class="option">--color-moved=blocks</span> <span class="option">HEAD^</span></pre></p>
- </li>
- <li>In addition, you can view GitHub-like diffs locally to identify what was changed within a code block using <tt class="docutils literal"><span class="pre"><span class="program">diff-highlight</span></span></tt> or <tt class="docutils literal"><span class="pre"><span class="program">diff-so-fancy</span></span></tt>, e.g.:<pre># put this in ~/.gitconfig:
- [core]
- pager = "diff-so-fancy | less -R" # or: use: `diff-highlight`</pre>
- </li>
- </ol>
- <h1><a class="toc-backref" id="documentation-style" href="#documentation-style">Documentation Style</a></h1>
- <h2><a class="toc-backref" id="documentation-style-general-guidelines" href="#documentation-style-general-guidelines">General Guidelines</a></h2><ul class="simple"><li>See also <a class="reference external" href="nep1.html">nep1</a> which should probably be merged here.</li>
- <li>Authors should document anything that is exported; documentation for private procs can be useful too (visible via <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span> <span class="option">--docInternal</span> <span class="Identifier">foo.nim</span></span></tt>).</li>
- <li>Within documentation, a period (<tt class="docutils literal"><span class="pre"><span class="Operator">.</span></span></tt>) should follow each sentence (or sentence fragment) in a comment block. The documentation may be limited to one sentence fragment, but if multiple sentences are within the documentation, each sentence after the first should be complete and in present tense.</li>
- <li>Documentation is parsed as a custom ReStructuredText (RST) with partial markdown support.</li>
- <li>In nim sources, prefer single backticks to double backticks since it's simpler and <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span></span></tt> supports it. Likewise with <tt class="docutils literal"><span class="pre">rst</span></tt> files: <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">rst2html</span></span></tt> will render those as monospace, and adding <tt class="docutils literal"><span class="pre">.. default-role:: code</span></tt> to an <tt class="docutils literal"><span class="pre">rst</span></tt> file will also make those render as monospace when rendered directly in tools such as github.</li>
- <li><p>(debatable) In nim sources, for links, prefer <tt class="docutils literal"><span class="pre">[link text](link.html)</span></tt> to <tt class="docutils literal"><span class="pre">`link text<link.html>`_</span></tt> since the syntax is simpler and markdown is more common (likewise, <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">rst2html</span></span></tt> also supports it in <tt class="docutils literal"><span class="pre">rst</span></tt> files).</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">someproc</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">s</span><span class="Punctuation">:</span> <span class="Identifier">string</span><span class="Punctuation">,</span> <span class="Identifier">foo</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment">## Use single backticks for inline code, e.g.: `s` or `someExpr(true)`.</span>
- <span class="Comment">## Use a backlash to follow with alphanumeric char: `int8`\s are great.</span></pre></p>
- </li>
- </ul>
- <h2><a class="toc-backref" id="documentation-style-moduleminuslevel-documentation" href="#documentation-style-moduleminuslevel-documentation">Module-level documentation</a></h2><p>Documentation of a module is placed at the top of the module itself. Each line of documentation begins with double hashes (<tt class="docutils literal"><span class="pre"><span class="Comment">##</span></span></tt>). Sometimes <tt class="docutils literal"><span class="pre"><span class="LongComment">##[ multiline docs containing code ]##</span></span></tt> is preferable, see <tt class="docutils literal"><span class="pre">lib/pure/times.nim</span></tt>. Code samples are encouraged, and should follow the general RST syntax:</p>
- <p><pre class="listing"><span class="Comment">## The `universe` module computes the answer to life, the universe, and everything.</span>
- <span class="Comment">##</span>
- <span class="Comment">## ```</span>
- <span class="Comment">## doAssert computeAnswerString() == 42</span>
- <span class="Comment">## ```</span></pre></p>
- <p>Within this top-level comment, you can indicate the authorship and copyright of the code, which will be featured in the produced documentation.</p>
- <p><pre class="listing"><span class="Comment">## This is the best module ever. It provides answers to everything!</span>
- <span class="Comment">##</span>
- <span class="Comment">## :Author: Steve McQueen</span>
- <span class="Comment">## :Copyright: 1965</span>
- <span class="Comment">##</span></pre></p>
- <p>Leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.).</p>
- <h2><a class="toc-backref" id="documentation-style-procs-templates-macros-converters-and-iterators" href="#documentation-style-procs-templates-macros-converters-and-iterators">Procs, Templates, Macros, Converters, and Iterators</a></h2><p>The documentation of a procedure should begin with a capital letter and should be in present tense. Variables referenced in the documentation should be surrounded by single tick marks:</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">example1</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span> <span class="Operator">=</span>
- <span class="Comment">## Prints the value of `x`.</span>
- <span class="Identifier">echo</span> <span class="Identifier">x</span></pre></p>
- <p>Whenever an example of usage would be helpful to the user, you should include one within the documentation in RST format as below.</p>
- <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">addThree</span><span class="Operator">*</span><span class="Punctuation">(</span><span class="Identifier">x</span><span class="Punctuation">,</span> <span class="Identifier">y</span><span class="Punctuation">,</span> <span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">int8</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
- <span class="Comment">## Adds three `int8` values, treating them as unsigned and</span>
- <span class="Comment">## truncating the result.</span>
- <span class="Comment">##</span>
- <span class="Comment">## ```</span>
- <span class="Comment">## # things that aren't suitable for a `runnableExamples` go in code block:</span>
- <span class="Comment">## echo execCmdEx("git pull")</span>
- <span class="Comment">## drawOnScreen()</span>
- <span class="Comment">## ```</span>
- <span class="Identifier">runnableExamples</span><span class="Punctuation">:</span>
- <span class="Comment"># `runnableExamples` is usually preferred to code blocks, when possible.</span>
- <span class="Identifier">doAssert</span> <span class="Identifier">addThree</span><span class="Punctuation">(</span><span class="DecNumber">3</span><span class="Punctuation">,</span> <span class="DecNumber">125</span><span class="Punctuation">,</span> <span class="DecNumber">6</span><span class="Punctuation">)</span> <span class="Operator">==</span> <span class="Operator">-</span><span class="DecNumber">122</span>
- <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Identifier">x</span> <span class="Operator">+%</span> <span class="Identifier">y</span> <span class="Operator">+%</span> <span class="Identifier">z</span></pre></p>
- <p>The command <tt class="docutils literal"><span class="pre"><span class="program">nim</span> <span class="option">doc</span></span></tt> will then correctly syntax highlight the Nim code within the documentation.</p>
- <h2><a class="toc-backref" id="documentation-style-types" href="#documentation-style-types">Types</a></h2><p>Exported types should also be documented. This documentation can also contain code samples, but those are better placed with the functions to which they refer.</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">NamedQueue</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Keyword">object</span> <span class="Comment">## Provides a linked data structure with names</span>
- <span class="Comment">## throughout. It is named for convenience. I'm making</span>
- <span class="Comment">## this comment long to show how you can, too.</span>
- <span class="Identifier">name</span><span class="Operator">*:</span> <span class="Identifier">string</span> <span class="Comment">## The name of the item</span>
- <span class="Identifier">val</span><span class="Operator">*:</span> <span class="Identifier">T</span> <span class="Comment">## Its value</span>
- <span class="Identifier">next</span><span class="Operator">*:</span> <span class="Keyword">ref</span> <span class="Identifier">NamedQueue</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Comment">## The next item in the queue</span></pre></p>
- <p>You have some flexibility when placing the documentation:</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Identifier">NamedQueue</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Keyword">object</span>
- <span class="Comment">## Provides a linked data structure with names</span>
- <span class="Comment">## throughout. It is named for convenience. I'm making</span>
- <span class="Comment">## this comment long to show how you can, too.</span>
- <span class="Identifier">name</span><span class="Operator">*:</span> <span class="Identifier">string</span> <span class="Comment">## The name of the item</span>
- <span class="Identifier">val</span><span class="Operator">*:</span> <span class="Identifier">T</span> <span class="Comment">## Its value</span>
- <span class="Identifier">next</span><span class="Operator">*:</span> <span class="Keyword">ref</span> <span class="Identifier">NamedQueue</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Comment">## The next item in the queue</span></pre></p>
- <p>Make sure to place the documentation beside or within the object.</p>
- <p><pre class="listing"><span class="Keyword">type</span>
- <span class="Comment">## Bad: this documentation disappears because it annotates the `type` keyword</span>
- <span class="Comment">## above, not `NamedQueue`.</span>
- <span class="Identifier">NamedQueue</span><span class="Operator">*</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Operator">=</span> <span class="Keyword">object</span>
- <span class="Identifier">name</span><span class="Operator">*:</span> <span class="Identifier">string</span> <span class="Comment">## This becomes the main documentation for the object, which</span>
- <span class="Comment">## is not what we want.</span>
- <span class="Identifier">val</span><span class="Operator">*:</span> <span class="Identifier">T</span> <span class="Comment">## Its value</span>
- <span class="Identifier">next</span><span class="Operator">*:</span> <span class="Keyword">ref</span> <span class="Identifier">NamedQueue</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span> <span class="Comment">## The next item in the queue</span></pre></p>
- <h2><a class="toc-backref" id="documentation-style-var-let-and-const" href="#documentation-style-var-let-and-const">Var, Let, and Const</a></h2><p>When declaring module-wide constants and values, documentation is encouraged. The placement of doc comments is similar to the <tt class="docutils literal"><span class="pre"><span class="Keyword">type</span></span></tt> sections.</p>
- <p><pre class="listing"><span class="Keyword">const</span>
- <span class="Identifier">X</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="DecNumber">42</span> <span class="Comment">## An awesome number.</span>
- <span class="Identifier">SpreadArray</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="Punctuation">[</span>
- <span class="Punctuation">[</span><span class="DecNumber">1</span><span class="Punctuation">,</span><span class="DecNumber">2</span><span class="Punctuation">,</span><span class="DecNumber">3</span><span class="Punctuation">]</span><span class="Punctuation">,</span>
- <span class="Punctuation">[</span><span class="DecNumber">2</span><span class="Punctuation">,</span><span class="DecNumber">3</span><span class="Punctuation">,</span><span class="DecNumber">1</span><span class="Punctuation">]</span><span class="Punctuation">,</span>
- <span class="Punctuation">[</span><span class="DecNumber">3</span><span class="Punctuation">,</span><span class="DecNumber">1</span><span class="Punctuation">,</span><span class="DecNumber">2</span><span class="Punctuation">]</span><span class="Punctuation">,</span>
- <span class="Punctuation">]</span> <span class="Comment">## Doc comment for `SpreadArray`.</span></pre></p>
- <p>Placement of comments in other areas is usually allowed, but will not become part of the documentation output and should therefore be prefaced by a single hash (<tt class="docutils literal"><span class="pre"><span class="Comment">#</span></span></tt>).</p>
- <p><pre class="listing"><span class="Keyword">const</span>
- <span class="Identifier">BadMathVals</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="Punctuation">[</span>
- <span class="FloatNumber">3.14</span><span class="Punctuation">,</span> <span class="Comment"># pi</span>
- <span class="FloatNumber">2.72</span><span class="Punctuation">,</span> <span class="Comment"># e</span>
- <span class="FloatNumber">0.58</span><span class="Punctuation">,</span> <span class="Comment"># gamma</span>
- <span class="Punctuation">]</span> <span class="Comment">## A bunch of badly rounded values.</span></pre></p>
- <p>Nim supports Unicode in comments, so the above can be replaced with the following:</p>
- <p><pre class="listing"><span class="Keyword">const</span>
- <span class="Identifier">BadMathVals</span><span class="Operator">*</span> <span class="Operator">=</span> <span class="Punctuation">[</span>
- <span class="FloatNumber">3.14</span><span class="Punctuation">,</span> <span class="Comment"># π</span>
- <span class="FloatNumber">2.72</span><span class="Punctuation">,</span> <span class="Comment"># e</span>
- <span class="FloatNumber">0.58</span><span class="Punctuation">,</span> <span class="Comment"># γ</span>
- <span class="Punctuation">]</span> <span class="Comment">## A bunch of badly rounded values (including π!).</span></pre></p>
- <h1><a class="toc-backref" id="evolving-the-stdlib" href="#evolving-the-stdlib">Evolving the stdlib</a></h1><p>As outlined in <a class="reference external" href="https://github.com/nim-lang/RFCs/issues/173">https://github.com/nim-lang/RFCs/issues/173</a> there are a couple of guidelines about what should go into the stdlib, what should be added and what eventually should be removed.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-what-the-compiler-itself-needs-must-be-part-of-the-stdlib" href="#evolving-the-stdlib-what-the-compiler-itself-needs-must-be-part-of-the-stdlib">What the compiler itself needs must be part of the stdlib</a></h2><p>Maybe in the future the compiler itself can depend on Nimble packages but for the time being, we strive to have zero dependencies in the compiler as the compiler is the root of the bootstrapping process and is also used to build Nimble.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-vocabulary-types-must-be-part-of-the-stdlib" href="#evolving-the-stdlib-vocabulary-types-must-be-part-of-the-stdlib">Vocabulary types must be part of the stdlib</a></h2><p>These are types most packages need to agree on for better interoperability, for example <tt class="docutils literal"><span class="pre"><span class="Identifier">Option</span><span class="Punctuation">[</span><span class="Identifier">T</span><span class="Punctuation">]</span></span></tt>. This rule also covers the existing collections like <tt class="docutils literal"><span class="pre"><span class="Identifier">Table</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">CountTable</span></span></tt> etc. "Sorted" containers based on a tree-like data structure are still missing and should be added.</p>
- <p>Time handling, especially the <tt class="docutils literal"><span class="pre"><span class="Identifier">Time</span></span></tt> type are also covered by this rule.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-existing-battleminustested-modules-stay" href="#evolving-the-stdlib-existing-battleminustested-modules-stay">Existing, battle-tested modules stay</a></h2><p>Reason: There is no benefit in moving them around just to fulfill some design fashion as in "Nim's core MUST BE SMALL". If you don't like an existing module, don't import it. If a compilation target (e.g. JS) cannot support a module, document this limitation.</p>
- <p>This covers modules like <tt class="docutils literal"><span class="pre"><span class="Identifier">os</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">osproc</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">strscans</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">strutils</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">strformat</span></span></tt>, etc.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-syntactic-helpers-can-start-as-experimental-stdlib-modules" href="#evolving-the-stdlib-syntactic-helpers-can-start-as-experimental-stdlib-modules">Syntactic helpers can start as experimental stdlib modules</a></h2><p>Reason: Generally speaking as external dependencies they are not exposed to enough users so that we can see if the shortcuts provide enough benefit or not. Many programmers avoid external dependencies, especially for "tiny syntactic improvements". However, this is only true for really good syntactic improvements that have the potential to clean up other parts of the Nim library substantially. If in doubt, new stdlib modules should start as external, successful Nimble packages.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-other-new-stdlib-modules-do-not-start-as-stdlib-modules" href="#evolving-the-stdlib-other-new-stdlib-modules-do-not-start-as-stdlib-modules">Other new stdlib modules do not start as stdlib modules</a></h2><p>As we strive for higher quality everywhere, it's easier to adopt existing, battle-tested modules eventually rather than creating modules from scratch.</p>
- <h2><a class="toc-backref" id="evolving-the-stdlib-little-additions-are-acceptable" href="#evolving-the-stdlib-little-additions-are-acceptable">Little additions are acceptable</a></h2><p>As long as they are documented and tested well, adding little helpers to existing modules is acceptable. For two reasons:</p>
- <ol class="simple"><li>It makes Nim easier to learn and use in the long run. ("Why does sequtils lack a <tt class="docutils literal"><span class="pre"><span class="Identifier">countIt</span></span></tt>? Because version 1.0 happens to have lacked it? Silly...")</li>
- <li>To encourage contributions. Contributors often start with PRs that add simple things, then they stay and also fix bugs. Nim is an open source project and lives from people's contributions and involvement. Newly introduced issues have to be balanced against motivating new people. We know where to find perfectly designed pieces of software that have no bugs -- these are the systems that nobody uses.</li>
- </ol>
- <h2><a class="toc-backref" id="evolving-the-stdlib-conventions" href="#evolving-the-stdlib-conventions">Conventions</a></h2><ol class="simple"><li>New stdlib modules should go under <tt class="docutils literal"><span class="pre">Nim/lib/std/</span></tt>. The rationale is to require users to import via <tt class="docutils literal"><span class="pre"><span class="Keyword">import</span> <span class="Identifier">std</span><span class="Operator">/</span><span class="Identifier">foo</span></span></tt> instead of <tt class="docutils literal"><span class="pre"><span class="Keyword">import</span> <span class="Identifier">foo</span></span></tt>, which would cause potential conflicts with nimble packages. Note that this still applies for new modules in existing logical directories, e.g.: use <tt class="docutils literal"><span class="pre">lib/std/collections/foo.nim</span></tt>, not <tt class="docutils literal"><span class="pre">lib/pure/collections/foo.nim</span></tt>.</li>
- <li>New module names should prefer plural form whenever possible, e.g.: <tt class="docutils literal"><span class="pre">std/sums.nim</span></tt> instead of <tt class="docutils literal"><span class="pre">std/sum.nim</span></tt>. In particular, this reduces chances of conflicts between module name and the symbols it defines. Furthermore, module names should use <tt class="docutils literal"><span class="pre"><span class="Identifier">snake_case</span></span></tt> and not use capital letters, which cause issues when going from an OS without case sensitivity to an OS with it.</li>
- </ol>
- <h1><a class="toc-backref" id="breaking-changes" href="#breaking-changes">Breaking Changes</a></h1><p>Introducing breaking changes, no matter how well-intentioned, creates long-term problems for the community, in particular those looking to promote reusable Nim code in libraries: In the Nim distribution, critical security and bugfixes, language changes and community improvements are bundled in a single distribution - it is difficult to make partial upgrades with only benign changes. When one library depends on a legacy behavior, it can no longer be used together with another library that does not, breaking all downstream applications - the standard library is unique in that it sits at the root of <strong>all</strong> dependency trees.</p>
- <p>There is a big difference between compile-time breaking changes and run-time breaking changes.</p>
- <h2><a class="toc-backref" id="breaking-changes-runminustime-breaking-changes" href="#breaking-changes-runminustime-breaking-changes">Run-time breaking changes</a></h2><p>Run-time breaking changes are to be avoided at almost all costs: Nim is used for mission critical applications which depend on behaviours that are not covered by the test suite. As such, it's important that changes to the <em>stable</em> parts of the standard library are made avoiding changing the existing behaviors, even when the test suite continues to pass.</p>
- <p>Examples of run-time breaking changes:</p>
- <ul class="simple"><li>Raising exceptions of a new type, compared to what's currently being raised.</li>
- <li>Adding unconstrained or poorly constrained generic procs or macros ("hash now works for all <tt class="docutils literal"><span class="pre"><span class="Keyword">ref</span> <span class="Identifier">T</span></span></tt>"): This may cause code to behave differently depending only on which modules are imported - common examples include <tt class="docutils literal"><span class="pre"><span class="Operator">==</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">hash</span></span></tt>.</li>
- <li>Changing behavior of existing functions like:<ul class="simple"><li>"Nim's path handling procs like <tt class="docutils literal"><span class="pre"><span class="Identifier">getXDir</span></span></tt> now consistently lack the trailing slash"</li>
- <li>"Nim's strformat implementation is now more consistent with Python"</li>
- </ul>
- </li>
- </ul>
- <p>Instead, write new code that explicitly announces the feature you think we announced but didn't. For example, <tt class="docutils literal"><span class="pre"><span class="Identifier">strformat</span></span></tt> does not say "it's compatible with Python", it says "inspired by Python's f-strings". This new code can be submitted to the stdlib and the old code can be deprecated or published as a Nimble package.</p>
- <p>Sometimes, a run-time breaking change is most desirable: For example, a string representation of a floating point number that "roundtrips" is much better than a string representation that doesn't. These run-time breaking changes must start in the state "opt-in" via a new <tt class="docutils literal"><span class="pre"><span class="Operator">-</span><span class="Identifier">d</span><span class="Punctuation">:</span><span class="Identifier">nimPreviewX</span></span></tt> or command line flag and then should become the new default later, in follow-up versions. This way users can track regressions more easily. ("git bisect" is not an acceptable alternative, that's for Nim compiler developers, not for Nim users.)</p>
- <p>Above all else, additive approaches that don't change existing behaviors should be preferred.</p>
- <h2><a class="toc-backref" id="breaking-changes-compileminustime-breaking-changes" href="#breaking-changes-compileminustime-breaking-changes">Compile-time breaking changes</a></h2><p>Compile-time breaking changes are usually easier to handle, but for large code bases they can also involve a large amount of work and can hinder the adoption of a new Nim release. Additive approaches are to be preferred here as well.</p>
- <p>Examples of compile-time breaking changes include (but are not limited to):</p>
- <ul class="simple"><li>Renaming functions and modules, or moving things. Instead of a direct rename, deprecate the old name and introduce a new one.</li>
- <li>Renaming the parameter names: Thanks to Nim's "named parameter" calling syntax like <tt class="docutils literal"><span class="pre"><span class="Identifier">f</span><span class="Punctuation">(</span><span class="Identifier">x</span> <span class="Operator">=</span> <span class="DecNumber">0</span><span class="Punctuation">,</span> <span class="Identifier">y</span> <span class="Operator">=</span> <span class="DecNumber">1</span><span class="Punctuation">)</span></span></tt> this is a breaking change. Instead, live with the existing parameter names.</li>
- <li>Adding an enum value to an existing enum. Nim's exhaustive case statements stop compiling after such a change. Instead, consider to introduce new <tt class="docutils literal"><span class="pre"><span class="Identifier">bool</span></span></tt> fields/parameters. This can be impractical though, so we use good judgement and our list of "important packages" to see if it doesn't break too much code out there in practice.</li>
- <li>Adding a new proc to an existing stdlib module. However, for aesthetic reasons this is often preferred over introducing a new module with just a single proc inside. We use good judgement and our list of "important packages" to see if it doesn't break too much code out there in practice. The new procs need to be annotated with a <tt class="docutils literal"><span class="pre"><span class="Operator">.</span><span class="Identifier">since</span></span></tt> annotation.</li>
- </ul>
- <h2><a class="toc-backref" id="breaking-changes-compilerslashlanguage-spec-bugfixes" href="#breaking-changes-compilerslashlanguage-spec-bugfixes">Compiler/language spec bugfixes</a></h2><p>This can even be applied to compiler "bugfixes": If the compiler should have been "pickier" in its handling of <tt class="docutils literal"><span class="pre"><span class="Identifier">typedesc</span></span></tt>, instead of "fixing typedesc handling bugs", consider the following solution:</p>
- <ul class="simple"><li>Spec out how <tt class="docutils literal"><span class="pre"><span class="Identifier">typedesc</span></span></tt> should really work and also spec out the cases where it should not be allowed!</li>
- <li>Deprecate <tt class="docutils literal"><span class="pre"><span class="Identifier">typedesc</span></span></tt> and name the new metatype something new like <tt class="docutils literal"><span class="pre"><span class="Identifier">typeArg</span></span></tt>.</li>
- <li>Implement the spec.</li>
- </ul>
- <h2><a class="toc-backref" id="breaking-changes-nonminusbreaking-changes" href="#breaking-changes-nonminusbreaking-changes">Non-breaking changes</a></h2><p>Examples of changes that are considered non-breaking (or acceptable breaking changes) include:</p>
- <ul class="simple"><li>Creating a new module.</li>
- <li>Adding an overload to an already overloaded proc.</li>
- <li>Adding new default parameters to an existing proc. It is assumed that you do not use Nim's stdlib procs's addresses (that you don't use them as first class entities).</li>
- <li>Changing the calling convention from <tt class="docutils literal"><span class="pre"><span class="Identifier">nimcall</span></span></tt> to <tt class="docutils literal"><span class="pre"><span class="Identifier">inline</span></span></tt> (but first RFC <a class="reference external" href="https://github.com/nim-lang/RFCs/issues/396">https://github.com/nim-lang/RFCs/issues/396</a> needs to be implemented).</li>
- <li>Changing the behavior from "crashing" into some other, well documented result (including raising a Defect, but not raising an exception that does not inherit from Defect).</li>
- <li>Adding new fields to an existing object.</li>
- </ul>
- <p>Nim's introspection facilities imply that strictly speaking almost every addition can break somebody's code. It is impractical to care about these cases, a change that only affects introspection is not considered to be a breaking change. </p>
- </p>
-
- </div>
- </div>
- <div class="twelve-columns footer">
- <span class="nim-sprite"></span>
- <br>
- <small style="color: var(--hint);">Made with Nim. Generated: 2025-02-03 14:56:32 UTC</small>
- </div>
- </div>
- </div>
- <script defer data-domain="nim-lang.org" src="https://plausible.io/js/plausible.js"></script>
-
- </body>
- </html>
|