From 373717968eeb851e30a300923aa62e4c2aec519d Mon Sep 17 00:00:00 2001 From: krolik Date: Tue, 12 May 2015 12:45:34 +0300 Subject: [PATCH 01/28] new now able to make distinction between ref and non-ref types, so we don't get 'ref ref' type when calling new on ref type --- lib/system.nim | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index 1e6f76f3d..a56e91594 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -172,10 +172,16 @@ proc new*[T](a: var ref T) {.magic: "New", noSideEffect.} ## creates a new object of type ``T`` and returns a safe (traced) ## reference to it in ``a``. -proc new*(T: typedesc): ref T = +proc new*(T: typedesc): auto = ## creates a new object of type ``T`` and returns a safe (traced) ## reference to it as result value - new(result) + when (T is ref): + var r: T + else: + var r: ref T + new(r) + return r + proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} ## leaked implementation detail. Do not use. From 39dd16b5ef0761fee0b9586a21b12e991c50e26e Mon Sep 17 00:00:00 2001 From: Jonathan Edwards Date: Tue, 14 Jul 2015 17:52:50 -0400 Subject: [PATCH 02/28] Added Documentation Style Guide; Linked from contributing.rst --- contributing.rst | 10 ++-- styleguide.rst | 140 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 styleguide.rst diff --git a/contributing.rst b/contributing.rst index 68b706c73..3b495f01f 100644 --- a/contributing.rst +++ b/contributing.rst @@ -142,7 +142,7 @@ When contributing new procedures, be sure to add documentation, especially if the procedure is exported from the module. Documentation begins on the line following the ``proc`` definition, and is prefixed by ``##`` on each line. -Code examples are also encouraged. The RestructuredText Nim uses has a special +Code examples are also encouraged. The RestructuredText Nim uses has a special syntax for including examples. .. code-block:: nim @@ -155,8 +155,8 @@ syntax for including examples. ## echo someproc() # "something" result = "something" # single-hash comments do not produce documentation -The ``.. code-block:: nim`` followed by a newline and an indentation instructs the -``nim doc`` and ``nim doc2`` commands to produce syntax-highlighted example code with +The ``.. code-block:: nim`` followed by a newline and an indentation instructs the +``nim doc`` and ``nim doc2`` commands to produce syntax-highlighted example code with the documentation. When forward declaration is used, the documentation should be included with the @@ -186,7 +186,7 @@ or proc hello*(): string = # says hello result = "hello" - + the first is preferred. The Git stuff @@ -216,3 +216,5 @@ General commit rules git diff --check --cached || exit $? 3. Describe your commit and use your common sense. + +.. include:: styleguide.rst diff --git a/styleguide.rst b/styleguide.rst new file mode 100644 index 000000000..f8fec910c --- /dev/null +++ b/styleguide.rst @@ -0,0 +1,140 @@ +Style Guide (Documentation) +=========================== + +General Guidelines +------------------ + +* Authors should document anything that is exported. +* Within a documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. +* Documentation is parsed as RST (RestructuredText). +* Inline code should be surrounded by double tick marks (``` `` ```). With ReStructuredTest (RST), if you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (`\`). The preceding is typed as ``` ``int8``\s are great!```. + +Module-level documentation +-------------------------- + +Documentation of a module is placed at the top of the module itself. Each line of documentation begins with double hashes (`##`). +Code samples are encouraged, and should follow the general RST syntax: + +```nim +## The ``universe`` module computes the answer to life, the universe, and everything. +## +## .. code-block:: nim +## echo computeAnswerString*() # "42" +``` + +Within this top-level comment, you can indicate the authorship and copyright of the code, which will be featured in the produced documentation. + +```nim +## This is the best module ever. It provides answers to everything! +## +## :Author: Steve McQueen +## :Copyright: 1965 +## +``` + +Users are encouraged to leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.). + +Procs, Templates, Macros, Converters, and Iterators +--------------------------------------------------- + +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 double tick marks (``` `` ```). + +```nim + proc example1*(x: int) = + ## Prints the value of ``x`` + echo x +``` + +Whenever an example of usage would be helpful to the user, please include a sample within the documentation in RST format as below. + +```nim + proc addThree*(x, y, z: int8): int = + ## Adds three ``int8`` values, treating them as unsigned and + ## truncating the result + ## + ## .. code-block:: nim + ## echo addThree(3, 125, 6) # -122 + result = x +% y +% z +``` + +The commands ``nim doc`` and ``nim doc2`` will then correctly syntax highlight the Nim code within the documentation. + +Types +----- + +Types should also be documented. This documentation can also contain code samples, but those are likely better placed with the functions to which they refer. + +```nim +type + NamedQueue*[T] = object ## Provides a linked data structure with names + ## throughout. Named for convenience. I'm making + ## this comment long to show how you can, too. + name*: string ## The name of the item + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue +``` + +You have some flexibility when placing the documentation: +```nim +type + NamedQueue*[T] = object + ## Provides a linked data structure with names + ## throughout. Named for convenience. I'm making + ## this comment long to show how you can, too. + name*: string ## The name of the item + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue +``` + +Make sure to place the documentation beside or within the object. + +```nim +type + ## This documentation disappears. It's basically annotating the + ## ``type`` above. + NamedQueue*[T] = object + name*: string ## This becomes the main documentation for the object, which + ## is not what we want. + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue + +``` + +Var, Let, and Const +------------------- + +When declaring module-wide constants and values, documentation is encouraged. The placement of doc comments is similar to the ``type`` sections. + +```nim +const + X* = 42 ## An awesome number + SpreadArray* = [ + [1,2,3], + [2,3,1], + [3,1,2], + ] ## Doc comment for ``SpreadArray`` +``` + +Placement of comments in other areas is usually allowed, but will not become part of the documentation output. + +```nim +const + BadMathVals* = [ + 3.14, ## pi + 2.72, ## e + 0.58, ## gamma + ] ## A bunch of badly rounded values +``` + +In the produced documentation, the comments beside the elements of ``BadMathVals`` do not make it into the final documentation. + +As a final note, Nim supports Unicode in comments just fine, so the above can be replaced with the following: + +```nim +const + BadMathVals* = [ + 3.14, ## π + 2.72, ## e + 0.58, ## γ + ] ## A bunch of badly rounded values (including π!) +``` From 6a490e95e4a0a173fdfe2da05e8025b21e236ae2 Mon Sep 17 00:00:00 2001 From: Jonathan Edwards Date: Tue, 14 Jul 2015 18:24:02 -0400 Subject: [PATCH 03/28] Corrected guide; polished it --- styleguide.rst | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/styleguide.rst b/styleguide.rst index f8fec910c..c6e04798b 100644 --- a/styleguide.rst +++ b/styleguide.rst @@ -5,9 +5,9 @@ General Guidelines ------------------ * Authors should document anything that is exported. -* Within a documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. -* Documentation is parsed as RST (RestructuredText). -* Inline code should be surrounded by double tick marks (``` `` ```). With ReStructuredTest (RST), if you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (`\`). The preceding is typed as ``` ``int8``\s are great!```. +* Within documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. +* Documentation is parsed as ReStructuredText (RST). +* Inline code should be surrounded by double tick marks (``` `` ```). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (`\`). The preceding is typed as ``` ``int8``\s are great!```. Module-level documentation -------------------------- @@ -18,7 +18,7 @@ Code samples are encouraged, and should follow the general RST syntax: ```nim ## The ``universe`` module computes the answer to life, the universe, and everything. ## -## .. code-block:: nim +## .. code-block:: Nim ## echo computeAnswerString*() # "42" ``` @@ -32,7 +32,7 @@ Within this top-level comment, you can indicate the authorship and copyright of ## ``` -Users are encouraged to leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.). +Leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.). Procs, Templates, Macros, Converters, and Iterators --------------------------------------------------- @@ -45,7 +45,7 @@ The documentation of a procedure should begin with a capital letter and should b echo x ``` -Whenever an example of usage would be helpful to the user, please include a sample within the documentation in RST format as below. +Whenever an example of usage would be helpful to the user, you should include one within the documentation in RST format as below. ```nim proc addThree*(x, y, z: int8): int = @@ -62,7 +62,7 @@ The commands ``nim doc`` and ``nim doc2`` will then correctly syntax highlight t Types ----- -Types should also be documented. This documentation can also contain code samples, but those are likely better placed with the functions to which they refer. +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. ```nim type @@ -90,8 +90,8 @@ Make sure to place the documentation beside or within the object. ```nim type - ## This documentation disappears. It's basically annotating the - ## ``type`` above. + ## This documentation disappears because it annotates the ``type`` keyword + ## above, not ``NamedQueue``. NamedQueue*[T] = object name*: string ## This becomes the main documentation for the object, which ## is not what we want. @@ -115,26 +115,24 @@ const ] ## Doc comment for ``SpreadArray`` ``` -Placement of comments in other areas is usually allowed, but will not become part of the documentation output. +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 (``#``). ```nim const BadMathVals* = [ - 3.14, ## pi - 2.72, ## e - 0.58, ## gamma + 3.14, # pi + 2.72, # e + 0.58, # gamma ] ## A bunch of badly rounded values ``` -In the produced documentation, the comments beside the elements of ``BadMathVals`` do not make it into the final documentation. - -As a final note, Nim supports Unicode in comments just fine, so the above can be replaced with the following: +Nim supports Unicode in comments, so the above can be replaced with the following: ```nim const BadMathVals* = [ - 3.14, ## π - 2.72, ## e - 0.58, ## γ + 3.14, # π + 2.72, # e + 0.58, # γ ] ## A bunch of badly rounded values (including π!) ``` From a98f609ae215d1fcf9922329b5d87bd1b9242800 Mon Sep 17 00:00:00 2001 From: Jonathan Edwards Date: Wed, 15 Jul 2015 16:40:13 -0400 Subject: [PATCH 04/28] Renamed file; made RST --- docstyle.rst | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ styleguide.rst | 138 ------------------------------------------------ 2 files changed, 140 insertions(+), 138 deletions(-) create mode 100644 docstyle.rst delete mode 100644 styleguide.rst diff --git a/docstyle.rst b/docstyle.rst new file mode 100644 index 000000000..d4443027b --- /dev/null +++ b/docstyle.rst @@ -0,0 +1,140 @@ +Documentation Style +=================== + +General Guidelines +------------------ + +* Authors should document anything that is exported. +* Within documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. +* Documentation is parsed as ReStructuredText (RST). +* Inline code should be surrounded by double tick marks ("``` `` ```"). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (``\``). The preceding is typed as ``` ``int8``\s are great!```. + +Module-level documentation +-------------------------- + +Documentation of a module is placed at the top of the module itself. Each line of documentation begins with double hashes (``##``). +Code samples are encouraged, and should follow the general RST syntax: + +.. code-block:: Nim + + ## The ``universe`` module computes the answer to life, the universe, and everything. + ## + ## .. code-block:: Nim + ## echo computeAnswerString*() # "42" + + +Within this top-level comment, you can indicate the authorship and copyright of the code, which will be featured in the produced documentation. + +.. code-block:: Nim + + ## This is the best module ever. It provides answers to everything! + ## + ## :Author: Steve McQueen + ## :Copyright: 1965 + ## + +Leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.). + +Procs, Templates, Macros, Converters, and Iterators +--------------------------------------------------- + +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 double tick marks (``` `` ```). + +.. code-block:: Nim + + proc example1*(x: int) = + ## Prints the value of ``x`` + echo x + +Whenever an example of usage would be helpful to the user, you should include one within the documentation in RST format as below. + +.. code-block:: Nim + + proc addThree*(x, y, z: int8): int = + ## Adds three ``int8`` values, treating them as unsigned and + ## truncating the result + ## + ## .. code-block:: nim + ## echo addThree(3, 125, 6) # -122 + result = x +% y +% z + +The commands ``nim doc`` and ``nim doc2`` will then correctly syntax highlight the Nim code within the documentation. + +Types +----- + +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. + +.. code-block:: Nim + + type + NamedQueue*[T] = object ## Provides a linked data structure with names + ## throughout. Named for convenience. I'm making + ## this comment long to show how you can, too. + name*: string ## The name of the item + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue + + +You have some flexibility when placing the documentation: + +.. code-block:: Nim + + type + NamedQueue*[T] = object + ## Provides a linked data structure with names + ## throughout. Named for convenience. I'm making + ## this comment long to show how you can, too. + name*: string ## The name of the item + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue + +Make sure to place the documentation beside or within the object. + +.. code-block:: Nim + + type + ## This documentation disappears because it annotates the ``type`` keyword + ## above, not ``NamedQueue``. + NamedQueue*[T] = object + name*: string ## This becomes the main documentation for the object, which + ## is not what we want. + val*: T ## Its value + next*: ref NamedQueue[T] ## The next item in the queue + +Var, Let, and Const +------------------- + +When declaring module-wide constants and values, documentation is encouraged. The placement of doc comments is similar to the ``type`` sections. + +.. code-block:: Nim + + const + X* = 42 ## An awesome number + SpreadArray* = [ + [1,2,3], + [2,3,1], + [3,1,2], + ] ## Doc comment for ``SpreadArray`` + +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 (``#``). + +.. code-block:: Nim + + const + BadMathVals* = [ + 3.14, # pi + 2.72, # e + 0.58, # gamma + ] ## A bunch of badly rounded values + +Nim supports Unicode in comments, so the above can be replaced with the following: + +.. code-block:: Nim + + const + BadMathVals* = [ + 3.14, # π + 2.72, # e + 0.58, # γ + ] ## A bunch of badly rounded values (including π!) diff --git a/styleguide.rst b/styleguide.rst deleted file mode 100644 index c6e04798b..000000000 --- a/styleguide.rst +++ /dev/null @@ -1,138 +0,0 @@ -Style Guide (Documentation) -=========================== - -General Guidelines ------------------- - -* Authors should document anything that is exported. -* Within documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. -* Documentation is parsed as ReStructuredText (RST). -* Inline code should be surrounded by double tick marks (``` `` ```). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (`\`). The preceding is typed as ``` ``int8``\s are great!```. - -Module-level documentation --------------------------- - -Documentation of a module is placed at the top of the module itself. Each line of documentation begins with double hashes (`##`). -Code samples are encouraged, and should follow the general RST syntax: - -```nim -## The ``universe`` module computes the answer to life, the universe, and everything. -## -## .. code-block:: Nim -## echo computeAnswerString*() # "42" -``` - -Within this top-level comment, you can indicate the authorship and copyright of the code, which will be featured in the produced documentation. - -```nim -## This is the best module ever. It provides answers to everything! -## -## :Author: Steve McQueen -## :Copyright: 1965 -## -``` - -Leave a space between the last line of top-level documentation and the beginning of Nim code (the imports, etc.). - -Procs, Templates, Macros, Converters, and Iterators ---------------------------------------------------- - -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 double tick marks (``` `` ```). - -```nim - proc example1*(x: int) = - ## Prints the value of ``x`` - echo x -``` - -Whenever an example of usage would be helpful to the user, you should include one within the documentation in RST format as below. - -```nim - proc addThree*(x, y, z: int8): int = - ## Adds three ``int8`` values, treating them as unsigned and - ## truncating the result - ## - ## .. code-block:: nim - ## echo addThree(3, 125, 6) # -122 - result = x +% y +% z -``` - -The commands ``nim doc`` and ``nim doc2`` will then correctly syntax highlight the Nim code within the documentation. - -Types ------ - -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. - -```nim -type - NamedQueue*[T] = object ## Provides a linked data structure with names - ## throughout. Named for convenience. I'm making - ## this comment long to show how you can, too. - name*: string ## The name of the item - val*: T ## Its value - next*: ref NamedQueue[T] ## The next item in the queue -``` - -You have some flexibility when placing the documentation: -```nim -type - NamedQueue*[T] = object - ## Provides a linked data structure with names - ## throughout. Named for convenience. I'm making - ## this comment long to show how you can, too. - name*: string ## The name of the item - val*: T ## Its value - next*: ref NamedQueue[T] ## The next item in the queue -``` - -Make sure to place the documentation beside or within the object. - -```nim -type - ## This documentation disappears because it annotates the ``type`` keyword - ## above, not ``NamedQueue``. - NamedQueue*[T] = object - name*: string ## This becomes the main documentation for the object, which - ## is not what we want. - val*: T ## Its value - next*: ref NamedQueue[T] ## The next item in the queue - -``` - -Var, Let, and Const -------------------- - -When declaring module-wide constants and values, documentation is encouraged. The placement of doc comments is similar to the ``type`` sections. - -```nim -const - X* = 42 ## An awesome number - SpreadArray* = [ - [1,2,3], - [2,3,1], - [3,1,2], - ] ## Doc comment for ``SpreadArray`` -``` - -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 (``#``). - -```nim -const - BadMathVals* = [ - 3.14, # pi - 2.72, # e - 0.58, # gamma - ] ## A bunch of badly rounded values -``` - -Nim supports Unicode in comments, so the above can be replaced with the following: - -```nim -const - BadMathVals* = [ - 3.14, # π - 2.72, # e - 0.58, # γ - ] ## A bunch of badly rounded values (including π!) -``` From 1670bf710fedfa59d0ca7514d6e5e2448ef00850 Mon Sep 17 00:00:00 2001 From: apense Date: Thu, 16 Jul 2015 20:44:54 -0400 Subject: [PATCH 05/28] Removed erroneous star --- docstyle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docstyle.rst b/docstyle.rst index d4443027b..5f7cf03d5 100644 --- a/docstyle.rst +++ b/docstyle.rst @@ -20,7 +20,7 @@ Code samples are encouraged, and should follow the general RST syntax: ## The ``universe`` module computes the answer to life, the universe, and everything. ## ## .. code-block:: Nim - ## echo computeAnswerString*() # "42" + ## echo computeAnswerString() # "42" Within this top-level comment, you can indicate the authorship and copyright of the code, which will be featured in the produced documentation. From c701ed3c99009992a111a6fed7fa74c2c0c8a119 Mon Sep 17 00:00:00 2001 From: apense Date: Thu, 16 Jul 2015 22:21:45 -0400 Subject: [PATCH 06/28] Changed period requirements --- docstyle.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docstyle.rst b/docstyle.rst index 5f7cf03d5..38ed28734 100644 --- a/docstyle.rst +++ b/docstyle.rst @@ -5,7 +5,7 @@ General Guidelines ------------------ * Authors should document anything that is exported. -* Within documentation for a procedure, a period (`.`) should follow each sentence in a comment block if there is more than one sentence in that block; otherwise, no period should be used. In other sections, complete sentences should have periods. Sentence fragments should have none. +* Within documentation for a procedure, a period (`.`) 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 procedure documentation, each should be complete and in present tense. * Documentation is parsed as ReStructuredText (RST). * Inline code should be surrounded by double tick marks ("``` `` ```"). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (``\``). The preceding is typed as ``` ``int8``\s are great!```. @@ -43,7 +43,7 @@ The documentation of a procedure should begin with a capital letter and should b .. code-block:: Nim proc example1*(x: int) = - ## Prints the value of ``x`` + ## Prints the value of ``x``. echo x Whenever an example of usage would be helpful to the user, you should include one within the documentation in RST format as below. @@ -52,7 +52,7 @@ Whenever an example of usage would be helpful to the user, you should include on proc addThree*(x, y, z: int8): int = ## Adds three ``int8`` values, treating them as unsigned and - ## truncating the result + ## truncating the result. ## ## .. code-block:: nim ## echo addThree(3, 125, 6) # -122 From a48cbfe5639466a44fb679fca8a1269a0a1d58b4 Mon Sep 17 00:00:00 2001 From: apense Date: Thu, 16 Jul 2015 22:32:40 -0400 Subject: [PATCH 07/28] Periods for everyone --- docstyle.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docstyle.rst b/docstyle.rst index 38ed28734..6b0e188fa 100644 --- a/docstyle.rst +++ b/docstyle.rst @@ -5,7 +5,7 @@ General Guidelines ------------------ * Authors should document anything that is exported. -* Within documentation for a procedure, a period (`.`) 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 procedure documentation, each should be complete and in present tense. +* Within documentation, a period (`.`) 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. * Documentation is parsed as ReStructuredText (RST). * Inline code should be surrounded by double tick marks ("``` `` ```"). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (``\``). The preceding is typed as ``` ``int8``\s are great!```. @@ -69,7 +69,7 @@ Exported types should also be documented. This documentation can also contain co type NamedQueue*[T] = object ## Provides a linked data structure with names - ## throughout. Named for convenience. I'm making + ## throughout. It is named for convenience. I'm making ## this comment long to show how you can, too. name*: string ## The name of the item val*: T ## Its value @@ -83,7 +83,7 @@ You have some flexibility when placing the documentation: type NamedQueue*[T] = object ## Provides a linked data structure with names - ## throughout. Named for convenience. I'm making + ## throughout. It is named for convenience. I'm making ## this comment long to show how you can, too. name*: string ## The name of the item val*: T ## Its value @@ -110,12 +110,12 @@ When declaring module-wide constants and values, documentation is encouraged. Th .. code-block:: Nim const - X* = 42 ## An awesome number + X* = 42 ## An awesome number. SpreadArray* = [ [1,2,3], [2,3,1], [3,1,2], - ] ## Doc comment for ``SpreadArray`` + ] ## Doc comment for ``SpreadArray``. 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 (``#``). @@ -126,7 +126,7 @@ Placement of comments in other areas is usually allowed, but will not become par 3.14, # pi 2.72, # e 0.58, # gamma - ] ## A bunch of badly rounded values + ] ## A bunch of badly rounded values. Nim supports Unicode in comments, so the above can be replaced with the following: @@ -137,4 +137,4 @@ Nim supports Unicode in comments, so the above can be replaced with the followin 3.14, # π 2.72, # e 0.58, # γ - ] ## A bunch of badly rounded values (including π!) + ] ## A bunch of badly rounded values (including π!). From 21e7e7c895568a79439f34f91a6132938cc742fc Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Sat, 25 Jul 2015 22:33:53 -0700 Subject: [PATCH 08/28] Emit pragma support for JS backend. --- compiler/jsgen.nim | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 87408f395..f32441d98 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -729,14 +729,13 @@ proc genBreakStmt(p: PProc, n: PNode) = p.blocks[idx].id = abs(p.blocks[idx].id) # label is used addf(p.body, "break L$1;$n" | "goto ::L$1::;$n", [rope(p.blocks[idx].id)]) -proc genAsmStmt(p: PProc, n: PNode) = +proc genAsmOrEmitStmt(p: PProc, n: PNode) = genLineDir(p, n) - assert(n.kind == nkAsmStmt) for i in countup(0, sonsLen(n) - 1): case n.sons[i].kind of nkStrLit..nkTripleStrLit: add(p.body, n.sons[i].strVal) of nkSym: add(p.body, mangleName(n.sons[i].sym)) - else: internalError(n.sons[i].info, "jsgen: genAsmStmt()") + else: internalError(n.sons[i].info, "jsgen: genAsmOrEmitStmt()") proc genIf(p: PProc, n: PNode, r: var TCompRes) = var cond, stmt: TCompRes @@ -1569,6 +1568,12 @@ proc genStmt(p: PProc, n: PNode) = gen(p, n, r) if r.res != nil: addf(p.body, "$#;$n", [r.res]) +proc genPragma(p: PProc, n: PNode) = + for it in n.sons: + case whichPragma(it) + of wEmit: genAsmOrEmitStmt(p, it.sons[1]) + else: discard + proc gen(p: PProc, n: PNode, r: var TCompRes) = r.typ = etyNone r.kind = resNone @@ -1668,12 +1673,13 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = if n.sons[0].kind != nkEmpty: genLineDir(p, n) gen(p, n.sons[0], r) - of nkAsmStmt: genAsmStmt(p, n) + of nkAsmStmt: genAsmOrEmitStmt(p, n) of nkTryStmt: genTry(p, n, r) of nkRaiseStmt: genRaiseStmt(p, n) of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, - nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: discard + nkFromStmt, nkTemplateDef, nkMacroDef: discard + of nkPragma: genPragma(p, n) of nkProcDef, nkMethodDef, nkConverterDef: var s = n.sons[namePos].sym if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: From 10da70d49e2f5e8030b5d797ea706bc4156cc100 Mon Sep 17 00:00:00 2001 From: apense Date: Wed, 29 Jul 2015 17:57:47 -0400 Subject: [PATCH 09/28] Fix double-ticks --- docstyle.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docstyle.rst b/docstyle.rst index 6b0e188fa..d789b1df9 100644 --- a/docstyle.rst +++ b/docstyle.rst @@ -7,7 +7,7 @@ General Guidelines * Authors should document anything that is exported. * Within documentation, a period (`.`) 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. * Documentation is parsed as ReStructuredText (RST). -* Inline code should be surrounded by double tick marks ("``` `` ```"). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (``\``). The preceding is typed as ``` ``int8``\s are great!```. +* Inline code should be surrounded by double tick marks ("``````"). If you would like a character to immediately follow inline code (e.g., "``int8``s are great!"), escape the following character with a backslash (``\``). The preceding is typed as ``` ``int8``\s are great!```. Module-level documentation -------------------------- @@ -38,7 +38,7 @@ Leave a space between the last line of top-level documentation and the beginning Procs, Templates, Macros, Converters, and Iterators --------------------------------------------------- -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 double tick marks (``` `` ```). +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 double tick marks (``````). .. code-block:: Nim From 70c4176105e08127da444a6419e1ad6d4c725dd7 Mon Sep 17 00:00:00 2001 From: def Date: Fri, 31 Jul 2015 23:16:52 +0200 Subject: [PATCH 10/28] Add Mipsel CPU support (untested) --- compiler/platform.nim | 3 ++- lib/system.nim | 3 ++- lib/system/platforms.nim | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/platform.nim b/compiler/platform.nim index 4dd5d8836..f52017af7 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -158,7 +158,7 @@ type TSystemCPU* = enum # Also add CPU for in initialization section and # alias conditionals to condsyms (end of module). cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64, - cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuArm, + cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, cpuArm, cpuJS, cpuNimrodVM, cpuAVR type @@ -180,6 +180,7 @@ const (name: "ia64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), (name: "amd64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), (name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), + (name: "mipsel", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32), (name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32), (name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32), (name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), diff --git a/lib/system.nim b/lib/system.nim index 91495f31a..56b62d111 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1150,7 +1150,8 @@ const hostCPU* {.magic: "HostCPU".}: string = "" ## a string that describes the host CPU. Possible values: - ## "i386", "alpha", "powerpc", "powerpc64", "sparc", "amd64", "mips", "arm". + ## "i386", "alpha", "powerpc", "powerpc64", "sparc", "amd64", "mips", + ## "mipsel", "arm". seqShallowFlag = low(int) diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index 47a01d5fe..0472181f5 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -22,6 +22,7 @@ type ia64, ## Intel Itanium amd64, ## x86_64 (AMD64); 64 bit x86 compatible CPU mips, ## Mips based processor + mipsel, ## Little Endian Mips based processor arm, ## ARM based processor vm, ## Some Virtual machine: Nim's VM or JavaScript avr ## AVR based processor @@ -67,6 +68,7 @@ const elif defined(ia64): CpuPlatform.ia64 elif defined(amd64): CpuPlatform.amd64 elif defined(mips): CpuPlatform.mips + elif defined(mipsel): CpuPlatform.mipsel elif defined(arm): CpuPlatform.arm elif defined(vm): CpuPlatform.vm elif defined(avr): CpuPlatform.avr From 3d6a8b401a22f02c6dd604bc6caac09f415d3ddf Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 31 Jul 2015 22:40:45 +0100 Subject: [PATCH 11/28] C source generation for mipsel. --- compiler/installer.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/installer.ini b/compiler/installer.ini index 52a3d0886..1ca615153 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -6,7 +6,7 @@ Name: "Nim" Version: "$version" Platforms: """ windows: i386;amd64 - linux: i386;amd64;powerpc64;arm;sparc;mips;powerpc + linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc macosx: i386;amd64;powerpc64 solaris: i386;amd64;sparc freebsd: i386;amd64 From 130605567e93902df1cc65dade92ec433fdf9dff Mon Sep 17 00:00:00 2001 From: def Date: Fri, 31 Jul 2015 23:55:31 +0200 Subject: [PATCH 12/28] Add powerpc64el support (untested) --- compiler/platform.nim | 5 +++-- lib/system.nim | 4 ++-- lib/system/platforms.nim | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/platform.nim b/compiler/platform.nim index f52017af7..153ada2b2 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -158,8 +158,8 @@ type TSystemCPU* = enum # Also add CPU for in initialization section and # alias conditionals to condsyms (end of module). cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64, - cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, cpuArm, - cpuJS, cpuNimrodVM, cpuAVR + cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, + cpuArm, cpuJS, cpuNimrodVM, cpuAVR type TEndian* = enum @@ -175,6 +175,7 @@ const (name: "alpha", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), (name: "powerpc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), (name: "powerpc64", intSize: 64, endian: bigEndian, floatSize: 64,bit: 64), + (name: "powerpc64el", intSize: 64, endian: littleEndian, floatSize: 64,bit: 64), (name: "sparc", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), (name: "vm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32), (name: "ia64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), diff --git a/lib/system.nim b/lib/system.nim index 56b62d111..19af433de 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1150,8 +1150,8 @@ const hostCPU* {.magic: "HostCPU".}: string = "" ## a string that describes the host CPU. Possible values: - ## "i386", "alpha", "powerpc", "powerpc64", "sparc", "amd64", "mips", - ## "mipsel", "arm". + ## "i386", "alpha", "powerpc", "powerpc64", "powerpc64el", "sparc", + ## "amd64", "mips", "mipsel", "arm". seqShallowFlag = low(int) diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index 0472181f5..243f48a3a 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -18,6 +18,7 @@ type alpha, ## Alpha processor powerpc, ## 32 bit PowerPC powerpc64, ## 64 bit PowerPC + powerpc64el, ## Little Endian 64 bit PowerPC sparc, ## Sparc based processor ia64, ## Intel Itanium amd64, ## x86_64 (AMD64); 64 bit x86 compatible CPU @@ -64,6 +65,7 @@ const elif defined(alpha): CpuPlatform.alpha elif defined(powerpc): CpuPlatform.powerpc elif defined(powerpc64): CpuPlatform.powerpc64 + elif defined(powerpc64el): CpuPlatform.powerpc64el elif defined(sparc): CpuPlatform.sparc elif defined(ia64): CpuPlatform.ia64 elif defined(amd64): CpuPlatform.amd64 From 13389eab9bc879a32e74c9b11ce17d68968cd4fe Mon Sep 17 00:00:00 2001 From: def Date: Fri, 31 Jul 2015 23:57:50 +0200 Subject: [PATCH 13/28] Add arm64 support (untested) --- compiler/platform.nim | 3 ++- lib/system.nim | 2 +- lib/system/platforms.nim | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/platform.nim b/compiler/platform.nim index 153ada2b2..c4e7d453a 100644 --- a/compiler/platform.nim +++ b/compiler/platform.nim @@ -159,7 +159,7 @@ type # alias conditionals to condsyms (end of module). cpuNone, cpuI386, cpuM68k, cpuAlpha, cpuPowerpc, cpuPowerpc64, cpuPowerpc64el, cpuSparc, cpuVm, cpuIa64, cpuAmd64, cpuMips, cpuMipsel, - cpuArm, cpuJS, cpuNimrodVM, cpuAVR + cpuArm, cpuArm64, cpuJS, cpuNimrodVM, cpuAVR type TEndian* = enum @@ -183,6 +183,7 @@ const (name: "mips", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), (name: "mipsel", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32), (name: "arm", intSize: 32, endian: littleEndian, floatSize: 64, bit: 32), + (name: "arm64", intSize: 64, endian: littleEndian, floatSize: 64, bit: 64), (name: "js", intSize: 32, endian: bigEndian,floatSize: 64,bit: 32), (name: "nimrodvm", intSize: 32, endian: bigEndian, floatSize: 64, bit: 32), (name: "avr", intSize: 16, endian: littleEndian, floatSize: 32, bit: 16)] diff --git a/lib/system.nim b/lib/system.nim index 19af433de..260d7fbcd 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1151,7 +1151,7 @@ const hostCPU* {.magic: "HostCPU".}: string = "" ## a string that describes the host CPU. Possible values: ## "i386", "alpha", "powerpc", "powerpc64", "powerpc64el", "sparc", - ## "amd64", "mips", "mipsel", "arm". + ## "amd64", "mips", "mipsel", "arm", "arm64". seqShallowFlag = low(int) diff --git a/lib/system/platforms.nim b/lib/system/platforms.nim index 243f48a3a..0a7045fae 100644 --- a/lib/system/platforms.nim +++ b/lib/system/platforms.nim @@ -25,6 +25,7 @@ type mips, ## Mips based processor mipsel, ## Little Endian Mips based processor arm, ## ARM based processor + arm64, ## ARM64 based processor vm, ## Some Virtual machine: Nim's VM or JavaScript avr ## AVR based processor @@ -72,6 +73,7 @@ const elif defined(mips): CpuPlatform.mips elif defined(mipsel): CpuPlatform.mipsel elif defined(arm): CpuPlatform.arm + elif defined(arm64): CpuPlatform.arm64 elif defined(vm): CpuPlatform.vm elif defined(avr): CpuPlatform.avr else: CpuPlatform.none From 9804033aa8f719e2b8cf74be76c4b693e8ea3ba9 Mon Sep 17 00:00:00 2001 From: def Date: Sat, 1 Aug 2015 00:00:51 +0200 Subject: [PATCH 14/28] Add new platforms to installer.ini (for linux at least) --- compiler/installer.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/installer.ini b/compiler/installer.ini index 1ca615153..f92d4a3eb 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -6,7 +6,7 @@ Name: "Nim" Version: "$version" Platforms: """ windows: i386;amd64 - linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc + linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc;powerpc64el;arm64;mipsel macosx: i386;amd64;powerpc64 solaris: i386;amd64;sparc freebsd: i386;amd64 From 92ca736f0ac2e3b8c66516fb22ce8c5fbdac69d5 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 1 Aug 2015 13:43:51 +0100 Subject: [PATCH 15/28] Removed duplicate 'mipsel' from installer.ini. Ref #3164. --- compiler/installer.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/installer.ini b/compiler/installer.ini index f92d4a3eb..c8af38886 100644 --- a/compiler/installer.ini +++ b/compiler/installer.ini @@ -6,7 +6,7 @@ Name: "Nim" Version: "$version" Platforms: """ windows: i386;amd64 - linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc;powerpc64el;arm64;mipsel + linux: i386;amd64;powerpc64;arm;sparc;mips;mipsel;powerpc;powerpc64el;arm64 macosx: i386;amd64;powerpc64 solaris: i386;amd64;sparc freebsd: i386;amd64 From 9dde0ae3ac6c97704f64e0dee0d55c1a49faaf4b Mon Sep 17 00:00:00 2001 From: jonathonf Date: Sat, 1 Aug 2015 20:53:37 +0100 Subject: [PATCH 16/28] Set correct Host in request header Ensure the correct destination hostname is used in the request, otherwise the request will fail in one of a number of interesting ways when using a proxy. Fixes https://github.com/nim-lang/Nim/issues/3166 --- lib/pure/httpclient.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index e6b8088c5..98687359b 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -402,7 +402,7 @@ proc request*(url: string, httpMethod: string, extraHeaders = "", headers.add(" HTTP/1.1\c\L") - add(headers, "Host: " & r.hostname & "\c\L") + add(headers, "Host: " & parseUri(url).hostname & "\c\L") if userAgent != "": add(headers, "User-Agent: " & userAgent & "\c\L") if proxy != nil and proxy.auth != "": From 9275d5c6178e7674882dbbaa257f6bb2b5a7b6bf Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 00:05:56 +0200 Subject: [PATCH 17/28] emerald project has a chance of working --- compiler/vm.nim | 9 +++++---- compiler/vmgen.nim | 27 ++++++++++++++++++--------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 40d273ceb..3166ba726 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -120,10 +120,10 @@ template decodeBx(k: expr) {.immediate, dirty.} = template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b) # XXX fix minor 'shallowCopy' overloading bug in compiler -proc createStrKeepNode(x: var TFullReg) = +proc createStrKeepNode(x: var TFullReg; keepNode=true) = if x.node.isNil: x.node = newNode(nkStrLit) - elif x.node.kind == nkNilLit: + elif x.node.kind == nkNilLit and keepNode: when defined(useNodeIds): let id = x.node.id system.reset(x.node[]) @@ -385,6 +385,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = #if c.traceActive: # echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra # message(c.debug[pc], warnUser, "Trace") + case instr.opcode of opcEof: return regs[ra] of opcRet: @@ -407,8 +408,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = decodeB(rkInt) regs[ra].intVal = regs[rb].intVal of opcAsgnStr: - decodeB(rkNode) - createStrKeepNode regs[ra] + decodeBC(rkNode) + createStrKeepNode regs[ra], rc != 0 regs[ra].node.strVal = regs[rb].node.strVal of opcAsgnFloat: decodeB(rkFloat) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 7abcbdb92..1bee9788a 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -74,8 +74,9 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) = result.addf("\t$#\tr$#, L$#", ($opc).substr(3), x.regA, i+x.regBx-wordExcess) elif opc in {opcLdConst, opcAsgnConst}: - result.addf("\t$#\tr$#, $#", ($opc).substr(3), x.regA, - c.constants[x.regBx-wordExcess].renderTree) + let idx = x.regBx-wordExcess + result.addf("\t$#\tr$#, $# ($#)", ($opc).substr(3), x.regA, + c.constants[idx].renderTree, $idx) elif opc in {opcMarshalLoad, opcMarshalStore}: let y = c.code[i+1] result.addf("\t$#\tr$#, r$#, $#", ($opc).substr(3), x.regA, x.regB, @@ -184,7 +185,7 @@ proc getTemp(cc: PCtx; typ: PType): TRegister = return TRegister(i) # if register pressure is high, we re-use more aggressively: - if c.maxSlots >= HighRegisterPressure: + if c.maxSlots >= HighRegisterPressure and false: for i in 0 .. c.maxSlots-1: if not c.slots[i].inUse: c.slots[i] = (inUse: true, kind: k) @@ -1073,6 +1074,7 @@ const tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64} proc fitsRegister*(t: PType): bool = + assert t != nil t.skipTypes(abstractInst-{tyTypeDesc}).kind in { tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar} @@ -1110,6 +1112,7 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode; if dest < 0: dest = c.getTemp(n.typ) if not isAddr: gABC(c, n, opc, dest, tmp) + assert n.typ != nil if gfAddrOf notin flags and fitsRegister(n.typ): c.gABC(n, opcNodeToReg, dest, dest) elif c.prc.slots[tmp].kind >= slotTempUnknown: @@ -1143,7 +1146,7 @@ proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode = opc proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) = let tmp = c.genx(ri) assert dest >= 0 - gABC(c, ri, whichAsgnOpc(ri), dest, tmp) + gABC(c, ri, whichAsgnOpc(ri), dest, tmp, 1-ord(requiresCopy)) c.freeTemp(tmp) proc setSlot(c: PCtx; v: PSym) = @@ -1194,9 +1197,10 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode; # opcLdObj et al really means "load address". We sometimes have to create a # copy in order to not introduce false aliasing: # mylocal = a.b # needs a copy of the data! + assert n.typ != nil if needsAdditionalCopy(n): var cc = c.getTemp(n.typ) - c.gABC(n, whichAsgnOpc(n), cc, value) + c.gABC(n, whichAsgnOpc(n), cc, value, 0) c.gABC(n, opc, dest, idx, cc) c.freeTemp(cc) else: @@ -1241,10 +1245,11 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) = internalAssert s.position > 0 or (s.position == 0 and s.kind in {skParam,skResult}) var dest: TRegister = s.position + ord(s.kind == skParam) + assert le.typ != nil if needsAdditionalCopy(le) and s.kind in {skResult, skVar, skParam}: var cc = c.getTemp(le.typ) gen(c, ri, cc) - c.gABC(le, whichAsgnOpc(le), dest, cc) + c.gABC(le, whichAsgnOpc(le), dest, cc, 1) c.freeTemp(cc) else: gen(c, ri, dest) @@ -1303,6 +1308,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) = if sfImportc in s.flags: c.importcSym(n.info, s) else: genGlobalInit(c, n, s) if dest < 0: dest = c.getTemp(n.typ) + assert s.typ != nil if gfAddrOf notin flags and fitsRegister(s.typ): var cc = c.getTemp(n.typ) c.gABx(n, opcLdGlobal, cc, s.position) @@ -1426,6 +1432,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = globalError(info, "cannot create null element for: " & $t.kind) proc ldNullOpcode(t: PType): TOpcode = + assert t != nil if fitsRegister(t): opcLdNullReg else: opcLdNull proc genVarSection(c: PCtx; n: PNode) = @@ -1453,7 +1460,7 @@ proc genVarSection(c: PCtx; n: PNode) = if a.sons[2].kind != nkEmpty: let tmp = c.genx(a.sons[0], {gfAddrOf}) let val = c.genx(a.sons[2]) - c.preventFalseAlias(a, opcWrDeref, tmp, 0, val) + c.preventFalseAlias(a.sons[2], opcWrDeref, tmp, 0, val) c.freeTemp(val) c.freeTemp(tmp) else: @@ -1461,13 +1468,15 @@ proc genVarSection(c: PCtx; n: PNode) = if a.sons[2].kind == nkEmpty: c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ)) else: + assert s.typ != nil if not fitsRegister(s.typ): c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ)) let le = a.sons[0] + assert le.typ != nil if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}: var cc = c.getTemp(le.typ) gen(c, a.sons[2], cc) - c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc) + c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc, 1) c.freeTemp(cc) else: gen(c, a.sons[2], s.position.TRegister) @@ -1694,7 +1703,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = c.freeTemp(tmp1) c.freeTemp(tmp2) if dest >= 0: - gABC(c, n, whichAsgnOpc(n), dest, tmp0) + gABC(c, n, whichAsgnOpc(n), dest, tmp0, 1) c.freeTemp(tmp0) else: dest = tmp0 From bd786812e7fd1cbd1b7a8f038000ac06ad08505e Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 00:35:02 +0200 Subject: [PATCH 18/28] fixes #3171 --- compiler/pragmas.nim | 546 ++++++++++++++++--------------- tests/pragmas/tsym_as_pragma.nim | 8 + 2 files changed, 282 insertions(+), 272 deletions(-) create mode 100644 tests/pragmas/tsym_as_pragma.nim diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index c771155af..128a90138 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -591,280 +591,282 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, validPragmas: TSpecialWords): bool = var it = n.sons[i] var key = if it.kind == nkExprColonExpr: it.sons[0] else: it - if key.kind == nkIdent: - var userPragma = strTableGet(c.userPragmas, key.ident) - if userPragma != nil: - inc c.instCounter - if c.instCounter > 100: - globalError(it.info, errRecursiveDependencyX, userPragma.name.s) - pragma(c, sym, userPragma.ast, validPragmas) - # ensure the pragma is also remember for generic instantiations in other - # modules: - n.sons[i] = userPragma.ast - dec c.instCounter - else: - var k = whichKeyword(key.ident) - if k in validPragmas: - case k - of wExportc: - makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info) - incl(sym.flags, sfUsed) # avoid wrong hints - of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1")) - of wImportCompilerProc: - processImportCompilerProc(sym, getOptionalStr(c, it, "$1")) - of wExtern: setExternName(sym, expectStrLit(c, it)) - of wImmediate: - if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) - else: invalidPragma(it) - of wDirty: - if sym.kind == skTemplate: incl(sym.flags, sfDirty) - else: invalidPragma(it) - of wImportCpp: - processImportCpp(sym, getOptionalStr(c, it, "$1")) - of wImportObjC: - processImportObjC(sym, getOptionalStr(c, it, "$1")) - of wAlign: - if sym.typ == nil: invalidPragma(it) - var align = expectIntLit(c, it) - if (not isPowerOfTwo(align) and align != 0) or align >% high(int16): - localError(it.info, errPowerOfTwoExpected) - else: - sym.typ.align = align.int16 - of wSize: - if sym.typ == nil: invalidPragma(it) - var size = expectIntLit(c, it) - if not isPowerOfTwo(size) or size <= 0 or size > 8: - localError(it.info, errPowerOfTwoExpected) - else: - sym.typ.size = size - of wNodecl: - noVal(it) - incl(sym.loc.flags, lfNoDecl) - of wPure, wAsmNoStackFrame: - noVal(it) - if sym != nil: - if k == wPure and sym.kind in routineKinds: invalidPragma(it) - else: incl(sym.flags, sfPure) - of wVolatile: - noVal(it) - incl(sym.flags, sfVolatile) - of wRegister: - noVal(it) - incl(sym.flags, sfRegister) - of wThreadVar: - noVal(it) - incl(sym.flags, sfThread) - of wDeadCodeElim: pragmaDeadCodeElim(c, it) - of wNoForward: pragmaNoForward(c, it) - of wMagic: processMagic(c, it, sym) - of wCompileTime: - noVal(it) - incl(sym.flags, sfCompileTime) - incl(sym.loc.flags, lfNoDecl) - of wGlobal: - noVal(it) - incl(sym.flags, sfGlobal) - incl(sym.flags, sfPure) - of wMerge: - # only supported for backwards compat, doesn't do anything anymore - noVal(it) - of wConstructor: - noVal(it) - incl(sym.flags, sfConstructor) - of wHeader: - var lib = getLib(c, libHeader, getStrLitNode(c, it)) - addToLib(lib, sym) - incl(sym.flags, sfImportc) - incl(sym.loc.flags, lfHeader) - incl(sym.loc.flags, lfNoDecl) - # implies nodecl, because otherwise header would not make sense - if sym.loc.r == nil: sym.loc.r = rope(sym.name.s) - of wDestructor: - sym.flags.incl sfOverriden - if sym.name.s.normalize != "destroy": - localError(n.info, errGenerated, "destructor has to be named 'destroy'") - of wOverride: - sym.flags.incl sfOverriden - of wNosideeffect: - noVal(it) - incl(sym.flags, sfNoSideEffect) - if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) - of wSideeffect: - noVal(it) - incl(sym.flags, sfSideEffect) - of wNoreturn: - noVal(it) - incl(sym.flags, sfNoReturn) - of wDynlib: - processDynLib(c, it, sym) - of wCompilerproc: - noVal(it) # compilerproc may not get a string! - if sfFromGeneric notin sym.flags: markCompilerProc(sym) - of wProcVar: - noVal(it) - incl(sym.flags, sfProcvar) - of wDeprecated: - if it.kind == nkExprColonExpr: deprecatedStmt(c, it) - elif sym != nil: incl(sym.flags, sfDeprecated) - else: incl(c.module.flags, sfDeprecated) - of wVarargs: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfVarargs) - of wBorrow: - if sym.kind == skType: - typeBorrow(sym, it) - else: - noVal(it) - incl(sym.flags, sfBorrow) - of wFinal: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfFinal) - of wInheritable: - noVal(it) - if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) - else: incl(sym.typ.flags, tfInheritable) - of wAcyclic: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfAcyclic) - of wShallow: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfShallow) - of wThread: - noVal(it) - incl(sym.flags, sfThread) - incl(sym.flags, sfProcvar) - if sym.typ != nil: incl(sym.typ.flags, tfThread) - of wGcSafe: - noVal(it) - if sym.kind != skType: incl(sym.flags, sfThread) - if sym.typ != nil: incl(sym.typ.flags, tfGcSafe) - else: invalidPragma(it) - of wPacked: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfPacked) - of wHint: message(it.info, hintUser, expectStrLit(c, it)) - of wWarning: message(it.info, warnUser, expectStrLit(c, it)) - of wError: - if sym != nil and sym.isRoutine: - # This is subtle but correct: the error *statement* is only - # allowed for top level statements. Seems to be easier than - # distinguishing properly between - # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` - noVal(it) - incl(sym.flags, sfError) - else: - localError(it.info, errUser, expectStrLit(c, it)) - of wFatal: fatal(it.info, errUser, expectStrLit(c, it)) - of wDefine: processDefine(c, it) - of wUndef: processUndef(c, it) - of wCompile: processCompile(c, it) - of wLink: processCommonLink(c, it, linkNormal) - of wLinksys: processCommonLink(c, it, linkSys) - of wPassl: extccomp.addLinkOption(expectStrLit(c, it)) - of wPassc: extccomp.addCompileOption(expectStrLit(c, it)) - of wBreakpoint: pragmaBreakpoint(c, it) - of wWatchPoint: pragmaWatchpoint(c, it) - of wPush: - processPush(c, n, i + 1) - result = true - of wPop: processPop(c, it) - of wPragma: - processPragma(c, n, i) - result = true - of wDiscardable: - noVal(it) - if sym != nil: incl(sym.flags, sfDiscardable) - of wNoInit: - noVal(it) - if sym != nil: incl(sym.flags, sfNoInit) - of wCodegenDecl: processCodegenDecl(c, it, sym) - of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, - wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, - wLinedir, wStacktrace, wLinetrace, wOptimization, - wCallconv, - wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks, - wPatterns: - if processOption(c, it): - # calling conventions (boring...): - localError(it.info, errOptionExpected) - of FirstCallConv..LastCallConv: - assert(sym != nil) - if sym.typ == nil: invalidPragma(it) - else: sym.typ.callConv = wordToCallConv(k) - of wEmit: pragmaEmit(c, it) - of wUnroll: pragmaUnroll(c, it) - of wLinearScanEnd, wComputedGoto: noVal(it) - of wEffects: - # is later processed in effect analysis: - noVal(it) - of wIncompleteStruct: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfIncompleteStruct) - of wUnchecked: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfUncheckedArray) - of wUnion: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfUnion) - of wRequiresInit: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfNeedsInit) - of wByRef: - noVal(it) - if sym == nil or sym.typ == nil: - if processOption(c, it): localError(it.info, errOptionExpected) - else: - incl(sym.typ.flags, tfByRef) - of wByCopy: - noVal(it) - if sym.kind != skType or sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfByCopy) - of wInject, wGensym: - # We check for errors, but do nothing with these pragmas otherwise - # as they are handled directly in 'evalTemplate'. - noVal(it) - if sym == nil: invalidPragma(it) - of wLine: pragmaLine(c, it) - of wRaises, wTags: pragmaRaisesOrTags(c, it) - of wLocks: - if sym == nil: pragmaLockStmt(c, it) - elif sym.typ == nil: invalidPragma(it) - else: sym.typ.lockLevel = pragmaLocks(c, it) - of wGuard: - if sym == nil or sym.kind notin {skVar, skLet, skField}: - invalidPragma(it) - else: - sym.guard = pragmaGuard(c, it, sym.kind) - of wGoto: - if sym == nil or sym.kind notin {skVar, skLet}: - invalidPragma(it) - else: - sym.flags.incl sfGoto - of wInjectStmt: - if it.kind != nkExprColonExpr: - localError(it.info, errExprExpected) - else: - it.sons[1] = c.semExpr(c, it.sons[1]) - of wExperimental: - noVal(it) - if isTopLevel(c): - c.module.flags.incl sfExperimental - else: - localError(it.info, "'experimental' pragma only valid as toplevel statement") - of wNoRewrite: - noVal(it) + if key.kind == nkBracketExpr: + processNote(c, it) + return + let ident = considerQuotedIdent(key) + var userPragma = strTableGet(c.userPragmas, ident) + if userPragma != nil: + inc c.instCounter + if c.instCounter > 100: + globalError(it.info, errRecursiveDependencyX, userPragma.name.s) + pragma(c, sym, userPragma.ast, validPragmas) + # ensure the pragma is also remember for generic instantiations in other + # modules: + n.sons[i] = userPragma.ast + dec c.instCounter + else: + var k = whichKeyword(ident) + if k in validPragmas: + case k + of wExportc: + makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info) + incl(sym.flags, sfUsed) # avoid wrong hints + of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1")) + of wImportCompilerProc: + processImportCompilerProc(sym, getOptionalStr(c, it, "$1")) + of wExtern: setExternName(sym, expectStrLit(c, it)) + of wImmediate: + if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) else: invalidPragma(it) + of wDirty: + if sym.kind == skTemplate: incl(sym.flags, sfDirty) + else: invalidPragma(it) + of wImportCpp: + processImportCpp(sym, getOptionalStr(c, it, "$1")) + of wImportObjC: + processImportObjC(sym, getOptionalStr(c, it, "$1")) + of wAlign: + if sym.typ == nil: invalidPragma(it) + var align = expectIntLit(c, it) + if (not isPowerOfTwo(align) and align != 0) or align >% high(int16): + localError(it.info, errPowerOfTwoExpected) + else: + sym.typ.align = align.int16 + of wSize: + if sym.typ == nil: invalidPragma(it) + var size = expectIntLit(c, it) + if not isPowerOfTwo(size) or size <= 0 or size > 8: + localError(it.info, errPowerOfTwoExpected) + else: + sym.typ.size = size + of wNodecl: + noVal(it) + incl(sym.loc.flags, lfNoDecl) + of wPure, wAsmNoStackFrame: + noVal(it) + if sym != nil: + if k == wPure and sym.kind in routineKinds: invalidPragma(it) + else: incl(sym.flags, sfPure) + of wVolatile: + noVal(it) + incl(sym.flags, sfVolatile) + of wRegister: + noVal(it) + incl(sym.flags, sfRegister) + of wThreadVar: + noVal(it) + incl(sym.flags, sfThread) + of wDeadCodeElim: pragmaDeadCodeElim(c, it) + of wNoForward: pragmaNoForward(c, it) + of wMagic: processMagic(c, it, sym) + of wCompileTime: + noVal(it) + incl(sym.flags, sfCompileTime) + incl(sym.loc.flags, lfNoDecl) + of wGlobal: + noVal(it) + incl(sym.flags, sfGlobal) + incl(sym.flags, sfPure) + of wMerge: + # only supported for backwards compat, doesn't do anything anymore + noVal(it) + of wConstructor: + noVal(it) + incl(sym.flags, sfConstructor) + of wHeader: + var lib = getLib(c, libHeader, getStrLitNode(c, it)) + addToLib(lib, sym) + incl(sym.flags, sfImportc) + incl(sym.loc.flags, lfHeader) + incl(sym.loc.flags, lfNoDecl) + # implies nodecl, because otherwise header would not make sense + if sym.loc.r == nil: sym.loc.r = rope(sym.name.s) + of wDestructor: + sym.flags.incl sfOverriden + if sym.name.s.normalize != "destroy": + localError(n.info, errGenerated, "destructor has to be named 'destroy'") + of wOverride: + sym.flags.incl sfOverriden + of wNosideeffect: + noVal(it) + incl(sym.flags, sfNoSideEffect) + if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) + of wSideeffect: + noVal(it) + incl(sym.flags, sfSideEffect) + of wNoreturn: + noVal(it) + incl(sym.flags, sfNoReturn) + of wDynlib: + processDynLib(c, it, sym) + of wCompilerproc: + noVal(it) # compilerproc may not get a string! + if sfFromGeneric notin sym.flags: markCompilerProc(sym) + of wProcVar: + noVal(it) + incl(sym.flags, sfProcvar) + of wDeprecated: + if it.kind == nkExprColonExpr: deprecatedStmt(c, it) + elif sym != nil: incl(sym.flags, sfDeprecated) + else: incl(c.module.flags, sfDeprecated) + of wVarargs: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfVarargs) + of wBorrow: + if sym.kind == skType: + typeBorrow(sym, it) + else: + noVal(it) + incl(sym.flags, sfBorrow) + of wFinal: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfFinal) + of wInheritable: + noVal(it) + if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) + else: incl(sym.typ.flags, tfInheritable) + of wAcyclic: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfAcyclic) + of wShallow: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfShallow) + of wThread: + noVal(it) + incl(sym.flags, sfThread) + incl(sym.flags, sfProcvar) + if sym.typ != nil: incl(sym.typ.flags, tfThread) + of wGcSafe: + noVal(it) + if sym.kind != skType: incl(sym.flags, sfThread) + if sym.typ != nil: incl(sym.typ.flags, tfGcSafe) + else: invalidPragma(it) + of wPacked: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfPacked) + of wHint: message(it.info, hintUser, expectStrLit(c, it)) + of wWarning: message(it.info, warnUser, expectStrLit(c, it)) + of wError: + if sym != nil and sym.isRoutine: + # This is subtle but correct: the error *statement* is only + # allowed for top level statements. Seems to be easier than + # distinguishing properly between + # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` + noVal(it) + incl(sym.flags, sfError) + else: + localError(it.info, errUser, expectStrLit(c, it)) + of wFatal: fatal(it.info, errUser, expectStrLit(c, it)) + of wDefine: processDefine(c, it) + of wUndef: processUndef(c, it) + of wCompile: processCompile(c, it) + of wLink: processCommonLink(c, it, linkNormal) + of wLinksys: processCommonLink(c, it, linkSys) + of wPassl: extccomp.addLinkOption(expectStrLit(c, it)) + of wPassc: extccomp.addCompileOption(expectStrLit(c, it)) + of wBreakpoint: pragmaBreakpoint(c, it) + of wWatchPoint: pragmaWatchpoint(c, it) + of wPush: + processPush(c, n, i + 1) + result = true + of wPop: processPop(c, it) + of wPragma: + processPragma(c, n, i) + result = true + of wDiscardable: + noVal(it) + if sym != nil: incl(sym.flags, sfDiscardable) + of wNoInit: + noVal(it) + if sym != nil: incl(sym.flags, sfNoInit) + of wCodegenDecl: processCodegenDecl(c, it, sym) + of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, + wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, + wLinedir, wStacktrace, wLinetrace, wOptimization, + wCallconv, + wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks, + wPatterns: + if processOption(c, it): + # calling conventions (boring...): + localError(it.info, errOptionExpected) + of FirstCallConv..LastCallConv: + assert(sym != nil) + if sym.typ == nil: invalidPragma(it) + else: sym.typ.callConv = wordToCallConv(k) + of wEmit: pragmaEmit(c, it) + of wUnroll: pragmaUnroll(c, it) + of wLinearScanEnd, wComputedGoto: noVal(it) + of wEffects: + # is later processed in effect analysis: + noVal(it) + of wIncompleteStruct: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfIncompleteStruct) + of wUnchecked: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfUncheckedArray) + of wUnion: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfUnion) + of wRequiresInit: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfNeedsInit) + of wByRef: + noVal(it) + if sym == nil or sym.typ == nil: + if processOption(c, it): localError(it.info, errOptionExpected) + else: + incl(sym.typ.flags, tfByRef) + of wByCopy: + noVal(it) + if sym.kind != skType or sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfByCopy) + of wInject, wGensym: + # We check for errors, but do nothing with these pragmas otherwise + # as they are handled directly in 'evalTemplate'. + noVal(it) + if sym == nil: invalidPragma(it) + of wLine: pragmaLine(c, it) + of wRaises, wTags: pragmaRaisesOrTags(c, it) + of wLocks: + if sym == nil: pragmaLockStmt(c, it) + elif sym.typ == nil: invalidPragma(it) + else: sym.typ.lockLevel = pragmaLocks(c, it) + of wGuard: + if sym == nil or sym.kind notin {skVar, skLet, skField}: + invalidPragma(it) + else: + sym.guard = pragmaGuard(c, it, sym.kind) + of wGoto: + if sym == nil or sym.kind notin {skVar, skLet}: + invalidPragma(it) + else: + sym.flags.incl sfGoto + of wInjectStmt: + if it.kind != nkExprColonExpr: + localError(it.info, errExprExpected) + else: + it.sons[1] = c.semExpr(c, it.sons[1]) + of wExperimental: + noVal(it) + if isTopLevel(c): + c.module.flags.incl sfExperimental + else: + localError(it.info, "'experimental' pragma only valid as toplevel statement") + of wNoRewrite: + noVal(it) else: invalidPragma(it) - else: processNote(c, it) + else: invalidPragma(it) proc implicitPragmas*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = diff --git a/tests/pragmas/tsym_as_pragma.nim b/tests/pragmas/tsym_as_pragma.nim new file mode 100644 index 000000000..f6ba44dc9 --- /dev/null +++ b/tests/pragmas/tsym_as_pragma.nim @@ -0,0 +1,8 @@ + +# bug #3171 + +template newDataWindow(): stmt = + let eventClosure = proc (closure: pointer): bool {.closure, cdecl.} = + discard + +newDataWindow() From 5e325bc9f9be68841ce1aef6b64aada2aeb52918 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 01:16:47 +0200 Subject: [PATCH 19/28] made test green again --- tests/template/t_otemplates.nim | 678 ++++++++++++++++---------------- 1 file changed, 339 insertions(+), 339 deletions(-) diff --git a/tests/template/t_otemplates.nim b/tests/template/t_otemplates.nim index db535d818..6c419f72f 100644 --- a/tests/template/t_otemplates.nim +++ b/tests/template/t_otemplates.nim @@ -2,344 +2,344 @@ discard """ output: "Success" """ -# Ref: -# http://nim-lang.org/macros.html -# http://nim-lang.org/parseutils.html - - -# Imports -import tables, parseutils, macros, strutils -import annotate -export annotate - - -# Fields -const identChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} - - -# Procedure Declarations -proc parse_template(node: NimNode, value: string) {.compiletime.} - - -# Procedure Definitions -proc substring(value: string, index: int, length = -1): string {.compiletime.} = - ## Returns a string at most `length` characters long, starting at `index`. - return if length < 0: value.substr(index) - elif length == 0: "" - else: value.substr(index, index + length-1) - - -proc parse_thru_eol(value: string, index: int): int {.compiletime.} = - ## Reads until and past the end of the current line, unless - ## a non-whitespace character is encountered first - var remainder: string - var read = value.parseUntil(remainder, {0x0A.char}, index) - if remainder.skipWhitespace() == read: - return read + 1 - - -proc trim_after_eol(value: var string) {.compiletime.} = - ## Trims any whitespace at end after \n - var toTrim = 0 - for i in countdown(value.len-1, 0): - # If \n, return - if value[i] in [' ', '\t']: inc(toTrim) - else: break - - if toTrim > 0: - value = value.substring(0, value.len - toTrim) - - -proc trim_eol(value: var string) {.compiletime.} = - ## Removes everything after the last line if it contains nothing but whitespace - for i in countdown(value.len - 1, 0): - # If \n, trim and return - if value[i] == 0x0A.char: - value = value.substr(0, i) - break - - # This is the first character - if i == 0: - value = "" - break - - # Skip change - if not (value[i] in [' ', '\t']): break - - -proc detect_indent(value: string, index: int): int {.compiletime.} = - ## Detects how indented the line at `index` is. - # Seek to the beginning of the line. - var lastChar = index - for i in countdown(index, 0): - if value[i] == 0x0A.char: - # if \n, return the indentation level - return lastChar - i - elif not (value[i] in [' ', '\t']): - # if non-whitespace char, decrement lastChar - dec(lastChar) - - -proc parse_thru_string(value: string, i: var int, strType = '"') {.compiletime.} = - ## Parses until ending " or ' is reached. - inc(i) - if i < value.len-1: - inc(i, value.skipUntil({'\\', strType}, i)) - - -proc parse_to_close(value: string, index: int, open='(', close=')', opened=0): int {.compiletime.} = - ## Reads until all opened braces are closed - ## ignoring any strings "" or '' - var remainder = value.substring(index) - var open_braces = opened - result = 0 - - while result < remainder.len: - var c = remainder[result] - - if c == open: inc(open_braces) - elif c == close: dec(open_braces) - elif c == '"': remainder.parse_thru_string(result) - elif c == '\'': remainder.parse_thru_string(result, '\'') - - if open_braces == 0: break - else: inc(result) - - -iterator parse_stmt_list(value: string, index: var int): string = - ## Parses unguided ${..} block - var read = value.parse_to_close(index, open='{', close='}') - var expressions = value.substring(index + 1, read - 1).split({ ';', 0x0A.char }) - - for expression in expressions: - let value = expression.strip - if value.len > 0: - yield value - - #Increment index & parse thru EOL - inc(index, read + 1) - inc(index, value.parse_thru_eol(index)) - - -iterator parse_compound_statements(value, identifier: string, index: int): string = - ## Parses through several statements, i.e. if {} elif {} else {} - ## and returns the initialization of each as an empty statement - ## i.e. if x == 5 { ... } becomes if x == 5: nil. - - template get_next_ident(expected): stmt = - var nextIdent: string - discard value.parseWhile(nextIdent, {'$'} + identChars, i) - - var next: string - var read: int - - if nextIdent == "case": - # We have to handle case a bit differently - read = value.parseUntil(next, '$', i) - inc(i, read) - yield next.strip(leading=false) & "\n" - - else: - read = value.parseUntil(next, '{', i) - - if nextIdent in expected: - inc(i, read) - # Parse until closing }, then skip whitespace afterwards - read = value.parse_to_close(i, open='{', close='}') - inc(i, read + 1) - inc(i, value.skipWhitespace(i)) - yield next & ": nil\n" - - else: break - - - var i = index - while true: - # Check if next statement would be valid, given the identifier - if identifier in ["if", "when"]: - get_next_ident([identifier, "$elif", "$else"]) - - elif identifier == "case": - get_next_ident(["case", "$of", "$elif", "$else"]) - - elif identifier == "try": - get_next_ident(["try", "$except", "$finally"]) - - -proc parse_complex_stmt(value, identifier: string, index: var int): NimNode {.compiletime.} = - ## Parses if/when/try /elif /else /except /finally statements - - # Build up complex statement string - var stmtString = newString(0) - var numStatements = 0 - for statement in value.parse_compound_statements(identifier, index): - if statement[0] == '$': stmtString.add(statement.substr(1)) - else: stmtString.add(statement) - inc(numStatements) - - # Parse stmt string - result = parseExpr(stmtString) - - var resultIndex = 0 - - # Fast forward a bit if this is a case statement - if identifier == "case": - inc(resultIndex) - - while resultIndex < numStatements: - - # Detect indentation - let indent = detect_indent(value, index) - - # Parse until an open brace `{` - var read = value.skipUntil('{', index) - inc(index, read + 1) - - # Parse through EOL - inc(index, value.parse_thru_eol(index)) - - # Parse through { .. } - read = value.parse_to_close(index, open='{', close='}', opened=1) - - # Add parsed sub-expression into body - var body = newStmtList() - var stmtString = value.substring(index, read) - trim_after_eol(stmtString) - stmtString = reindent(stmtString, indent) - parse_template(body, stmtString) - inc(index, read + 1) - - # Insert body into result - var stmtIndex = macros.high(result[resultIndex]) - result[resultIndex][stmtIndex] = body - - # Parse through EOL again & increment result index - inc(index, value.parse_thru_eol(index)) - inc(resultIndex) - - -proc parse_simple_statement(value: string, index: var int): NimNode {.compiletime.} = - ## Parses for/while - - # Detect indentation - let indent = detect_indent(value, index) - - # Parse until an open brace `{` - var splitValue: string - var read = value.parseUntil(splitValue, '{', index) - result = parseExpr(splitValue & ":nil") - inc(index, read + 1) - - # Parse through EOL - inc(index, value.parse_thru_eol(index)) - - # Parse through { .. } - read = value.parse_to_close(index, open='{', close='}', opened=1) - - # Add parsed sub-expression into body - var body = newStmtList() - var stmtString = value.substring(index, read) - trim_after_eol(stmtString) - stmtString = reindent(stmtString, indent) - parse_template(body, stmtString) - inc(index, read + 1) - - # Insert body into result - var stmtIndex = macros.high(result) - result[stmtIndex] = body - - # Parse through EOL again - inc(index, value.parse_thru_eol(index)) - - -proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} = - ## Parses a string until a $ symbol is encountered, if - ## two $$'s are encountered in a row, a split will happen - ## removing one of the $'s from the resulting output - var splitValue: string - var read = value.parseUntil(splitValue, '$', index) - var insertionPoint = node.len - - inc(index, read + 1) - if index < value.len: - - case value[index] - of '$': - # Check for duplicate `$`, meaning this is an escaped $ - node.add newCall("add", ident("result"), newStrLitNode("$")) - inc(index) - - of '(': - # Check for open `(`, which means parse as simple single-line expression. - trim_eol(splitValue) - read = value.parse_to_close(index) + 1 - node.add newCall("add", ident("result"), - newCall(bindSym"strip", parseExpr("$" & value.substring(index, read))) - ) - inc(index, read) - - of '{': - # Check for open `{`, which means open statement list - trim_eol(splitValue) - for s in value.parse_stmt_list(index): - node.add parseExpr(s) - - else: - # Otherwise parse while valid `identChars` and make expression w/ $ - var identifier: string - read = value.parseWhile(identifier, identChars, index) - - if identifier in ["for", "while"]: - ## for/while means open simple statement - trim_eol(splitValue) - node.add value.parse_simple_statement(index) - - elif identifier in ["if", "when", "case", "try"]: - ## if/when/case/try means complex statement - trim_eol(splitValue) - node.add value.parse_complex_stmt(identifier, index) - - elif identifier.len > 0: - ## Treat as simple variable - node.add newCall("add", ident("result"), newCall("$", ident(identifier))) - inc(index, read) - - result = true - - # Insert - if splitValue.len > 0: - node.insert insertionPoint, newCall("add", ident("result"), newStrLitNode(splitValue)) - - -proc parse_template(node: NimNode, value: string) = - ## Parses through entire template, outputing valid - ## Nim code into the input `node` AST. - var index = 0 - while index < value.len and - parse_until_symbol(node, value, index): nil - - -macro tmpli*(body: expr): stmt = - result = newStmtList() - - result.add parseExpr("result = \"\"") - - var value = if body.kind in nnkStrLit..nnkTripleStrLit: body.strVal - else: body[1].strVal - - parse_template(result, reindent(value)) - - -macro tmpl*(body: expr): stmt = - result = newStmtList() - - var value = if body.kind in nnkStrLit..nnkTripleStrLit: body.strVal - else: body[1].strVal - - parse_template(result, reindent(value)) - - -# Run tests -when isMainModule: +# Ref: +# http://nim-lang.org/macros.html +# http://nim-lang.org/parseutils.html + + +# Imports +import tables, parseutils, macros, strutils +import annotate +export annotate + + +# Fields +const identChars = {'a'..'z', 'A'..'Z', '0'..'9', '_'} + + +# Procedure Declarations +proc parse_template(node: NimNode, value: string) {.compiletime.} + + +# Procedure Definitions +proc substring(value: string, index: int, length = -1): string {.compiletime.} = + ## Returns a string at most `length` characters long, starting at `index`. + return if length < 0: value.substr(index) + elif length == 0: "" + else: value.substr(index, index + length-1) + + +proc parse_thru_eol(value: string, index: int): int {.compiletime.} = + ## Reads until and past the end of the current line, unless + ## a non-whitespace character is encountered first + var remainder: string + var read = value.parseUntil(remainder, {0x0A.char}, index) + if remainder.skipWhitespace() == read: + return read + 1 + + +proc trim_after_eol(value: var string) {.compiletime.} = + ## Trims any whitespace at end after \n + var toTrim = 0 + for i in countdown(value.len-1, 0): + # If \n, return + if value[i] in [' ', '\t']: inc(toTrim) + else: break + + if toTrim > 0: + value = value.substring(0, value.len - toTrim) + + +proc trim_eol(value: var string) {.compiletime.} = + ## Removes everything after the last line if it contains nothing but whitespace + for i in countdown(value.len - 1, 0): + # If \n, trim and return + if value[i] == 0x0A.char: + value = value.substr(0, i) + break + + # This is the first character + if i == 0: + value = "" + break + + # Skip change + if not (value[i] in [' ', '\t']): break + + +proc detect_indent(value: string, index: int): int {.compiletime.} = + ## Detects how indented the line at `index` is. + # Seek to the beginning of the line. + var lastChar = index + for i in countdown(index, 0): + if value[i] == 0x0A.char: + # if \n, return the indentation level + return lastChar - i + elif not (value[i] in [' ', '\t']): + # if non-whitespace char, decrement lastChar + dec(lastChar) + + +proc parse_thru_string(value: string, i: var int, strType = '"') {.compiletime.} = + ## Parses until ending " or ' is reached. + inc(i) + if i < value.len-1: + inc(i, value.skipUntil({'\\', strType}, i)) + + +proc parse_to_close(value: string, index: int, open='(', close=')', opened=0): int {.compiletime.} = + ## Reads until all opened braces are closed + ## ignoring any strings "" or '' + var remainder = value.substring(index) + var open_braces = opened + result = 0 + + while result < remainder.len: + var c = remainder[result] + + if c == open: inc(open_braces) + elif c == close: dec(open_braces) + elif c == '"': remainder.parse_thru_string(result) + elif c == '\'': remainder.parse_thru_string(result, '\'') + + if open_braces == 0: break + else: inc(result) + + +iterator parse_stmt_list(value: string, index: var int): string = + ## Parses unguided ${..} block + var read = value.parse_to_close(index, open='{', close='}') + var expressions = value.substring(index + 1, read - 1).split({ ';', 0x0A.char }) + + for expression in expressions: + let value = expression.strip + if value.len > 0: + yield value + + #Increment index & parse thru EOL + inc(index, read + 1) + inc(index, value.parse_thru_eol(index)) + + +iterator parse_compound_statements(value, identifier: string, index: int): string = + ## Parses through several statements, i.e. if {} elif {} else {} + ## and returns the initialization of each as an empty statement + ## i.e. if x == 5 { ... } becomes if x == 5: nil. + + template get_next_ident(expected): stmt = + var nextIdent: string + discard value.parseWhile(nextIdent, {'$'} + identChars, i) + + var next: string + var read: int + + if nextIdent == "case": + # We have to handle case a bit differently + read = value.parseUntil(next, '$', i) + inc(i, read) + yield next.strip(leading=false) & "\n" + + else: + read = value.parseUntil(next, '{', i) + + if nextIdent in expected: + inc(i, read) + # Parse until closing }, then skip whitespace afterwards + read = value.parse_to_close(i, open='{', close='}') + inc(i, read + 1) + inc(i, value.skipWhitespace(i)) + yield next & ": nil\n" + + else: break + + + var i = index + while true: + # Check if next statement would be valid, given the identifier + if identifier in ["if", "when"]: + get_next_ident([identifier, "$elif", "$else"]) + + elif identifier == "case": + get_next_ident(["case", "$of", "$elif", "$else"]) + + elif identifier == "try": + get_next_ident(["try", "$except", "$finally"]) + + +proc parse_complex_stmt(value, identifier: string, index: var int): NimNode {.compiletime.} = + ## Parses if/when/try /elif /else /except /finally statements + + # Build up complex statement string + var stmtString = newString(0) + var numStatements = 0 + for statement in value.parse_compound_statements(identifier, index): + if statement[0] == '$': stmtString.add(statement.substr(1)) + else: stmtString.add(statement) + inc(numStatements) + + # Parse stmt string + result = parseExpr(stmtString) + + var resultIndex = 0 + + # Fast forward a bit if this is a case statement + if identifier == "case": + inc(resultIndex) + + while resultIndex < numStatements: + + # Detect indentation + let indent = detect_indent(value, index) + + # Parse until an open brace `{` + var read = value.skipUntil('{', index) + inc(index, read + 1) + + # Parse through EOL + inc(index, value.parse_thru_eol(index)) + + # Parse through { .. } + read = value.parse_to_close(index, open='{', close='}', opened=1) + + # Add parsed sub-expression into body + var body = newStmtList() + var stmtString = value.substring(index, read) + trim_after_eol(stmtString) + stmtString = reindent(stmtString, indent) + parse_template(body, stmtString) + inc(index, read + 1) + + # Insert body into result + var stmtIndex = result[resultIndex].len-1 + result[resultIndex][stmtIndex] = body + + # Parse through EOL again & increment result index + inc(index, value.parse_thru_eol(index)) + inc(resultIndex) + + +proc parse_simple_statement(value: string, index: var int): NimNode {.compiletime.} = + ## Parses for/while + + # Detect indentation + let indent = detect_indent(value, index) + + # Parse until an open brace `{` + var splitValue: string + var read = value.parseUntil(splitValue, '{', index) + result = parseExpr(splitValue & ":nil") + inc(index, read + 1) + + # Parse through EOL + inc(index, value.parse_thru_eol(index)) + + # Parse through { .. } + read = value.parse_to_close(index, open='{', close='}', opened=1) + + # Add parsed sub-expression into body + var body = newStmtList() + var stmtString = value.substring(index, read) + trim_after_eol(stmtString) + stmtString = reindent(stmtString, indent) + parse_template(body, stmtString) + inc(index, read + 1) + + # Insert body into result + var stmtIndex = result.len-1 + result[stmtIndex] = body + + # Parse through EOL again + inc(index, value.parse_thru_eol(index)) + + +proc parse_until_symbol(node: NimNode, value: string, index: var int): bool {.compiletime.} = + ## Parses a string until a $ symbol is encountered, if + ## two $$'s are encountered in a row, a split will happen + ## removing one of the $'s from the resulting output + var splitValue: string + var read = value.parseUntil(splitValue, '$', index) + var insertionPoint = node.len + + inc(index, read + 1) + if index < value.len: + + case value[index] + of '$': + # Check for duplicate `$`, meaning this is an escaped $ + node.add newCall("add", ident("result"), newStrLitNode("$")) + inc(index) + + of '(': + # Check for open `(`, which means parse as simple single-line expression. + trim_eol(splitValue) + read = value.parse_to_close(index) + 1 + node.add newCall("add", ident("result"), + newCall(bindSym"strip", parseExpr("$" & value.substring(index, read))) + ) + inc(index, read) + + of '{': + # Check for open `{`, which means open statement list + trim_eol(splitValue) + for s in value.parse_stmt_list(index): + node.add parseExpr(s) + + else: + # Otherwise parse while valid `identChars` and make expression w/ $ + var identifier: string + read = value.parseWhile(identifier, identChars, index) + + if identifier in ["for", "while"]: + ## for/while means open simple statement + trim_eol(splitValue) + node.add value.parse_simple_statement(index) + + elif identifier in ["if", "when", "case", "try"]: + ## if/when/case/try means complex statement + trim_eol(splitValue) + node.add value.parse_complex_stmt(identifier, index) + + elif identifier.len > 0: + ## Treat as simple variable + node.add newCall("add", ident("result"), newCall("$", ident(identifier))) + inc(index, read) + + result = true + + # Insert + if splitValue.len > 0: + node.insert insertionPoint, newCall("add", ident("result"), newStrLitNode(splitValue)) + + +proc parse_template(node: NimNode, value: string) = + ## Parses through entire template, outputing valid + ## Nim code into the input `node` AST. + var index = 0 + while index < value.len and + parse_until_symbol(node, value, index): nil + + +macro tmpli*(body: expr): stmt = + result = newStmtList() + + result.add parseExpr("result = \"\"") + + var value = if body.kind in nnkStrLit..nnkTripleStrLit: body.strVal + else: body[1].strVal + + parse_template(result, reindent(value)) + + +macro tmpl*(body: expr): stmt = + result = newStmtList() + + var value = if body.kind in nnkStrLit..nnkTripleStrLit: body.strVal + else: body[1].strVal + + parse_template(result, reindent(value)) + + +# Run tests +when isMainModule: include otests echo "Success" From 41e8c9b9acc16f65166648aaba38408dad42e7bc Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 01:17:23 +0200 Subject: [PATCH 20/28] fixes #3158 --- compiler/sem.nim | 6 +++++- tests/template/twrongsymkind.nim | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/template/twrongsymkind.nim diff --git a/compiler/sem.nim b/compiler/sem.nim index d23dd1543..041524f84 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -171,11 +171,15 @@ proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = + proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLower + # like newSymS, but considers gensym'ed symbols if n.kind == nkSym: # and sfGenSym in n.sym.flags: result = n.sym - internalAssert result.kind == kind + if result.kind != kind: + localError(n.info, "cannot use symbol of kind '" & + $result.kind & "' as a '" & $kind & "'") # when there is a nested proc inside a template, semtmpl # will assign a wrong owner during the first pass over the # template; we must fix it here: see #909 diff --git a/tests/template/twrongsymkind.nim b/tests/template/twrongsymkind.nim new file mode 100644 index 000000000..be3d8c652 --- /dev/null +++ b/tests/template/twrongsymkind.nim @@ -0,0 +1,20 @@ +discard """ + errormsg: "cannot use symbol of kind 'var' as a 'param'" + line: 20 +""" + +# bug #3158 + +type + MyData = object + x: int + +template newDataWindow(data: ref MyData): stmt = + proc testProc(data: ref MyData) = + echo "Hello, ", data.x + testProc(data) + +var d: ref MyData +new(d) +d.x = 10 +newDataWindow(d) From e9899af9b20b1ac55c66b32a8ab354942ef2816f Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 01:42:41 +0200 Subject: [PATCH 21/28] fixes #3135 --- lib/system/sets.nim | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/system/sets.nim b/lib/system/sets.nim index 22d6d57c0..66877de30 100644 --- a/lib/system/sets.nim +++ b/lib/system/sets.nim @@ -19,9 +19,9 @@ proc countBits32(n: int32): int {.compilerproc.} = v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32) result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32 -proc countBits64(n: int64): int {.compilerproc.} = - result = countBits32(toU32(n and 0xffff'i64)) + - countBits32(toU32(n shr 16'i64)) +proc countBits64(n: int64): int {.compilerproc.} = + result = countBits32(toU32(n and 0xffffffff'i64)) + + countBits32(toU32(n shr 32'i64)) proc cardSet(s: NimSet, len: int): int {.compilerproc.} = result = 0 From ea35cede8e99b936c4a3003640844335001fe0b3 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 01:51:06 +0200 Subject: [PATCH 22/28] fixes #3103 --- compiler/vm.nim | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index 3166ba726..d7495d77f 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -510,8 +510,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of rkNode: if regs[rb].node.kind == nkNilLit: stackTrace(c, tos, pc, errNilAccess) - assert regs[rb].node.kind == nkRefTy - regs[ra].node = regs[rb].node.sons[0] + if regs[rb].node.kind == nkRefTy: + regs[ra].node = regs[rb].node.sons[0] + else: + stackTrace(c, tos, pc, errGenerated, "limited VM support for 'ref'") else: stackTrace(c, tos, pc, errNilAccess) of opcWrDeref: From f9750781c04cf0f2f278ef4ce8734ba9bc3e859c Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 02:16:45 +0200 Subject: [PATCH 23/28] fixes #3080 --- lib/system/repr.nim | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/system/repr.nim b/lib/system/repr.nim index 74396f424..b4188527f 100644 --- a/lib/system/repr.nim +++ b/lib/system/repr.nim @@ -256,7 +256,10 @@ when not defined(useNimRtl): of tyBool: add result, reprBool(cast[ptr bool](p)[]) of tyChar: add result, reprChar(cast[ptr char](p)[]) of tyString: reprStrAux(result, cast[ptr string](p)[]) - of tyCString: reprStrAux(result, $(cast[ptr cstring](p)[])) + of tyCString: + let cs = cast[ptr cstring](p)[] + if cs.isNil: add result, "nil" + else: reprStrAux(result, $cs) of tyRange: reprAux(result, p, typ.base, cl) of tyProc, tyPointer: if cast[PPointer](p)[] == nil: add result, "nil" From 1b4116702b411c82ccec4b558768689b2a1a0964 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 02:54:43 +0200 Subject: [PATCH 24/28] fixes #3052 --- compiler/semtypes.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index b518f0fb9..3bb1284fc 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -23,6 +23,9 @@ proc newConstraint(c: PContext, k: TTypeKind): PType = proc semEnum(c: PContext, n: PNode, prev: PType): PType = if n.sonsLen == 0: return newConstraint(c, tyEnum) + elif n.sonsLen == 1: + # don't create an empty tyEnum; fixes #3052 + return errorType(c) var counter, x: BiggestInt e: PSym From 4c1611fc13bbdc516fb08f1e12bf3a873489d705 Mon Sep 17 00:00:00 2001 From: singularperturbation Date: Sun, 2 Aug 2015 14:16:49 -0500 Subject: [PATCH 25/28] Fix for image directive with periods Saw in https://github.com/nim-lang/nimforum/issues/41 that there was an issue in rendering inline images. Traced back through rstgen and found that it was not counting something like: `.. image:: http://i.imgur.com/oCem13Y.png` as valid since it contained a period, and this wasn't in the set of valid characters, so the empty string is returned by default. Added a period to the allowable characters, and now renders correctly. Test case: ``` import rst, rstgen, strtabs var docConfig: StringTableRef docConfig = rstgen.defaultConfig() docConfig["doc.smiley_format"] = "/images/smilieys/$1.png" proc rstToHtml(content: string): string = result = rstgen.rstToHtml(content, {roSupportSmilies,roSupportMarkdown}, docConfig) var a: string = rstToHtml(".. image:: http://i.imgur.com/oCem13Y.png") echo a ``` --- lib/packages/docutils/rstgen.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index cc21b9382..83e1b8b9f 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -755,7 +755,7 @@ proc renderTocEntries*(d: var RstGenerator, j: var int, lvl: int, proc renderImage(d: PDoc, n: PRstNode, result: var string) = template valid(s): expr = - s.len > 0 and allCharsInSet(s, {'/',':','%','_','\\','\128'..'\xFF'} + + s.len > 0 and allCharsInSet(s, {'.','/',':','%','_','\\','\128'..'\xFF'} + Digits + Letters + WhiteSpace) var options = "" From 05754377621e43f32aafbeb149c1bd5927afd430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Zieli=C5=84ski?= Date: Sun, 2 Aug 2015 22:55:22 +0200 Subject: [PATCH 26/28] Improve discoverability of 'of' operator --- doc/manual/types.txt | 3 ++- lib/system.nim | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/manual/types.txt b/doc/manual/types.txt index 2eb034ba2..44a20d093 100644 --- a/doc/manual/types.txt +++ b/doc/manual/types.txt @@ -588,7 +588,8 @@ can also be defined with indentation instead of ``[]``: Objects provide many features that tuples do not. Object provide inheritance and information hiding. Objects have access to their type at runtime, so that -the ``of`` operator can be used to determine the object's type. +the ``of`` operator can be used to determine the object's type. The ``of`` operator +is similar to the ``instanceof`` operator in Java. .. code-block:: nim type diff --git a/lib/system.nim b/lib/system.nim index dd1a0721a..383002fcf 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -487,6 +487,7 @@ type ## See the full `exception hierarchy`_. ObjectConversionError* = object of Exception ## \ ## Raised if an object is converted to an incompatible object type. + ## You can use ``of`` operator to check if conversion will succeed. ## ## See the full `exception hierarchy`_. FloatingPointError* = object of Exception ## \ From 15df168f99a9fb7f0d4ef712795cbf070a9deda6 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Mon, 3 Aug 2015 01:27:41 +0300 Subject: [PATCH 27/28] Rename compiler configuration file to fix "nim check" within the repo Prior to the change, "nim check" would fail on any file besides the main nim.nim, because the include paths for the documentation were not set correctly and this produced various compilation errors. --- compiler/{nim.nim.cfg => nim.cfg} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/{nim.nim.cfg => nim.cfg} (100%) diff --git a/compiler/nim.nim.cfg b/compiler/nim.cfg similarity index 100% rename from compiler/nim.nim.cfg rename to compiler/nim.cfg From e1913abdd4a397ad21aa2452c75e82e163df0c20 Mon Sep 17 00:00:00 2001 From: Araq Date: Sun, 2 Aug 2015 22:12:39 +0200 Subject: [PATCH 28/28] fixes #3140 --- compiler/semfold.nim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 729222220..2ab43a9c9 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -307,12 +307,12 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mToU8: result = newIntNodeT(getInt(a) and 0x000000FF, n) of mToU16: result = newIntNodeT(getInt(a) and 0x0000FFFF, n) of mToU32: result = newIntNodeT(getInt(a) and 0x00000000FFFFFFFF'i64, n) - of mUnaryLt: result = newIntNodeT(getOrdValue(a) - 1, n) - of mSucc: result = newIntNodeT(getOrdValue(a) + getInt(b), n) - of mPred: result = newIntNodeT(getOrdValue(a) - getInt(b), n) - of mAddI: result = newIntNodeT(getInt(a) + getInt(b), n) - of mSubI: result = newIntNodeT(getInt(a) - getInt(b), n) - of mMulI: result = newIntNodeT(getInt(a) * getInt(b), n) + of mUnaryLt: result = newIntNodeT(getOrdValue(a) |-| 1, n) + of mSucc: result = newIntNodeT(getOrdValue(a) |+| getInt(b), n) + of mPred: result = newIntNodeT(getOrdValue(a) |-| getInt(b), n) + of mAddI: result = newIntNodeT(getInt(a) |+| getInt(b), n) + of mSubI: result = newIntNodeT(getInt(a) |-| getInt(b), n) + of mMulI: result = newIntNodeT(getInt(a) |*| getInt(b), n) of mMinI: if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n) else: result = newIntNodeT(getInt(a), n) @@ -338,11 +338,11 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = of mDivI: let y = getInt(b) if y != 0: - result = newIntNodeT(getInt(a) div y, n) + result = newIntNodeT(`|div|`(getInt(a), y), n) of mModI: let y = getInt(b) if y != 0: - result = newIntNodeT(getInt(a) mod y, n) + result = newIntNodeT(`|mod|`(getInt(a), y), n) of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n) of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n) of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n)