intern.html 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <!-- This file is generated by Nim. -->
  4. <html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en" data-theme="auto">
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  7. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8. <title>Internals of the Nim Compiler</title>
  9. <!-- Google fonts -->
  10. <link href='https://fonts.googleapis.com/css?family=Lato:400,600,900' rel='stylesheet' type='text/css'/>
  11. <link href='https://fonts.googleapis.com/css?family=Source+Code+Pro:400,500,600' rel='stylesheet' type='text/css'/>
  12. <!-- Favicon -->
  13. <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=="/>
  14. <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=">
  15. <!-- CSS -->
  16. <link rel="stylesheet" type="text/css" href="nimdoc.out.css?v=2.3.1">
  17. <!-- JS -->
  18. <script type="text/javascript" src="dochack.js?v=2.3.1"></script>
  19. </head>
  20. <body>
  21. <div class="document" id="documentId">
  22. <div class="container">
  23. <h1 class="title">Internals of the Nim Compiler</h1>
  24. <div class="row">
  25. <div class="three columns">
  26. <div class="theme-select-wrapper">
  27. <label for="theme-select">Theme:&nbsp;</label>
  28. <select id="theme-select" onchange="setTheme(this.value)">
  29. <option value="auto">🌗 Match OS</option>
  30. <option value="dark">🌑 Dark</option>
  31. <option value="light">🌕 Light</option>
  32. </select>
  33. </div>
  34. <div id="global-links">
  35. <ul class="simple-boot">
  36. <li><a href="manual.html">Manual</a></li>
  37. <li><a href="lib.html">Standard library</a></li>
  38. <li> <a id="indexLink" href="theindex.html">Index</a></li>
  39. <li><a href="compiler/theindex.html">Compiler docs</a></li>
  40. <li><a href="https://nim-lang.github.io/fusion/theindex.html">Fusion docs</a></li>
  41. <li><a href="https://nim-lang.github.io/Nim/">devel</a>, <a href="https://nim-lang.org/documentation.html">stable</a></li>
  42. </ul>
  43. </div>
  44. <div id="searchInputDiv">
  45. Search: <input type="search" id="searchInput"
  46. oninput="search()" />
  47. </div>
  48. <div class="search-groupby">
  49. Group by:
  50. <select onchange="groupBy(this.value)">
  51. <option value="section">Section</option>
  52. <option value="type">Type</option>
  53. </select>
  54. </div>
  55. <ul class="simple simple-toc" id="toc-list">
  56. <li><a class="reference" id="directory-structure_toc" href="#directory-structure">Directory structure</a></li>
  57. <li><a class="reference" id="bootstrapping-the-compiler_toc" href="#bootstrapping-the-compiler">Bootstrapping the compiler</a></li>
  58. <ul class="simple"><li><a class="reference" id="bootstrapping-the-compiler-reproducible-builds_toc" href="#bootstrapping-the-compiler-reproducible-builds">Reproducible builds</a></li>
  59. </ul><li><a class="reference" id="debugging-the-compiler_toc" href="#debugging-the-compiler">Debugging the compiler</a></li>
  60. <ul class="simple"><li><a class="reference" id="debugging-the-compiler-bisecting-for-regressions_toc" href="#debugging-the-compiler-bisecting-for-regressions">Bisecting for regressions</a></li>
  61. <li><a class="reference" id="debugging-the-compiler-building-an-instrumented-compiler_toc" href="#debugging-the-compiler-building-an-instrumented-compiler">Building an instrumented compiler</a></li>
  62. <li><a class="reference" id="debugging-the-compiler-debug-logging_toc" href="#debugging-the-compiler-debug-logging">Debug logging</a></li>
  63. <li><a class="reference" id="debugging-the-compiler-native-debugging_toc" href="#debugging-the-compiler-native-debugging">Native debugging</a></li>
  64. </ul><li><a class="reference" id="the-compiler-s-architecture_toc" href="#the-compiler-s-architecture">The compiler's architecture</a></li>
  65. <ul class="simple"><li><a class="reference" id="the-compiler-s-architecture-short-description-of-nim-s-modules_toc" href="#the-compiler-s-architecture-short-description-of-nim-s-modules">Short description of Nim's modules</a></li>
  66. <li><a class="reference" id="the-compiler-s-architecture-the-syntax-tree_toc" href="#the-compiler-s-architecture-the-syntax-tree">The syntax tree</a></li>
  67. </ul><li><a class="reference" id="runtimes_toc" href="#runtimes">Runtimes</a></li>
  68. <li><a class="reference" id="coding-guidelines_toc" href="#coding-guidelines">Coding Guidelines</a></li>
  69. <li><a class="reference" id="porting-to-new-platforms_toc" href="#porting-to-new-platforms">Porting to new platforms</a></li>
  70. <li><a class="reference" id="runtime-type-information_toc" href="#runtime-type-information">Runtime type information</a></li>
  71. <li><a class="reference" id="magics-and-compilerprocs_toc" href="#magics-and-compilerprocs">Magics and compilerProcs</a></li>
  72. <li><a class="reference" id="code-generation-for-closures_toc" href="#code-generation-for-closures">Code generation for closures</a></li>
  73. <ul class="simple"><li><a class="reference" id="code-generation-for-closures-design_toc" href="#code-generation-for-closures-design">Design</a></li>
  74. <li><a class="reference" id="code-generation-for-closures-accumulator_toc" href="#code-generation-for-closures-accumulator">Accumulator</a></li>
  75. <li><a class="reference" id="code-generation-for-closures-internals_toc" href="#code-generation-for-closures-internals">Internals</a></li>
  76. </ul><li><a class="reference" id="notes-on-type-and-ast-representation_toc" href="#notes-on-type-and-ast-representation">Notes on type and AST representation</a></li>
  77. <ul class="simple"><li><a class="reference" id="notes-on-type-and-ast-representation-integer-literals_toc" href="#notes-on-type-and-ast-representation-integer-literals">Integer literals</a></li>
  78. </ul>
  79. </ul>
  80. </div>
  81. <div class="nine columns" id="content">
  82. <a href="https://github.com/nim-lang/Nim/tree/devel/doc/intern.md#L1" class="link-seesrc" target="_blank">Source</a>&nbsp;&nbsp;
  83. <a href="https://github.com/nim-lang/Nim/edit/devel/doc/intern.md#L1" class="link-seesrc" target="_blank" >Edit</a>&nbsp;&nbsp;
  84. <div id="tocRoot"></div>
  85. <p class="module-desc"><table class="docinfo" frame="void" rules="none"><col class="docinfo-name" /><col class="docinfo-content" /><tbody valign="top"><tr><th class="docinfo-name">Author:</th><td>Andreas Rumpf</td></tr>
  86. <tr><th class="docinfo-name">Version:</th><td>2.3.1</td></tr>
  87. </tbody></table><blockquote class="markdown-quote"><p>&quot;Abstraction is layering ignorance on top of reality.&quot; -- Richard Gabriel</p></blockquote>
  88. <h1><a class="toc-backref" id="directory-structure" href="#directory-structure">Directory structure</a></h1><p>The Nim project's directory structure is:</p>
  89. <table border="1" class="docutils"><tr><th>Path</th><th>Purpose</th></tr>
  90. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">bin</span></span></tt></td><td>generated binary files</td></tr>
  91. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">build</span></span></tt></td><td>generated C code for the installation</td></tr>
  92. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span></span></tt></td><td>the Nim compiler itself; note that this code has been translated from a bootstrapping version written in Pascal, so the code is <strong>not</strong> a poster child of good Nim code</td></tr>
  93. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">config</span></span></tt></td><td>configuration files for Nim</td></tr>
  94. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">dist</span></span></tt></td><td>additional packages for the distribution</td></tr>
  95. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">doc</span></span></tt></td><td>the documentation; it is a bunch of reStructuredText files</td></tr>
  96. <tr><td><tt class="docutils literal"><span class="pre"><span class="Identifier">lib</span></span></tt></td><td>the Nim library</td></tr>
  97. </table>
  98. <h1><a class="toc-backref" id="bootstrapping-the-compiler" href="#bootstrapping-the-compiler">Bootstrapping the compiler</a></h1><p><strong>Note</strong>: Add <tt class="docutils literal"><span class="pre">.</span></tt> to your PATH so that <tt class="docutils literal"><span class="pre"><span class="program">koch</span></span></tt> can be used without the <tt class="docutils literal"><span class="pre">./</span></tt>.</p>
  99. <p>Compiling the compiler is a simple matter of running:</p>
  100. <p><pre class="listing"><span class="program">nim</span> <span class="option">c</span> <span class="Identifier">koch.nim</span>
  101. <span class="program">koch</span> <span class="option">boot</span> <span class="option">-d:release</span></pre></p>
  102. <p>For a debug version use:</p>
  103. <p><pre class="listing"><span class="program">nim</span> <span class="option">c</span> <span class="Identifier">koch.nim</span>
  104. <span class="program">koch</span> <span class="option">boot</span></pre></p>
  105. <p>And for a debug version compatible with GDB:</p>
  106. <p><pre class="listing"><span class="program">nim</span> <span class="option">c</span> <span class="Identifier">koch.nim</span>
  107. <span class="program">koch</span> <span class="option">boot</span> <span class="option">--debuginfo</span> <span class="option">--linedir:on</span></pre></p>
  108. <p>The <tt class="docutils literal"><span class="pre"><span class="program">koch</span></span></tt> program is Nim's maintenance script. It is a replacement for make and shell scripting with the advantage that it is much more portable. More information about its options can be found in the <a class="reference external" href="koch.html">koch</a> documentation.</p>
  109. <h2><a class="toc-backref" id="bootstrapping-the-compiler-reproducible-builds" href="#bootstrapping-the-compiler-reproducible-builds">Reproducible builds</a></h2><p>Set the compilation timestamp with the <tt class="docutils literal"><span class="pre"><span class="Identifier">SOURCE_DATE_EPOCH</span></span></tt> environment variable.</p>
  110. <p><pre class="listing"><span class="program">export</span> <span class="option">SOURCE_DATE_EPOCH=$</span><span class="Operator">(</span><span class="program">git</span> <span class="option">log</span> <span class="option">-n</span> <span class="option">1</span> <span class="option">--format=%at</span><span class="Operator">)</span>
  111. <span class="program">koch</span> <span class="option">boot</span> <span class="Comment"># or `./build_all.sh`</span></pre></p>
  112. <h1><a class="toc-backref" id="debugging-the-compiler" href="#debugging-the-compiler">Debugging the compiler</a></h1>
  113. <h2><a class="toc-backref" id="debugging-the-compiler-bisecting-for-regressions" href="#debugging-the-compiler-bisecting-for-regressions">Bisecting for regressions</a></h2><p>There are often times when there is a bug that is caused by a regression in the compiler or stdlib. Bisecting the Nim repo commits is a useful tool to identify what commit introduced the regression.</p>
  114. <p>Even if it's not known whether a bug is caused by a regression, bisection can reduce debugging time by ruling it out. If the bug is found to be a regression, then you focus on the changes introduced by that one specific commit.</p>
  115. <p><tt class="docutils literal"><span class="pre"><span class="program">koch</span> <span class="option">temp</span></span></tt> returns 125 as the exit code in case the compiler compilation fails. This exit code tells <tt class="docutils literal"><span class="pre"><span class="program">git</span> <span class="option">bisect</span></span></tt> to skip the current commit:</p>
  116. <p><pre class="listing"><span class="program">git</span> <span class="option">bisect</span> <span class="option">start</span> <span class="option">bad-commit</span> <span class="option">good-commit</span>
  117. <span class="program">git</span> <span class="option">bisect</span> <span class="option">run</span> <span class="Identifier">./koch</span> <span class="option">temp</span> <span class="option">-r</span> <span class="option">c</span> <span class="Identifier">test-source.nim</span></pre></p>
  118. <p>You can also bisect using custom options to build the compiler, for example if you don't need a debug version of the compiler (which runs slower), you can replace <tt class="docutils literal"><span class="pre"><span class="program">./koch</span> <span class="option">temp</span></span></tt> by explicit compilation command, see <a class="reference internal" href="#bootstrapping-the-compiler">Bootstrapping the compiler</a>.</p>
  119. <p>See also:</p>
  120. <ul class="simple"><li>Crossplatform C/Cpp/Valgrind/JS Bisect in GitHub: <a class="reference external" href="https://github.com/juancarlospaco/nimrun-action#examples">https://github.com/juancarlospaco/nimrun-action#examples</a></li>
  121. </ul>
  122. <h2><a class="toc-backref" id="debugging-the-compiler-building-an-instrumented-compiler" href="#debugging-the-compiler-building-an-instrumented-compiler">Building an instrumented compiler</a></h2><p>Considering that a useful method of debugging the compiler is inserting debug logging, or changing code and then observing the outcome of a testcase, it is fastest to build a compiler that is instrumented for debugging from an existing release build. <tt class="docutils literal"><span class="pre"><span class="program">koch</span> <span class="option">temp</span></span></tt> provides a convenient method of doing just that.</p>
  123. <p>By default, running <tt class="docutils literal"><span class="pre"><span class="program">koch</span> <span class="option">temp</span></span></tt> will build a lean version of the compiler with <tt class="docutils literal"><span class="pre option">-d:debug</span></tt> enabled. The compiler is written to <tt class="docutils literal"><span class="pre"><span class="Identifier">bin</span><span class="Operator">/</span><span class="Identifier">nim_temp</span></span></tt> by default. A lean version of the compiler lacks JS and documentation generation.</p>
  124. <p><tt class="docutils literal"><span class="pre"><span class="Identifier">bin</span><span class="Operator">/</span><span class="Identifier">nim_temp</span></span></tt> can be directly used to run testcases, or used with testament with <tt class="docutils literal"><span class="pre"><span class="program">testament</span> <span class="Identifier">--nim:bin/nim_temp</span> <span class="option">r</span> <span class="Identifier">tests/category/tsometest</span></span></tt>.</p>
  125. <p><tt class="docutils literal"><span class="pre"><span class="program">koch</span> <span class="option">temp</span></span></tt> will build the temporary compiler with the <tt class="docutils literal"><span class="pre option">-d:debug</span></tt> enabled. Here are compiler options that are of interest when debugging:</p>
  126. <ul class="simple"><li><tt class="docutils literal"><span class="pre option">-d:debug</span></tt>: enables <tt class="docutils literal"><span class="pre"><span class="Identifier">assert</span></span></tt> statements and stacktraces and all runtime checks</li>
  127. <li><tt class="docutils literal"><span class="pre option">--opt:speed</span></tt>: build with optimizations enabled</li>
  128. <li><tt class="docutils literal"><span class="pre option">--debugger:native</span></tt>: enables <tt class="docutils literal"><span class="pre option">--debuginfo --lineDir:on</span></tt> for using a native debugger like GDB, LLDB or CDB</li>
  129. <li><tt class="docutils literal"><span class="pre option">-d:nimDebug</span></tt> cause calls to <tt class="docutils literal"><span class="pre"><span class="Identifier">quit</span></span></tt> to raise an assertion exception</li>
  130. <li><tt class="docutils literal"><span class="pre option">-d:nimDebugUtils</span></tt>: enables various debugging utilities; see <tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">debugutils</span></span></tt></li>
  131. <li><tt class="docutils literal"><span class="pre option">-d:stacktraceMsgs -d:nimCompilerStacktraceHints</span></tt>: adds some additional stacktrace hints; see <a class="reference external" href="https://github.com/nim-lang/Nim/pull/13351">https://github.com/nim-lang/Nim/pull/13351</a></li>
  132. <li><tt class="docutils literal"><span class="pre option">-u:leanCompiler</span></tt>: enable JS and doc generation</li>
  133. </ul>
  134. <p>Another method to build and run the compiler is directly through <tt class="docutils literal"><span class="pre"><span class="program">koch</span></span></tt>:</p>
  135. <p><pre class="listing"><span class="program">koch</span> <span class="option">temp</span> <span class="option">[options]</span> <span class="option">c</span> <span class="Identifier">test.nim</span>
  136. <span class="Comment"># (will build with js support)</span>
  137. <span class="program">koch</span> <span class="option">temp</span> <span class="option">[options]</span> <span class="option">js</span> <span class="Identifier">test.nim</span>
  138. <span class="Comment"># (will build with doc support)</span>
  139. <span class="program">koch</span> <span class="option">temp</span> <span class="option">[options]</span> <span class="option">doc</span> <span class="Identifier">test.nim</span></pre></p>
  140. <h2><a class="toc-backref" id="debugging-the-compiler-debug-logging" href="#debugging-the-compiler-debug-logging">Debug logging</a></h2><p>&quot;Printf debugging&quot; is still the most appropriate way to debug many problems arising in compiler development. The typical usage of breakpoints to debug the code is often less practical, because almost all code paths in the compiler will be executed hundreds of times before a particular section of the tested program is reached where the newly developed code must be activated.</p>
  141. <p>To work around this problem, you'll typically introduce an if statement in the compiler code detecting more precisely the conditions where the tested feature is being used. One very common way to achieve this is to use the <tt class="docutils literal"><span class="pre"><span class="Identifier">mdbg</span></span></tt> condition, which will be true only in contexts, processing expressions and statements from the currently compiled main module:</p>
  142. <p><pre class="listing"><span class="Comment"># inside some compiler module</span>
  143. <span class="Keyword">if</span> <span class="Identifier">mdbg</span><span class="Punctuation">:</span>
  144. <span class="Identifier">debug</span> <span class="Identifier">someAstNode</span></pre></p>
  145. <p>Using the <tt class="docutils literal"><span class="pre"><span class="Identifier">isCompilerDebug</span></span></tt> condition along with inserting some statements into the testcase provides more granular logging:</p>
  146. <p><pre class="listing"><span class="Comment"># compilermodule.nim</span>
  147. <span class="Keyword">if</span> <span class="Identifier">isCompilerDebug</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
  148. <span class="Identifier">debug</span> <span class="Identifier">someAstNode</span>
  149. <span class="Comment"># testcase.nim</span>
  150. <span class="Keyword">proc</span> <span class="Identifier">main</span> <span class="Operator">=</span>
  151. <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">define</span><span class="Punctuation">(</span><span class="Identifier">nimCompilerDebug</span><span class="Punctuation">)</span><span class="Operator">.</span><span class="Punctuation">}</span>
  152. <span class="Keyword">let</span> <span class="Identifier">a</span> <span class="Operator">=</span> <span class="FloatNumber">2.5</span> <span class="Operator">*</span> <span class="DecNumber">3</span>
  153. <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">undef</span><span class="Punctuation">(</span><span class="Identifier">nimCompilerDebug</span><span class="Punctuation">)</span><span class="Operator">.</span><span class="Punctuation">}</span></pre></p>
  154. <p>Logging can also be scoped to a specific filename as well. This will of course match against every module with that name.</p>
  155. <p><pre class="listing"><span class="Keyword">if</span> <span class="Punctuation">`</span><span class="Operator">??</span><span class="Punctuation">`</span><span class="Punctuation">(</span><span class="Identifier">conf</span><span class="Punctuation">,</span> <span class="Identifier">n</span><span class="Operator">.</span><span class="Identifier">info</span><span class="Punctuation">,</span> <span class="StringLit">&quot;module.nim&quot;</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
  156. <span class="Identifier">debug</span><span class="Punctuation">(</span><span class="Identifier">n</span><span class="Punctuation">)</span></pre></p>
  157. <p>The above examples also makes use of the <tt class="docutils literal"><span class="pre"><span class="Identifier">debug</span></span></tt> proc, which is able to print a human-readable form of an arbitrary AST tree. Other common ways to print information about the internal compiler types include:</p>
  158. <p><pre class="listing"><span class="Comment"># pretty print PNode</span>
  159. <span class="Comment"># pretty prints the Nim ast</span>
  160. <span class="Identifier">echo</span> <span class="Identifier">renderTree</span><span class="Punctuation">(</span><span class="Identifier">someNode</span><span class="Punctuation">)</span>
  161. <span class="Comment"># pretty prints the Nim ast, but annotates symbol IDs</span>
  162. <span class="Identifier">echo</span> <span class="Identifier">renderTree</span><span class="Punctuation">(</span><span class="Identifier">someNode</span><span class="Punctuation">,</span> <span class="Punctuation">{</span><span class="Identifier">renderIds</span><span class="Punctuation">}</span><span class="Punctuation">)</span>
  163. <span class="Comment"># pretty print ast as JSON</span>
  164. <span class="Identifier">debug</span><span class="Punctuation">(</span><span class="Identifier">someNode</span><span class="Punctuation">)</span>
  165. <span class="Comment"># print as YAML</span>
  166. <span class="Identifier">echo</span> <span class="Identifier">treeToYaml</span><span class="Punctuation">(</span><span class="Identifier">config</span><span class="Punctuation">,</span> <span class="Identifier">someNode</span><span class="Punctuation">)</span>
  167. <span class="Comment"># pretty print PType</span>
  168. <span class="Comment"># print type name</span>
  169. <span class="Identifier">echo</span> <span class="Identifier">typeToString</span><span class="Punctuation">(</span><span class="Identifier">someType</span><span class="Punctuation">)</span>
  170. <span class="Comment"># pretty print as JSON</span>
  171. <span class="Identifier">debug</span><span class="Punctuation">(</span><span class="Identifier">someType</span><span class="Punctuation">)</span>
  172. <span class="Comment"># print as YAML</span>
  173. <span class="Identifier">echo</span> <span class="Identifier">typeToYaml</span><span class="Punctuation">(</span><span class="Identifier">config</span><span class="Punctuation">,</span> <span class="Identifier">someType</span><span class="Punctuation">)</span>
  174. <span class="Comment"># pretty print PSym</span>
  175. <span class="Comment"># print the symbol's name</span>
  176. <span class="Identifier">echo</span> <span class="Identifier">symbol</span><span class="Operator">.</span><span class="Identifier">name</span><span class="Operator">.</span><span class="Identifier">s</span>
  177. <span class="Comment"># pretty print as JSON</span>
  178. <span class="Identifier">debug</span><span class="Punctuation">(</span><span class="Identifier">symbol</span><span class="Punctuation">)</span>
  179. <span class="Comment"># print as YAML</span>
  180. <span class="Identifier">echo</span> <span class="Identifier">symToYaml</span><span class="Punctuation">(</span><span class="Identifier">config</span><span class="Punctuation">,</span> <span class="Identifier">symbol</span><span class="Punctuation">)</span>
  181. <span class="Comment"># pretty print TLineInfo</span>
  182. <span class="Identifier">lineInfoToStr</span><span class="Punctuation">(</span><span class="Identifier">lineInfo</span><span class="Punctuation">)</span>
  183. <span class="Comment"># print the structure of any type</span>
  184. <span class="Identifier">repr</span><span class="Punctuation">(</span><span class="Identifier">someVar</span><span class="Punctuation">)</span></pre></p>
  185. <p>Here are some other helpful utilities:</p>
  186. <p><pre class="listing"><span class="Comment"># how did execution reach this location?</span>
  187. <span class="Identifier">writeStackTrace</span><span class="Punctuation">(</span><span class="Punctuation">)</span></pre></p>
  188. <p>These procs may not already be imported by the module you're editing. You can import them directly for debugging:</p>
  189. <p><pre class="listing"><span class="Keyword">from</span> <span class="Identifier">astalgo</span> <span class="Keyword">import</span> <span class="Identifier">debug</span>
  190. <span class="Keyword">from</span> <span class="Identifier">types</span> <span class="Keyword">import</span> <span class="Identifier">typeToString</span>
  191. <span class="Keyword">from</span> <span class="Identifier">renderer</span> <span class="Keyword">import</span> <span class="Identifier">renderTree</span>
  192. <span class="Keyword">from</span> <span class="Identifier">msgs</span> <span class="Keyword">import</span> <span class="Punctuation">`</span><span class="Operator">??</span><span class="Punctuation">`</span></pre></p>
  193. <h2><a class="toc-backref" id="debugging-the-compiler-native-debugging" href="#debugging-the-compiler-native-debugging">Native debugging</a></h2><p>Stepping through the compiler with a native debugger is a very powerful tool to both learn and debug it. However, there is still the need to constrain when breakpoints are triggered. The same methods as in <a class="reference internal" href="#debugging-the-compiler-debug-logging">Debug logging</a> can be applied here when combined with calls to the debug helpers <tt class="docutils literal"><span class="pre"><span class="Identifier">enteringDebugSection</span><span class="Punctuation">(</span><span class="Punctuation">)</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">exitingDebugSection</span><span class="Punctuation">(</span><span class="Punctuation">)</span></span></tt>.</p>
  194. <ol class="simple"><li>Compile the temp compiler with <tt class="docutils literal"><span class="pre option">--debugger:native -d:nimDebugUtils</span></tt></li>
  195. <li>Set your desired breakpoints or watchpoints.</li>
  196. <li>Configure your debugger:<ul class="simple"><li>GDB: execute <tt class="docutils literal"><span class="pre"><span class="Identifier">source</span> <span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">compiler</span><span class="Operator">.</span><span class="Identifier">gdb</span></span></tt> at startup</li>
  197. <li>LLDB execute <tt class="docutils literal"><span class="pre"><span class="Identifier">command</span> <span class="Identifier">source</span> <span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">compiler</span><span class="Operator">.</span><span class="Identifier">lldb</span></span></tt> at startup</li>
  198. </ul>
  199. </li>
  200. <li>Use one of the scoping helpers like so:</li>
  201. </ol>
  202. <p><pre class="listing"><span class="Keyword">if</span> <span class="Identifier">isCompilerDebug</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span>
  203. <span class="Identifier">enteringDebugSection</span><span class="Punctuation">(</span><span class="Punctuation">)</span>
  204. <span class="Keyword">else</span><span class="Punctuation">:</span>
  205. <span class="Identifier">exitingDebugSection</span><span class="Punctuation">(</span><span class="Punctuation">)</span></pre></p>
  206. <p>A caveat of this method is that all breakpoints and watchpoints are enabled or disabled. Also, due to a bug, only breakpoints can be constrained for LLDB.</p>
  207. <h1><a class="toc-backref" id="the-compiler-s-architecture" href="#the-compiler-s-architecture">The compiler's architecture</a></h1><p>Nim uses the classic compiler architecture: A lexer/scanner feeds tokens to a parser. The parser builds a syntax tree that is used by the code generators. This syntax tree is the interface between the parser and the code generator. It is essential to understand most of the compiler's code.</p>
  208. <p>Semantic analysis is separated from parsing.</p>
  209. <h2><a class="toc-backref" id="the-compiler-s-architecture-short-description-of-nim-s-modules" href="#the-compiler-s-architecture-short-description-of-nim-s-modules">Short description of Nim's modules</a></h2><table border="1" class="docutils"><tr><th>Module</th><th>Description</th></tr>
  210. <tr><td>nim</td><td>main module: parses the command line and calls <tt class="docutils literal"><span class="pre"><span class="Identifier">main</span><span class="Operator">.</span><span class="Identifier">MainCommand</span></span></tt></td></tr>
  211. <tr><td>main</td><td>implements the top-level command dispatching</td></tr>
  212. <tr><td>nimconf</td><td>implements the config file reader</td></tr>
  213. <tr><td>syntaxes</td><td>dispatcher for the different parsers and filters</td></tr>
  214. <tr><td>filter_tmpl</td><td>standard template filter (<tt class="docutils literal"><span class="pre">#? stdtempl</span></tt>)</td></tr>
  215. <tr><td>lexbase</td><td>buffer handling of the lexical analyser</td></tr>
  216. <tr><td>lexer</td><td>lexical analyser</td></tr>
  217. <tr><td>parser</td><td>Nim's parser</td></tr>
  218. <tr><td>renderer</td><td>Nim code renderer (AST back to its textual form)</td></tr>
  219. <tr><td>options</td><td>contains global and local compiler options</td></tr>
  220. <tr><td>ast</td><td>type definitions of the abstract syntax tree (AST) and node constructors</td></tr>
  221. <tr><td>astalgo</td><td>algorithms for containers of AST nodes; converting the AST to YAML; the symbol table</td></tr>
  222. <tr><td>passes</td><td>implement the passes manager for passes over the AST</td></tr>
  223. <tr><td>trees</td><td>some algorithms for nodes; this module is less important</td></tr>
  224. <tr><td>types</td><td>module for traversing type graphs; also contain several helpers for dealing with types</td></tr>
  225. <tr><td></td><td></td></tr>
  226. <tr><td>sigmatch</td><td>contains the matching algorithm that is used for proc calls</td></tr>
  227. <tr><td>semexprs</td><td>contains the semantic checking phase for expressions</td></tr>
  228. <tr><td>semstmts</td><td>contains the semantic checking phase for statements</td></tr>
  229. <tr><td>semtypes</td><td>contains the semantic checking phase for types</td></tr>
  230. <tr><td>seminst</td><td>instantiation of generic procs and types</td></tr>
  231. <tr><td>semfold</td><td>contains code to deal with constant folding</td></tr>
  232. <tr><td>sempass2</td><td>Second semantic checking pass over the AST</td></tr>
  233. <tr><td>vm</td><td>contains an AST interpreter for compile time evaluation</td></tr>
  234. <tr><td>pragmas</td><td>semantic checking of pragmas</td></tr>
  235. <tr><td></td><td></td></tr>
  236. <tr><td>idents</td><td>implements a general mapping from identifiers to an internal representation (<tt class="docutils literal"><span class="pre"><span class="Identifier">PIdent</span></span></tt>) that is used so that a simple id-comparison suffices to establish whether two Nim identifiers are equivalent</td></tr>
  237. <tr><td></td><td></td></tr>
  238. <tr><td>transf</td><td>transformations on the AST that need to be done before code generation</td></tr>
  239. <tr><td>cgen</td><td>main file of the C code generator</td></tr>
  240. <tr><td>ccgutils</td><td>contains helpers for the C code generator</td></tr>
  241. <tr><td>ccgtypes</td><td>the generator for C types</td></tr>
  242. <tr><td>ccgstmts</td><td>the generator for statements</td></tr>
  243. <tr><td>ccgexprs</td><td>the generator for expressions</td></tr>
  244. <tr><td>extccomp</td><td>this module calls the C compiler and linker; interesting if you want to add support for a new C compiler</td></tr>
  245. </table>
  246. <h2><a class="toc-backref" id="the-compiler-s-architecture-the-syntax-tree" href="#the-compiler-s-architecture-the-syntax-tree">The syntax tree</a></h2><p>The syntax tree consists of nodes which may have an arbitrary number of children. Types and symbols are represented by other nodes, because they may contain cycles. The AST changes its shape after semantic checking. This is needed to make life easier for the code generators. See the &quot;ast&quot; module for the type definitions. The <a class="reference external" href="macros.html">macros</a> module contains many examples how the AST represents each syntactic structure.</p>
  247. <h1><a class="toc-backref" id="runtimes" href="#runtimes">Runtimes</a></h1><p>Nim has two different runtimes, the &quot;old runtime&quot; and the &quot;new runtime&quot;. The old runtime supports the old GCs (markAndSweep, refc, Boehm), the new runtime supports ARC/ORC. The new runtime is active <tt class="docutils literal"><span class="pre"><span class="Keyword">when</span> <span class="Identifier">defined</span><span class="Punctuation">(</span><span class="Identifier">nimV2</span><span class="Punctuation">)</span></span></tt>.</p>
  248. <h1><a class="toc-backref" id="coding-guidelines" href="#coding-guidelines">Coding Guidelines</a></h1><ul class="simple"><li>We follow Nim's official style guide, see <a class="reference external" href="nep1.html">NEP1</a>.</li>
  249. <li>Max line length is 100 characters.</li>
  250. <li>Provide spaces around binary operators if that enhances readability.</li>
  251. <li>Use a space after a colon, but not before it.</li>
  252. <li>(deprecated) Start types with a capital <tt class="docutils literal"><span class="pre"><span class="Identifier">T</span></span></tt>, unless they are pointers/references which start with <tt class="docutils literal"><span class="pre"><span class="Identifier">P</span></span></tt>.</li>
  253. <li>Prefer <tt class="docutils literal"><span class="pre"><span class="Keyword">import</span> <span class="Identifier">package</span></span></tt> over <tt class="docutils literal"><span class="pre"><span class="Keyword">from</span> <span class="Identifier">package</span> <span class="Keyword">import</span> <span class="Identifier">symbol</span></span></tt>.</li>
  254. </ul>
  255. <p>See also the <a class="reference external" href="apis.html">API naming design</a> document.</p>
  256. <h1><a class="toc-backref" id="porting-to-new-platforms" href="#porting-to-new-platforms">Porting to new platforms</a></h1><p>Porting Nim to a new architecture is pretty easy, since C is the most portable programming language (within certain limits) and Nim generates C code, porting the code generator is not necessary.</p>
  257. <p>POSIX-compliant systems on conventional hardware are usually pretty easy to port: Add the platform to <tt class="docutils literal"><span class="pre"><span class="Identifier">platform</span></span></tt> (if it is not already listed there), check that the OS, System modules work and recompile Nim.</p>
  258. <p>The only case where things aren't as easy is when old runtime's garbage collectors need some assembler tweaking to work. The default implementation uses C's <tt class="docutils literal"><span class="pre"><span class="Identifier">setjmp</span></span></tt> function to store all registers on the hardware stack. It may be necessary that the new platform needs to replace this generic code by some assembler code.</p>
  259. <p>Files that may need changed for your platform include:</p>
  260. <ul class="simple"><li><tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">platform</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add os/cpu properties.</li>
  261. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">lib</span><span class="Operator">/</span><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add os/cpu to the documentation for <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">hostOS</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">hostCPU</span></span></tt>.</li>
  262. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">options</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add special os/cpu property checks in <tt class="docutils literal"><span class="pre"><span class="Identifier">isDefined</span></span></tt>.</li>
  263. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">installer</span><span class="Operator">.</span><span class="Identifier">ini</span></span></tt> Add os/cpu to <tt class="docutils literal"><span class="pre"><span class="Identifier">Project</span><span class="Operator">.</span><span class="Identifier">Platforms</span></span></tt> field.</li>
  264. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">lib</span><span class="Operator">/</span><span class="Identifier">system</span><span class="Operator">/</span><span class="Identifier">platforms</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add os/cpu.</li>
  265. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">std</span><span class="Operator">/</span><span class="Identifier">private</span><span class="Operator">/</span><span class="Identifier">osseps</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add os specializations.</li>
  266. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">lib</span><span class="Operator">/</span><span class="Identifier">pure</span><span class="Operator">/</span><span class="Identifier">distros</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> Add os, package handler.</li>
  267. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">niminst</span><span class="Operator">/</span><span class="Identifier">makefile</span><span class="Operator">.</span><span class="Identifier">nimf</span></span></tt> Add os/cpu compiler/linker flags.</li>
  268. <li><tt class="docutils literal"><span class="pre"><span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">niminst</span><span class="Operator">/</span><span class="Identifier">buildsh</span><span class="Operator">.</span><span class="Identifier">nimf</span></span></tt> Add os/cpu compiler/linker flags.</li>
  269. </ul>
  270. <p>If the <tt class="docutils literal"><span class="pre"><span class="Operator">--</span><span class="Identifier">os</span></span></tt> or <tt class="docutils literal"><span class="pre"><span class="Operator">--</span><span class="Identifier">cpu</span></span></tt> options aren't passed to the compiler, then Nim will determine the current host os, cpu and endianness from <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">cpuEndian</span></span></tt>, <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">hostOS</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span><span class="Operator">.</span><span class="Identifier">hostCPU</span></span></tt>. Those values are derived from <tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">platform</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt>.</p>
  271. <p>In order for the new platform to be bootstrapped from the <tt class="docutils literal"><span class="pre"><span class="Identifier">csources</span></span></tt>, it must:</p>
  272. <ul class="simple"><li>have <tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">platform</span><span class="Operator">.</span><span class="Identifier">nim</span></span></tt> updated</li>
  273. <li>have <tt class="docutils literal"><span class="pre"><span class="Identifier">compiler</span><span class="Operator">/</span><span class="Identifier">installer</span><span class="Operator">.</span><span class="Identifier">ini</span></span></tt> updated</li>
  274. <li>have <tt class="docutils literal"><span class="pre"><span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">niminst</span><span class="Operator">/</span><span class="Identifier">buildsh</span><span class="Operator">.</span><span class="Identifier">nimf</span></span></tt> updated</li>
  275. <li>have <tt class="docutils literal"><span class="pre"><span class="Identifier">tools</span><span class="Operator">/</span><span class="Identifier">niminst</span><span class="Operator">/</span><span class="Identifier">makefile</span><span class="Operator">.</span><span class="Identifier">nimf</span></span></tt> updated</li>
  276. <li>be backported to the Nim version used by the <tt class="docutils literal"><span class="pre"><span class="Identifier">csources</span></span></tt></li>
  277. <li>the new <tt class="docutils literal"><span class="pre"><span class="Identifier">csources</span></span></tt> must be pushed</li>
  278. <li>the new <tt class="docutils literal"><span class="pre"><span class="Identifier">csources</span></span></tt> revision must be updated in <tt class="docutils literal"><span class="pre"><span class="Identifier">config</span><span class="Operator">/</span><span class="Identifier">build_config</span><span class="Operator">.</span><span class="Identifier">txt</span></span></tt></li>
  279. </ul>
  280. <h1><a class="toc-backref" id="runtime-type-information" href="#runtime-type-information">Runtime type information</a></h1><p><strong>Note</strong>: This section describes the &quot;old runtime&quot;.</p>
  281. <p><em>Runtime type information</em> (RTTI) is needed for several aspects of the Nim programming language:</p>
  282. <dl class="docutils"><dt>Garbage collection</dt>
  283. <dd>The old GCs use the RTTI for traversing arbitrary Nim types, but usually only the <tt class="docutils literal"><span class="pre"><span class="Identifier">marker</span></span></tt> field which contains a proc that does the traversal.</dd>
  284. <dt>Complex assignments</dt>
  285. <dd>Sequences and strings are implemented as pointers to resizable buffers, but Nim requires copying for assignments. Apart from RTTI the compiler also generates copy procedures as a specialization.</dd>
  286. </dl>
  287. <p>We already know the type information as a graph in the compiler. Thus, we need to serialize this graph as RTTI for C code generation. Look at the file <tt class="docutils literal"><span class="pre">lib/system/hti.nim</span></tt> for more information.</p>
  288. <h1><a class="toc-backref" id="magics-and-compilerprocs" href="#magics-and-compilerprocs">Magics and compilerProcs</a></h1><p>The <tt class="docutils literal"><span class="pre"><span class="Identifier">system</span></span></tt> module contains the part of the RTL which needs support by compiler magic. The C code generator generates the C code for it, just like any other module. However, calls to some procedures like <tt class="docutils literal"><span class="pre"><span class="Identifier">addInt</span></span></tt> are inserted by the generator. Therefore, there is a table (<tt class="docutils literal"><span class="pre"><span class="Identifier">compilerprocs</span></span></tt>) with all symbols that are marked as <tt class="docutils literal"><span class="pre"><span class="Identifier">compilerproc</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="Identifier">compilerprocs</span></span></tt> are needed by the code generator. A <tt class="docutils literal"><span class="pre"><span class="Identifier">magic</span></span></tt> proc is not the same as a <tt class="docutils literal"><span class="pre"><span class="Identifier">compilerproc</span></span></tt>: A <tt class="docutils literal"><span class="pre"><span class="Identifier">magic</span></span></tt> is a proc that needs compiler magic for its semantic checking, a <tt class="docutils literal"><span class="pre"><span class="Identifier">compilerproc</span></span></tt> is a proc that is used by the code generator.</p>
  289. <h1><a class="toc-backref" id="code-generation-for-closures" href="#code-generation-for-closures">Code generation for closures</a></h1><p>Code generation for closures is implemented by <span id="lambda-lifting_1">lambda lifting</span>.</p>
  290. <h2><a class="toc-backref" id="code-generation-for-closures-design" href="#code-generation-for-closures-design">Design</a></h2><p>A <tt class="docutils literal"><span class="pre"><span class="Identifier">closure</span></span></tt> proc var can call ordinary procs of the default Nim calling convention. But not the other way round! A closure is implemented as a <tt class="docutils literal"><span class="pre"><span class="Keyword">tuple</span><span class="Punctuation">[</span><span class="Identifier">prc</span><span class="Punctuation">,</span> <span class="Identifier">env</span><span class="Punctuation">]</span></span></tt>. <tt class="docutils literal"><span class="pre"><span class="Identifier">env</span></span></tt> can be nil implying a call without a closure. This means that a call through a closure generates an <tt class="docutils literal"><span class="pre"><span class="Keyword">if</span></span></tt> but the interoperability is worth the cost of the <tt class="docutils literal"><span class="pre"><span class="Keyword">if</span></span></tt>. Thunk generation would be possible too, but it's slightly more effort to implement.</p>
  291. <p>Tests with GCC on Amd64 showed that it's really beneficial if the 'environment' pointer is passed as the last argument, not as the first argument.</p>
  292. <p>Proper thunk generation is harder because the proc that is to wrap could stem from a complex expression:</p>
  293. <p><pre class="listing"><span class="Identifier">receivesClosure</span><span class="Punctuation">(</span><span class="Identifier">returnsDefaultCC</span><span class="Punctuation">[</span><span class="Identifier">i</span><span class="Punctuation">]</span><span class="Punctuation">)</span></pre></p>
  294. <p>A thunk would need to call <tt class="docutils literal"><span class="pre"><span class="Identifier">returnsDefaultCC</span><span class="Punctuation">[</span><span class="Identifier">i</span><span class="Punctuation">]</span></span></tt> somehow and that would require an <em>additional</em> closure generation... Ok, not really, but it requires to pass the function to call. So we'd end up with 2 indirect calls instead of one. Another much more severe problem with this solution is that it's not GC-safe to pass a proc pointer around via a generic <tt class="docutils literal"><span class="pre"><span class="Keyword">ref</span></span></tt> type.</p>
  295. <p>Example code:</p>
  296. <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">add</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="Punctuation">:</span> <span class="Keyword">proc</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="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">closure</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
  297. <span class="Keyword">return</span> <span class="Keyword">proc</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="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  298. <span class="Keyword">return</span> <span class="Identifier">x</span> <span class="Operator">+</span> <span class="Identifier">y</span>
  299. <span class="Keyword">var</span> <span class="Identifier">add2</span> <span class="Operator">=</span> <span class="Identifier">add</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span>
  300. <span class="Identifier">echo</span> <span class="Identifier">add2</span><span class="Punctuation">(</span><span class="DecNumber">5</span><span class="Punctuation">)</span> <span class="Comment">#OUT 7</span></pre></p>
  301. <p>This should produce roughly this code:</p>
  302. <p><pre class="listing"><span class="Keyword">type</span>
  303. <span class="Identifier">Env</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span>
  304. <span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># data</span>
  305. <span class="Keyword">proc</span> <span class="Identifier">anon</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="Identifier">c</span><span class="Punctuation">:</span> <span class="Identifier">Env</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  306. <span class="Keyword">return</span> <span class="Identifier">y</span> <span class="Operator">+</span> <span class="Identifier">c</span><span class="Operator">.</span><span class="Identifier">x</span>
  307. <span class="Keyword">proc</span> <span class="Identifier">add</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="Punctuation">:</span> <span class="Keyword">tuple</span><span class="Punctuation">[</span><span class="Identifier">prc</span><span class="Punctuation">,</span> <span class="Identifier">data</span><span class="Punctuation">]</span> <span class="Operator">=</span>
  308. <span class="Keyword">var</span> <span class="Identifier">env</span><span class="Punctuation">:</span> <span class="Identifier">Env</span>
  309. <span class="Identifier">new</span> <span class="Identifier">env</span>
  310. <span class="Identifier">env</span><span class="Operator">.</span><span class="Identifier">x</span> <span class="Operator">=</span> <span class="Identifier">x</span>
  311. <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Punctuation">(</span><span class="Identifier">anon</span><span class="Punctuation">,</span> <span class="Identifier">env</span><span class="Punctuation">)</span>
  312. <span class="Keyword">var</span> <span class="Identifier">add2</span> <span class="Operator">=</span> <span class="Identifier">add</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span>
  313. <span class="Keyword">let</span> <span class="Identifier">tmp</span> <span class="Operator">=</span> <span class="Keyword">if</span> <span class="Identifier">add2</span><span class="Operator">.</span><span class="Identifier">data</span> <span class="Operator">==</span> <span class="Keyword">nil</span><span class="Punctuation">:</span> <span class="Identifier">add2</span><span class="Operator">.</span><span class="Identifier">prc</span><span class="Punctuation">(</span><span class="DecNumber">5</span><span class="Punctuation">)</span> <span class="Keyword">else</span><span class="Punctuation">:</span> <span class="Identifier">add2</span><span class="Operator">.</span><span class="Identifier">prc</span><span class="Punctuation">(</span><span class="DecNumber">5</span><span class="Punctuation">,</span> <span class="Identifier">add2</span><span class="Operator">.</span><span class="Identifier">data</span><span class="Punctuation">)</span>
  314. <span class="Identifier">echo</span> <span class="Identifier">tmp</span></pre></p>
  315. <p>Beware of nesting:</p>
  316. <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">add</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="Punctuation">:</span> <span class="Keyword">proc</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="Punctuation">:</span> <span class="Keyword">proc</span> <span class="Punctuation">(</span><span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">closure</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">closure</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
  317. <span class="Keyword">return</span> <span class="Identifier">lambda</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="Punctuation">:</span> <span class="Keyword">proc</span> <span class="Punctuation">(</span><span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">closure</span><span class="Operator">.</span><span class="Punctuation">}</span> <span class="Operator">=</span>
  318. <span class="Keyword">return</span> <span class="Identifier">lambda</span> <span class="Punctuation">(</span><span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  319. <span class="Keyword">return</span> <span class="Identifier">x</span> <span class="Operator">+</span> <span class="Identifier">y</span> <span class="Operator">+</span> <span class="Identifier">z</span>
  320. <span class="Keyword">var</span> <span class="Identifier">add24</span> <span class="Operator">=</span> <span class="Identifier">add</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">)</span>
  321. <span class="Identifier">echo</span> <span class="Identifier">add24</span><span class="Punctuation">(</span><span class="DecNumber">5</span><span class="Punctuation">)</span> <span class="Comment">#OUT 11</span></pre></p>
  322. <p>This should produce roughly this code:</p>
  323. <p><pre class="listing"><span class="Keyword">type</span>
  324. <span class="Identifier">EnvX</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span>
  325. <span class="Identifier">x</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Comment"># data</span>
  326. <span class="Identifier">EnvY</span> <span class="Operator">=</span> <span class="Keyword">ref</span> <span class="Keyword">object</span>
  327. <span class="Identifier">y</span><span class="Punctuation">:</span> <span class="Identifier">int</span>
  328. <span class="Identifier">ex</span><span class="Punctuation">:</span> <span class="Identifier">EnvX</span>
  329. <span class="Keyword">proc</span> <span class="Identifier">lambdaZ</span><span class="Punctuation">(</span><span class="Identifier">z</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">,</span> <span class="Identifier">ey</span><span class="Punctuation">:</span> <span class="Identifier">EnvY</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  330. <span class="Keyword">return</span> <span class="Identifier">ey</span><span class="Operator">.</span><span class="Identifier">ex</span><span class="Operator">.</span><span class="Identifier">x</span> <span class="Operator">+</span> <span class="Identifier">ey</span><span class="Operator">.</span><span class="Identifier">y</span> <span class="Operator">+</span> <span class="Identifier">z</span>
  331. <span class="Keyword">proc</span> <span class="Identifier">lambdaY</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="Identifier">ex</span><span class="Punctuation">:</span> <span class="Identifier">EnvX</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">tuple</span><span class="Punctuation">[</span><span class="Identifier">prc</span><span class="Punctuation">,</span> <span class="Identifier">data</span><span class="Punctuation">:</span> <span class="Identifier">EnvY</span><span class="Punctuation">]</span> <span class="Operator">=</span>
  332. <span class="Keyword">var</span> <span class="Identifier">ey</span><span class="Punctuation">:</span> <span class="Identifier">EnvY</span>
  333. <span class="Identifier">new</span> <span class="Identifier">ey</span>
  334. <span class="Identifier">ey</span><span class="Operator">.</span><span class="Identifier">y</span> <span class="Operator">=</span> <span class="Identifier">y</span>
  335. <span class="Identifier">ey</span><span class="Operator">.</span><span class="Identifier">ex</span> <span class="Operator">=</span> <span class="Identifier">ex</span>
  336. <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Punctuation">(</span><span class="Identifier">lambdaZ</span><span class="Punctuation">,</span> <span class="Identifier">ey</span><span class="Punctuation">)</span>
  337. <span class="Keyword">proc</span> <span class="Identifier">add</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="Punctuation">:</span> <span class="Keyword">tuple</span><span class="Punctuation">[</span><span class="Identifier">prc</span><span class="Punctuation">,</span> <span class="Identifier">data</span><span class="Punctuation">:</span> <span class="Identifier">EnvX</span><span class="Punctuation">]</span> <span class="Operator">=</span>
  338. <span class="Keyword">var</span> <span class="Identifier">ex</span><span class="Punctuation">:</span> <span class="Identifier">EnvX</span>
  339. <span class="Identifier">ex</span><span class="Operator">.</span><span class="Identifier">x</span> <span class="Operator">=</span> <span class="Identifier">x</span>
  340. <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Punctuation">(</span><span class="Identifier">lambdaY</span><span class="Punctuation">,</span> <span class="Identifier">ex</span><span class="Punctuation">)</span>
  341. <span class="Keyword">var</span> <span class="Identifier">tmp</span> <span class="Operator">=</span> <span class="Identifier">add</span><span class="Punctuation">(</span><span class="DecNumber">2</span><span class="Punctuation">)</span>
  342. <span class="Keyword">var</span> <span class="Identifier">tmp2</span> <span class="Operator">=</span> <span class="Identifier">tmp</span><span class="Operator">.</span><span class="Identifier">fn</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">,</span> <span class="Identifier">tmp</span><span class="Operator">.</span><span class="Identifier">data</span><span class="Punctuation">)</span>
  343. <span class="Keyword">var</span> <span class="Identifier">add24</span> <span class="Operator">=</span> <span class="Identifier">tmp2</span><span class="Operator">.</span><span class="Identifier">fn</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">,</span> <span class="Identifier">tmp2</span><span class="Operator">.</span><span class="Identifier">data</span><span class="Punctuation">)</span>
  344. <span class="Identifier">echo</span> <span class="Identifier">add24</span><span class="Punctuation">(</span><span class="DecNumber">5</span><span class="Punctuation">)</span></pre></p>
  345. <p>We could get rid of nesting environments by always inlining inner anon procs. More useful is escape analysis and stack allocation of the environment, however.</p>
  346. <h2><a class="toc-backref" id="code-generation-for-closures-accumulator" href="#code-generation-for-closures-accumulator">Accumulator</a></h2><p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">getAccumulator</span><span class="Punctuation">(</span><span class="Identifier">start</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">proc</span> <span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Punctuation">{</span><span class="Operator">.</span><span class="Identifier">closure</span><span class="Punctuation">}</span> <span class="Operator">=</span>
  347. <span class="Keyword">var</span> <span class="Identifier">i</span> <span class="Operator">=</span> <span class="Identifier">start</span>
  348. <span class="Keyword">return</span> <span class="Identifier">lambda</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  349. <span class="Identifier">inc</span> <span class="Identifier">i</span>
  350. <span class="Keyword">return</span> <span class="Identifier">i</span>
  351. <span class="Keyword">proc</span> <span class="Identifier">p</span> <span class="Operator">=</span>
  352. <span class="Keyword">var</span> <span class="Identifier">delta</span> <span class="Operator">=</span> <span class="DecNumber">7</span>
  353. <span class="Keyword">proc</span> <span class="Identifier">accumulator</span><span class="Punctuation">(</span><span class="Identifier">start</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Keyword">proc</span><span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  354. <span class="Keyword">var</span> <span class="Identifier">x</span> <span class="Operator">=</span> <span class="Identifier">start</span><span class="Operator">-</span><span class="DecNumber">1</span>
  355. <span class="Identifier">result</span> <span class="Operator">=</span> <span class="Keyword">proc</span> <span class="Punctuation">(</span><span class="Punctuation">)</span><span class="Punctuation">:</span> <span class="Identifier">int</span> <span class="Operator">=</span>
  356. <span class="Identifier">x</span> <span class="Operator">=</span> <span class="Identifier">x</span> <span class="Operator">+</span> <span class="Identifier">delta</span>
  357. <span class="Identifier">inc</span> <span class="Identifier">delta</span>
  358. <span class="Keyword">return</span> <span class="Identifier">x</span>
  359. <span class="Keyword">var</span> <span class="Identifier">a</span> <span class="Operator">=</span> <span class="Identifier">accumulator</span><span class="Punctuation">(</span><span class="DecNumber">3</span><span class="Punctuation">)</span>
  360. <span class="Keyword">var</span> <span class="Identifier">b</span> <span class="Operator">=</span> <span class="Identifier">accumulator</span><span class="Punctuation">(</span><span class="DecNumber">4</span><span class="Punctuation">)</span>
  361. <span class="Identifier">echo</span> <span class="Identifier">a</span><span class="Punctuation">(</span><span class="Punctuation">)</span> <span class="Operator">+</span> <span class="Identifier">b</span><span class="Punctuation">(</span><span class="Punctuation">)</span></pre></p>
  362. <h2><a class="toc-backref" id="code-generation-for-closures-internals" href="#code-generation-for-closures-internals">Internals</a></h2><p>Lambda lifting is implemented as part of the <tt class="docutils literal"><span class="pre"><span class="Identifier">transf</span></span></tt> pass. The <tt class="docutils literal"><span class="pre"><span class="Identifier">transf</span></span></tt> pass generates code to set up the environment and to pass it around. However, this pass does not change the types! So we have some kind of mismatch here; on the one hand the proc expression becomes an explicit tuple, on the other hand the tyProc(ccClosure) type is not changed. For C code generation it's also important the hidden formal param is <tt class="docutils literal"><span class="pre"><span class="Keyword">void</span><span class="Operator">*</span></span></tt> and not something more specialized. However, the more specialized env type needs to passed to the backend somehow. We deal with this by modifying <tt class="docutils literal"><span class="pre"><span class="Identifier">s</span><span class="Operator">.</span><span class="Identifier">ast</span><span class="Punctuation">[</span><span class="Identifier">paramPos</span><span class="Punctuation">]</span></span></tt> to contain the formal hidden parameter, but not <tt class="docutils literal"><span class="pre"><span class="Identifier">s</span><span class="Operator">.</span><span class="Identifier">typ</span></span></tt>!</p>
  363. <h1><a class="toc-backref" id="notes-on-type-and-ast-representation" href="#notes-on-type-and-ast-representation">Notes on type and AST representation</a></h1><p>To be expanded.</p>
  364. <h2><a class="toc-backref" id="notes-on-type-and-ast-representation-integer-literals" href="#notes-on-type-and-ast-representation-integer-literals">Integer literals</a></h2><p>In Nim, there is a redundant way to specify the type of an integer literal. First, it should be unsurprising that every node has a node kind. The node of an integer literal can be any of the following values:</p>
  365. <pre>nkIntLit, nkInt8Lit, nkInt16Lit, nkInt32Lit, nkInt64Lit,
  366. nkUIntLit, nkUInt8Lit, nkUInt16Lit, nkUInt32Lit, nkUInt64Lit</pre>
  367. <p>On top of that, there is also the <tt class="docutils literal"><span class="pre"><span class="Identifier">typ</span></span></tt> field for the type. The kind of the <tt class="docutils literal"><span class="pre"><span class="Identifier">typ</span></span></tt> field can be one of the following ones, and it should be matching the literal kind:</p>
  368. <pre>tyInt, tyInt8, tyInt16, tyInt32, tyInt64, tyUInt, tyUInt8,
  369. tyUInt16, tyUInt32, tyUInt64</pre>
  370. <p>Then there is also the integer literal type. This is a specific type that is implicitly convertible into the requested type if the requested type can hold the value. For this to work, the type needs to know the concrete value of the literal. For example an expression <tt class="docutils literal"><span class="pre"><span class="DecNumber">321</span></span></tt> will be of type <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span> <span class="Identifier">literal</span><span class="Punctuation">(</span><span class="DecNumber">321</span><span class="Punctuation">)</span></span></tt>. This type is implicitly convertible to all integer types and ranges that contain the value <tt class="docutils literal"><span class="pre"><span class="DecNumber">321</span></span></tt>. That would be all builtin integer types except <tt class="docutils literal"><span class="pre"><span class="Identifier">uint8</span></span></tt> and <tt class="docutils literal"><span class="pre"><span class="Identifier">int8</span></span></tt> where <tt class="docutils literal"><span class="pre"><span class="DecNumber">321</span></span></tt> would be out of range. When this literal type is assigned to a new <tt class="docutils literal"><span class="pre"><span class="Keyword">var</span></span></tt> or <tt class="docutils literal"><span class="pre"><span class="Keyword">let</span></span></tt> variable, it's type will be resolved to just <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span></span></tt>, not <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span> <span class="Identifier">literal</span><span class="Punctuation">(</span><span class="DecNumber">321</span><span class="Punctuation">)</span></span></tt> unlike constants. A constant keeps the full <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span> <span class="Identifier">literal</span><span class="Punctuation">(</span><span class="DecNumber">321</span><span class="Punctuation">)</span></span></tt> type. Here is an example where that difference matters.</p>
  371. <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">arg</span><span class="Punctuation">:</span> <span class="Identifier">int8</span><span class="Punctuation">)</span> <span class="Operator">=</span>
  372. <span class="Identifier">echo</span> <span class="StringLit">&quot;def&quot;</span>
  373. <span class="Keyword">const</span> <span class="Identifier">tmp1</span> <span class="Operator">=</span> <span class="DecNumber">123</span>
  374. <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">tmp1</span><span class="Punctuation">)</span> <span class="Comment"># OK</span>
  375. <span class="Keyword">let</span> <span class="Identifier">tmp2</span> <span class="Operator">=</span> <span class="DecNumber">123</span>
  376. <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">tmp2</span><span class="Punctuation">)</span> <span class="Comment"># Error</span></pre></p>
  377. <p>In a context with multiple overloads, the integer literal kind will always prefer the <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span></span></tt> type over all other types. If none of the overloads is of type <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span></span></tt>, then there will be an error because of ambiguity.</p>
  378. <p><pre class="listing"><span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">arg</span><span class="Punctuation">:</span> <span class="Identifier">int</span><span class="Punctuation">)</span> <span class="Operator">=</span>
  379. <span class="Identifier">echo</span> <span class="StringLit">&quot;abc&quot;</span>
  380. <span class="Keyword">proc</span> <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="Identifier">arg</span><span class="Punctuation">:</span> <span class="Identifier">int8</span><span class="Punctuation">)</span> <span class="Operator">=</span>
  381. <span class="Identifier">echo</span> <span class="StringLit">&quot;def&quot;</span>
  382. <span class="Identifier">foo</span><span class="Punctuation">(</span><span class="DecNumber">123</span><span class="Punctuation">)</span> <span class="Comment"># output: abc</span>
  383. <span class="Keyword">proc</span> <span class="Identifier">bar</span><span class="Punctuation">(</span><span class="Identifier">arg</span><span class="Punctuation">:</span> <span class="Identifier">int16</span><span class="Punctuation">)</span> <span class="Operator">=</span>
  384. <span class="Identifier">echo</span> <span class="StringLit">&quot;abc&quot;</span>
  385. <span class="Keyword">proc</span> <span class="Identifier">bar</span><span class="Punctuation">(</span><span class="Identifier">arg</span><span class="Punctuation">:</span> <span class="Identifier">int8</span><span class="Punctuation">)</span> <span class="Operator">=</span>
  386. <span class="Identifier">echo</span> <span class="StringLit">&quot;def&quot;</span>
  387. <span class="Identifier">bar</span><span class="Punctuation">(</span><span class="DecNumber">123</span><span class="Punctuation">)</span> <span class="Comment"># Error ambiguous call</span></pre></p>
  388. <p>In the compiler these integer literal types are represented with the node kind <tt class="docutils literal"><span class="pre"><span class="Identifier">nkIntLit</span></span></tt>, type kind <tt class="docutils literal"><span class="pre"><span class="Identifier">tyInt</span></span></tt> and the member <tt class="docutils literal"><span class="pre"><span class="Identifier">n</span></span></tt> of the type pointing back to the integer literal node in the ast containing the integer value. These are the properties that hold true for integer literal types.</p>
  389. <pre>n.kind == nkIntLit
  390. n.typ.kind == tyInt
  391. n.typ.n == n</pre>
  392. <p>Other literal types, such as <tt class="docutils literal"><span class="pre"><span class="Identifier">uint</span> <span class="Identifier">literal</span><span class="Punctuation">(</span><span class="DecNumber">123</span><span class="Punctuation">)</span></span></tt> that would automatically convert to other integer types, but prefers to become a <tt class="docutils literal"><span class="pre"><span class="Identifier">uint</span></span></tt> are not part of the Nim language.</p>
  393. <p>In an unchecked AST, the <tt class="docutils literal"><span class="pre"><span class="Identifier">typ</span></span></tt> field is nil. The type checker will set the <tt class="docutils literal"><span class="pre"><span class="Identifier">typ</span></span></tt> field accordingly to the node kind. Nodes of kind <tt class="docutils literal"><span class="pre"><span class="Identifier">nkIntLit</span></span></tt> will get the integer literal type (e.g. <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span> <span class="Identifier">literal</span><span class="Punctuation">(</span><span class="DecNumber">123</span><span class="Punctuation">)</span></span></tt>). Nodes of kind <tt class="docutils literal"><span class="pre"><span class="Identifier">nkUIntLit</span></span></tt> will get type <tt class="docutils literal"><span class="pre"><span class="Identifier">uint</span></span></tt> (kind <tt class="docutils literal"><span class="pre"><span class="Identifier">tyUint</span></span></tt>), etc.</p>
  394. <p>This also means that it is not possible to write a literal in an unchecked AST that will after sem checking just be of type <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span></span></tt> and not implicitly convertible to other integer types. This only works for all integer types that are not <tt class="docutils literal"><span class="pre"><span class="Identifier">int</span></span></tt>. </p>
  395. </p>
  396. </div>
  397. </div>
  398. <div class="twelve-columns footer">
  399. <span class="nim-sprite"></span>
  400. <br>
  401. <small style="color: var(--hint);">Made with Nim. Generated: 2025-03-15 14:12:48 UTC</small>
  402. </div>
  403. </div>
  404. </div>
  405. <script defer data-domain="nim-lang.org" src="https://plausible.io/js/plausible.js"></script>
  406. </body>
  407. </html>