From 8062698e7f6c28debb7e938e472ac64632e6a1ff Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Wed, 29 Aug 2018 13:49:45 -0500 Subject: [PATCH 01/13] [Docs] Added {.reorder.} to manual --- doc/manual.rst | 107 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 35 deletions(-) diff --git a/doc/manual.rst b/doc/manual.rst index bb2650799b..26ff071d7d 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6823,54 +6823,91 @@ the created global variables within a module is not defined, but all of them will be initialized after any top-level variables in their originating module and before any variable in a module that imports it. +reorder pragma +-------------- +**Note**: Code reordering is experimental. By default it is turned off. + +The ``reorder`` pragma can be used to turn on and off a special compilation mode +that aims to be able to implicitly rearrange procedure, template, and macro +definitions along with variable declarations and initializations at the top +level scope so that, to a large extent, a programmer should not have to worry +about ordering definitions correctly or be forced to use forward declarations to +preface definitions inside a module. .. - NoForward pragma - ---------------- - The ``noforward`` pragma can be used to turn on and off a special compilation - mode that to large extent eliminates the need for forward declarations. In this - mode, the proc definitions may appear out of order and the compiler will postpone - their semantic analysis and compilation until it actually needs to generate code - using the definitions. In this regard, this mode is similar to the modus operandi - of dynamic scripting languages, where the function calls are not resolved until - the code is executed. Here is the detailed algorithm taken by the compiler: + NOTE: The following was documentation for the precursor to {.reorder.}, + which was {.noForward.}. + + In this mode, procedure definitions may appear out of order and the compiler + will postpone their semantic analysis and compilation until it actually needs + to generate code using the definitions. In this regard, this mode is similar + to the modus operandi of dynamic scripting languages, where the function + calls are not resolved until the code is executed. Here is the detailed + algorithm taken by the compiler: - 1. When a callable symbol is first encountered, the compiler will only note the - symbol callable name and it will add it to the appropriate overload set in the - current scope. At this step, it won't try to resolve any of the type expressions - used in the signature of the symbol (so they can refer to other not yet defined - symbols). + 1. When a callable symbol is first encountered, the compiler will only note + the symbol callable name and it will add it to the appropriate overload set + in the current scope. At this step, it won't try to resolve any of the type + expressions used in the signature of the symbol (so they can refer to other + not yet defined symbols). - 2. When a top level call is encountered (usually at the very end of the module), - the compiler will try to determine the actual types of all of the symbols in the - matching overload set. This is a potentially recursive process as the signatures - of the symbols may include other call expressions, whose types will be resolved - at this point too. + 2. When a top level call is encountered (usually at the very end of the + module), the compiler will try to determine the actual types of all of the + symbols in the matching overload set. This is a potentially recursive process + as the signatures of the symbols may include other call expressions, whose + types will be resolved at this point too. - 3. Finally, after the best overload is picked, the compiler will start - compiling the body of the respective symbol. This in turn will lead the - compiler to discover more call expressions that need to be resolved and steps - 2 and 3 will be repeated as necessary. + 3. Finally, after the best overload is picked, the compiler will start + compiling the body of the respective symbol. This in turn will lead the + compiler to discover more call expressions that need to be resolved and steps + 2 and 3 will be repeated as necessary. - Please note that if a callable symbol is never used in this scenario, its body - will never be compiled. This is the default behavior leading to best compilation - times, but if exhaustive compilation of all definitions is required, using - ``nim check`` provides this option as well. + Please note that if a callable symbol is never used in this scenario, its + body will never be compiled. This is the default behavior leading to best + compilation times, but if exhaustive compilation of all definitions is + required, using ``nim check`` provides this option as well. - Example: +Example: - .. code-block:: nim +.. code-block:: nim - {.noforward: on.} + {.reorder: on.} - proc foo(x: int) = - bar x + proc foo(x: int) = + bar(x) - proc bar(x: int) = - echo x + proc bar(x: int) = + echo(x) - foo(10) + foo(10) +Variables can also be reordered as well. Keep in mind, when we initialize (i.e. +combined declaration and assignment in one statement) variables, that entire +statement itself may be reordered. Be wary of what code you execute at the top +level: + +.. code-block:: nim + {.reorder: on.} + + proc a() = + echo(foo) + + var foo = 5 + + a() # outputs: "5" + +It is important to note that reordering *only* works for symbols at top level +scope. Therefore, the following will *fail to compile:* + +.. code-block:: nim + {.reorder: on.} + + proc a() = + b() + proc b() = + echo("Hello!") + + a() pragma pragma ------------- From 47726ecb9e4af38bfdad7f94f03d27385f2ac0f6 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 15:25:46 -0500 Subject: [PATCH 02/13] updated manual for declared() --- doc/manual.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/manual.rst b/doc/manual.rst index 26ff071d7d..e76cf3d78a 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6896,6 +6896,20 @@ level: a() # outputs: "5" +The values of expressions involving `declared` are decided *before* the code +reordering process, and not after. As an example, the output of this code is +the same as it would be with code reordering disabled. + +.. code-block:: nim + {.reorder: on.} + + proc x() = + echo(declared(foo)) + + var foo = 4 + + x() # "false" + It is important to note that reordering *only* works for symbols at top level scope. Therefore, the following will *fail to compile:* From e6a4213faeb28530e33663d27ff446a5b74b4a5e Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 15:31:38 -0500 Subject: [PATCH 03/13] transformed {.reorder: on.} into {.experimental: codeReordering.}, added tests --- compiler/options.nim | 3 ++- compiler/pragmas.nim | 13 +++++-------- tests/misc/tnoforward.nim | 3 ++- tests/pragmas/treorder.nim | 5 +++-- tests/pragmas/treorderdeclared.nim | 12 ++++++++++++ 5 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 tests/pragmas/treorderdeclared.nim diff --git a/compiler/options.nim b/compiler/options.nim index 1873d9d5b4..f2701dadd4 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -120,7 +120,8 @@ type notnil, dynamicBindSym, forLoopMacros, - caseStmtMacros + caseStmtMacros, + codeReordering, SymbolFilesOption* = enum disabledSf, writeOnlySf, readOnlySf, v2Sf diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 263068344d..0ef87720d1 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -48,7 +48,7 @@ const wDeadCodeElimUnused, # deprecated, always on wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, - wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto, + wLinearScanEnd, wPatterns, wEffects, wComputedGoto, wInjectStmt, wDeprecated, wExperimental, wThis} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, @@ -227,10 +227,6 @@ proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) = if isTurnedOn(c, n): resOptions = resOptions + op else: resOptions = resOptions - op -proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) = - if isTurnedOn(c, n): incl(c.module.flags, flag) - else: excl(c.module.flags, flag) - proc processCallConv(c: PContext, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2 and n.sons[1].kind == nkIdent: let sw = whichKeyword(n.sons[1].ident) @@ -724,7 +720,10 @@ proc processExperimental(c: PContext; n: PNode; s: PSym) = case n[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: try: - c.features.incl parseEnum[Feature](n[1].strVal) + let feature = parseEnum[Feature](n[1].strVal) + c.features.incl feature + if feature == codeReordering: + c.module.flags.incl sfReorder except ValueError: localError(c.config, n[1].info, "unknown experimental feature") else: @@ -815,8 +814,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, noVal(c, it) incl(sym.flags, {sfThread, sfGlobal}) of wDeadCodeElimUnused: discard # deprecated, dead code elim always on - of wNoForward: pragmaNoForward(c, it) - of wReorder: pragmaNoForward(c, it, sfReorder) of wMagic: processMagic(c, it, sym) of wCompileTime: noVal(c, it) diff --git a/tests/misc/tnoforward.nim b/tests/misc/tnoforward.nim index 342e757b85..3e96e34890 100644 --- a/tests/misc/tnoforward.nim +++ b/tests/misc/tnoforward.nim @@ -2,7 +2,8 @@ discard """ disabled: true """ -{. noforward: on .} +# {. noforward: on .} +{.experimental: "codeReordering".} proc foo(x: int) = bar x diff --git a/tests/pragmas/treorder.nim b/tests/pragmas/treorder.nim index 1006af5274..659a6f644f 100644 --- a/tests/pragmas/treorder.nim +++ b/tests/pragmas/treorder.nim @@ -6,7 +6,8 @@ output:'''0 """ import macros -{.reorder: on .} +# {.reorder: on .} +{.experimental: "codeReordering".} echo foo(-1) echo callWithFoo(0) @@ -71,4 +72,4 @@ macro make(arg: untyped): untyped = proc first(i: int): void = make(second) -var ss {.compileTime.}: string = "" \ No newline at end of file +var ss {.compileTime.}: string = "" diff --git a/tests/pragmas/treorderdeclared.nim b/tests/pragmas/treorderdeclared.nim new file mode 100644 index 0000000000..67403471b0 --- /dev/null +++ b/tests/pragmas/treorderdeclared.nim @@ -0,0 +1,12 @@ +discard """ +output:'''false''' +""" + +{.experimental: "codeReordering".} + +proc x() = + echo(declared(foo)) + +var foo = 4 + +x() # "false", the same as it would be with code reordering OFF From 89ad1cc9b18db8320e5b170ee45888cf79d52001 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 16:21:47 -0500 Subject: [PATCH 04/13] tabling declared() stuff --- tests/pragmas/treorderdeclared.nim | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 tests/pragmas/treorderdeclared.nim diff --git a/tests/pragmas/treorderdeclared.nim b/tests/pragmas/treorderdeclared.nim deleted file mode 100644 index 67403471b0..0000000000 --- a/tests/pragmas/treorderdeclared.nim +++ /dev/null @@ -1,12 +0,0 @@ -discard """ -output:'''false''' -""" - -{.experimental: "codeReordering".} - -proc x() = - echo(declared(foo)) - -var foo = 4 - -x() # "false", the same as it would be with code reordering OFF From cd3d4faa79d0ae90afa706393ec67f0721ed87be Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 16:42:37 -0500 Subject: [PATCH 05/13] Deny THIS experimental pragma specifically for non-toplevel --- compiler/pragmas.nim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 910ee799c5..fae2155567 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -743,7 +743,11 @@ proc processExperimental(c: PContext; n: PNode) = let feature = parseEnum[Feature](n[1].strVal) c.features.incl feature if feature == codeReordering: - c.module.flags.incl sfReorder + if not isTopLevel(c): + localError(c.config, n.info, + "Code reordering experimental pragma only valid at toplevel") + else: + c.module.flags.incl sfReorder except ValueError: localError(c.config, n[1].info, "unknown experimental feature") else: From c2b09a499c7b4fe255bb57ade50e2736f89aba2c Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 16:46:43 -0500 Subject: [PATCH 06/13] Fix merge --- compiler/pragmas.nim | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index fae2155567..8f6b6e362c 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -347,7 +347,13 @@ proc processExperimental(c: PContext; n: PNode) = case n[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: try: - c.features.incl parseEnum[Feature](n[1].strVal) + let feature = parseEnum[Feature](n[1].strVal) + c.features.incl feature + if feature == codeReordering: + if not isTopLevel(c): + localError(c.config, n.info, + "Code reordering experimental pragma only valid at toplevel") + c.module.flags.incl sfReorder except ValueError: localError(c.config, n[1].info, "unknown experimental feature") else: @@ -732,27 +738,6 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = elif n.kind == nkExprColonExpr: result.kind = n.kind # pragma(arg) -> pragma: arg -proc processExperimental(c: PContext; n: PNode) = - if n.kind notin nkPragmaCallKinds or n.len != 2: - c.features.incl oldExperimentalFeatures - else: - n[1] = c.semConstExpr(c, n[1]) - case n[1].kind - of nkStrLit, nkRStrLit, nkTripleStrLit: - try: - let feature = parseEnum[Feature](n[1].strVal) - c.features.incl feature - if feature == codeReordering: - if not isTopLevel(c): - localError(c.config, n.info, - "Code reordering experimental pragma only valid at toplevel") - else: - c.module.flags.incl sfReorder - except ValueError: - localError(c.config, n[1].info, "unknown experimental feature") - else: - localError(c.config, n.info, errStringLiteralExpected) - proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, validPragmas: TSpecialWords): bool = var it = n.sons[i] From 02306020b27a69a6f5f9eaa0926c87da0636a018 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Tue, 4 Sep 2018 18:25:54 -0500 Subject: [PATCH 07/13] fix test --- tests/modules/treorder.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/modules/treorder.nim b/tests/modules/treorder.nim index 8715e45482..c81715cd8c 100644 --- a/tests/modules/treorder.nim +++ b/tests/modules/treorder.nim @@ -6,8 +6,7 @@ defined 3''' """ -{.reorder: on.} -{.experimental.} +{.experimental: "codeReordering".} proc bar(x: T) From 2b8c4096a48449d424db6869c7281c837e3e0904 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Wed, 5 Sep 2018 09:03:44 -0500 Subject: [PATCH 08/13] brought back pragmaNoForward, deprecated --- compiler/pragmas.nim | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 8f6b6e362c..aa0783bd5a 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -230,6 +230,19 @@ proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) = if isTurnedOn(c, n): resOptions = resOptions + op else: resOptions = resOptions - op +proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) = + if isTurnedOn(c, n): + incl(c.module.flags, flag) + c.features.incl codeReordering + else: + excl(c.module.flags, flag) + # c.features.excl codeReordering + + # deprecated as of 0.18.1 + message(c.config, n.info, warnDeprecated, + "use {.experimental: \"codeReordering.\".} instead; " & + (if flag == sfNoForward: "{.noForward.}" else: "{.reorder.}")) + proc processCallConv(c: PContext, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2 and n.sons[1].kind == nkIdent: let sw = whichKeyword(n.sons[1].ident) @@ -823,6 +836,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, noVal(c, it) incl(sym.flags, {sfThread, sfGlobal}) of wDeadCodeElimUnused: discard # deprecated, dead code elim always on + of wNoForward: pragmaNoForward(c, it) + of wReorder: pragmaNoForward(c, it, flag = sfReorder) of wMagic: processMagic(c, it, sym) of wCompileTime: noVal(c, it) From 32deb70bae984dc034c3f0d61f414f1530701b3f Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Thu, 6 Sep 2018 23:49:38 -0500 Subject: [PATCH 09/13] changed to {.experimental: codeReordering.}, postpoing declared() stuff --- doc/manual.rst | 202 +++++++++++++++++++++++++------------------------ 1 file changed, 105 insertions(+), 97 deletions(-) diff --git a/doc/manual.rst b/doc/manual.rst index e76cf3d78a..33d3e8242a 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6418,6 +6418,111 @@ iterator in which case the overloading resolution takes place: var x = 4 write(stdout, x) # not ambiguous: uses the module C's x +Code reordering +~~~~~~~~~~~~~~~ + +**Note**: Code reordering is experimental and must be enabled via the +``{.experimental.}`` pragma. + +The code reordering feature can implicitly rearrange procedure, template, and +macro definitions along with variable declarations and initializations at the top +level scope so that, to a large extent, a programmer should not have to worry +about ordering definitions correctly or be forced to use forward declarations to +preface definitions inside a module. + +.. + NOTE: The following was documentation for the code reordering precursor, + which was {.noForward.}. + + In this mode, procedure definitions may appear out of order and the compiler + will postpone their semantic analysis and compilation until it actually needs + to generate code using the definitions. In this regard, this mode is similar + to the modus operandi of dynamic scripting languages, where the function + calls are not resolved until the code is executed. Here is the detailed + algorithm taken by the compiler: + + 1. When a callable symbol is first encountered, the compiler will only note + the symbol callable name and it will add it to the appropriate overload set + in the current scope. At this step, it won't try to resolve any of the type + expressions used in the signature of the symbol (so they can refer to other + not yet defined symbols). + + 2. When a top level call is encountered (usually at the very end of the + module), the compiler will try to determine the actual types of all of the + symbols in the matching overload set. This is a potentially recursive process + as the signatures of the symbols may include other call expressions, whose + types will be resolved at this point too. + + 3. Finally, after the best overload is picked, the compiler will start + compiling the body of the respective symbol. This in turn will lead the + compiler to discover more call expressions that need to be resolved and steps + 2 and 3 will be repeated as necessary. + + Please note that if a callable symbol is never used in this scenario, its + body will never be compiled. This is the default behavior leading to best + compilation times, but if exhaustive compilation of all definitions is + required, using ``nim check`` provides this option as well. + +Example: + +.. code-block:: nim + + {.experimental: "codeReordering".} + + proc foo(x: int) = + bar(x) + + proc bar(x: int) = + echo(x) + + foo(10) + +Variables can also be reordered as well. Keep in mind, when we initialize (i.e. +combined declaration and assignment in one statement) variables, that entire +statement itself may be reordered. Be wary of what code you execute at the top +level: + +.. code-block:: nim + {.experimental: "codeReordering".} + + proc a() = + echo(foo) + + var foo = 5 + + a() # outputs: "5" + +.. + TODO: Let's table this for now. This is an *experimental feature* and so the + specific manner in which ``declared`` operates with it can be decided in + eventuality. + + The values of expressions involving ``declared`` are decided *before* the + code reordering process, and not after. As an example, the output of this + code is the same as it would be with code reordering disabled. + + .. code-block:: nim + {.experimental: "codeReordering".} + + proc x() = + echo(declared(foo)) + + var foo = 4 + + x() # "false" + +It is important to note that reordering *only* works for symbols at top level +scope. Therefore, the following will *fail to compile:* + +.. code-block:: nim + {.experimental: "codeReordering".} + + proc a() = + b() + proc b() = + echo("Hello!") + + a() Compiler Messages ================= @@ -6825,103 +6930,6 @@ and before any variable in a module that imports it. reorder pragma -------------- -**Note**: Code reordering is experimental. By default it is turned off. - -The ``reorder`` pragma can be used to turn on and off a special compilation mode -that aims to be able to implicitly rearrange procedure, template, and macro -definitions along with variable declarations and initializations at the top -level scope so that, to a large extent, a programmer should not have to worry -about ordering definitions correctly or be forced to use forward declarations to -preface definitions inside a module. - -.. - NOTE: The following was documentation for the precursor to {.reorder.}, - which was {.noForward.}. - - In this mode, procedure definitions may appear out of order and the compiler - will postpone their semantic analysis and compilation until it actually needs - to generate code using the definitions. In this regard, this mode is similar - to the modus operandi of dynamic scripting languages, where the function - calls are not resolved until the code is executed. Here is the detailed - algorithm taken by the compiler: - - 1. When a callable symbol is first encountered, the compiler will only note - the symbol callable name and it will add it to the appropriate overload set - in the current scope. At this step, it won't try to resolve any of the type - expressions used in the signature of the symbol (so they can refer to other - not yet defined symbols). - - 2. When a top level call is encountered (usually at the very end of the - module), the compiler will try to determine the actual types of all of the - symbols in the matching overload set. This is a potentially recursive process - as the signatures of the symbols may include other call expressions, whose - types will be resolved at this point too. - - 3. Finally, after the best overload is picked, the compiler will start - compiling the body of the respective symbol. This in turn will lead the - compiler to discover more call expressions that need to be resolved and steps - 2 and 3 will be repeated as necessary. - - Please note that if a callable symbol is never used in this scenario, its - body will never be compiled. This is the default behavior leading to best - compilation times, but if exhaustive compilation of all definitions is - required, using ``nim check`` provides this option as well. - -Example: - -.. code-block:: nim - - {.reorder: on.} - - proc foo(x: int) = - bar(x) - - proc bar(x: int) = - echo(x) - - foo(10) - -Variables can also be reordered as well. Keep in mind, when we initialize (i.e. -combined declaration and assignment in one statement) variables, that entire -statement itself may be reordered. Be wary of what code you execute at the top -level: - -.. code-block:: nim - {.reorder: on.} - - proc a() = - echo(foo) - - var foo = 5 - - a() # outputs: "5" - -The values of expressions involving `declared` are decided *before* the code -reordering process, and not after. As an example, the output of this code is -the same as it would be with code reordering disabled. - -.. code-block:: nim - {.reorder: on.} - - proc x() = - echo(declared(foo)) - - var foo = 4 - - x() # "false" - -It is important to note that reordering *only* works for symbols at top level -scope. Therefore, the following will *fail to compile:* - -.. code-block:: nim - {.reorder: on.} - - proc a() = - b() - proc b() = - echo("Hello!") - - a() pragma pragma ------------- From 5ee924c711fdb04bef0106ccaeb21c37542c2508 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Fri, 7 Sep 2018 00:00:20 -0500 Subject: [PATCH 10/13] whoops, forgot to remove old pragma section --- doc/manual.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/manual.rst b/doc/manual.rst index 33d3e8242a..a7bec649ce 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6495,7 +6495,7 @@ level: .. TODO: Let's table this for now. This is an *experimental feature* and so the specific manner in which ``declared`` operates with it can be decided in - eventuality. + eventuality, because right now it works a bit weirdly. The values of expressions involving ``declared`` are decided *before* the code reordering process, and not after. As an example, the output of this @@ -6928,9 +6928,6 @@ the created global variables within a module is not defined, but all of them will be initialized after any top-level variables in their originating module and before any variable in a module that imports it. -reorder pragma --------------- - pragma pragma ------------- From e3d7056902550f85cee68ee0cddfe4d944b4e815 Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Fri, 7 Sep 2018 11:28:01 -0500 Subject: [PATCH 11/13] fixed stmtPragmas stuff --- compiler/pragmas.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index aa0783bd5a..9bc3f353e1 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -48,7 +48,7 @@ const wDeadCodeElimUnused, # deprecated, always on wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, - wLinearScanEnd, wPatterns, wEffects, wComputedGoto, + wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto, wInjectStmt, wDeprecated, wExperimental, wThis} lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, From e4c4cbc176b62c8e4ee715a25640e40e1533584e Mon Sep 17 00:00:00 2001 From: awr <41453959+awr1@users.noreply.github.com> Date: Wed, 12 Sep 2018 18:29:01 -0500 Subject: [PATCH 12/13] fixed language wrt initialization --- doc/manual.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/manual.rst b/doc/manual.rst index a7bec649ce..4f0530a8a5 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6477,10 +6477,10 @@ Example: foo(10) -Variables can also be reordered as well. Keep in mind, when we initialize (i.e. -combined declaration and assignment in one statement) variables, that entire -statement itself may be reordered. Be wary of what code you execute at the top -level: +Variables can also be reordered as well. Variables that are *initialized* (i.e. +variables that have their declaration and assignment combined in a single +statement) can have their entire initialization statement reordered. Be wary of +what code is executed at the top level: .. code-block:: nim {.experimental: "codeReordering".} From 839953c3e167828f93bdddd27ae88c5909c8aca9 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 14 Sep 2018 15:29:34 +0200 Subject: [PATCH 13/13] Fix hashing for codegenProc (sic) types Since the name mangling is inhibited we should take the user-supplied name during the sighash computation. Fixes #8964 --- compiler/sighashes.nim | 12 +++++++----- lib/system/hti.nim | 12 +++--------- tests/ccgbugs/t8964.nim | 10 ++++++++++ 3 files changed, 20 insertions(+), 14 deletions(-) create mode 100644 tests/ccgbugs/t8964.nim diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 8f95175e5e..097695f821 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -68,6 +68,8 @@ else: toBase64a(cast[cstring](unsafeAddr u), sizeof(u)) proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len) proc `&=`(c: var MD5Context, ch: char) = md5Update(c, unsafeAddr ch, 1) + proc `&=`(c: var MD5Context, r: Rope) = + for l in leaves(r): md5Update(c, l, l.len) proc `&=`(c: var MD5Context, i: BiggestInt) = md5Update(c, cast[cstring](unsafeAddr i), sizeof(i)) @@ -181,11 +183,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = # Every cyclic type in Nim need to be constructed via some 't.sym', so this # is actually safe without an infinite recursion check: if t.sym != nil: - #if "Future:" in t.sym.name.s and t.typeInst == nil: - # writeStackTrace() - # echo "yes ", t.sym.name.s - # #quit 1 - if CoOwnerSig in flags: + if {sfCompilerProc} * t.sym.flags != {}: + doAssert t.sym.loc.r != nil + # The user has set a specific name for this type + c &= t.sym.loc.r + elif CoOwnerSig in flags: c.hashTypeSym(t.sym) else: c.hashSym(t.sym) diff --git a/lib/system/hti.nim b/lib/system/hti.nim index 9931fa11ed..c7b52bbdfc 100644 --- a/lib/system/hti.nim +++ b/lib/system/hti.nim @@ -7,12 +7,6 @@ # distribution, for details about the copyright. # -when declared(ThisIsSystem): - # we are in system module: - {.pragma: codegenType, compilerproc.} -else: - {.pragma: codegenType.} - type # This should be the same as ast.TTypeKind # many enum fields are not used at runtime @@ -79,7 +73,7 @@ type tyVoidHidden TNimNodeKind = enum nkNone, nkSlot, nkList, nkCase - TNimNode {.codegenType.} = object + TNimNode {.compilerProc.} = object kind: TNimNodeKind offset: int typ: ptr TNimType @@ -92,7 +86,7 @@ type ntfAcyclic = 1, # type cannot form a cycle ntfEnumHole = 2 # enum has holes and thus `$` for them needs the slow # version - TNimType {.codegenType.} = object + TNimType {.compilerProc.} = object size: int kind: TNimKind flags: set[TNimTypeFlag] @@ -109,6 +103,6 @@ type PNimType = ptr TNimType when defined(nimTypeNames): - var nimTypeRoot {.codegenType.}: PNimType + var nimTypeRoot {.compilerProc.}: PNimType # node.len may be the ``first`` element of a set diff --git a/tests/ccgbugs/t8964.nim b/tests/ccgbugs/t8964.nim new file mode 100644 index 0000000000..5b41e8bdba --- /dev/null +++ b/tests/ccgbugs/t8964.nim @@ -0,0 +1,10 @@ +discard """ + targets: "c cpp" +""" + +from json import JsonParsingError +import marshal + +const nothing = "" +doAssertRaises(JsonParsingError): + var bar = marshal.to[int](nothing)