Compare commits

...

1082 Commits

Author SHA1 Message Date
narimiran
e941ee15be bump NimVersion to 2.0.10 2024-09-30 19:18:52 +02:00
metagn
5f119f0cdf allow C atomics on C++ with -d:nimUseCAtomics (#24207)
refs https://github.com/nim-lang/Nim/pull/24200#issuecomment-2382501282

Workaround for C++ Atomic[T] issues that doesn't require a compiler
change. Not tested or documented in case it's not meant to be officially
supported, locally tested `tatomics` and #24159 to work with it though,
can add these as tests if required.

(cherry picked from commit febc58e036)
2024-09-30 18:58:01 +02:00
metagn
0636bd2a04 fix cyclic node flag getting added to sink call [backport:2.0] (#24194)
Sorry I don't have a test case or issue for this. `injectdestructors` is
supposed to add a final bool argument to `=copy` and `=dup` to mark
cyclic types, as generated by `liftdestructors`. Hence this flag is
added after every call to `genCopy`, but `genCopy` can generate a
`=sink` call when passed the flag `IsExplicitSink` by `nkSinkAsgn`. This
creates a codegen error, saying the sink received an extra argument.
This is fixed by not adding the argument on the flag `IsExplicitSink`.

This is a followup to #20585 which is on the 2.0 branch, hence this is
marked backport.

(cherry picked from commit 7974a2208c)
2024-09-30 18:29:19 +02:00
metagn
2499336fef remove prev == nil requirement for typedesc params as type nodes (#24206)
fixes #24203

`semTypeNode` is called twice for RHS'es of type sections,
[here](b0e6d28782/compiler/semstmts.nim (L1612))
and
[here](b0e6d28782/compiler/semstmts.nim (L1646)).
Each time `prev` is `s.typ`, but the assertion expects `prev == nil`
which is false since `s.typ` is not nil the second time. To fix this,
the `prev == nil` part of the assertion is removed.

The reason this only happens for types like `seq[int]`, `(int, int)` etc
is because they don't have syms: `semTypeIdent` attempts to directly
[replace the typedesc param
itself](b0e6d28782/compiler/semtypes.nim (L1916))
with the sym of the base type of the resolved typedesc type if it
exists, which means `semTypeNode` doesn't receive the typedesc param sym
to perform the assert.

(cherry picked from commit 2a48182288)
2024-09-30 18:24:24 +02:00
ringabout
1ba16876f1 fixes #24167; {.push deprecated.} for templates (#24170)
fixes #24167

(cherry picked from commit 3b85c1a2e9)
2024-09-28 08:18:28 +02:00
metagn
3a180df0d8 fix inTypeofContext leaking after compiles raises exception [backport:2.0] (#24152)
fixes #24150, refs #22022

An exception is raised in the `semExprWithType` call, which means `dec
c.inTypeofContext` is never called, but `compiles` allows compilation to
continue. This means `c.inTypeofContext` is left perpetually nonzero,
which prevents `compileTime` evaluation for the rest of the program.

To fix this, `defer:` is used for the `dec c.inTypeofContext` call, as
is done for
[`instCounter`](d51d88700b/compiler/seminst.nim (L374))
in other parts of the compiler.

(cherry picked from commit a1777200c1)
2024-09-28 08:18:04 +02:00
metagn
9d65507d20 fix nil literal giving itself type untyped/typed [backport] (#24165)
fixes #24164, regression from #20091

The expression `nil` as the default value of template parameter `x:
untyped` is typechecked with expected type `untyped` since #20091. The
expected type is checked if it matches the `nil` literal with a match
better than a subtype match, and the type is set to it if it does.
However `untyped` matches with a generic match which is better, so the
`nil` literal has type `untyped`. This breaks type matching for the
literal. So if the expected type is `untyped` or `typed`, it is now
ignored and the `nil` literal just has the `nil` type.

(cherry picked from commit b9de2bb4f3)
2024-09-23 17:24:59 +02:00
Ryan McConnell
78003e9f7b Fix incorrect inheritance penalty for some objects (#24144)
This fixes a logic error in  #23870
The inheritance penalty should be -1 if there is no inheritance
relationship. Not sure how to write a test case for this one honestly.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 37dba853c9)
2024-09-23 16:41:38 +02:00
metagn
27381cc602 make genericsOpenSym work at instantiation time, new behavior in openSym (#24111)
alternative to #24101

enabled in the context of the generic/template declarations capturing
the symbols, not the context of the instantiation of the
generics/templates. This was to be in line with where the compiler gives
the warnings and changes behavior in a potentially breaking way.

However `results` [depends on the old
behavior](71d404b314/results.nim (L1428)),
so that the callers of the macros provided by results always take
advantage of the opensym behavior. To accomodate this, we change the
behavior of the old experimental option that `results` uses,
`genericsOpenSym`, so that ignores the information of whether or not
symbols are intentionally opened and always gives the opensym behavior
as long as it's enabled at instantiation time. This should keep
`results` working as is. However this differs from the normal opensym
switch in that it doesn't generate `nnkOpenSym`.

Before it was just a generics-only version of `openSym` along with
`templateOpenSym` which was only for templates. So `templateOpenSym` is
removed along with this change, but no one appears to have used it.

(cherry picked from commit 0c3573e4a0)
2024-09-18 19:36:30 +02:00
metagn
dd9cb0425c fix segfault in effect tracking for sym node with nil type (#24114)
fixes #24112

Sym nodes in templates that could be open are [given `nil`
type](22d2cf2175/compiler/semtempl.nim (L274))
when `--experimentalOpenSym` is disabled so that they can be semchecked
to give a warning since #24007. The first nodes of object constructors
(in this case) and in type conversions don't replace their first node
(the symbol) with a typechecked one, they only call `semTypeNode` on it
and leave it as is.

Effect tracking checks if the type of a sym node has a destructor to
check if the node type should be replaced with the sym type. But this
causes a segfault when the type of the node is nil. To fix this, we
always set the node type to the sym type if the node type is nil.

Alternatively `semObjConstr` and `semConv` could be changed to set the
type of their first node to the found type but I'm not sure if this
would break anything. They could call `semExprWithType` on the first
node but `semTypeNode` would still have to be called (maybe call it
before?). This isn't a problem if the sym node has a type but is just
nested in `nkOpenSym` or `nkOpenSymChoice` which have nil type instead
(i.e. with openSym enabled), so maybe this still is the "most general"
solution, I don't know.

(cherry picked from commit 680a13a142)
2024-09-18 19:27:51 +02:00
metagn
894eee03a5 make var/pointer types not match if base type has to be converted (#24130)
split again from #24038, fixes
https://github.com/status-im/nimbus-eth2/pull/6554#issuecomment-2354977102

`var`/pointer types are no longer implicitly convertible to each other
if their element types either:

* require an int conversion or another conversion operation as long as
it's not to `openarray`,
* are subtypes with pointer indirection,

Previously any conversion below a subrange match would match if the
element type wasn't a pointer type, then it would error later in
`analyseIfAddressTaken`.

Different from #24038 in that the preview define that made subrange
matches also fail to match is removed for a simpler diff so that it can
be backported.

(cherry picked from commit 1660ddf98a)
2024-09-18 19:25:18 +02:00
ringabout
4b8b8fb9d7 fixes for 32bit system (#23980)
(cherry picked from commit a4dff1a03e)
2024-09-17 13:43:10 +02:00
metagn
3214174f06 opensym for templates + move behavior of opensymchoice to itself (#24007)
fixes #15314, fixes #24002

The OpenSym behavior first added to generics in #23091 now also applies
to templates, since templates can also capture symbols that are meant to
be replaced by local symbols if the context imports symbols with the
same name, as in the issue #24002. The experimental switch
`templateOpenSym` is added to enable this behavior for templates only,
and the experimental switch `openSym` is added to enable it for both
templates and generics, and the documentation now mainly mentions this
switch.

Additionally the logic for `nkOpenSymChoice` nodes that were previously
wrapped in `nkOpenSym` now apply to all `nkOpenSymChoice` nodes, and so
these nodes aren't wrapped in `nkOpenSym` anymore. This means
`nkOpenSym` can only have children of kind `nkSym` again, so it is more
in line with the structure of symchoice nodes. As for why they aren't
merged with `nkOpenSymChoice` nodes yet, we need some way to signal that
the node shouldn't become ambiguous if other options exist at
instantiation time, we already captured a symbol at the beginning and
another symbol can only replace it if it's closer in scope and
unambiguous.

(cherry picked from commit 770f8d5513)
2024-09-16 16:29:37 +02:00
Andreas Rumpf
8bb9823fde fixes #23445; fixes #23418 [backport] (#23699)
(cherry picked from commit 56c95758b2)
2024-09-16 12:30:27 +02:00
SirOlaf
40ee3a950e Fix #22826: Don't skip generic instances in type comparison (#22828)
Close #22826

I am not sure why this code skips generic insts, so letting CI tell me.
Update: It has told me nothing. Maybe someone knows during review.

Issue itself seems to be that the generic instance is skipped thus it
ends up being just `float` which makes it use the wrong generic instance
of the proc because it matches the one in cache

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit c13c48500b)
2024-09-16 12:30:27 +02:00
narimiran
74c4b23e0d backport ast.nim refactorings 2024-09-16 12:30:27 +02:00
Juan M Gómez
7180ce6faa bumps nimble to 0.16.1 (#24102)
(cherry picked from commit 6c35a36043)
2024-09-16 10:00:41 +02:00
metagn
fd1d008cce fix regression with uint constant losing abstract type (#24105)
fixes #24104, refs #23955

The line `result.typ = dstTyp` added in #23955 changes the type of
`result`, which was the type of `n` due to the argument passed to
`newIntNodeT`, to the abstract type skipped `dstTyp`. The line is
removed to just keep the type as abstract.

(cherry picked from commit 6d362e0ffe)
2024-09-16 10:00:18 +02:00
ringabout
8bc8347f02 bump checksums (#23975)
ref https://github.com/nim-lang/checksums/pull/16
ref https://github.com/nim-lang/Nim/pull/23970

(cherry picked from commit 0ffc0493a3)
2024-09-13 14:22:54 +02:00
ringabout
33bef682dd fixes cast expressions introduces unnecessary copies (#24004)
It speeds up
```nim
proc foo =
  let piece = cast[seq[char]](newSeqUninit[uint8](5220600386'i64))

foo()
```

Notes that `cast[ref](...)` is excluded because we need to keep the ref
alive if the parameter is something with pointer types (e.g.
`cast[ref](pointer)`or `cast[ref](makePointer(...))`)

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 4ef06a5cc5)
2024-09-13 13:43:53 +02:00
ringabout
bfd4b9b7a4 fixes #23945; type checking for whenvm expresssions (#23970)
fixes #23945

(cherry picked from commit dda638c1ba)
2024-09-13 13:43:45 +02:00
metagn
7d2fe8086f allow untyped arguments to fail to compile in overload mismatch error (#23984)
fixes #8697, fixes #9620, fixes #23265

When matching a `template` with an `untyped` argument fails because of a
mismatching typed argument, `presentFailedCandidates` tries to sem every
single argument to show their types, but trying to type the `untyped`
argument can fail if it's supposed to use an injected symbol, so we get
an unrelated error message like "undeclared identifier".

Instead we use `tryExpr` as the comment suggests, setting the type to
`untyped` if it fails to compile. We could also maybe check if an
`untyped` argument is expected in its place and not try to compile the
expression if it is but this would require a bit of reorganizing the
code here and IMO it's better to have the information of what type it
would be if it can be typed.

(cherry picked from commit 34719cad9d)
2024-09-13 13:43:38 +02:00
metagn
a78834c26c make all generic aliases tyAlias (#23978)
fixes #23977

The problem is that for *any* body of a generic declaration,
[semstmts](2e4d344b43/compiler/semstmts.nim (L1610-L1611))
sets the sym of its value to the generic type name, and
[semtypes](2e4d344b43/compiler/semtypes.nim (L2143))
just directly gives the referenced type *specifically* when the
expression is a generic body. I'm blaming `semtypes` here because it's
responsible for the type given but the exact opposite behavior
specifically written in makes me think generating an alias type here
maybe breaks something.

(cherry picked from commit 58813a3b2e)
2024-09-13 13:43:29 +02:00
metagn
7cbf0ee53c allow generic compileTime proc folding (#22022)
fixes #10753, fixes #22021, refs #19365 (was fixed by #22029, but more
faithful test added)

For whatever reason `compileTime` proc calls did not fold if the proc
was generic ([since this folding was
introduced](c25ffbf262 (diff-539da3a63df08fa987f1b0c67d26cdc690753843d110b6bf0805a685eeaffd40))).
I'm guessing the intention was for *unresolved* generic procs to not
fold, which is now the logic.

Non-magic `compileTime` procs also now don't fold at compile time in
`typeof` contexts to avoid possible runtime errors (only the important)
and prevent double/needless evaluation.

(cherry picked from commit f7c11a8978)
2024-09-13 13:43:23 +02:00
metagn
f86f2928a7 fix is with type/typedesc crashing the compiler (#23967)
fixes #22850

The `is` operator checks the type of the left hand side, and if it's
generic or if it's a `typedesc` type with no base type, it leaves it to
be evaluated later. But `typedesc` types with no base type precisely
describe the default typeclass `type`/`typeclass`, so this condition is
removed. Maybe at some point this represented an unresolved generic
type?

(cherry picked from commit 995081b56a)
2024-09-13 13:43:06 +02:00
ringabout
5f09bf11de fixes #23954; uint8 > 8 bit at compile-time (#23955)
fixes #23954

(cherry picked from commit 298ada3412)
2024-09-13 13:43:00 +02:00
Mark Leyva
25ce25bc42 fix #23817; Use __builtin_saddl_overflow variants for arm-none-eabi-gcc. (#23835)
Provides a fix for #23817.

With target `arm-none-eabi`, GCC defines `int32_t` to `long int`. Nim
uses `__builtin_sadd_overflow` for 32-bit targets, but this emits
warnings on GCC releases 13 and under, while generating an error on GCC
14. More info regarding this
[here](https://gcc.gnu.org/gcc-14/porting_to.html#c) and
[here](https://gcc.gnu.org/pipermail/gcc-cvs/2023-December/394351.html).

The proposed PR attempts to address this issue for these targets by
defining the `nimAddInt`, `nimSubInt`, and `nimMulInt` macros to use the
appropriate compiler intrinsics for this platform.

As for as we know, the LLVM toolchain for bare metal Arm does not define
`int32_t` as `long int` and has no need for this patch. Thus, we only
define the above macros for GCC targeting `arm-non-eabi`.

(cherry picked from commit c5b206d4ac)
2024-09-13 13:42:36 +02:00
ringabout
7503bed717 fixes #14522 #22085 #12700 #23132; no range check for uints (#23930)
fixes #14522
fixes #22085
fixes #12700
fixes #23132
closes https://github.com/nim-lang/Nim/pull/22343 (succeeded by this PR)
completes https://github.com/nim-lang/RFCs/issues/175

follow up https://github.com/nim-lang/Nim/pull/12688

(cherry picked from commit f0e1eef65e)
2024-09-13 11:10:00 +02:00
ringabout
b7041b250c fixes #23894; succ/pred shouldn't raise OverflowDefect for unsigned integers (#23895)
fixes #23894

keeps it consistent with `inc`

(cherry picked from commit bd063113ec)
2024-09-13 11:09:45 +02:00
Buldram
06d00dfcf6 fixes #19171; have openArray converted from ptr UncheckedArray be mutable (#23882)
Makes `toOpenArray(x: ptr UncheckedArray)` always return a `var
openArray` regardless of if `x` is mutable.

(cherry picked from commit 925dc5c131)
2024-09-13 11:09:35 +02:00
metagn
baa8af92af fix generics treating symchoice symbols as uninstantiated (#23860)
fixes #23853

Since #22610 generics turns the `Name` in the `GT.Name` expression in
the test code into a sym choice. The problem is when the compiler tries
to instantiate `GT.Name` it also instantiates the sym choice symbols.
`Name` has type `template (E: type ExtensionField)` which contains the
unresolved generic type `ExtensionField`, which the compiler mistakes as
an uninstantiated node, when it's just part of the type of the template.
The compilation of the node itself and hence overloading will handle the
instantiation of the proc, so we avoid instantiating it in `semtypinst`,
similar to how the first nodes of call nodes aren't instantiated.

(cherry picked from commit 97f5474545)
2024-09-13 11:09:24 +02:00
ringabout
f09b612f64 fixes #20865; fixes #20987; Missing bounds check in array slicing (#23814)
fixes #20865
fixes #20987

(cherry picked from commit e53a2ed19b)
2024-09-13 11:09:04 +02:00
Mark Leyva
7d0cdfc79d fixes #5091; Ensure we don't wait on an exited process on Linux (#23743)
Fixes #5091.

Ensure we don't wait on an exited process on Linux

(cherry picked from commit 288d5c4ac3)
2024-09-13 11:00:07 +02:00
lit
ae117bd7bc fixes #23732, os.sleep(-1) now returns immediately (#23734)
fixes #23732

(cherry picked from commit 2a658c64d8)
2024-09-13 10:59:57 +02:00
ringabout
b79e603702 ref #20653; fixes chronos empty case branches (#23706)
ref #20653

```nim
  Error* = object
    case kind*: ErrorType
    of ErrorA:
      discard
    of ErrorB:
      discard
```
For an object variants without fields, it shouldn't generate empty
brackets for default values since there are no fields at all in case
branches.

(cherry picked from commit 948bb38335)
2024-09-13 10:56:05 +02:00
c-blake
da2ba43dca Fix non-exported memfiles.setFileSize to be able to shrink files on posix via memfiles.resize (#23717)
Fix non-exported `setFileSize` to take optional `oldSize` to (on posix)
shrink differently than it grows (`ftruncate` not `posix_fallocate`)
since it makes sense to assume the higher address space has already been
allocated there and include the old file size in the `proc resize` call.
Also, do not even try `setFileSize` in the first place unless the `open`
itself works by moving the call into the `if newFileSize != -1` branch.

Just cosmetics, also improve some old 2011 comments, note a logic diff
for callers using both `mappedSize` & `newFileSize` from windows branch
in case someone wants to fix that & simplify code formatting a little.

(cherry picked from commit 8037bbe327)
2024-09-13 10:55:55 +02:00
ringabout
b5ef14ceda fixes #22798; Duplicate libraries linker warning (i.e., '-lm') on macOS (#23292)
fixes #22798

Per
https://stackoverflow.com/questions/33675638/gcc-link-the-math-library-by-default-in-c-on-mac-os-x
and
https://stackoverflow.com/questions/30694042/c-std-library-dont-appear-to-be-linked-in-object-file

> There's no separate math library on OSX. While a lot of systems ship
functions in the standard C math.h header in a separate math library,
OSX does not do that, it's part of the libSystem library, which is
always linked in.

required by https://github.com/nim-lang/Nim/pull/23290

(cherry picked from commit de4c7dfdd9)
2024-09-13 10:24:01 +02:00
ringabout
dc62ee00df fixes #23635; tasks.toTask Doesn't Expect a Dot Expression (#23641)
fixes #23635

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit cc5ce72376)
2024-09-13 10:22:36 +02:00
ringabout
b6a8dcd922 fixes #22852; fixes #23435; fixes #23645; SIGSEGV when slicing string or seq[T] with index out of range (#23279)
follow up https://github.com/nim-lang/Nim/pull/23013

fixes #22852
fixes #23435
fixes #23645

reports rangeDefect correctly

```nim
/workspaces/Nim/test9.nim(1) test9
/workspaces/Nim/lib/system/indices.nim(116) []
/workspaces/Nim/lib/system/fatal.nim(53) sysFatal
Error: unhandled exception: value out of range: -2 notin 0 .. 9223372036854775807 [RangeDefect]
```

(cherry picked from commit c615828ccb)
2024-09-13 10:22:30 +02:00
Alexander Kernozhitsky
37965bd591 Handle arbitrarily long symlink target in expandSymlinks() (#23650)
For now, `expandSymlinks()` can handle only symlinks with lengths up to
1024.

We can improve this logic and retry inside a loop with increasing
lengths until we succeed.

The same approach is used in
[Go](377646589d/src/os/file_unix.go (L446)),
[Rust](785eb65377/library/std/src/sys/pal/unix/fs.rs (L1700))
and [Nim's
`getCurrentDir()`](https://github.com/nim-lang/Nim/blob/devel/lib/std/private/ospaths2.nim#L877),
so maybe it's a good idea to use the same logic in `expandSymlinks()`
also.

(cherry picked from commit 3bda5fc840)
2024-09-13 10:22:20 +02:00
ringabout
c2b4d8a968 fixes reifiedOpenArray; nkHiddenStdConv is PathKinds1 not PathKinds0 (#23633)
(cherry picked from commit 5cd141cebb)
2024-09-13 10:22:11 +02:00
ringabout
8d254a5945 fixes #24053; fixes #18288; relax reorder with push/pop pragmas restrictions; no crossing push/pop barriers (#24061)
fixes #24053;
fixes #18288

makes push pragmas depend on each node before it and nodes after it
depend on it

(cherry picked from commit c10f84b9d7)
2024-09-08 08:42:53 +02:00
ringabout
4856beae70 fixes #23973; fixes #23974; Memory corruption with lent and ORC (#23981)
fixes #23973;
fixes #23974

(cherry picked from commit 26107e931c)
2024-08-31 13:51:52 +02:00
ringabout
568a637f0f fixes semi-regression; discard check now skips nkHiddenSubConv (#23840)
follow up https://github.com/nim-lang/Nim/pull/23681

ref https://forum.nim-lang.org/t/11987

(cherry picked from commit 648f82c2ed)
2024-08-31 13:50:28 +02:00
ringabout
8b421d2203 fixes regression; block can have arbitrary exit points; too hard for a simple analysis (#23839)
follow up https://github.com/nim-lang/Nim/pull/23681

ref https://forum.nim-lang.org/t/11987
ref https://github.com/nim-lang/Nim/issues/23836#issuecomment-2227267251

(cherry picked from commit b7a275da1d)
2024-08-31 13:49:36 +02:00
Ryan McConnell
a5237a5053 Overload resultion with generic variables an inheritance (#23870)
The test case diff is self explanatory

(cherry picked from commit c1f91c26a5)
2024-08-31 13:49:16 +02:00
metagn
d0a8637872 fix noreturn/implicit discard check logic (#23681)
fixes #10440, fixes #13871, fixes #14665, fixes #19672, fixes #23677

The false positive in #23677 was caused by behavior in
`implicitlyDiscardable` where only the last node of `if`/`case`/`try`
etc expressions were considered, as in the final node of the final
branch (in this case `else`). To fix this we use the same iteration in
`implicitlyDiscardable` that we use in `endsInNoReturn`, with the
difference that for an `if`/`case`/`try` statement to be implicitly
discardable, all of its branches must be implicitly discardable.
`noreturn` calls are also considered implicitly discardable for this
reason, otherwise stuff like `if true: discardableCall() else: error()`
doesn't compile.

However `endsInNoReturn` also had bugs, one where `finally` was
considered in noreturn checking when it shouldn't, another where only
`nkIfStmt` was checked and not `nkIfExpr`, and the node given for the
error message was bad. So `endsInNoReturn` now skips over
`skipForDiscardable` which no longer contains
`nkIfStmt`/`nkCaseStmt`/`nkTryStmt`, stores the first encountered
returning node in a var parameter for the error message, and handles
`finally` and `nkIfExpr`.

Fixing #23677 already broke a line in `syncio` so some package code
might be affected.

(cherry picked from commit 42e8472ca6)
2024-08-31 13:45:23 +02:00
metagn
7821aa94eb remove bad type inference behavior for enum identifiers (#23588)
refs
https://github.com/nim-lang/Nim/issues/23586#issuecomment-2102113750

In #20091 a bad kind of type inference was mistakenly left in where if
an identifier `abc` had an expected type of an enum type `Enum`, and
`Enum` had a member called `abc`, the identifier would change to be that
enum member. This causes bugs where a local symbol can have the same
name as an enum member but have a different value. I had assumed this
behavior was removed since but it wasn't, and CI seems to pass having it
removed.

A separate PR needs to be made for the 2.0 branch because these lines
were moved around during a refactoring in #23123 which is not in 2.0.

(cherry picked from commit c101490a0c)
2024-08-31 13:44:58 +02:00
metagn
b1e5dd605a fix wrong subtype relation in tuples & infer some conversions (#23228)
fixes #18125

Previously a tuple type like `(T, int)` would match an expected tuple
type `(U, int)` if `T` is a subtype of `U`. This is wrong since the
codegen does not handle type conversions of individual tuple elements in
a type conversion of an entire tuple. For this reason the compiler
already does not accept `(float, int)` for a matched type `(int, int)`,
however the code that checked for which relations are unacceptable
checked for `< isSubtype` rather than `<= isSubtype`, so subtypes were
not included in the unacceptable relations.

Update: Now only considered unacceptable when inheritance is used, as in
[`paramTypesMatch`](3379d26629/compiler/sigmatch.nim (L2252-L2254)).
Ideally subtype relations that don't need conversions, like `nil`,
`seq[empty]`, `range[0..5]` etc would be their own relation
`isConcreteSubtype` (which would also allow us to differentiate with
`openArray[T]`), but this is too big of a refactor for now.

To compensate for this making things like `let x: (Parent, int) =
(Child(), 0)` not compile (they would crash codegen before anyway but
should still work in principle), type inference for tuple constructors
is updated such that they call `fitNode` on the fields and their
expected types, so a type conversion is generated for the individual
subtype element.

(cherry picked from commit cfd69bad1a)
2024-08-31 13:44:37 +02:00
Ryan McConnell
87ab9b8ac2 typRel and sumGeneric adjustments (#23137)
Filling in some more logic in `typeRel` that I came across when poking
the compiler in another PR. Some of the cases where `typeRel` returns an
"incorrect" result are actually common, but `sumGeneric` ends up
breaking the tie correctly. There isn't anything wrong with that
necessarily, but I assume that it's preferred these functions behave
just as well in isolation as they do when integrated.

I will be following up this description with specific examples.

(cherry picked from commit ccc7c45d71)
2024-08-31 13:41:38 +02:00
metagn
c18e599f53 ambiguous identifier resolution (#23123)
fixes #23002, fixes #22841, refs comments in #23097

When an identifier is ambiguous in scope (i.e. multiple imports contain
symbols with the same name), attempt resolving it through type inference
(by creating a symchoice). To do this efficiently, `qualifiedLookUp` had
to be broken up so that `semExpr` can access the ambiguous candidates
directly (now obtained directly via `lookUpCandidates`).

This fixes the linked issues, but an example like:

```nim
let on = 123

{.warning[ProveInit]: on.}
```

will still fail, since `on` is unambiguously the local `let` symbol here
(this is also true for `proc on` but `proc` symbols generate symchoices
anyway).

Type symbols are not considered to not confuse the type inference. This
includes the change in sigmatch, up to this point symchoices with
nonoverloadable symbols could be created, they just wouldn't be
considered during disambiguation. Now every proper symbol except types
are considered in disambiguation, so the correct symbols must be picked
during the creation of the symchoice node. I remember there being a
violating case of this in the compiler, but this was very likely fixed
by excluding type symbols as CI seems to have found no issues.

The pure enum ambiguity test was disabled because ambiguous pure enums
now behave like overloadable enums with this behavior, so we get a
longer error message for `echo amb` like `type mismatch: got <MyEnum |
OtherEnum> but expected T`

(cherry picked from commit b280100499)
2024-08-31 12:53:43 +02:00
Ryan McConnell
d1aa568de3 Param match relax (#23033)
---------

Co-authored-by: Nikolay Nikolov <nickysn@gmail.com>
Co-authored-by: Pylgos <43234674+Pylgos@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Jason Beetham <beefers331@gmail.com>
(cherry picked from commit 94f7e9683f)
2024-08-31 12:47:25 +02:00
ringabout
352c82af89 Try to revert "disable presto" (#23987)
Reverts nim-lang/Nim#23958

follow up https://github.com/nim-lang/Nim/pull/23981

ref https://github.com/nim-lang/Nim/pull/23958#issuecomment-2294848209

(cherry picked from commit eed9cb0d3f)
2024-08-29 06:31:14 +02:00
ringabout
22149422ee fixes LineTooLong hints on old compilers (#22412)
* fixes LineTooLong hints on old compilers

* fixes config/nim.cfg

(cherry picked from commit bf5d173bc6)
2024-08-29 06:23:13 +02:00
ringabout
d6f7625626 disable presto (#23958)
(cherry picked from commit 06b25bd2c4)
2024-08-19 09:25:29 +02:00
narimiran
3e8dfde2f9 Revert "bump NimVersion to 2.0.10"
This reverts commit 92e505577e.
2024-08-19 09:25:03 +02:00
ringabout
3f183f6769 fixes #23936; opcParseFloat accepts the wrong register as the first param [backport] (#23941)
fixes #23936
follow up https://github.com/nim-lang/Nim/pull/20527

(cherry picked from commit b215ec3735)
2024-08-19 09:23:43 +02:00
Alexander Kernozhitsky
1100f550dc [backport] fixes #23796; remove extra indirection for args in importc'ed functions in cpp (#23800)
fixes #23796

(cherry picked from commit 1dcc364cd2)
2024-08-19 09:23:35 +02:00
Juan M Gómez
02eb396f45 bump nimble to include the fix to nimble dump (#23918)
(cherry picked from commit 6126a0bf46)
2024-08-14 11:55:57 +02:00
metagn
796aa78562 opensym as node kind + fixed experimental switch (#23892)
refs https://github.com/nim-lang/Nim/pull/23873#discussion_r1687995060,
fixes #23386, fixes #23385, supersedes #23572

Turns the `nfOpenSym` node flag implemented in #23091 and extended in
containing either `nkSym` or `nkOpenSymChoice`. Since this affects
macros working on generic proc AST, the node kind is now only generated
when the experimental switch `genericsOpenSym` is enabled, and a new
node flag `nfDisabledOpenSym` is set to the `nkSym` or `nkOpenSymChoice`
when the switch is not enabled so that we can give a warning.

Now that the experimental switch has more reasonable semantics, we
define `nimHasGenericsOpenSym2`.

(cherry picked from commit 0c890ff9a7)
2024-08-14 09:36:57 +02:00
metagn
1cc1451ca3 don't treat template/macro/module as overloaded for opensym (#23939)
actually fixes #23865 following up #23873

In the handling of `nkIdent` in `semExpr`, the compiler looks for the
closest symbol with the name and [checks the symbol
kind](6126a0bf46/compiler/semexprs.nim (L3171))
to also consider the overloads if the symbol kind is overloadable. But
it treats the normally overloadable template/macro/module sym kinds the
same as non-overloadable symbols, just calling `semSym` on it. We need
to mirror this behavior in `semOpenSym`; we treat the captured symchoice
as a fresh identifier, so if the symbol we find is a
template/macro/module, we use that symbol immediately as opposed to
waiting for overloads.

(cherry picked from commit a64aa51fe9)
2024-08-14 09:36:56 +02:00
metagn
dd37bb88fe implement genericsOpenSym for symchoices (#23873)
fixes #23865

The node flag `nfOpenSym` implemented in #23091 for sym nodes is now
also implemented for open symchoices. This means the intended behavior
is still achieved when multiple overloads are in scope to be captured,
so the issue is fixed. The code for the flag is documented and moved
into a helper proc and the experimental switch is now enabled for the
compiler test suite.

(cherry picked from commit 469a6044c0)
2024-08-14 09:36:56 +02:00
metagn
a88bce6106 adapt semOpAux to opt-in symchoices (#23750)
fixes #23749, refs #22716

`semIndirectOp` is used here because of the callback expressions, in
this case `db.getProc(...)`, and `semIndirectOp` calls `semOpAux` to
type its arguments before overloading starts. Hence it can opt in to
symchoices since overloading will resolve them.

(cherry picked from commit 948fc29bb2)
2024-08-14 09:08:41 +02:00
metagn
8a4ee2b84f make expressions opt in to symchoices (#22716)
refs #22605

Sym choice nodes are now only allowed to pass through semchecking if
contexts ask for them to (with `efAllowSymChoice`). Otherwise they are
resolved or treated as ambiguous. The contexts that can receive
symchoices in this PR are:

* Call operands and addresses and emulations of such, which will subject
them to overload resolution which will resolve them or fail.
* Type conversion operands only for routine symchoices for type
disambiguation syntax (like `(proc (x: int): int)(foo)`), which will
resolve them or fail.
* Proc parameter default values both at the declaration and during
generic instantiation, which undergo type narrowing and so will resolve
them or fail.

This means unless these contexts mess up sym choice nodes should never
leave the semchecking stage. This serves as a blueprint for future
improvements to intermediate symbol resolution.

Some tangential changes are also in this PR:

1. The `AmbiguousEnum` hint is removed, it was always disabled by
default and since #22606 it only started getting emitted after the
symchoice was soundly resolved.
2. Proc setter syntax (`a.b = c` becoming `` `b=`(a, c) ``) used to
fully type check the RHS before passing the transformed call node to
proc overloading. Now it just passes the original node directly so proc
overloading can deal with its typechecking.

(cherry picked from commit 5f9038a5d7)
2024-08-14 09:08:41 +02:00
SirOlaf
7b834b94da Allocator: Always place free cells into the active chunk and add documentation (#23871)
Lets single threaded applications benefit from tracking foreign cells as
well.
After this, `SmallChunk` technically doesn't need to act as a linked
list anymore I think, gotta investigate that more though.
The likelihood of overflowing `chunk.free` also rises, so to work around
that it might make sense to check `foreignCells` instead of adjusting
free space or replace free with a counter for the local capacity.

For Nim compile I can observe a ~10mb reduction, and smaller ones for
other projects.

(cherry picked from commit 881fbb8f81)
2024-08-13 15:31:16 +02:00
SirOlaf
179ae267e9 Allocator: Track number of foreign cells a small chunk has access to (#23856)
Ref: https://github.com/nim-lang/Nim/issues/23788

There was a small leak in the above issue even after fixing the
segfault. The sizes of `free` and `acc` were changed to 32bit because
adding the `foreignCells` field will drastically increase the memory
usage for programs that hold onto memory for a long time if they stay as
64bit.

(cherry picked from commit fd1e62a7e2)
2024-08-13 15:31:16 +02:00
ringabout
5d872321b3 make -d:debugHeapLinks compile again (#23126)
I have made `realloc` absorb unused adjacent memory, which improves the
performance. I'm investigating whether `deallocOsPages` can be used to
improve memory comsumption.

(cherry picked from commit 53855a9fa3)
2024-08-13 15:23:19 +02:00
Andreas Rumpf
ff1881a4c1 fixes #22510 (#23100)
(cherry picked from commit 69d0b73d66)
2024-08-13 15:22:06 +02:00
Juan M Gómez
702f8342ff bump nimble to 0.16.0 (#23883)
(cherry picked from commit ccf90f5bcb)
2024-08-01 13:33:05 +02:00
narimiran
92e505577e bump NimVersion to 2.0.10 2024-07-17 14:44:53 +02:00
metagn
1ce954a0cf make routine implicitly gensym when other gensym symbol exists again (#23842)
fixes #23813, partially reverts #23392

Before #23392, if a `gensym` symbol was defined before a proc with the
same name in a template even with an `inject` annotation, the proc would
be `gensym`. After #23392 the proc was instead changed to be `inject` as
long as no `gensym` annotation was given. Now, to keep compatibility
with the old behavior, the behavior is changed back to infer the proc as
`gensym` when no `inject` annotation is given, however an explicit
`inject` annotation will still inject the proc. This is also documented
in the manual as the old behavior was undocumented and the new behavior
is slightly different.

(cherry picked from commit cd946084ab)
2024-07-16 13:00:15 +02:00
ringabout
76e6130f64 patches for #23129 (#23198)
fixes it in the normal situation

(cherry picked from commit 30cb6826c0)
2024-07-09 20:09:41 +02:00
ringabout
83455cf1d5 fixes #23129; fixes generated hooks raise unlisted Exception, which never raise (#23195)
fixes #23129

(cherry picked from commit 62c5b8b287)
2024-07-09 20:09:41 +02:00
ringabout
be99f2fed8 fixes #22286; enforce Non-var T destructors by nimPreviewNonVarDestructor (#22975)
fixes #22286
ref https://forum.nim-lang.org/t/10642

For backwards compatibilities, we might need to keep the changes under a
preview compiler flag. Let's see how many packags it break.

**TODO** in the following PRs

- [ ] Turn the `var T` destructors warning into an error with
`nimPreviewNonVarDestructor`

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 379299a5ac)
2024-07-09 20:09:41 +02:00
Juan M Gómez
cbcf6c5be6 Bumps nimble so the next Nim release includes the latest changes (#23808)
(cherry picked from commit 14f86b3965)
2024-07-09 08:19:26 +02:00
SirOlaf
e4db9bffba Adjust the correct chunk's free space in allocator (#23795)
Fixes #23788

(cherry picked from commit 3f5016f60e)
2024-07-09 08:19:16 +02:00
Alexander Kernozhitsky
ecc7e3d41d fixes #23790; roll back instCounter properly in case of exceptions (#23802)
fixes #23790

(cherry picked from commit 841d30a213)
2024-07-08 11:17:49 +02:00
narimiran
22896b3a95 bump NimVersion to 2.0.9 2024-07-08 11:17:49 +02:00
David Krause
eaf0e7ff60 Update mimetypes.nim; added avif & avifs (#23786)
Added avif and avifs to mimetypes
2024-07-03 22:47:42 +02:00
narimiran
5935c3bfa9 bump NimVersion to 2.0.8 2024-07-02 17:05:59 +02:00
ringabout
2114414099 fixes #19977; rework inlining of 'var openarray' iterators for C++ (#23258)
fixes #19977

(cherry picked from commit f7c6e04cfb)
2024-07-02 06:06:13 +02:00
Alexander Kernozhitsky
3788aa0a99 [backport] fixes #23748; do not skip materializing temporaries for proc arguments (#23769)
fixes #23748

(cherry picked from commit 4202b606b1)
2024-06-30 18:54:32 +02:00
Alexander Kernozhitsky
e98c98b46c Comment out flaky test in tests/stdlib/thttpclient (#23772)
```
$ curl -v http://example.com/404 |& grep 'HTTP/1.1'
> GET /404 HTTP/1.1
< HTTP/1.1 500 Internal Server Error
```

So, the test with http://example.com/404 should be disabled, I think.

(cherry picked from commit c88894bf76)
2024-06-30 07:28:27 +02:00
narimiran
51723bace8 getTemp has a different signature in Nim 2.0.x 2024-06-29 13:03:12 +02:00
Juan Carlos
a90e687d26 Document move limitations (#23763)
- See
https://github.com/nim-lang/Nim/issues/23759#issuecomment-2192123783

(cherry picked from commit 179897e55f)
2024-06-29 12:57:47 +02:00
Juan M Gómez
4b42170022 Bumps nimble to entryPoints commit (#23766)
(cherry picked from commit 9f74baa49d)
2024-06-29 12:57:17 +02:00
ringabout
2eff34f08a fixes commit hashes (#23520)
(cherry picked from commit 1185b93c6d)
2024-06-29 12:57:02 +02:00
ringabout
ba51e7c4d8 bundle atlas with sat (#23375)
pending https://github.com/nim-lang/atlas/pull/119
pending AtlasStableCommit updates

(cherry picked from commit 2a7ddcab2d)
2024-06-29 12:55:30 +02:00
ringabout
d259099ef0 fixes #23759; rework move for refc (#23764)
fixes #23759

(cherry picked from commit 56ed4e0bb9)
2024-06-29 12:38:52 +02:00
ringabout
915cd5b28b fixes #9940; genericAssign does not take care of the importC variables in refc [backport] (#23761)
fixes #9940

(cherry picked from commit 828cd58d8a)
2024-06-26 18:50:37 +02:00
Andreas Rumpf
16bbffcb77 fixes #23725; Size computations work better when they are correct (#23758)
[backport]

(cherry picked from commit 8096fa45bd)
2024-06-26 08:15:51 +02:00
ringabout
73af7c60a1 nrvo for embedded importc'ed types (#23708)
(cherry picked from commit 0b5a938f57)
2024-06-25 17:42:36 +02:00
narimiran
7bdcaada13 don't use unknown proc 2024-06-24 11:16:56 +02:00
ringabout
e77e129a05 fixes #23742; setLen(0) no longer allocates memory for uninitialized strs/seqs for refc (#23745)
fixes #23742

Before my PR, `setLen(0)` doesn't free buffer if `s != nil`, but it
allocated unnecessary memory for `strs`. This PR rectifies this
behavior. `setLen(0)` no longer allocates memory for uninitialized
strs/seqs

(cherry picked from commit 2bef08774f)
2024-06-24 08:29:11 +02:00
ringabout
d0b3b7e1a7 [backport] fixes #23711; C code contains backtick`gensym (#23716)
fixes #23711

(cherry picked from commit 646bd99d46)
2024-06-24 08:28:29 +02:00
metagn
2735fd2bf5 ignore uninstantiated static on match to base type [backport:2.0] (#23731)
fixes #23730

Since #23188 the compiler errors when matching a type variable to an
uninstantiated static value. However sometimes an uninstantiated static
value is given even when only a type match is being performed to the
base type of the static type, in the given issue this case is:

```nim
proc foo[T: SomeInteger](x: T): int = int(x)
proc bar(x: static int): array[foo(x), int] = discard
discard bar(123)
```

To deal with this issue we only error when matching against a type
variable constrained to `static`.

Not sure if the `q.typ.kind == tyGenericParam and
q.typ.genericConstraint == tyStatic` check is necessary, the code above
for deciding whether the variable becomes `skConst` doesn't use it.

(cherry picked from commit 128090c593)
2024-06-24 08:26:49 +02:00
Andreas Rumpf
8d1f03e1da fixes a long standing bug with varargs type inference [backport] (#23720)
(cherry picked from commit 5996b12355)
2024-06-24 08:26:19 +02:00
ringabout
d83eb88eb9 disable dnsclient because it is fragile (#23728)
```
  Unhandled exception: /home/runner/work/Nim/Nim/pkgstemp/dnsclient/tests/test1.nim(28, 3) `rr.strings == @["dnsclient.nim"]`  [AssertionDefect]
  [FAILED] query TXT
  [OK] query MX
  [OK] query CNAME
  [OK] query SRV
  Error: execution of an external program failed: '/home/runner/work/Nim/Nim/pkgstemp/dnsclient/tests/test1'
         Tip: 2 messages have been suppressed, use --verbose to show them.
  tools.nim(36)            doCmd

      Error:  Execution failed with exit code 1
          ... Command: /home/runner/work/Nim/Nim/bin/nim c --noNimblePath -d:NimblePkgVersion=0.3.4 --hints:off -r --path:. /home/runner/work/Nim/Nim/pkgstemp/dnsclient/tests/test1
```

(cherry picked from commit c58b6e8df8)
2024-06-24 08:25:27 +02:00
narimiran
10907cc4a7 bump NimVersion to 2.0.7 2024-06-24 08:24:34 +02:00
narimiran
c00e8e71e0 bump NimVersion to 2.0.6 2024-06-16 19:01:20 +02:00
narimiran
a073e225c8 Revert "fixes #22510 (#23100)"
This reverts commit d6bc8699b9.
2024-06-16 19:01:01 +02:00
Andreas Rumpf
140d641443 fixes #22927; no test case extractable [backport] (#23707)
(cherry picked from commit 3770236bee)
2024-06-13 11:08:08 +02:00
ringabout
cc779a42ce remove pkg "pylib" (#23691)
https://github.com/Yardanico/nimpylib is 404 now
(cherry picked from commit 09b5ed251e)
2024-06-11 14:07:27 +02:00
ringabout
26a4b137c6 [backport] fixes #23690; SIGSEGV with object variants and RTTI (#23703)
fixes #23690

```nim
dest.`:state` = src.`:state`
var :tmp_553651276 = dest.e1.a
`=wasMoved`(dest.e1.a)
dest.e1.a.kind = src.e1.a.kind
case dest.e1.a.kind
of 0:
  dest.e1.a.a = src.e1.a.a
of 1:
  `=copy`(dest.e1.a.c, src.e1.a.c)
case :tmp_553651276.kind
of 0:
of 1:
  `=destroy`(:tmp_553651276.c)
```
`dest.e1.a.kind = src.e1.a.kind` changes the discrimant but it fails to
clear the memory of `dest.e1.a`. Before using hooks for copying, we need
to clear the dest, e.g. `=wasMoved(dest.e1.a.c)`.

```nim
dest.`:state` = src.`:state`
var :tmp_553651276 = dest.e1.a
`=wasMoved`(dest.e1.a)
dest.e1.a.kind = src.e1.a.kind
case dest.e1.a.kind
of 0:
  `=wasMoved`(dest.e1.a.a)
  dest.e1.a.a = src.e1.a.a
  `=wasMoved`(dest.e1.a.b)
of 1:
  `=wasMoved`(dest.e1.a.c)
  `=copy`(dest.e1.a.c, src.e1.a.c)
case :tmp_553651276.kind
of 0:
of 1:
  `=destroy`(:tmp_553651276.c)
```

(cherry picked from commit 262ff648aa)
2024-06-11 14:04:29 +02:00
Juan M Gómez
d7544ec3db [Backport 2.0] Nimsuggest handle unknown file (#23701) 2024-06-10 17:14:16 +02:00
narimiran
767a901267 Revert "Fix #22826: Don't skip generic instances in type comparison (#22828)"
This reverts commit 5e20e935dd.
2024-06-07 16:30:32 +02:00
Andreas Rumpf
36f8cccda4 fixes #23354; [backport] (#23685)
(cherry picked from commit 7039b8b5bc)
2024-06-07 15:34:34 +02:00
Andreas Rumpf
d6bc8699b9 fixes #22510 (#23100)
(cherry picked from commit 69d0b73d66)
2024-06-06 16:14:57 +02:00
ringabout
7db4376cda fixes openarray hoist with gcc 14 (#23647)
blocks https://github.com/nim-lang/Nim/pull/23673

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 17475fc5d3)
2024-06-04 10:13:14 +02:00
ringabout
a85c635da8 fixes#23665; rework spawn with gcc 14 and fixes other tests (#23660)
fixes #23665

(cherry picked from commit 08f1eac8ac)
2024-06-04 07:38:38 +02:00
Miran
3e18c48cda [backport] test more packages (#23671)
These packages are some of the dependencies of Nimbus with shorter
testing times.

(cherry picked from commit d22e8f7f82)
2024-06-03 15:06:37 +02:00
ringabout
3455623500 rework ctypes with gcc 14 (#23636)
(cherry picked from commit 4bd1cf2376)
2024-06-03 08:25:55 +02:00
Juan M Gómez
8daac1b061 [Backport 2.0] Updates nimble (#23643) 2024-06-02 15:16:04 +02:00
ringabout
7071e3a080 closes #15778; adds a test case (#23613)
closes #15778

(cherry picked from commit c08356865d)
2024-05-24 15:57:30 +02:00
ringabout
98075688f3 fixes openarray views default values in JS (#23607)
(cherry picked from commit 0fcd838fd9)
2024-05-24 15:57:15 +02:00
ringabout
5abf9a1d77 fixes #23440; fixes destruction for temporary object subclass (#23452)
fixes #23440

(cherry picked from commit f175c81079)
2024-05-24 11:18:18 +02:00
metagn
ab053fd56a remove HEAD arraymancer dependency requirement in package CI (#23509)
Was introduced to handle a break in #23392, according to
https://github.com/nim-lang/Nim/pull/23503#issuecomment-2057266475
should not be needed anymore

(cherry picked from commit 49e1ca0b3e)
2024-05-24 08:28:08 +02:00
lit
598de35d45 doc(format): ospaths2,strutils: followup #23560 (#23629)
followup #23560

(cherry picked from commit b838d3ece1)
2024-05-23 13:55:24 +02:00
lit
a88b275bc3 doc(format): system.nim: doc of hostCPU for loongarch64 (#23621)
In doc, `loongarch64` used to be written as `'"loongarch64"'`

since it's [supported](https://github.com/nim-lang/Nim/pull/19223)

(cherry picked from commit b3b26b2e56)
2024-05-23 13:55:24 +02:00
PHO
e57b207ff8 Support NetBSD/aarch64 (#23616)
I could trivially port Nim to NetBSD/aarch64 because it already
supported NetBSD and aarch64. I only needed to generate `c_code` for
this combination.

(cherry picked from commit 0ba932132e)
2024-05-23 13:55:23 +02:00
ringabout
b9951e8c87 fixes lifting subtype calling parent's hooks (#23612)
ref https://forum.nim-lang.org/t/11587

Tested with `gcc version 14.0.1 20240412` locally

(cherry picked from commit 2c8551556e)
2024-05-23 13:55:23 +02:00
ringabout
9ad0ada8e4 adds Nim-related mimetypes back (#23589)
ref https://github.com/nim-lang/Nim/pull/23226

(cherry picked from commit 1eb9aac2f7)
2024-05-23 09:02:25 +02:00
lit
30eb2b394e Improve strutils.rsplit doc, proc and iterator have oppose result order. (#23570)
[`rsplit
iterator`](https://nim-lang.org/docs/strutils.html#rsplit.i,string,char,int)
yields substring in reversed order,

while [`proc
rsplit`](https://nim-lang.org/docs/strutils.html#rsplit%2Cstring%2Cchar%2Cint)'s
order is not reversed, but its doc only declare ```
The same as the rsplit iterator, but is a func that returns a sequence
of substrings.
```

(cherry picked from commit 2e3777d6f3)
2024-05-23 09:02:19 +02:00
ringabout
6a1694b28b fixes #23552; Invalid codegen when trying to mannualy delete distinct seq (#23558)
fixes #23552

(cherry picked from commit 2995a0318b)
2024-05-23 09:01:58 +02:00
Antonis Geralis
8f5451832e Add a note about the sideeffect pragma (#23543)
(cherry picked from commit 63398b11f5)
2024-05-23 08:59:31 +02:00
Angel Ezquerra
cd65b5e5f8 Add Complex version of almostEqual function (#23549)
This adds a version of `almostEqual` (which was already available for
floats) thata works with `Complex[SomeFloat]`.

Proof that this is needed is that the first thing that the complex.nim
runnable examples block did before this commit was define (an
incomplete) `almostEqual` function that worked with complex values.

(cherry picked from commit d8e1504ed1)
2024-05-23 08:59:23 +02:00
ringabout
80a6005f55 fixes #22409; don't check style for enumFieldSymChoice in the function (#23580)
fixes #22409

(cherry picked from commit 1ad4e80060)
2024-05-23 08:59:09 +02:00
lit
cd72be29c6 fixes #23442, fix for FileId under Windows (#23444)
See according issue:

Details:
<https://github.com/nim-lang/Nim/issues/23442#issuecomment-2021763669>

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 6cc783f7f3)
2024-05-23 08:57:35 +02:00
ringabout
1425654e9d fixes #23556; typeinfo.extendSeq generates random values in ORC (#23557)
fixes #23556

It should somehow handle default fields in the future

(cherry picked from commit 36bf3fa47b)
2024-05-23 08:57:27 +02:00
lit
1463d811fb Update unicode.nim: cmpRunesIgnoreCase: fix doc format (#23560)
Its doc used to render wrongly where `>` is considered as quote block:

![image](https://github.com/nim-lang/Nim/assets/97860435/4aeda257-3231-42a5-9dd9-0052950a160e)

(cherry picked from commit d772186b2d)
2024-05-23 08:57:19 +02:00
ringabout
d372a0030d fixes #23419; internal error with void in generic array instantiation (#23550)
fixes #23419

`void` is only supported as fields of objects/tuples. It shouldn't allow
void in the array.

I didn't merge it with taField because that flag is also used for
tyLent, which is allowed in the fields of other types.

(cherry picked from commit 185e06c923)
2024-05-23 08:56:53 +02:00
ringabout
a6e729ed5d fixes #23321; Error: internal error: openArrayLoc: ref array[0..0, int] (#23548)
fixes #23321

In the function `mapType`, ptrs (tyPtr, tyVar, tyLent, tyRef)
are mapped into ctPtrToArray, the dereference of which is skipped
in the `genref`. We need to skip these ptrs in the function
`genOpenArraySlice`.

(cherry picked from commit d09c3c0f58)
2024-05-22 09:39:02 +02:00
yojiyama7
c5f2d84ac7 fix typo: "As can been seen" to "As can be seen" (#23544)
(cherry picked from commit 47594eb909)
2024-05-22 09:38:57 +02:00
ringabout
24e5e9875c fixes #23531; fixes invalid meta type accepted in the object fields (#23532)
fixes #23531
fixes #19546
fixes #6982

(cherry picked from commit f682dabf71)
2024-05-22 09:38:27 +02:00
ringabout
4e977767a7 fixes #23536; Stack trace with wrong line number when the proc called inside for loop (#23540)
fixes #23536

(cherry picked from commit 0b0f185bd1)
2024-05-22 09:28:43 +02:00
ringabout
df589bcce1 fixes #23522; fixes pre-existing wrong type for iter in liftIterSym (#23538)
fixes #23522

(cherry picked from commit 407c0cb64a)
2024-05-22 09:28:21 +02:00
ringabout
e690ff35a2 fixes #23525; an 'emit' pragma cannot be pushed (#23537)
fixes #23525

(cherry picked from commit 4601bb0255)
2024-05-22 09:24:12 +02:00
ringabout
e3f4c3d417 fixes #23524; global variables cannot be analysed when injecting move (#23529)
fixes #23524

```nim
proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
  ...
  result = n.kind == nkSym and n.sym.owner == owner and
    {sfGlobal, sfThread, sfCursor} * n.sym.flags == {} and
    (n.sym.kind != skParam or isSinkParam(n.sym))
```
In `isAnalysableFieldAccess`, globals, cursors are already rejected

(cherry picked from commit cd3cf3a20e)
2024-05-22 09:23:43 +02:00
Nikolay Nikolov
efcb6b4b11 * fix for the debug line info code generation (#23488)
Previously, in certain cases, the compiler would generate debug info for
the correct line number, but for the wrong .nim source file.

(cherry picked from commit 7e3bac9235)
2024-05-21 18:51:04 +02:00
José Paulo
5eee3e06fc fix #23518 - <expr> is crashes nimsuggest (#23523)
This solution should resolve the nimsuggest crash issue. However,
perhaps the problem is in the parser?

fix #23518

(cherry picked from commit 60af04635f)
2024-05-21 18:51:04 +02:00
ringabout
dbbd2c8002 fixes #23505; fixes injectdestructors errors on transformed addr (deref) refs (#23507)
fixes #23505

(cherry picked from commit acd4c8a353)
2024-05-21 18:51:04 +02:00
ringabout
59e49ded2d fixes #23494; Wrong type in object construction error message (#23504)
fixes #23494

(cherry picked from commit 20698b8057)
2024-05-21 18:51:03 +02:00
Pouriya Jamshidi
4bf12a086d fix JSON deep copy description (#23495)
Hi,

This is a tiny change, fixing the error in the documentation of JSON's
deep copy proc.

(cherry picked from commit 1bd0955218)
2024-05-21 18:51:03 +02:00
metagn
b1bfba9a31 stop gensym identifiers hijacking routine decl names in templates (#23392)
fixes #23326

In a routine declaration node in a template, if the routine is marked as
`gensym`, the compiler adds it as a new symbol to a preliminary scope of
the template. If it's not marked as gensym, then it searches the
preliminary scope of the template for the name of the routine, then when
it matches a template parameter or a gensym identifier, the compiler
replaces the name node with a symbol node of the found symbol.

This makes sense for the template parameter since it has to be replaced
later, but not really for the gensym identifier, as it doesn't allow us
to inject a routine with the same name as an identifier previously
declared as gensym (the problem in #23326 is when this is in another
`when` branch).

However this is the only channel to reuse a gensym symbol in a
declaration, so maybe removing it has side effects. For example if we
have:

```nim
proc foo(x: int) {.gensym.} = discard
proc foo(x: float) {.gensym.} = discard
```

it will not behave the same as

```nim
proc foo(x: int) {.gensym.} = discard
proc foo(x: float) = discard
```

behaved previously, which maybe allowed overloading over the gensym'd
symbols.

A note to the "undeclared identifier" error message has also been added
for a potential error code that implicitly depended on the old behavior
might give, namely ``undeclared identifier: 'abc`gensym123'``, which
happens when in a template an identifier is first declared gensym in
code that doesn't compile, then as a routine which injects by default,
then the identifier is used.

(cherry picked from commit 73b0b0d31c)
2024-05-21 18:51:03 +02:00
lit
a798356838 Update encodings.nim, fix open with bad arg raising no EncodingError (#23481)
On POSIX, `std/encodings` uses iconv, and `iconv_open` returns
`(iconv_t) -1` on failure, not `NULL`

(cherry picked from commit c23d6a3cb9)
2024-05-21 18:51:02 +02:00
lit
1d7170f0ed Update syncio.nim, fixes "open by FileHandle" doesn't work on Windows (#23456)
## Reprodution
if on Windows:
```Nim
when defined(windows):
  var file: File
  let succ = file.open(<aFileHandle>)
```
then `succ` will be false.

If tested, it can be found to fail with errno `22` and message: `Invalid
argument`

## Problem
After some investigations and tests,
I found it's due to the `mode` argument for `fdopen`.

Currently `NoInheritFlag`(`'N'` in Windows) is added to `mode` arg
passed to `_fdopen`, but if referring to
[Windows `_fdopen`
doc](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fdopen-wfdopen?view=msvc-170),
you'll find there is no `'N'` describled. That's `'N'` is not accepted
by `_fdopen`.

Therefore, the demo above will fail.

## In Addition
To begin with, technologically speaking, when opening with a
`fileHandle`(or called `fd`), there is no concept of fd-inheritable as
`fd` is opened already.

In POSIX, `NoInheritFlag` is defined as `e`.

It's pointed out in [POSIX `open`
man-doc](https://www.man7.org/linux/man-pages/man3/fopen.3.html) that
`e` in mode is ignored for fdopen(),

which means `e` for `fdopen()` is not wanted, just allowed.

Therefore, better to also not pass `e` to `fdopen`

---

In all, that's this PR.

(cherry picked from commit dee55f587f)
2024-05-21 18:35:22 +02:00
ringabout
eaa8c7ca7a fixes #23422; card regression (#23437)
fixes #23422

ref https://github.com/nim-lang/Nim/issues/20997
https://github.com/nim-lang/Nim/pull/21165

The function `cardSet` is used for large sets that are stored in the
form of arrays. It shouldn't be passed as a pointer

(cherry picked from commit 4b6a9e4add)
2024-05-21 18:35:04 +02:00
ringabout
5f8e08031d fixes #23429; rework --verbosity with warnings/hints (#23441)
fixes #23429

(cherry picked from commit a24990bd8c)
2024-05-21 14:52:30 +02:00
Gianmarco
c2a14cb3fc Fix compile time errors when using tables on 8/16-bits systems. (#23450)
Refer to the discussion in #23439.

(cherry picked from commit afc30a3b93)
2024-05-21 14:52:30 +02:00
arkanoid87
b3a62931cd Update manual.md (#23393)
adding link to generic == for tuples in Open and Closed symbols example

(cherry picked from commit cbf48a253f)
2024-05-21 14:52:29 +02:00
soonsouth
b213da9937 chore: fix some typos (#23412)
Signed-off-by: soonsouth <cuibuwei@163.com>
(cherry picked from commit b387bc49b5)
2024-05-21 14:52:29 +02:00
ringabout
6eb3e3134e closes #22846; adds a test case (#23374)
closes #22846

(cherry picked from commit 6ebad30e7a)
2024-05-21 14:19:42 +02:00
ringabout
1e2d98a3e0 closes #15751; adds a test case (#23372)
closes #15751

(cherry picked from commit a2584c779b)
2024-05-21 14:19:35 +02:00
ringabout
55b5068d20 closes #10219; adds a test case (#23370)
closes #10219

(cherry picked from commit d373d304ff)
2024-05-21 14:19:25 +02:00
Juan M Gómez
c17e48c9c5 makes nimsuggest listen on localhost by default (#23351)
(cherry picked from commit 2081da3207)
2024-05-21 14:19:19 +02:00
ringabout
11713ef018 remove obselete doc with nimrtl (#23358)
since nimrtl.dll is created with `--threads:on`

(cherry picked from commit a619434904)
2024-05-21 14:19:04 +02:00
Juan M Gómez
b522d1fe24 Dont mangle when targeting cpp (#23335)
Unfortunately we cant trick the debugger when targeting C++ so this one
also needs to wait for our own debugger adapter.

(cherry picked from commit 90fe1b340f)
2024-05-21 14:18:54 +02:00
autumngray
dd94d98110 Fix nimsuggest highlight for import statements (#23263)
Currently, I don't have syntax highlighting (+ no/wrong
jump-to-definition) for some import statement forms, namely:

- `import module/name/with/(slashes)`
- `import (mod) as alias`
- `import basemod/[ (sub1), (sub2) ]`

With this patch, highlight/def will work for the regions indicated by
parentheses.

(cherry picked from commit 15577043e8)
2024-05-21 14:17:58 +02:00
Juan M Gómez
2f399807cb [Backport 2.0 ] Skips generic owner when mangling instances (#23600) 2024-05-14 15:03:26 +02:00
metagn
5cecd81a05 fix semFinishOperands for bracket expressions [backport:2.0] (#23571)
fixes #23568, fixes #23310

In #23091 `semFinishOperands` was changed to not be called for `mArrGet`
and `mArrPut`, presumably in preparation for #23188 (not sure why it was
needed in #23091, maybe they got mixed together), since the compiler
handles these later and needs the first argument to not be completely
"typed" since brackets can serve as explicit generic instantiations in
which case the first argument would have to be an unresolved generic
proc (not accepted by `finishOperand`).

In this PR we just make it so `mArrGet` and `mArrPut` specifically skip
calling `finishOperand` on the first argument. This way the generic
arguments in the explicit instantiation get typed, but not the
unresolved generic proc.

(cherry picked from commit 09bd9d0b19)
2024-05-08 18:41:43 +02:00
narimiran
526e48b2ed handle the weirdness of the type of the type keyword 2024-05-03 07:35:06 +02:00
metagn
a16f126614 add switch, warning, and bind support for new generic injection behavior (#23102)
refs #23091, especially post merge comments

Unsure if `experimental` and `bind` are the perfect constructs to use
but they seem to get the job done here. Symbol nodes do not get marked
`nfOpenSym` if the `bind` statement is used for their symbol, and
`nfOpenSym` nodes do not get replaced by new local symbols if the
experimental switch is not enabled in the local context (meaning it also
works with `push experimental`). However this incurs a warning as the
fact that the node is marked `nfOpenSym` means we did not `bind` it, so
we might want to do that or turn on the experimental switch if we didn't
intend to bind it.

The experimental switch name is arbitrary and could be changed.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 4b1a841707)
2024-05-03 07:32:19 +02:00
metagn
8b815cc857 delay resolved procvar check for proc params + acknowledge unresolved statics (#23188)
fixes #23186

As explained in #23186, generics can transform `genericProc[int]` into a
call `` `[]`(genericProc, int) `` which causes a problem when
`genericProc` is resemmed, since it is not a resolved generic proc. `[]`
needs unresolved generic procs since `mArrGet` also handles explicit
generic instantiations, so delay the resolved generic proc check to
`semFinishOperands` which is intentionally not called for `mArrGet`.

The root issue for
[t6137](https://github.com/nim-lang/Nim/blob/devel/tests/generics/t6137.nim)
is also fixed (because this change breaks it otherwise), the compiler
doesn't consider the possibility that an assigned generic param can be
an unresolved static value (note the line `if t.kind == tyStatic: s.ast
= t.n` below the change in sigmatch), now it properly errors that it
couldn't instantiate it as it would for a type param. ~~The change in
semtypinst is just for symmetry with the code above it which also gives
a `cannot instantiate` error, it may or may not be necessary/correct.~~
Now removed, I don't think it was correct.

Still possible that this has unintended consequences.

(cherry picked from commit e8092a5470)
2024-05-02 12:17:23 +02:00
metagn
d43672833a allow replacing captured syms in macro calls in generics (#23091)
fixes #22605, separated from #22744

This marks symbol captures in macro calls in generic contexts as
`nfOpenSym`, which means if there is a new symbol in the local
instantiatied body during instantiation time, this symbol replaces the
captured symbol. We have to be careful not to consider symbols outside
of the instantiation body during instantiation, because this will leak
symbols from the instantiation context scope rather than the original
declaration scope. This is done by checking if the local context owner
(maybe should be the symbol of the proc currently getting instantiated
instead? not sure how to get this) is the same as or a parent owner of
the owner of the replacement candidate symbol.

This solution is distinct from the symchoice mechanisms which we
originally assumed had to be related, if this assumption was wrong it
would explain why this solution took so long to arrive at.

(cherry picked from commit 941659581a)
2024-05-02 10:02:06 +02:00
Juan M Gómez
fcb8461efa Fixes an issue where exported types werent being cgen with the exportc pragma (#23369)
(cherry picked from commit 78c834dd76)
2024-04-28 06:57:55 +02:00
ringabout
871cd4b9db fixes refc with non-var destructor; cancel warnings (#23156)
fixes https://forum.nim-lang.org/t/10807

(cherry picked from commit 35ec9c31bd)
2024-04-27 20:00:30 +02:00
ringabout
fa78d937dc fixes #22597; avoid side effects for call returning openArray types (#23257)
fixes #22597

```nim
proc autoToOpenArray*[T](s: Slice[T]): openArray[T] =
  echo "here twice"
  result = toOpenArray(s.p, s.first, s.last)
```
For functions returning openarray types, `fixupCall` creates a temporary
variable to store the return value: `let tmp = autoToOpenArray()`. But
`genOpenArrayConv` cannot handle openarray assignements with side
effects. It should have stored the right part of the assignment first
instead of calling the right part twice.

(cherry picked from commit d44b0b1869)
2024-04-27 20:00:30 +02:00
metagn
b302b3102e don't use previous bindings of auto for routine return types (#23207)
fixes #23200, fixes #18866

not turned to `tyUntyped`. This had the side effect that anything
previously bound to `tyAnything` in the proc type match was then bound
to the proc return type, which is wrong since we don't know the proc
return type even if we know the expected parameter types (`tyUntyped`
also [does not care about its previous bindings in
`typeRel`](ab4278d217/compiler/sigmatch.nim (L1059-L1061))
maybe for this reason).

Now we mark `tyAnything` return types for routines as `tfRetType` [as
done for other meta return
types](18b5fb256d/compiler/semtypes.nim (L1451)),
and ignore bindings to `tyAnything` + `tfRetType` types in `semtypinst`.
On top of this, we reset the type relation in `paramTypesMatch` only
after creating the instantiation (instead of trusting
`isInferred`/`isInferredConvertible` before creating the instantiation),
using the same mechanism that `isBothMetaConvertible` uses.

This fixes the issues as well as making the disabled t15386_2 test
introduced in #21065 work. As seen in the changes for the other tests,
the error messages give an obscure `proc (a: GenericParam): auto` now,
but it does give the correct error that the overload doesn't match
instead of matching the overload pre-emptively and expecting a specific
return type.

tsugar had to be changed due to #16906, which is the problem where
`void` is not inferred in the case where `result` was never touched.

(cherry picked from commit f46f26e79a)
2024-04-27 20:00:30 +02:00
ringabout
eb3aa70ffa fixes #22939; fixes #16890; push should but doesn't apply to importc … (#22944)
…var/let symbols

fixes #22939
fixes #16890

Besides, it was applied to let/const/var with pragmas, now it is
universally applied.

```nim
{.push exportc.}
proc foo =
  let bar = 12
  echo bar
{.pop.}
```

For example, the `bar` variable will be affected by `exportc`.

(cherry picked from commit cecaf9c56b)
2024-04-26 14:27:17 +02:00
ringabout
72a2fe5125 fixes broken nightlies; follow up #22544 (#22585)
ref https://github.com/nim-lang/nightlies/actions/runs/5970369118/job/16197865657

> /home/runner/work/nightlies/nightlies/nim/lib/pure/os.nim(678, 30) Error: getApplOpenBsd() can raise an unlisted exception: ref OSError

(cherry picked from commit 1fcb53cded)
2024-04-24 06:48:51 +02:00
narimiran
e582f1ccb3 Revert "Look up generic parameters when found inside semOverloadedCall, fixin… (#23054)"
This reverts commit 54bd380011.
2024-04-23 18:01:24 +02:00
narimiran
0e1a699937 Revert "Overloads passed to static proc parameters now convert to the desired… (#23063)"
This reverts commit 82e77a13f3.
2024-04-23 18:01:12 +02:00
bptato
494b5486ba Fix std/base64.decode out of bounds read (#23526)
inputLen may end up as 0 in the loop if the input string only includes
trailing characters. e.g. without the patch, decode(" ") would panic.

(cherry picked from commit 30cf570af9)
2024-04-23 06:57:55 +02:00
narimiran
33817f2c30 Revert "fixes #22923; fixes =dup issues (#23182)"
This reverts commit fbb9ce4d5c.
2024-04-23 06:57:09 +02:00
Gianmarco
f44c49c5bd Change unicode lookup tables to have int32 elements to support platforms where sizeof(int) < 4 (#23433)
Fixes an issue that comes up when using strutils.`%` or any other
strutils/strformat feature that uses the unicode lookup tables behind
the scenes, on systems where ints are than 32-bit wide.

Tested with:

```bash
./koch test cat lib
```

Refer to the discussion in #23125.

(cherry picked from commit 4c38569229)
2024-04-22 16:18:24 +02:00
Igor Sirotin
3dd5e11480 fix: use ErrorColor for hints marked as errors (#23430)
# Description

When using `--hintAsError`, we want some red color to appear in the
logs.
Same is already done for `warningAsError`.

# Cherry-picking to Nim 1.6

Would be nice to cherry-pick this and the `warningAsError` log highlight
to 1.6 branch, as it's used in status-desktop.

(cherry picked from commit 50c1e93a74)
2024-04-22 16:18:16 +02:00
ringabout
716ff93161 fixes #23401; prevents nrvo for cdecl procs (#23409)
fixes #23401

(cherry picked from commit f639cf063f)
2024-04-22 16:18:08 +02:00
metagn
1ac5aa951d propagate efWantStmt in semWhen (#23400)
fixes #23399

The new case introduced in #21657 is triggered by `efWantStmt` but the
`when` statement doesn't normally propagate this flag, so propagate it
when the `semCheck` param in `semWhen` is true which happens when the
`when` statement is `efWhenStmt` anyway.

(cherry picked from commit fb6c805568)
2024-04-22 16:17:56 +02:00
ringabout
d112874078 fixes #22166; adds sideeffects for close and setFilePos (#23380)
fixes #22166

(cherry picked from commit 1e20165a15)
2024-04-22 16:17:09 +02:00
ringabout
61da33f31b fixes #22284; fixes #22282; don't override original parameters of inferred lambdas (#23368)
fixes #22284
fixes #22282

```
Error: j(uRef, proc (config: F; sources: auto) {.raises: [].} = discard ) can raise an unlisted exception: Exception
```

The problem is that `n.typ.n` contains the effectList which shouldn't
appear in the parameter of a function defintion. We could not simply use
`n.typ.n` as `n[paramsPos]`. The effect lists should be stripped away
anyway.

(cherry picked from commit 320311182c)
2024-04-22 16:16:57 +02:00
ringabout
e15aa20059 fixes sink regression for ORC; ref #23354 (#23359)
ref #23354

The new move analyzer requires types that have the tfAsgn flag
(otherwise `lastRead` will return true); tfAsgn is included when the
destructor is not trival. But it should consider the assignement for
objects in this case because objects might have a trival destructors but
it's the assignement that matters when it is passed to sink parameters.

(cherry picked from commit 572b0b67ff)
2024-04-22 10:22:28 +02:00
ringabout
8d7b7ff861 fixes #13481; fixes #22708; disable using union objects in VM (#23362)
fixes #13481;
fixes #22708

Otherwise it gives implicit results or bad codegen

(cherry picked from commit 31d7554524)
2024-04-22 10:22:28 +02:00
Jacek Sieka
d389310bb9 strformat: detect format string errors at compile-time (#23356)
This also prevents unwanted `raises: [ValueError]` effects from bubbling
up from correct format strings which makes `fmt` broadly unusable with
`raises`.

The old runtime-based `formatValue` overloads are kept for
backwards-compatibility, should anyone be using runtime format strings.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit a1e41930f8)
2024-04-22 10:22:28 +02:00
ringabout
1ae6deda61 fixes #22723; skips tyUserTypeClasses in injectdestructors (#23341)
fixes #22723

(cherry picked from commit 6ce6cd4bb8)
2024-04-22 10:22:28 +02:00
ringabout
6d38eafda1 fixes #23304; uses snprintf instead of sprintf (#23322)
fixes #23304

(cherry picked from commit dfd778d056)
2024-04-22 10:22:28 +02:00
heterodoxic
845be91df5 assume a module's usage if it contains a passC/passL/compile pragma w… (#23323)
…hich conveys effects beyond its module scope for C/C++
codegen(suppresses current UnusedImport warning)

Just a minor inconvenience working in the area of C/C++ integration I
guess, but here we go:

I noticed receiving ```UnusedImport``` warnings for modules having only
```passC```/```passL```/```compile``` pragmas around. I gather the
compiler cannot actually infer those modules being unused as they *may*
have consequences for the whole build process (as they did in my simple
case).

Thus, I hereby suggest adding the `sfUsed` flag to the respective module
in order to suppress the compiler's warning.

I reckon other pragmas should be put into consideration as well: I will
keep up the investigation with PR followups.

(cherry picked from commit 9a46230335)
2024-04-22 10:22:27 +02:00
ringabout
fa003a00ee fixes regression #22909; don't optimize result init if statements can raise which corrupts the compiler (#23271)
fixes #22909
required by https://github.com/nim-lang/Nim/pull/23267

```nim
proc foo: string =
  assert false
  result = ""
```

In the function `foo`, `assert false` raises an exception, which can
cause `result` to be uninitialized if the default result initialization
is optimized out

(cherry picked from commit 7d9721007c)
2024-04-22 08:53:16 +02:00
ringabout
45f1b19942 clean up goto exceptions; remove the setjmp.h dep (#23259)
(cherry picked from commit e3350cbe6f)
2024-04-22 08:53:03 +02:00
ringabout
96917755cd fixes #23247; don't destroy openarray since it doesn't own the data (#23254)
fixes #23247
closes #23251 (which accounts for why the openarray type is lifted
because ops are lifted for openarray conversions)

related: https://github.com/nim-lang/Nim/pull/18713

It seems to me that openarray doesn't own the data, so it cannot destroy
itself. The same case should be applied to
https://github.com/nim-lang/Nim/issues/19435. It shouldn't be destroyed
even openarray can have a destructor. A cleanup will be followed for
https://github.com/nim-lang/Nim/pull/19723 if it makes sense.

According to https://github.com/nim-lang/Nim/pull/12073, it lifts
destructor for openarray when openarray is sunk into the function, when
means `sink openarray` owns the data and needs to destroy it. In other
cases, destructor shouldn't be lifted for `openarray` in the first place
and it shouldn't destroy the data if it doesn't own it.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 24a606902a)
2024-04-22 08:52:55 +02:00
Bung
8a7a776034 fix mime types data (#23226)
generated via https://github.com/bung87/mimetypes_gen

source data:
http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types?view=co

(cherry picked from commit 01097fc1fc)
2024-04-20 09:44:31 +02:00
Angel Ezquerra
e33d96ad4e Make std/math classify work without --passc:-fast-math. (#23211)
By using the existing isNaN function we can make std/math's classify
function work even if `--passc:-fast-math` is used.

(cherry picked from commit 38f9ee0e58)
2024-04-20 09:44:31 +02:00
ringabout
5a2cd98867 fixes #22218; avoids cursor when copy is disabled (#23209)
fixes #22218

(cherry picked from commit b2f79df81c)
2024-04-20 09:44:31 +02:00
ringabout
a1b310d186 fixes #12334; keeps nkHiddenStdConv for cstring conversions (#23216)
fixes #12334

`nkHiddenStdConv` shouldn't be removed if the sources aren't literals,
viz. constant symbols.

(cherry picked from commit 3fb46fac32)
2024-04-20 09:44:31 +02:00
metagn
f97c0cced0 error on large integer types as array index range (#23229)
fixes #17163, refs #23204

Types that aren't `tyRange` and are bigger than 16 bits, so `int32`,
`uint64`, `int` etc, are disallowed as array index range types.
`tyRange` is excluded because the max array size is backend independent
(except for the specific size of `high(uint64)` which crashes the
compiler) and so there should still be an escape hatch for people who
want bigger arrays.

(cherry picked from commit 3ab8b6b2cf)
2024-04-20 09:44:31 +02:00
ringabout
2c964268f8 fixes #23223; prevents insert self-assignment (#23225)
fixes #23223

(cherry picked from commit 3379d26629)
2024-04-20 09:44:30 +02:00
ringabout
a715aeb716 fixes #23180; fixes #19805; prohibits invalid tuple unpacking code in for loop (#23185)
fixes #23180
fixes #19805

(cherry picked from commit ab4278d217)
2024-04-20 09:44:30 +02:00
ringabout
d57200bc6f fixes #15924; Tuple destructuring is broken with closure iterators (#23205)
fixes #15924

(cherry picked from commit 8484abc2e4)
2024-04-20 09:44:30 +02:00
ringabout
fbb9ce4d5c fixes #22923; fixes =dup issues (#23182)
fixes #22923

(cherry picked from commit 29ac3c9986)
2024-04-20 09:44:29 +02:00
metagn
76735147b3 trigger range check with new type inference on nkIntLit [backport:1.6] (#23179)
fixes #23177

`changeType` doesn't perform range checks to see if the expression fits
the new type [if the old type is the same as the new
type](62d8ca4306/compiler/semexprs.nim (L633)).
For `nkIntLit`, we previously set the type to the concrete base of the
expected type first, then call `changeType`, which works for things like
range types but not bare types of smaller bit size like `int8`. Now we
don't set the type (so the type is nil), and `changeType` performs the
range check when the type is unset (nil).

(cherry picked from commit 00be8f287a)
2024-04-19 18:31:38 +02:00
metagn
c2d297cc3c don't transform typed bracket exprs to [] calls in templates (#23175)
fixes #22775

It's pre-existing that [`prepareOperand` doesn't typecheck expressions
which have
types](a4f3bf3742/compiler/sigmatch.nim (L2444)).
Templates can take typed subscript expressions, transform them into
calls to `[]`, and then have this `[]` not be resolved later if the
expression is nested inside of a call argument, which leaks an untyped
expression past semantic analysis. To prevent this, don't transform any
typed subscript expressions into calls to `[]` in templates. Ditto for
curly subscripts (with `{}`) and assignments to subscripts and curly
subscripts (with `[]=` and `{}=`).

(cherry picked from commit 62d8ca4306)
2024-04-19 16:42:44 +02:00
Ryan McConnell
4886534ed3 Fixes #23172 (#23173)
#23172

(cherry picked from commit a4f3bf3742)
2024-04-19 16:42:34 +02:00
ringabout
2ed16bf2d4 fixes #23139; Cannot get repr of range type of enum (#23164)
fixes #23139

(cherry picked from commit 3dee1a3e4c)
2024-04-19 16:42:27 +02:00
ringabout
c3d043e980 fixes #23167; take nkOpenSymChoice into consideration caused by templates [backport] (#23168)
fixes #23167

(cherry picked from commit 4eaa3b028c)
2024-04-19 16:39:22 +02:00
Jacek Sieka
0cdca3a0cd Recommend hanging indent in NEP1 (#23105)
This PR modernises the NEP1 style guide to prefer hanging indent over
vertial alignment for long code statements while still allowing
alignment in legacy code.

The change is based on research and study of existing style guides for
both braced and indented languages that have seen wide adoption as well
as working with a large Nim codebase with several teams touching the
same code regularly.

The research was done as part of due diligence leading up to
[nph](https://github.com/arnetheduck/nph) which uses this style
throughout.

There are several reasons why hanging indent works well for
collaboration, good code practices and modern Nim features:

* as NEP1 itself points out, alignment causes unnecessary friction when
refactoring, adding/removing items to lists and otherwise improving code
style or due to the need for realignment - the new recommendation aligns
NEP1 with itself
* When collaborating, alignment leads to unnecessary git conflicts and
blame changes - with hanging indent, such conflicts are minimised.
* Vertical alignment pushes much of the code to the right where often
there is little space - when using modern features such as generics
where types may be composed of several (descriptively named) components,
there is simply no more room for parameters or comments
* The space to the left of the alignemnt cannot productively be used for
anything (unlike on the right, where comments may be placed)
* Double hanging indent maintaines visual separation between parameters
/ condition and the body that follows.

This may seem like a drastic change, but in reality, it is not:

* the most popular editor for Nim (vscode) already promotes this style
by default (if you press enter after `(`, it will jump to an indent on
the next line)
* although orthogonal to these changes, tools such as `nph` can be used
to reformat existing code should this be desired - when done in a single
commit, `git blame` is not lost and neither are exsting PRs (they can
simply be reformatted deterministically) - `nph` is also integrated with
vscode.
* It only affects long lines - ie most code remains unchanged

Examples of vertical alignment in the wild, for wildly successful
languages and formatters:

* [PEP-8](https://peps.python.org/pep-0008/#indentation)
*
[black](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#how-black-wraps-lines)
* [prettier](https://prettier.io/docs/en/)

The above examples are useful mainly to show that hanging-indent
_generally_ is no impediment to efficient code reading and on the whole
is an uncontroversial choice as befits the standard library.

(cherry picked from commit c4f98b7696)
2024-04-19 16:39:13 +02:00
Gianmarco
5e22f6ca58 Fix cmpRunesIgnoreCase on system where sizeof(int) < 4. Fixes #23125. (#23138)
Fixes an issue where importing the `strutils` module, or any other
importing the `strutils` module, ends up with a compile time error on
platforms where ints are less then 32-bit wide.

The fix follows the suggestions made in #23125.

(cherry picked from commit 15c7b76c66)
2024-04-19 16:37:28 +02:00
metagn
f8d538f4ad fix spurious indent and newlines in rendering of nkRecList (#23121)
Rendering of `nkRecList` produces an indent and adds a new line at the
end. However for things like case object `of`/`else` branches or `when`
branches this is already done, so this produces 2 indents and an extra
new line. Instead, just add an indent in the place where the indent that
`nkRecList` produces is needed, for the rendering of the final node of
`nkObjectTy`. There doesn't seem to be a need to add the newline.

Before:

```nim
case x*: bool
of true:
    y*: int

of false:
  nil
```

After:

```nim
case x*: bool
of true:
  y*: int
of false:
  nil
```

(cherry picked from commit fc49c6e3ba)
2024-04-19 16:37:23 +02:00
Jake Leahy
8efdc313a3 Don't crash for invalid toplevel parseStmt/Expr calls (#23089)
This code will crash `check`/`nimsuggest` since the `ra` register is
uninitialised

```nim
import macros

static:
  discard parseExpr("'")
```
Now it assigns an empty node so that it has something

Testament changes were so I could properly write a test. It would pass
even with a segfault since it could find the error

(cherry picked from commit db9d8003b0)
2024-04-19 16:37:16 +02:00
Jake Leahy
49cc3c5746 Mark macros.error as .noreturn. (#23081)
Closes #14329

Marks `macros.error` as `.noreturn` so that it can be used in
expressions. This also fixes the issue that occurred in #19659 where a
stmt that could be an expression (Due to having `discardable` procs at
the end of other branches) would believe a `noreturn` proc is returning
the same type e.g.
```nim
 proc bar(): int {.discardable.} = discard

if true: bar()
else: quit(0) # Says that quit is of type `int` and needs to be used/discarded except it actually has no return type
```

(cherry picked from commit b3b87f0f8a)
2024-04-19 16:35:26 +02:00
Jake Leahy
865a2f895e Allow parseAll to parse statements separated by semicolons (#23088)
Fixes the second issue listed in #9918.

Fixed by replacing the logic used in `parseAll` with just a continious
loop to `complexOrSimpleStmt` like what the [normal parser
does](https://github.com/nim-lang/Nim/blob/devel/compiler/passes.nim#L143-L146).
`complexOrSimpleStmt` [guarantees
progress](https://github.com/nim-lang/Nim/blob/devel/compiler/parser.nim#L2541)
so we don't need to check progress ourselves.

Also allows `nimpretty` to parse more valid Nim code such as
```nim
proc foo(); # Would complain about indention here
proc foo() =
  # ...
```

(cherry picked from commit 0bd4d80238)
2024-04-19 16:35:07 +02:00
Jason Beetham
82e77a13f3 Overloads passed to static proc parameters now convert to the desired… (#23063)
… type mirroring proc params

(cherry picked from commit 91efa49550)
2024-04-19 14:01:22 +02:00
Pylgos
fca71c4bb4 fixes #9381; Fix double evaluation of types in generic objects (#23072)
fixes https://github.com/nim-lang/Nim/issues/9381

(cherry picked from commit 1b7b0d69db)
2024-04-19 14:01:07 +02:00
ringabout
3d4ec68e54 fixes #23060; editDistance wrongly compare the length of rune strings (#23062)
fixes #23060

(cherry picked from commit 7e1ea50bc3)
2024-04-19 14:00:01 +02:00
Jason Beetham
54bd380011 Look up generic parameters when found inside semOverloadedCall, fixin… (#23054)
…g static procs

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 8cc3c774c8)
2024-04-19 13:59:54 +02:00
narimiran
55905604da Revert "fixes #22913; fixes #12985 differently push-ing pragma exportc genera… (#22941)"
This reverts commit d566d21730.
2024-04-19 08:12:35 +02:00
Jakub
fd64402e47 allow Nix builds by not calling git in isGitRepo for Nimble (#23515)
Because `isGitRepo()` call requires `/bin/sh` it will always fail when
building Nim in a Nix build sandbox, and the check doesn't even make
sense if Nix already provides Nimble source code.

Since for Nimble `allowBundled` is set to `true` this effectlvely does
not change behavior for normal builds, but does avoid ugly hacks when
building in Nix which lacks `/bin/sh` and fails to call `git`.

Reference:
*
https://github.com/status-im/nimbus-eth2/pull/6180#discussion_r1570237858

Signed-off-by: Jakub Sokołowski <jakub@status.im>
(cherry picked from commit d6823f4776)
2024-04-18 12:28:06 +02:00
ringabout
c696ec92db fixes #23001; give a better warning for PtrToCstringConv (#23005)
fixes #23001

(cherry picked from commit 7ea5aaaebb)
2024-04-18 10:34:01 +02:00
SirOlaf
4bc45bb6bc Fix endsInNoReturn for case statements (#23009)
While looking at the CI I noticed that there's a couple false positives
for `case` statements that cannot be checked for exhaustiveness since my
changes, this should resolve them.

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit 9140f8e221)
2024-04-18 10:33:54 +02:00
ringabout
9f35ede1a8 fixes #22926; Different type inferred when setting a default value for an array field (#22999)
fixes #22926

(cherry picked from commit 96513b2506)
2024-04-18 10:33:47 +02:00
ringabout
51fa2fada1 fixes #22996; typeAllowedCheck for default fields (#22998)
fixes #22996

(cherry picked from commit 795aad4f2a)
2024-04-18 10:33:25 +02:00
John Viega
aed04c6405 fix: std/marshal unmarshaling of ref objects (#22983)
Fixes #16496

![Marshal doesn't properly unmarshal *most* ref objects; the exceptions
being nil
ones](https://github-production-user-asset-6210df.s3.amazonaws.com/4764481/285471431-a39ee2c5-5670-4b12-aa10-7a10ba6b5b96.gif)
Test case added.

Note that this test (t9754) does pass locally, but there are tons of
failures by default on OS X arm64, mostly around the bohem GC, so it's
pretty spammy, and could easily have missed something. If there are
better instructions please do let me know.

---------

Co-authored-by: John Viega <viega@Johns-MacBook-Pro.local>
Co-authored-by: John Viega <viega@Johns-MBP.localdomain>
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 5b2fcabff5)
2024-04-18 10:33:14 +02:00
ringabout
d566d21730 fixes #22913; fixes #12985 differently push-ing pragma exportc genera… (#22941)
…tes invalid C identifiers

fixes #22913
fixes #12985 differently

`{.push.} now does not apply to generic instantiations`

(cherry picked from commit 5dafcf4957)
2024-04-18 10:30:56 +02:00
Derek
5c4c8c44dc let InotifyEvent type sizeof-able (#22958)
Since the `InotifyEvent`s are receive through `read()`, user need the
size of the type.

(cherry picked from commit 0f7488e20f)
2024-04-18 10:30:51 +02:00
握猫猫
47f1ab7b97 Fix OSError errorCode field is not assigned a value (#22954)
In this PR, the following changes were made:
1. Replaced `raise newException(OSError, osErrorMsg(errno))` in batches
with `raiseOSError(errcode)`.
2. Replaced `newException(OSError, osErrorMsg(errno))` in batches with
`newOSError(errcode)`.

There are still some places that have not been replaced. After checking,
they are not system errors in the traditional sense.

```nim
proc dlclose(lib: LibHandle) =
  raise newException(OSError, "dlclose not implemented on Nintendo Switch!")
```

```nim
if not fileExists(result) and not dirExists(result):
  # consider using: `raiseOSError(osLastError(), result)`
  raise newException(OSError, "file '" & result & "' does not exist")
```

```nim
proc paramStr*(i: int): string =
  raise newException(OSError, "paramStr is not implemented on Genode")
```

(cherry picked from commit 39fbd30513)
2024-04-18 10:30:46 +02:00
ringabout
710801d880 fixes #22932; treats closure iterators as pointers (#22934)
fixes #22932
follow up https://github.com/nim-lang/Nim/pull/21629

---------

Co-authored-by: Nickolay Bukreyev <SirNickolas@users.noreply.github.com>
(cherry picked from commit 0dc3513613)
2024-04-18 10:30:40 +02:00
ringabout
39d0eb3a58 fixes #22673; Cannot prove that result is initialized for a placehold… (#22915)
…er base method returning a lent

fixes #22673

(cherry picked from commit 2e070dfc76)
2024-04-18 10:30:34 +02:00
Jacek Sieka
71dde8f7cf reserve sysFatal for Defect (#22158)
Per manual, `panics:on` affects _only_ `Defect`:s - thus `sysFatal`
should not redirect any other exceptions.

Also, when `sysFatal` is used in `nimPanics` mode, it should use regular
exception handling pipeline to ensure exception hooks are called
consistently for all raised defects.

(cherry picked from commit 58c44312af)
2024-04-18 10:30:26 +02:00
ringabout
683a1213db fixes #22860; suppress AnyEnumConv warning when iterating over set (#22904)
fixes #22860

(cherry picked from commit af556841ac)
2024-04-18 10:30:16 +02:00
ringabout
3ae3050b80 fixes #22902; borrow from proc return type mismatch (#22908)
fixes #22902

(cherry picked from commit 95e5ad6927)
2024-04-18 10:30:09 +02:00
ringabout
bd829c093d fixes #22883; replace default(typeof( with reset; suppress `Unsaf… (#22895)
fixes #22883

…eDefault` warnings

avoid issues mentioned by https://forum.nim-lang.org namely, it
allocated unnecessary stack objects in the loop

```c
while (1)
{
tyObject_N__8DSNqSGSHBKOhI8CqSgAow T5_;
nimZeroMem((void *)(&T5_), sizeof(tyObject_N__8DSNqSGSHBKOhI8CqSgAow));
eqsink___test4954_u450((&(*t_p0).data.p->data[i].Field1), T5_);
}
```

It might be more efficient in some cases

follow up https://github.com/nim-lang/Nim/pull/21821

(cherry picked from commit 92141e82ed)
2024-04-18 10:29:59 +02:00
SirOlaf
5e20e935dd Fix #22826: Don't skip generic instances in type comparison (#22828)
Close #22826

I am not sure why this code skips generic insts, so letting CI tell me.
Update: It has told me nothing. Maybe someone knows during review.

Issue itself seems to be that the generic instance is skipped thus it
ends up being just `float` which makes it use the wrong generic instance
of the proc because it matches the one in cache

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit c13c48500b)
2024-04-18 10:29:53 +02:00
ringabout
106c7d2afb fixes #22844; uses arrays to store holeyenums for iterations; much more efficient than sets and reasonable for holeyenums (#22845)
fixes #22844

(cherry picked from commit e10878085e)
2024-04-18 10:29:47 +02:00
ringabout
755a15d8d4 fixes #19250; fixes #22259; ORC AssertionDefect not containsManagedMemory(n.typ) (#22823)
fixes #19250
fixes #22259

The strings, seqs, refs types all have this flag, why should closures be
treated differently?

follow up https://github.com/nim-lang/Nim/pull/14336

(cherry picked from commit f5d70e7fa7)
2024-04-18 10:29:33 +02:00
ringabout
a5a6a4d39e fixes #22790; use cast suppress AnyEnumConv warnings for enums withou… (#22813)
…t holes

fixes #22790

(cherry picked from commit ecaccafa6c)
2024-04-18 09:04:17 +02:00
ringabout
3120c6e839 use lent for the return value of index accesses of tables (#22812)
ref https://forum.nim-lang.org/t/10525

(cherry picked from commit 9d7acd001f)
2024-04-18 09:03:06 +02:00
ringabout
0d255b4ea1 suppress incorrect var T destructor warnings for newFinalizer in stdlib (#22810)
in `std/nre`
```nim
proc initRegex(pattern: string, flags: int, study = true): Regex =
  new(result, destroyRegex)
```
gives incorrect warnings like

```
C:\Users\blue\Documents\Nim\lib\impure\nre.nim(252, 6) Error: A custom '=destroy' hook which takes a 'var T' parameter is deprecated; it should take a 'T' parameter [Deprecated
```

(cherry picked from commit 14d25eedfd)
2024-04-18 09:02:55 +02:00
ringabout
e9067c03c6 allows cast int to bool/enum in VM (#22809)
Since they are integer types, by mean of allowing cast integer to enums
in VM, we can suppress some enum warnings in the stdlib in the unified
form, namely using a cast expression.

(cherry picked from commit 2cf214d6d4)
2024-04-18 09:02:44 +02:00
ringabout
999d29d2a0 fixes #8893; guard against array access in renderer (#22807)
fixes #8893

(cherry picked from commit 81b2ae747e)
2024-04-18 09:02:38 +02:00
ringabout
08d37c2d7e fixes #22787; marks var section in the loop as reassign preventing cursor (#22800)
fixes #22787

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit efa64aa49b)
2024-04-18 09:02:29 +02:00
Ryan McConnell
4f78a4dd3e Make typeRel behave to spec (#22261)
The goal of this PR is to make `typeRel` accurate to it's definition for
generics:
```
# 3) When used with two type classes, it will check whether the types
# matching the first type class (aOrig) are a strict subset of the types matching
# the other (f). This allows us to compare the signatures of generic procs in
# order to give preferrence to the most specific one:
```

I don't want this PR to break any code, and I want to preserve all of
Nims current behaviors. I think that making this more accurate will help
serve as ground work for the future. It may not be possible to not break
anything but this is my attempt.

So that it is understood, this code was part of another PR (#22143) but
that problem statement only needed this change by extension. It's more
organized to split two problems into two PRs and this issue, being
non-breaking, should be a more immediate improvement.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit b2ca6bedae)
2024-04-18 09:01:14 +02:00
ringabout
bb82d46ef1 fixes #22696; func strutils.join for non-strings uses proc $ which can have side effects (#22770)
fixes #22696
partially revert https://github.com/nim-lang/Nim/pull/16281

`join` calls `$` interally, which might introduce a sideeffect call.

(cherry picked from commit 5eeafbf550)
2024-04-18 09:01:09 +02:00
Juan M Gómez
567900be76 case macro now can be used inside generic. Fixes #20435 (#22752)
fixes #20435

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Jake Leahy <jake@leahy.dev>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 0c179db657)
2024-04-18 09:01:03 +02:00
ringabout
cb899ccf25 ref #19727; implement setLenUninit for seqsv2 (#22767)
ref #19727

(cherry picked from commit 285cbcb6aa)
2024-04-18 09:00:58 +02:00
ringabout
710fd14393 fixes #10542; suppresses varargs conversion warnings (#22757)
fixes #10542
revives and close #20169

(cherry picked from commit a7a0cfe8eb)
2024-04-18 09:00:51 +02:00
ringabout
499ad5b63c fixes #22706; turn "unknown hint" into a hint (#22755)
fixes #22706

(cherry picked from commit 3979e83fcb)
2024-04-18 09:00:46 +02:00
ringabout
8ab6cf1ca8 fixes #22246; generate __builtin_unreachable hints for case defaults (#22737)
fixes #22246
resurrects #22350

(cherry picked from commit a1b6fa9420)
2024-04-18 09:00:35 +02:00
ringabout
577ffbc57c items, pairs and friends now use unCheckedInc (#22729)
`{.push overflowChecks: off.}` works in backends. Though it could be
implemented as a magic function.

By inspecting the generated C code, the overflow check is eliminated in
the debug or release mode.

![image](https://github.com/nim-lang/Nim/assets/43030857/49c3dbf4-675e-414a-b972-b91cf218c9f8)

Likewise, the index checking is probably not needed.

(cherry picked from commit d82bc0a29f)
2024-04-18 09:00:28 +02:00
Juan M Gómez
e918a762f7 fixes compiler crash by preventing exportc on generics (#22731)
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit fefde3a735)
2024-04-18 09:00:05 +02:00
metagn
d56000eaff make parseEnum skip type aliases for enum type sym (#22727)
fixes #22726

(cherry picked from commit 51cb493b22)
2024-04-18 08:59:51 +02:00
litlighilit
cc7f76a247 Update osfiles.nim, make moveFile consider permission on *nix (#22719)
see https://github.com/nim-lang/Nim/issues/22674

(cherry picked from commit 741285b335)
2024-04-18 08:59:35 +02:00
ringabout
adf3e3ceb5 fixes incorrect cint overflow in system (#22718)
fixes #22700

(cherry picked from commit 63c2ea5566)
2024-04-18 08:59:28 +02:00
SirOlaf
344feb0dd1 Fix #22713: Make size unknown for tyForward (#22714)
Close #22713

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit fcf4c1ae17)
2024-04-17 16:02:18 +02:00
metagn
dc6058fb9b implement semgnrc for tuple and object type nodes (#22709)
fixes #22699

(cherry picked from commit 8836207a4e)
2024-04-17 16:01:48 +02:00
Amjad Ben Hedhili
bbf32118a2 followup of #22568 (#22690)
(cherry picked from commit 38b58239e8)
2024-04-17 16:01:36 +02:00
metagn
b2cb5f55ac refactor semtempl ident declarations, some special word use (#22693)
`semtempl` is refactored to combine the uses of `getIdentNode`,
`onlyReplaceParams`, `isTemplParam` and most of `replaceIdentBySym` into
a single `getIdentReplaceParams` proc. This might fix possible problems
with injections of `nkAccQuoted`.

Some special word comparison in `ast` and `semtempl` are also made more
efficient.

(cherry picked from commit ac1804aba6)
2024-04-17 16:01:29 +02:00
ringabout
7083d397f3 fixes the discVal register is used after free in vmgen (#22688)
follow up https://github.com/nim-lang/Nim/pull/11955

(cherry picked from commit b1a8d6976f)
2024-04-17 16:01:23 +02:00
Amjad Ben Hedhili
3ddacd90d1 Remove some unnecessary initialization in seq operations (#22677)
* `PrepareSeqAdd`
* `add`
* `setLen`
* `grow`

Merge after #21842.

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit fbb5ac512c)
2024-04-17 16:01:17 +02:00
ringabout
cb3e5d3f28 [minor] merge similar branches in vmgen (#22683)
(cherry picked from commit 2ce9197d3a)
2024-04-17 16:01:11 +02:00
Amjad Ben Hedhili
12f2c36aca Make newSeqOfCap not initialize memory. (#21842)
It's used in `newSeqUninitialized`.

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit 8853fb0775)
2024-04-17 15:53:16 +02:00
ringabout
a12cb273b3 fixes #22664; guard against potential seqs self assignments (#22671)
fixes #22664

(cherry picked from commit 5f13e15e0a)
2024-04-17 15:51:26 +02:00
Juan M Gómez
1bbbb2f46b fixes #22662 Procs with constructor pragma doesn't initialize object's fields (#22665)
fixes #22662 Procs with constructor pragma doesn't initialize object's
fields

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit d45270bdf7)
2024-04-17 15:51:15 +02:00
SirOlaf
28cef86a09 Fix #21742: Check generic alias depth before skip (#22443)
Close #21742

Checking if there's any side-effects and if just changing typeRel is
adequate for this issue before trying to look into related ones.

`skipBoth` is also not that great, it can lead to code that works
sometimes but fails when the proc is instantiated with branching
aliases. This is mostly an issue with error clarity though.

---------

Co-authored-by: SirOlaf <unknown>
Co-authored-by: SirOlaf <>
(cherry picked from commit 2a8c759df0)
2024-04-17 14:07:06 +02:00
metagn
9ac5666271 make getType nodes of generic insts have full inst type (#22655)
fixes #22639 for the third time

Nodes generated by `getType` for `tyGenericInst` types, instead of
having the original `tyGenericInst` type, will have the type of the last
child (due to the `mapTypeToAst` calls which set the type to the given
argument). This will cause subsequent `getType` calls to lose
information and think it's OK to use the sym of the instantiated type
rather than fully expand the generic instantiation.

To prevent this, update the type of the node from the `mapTypeToAst`
calls to the full generic instantiation type.

(cherry picked from commit ed9e3cba07)
2024-04-17 14:06:46 +02:00
metagn
70ab7a53f3 resolve unambiguous enum symchoices from local scope, error on rest (#22606)
fixes #22598, properly fixes #21887 and fixes test case issue number

When an enum field sym choice has to choose a type, check if its name is
ambiguous in the local scope, then check if the first symbol found in
the local scope is the first symbol in the sym choice. If so, choose
that symbol. Otherwise, give an ambiguous identifier error.

The dependence on the local scope implies this will always give
ambiguity errors for unpicked enum symchoices from generics and
templates and macros from other scopes. We can change `not
isAmbiguous(...) and foundSym == first` to `not (isAmbiguous(...) and
foundSym == first)` to make it so they never give ambiguity errors, and
always pick the first symbol in the symchoice. I can do this if this is
preferred, but no code from CI seems affected.

(cherry picked from commit 480e98c479)
2024-04-17 14:06:38 +02:00
metagn
70d771d1a9 fix isNil folding for compile time closures (#22574)
fixes #20543

(cherry picked from commit bd6adbcc9d)
2024-04-17 14:06:21 +02:00
Pylgos
45aa0a4725 Fix the problem where instances of generic objects with sendable pragmas are not being cached (#22622)
remove `tfSendable` from `eqTypeFlags`

(cherry picked from commit 9f1fe8a2da)
2024-04-17 14:06:09 +02:00
Juan M Gómez
d4c1cc7a34 fixes internal error: no generic body fixes #1500 (#22580)
* fixes internal error: no generic body fixes #1500

* adds guard

* adds guard

* removes unnecessary test

* refactor: extracts containsGenericInvocationWithForward

(cherry picked from commit 0c6e13806d)
2024-04-17 14:06:00 +02:00
metagn
131a0328b5 resolve local symbols in generic type call RHS (#22610)
resolve local symbols in generic type call

fixes #14509

(cherry picked from commit f1789cc465)
2024-04-17 14:05:52 +02:00
metagn
7335495db7 don't update const symbol on const section re-sems (#22609)
fixes #19849

(cherry picked from commit 53d9fb259f)
2024-04-17 14:05:42 +02:00
ringabout
24f3272db3 fixes #22613; Default value does not work with object's discriminator (#22614)
* fixes #22613; Default value does not work with object's discriminator

fixes #22613

* merge branches

* add a test case

* fixes status

* remove outdated comments

* move collectBranchFields into the global scope

(cherry picked from commit affd3f7858)
2024-04-17 14:04:48 +02:00
metagn
3911c90d7b type annotations for variable tuple unpacking, better error messages (#22611)
* type annotations for variable tuple unpacking, better error messages

closes #17989, closes https://github.com/nim-lang/RFCs/issues/339

* update grammar

* fix test

(cherry picked from commit ba158d73dc)
2024-04-17 14:04:43 +02:00
metagn
7c44af4e22 properly fold constants for dynlib pragma (#22575)
fixes #12929

(cherry picked from commit 6b955ac4af)
2024-04-17 14:04:29 +02:00
Bung
d49d7ba90c fix #22548;environment misses for type reference in iterator access n… (#22559)
* fix #22548;environment misses for type reference in iterator access nested in closure

* fix #21737

* Update lambdalifting.nim

* remove containsCallKinds

* simplify

(cherry picked from commit 0b78b7f595)
2024-04-17 14:04:19 +02:00
ringabout
26f3dfff75 fixes a strictdef ten years long vintage bug, which counts the same thing twice (#22549)
fixes a strictdef ten years long vintage bug

(cherry picked from commit 1013378854)
2024-04-17 14:03:45 +02:00
Jacek Sieka
271632a72d Fix getAppFilename exception handling (#22544)
* Fix `getAppFilename` exception handling

avoid platform-dependendent error handling strategies

* more fixes

* space

(cherry picked from commit bc9785c08d)
2024-04-17 14:01:27 +02:00
metagn
0d02bee23f round out tuple unpacking assignment, support underscores (#22537)
* round out tuple unpacking assignment, support underscores

fixes #18710

* fix test messages

* use discard instead of continue

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 53d43e9671)
2024-04-17 14:00:45 +02:00
metagn
c39a0139fc allow non-pragma special words as user pragmas (#22526)
allow non-pragma special words as macro pragmas

fixes #22525

(cherry picked from commit 602f537eb2)
2024-04-17 12:40:00 +02:00
SirOlaf
06464fe2ff Fix #21722 (#22512)
* Keep return in mind for sink
* Keep track of return using bool instead of mode
* Update compiler/injectdestructors.nim
* Add back IsReturn

---------

Co-authored-by: SirOlaf <>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit c0ecdb01a9)
2024-04-17 12:40:00 +02:00
metagn
8eaf98d64f cascade tyFromExpr in type conversions in generic bodies (#22499)
fixes #22490, fixes #22491, adapts #22029 to type conversions

(cherry picked from commit 98c39e8e57)
2024-04-17 12:40:00 +02:00
ringabout
2a4755ddf2 fixes #22469; generates nimTestErrorFlag for top level statements (#22472)
fixes #22469; generates `nimTestErrorFlag` for top level statements

(cherry picked from commit 09d0fda7fd)
2024-04-17 12:39:59 +02:00
Pylgos
814e929eeb fix #22448 Remove structuredErrorHook temporary in tryConstExpr (#22450)
* fix #22448

* add test

(cherry picked from commit 48da472dd2)
2024-04-17 12:39:59 +02:00
ringabout
6f00b46c4b fixes move sideeffects issues [backport] (#22439)
* fixes move sideeffects issues [backport]

* fix openarray

* fixes openarray

(cherry picked from commit faf1c91e6a)
2024-04-17 12:39:44 +02:00
Bung
665480372e fix #19304 Borrowing std/times.format causes Error: illformed AST (#20659)
* fix #19304 Borrowing std/times.format causes Error: illformed AST

* follow suggestions

* mitigate for #4121

* improve error message

(cherry picked from commit 2aab03bdfb)
2024-04-17 10:57:32 +02:00
SirOlaf
2fa314a89d Fix #21760 (#22422)
* Remove call-specific replaceTypeVarsN

* Run for all call kinds and ignore typedesc

* Testcase

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit baf350493b)
2024-04-17 10:55:19 +02:00
Bung
bd63124a00 fix #12938 index type of array in type section without static (#20529)
* fix #12938 nim compiler assertion fail when literal integer is passed as template argument for array size

* use new flag tfImplicitStatic

* fix

* fix #14193

* correct tfUnresolved add condition

* clean test

(cherry picked from commit d53a89e453)
2024-04-17 10:55:14 +02:00
Bung
b67d0a64b4 fix #20891 Illegal capture error of env its self (#22414)
* fix #20891 Illegal capture error of env its self

* fix innerClosure too earlier, make condition shorter

(cherry picked from commit 989da75b84)
2024-04-17 10:55:05 +02:00
ringabout
09109c55c9 clean up gc:arc or gc:orc in docs and in error messages (#22408)
* clean up gc:arc/orc in docs

* in error messages

(cherry picked from commit 10a6e4c236)
2024-04-17 10:54:56 +02:00
Bung
c1745b5924 fix #18823 Passing Natural to bitops.BitsRange[T] parameter in generi… (#20683)
* fix #18823 Passing Natural to bitops.BitsRange[T] parameter in generic proc is compile error

(cherry picked from commit 37d8f32ae9)
2024-04-17 09:37:18 +02:00
ringabout
a7394440b9 Delete parse directory, which was pushed wrongly before [backport] (#22401)
Delete parse directory

(cherry picked from commit 614a18cd05)
2024-04-17 09:37:02 +02:00
Bung
42e4190e1a add test for #3907 (#21069)
* add test for #3907

(cherry picked from commit 137d608d7d)
2024-04-17 09:36:48 +02:00
norrath-hero-cn
36b339bbcf Prevent early destruction of gFuns, fixes AddressSanitizer: heap-use-after-free (#22386)
Prevent destruction of gFuns before callClosures

(cherry picked from commit e0396900ed)
2024-04-17 09:36:41 +02:00
Andreas Rumpf
fb2cc06557 destructors: better docs [backport:2.0] (#22391)
(cherry picked from commit 9872453365)
2024-04-17 09:36:34 +02:00
Tomohiro
ac66f6ce7a Fix searchExtPos so that it returns -1 when the path is not a file ext (#22245)
* Fix searchExtPos so that it returns -1 when the path is not a file ext

* fix comparision expression

* Remove splitDrive from searchExtPos

(cherry picked from commit db435a4a79)
2024-04-17 09:36:23 +02:00
Bung
f4d99c8d56 fix #20883 Unspecified generic on default value segfaults the compiler (#21172)
* fix #20883 Unspecified generic on default value segfaults the compiler

* fallback to isGeneric

* change to closer error

* Update t20883.nim

(cherry picked from commit 26f183043f)
2024-04-17 09:36:10 +02:00
ringabout
d097028307 fixes a typo in the manual (#22383)
ref 0d3bde95f5 (commitcomment-122093273)

(cherry picked from commit 7c2a2c8dc8)
2024-04-17 09:35:58 +02:00
ringabout
7fbf42960b follow up #22322; fixes changelog (#22381)
(cherry picked from commit fb7acd6600)
2024-04-17 09:35:13 +02:00
konsumlamm
526dbf0cf2 Make repr(HSlice) always available (#22332)
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
(cherry picked from commit d37b620757)
2024-04-17 09:34:31 +02:00
ringabout
1c19d5c72e fixes #22362; Compiler crashes with staticBoundsCheck on (#22363)
(cherry picked from commit 825a0e7df4)
2024-04-17 09:34:23 +02:00
ringabout
413395866f fixes #22360; compare with the half of randMax (#22361)
* fixes #22360; compare with the half of randMax

* add a test

(cherry picked from commit f3a7622514)
2024-04-17 09:34:15 +02:00
narimiran
3ad16028aa bump NimVersion to 2.0.5 2024-04-16 15:49:33 +02:00
Nikolay Nikolov
b47747d318 [backport v2.0] Converted the 'invalid kind for firstOrd/lastOrd(XXX)' messages from internal errors to fatal errors. (#23443) (#23446)
This fixes a nimsuggest crash when opening:
    beacon_chain/consensus_object_pools/blockchain_dag.nim
from the nimbus-eth2 project and many other .nim files (44 files, to be
precise) in the same project.

Replaces: https://github.com/nim-lang/Nim/pull/23402 (cherry picked from
commit c934d5986d)
2024-03-27 15:58:56 +01:00
Александр Старочкин
5667fbfbf3 fix position for "imported but not used" warning for modules inside brackets (#23424) 2024-03-21 08:03:31 +01:00
narimiran
d4b58b0b06 bump NimVersion to 2.0.4 2024-03-19 16:39:02 +01:00
Nikolay Nikolov
ef356cfd4b * [backport] fixed nimsuggest crash with 'Something = concept' put (erroneously) outside of a 'type' block (#23331) (#23346)
(cherry picked from commit 37ed8c8480)
2024-03-19 05:46:52 +01:00
Juan M Gómez
e374759f29 [Backport 2.0] When NimScript errors prevents NimSuggest from Init (#23349) 2024-03-09 11:42:34 +01:00
Juan M Gómez
0de70dc7f3 [backport 2.0] nimsuggest fix (#23336) 2024-03-04 09:58:54 +01:00
Andreas Rumpf
2f15b67fd9 fixes an issue with string to 'var openArray' at compile-time; [backport] (#23363)
(cherry picked from commit 24fbacc63f)
2024-03-03 15:42:20 +01:00
ringabout
e03667e920 improve error messages [backport] (#23345)
ref https://forum.nim-lang.org/t/11052

![image](https://github.com/nim-lang/Nim/assets/43030857/1df87691-32d9-46b5-b61b-6b9f7cc94862)

(cherry picked from commit 1e7ca2dc78)
2024-02-27 08:17:37 +01:00
Nikolay Nikolov
11c048b06f fixes #22753; Nimsuggest segfault with invalid assignment to table (#22781) (#23313)
fixes #22753

## Future work
We should turn all the error nodes into nodes of a nkError kind, which
could be a industrious task. But perhaps we can add a special treatment
for error nodes to make the transition smooth.

(cherry picked from commit 642ac0c1c3)

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2024-02-24 07:54:42 +01:00
Nikolay Nikolov
22de3ae53e * fixed nimsuggest crash when opening a .nim file, that contain a {.fatal: "msg".} pragma. (#23325) (#23328)
(cherry picked from commit 773c066634)
2024-02-24 07:40:18 +01:00
Juan M Gómez
3be2514683 [Backport 2.0] Itanium mangling scheme (#23301) 2024-02-13 08:09:23 +01:00
ringabout
57658b685c fixes regression #23280; Operations on inline toOpenArray len return a wrong result (#23285)
fixes #23280

(cherry picked from commit 4b67cccf50)
2024-02-07 20:25:45 +01:00
ringabout
5f6ff1f051 compute checksum of nim files early in the pipelines (#23268)
related https://github.com/nim-lang/Nim/issues/21717 configs will be
resolved later

(cherry picked from commit 519d976f62)
2024-02-01 12:30:21 +01:00
rockcavera
7e6f4723c3 Fix system.currentSourcePath() documentation [backport 2.0] (#23243)
The documentation links for `parentDir()` and `getCurrentDir()` are
broken as they are no longer part of `std/os`. Link changed to
`std/private/ospaths2`.

(cherry picked from commit 9c155eaccc)
2024-01-30 08:11:10 +01:00
metagn
4a1151d6b4 give typedesc param nodes type T not typedesc[T] [backport:2.0] (#23115)
fixes https://github.com/nim-lang/Nim/issues/23112, fixes a mistake in
https://github.com/nim-lang/Nim/pull/22581

This makes `getType(t)` where `t` is a typedesc param with value `T`
equal to `getType(T)`.

(cherry picked from commit 3224337550)
2024-01-19 09:19:18 +01:00
Giuliano Mega
9994b019c5 Fix reset code gen for range types (#22462, #23214) (#23215)
This PR modifies `specializeResetT` so that it generates the proper
reset code for range types. I've tested it in the examples for issues
issues I had been experiencing.

(cherry picked from commit 473f259268)
2024-01-19 09:18:23 +01:00
metagn
bb930aef2d don't render underscore identifiers with id (#22538)
(cherry picked from commit 4f891aa50c)
2024-01-16 08:43:09 +01:00
Nikolay Nikolov
be66aedb9e + show the inferred exception list (as part of the type) for functions that don't have an explicit .raises pragma (#23193) (#23210)
(cherry picked from commit 18b5fb256d)
2024-01-16 15:36:03 +08:00
Juan M Gómez
4bc305db1e backport nimsuggest capabilities to 2.0 (#23191) 2024-01-09 22:48:18 +08:00
Juan M Gómez
fdb1f4451d makes nimsuggest con work under v3 [backport 2.0.2] (#23159)
Co-authored-by: Jake Leahy <jake@leahy.dev>
2024-01-08 20:30:59 +01:00
metagn
02497c9533 2.0 branch fixes: no LineTooLong, update macos CI (#23184)
Adapts #23108 to the version-2-0 branch and makes the 2.0 compiler
define `nimHasNoLineTooLong` as the devel compiler depends on it to not
turn off `hint[LineTooLong]`, which means the 2.0 compiler errors on the
devel compiler config (as mentioned in
https://github.com/nim-lang/Nim/issues/23178#issuecomment-1880511322).

Would have these as separate PRs but the macos CI PR would have to be
merged first, then the second PR would have to be rebased.
2024-01-08 13:49:20 +01:00
ringabout
0acdce502c fixes #23148; restricts infix path concatenation to what starts with / (#23150)
fixes #23148

(cherry picked from commit c7d742e484)
2024-01-03 10:57:42 +01:00
narimiran
fe1d4a6232 bump NimVersion to 2.0.3 2024-01-03 10:57:30 +01:00
narimiran
c4c44d10df bump NimVersion to 2.0.2 2023-12-14 17:51:05 +01:00
ringabout
55bb60a56b fixes #22947; static integers in quote do [backport] (#22948)
fixes #22947

(cherry picked from commit 09ea1b168f)
2023-12-14 17:48:55 +01:00
Amjad Ben Hedhili
ef8b8317ff Fix capacity for const and shallow [backport] (#22705)
(cherry picked from commit b542be1e7d)
2023-12-14 17:47:00 +01:00
Nikolay Nikolov
fff127bec7 Skip trailing asterisk when placing inlay type hints. Fixes #23067 (backport of #23068) (#23070)
(cherry picked from commit a3739751a8)
2023-12-14 09:26:01 +08:00
Kernel-Zhang
7b5289a1a4 Correction of “Tnfds” type error (#23045)
The types in Nim don't match the actual types in the header files, this
can lead to bugs in some cases.
2023-12-08 11:09:49 +01:00
Nikolay Nikolov
3a0d09c1c5 backport to version 2.0: display raises pragma in proc types (#23026) (#23028)
This affects also nimsuggest hints (e.g. on mouse hover), as well as
compiler messages.

(cherry picked from commit 618ccb6b6a)
2023-12-04 09:46:57 +01:00
metagn
3ab6012c81 fix generic param substitution in templates (#22535)
* fix generic param substitution in templates

fixes #13527, fixes #17240, fixes #6340, fixes #20033, fixes #19576, fixes #19076

* fix bare except in test, test updated packages in CI

(cherry picked from commit 1cc4d3f622)
2023-12-01 08:27:06 +01:00
Jake Leahy
add124e07a Register declaration of enum field has a use (#22990)
Currently when using `use` with nimsuggest on an enum field, it doesn't
return the definition of the field.

Breaks renaming in IDEs since it will replace all the usages, but not
the declaration

(cherry picked from commit c31bbb07fb)
2023-11-28 08:25:56 +01:00
tersec
8834f3e74d remove unnecessary side-effects from base64.encode(mime) (#22986)
Fixes https://github.com/nim-lang/Nim/issues/22985

(cherry picked from commit 26f2ea149c)
2023-11-26 07:15:40 +01:00
Nikolay Nikolov
489dd89a45 backport to v 2.0: nimsuggest: Added optional command line option '--clientProcessId:XXX' (#22969) (#22981)
When it is specified, the nimsuggest instance monitors whether this
process is still alive. In case it's found to be dead, nimsuggest shuts
itself down. Currently only implemented on POSIX and Windows platforms.
The switch is silently ignored on other platforms. Note that the Nim
language server should still try to shut down its child nimsuggest
processes. This switch just adds extra protection against crashing Nim
language server and gets rid of the remaining nimsuggest processes,
which consume memory and system resources.

(cherry picked from commit 502a4486ae)
2023-11-25 11:50:27 +01:00
Nikolay Nikolov
ba9effc8a1 Backport to 2.0: Introduced version 4 of the NimSuggest protocol. The InlayHints feature made V4 or later only. (#22953) (#22963)
Since nimsuggest now has a protocol version support detection via
`--info:protocolVer`, the InlayHints feature can be moved to protocol
V4. This way, the Nim language server can detect the nimsuggest version
and avoid sending unsupported `InlayHints` commands to older nimsuggest
versions. Related nim language server PR:
https://github.com/nim-lang/langserver/pull/60

(cherry picked from commit 4fc0027b57)
2023-11-20 09:13:33 +08:00
Nikolay Nikolov
0d93fdf607 backport to version 2.0: nimsuggest: Instead of checking for protocol version 3 exactly, check for version 3 or later. (#22945) (#22957)
Refactored the way nimsuggest checks for protocol version 3. Instead of
checking for version 3 exactly, it now checks for version 3 or later.
This way, once a version 4 is introduced, it will use version 3 as a
base line, and then extra changes to the protocol can be added on top.
No functional changes are introduced in this commit.

(cherry picked from commit 3680200df4)
2023-11-18 09:52:06 +08:00
Nikolay Nikolov
b8cec0c714 Added new command line option --info:X to nimsuggest for obtaining … (#22943)
…information. (#22940)

`--info:protocolVer` returns the highest nimsuggest protocol version
that is supported (currently, it's version 3).
`--info:nimVer` returns the Nim compiler version that nimsuggest uses
internally.

Note that you can obtain the Nim compiler version via `nimsuggest -v`,
but that requires parsing the output, which looks like this:

```
Nim Compiler Version 2.1.1 [Linux: amd64]
Compiled at 2023-11-14
Copyright (c) 2006-2023 by Andreas Rumpf

git hash: 47ddfeca5247dce992becd734d1ae44e621207b8
active boot switches: -d:release -d:danger --gc:markAndSweep
```

`--info:nimVer` will return just:

```
2.1.1
```

(cherry picked from commit d0cc02dfc4)
2023-11-16 20:30:22 +08:00
Nikolay Nikolov
4793fc0fc1 Inlay hints backport to Nim v2.0.x (#22919)
Backport of the nimsuggest inlay hints to the Nim v2.0.x series.
2023-11-09 07:33:20 +01:00
ringabout
e1b44666b0 iNim switch to the official URL (#22762)
ref https://github.com/inim-repl/INim/pull/139

(cherry picked from commit 02ba28eda5)
2023-11-08 13:55:49 +01:00
ringabout
194d21a6e4 fixes stint CI (#22756)
(cherry picked from commit 46544f234d)
2023-11-08 13:55:41 +01:00
metagn
1b80f7126a switch back to main neo in CI (#22660)
refs https://github.com/andreaferretti/neo/pull/53

(cherry picked from commit b9f039e0c3)
2023-11-08 13:55:31 +01:00
ringabout
1dc85802e2 add union to packages (#22658)
(cherry picked from commit 009ce1e17e)
2023-11-08 13:55:23 +01:00
ringabout
9e081579bb fixes yaml tests (#22595)
(cherry picked from commit dfb3a88cc3)
2023-11-08 13:55:15 +01:00
ringabout
30dad5dfa1 deprecate std/threadpool; use malebolgia, weave, nim-taskpool instead (#22576)
* deprecate `std/threadpool`; use `malebolgia` instead

* Apply suggestions from code review

* Apply suggestions from code review

* change the URL of inim

(cherry picked from commit a7a0105d8c)
2023-11-08 13:55:01 +01:00
ringabout
6d32066055 update test command of important packages (#22485)
(cherry picked from commit 9296b45de4)
2023-11-08 13:54:54 +01:00
ringabout
86e5545c25 fixes #22866; fixes #19998; ensure destruction for Object construction with custom destructors (#22901)
fixes #22866;
fixes #19998

(cherry picked from commit b68e0aab4c)
2023-11-02 14:40:40 +01:00
ringabout
f4e80d51ff bump node to 20.x; since 16.x is End-of-Life (#22892)
(cherry picked from commit f61311f7a0)
2023-10-31 07:08:42 +01:00
ringabout
1db305af1c fixes #22868; fixes std/nre leaks under ARC/ORC (#22872)
fixes #22868

(cherry picked from commit d66f3febd1)
2023-10-29 18:14:45 +01:00
握猫猫
805b4e2dc2 fix use after free (#22854)
1. `freeAddrInfo` is called prematurely, the variable `myAddr` is still
in use
2. Use defer syntax to ensure that `freeAddrInfo` is also called on
exceptions

(cherry picked from commit 562a5fb8f9)
2023-10-24 08:57:38 +02:00
rockcavera
e8e9948223 fix #22834 (#22843)
fix #22834

Edit: also fixes `result.addrList` when IPv6, which previously only
performed a `result.addrList = cstringArrayToSeq(s.h_addr_list)` which
does not provide the textual representation of an IPv6

(cherry picked from commit 27deacecaa)
2023-10-24 08:57:25 +02:00
Amjad Ben Hedhili
75441dcdc3 Initialize newString in js [backport:1.6] (#22745)
```nim
echo newString(8)
```

results in:
```
D:\User\test.js:25
                  var code_33556944 = c_33556931.toString(16);
                                                 ^

TypeError: Cannot read properties of undefined (reading 'toString')
    at toJSStr (D:\User\test.js:25:50)
    at rawEcho (D:\User\test.js:70:16)
    at Object.<anonymous> (D:\User\test.js:101:1)
    at Module._compile (node:internal/modules/cjs/loader:1095:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1147:10)
    at Module.load (node:internal/modules/cjs/loader:975:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47

Node.js v17.0.1
Error: execution of an external program failed: '"C:\Program Files\nodejs\node.exe" --unhandled-rejections=strict D:\User\test.js'
```

(cherry picked from commit eadd0d72cf)
2023-10-24 08:49:16 +02:00
SirOlaf
d30565f810 Fix #17509: Continue instead of return with unfinished generics (#22563)
Close #17509

Current knowledge:
- delaying cache fixes the issue
- changing return of `if inst.len < key.len:` in `searchInstTypes` to
`continue` fixes the issue. With return the broken types are also cached
over and over

Related issues are completely unaffected as of now, so there must be
something deeper.

I am also still trying to find the true cause, so feel free to ignore
for now

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit ee4a219012)
2023-09-18 12:13:00 +02:00
Amjad Ben Hedhili
5c916b645b Remove some unnecessary initialization in string operations (#22579)
* `prepareAdd`
* `toNimStr`
* `setLengthStrV2`
* `NimAsgnStrV2`
* `prepareMutation`
* Some cleanups

(cherry picked from commit a4df44d9fb)
2023-09-18 12:13:00 +02:00
SirOlaf
9ad184841e Exclude block from endsInNoReturn, fix regression (#22632)
Co-authored-by: SirOlaf <>
(cherry picked from commit d2f36c071b)
2023-09-18 12:13:00 +02:00
metagn
7536d7f94a use dummy dest for void branches to fix noreturn in VM (#22617)
fixes #22216

(cherry picked from commit 2542dc09c8)
2023-09-18 12:13:00 +02:00
metagn
ee0d3f9b34 unify explicit generic param semchecking in calls (#22618)
fixes #9040

(cherry picked from commit 6738f44af3)
2023-09-18 12:13:00 +02:00
SirOlaf
d3cf815dbe Fix #22604: Make endsInNoReturn traverse the tree (#22612)
* Rewrite endsInNoReturn

* Handle `try` stmt again and add tests

* Fix unreachable code warning

* Remove unreachable code in semexprs again

* Check `it.len` before skip

* Move import of assertions

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit 3b206ed988)
2023-09-18 12:12:59 +02:00
ringabout
b477c2adcc fixes #17197; fixes #22560; fixes the dest of newSeqOfCap in refc (#22594)
(cherry picked from commit 5bd1afc3f9)
2023-09-18 12:12:59 +02:00
metagn
78d4aa3d01 handle typedesc params in VM (#22581)
* handle typedesc params in VM

fixes #15760

* add test

* fix getType(typedesc) test

(cherry picked from commit 2e4e2f8f50)
2023-09-18 12:12:59 +02:00
metagn
855f5c8b81 clearer error for different size int/float cast in VM (#22582)
refs #16547

(cherry picked from commit b6cea7b599)
2023-09-18 12:12:59 +02:00
metagn
7ab0f3beec correct logic for qualified symbol in templates (#22577)
* correct logic for qualified symbol in templates

fixes #19865

* add test

(cherry picked from commit 3de8d75513)
2023-09-18 12:12:59 +02:00
ringabout
ba8c9a9d1e newStringOfCap now won't initialize all elements anymore (#22568)
newStringOfCap nows won't initialize all elements anymore

(cherry picked from commit 2e7c8a339f)
2023-09-18 12:12:59 +02:00
metagn
87c1200c93 test case haul for old generic/template/macro issues (#22564)
* test case haul for old generic/template/macro issues

closes #12582, closes #19552, closes #2465, closes #4596, closes #15246,
closes #12683, closes #7889, closes #4547, closes #12415, closes #2002,
closes #1771, closes #5121

The test for #5648 is also moved into its own test
from `types/tissues_types` due to not being joinable.

* fix template gensym test

(cherry picked from commit c19fd69b69)
2023-09-18 12:12:58 +02:00
ringabout
d46e71bea3 fixes #22541; peg matchLen can raise an unlisted exception: Exception (#22545)
The `mopProc` is a recursive function.

(cherry picked from commit c56a712e7d)
2023-09-18 12:12:58 +02:00
SirOlaf
4cf2658235 Fix #21532: Check if template return is untyped (#22517)
* Don't ignore return in semTemplateDef

* Add test

---------

Co-authored-by: SirOlaf <>
(cherry picked from commit 3de75ffc02)
2023-09-18 12:12:58 +02:00
metagn
5fa48e97b6 fix getNullValue for cstring in VM, make other VM code aware of nil cstring (#22527)
* fix getNullValue for cstring in VM

fixes #22524

* very ugly fixes, but fix #15730

* nil cstring len works, more test lines

* fix high

(cherry picked from commit 942f846f04)
2023-09-18 12:12:58 +02:00
ringabout
562fb0d14b fixes #22481; fixes card undefined misalignment behavior (#22484)
* fixes `card` undefined misalignment behavior

* Update lib/system/sets.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit ade75a1483)
2023-09-18 12:12:58 +02:00
Emery Hemingway
320ecc69a0 Add Linux constant SO_BINDTODEVICE (#22468)
(cherry picked from commit 1927ae72d0)
2023-09-18 12:12:58 +02:00
Bung
106cf7a9f7 Fix #5780 (#22428)
* fix #5780

(cherry picked from commit 46e94c83d4)
2023-09-18 10:13:38 +02:00
Jake Leahy
7221c6f156 Fix crash when using uninstantiated generic (#22379)
* Add test case

* Add in a bounds check when accessing generic types

Removes idnex out of bounds exception when comparing a generic that isn't fully instantiated

(cherry picked from commit 3efabd3ec6)
2023-09-18 10:13:27 +02:00
ringabout
4a7cdaecb4 fixes #22262; fixes -d:useMalloc broken with --mm:none and --threads on (#22355)
* fixes #22262; -d:useMalloc broken with --mm:none and threads on

* fixes

(cherry picked from commit a23e53b490)
2023-09-18 10:13:09 +02:00
Amjad Ben Hedhili
81d58d2cc8 Make capacity work with refc [backport] (#22697)
followup of #19771.

(cherry picked from commit 325341866f)
2023-09-14 06:02:46 +02:00
Andreas Rumpf
1080f5eba2 produce better code for object constructions and 'result' [backport] (#22668)
(cherry picked from commit 8f5b90f886)
2023-09-14 06:02:30 +02:00
ringabout
18e62ad136 fixes #22619; don't lift cursor fields in the hook calls (#22638)
fixes https://github.com/nim-lang/Nim/issues/22619

It causes double free for closure iterators because cursor fields are
destroyed in the lifted destructors of `Env`.

Besides, according to the Nim manual

> In fact, cursor more generally prevents object
construction/destruction pairs and so can also be useful in other
contexts.

At least, destruction of cursor fields might cause troubles.

todo
- [x] tests
- [x] revert a certain old PR

---------

Co-authored-by: zerbina <100542850+zerbina@users.noreply.github.com>
(cherry picked from commit eb91cf991a)
2023-09-05 11:50:59 +02:00
metagn
f03aa1d0b5 define toList procs after add for lists [backport] (#22573)
fixes #22543

(cherry picked from commit 94454addb2)
2023-09-05 11:50:41 +02:00
Daniel Belmes
ef63d47ecd fix server caching issue causing Theme failures (#22378)
* fix server caching issue causing Theme failures

* Fix tester to ignore version cache param

* fix case of people using -d:nimTestsNimdocFixup

* rsttester needed the same fix

(cherry picked from commit 7bf7496557)
2023-08-22 08:28:30 +02:00
ringabout
0a58af8cbf fixes #22357; don't sink elements of var tuple cursors (#22486)
(cherry picked from commit 940b1607b8)
2023-08-22 08:23:56 +02:00
Jason Beetham
8359f9683a When in object handles procedure call again, fixes #22474 (#22480)
Ping @narimiran please backport to the 2.0 line.

(cherry picked from commit 6c4e7835bf)
2023-08-22 08:23:32 +02:00
ringabout
c3425c05e9 relax the parameter of ensureMove; allow let statements (#22466)
* relax the parameter of `ensureMove`; allow let statements

* fixes the test

(cherry picked from commit 4c89223171)
2023-08-22 08:23:06 +02:00
Alberto Torres
3fa378533a Fix #22366 by making nimlf_/nimln_ part of the same line (backport) (#22508) 2023-08-22 08:22:58 +02:00
Amjad Ben Hedhili
4850bb5a59 fix seq.capacity [backport] (#22505) 2023-08-22 08:22:42 +02:00
ringabout
037f536e7e fixes #22419; async/closure environment does not align local variables (#22425)
* fixes #22419; async/closure environment does not align local variables

* Apply suggestions from code review

* Update tests/align/talign.nim

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>

* apply code review

* update tests

---------

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>
(cherry picked from commit 5334dc921f)
2023-08-11 10:49:49 +02:00
ringabout
287fbc5fb5 fixes #22387; Undefined behavior when with hash(...) (#22404)
* fixes #22387; Undefined behavior when with hash(...)

* fixes vm

* fixes nimscript

(cherry picked from commit 47d06d3d4c)
2023-08-11 10:49:30 +02:00
metagn
f553288db3 block ambiguous type conversion dotcalls in generics (#22375)
fixes #22373

(cherry picked from commit 3aaef9e4cf)
2023-08-11 10:49:11 +02:00
norrath-hero-cn
e0e386314f fixes AddressSanitizer: global-buffer-overflow in getAppFilename on windows 10 (#22380)
fixes AddressSanitizer: global-buffer-overflow

(cherry picked from commit 73a29d72e3)
2023-08-11 10:48:21 +02:00
Michal Maršálek
1de6a7a023 Fix the position of "Grey" in colors.nim (#22358)
Update the position of "Grey"

(cherry picked from commit da368885da)
2023-08-11 10:47:54 +02:00
narimiran
d1db4c29fa bump NimVersion to 2.0.1 2023-08-11 10:47:05 +02:00
narimiran
a488067a41 bump NimVersion to 2.0.0 2023-07-31 21:22:28 +02:00
Andreas Rumpf
35ff70f36c Tomorrow is the release. I hope. (#22353) 2023-07-31 20:19:18 +02:00
ringabout
0b3ddd4e47 Revert "fixes #22246; generate __builtin_unreachable hints for case defaults" (#22351)
Revert "fixes #22246; generate `__builtin_unreachable` hints for case defaults (#22350)"

This reverts commit b56df5c07f.
2023-07-31 22:14:15 +08:00
ringabout
b56df5c07f fixes #22246; generate __builtin_unreachable hints for case defaults (#22350)
* fixes #22246; generate `__builtin_unreachable` hints

* use elif

* indentation

* fixes holy enums in sim
2023-07-31 16:02:52 +02:00
ringabout
569ccc50ff fixes #22174; fixes destructor examples (#22349)
* fixes #22174; fixes destructor examples

* Update doc/destructors.md

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-07-31 15:37:24 +02:00
Bung
d51bc084fd remove thread duplicated code (#22348) 2023-07-31 10:58:59 +02:00
ringabout
281016a802 add a changelog for ensureMove (#22347)
* add a changelog for `ensureMove`

* Update changelogs/changelog_2_0_0_details.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-07-30 20:43:52 +02:00
Juan Carlos
19d1fe7af3 Add Valgrind (#22346)
* .

* Add Valgrind for Bisect bot in GitHub Actions
2023-07-30 13:21:22 +08:00
Juan M Gómez
e70992d291 fixes an issue where byref wasnt properly handled when using it in a generic param (#22337)
* fixes an issue where byref wasnt properly handled when using it in a generic param

* removes unreachable check
2023-07-29 18:05:31 +02:00
ringabout
f0f3904ff0 implement ensureMove (#22339)
* implement `ensureMove`

* use an additional flag

* improve some logics

* progress: fixes discard ensureMove

* forbids nested expressions

* improve error messages

* checkpoint

* fixes cursor

* ADD MORE TESTS

* fixes cursorinference again

* tiny cleanup

* improve error messages

* fixes docs

* implement comments add more tests

* fixes js
2023-07-29 10:57:03 +02:00
Eric N. Vander Weele
f1ac979184 Remove declared and not used variable in packedsets.bitincl (#22334)
When compiling code that uses PackedSet with warnings enabled, `var ret`
in `bitincl` emits a "XDeclaredButNotUsed" warning.
2023-07-27 23:07:03 +02:00
konsumlamm
db77c98471 [JS] Fix bitwise ops & shifts (#22340)
* [JS] Fix bitwise ops & shifts

* Test `int64` & `uint64` only with `jsbigint64`
2023-07-27 23:06:30 +02:00
ringabout
11c8dfc9b3 fixes docs (#22331) 2023-07-26 10:04:34 +08:00
konsumlamm
c0994c2dbd [JS] Fix casting to ints (#22327)
* [JS] Fix casting to ints

* Simplify `genCast` by using `asUintN`/`asIntN`
2023-07-25 17:56:14 +02:00
ringabout
1c2ccfad08 fixes #22301; fixes #22324; rejects branch initialization with a runtime discriminator with defaults (#22303)
* fixes #22301; rejects branch initialization with a runtime discriminator with defaults

* undefault nimPreviewRangeDefault

* fixes tests

* use oldCheckDefault
2023-07-25 12:08:32 +02:00
Khaled Hammouda
dce714b259 Fix grammar top rule (#22325)
change stmt to complexOrSimpleStmt in the top grammar rule
2023-07-24 19:48:41 +02:00
ringabout
8216d7dd46 fixes #22321; fixes building DLL with --noMain still produces a DllMain (#22323)
* fixes #22321; Building DLL with --noMain produces an unexpected DllMain on devel branch

* remove implicit nomain
2023-07-24 17:22:50 +02:00
Juan M Gómez
49a108b302 Expands codegenDecl to work in function params. fixes #22306 (#22307)
* Expands codegenDecl to work in function params. fixes #22306

* makes the test more concrete so T{lit} params dont match

* adds sfCodegenDecl
2023-07-23 16:42:20 +02:00
SirOlaf
808c9c6c2a Testcase for #22008 (#22320)
Testcase

Co-authored-by: SirOlaf <>
2023-07-23 21:35:30 +08:00
Andreas Rumpf
be1844541c implemented 'push quirky' switch for fine grained control over the ex… (#22318)
* implemented 'push quirky' switch for fine grained control over the exception handling overhead

* documentation
2023-07-23 13:39:58 +02:00
SirOlaf
62869a5c68 Check try block for endsInNoReturn (#22314)
Co-authored-by: SirOlaf <>
2023-07-22 21:13:55 +02:00
konsumlamm
b10d3cd98d Update 2.0 changelog (#22311) 2023-07-22 21:13:23 +02:00
konsumlamm
e2ea9140ac Document cast zeroing memory (#22313) 2023-07-22 21:11:49 +02:00
konsumlamm
0e555ade31 Add test for #22309 (#22316) 2023-07-22 21:11:08 +02:00
konsumlamm
576f4a7348 Fix doc comment rendering for concepts (#22312) 2023-07-22 19:10:12 +02:00
SirOlaf
3ebe24977c Open scope for defer (#22315)
Co-authored-by: SirOlaf <>
2023-07-22 19:09:39 +02:00
ringabout
b02c1dd6ca fixes #22297; return in the finally in the closure iterators (#22300)
ref #22297; return in the finally in the closure iterators
2023-07-22 06:37:27 +02:00
ringabout
993fcf5bda fixes CI; disable SSL tests on osx for now (#22304)
* test CI

* disable osx
2023-07-22 11:31:01 +08:00
ringabout
91987f8eb5 fixes #22210; transform return future in try/finally properly (#22249)
* wip; fixes #22210; transform return future in try/finally properly

* add a test case for #22210

* minor

* inserts a needsCompletion flag

* uses copyNimNode
2023-07-21 05:40:11 +02:00
Ryan McConnell
2f817ee5b4 infixArgument fail in renderer.nim sometimes (#22264)
* fixing minor typo

* Adding err msg
2023-07-20 19:56:54 +02:00
Jake Leahy
3f9e16594f fix jsondoc not getting showNonExports flag (#22267)
Pass the config down so we can check if the `--showNonExports` flag is used
2023-07-20 19:56:04 +02:00
Andreas Rumpf
c1a82aa5c5 minor code improvement (#22293) 2023-07-19 16:03:26 +02:00
ringabout
5ed44e1ec4 fixes #22254; fixes #22253; stricteffects bugs on recursive calls (#22294) 2023-07-19 15:20:41 +02:00
Ryan McConnell
0d3bde95f5 Adding info to manual (#22252)
* Adjustments

* Moving example

* typo

* adding code example back and fix terms

* Condensing
2023-07-19 15:04:14 +02:00
ringabout
7d9fe106ec fixes #22268; fixes move codegen (#22288) 2023-07-19 12:57:58 +02:00
ringabout
1aff402998 fixes #6499; disallow built-in procs used as procvars (#22291) 2023-07-19 09:45:28 +02:00
Anna
14a9929464 Fix #22281 (#22289)
Respect `--gcc.exe` and similar options when `--genScript:on` is used.
2023-07-18 16:06:21 +02:00
ringabout
f16b94a9d7 extend the skipAddr for potential types for destructors (#22265)
extend the skipAddr for potential types
2023-07-18 16:05:05 +02:00
Jake Leahy
17915d93bf Fix non-toplevel fields in objects not getting rendered (#22266)
* Add example object into testproject

The proc is there to check the case of an identDef being inside an identDef (We do want to render those even if they are not exported)

* Add `inside` set to `TSrcGen` which allows us to see what context we are in

This is done instead of adding another inXyz bool parameter

We then use this to know if we are inside an object when rendering an nkIdentDefs (To know if we need to skip rendering it)

* Update test files
2023-07-16 19:46:18 +02:00
Juan M Gómez
50d435cd39 Fixes Naive virtual crash the compiler fixes #22269 (#22271)
* Fixes Naive virtual crash the compiler fixes #22269

* adds type specific test
2023-07-16 17:01:34 +02:00
ringabout
f9280090f6 fixes idx properly (#22280) 2023-07-14 14:44:02 +02:00
Juan Carlos
db1ce4ff12 Fix #22273 (#22275)
* Fix #22273
2023-07-14 12:40:57 +02:00
ringabout
3b377937de gendepends now supports pkgs2 (#22277) 2023-07-14 12:40:24 +02:00
ringabout
9471b5f964 fixes #22256; fixes GC_disableOrc overflow (#22257) 2023-07-11 19:01:18 +02:00
Solitude
9ddd768cce Rename seq.add parameter to be consistent with refc (#22244) 2023-07-10 14:27:28 +02:00
ringabout
ecc6ab7ee0 fixes #22237; fixes #21160; wrong cursor on unowned parameters in the for loop in ORC (#22240)
fixes #22237; fixes #21160; wrong cursor on unowned parameters
2023-07-10 10:31:13 +02:00
Jake Leahy
1b132ddaa2 Fix nimsuggest not showing suggestions for imported tuples (#22241)
* Add tests

Also test if exported all tuple fields works. This seems like a hacky solution so will try and dive further to find a better solution

* Always suggest tuple fields if it passes the filter

If the tuple we are accessing is in scope then all the fields will also be in scope

* Update tests so line numbers are correct
2023-07-10 08:34:10 +02:00
ringabout
6ec10a4c91 fixes #21730; adds pkgs2 as well when nimbleDir is set (#22234) 2023-07-07 12:40:29 +02:00
Juan Carlos
54d7c9fdf8 Fix #21595 (#22233)
* .

* Fix #21595
2023-07-07 12:39:59 +02:00
Andrey Makarov
2e987cb75a Tolerate markup errors for doc comments (#19607) (#22235)
Follow-up to #21576 (for solving #19607).

1) errors in Markdown mode for `.nim` doc comments are reported with
   red color but allow to generate `.html` with the comment represented by
   literate block (monospaced text). We suppose that it's what people want
   for (supposedly) small doc comments. And this behavior is also a bit
   more Markdown-ish in the sense that Markdown generally does not have
   the concept of parsing error.
   - However, for standalone `.md` it's **not** applied because for large
     files the consequences are way bigger.

(In {.doctype: rst.} mode the behavior is the same as before -- report
the error and stop.)
In future, when our parser can handle Markdown without errors according to
the spec, this code will most probably be not needed.
2023-07-07 12:38:37 +02:00
Juan Carlos
148ff74c93 Fix #21401 (#22232) 2023-07-07 09:18:40 +02:00
Andreas Rumpf
a15db5d60b fixes #22175 (#22229) 2023-07-06 15:15:50 +02:00
ringabout
dfa0d2569e alternative to #22219; adds a pointer wrapper for T destructor (#22225)
* alternative to #22219; adds a pointer wrapper for T destructor

* clean up and add comments

* Update compiler/ccgtypes.nim

* tidy up

* fixes comments

* fixes cpp

* fixes cpp
2023-07-06 11:14:42 +02:00
Jake Leahy
7616e6ee2b Fix concepts with doc comments (#22228)
* Add testcase

This tries to use a concept with a doc comment which currently leads to a segfault

* Ignore nil nodes which happen when there are doc comments in new style concept

This was done instead of semming the comments since `semConceptDecl` says it only supports lists of actual statements

* Go with alternative fix: Sem comments but ignore them

Since `nil` could mean anything it is best to not silently ignore it (In case another nil problem happens in future

Also fix test case so it isn't an infinite loop
2023-07-06 08:18:47 +02:00
ringabout
145e002c74 fixes #22132; hoisted openArray params result in erroneous code (#22224) 2023-07-05 11:21:57 +02:00
Andreas Rumpf
86ff37fab8 fixes #22138 (#22221) 2023-07-04 23:35:25 +02:00
ringabout
31ba1046fc add a test case for #22190 in case of regression (#22217) 2023-07-04 10:58:14 +08:00
ringabout
c513e37a70 fixes #22212; Compile error when running a Nimscript that compares se… (#22213)
fixes #22212; Compile error when running a Nimscript that compares seq with switch("mm", "arc")
2023-07-03 14:15:44 +02:00
ringabout
d9a24b9b81 fixes #22208; Ambiguous error when import modules with same names but… (#22211)
fixes #22208; Ambiguous error when import modules with same names but different aliases
2023-07-03 14:08:40 +02:00
ringabout
1ad618d96c clean up the documentation (#22196) 2023-07-02 22:36:05 +02:00
ringabout
57296a5139 fixes #22197; Distinct ref objects + destructor cause C++ codegen error (#22207) 2023-07-02 21:04:48 +02:00
Andreas Rumpf
83a5865024 fixes #22200 (#22206)
* fixes #22200

* typo
2023-07-02 20:57:10 +02:00
Juan Carlos
aedb4c26de Bisect Bugs (#22157)
* Add Git bisect like for bug repro code on issue comments against Nim versions >1.0
* Add Git bisect like for bug repro code on issue comments against Nim versions >1.0
* Add Git bisect like for bug repro code on issue comments against Nim versions >1.0
2023-07-01 18:18:21 +02:00
心夏❤v
7cb59efd4b Tidy contributing.md: format cmd (#22204) 2023-07-01 16:16:59 +08:00
Juan M Gómez
2f109595e9 reset macrocache after each script evaluation (#22195) 2023-06-30 23:03:25 +02:00
Jacek Sieka
4d2ebbb877 fix controlflow test (#22194)
the function actually returns
2023-06-30 14:54:46 +02:00
Andreas Rumpf
3a1adf7d66 v2.0: changelog improvements (#22192)
* changelog improvements

* changelog that people want to actually read

* improvements
2023-06-30 14:54:29 +02:00
metagn
210b10dd0d fix nested call regression in generic bodies (#22189)
fixes #22187
2023-06-29 22:05:18 +02:00
ringabout
41ec894cb0 alternative to #22183; nimscript shares the same compileTime sym with VM (#22184) 2023-06-29 11:21:22 +02:00
ringabout
d139d99946 fixes #19101; zero initialization union casts (#22185)
* zero initialization union casts

* cleans up and adds a test case for #19101

* uses nimZeroMem
2023-06-29 10:51:18 +02:00
Andrey Makarov
57de460437 Don't throw errors on RST tables in Markdown and RstMarkdown modes (#22165)
* Don't throw errors on RST tables in Markdown and RstMarkdown modes

Additions to RST simple tables (#19859) made their parsing more
restrictive, which can introduce problems with of some old
nimforum posts, which have tables with sloppily aligned columns
(like this one:
https://github.com/nim-lang/nimforum/issues/330#issuecomment-1376039966).
Also this strictness contradicts to Markdown style of not getting
in the way (ignoring errors).

So this PR proposes a new strategy of dealing with errors:
* In Markdown and legacy (old default) RstMarkdown we try to
  continue parsing, emitting only warnings
* And only in pure RST mode we throw a error

I expect that this strategy will be applied to more parts of markup code
in the future.

* Don't return anything in `checkColumns`
2023-06-28 22:38:54 +02:00
metagn
b35942ef83 fix new type inference for noreturn [backport] (#22182)
fixes #22180

Backported since apparently the new type inference was backported
2023-06-28 22:38:08 +02:00
Juan M Gómez
d195877615 docs nimBasePattern (#22179) 2023-06-28 17:49:35 +02:00
Andreas Rumpf
427ad17161 fixes #22001 (#22177)
* fixes #22001

* added test case
2023-06-27 22:42:48 +02:00
Andreas Rumpf
9616762cfe Revert "fix struct stat" (#22171)
Revert "fix struct stat (#22161)"

This reverts commit 4b761295e7.
2023-06-27 16:46:41 +02:00
Andreas Rumpf
ce0909f047 fixes #22137 (#22170) 2023-06-27 14:58:02 +02:00
Andreas Rumpf
faa59b1e1f Use pinned Atlas commit (#22169) 2023-06-27 14:12:21 +02:00
ringabout
e422b3c860 adds =destroy T support for strings and seqs (#22167)
* adds =destroy T support for strings and seqs

* fixes system

* fixes tests
2023-06-27 13:07:29 +02:00
Andreas Rumpf
d52b1d848e destructors: update, =destroy does not require a 'var T' (#22168) 2023-06-27 12:55:47 +02:00
Jacek Sieka
47635d3031 fix Sigaction struct definition (#22160)
SigInfo is still wrong (most of its fields are in a union)
2023-06-27 10:09:04 +02:00
Jacek Sieka
cb40f11e6c uint arithmetic for pointers (#22159)
pointers are not signed and arithmetic may correctly cross int.max
threshold

this PR only fixes 2 occurances - there are plenty however in the std
lib
2023-06-27 08:20:02 +02:00
Jacek Sieka
4b761295e7 fix struct stat (#22161)
Undo damage of https://github.com/nim-lang/Nim/pull/14170
2023-06-27 08:19:17 +02:00
ringabout
4ce3a68e79 fixes #22163; use {.push warning[BareExcept]:off.} to override settings temporarily (#21390)
* use `{.push warning[BareExcept]:off.}` to override settings temporarily

* likewise, suppress expect
2023-06-27 08:03:52 +08:00
ringabout
4546f5dfe5 adds T destructor for refs (#22147)
* adds T destructor for refs

* add `newRefdestructor`

* adds ref overload for destructors

* fixes config
2023-06-26 15:10:06 +02:00
Jake Leahy
43a3de9077 Fix regression in std/times (#22155)
* Add simple test case

Just so the regression doesn't happen again

* Specify initDateTime is gcsafe in the forward declarations
2023-06-26 15:07:42 +02:00
tersec
3e44d5742f rm zero-extension and uint conversions deprecated since 0.19.9 (#22151) 2023-06-25 20:37:21 +02:00
ringabout
942c378659 fixes #22148; std/memfiles.memSlices nesting now fails with memory sa… (#22154)
* fixes #22148; std/memfiles.memSlices nesting now fails with memory safety capture violation

* adds a test case
2023-06-25 17:15:47 +02:00
metagn
20037a4749 make var object match better than object (#22152)
* fix `var object` not matching better than `object`

fixes #13302

* remove comment for brevity

* try note

* try minimize breaks
2023-06-25 16:52:16 +02:00
metagn
f718f295df fix VM uint conversion size bug, stricter int gen on JS (#22150)
* fix VM uint conversion bug, stricter int gen on JS

fixes #19929

* fix float -> uint64 conversion too

* no need to mask to source type

* simpler diff with explanation, add test for described issue
2023-06-25 00:01:08 +02:00
Etan Kissling
c6c85f84db macOS ar doesn't support @ syntax (#22146)
When the linker command line is long, Nim compiler generates a file for
passing the linker arguments. On `macOS`, that mechanism fails as the
`@` syntax is not supported by `ar`. Use `xargs` instead to pass the
linker arguments file.
2023-06-24 08:13:43 +02:00
Juan M Gómez
beaac609ab adds nimbasePattern compiler option (#22144)
adds optonal --nimbasepattern
2023-06-24 08:13:15 +02:00
ringabout
88114948c4 fixes #21110; duplicate proc definitions for inline iters (#21136)
fixes #21110; duplicate proc definitions for iters
2023-06-22 22:17:23 +02:00
ringabout
d137a3b52a fixes :idx: index in in modules (2.0 regression) and in markdown files (persistent issues since 0.20.2) (#22141)
fixes :idx: index
2023-06-22 15:58:10 +02:00
ringabout
ac7b8b678c fixes #21231; template with module as parameter elides usage/checking of module name specifier (#22109)
* fixes #21231; template with module as parameter elides usage/checking of module name specifier

* add a test case
2023-06-21 16:30:55 +02:00
ringabout
eb2f0353bc adds missing staticlib hints (#22140) 2023-06-21 16:30:23 +02:00
Bung
3ad2e7df1c fix #20023 hash for generic tables (#20346)
* fix #20023 hash for generic tables

* use default computation

* Update lib/pure/collections/tables.nim

Co-authored-by: Dan Rose <dan@digilabs.io>

* Update lib/pure/collections/tables.nim

Co-authored-by: Dan Rose <dan@digilabs.io>

* Update lib/pure/collections/tables.nim

* Update lib/pure/collections/tables.nim

* Update t20023.nim

---------

Co-authored-by: Dan Rose <dan@digilabs.io>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-21 12:19:40 +02:00
Juan M Gómez
ede03782a3 Update changelog_2_0_0.md (#22135) 2023-06-21 11:41:40 +02:00
Zoom
5e529b3bfa strutils.split/rsplit now return src on an empty sep (#22136)
This is a rebase of an earlier rejected PR. Following the discussion
around it, this commit provides a valid output for and edge case
of an empty separator for `split` and `rsplit` routines. The empty
separator is interpreted as "split by no separators" and the initial
string is returned. This is consistent with the behaviour of the
`set[char]` version of `split`/`rsplit` routines and unifies them all.

Compared to a commit merged earlier, this one has a benefit of
not using assertions that will be removed in release builds
and thus still not preventing possible infinite loops (which was the
earlier behaviour for this edge case for separator of type `string`).

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-21 08:52:33 +02:00
ringabout
a345cde26e allow destructors to accept non var parameters; deprecate proc =destroy(x: var T) (#22130)
* make destructors accept non var parameters
* define nimAllowNonVarDestructor
* add a test case and a changelog
* update documentation and error messages
* deprecate destructors taking 'var T'
2023-06-21 08:51:03 +02:00
Ryan McConnell
db41f04ab0 Amend divmod (#22131)
* Add Overflow checks & test adjust

* Avoiding nimvm differences in tests

* distinguish DivByZeroDefect
2023-06-20 13:04:34 +02:00
ringabout
f524d60fa1 fixes #22123; Compiler bug with default initializer values and arrays (#22128) 2023-06-20 08:02:06 +02:00
ringabout
29a43124cf overhaul the error messages of =dup (#22129) 2023-06-20 07:08:39 +02:00
ringabout
2054f1c3a9 fixes #22117; View types lifetime tracking does not work with defer (#22121) 2023-06-19 15:23:51 +02:00
Ivan Yonchovski
2bb7277a61 Create compiler and nimsuggest packages (#22118)
I have tested it locally with the following in my local packages_official.json

```
  {
    "name": "compiler",
    "url": "https://github.com/yyoncho/Nim.git/?subdir=compiler",
    "method": "git",
    "tags": [
      "library",
      "compiler"
    ],
    "description": "Package providing the Nim compiler binaries plus all its source files that can be used as a library",
    "license": "MIT",
    "web": "https://github.com/nim-lang/Nim"
  },
  {
    "name": "nimsuggest",
    "url": "https://github.com/yyoncho/Nim.git/?nimsuggest=compiler",
    "method": "git",
    "tags": [
      "library",
      "compiler"
    ],
    "description": "Package providing the Nim compiler binaries plus all its source files that can be used as a library",
    "license": "MIT",
    "web": "https://github.com/nim-lang/Nim"
  },
```

Then `nimble install compiler`, `nimble install nimsuggest` work as expected.
2023-06-18 16:06:14 +02:00
metagn
6d21637245 fix scoping regression with calls in generic bodies (#22115)
refs #22029, refs https://github.com/status-im/nim-libp2p/actions/runs/5263850340/jobs/9514434659
2023-06-17 15:24:32 +08:00
Ryan McConnell
647d9611ae Add divmod (#22102)
* Adding divmod

* Adding support to VM

* Wrapped C structs and funcs

* Fix javascript impl

* Fixing struct compat

* Segregate tests, better compiletime defs

* Using `inline` and switch back to `func`

* Apply suggestions from code review

* Explicit structures

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-17 05:42:05 +02:00
Andreas Rumpf
e8d0f1c3ae fixes #16331; aliasing of tuple construction within a single assignme… (#22113)
* fixes #16331; aliasing of tuple construction within a single assignment, great coding style

* added test case
2023-06-16 20:59:59 +02:00
metagn
0de9e6bbf3 add test to close #7209 (#22110)
* add test to close #7209

was fixed by #22029

* fix echo => doAssert
2023-06-16 20:20:06 +02:00
Andreas Rumpf
8c3b0e9b48 added new experimental API isUniqueRef (#21812)
* added new experimental API isUniqueRef

* typo
2023-06-16 19:35:16 +02:00
Miran
7ea8f1d5dd bump NimVersion to 1.9.5 (#22112) 2023-06-16 17:20:28 +02:00
metagn
88388040db add tests to close #7223, close #11733 (#22111)
add test to close #7223, close #11733

closes #7223, closes #11733, were fixed by #22076
2023-06-16 17:14:47 +02:00
ringabout
77beb15214 fixes #22049; fixes #22054; implicit conversion keeps varness (#22097)
* fixes #22054; codegen for var tuples conv

* rethink fixes

* add test cases

* templates only

* fixes var tuples

* keep varness no matter what

* fixes typ.isNil

* make it work for generics

* restore isSubrange

* add a test case as requested
2023-06-16 12:06:50 +02:00
Andreas Rumpf
0750210a50 fixes #19607 (#21576) 2023-06-16 12:06:18 +02:00
metagn
3ac2d81601 consider object types as declarative in templates (#22106)
* consider object types as declarative in templates

fixes #16005

* correct logic for nkRecList children, inject fields

* don't actually inject fields
2023-06-16 08:38:48 +02:00
Juan M Gómez
b4d9be0f8a fixes ilegal recursion (#22105) 2023-06-16 08:23:25 +02:00
Juan Carlos
0a19d78b22 Revert the .inline semantics change (#22104) 2023-06-15 21:09:33 +02:00
Juan M Gómez
4937aa952b adds another pass for sets fixes #6259 (#22099)
* adds another pass for sets fixes #6259

* Update tsets.nim

removes extra `#`
2023-06-15 18:50:00 +02:00
ringabout
edb64bcff4 fixes explicit deref block (#22093)
fixes explicit deref
2023-06-15 09:56:58 +02:00
Juan M Gómez
d90581c677 Allows for arbitrary ordering of inheritance in type section #6259 (#22070)
* Allows for arbitrary ordering of inheritance in type section #6259

* prevents ilegal recursion

* fixes ilegal recursion. Test passes with a better message

* Apply suggestions from code review

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-15 09:56:08 +02:00
metagn
13b7e4e0e5 use TimeInterval instead of Duration for calculating ISO week date (#22091)
* use TimeInterval instead of Duration for calculating ISO week date

hopefully actually fixes (space) #22059

* forward declare

* explicit effects
2023-06-14 20:43:46 +02:00
ringabout
44f377edaf imrpove changelog (#22096)
Update changelog_2_0_0.md
2023-06-14 13:10:24 +02:00
metagn
20dfdba2df fix timezone in initDateTime for ISO week date (#22090)
fixes #22059
2023-06-13 20:09:28 +02:00
metagn
894a19c6ed fix calls in generic bodies, delay typecheck when no overloads match (#22029)
* sacrifice "tgenericshardcases" for working statics

* legacy switch for CI, maybe experimental later

* convert to experimental

* apparently untyped needs the experimental switch

* try special case call semcheck

* try fix

* fix compilation

* final cleanup, not experimental, make `when` work

* remove last needed use of untyped

* fix unused warning in test

* remove untyped feature
2023-06-13 20:05:44 +02:00
Andreas Rumpf
606e9941d0 better docs; undocument sinkInference as it doesn't work (#22089) 2023-06-13 13:44:41 +02:00
ringabout
cca5e5ffb9 fixes #22065; do not search path for relative imports (#22073)
* fixes #22065; do not search path for "./"

* simplify

* fixes

* fixes

* allow ".."

* cleanup

* add a test case

* slightly modify the import

* adds a changelog
2023-06-13 13:23:11 +02:00
metagn
fda8b6f193 strictly typecheck expressions in bracketed emit (#22074)
* strictly typecheck expressions in bracketed `emit`

* use nim check in test
2023-06-13 12:04:24 +02:00
ringabout
2e12d3e26b fixes #22058; invalid free with {.noSideEffect.} in template (#22088) 2023-06-13 12:03:20 +02:00
ringabout
5679f2b84c clean up nimfix leftover (#22087) 2023-06-13 16:34:16 +08:00
ringabout
db8f6f4e38 change it to the latest branch instead of head (#22086)
Who knows what's wrong with git
2023-06-13 09:51:43 +02:00
ringabout
93cace160e fix atlas nightlies regresion; fixes the hash value (#22080) 2023-06-12 17:25:30 +02:00
metagn
71801c2b8f fix dot calls with resolved symbols in templates (#22076)
* fix dot calls with resolved symbols in templates

* make old code work

* fix custom number literals test

* remove leftover debug marker

* enable "bug 9" test too

* fix renderer, add test for #7085
2023-06-12 06:34:34 +02:00
metagn
e0ad71a912 make binary not not parse complex expressions on right side (#22078)
* binary `not` only parses simple expressions

fixes #16324

* switch to primary
2023-06-12 06:22:50 +02:00
metagn
7b1c448744 more test cases for generic object impl AST (#22077)
closes #9899, closes #14708, refs #21017
2023-06-11 19:20:17 +02:00
metagn
5139a2ec37 make borrow . work with aliases if not overriden (#22072) 2023-06-11 19:19:48 +02:00
ringabout
9b5f310b9e build atlas documentation (#22071) 2023-06-11 19:18:32 +02:00
Andreas Rumpf
21d941c16a Atlas: now in its own repository (#22066)
* Atlas: now in its own repository

* progress
2023-06-10 17:32:11 +02:00
Etan Kissling
8bba04078c avoid AnyEnumConv warning in genEnumCaseStmt (#22061)
When parsing enums from strings using `genEnumCaseStmt`, `AnyEnumConv`
warnings are generated due to conversion from integer value. It seems
possible meanwhile to refer to the actual `enum` value by symbol instead
of being required to do the conversion from `ord`, even when the `enum`
is defined in a `block`.
2023-06-10 14:45:00 +02:00
Jake Leahy
d3af0882cf BackwardsIndex overload for CacheSeq.[] (#22043)
* Add `BackwardsIndex` support for `CacheSeq`

* Add changelog entry

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-10 14:43:32 +02:00
Juan Carlos
b2d7761975 Remove Deprecated Nimfix (#22062)
* Remove Deprecated Nimfix
* Trailing whitespace cleanups
2023-06-10 07:09:03 +02:00
Andreas Rumpf
65c412e3f0 atlas: SAT based package solver, WIP (#22027)
* atlas: SAT based package solver, WIP

* progress

* make tests green

* progress

* SAT: now works; enabled unit tests in versions.nim

* Atlas: SAT: completed
2023-06-09 16:15:43 +02:00
Qinsi (James) ZHU
744a99d75c add const RLIMIT_STACK (#21772)
* add const RLIMIT_STACK

* generate by detect.nim

* add generated const for linux-amd64
2023-06-09 16:03:28 +02:00
litlighilit
1d6fd30afb Update browsers.nim, fix openDefaultBrowser()'s bug (#22052)
modified to fix blank page fault. see openDefaultBrowser()

The previous implement use "http:about:blank" which will be processed by "prepare" and be considered as a file path, turning to "file://...", which is no doubt beyond expectation.
To fix it,firstly the "about:blank" is used instead. Next, a new "openDefaultBrowserImplPrep" proc is added, take place of the previous version of "openDefaultBrowserImpl"
2023-06-09 15:54:33 +02:00
ringabout
64b27edd3a make move use =wasMoved internally (#22032)
* make `move` use `=wasMoved` internally

* fixes tests

* fixes spawn finally

* fixes views

* rename to internalMove

* add a test case
2023-06-09 15:53:12 +02:00
ringabout
49e11d9dcc clean up isNilConversion for seqs, strings (#22057) 2023-06-09 14:47:52 +02:00
awr1
18462b1026 Add nested with to changelog (#22053)
Add nested with to changelog
2023-06-09 14:40:17 +02:00
ringabout
f09101416f fixes stale bot (#22056) 2023-06-09 17:16:13 +08:00
Juan M Gómez
a7682325a2 fixes typos in the constructor docs (#22035)
* fixes typos in the constructor docs

* updates constructor docs

* Update doc/manual_experimental.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-09 09:55:24 +02:00
Antonis Geralis
a3bbb71240 Remove debug echo from with (#22047) 2023-06-08 22:52:24 +08:00
Tanguy
a4f9413a65 Fix: don't track Defect in proc effect compatibility (#22037) 2023-06-08 14:09:06 +02:00
ringabout
a8d0dda833 allow addressing elements of openArray[char] in VM (#22045)
allow addressing elements of openArray[char]
2023-06-08 14:08:49 +02:00
Antonis Geralis
750a33cbf1 Fix indentation in destructors.md (#22048) 2023-06-08 14:07:40 +02:00
ringabout
64accd1c57 fixes {.global.} ref typedesc regressions (#22046) 2023-06-08 13:06:47 +02:00
awr1
6514eaa8e0 Nested with blocks (#22042)
* Implemented with-nesting in underscoredCalls()

* Add tests for nested with
2023-06-08 08:02:57 +02:00
ringabout
7ee00d86b1 fixes overriden typo (#22044) 2023-06-08 08:02:11 +02:00
Raynei
ba4fb21032 fixes #19086: Document exception and defect hierarchy (#22030)
* Documented exception and defect hierarchy (#19086)

* Fixed style
2023-06-08 06:55:17 +02:00
Juan Carlos
ea91cfb305 Improve compiler messages (#22040)
* Improve compiler messages
2023-06-08 00:09:09 +02:00
Juan M Gómez
d29237b3c7 adds rkInt to the opcCastPtrToInt op (#22039)
adds rkInt to the opcCastPtrToInt op
2023-06-08 00:08:36 +02:00
heterodoxic
7fad6e5c70 fixes #21995: align C++ with C backend behavior for empty raise state… (#21998)
* fixes #21995: align C with C++ backend behavior for empty raise statements

* make runtime behavior match across both C and C++ backend and all exception modes
2023-06-07 15:15:08 +02:00
ringabout
47fa7506ab fixes #21989; lift =dup from a custom =copy for objects to keep backward compatibilities (#22009)
* fixes #21989; optimize `=dup` iff it is overridden

* remove owned

* fixes refs

* lift destructors

* lift dup
2023-06-07 15:13:34 +02:00
ringabout
ebecfbc7a5 switch to the official chronicles URL (#22033) 2023-06-07 17:58:24 +08:00
metagn
ce72b564bc retain forced open undeclared ident information (#22019) 2023-06-07 11:36:51 +02:00
ringabout
fcc383d899 fixes stale workflows; stale issues defaults to -1 instead of 7 days (#22031)
* fixes workflows; stale issues defaults to 100 years instead of 7 days

* Update .github/workflows/stale.yml

* Update .github/workflows/stale.yml
2023-06-07 10:02:19 +08:00
Juan Carlos
9f3d1b1290 Improve compiler messages (#22028)
* Improve compiler messages with simpler code
2023-06-07 02:02:14 +02:00
metagn
ccc706ff12 add test case to close #7974 (#22023)
close #7974 by adding test case
2023-06-06 23:32:15 +02:00
metagn
1dedad5620 make runnableExamples a special word (#22024)
* make runnableExamples a special word

* fix imports
2023-06-06 23:31:55 +02:00
Juan M Gómez
80fc749835 fixes #22025 vcc fails with The filename or extension is too long. when linking (#22026)
[vcc]makes paths relative when possible fixes #22025
2023-06-06 21:32:16 +02:00
Juan M Gómez
134b1890d5 documents constructor (#22013)
* documents constructor

* Apply suggestions from code review

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-06 21:22:32 +02:00
ringabout
0f3d6b5a52 small fixes for atomicArc (#22017)
* small fixes for atomicArc

* Update lib/system/arc.nim
2023-06-06 21:22:07 +02:00
ringabout
7ca55f7de6 close #12852; add a test case (#22016) 2023-06-06 20:40:17 +08:00
metagn
b97d603cd0 some test cleanups & category reorganization (#22010)
* clean up some test categories

* mention exact slice issue

* magics into system

* move trangechecks into overflow

* move tmemory to system

* try fix CI

* try fix CI

* final CI fix
2023-06-06 06:54:07 +02:00
metagn
2ab948ce53 post expr blocks colon fix + correct grammar (#21983)
* post expr blocks colon fix + correct grammar

fixes #21982

* fix dochelpers

* this is remarkably common

* use head for unchained

* fix atlas

* final grammar fix
2023-06-06 06:53:21 +02:00
metagn
0a212f97a5 properly disallow unresolved generic proc values (#22005)
* properly disallow unresolved generic proc values

* mirrors semoperand

* shallow efTypeAllowed, add back special case
2023-06-05 10:53:40 +02:00
Bung
c7c3362cc8 add test case for #7839 (#22006) 2023-06-05 16:30:08 +08:00
ringabout
1edae67efd infer error for =dup if there is a custom =copy error hook (#22004) 2023-06-05 08:06:14 +02:00
Miguel Madrid-Mencía
211ef26f29 Remove unused astago import warning from vm.nim (#22003) 2023-06-04 22:56:14 +08:00
Miguel Madrid-Mencía
85d8ee2cee Fix typo in installer.ini (#22002) 2023-06-04 16:07:29 +02:00
ringabout
767fec1640 fixes nightlies regression caused by atlas moving out of the tools dir (#21999)
fixes nightlies caused by atlas moving out of the tools dir
2023-06-04 13:51:03 +02:00
Andreas Rumpf
a1b7d2278a Atlas: refactoring and --autoenv feature (#21993) 2023-06-04 11:32:37 +02:00
heterodoxic
0d4d70f15c shallow fix for #21972, #18552 by moving std::exception_ptr to the parent sco… (#21988)
shallow fix for #21972 by moving std::exception_ptr to the parent scope, minor cleanup
2023-06-04 08:56:11 +02:00
ringabout
929cb4d601 fixes #21987; don't create type bound ops for anything in a function with a nodestroy pragma (#21992)
* fixes #21987; don't create type bound ops for anything in a function with a `nodestroy` pragma

* add a comment
2023-06-04 08:37:58 +02:00
Andreas Rumpf
25fe4124e6 Atlas: 'list outdated packages' feature (#21991) 2023-06-04 05:02:29 +02:00
Andreas Rumpf
f552618d6b atlas: tests graph generation (#21990)
* atlas: tests graph generation

* silly typo

* make tests green; lockfile implementation begins to make sense

* make tests green on Windows
2023-06-03 20:07:48 +02:00
Antonis Geralis
3d18b204dd Add drchaos, ssostrings, cowstrings to important packages (#21824)
* Add drchaos, ssostrings, cowstrings to important packages

* Update important_packages.nim

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-06-03 12:36:57 +02:00
Andreas Rumpf
b86060b2ba Atlas: --project switch and better graph representation (#21971) 2023-06-03 12:34:58 +02:00
ringabout
8cc49f221e update the documentation of the dup hook (#21984)
* update the documentation of the dup hook

* document `=dup`

* typo

* minor improvement

* typo

* Update doc/destructors.md

* Update doc/destructors.md

* Update doc/destructors.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-06-03 07:09:05 +02:00
ringabout
6dd30a6d86 switch to official manu URL (#21986) 2023-06-03 12:15:08 +08:00
ringabout
1133f20fe2 lift the =dup hook (#21903)
* fixes tests again
* remove helper functions
* fixes closures, owned refs
* final cleanup
2023-06-02 16:03:32 +02:00
Gruruya
ead7e20926 Atlas: avoid segfault on failed Github search (#21980)
* Atlas: avoid segfault on failed Github search

* Return empty array on failed search instead of nil
2023-06-02 05:02:40 +02:00
heterodoxic
c507ced51e partially fixes #20787 by having a char dummy member prepended to objs only containing an UncheckedArray (i.e. C FAM) (#21979)
partial fix for #20787
2023-06-01 19:37:01 +02:00
ringabout
8e35b3d577 fixes #21974; fixes sameConstant fieldDefect (#21981)
* fixes #21974; fixes sameConstant fieldDefect

* add a test case
2023-06-01 19:02:56 +02:00
ringabout
b3e1892eb7 fixes #21977; add sideEffects to dirExists, fileExists and symlinkExists (#21978) 2023-06-01 08:03:17 +02:00
metagn
8f760080c5 privateAccess ignores non-objects (#21973)
closes #21969
2023-06-01 05:20:08 +02:00
Etan Kissling
b880cdff49 handle out of range value for COLUMNS / LINES (#21968)
* handle out of range value for `COLUMNS` / `LINES`

Querying terminal size may fail with a `ValueError` if size is too big.
Return highest possible value instead. Note that `ValueError` is also
reported on underflow (negative size) but that is out of POSIX specs.

* `parseSaturatedNatural`
2023-05-31 19:10:58 +02:00
heterodoxic
0e5c18a73a removal of seq spam in generated C/C++ code and Module.typeStack cleanup (#21964)
* WIP: removal of seq spam in generated C/C++ output and Module.typeStack cleanup

* removal of seq spam in generated C/C++ output and Module.typeStack cleanup
2023-05-31 16:24:45 +02:00
Juan Carlos
086a3e42eb Add GitHub Action Stale, remove Deprecated Probot Stale (#21943)
* .

* Add github action stale,remove deprecated stalebot

* Add github action stale,remove deprecated stalebot

* Update .github/workflows/stale.yml

* Update .github/workflows/stale.yml

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-05-31 22:00:35 +08:00
SirOlaf
bf9ee00998 Atlas: Use copyFileWithPermissions to copy nim executable (#21967)
Use copyFileWithPermissions to copy nim executable

Co-authored-by: SirOlaf <>
2023-05-31 06:26:51 +02:00
Juan M Gómez
e43a51fcf3 Implements: [C++] constructor pragma improvement (fix #21921) (#21916)
* implements: [C++] constructor pragma improvement (fix #21921)

t

* fix test so it doesnt use echo in globals

* Update compiler/ccgtypes.nim

* Update lib/std/private/dragonbox.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-30 21:47:26 +02:00
metagn
20446b437b make proc not implicitly convert to pointer with a preview define (#21953)
* test `proc` not converting to `pointer`

* ignore define for now to test

* remove cstring

* fixes, changelog
2023-05-30 21:29:38 +02:00
Andreas Rumpf
a9385a6b4a Atlas: virtual environments (#21965)
* Atlas: virtual environments

* fixes
2023-05-30 18:02:55 +02:00
Andreas Rumpf
4d20227438 Atlas: URL rewrite rules; --autoinit flag (#21963) 2023-05-30 14:00:09 +02:00
heterodoxic
546af8c571 simple micro-optimizations of ropes' runtime-formatting (#21962) 2023-05-30 13:41:56 +02:00
ringabout
40f88da90b alternative to #21914; split, rsplit now forbid an empty separator (#21961) 2023-05-30 13:40:09 +02:00
metagn
7e055413f9 hot code reloading: fix regression? and PreMain with arc/orc (#21940)
* fix PreMain for hot code reloading with arc/orc

* fix regression? actually test nimhcr_basic
2023-05-30 07:35:29 +02:00
Mamy Ratsimbazafy
171b916613 Add anti-regression for #21958 (#21960)
Add anti-regression test to close #21958
2023-05-30 10:46:24 +08:00
Andreas Rumpf
244565397d fixes #21734; backport (#21957) 2023-05-29 21:31:53 +02:00
Federico Ceratto
ef060e8184 Suggest files and paths modules (#21950) 2023-05-29 17:51:31 +02:00
ringabout
108410ac34 fixes fieldDefect loses enum type info in ORC; consistent with VM and refc (#21954)
fixes fieldDefect loses enum type info in ORC
2023-05-29 14:59:59 +02:00
heterodoxic
f47b27d532 prevent spamming of thread local forward declarations in C/C++ output (#21955) 2023-05-29 14:55:04 +02:00
Simon Krauter
8c55e2999b Fix documentation typo in endians.nim (#21949) 2023-05-28 19:40:37 +02:00
Andreas Rumpf
7ebb042f79 Atlas: some final cleanups (#21947) 2023-05-28 18:18:30 +02:00
ringabout
5997324709 fixes atlas logging colors on windows (#21946)
fixes atlas logging colors
2023-05-28 08:58:23 +02:00
Gruruya
9cb0fcf319 Atlas: checkout latest tagged commit with atlas use (#21944)
Now any deps with unspecified version reqs will checkout the last
tagged commit instead of the first commit.
2023-05-28 08:57:29 +02:00
ringabout
c2abcb06cc ship atlas and build documentation (#21945)
* ship atlas and build documentation

* move atlas.md and link it in tools' index
2023-05-28 08:28:49 +02:00
Andreas Rumpf
2900987c2f Atlas: use colored output (#21939)
* Atlas: use colored output

* fixes merge conflict

* another tiny improvement
2023-05-28 05:54:32 +02:00
Juan Carlos
b96c501836 Refactor pragma inline (#21930)
* Add __force_inline support
2023-05-27 20:52:08 +02:00
Gruruya
d5ba14db61 Atlas: add atlas tag command (#21936)
* Initial structure, `GitTags` → `GitRefsTags`

* Determine if we should use v prefix

* get tag from latest tag, patch nimble file

* Just do tags for now

* atlas tag now tags and pushes

* Improve UX of `atlas tag`

* better description for `tag`

* Small fixup

* Consistent naming

* strip after checking status

* Take major/minor/patch as arg for `atlas tag`

* undo testing comment

* Fix for `v` prefixed versions

* Avoid useless assignment

* Remove uselss enum assignment

* Consistent parameter seperation

* Add error handling for non-semver tags

* Use `assert` to quit on error

* Update tools/atlas/atlas.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Don't push tags if errors occurred

* Allow `atlas tag [tag]` again

* Add atlas tag `a..z` for fields > 3

* Document the three input options

* Take up less lines in help

* Less or in help

* One last doc pass

* Check args length

* clarify last tag

* consistency/order

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-27 20:49:19 +02:00
metagn
2dcc7195da support generic void return type for templates (#21934)
fixes #21920
2023-05-27 20:09:34 +02:00
Andreas Rumpf
ef3c0bec1c Atlas: explicit graph representation (#21937) 2023-05-27 16:48:10 +02:00
heterodoxic
af3fd5a010 fixes #15428 by updating deep open array copy codegen (#21935)
* fix #15428

* add test
2023-05-27 15:27:42 +02:00
Andreas Rumpf
73095e2abb Atlas: fixes 'use' command (#21932)
* Atlas: fixes 'use' command

* Atlas: refactoring + make tests green again
2023-05-27 13:53:07 +02:00
Gruruya
6048367a9f Atlas: clone with --recursive (#21933) 2023-05-27 10:55:31 +02:00
Juan Carlos
b0e1bc02c6 Remove unused dead code (#21931)
* .

* Remove dead code
2023-05-27 10:24:32 +02:00
Juan Carlos
38fdf13982 Clean nimbase (#21927)
* .

* Clean out nimbase.h

* Clean out nimbase.h
2023-05-27 07:44:15 +02:00
heterodoxic
6128ef53c5 fix #10964 by honoring pointer deref syntax if a reified openarray is used to get an array's length (#21925)
* fix #10964

* add test
2023-05-27 06:54:41 +02:00
Gruruya
09f36f5198 atlas: search improvements (#21929)
* Get description and license from github json response

* Allow running `atlas search` outside of a workspace

* Check `len` instead of `dirExists`

* make `list` identical to `search`
2023-05-27 06:54:21 +02:00
Andreas Rumpf
2beea72810 atlas: better code (#21926) 2023-05-26 21:24:29 +02:00
metagn
1aaff9dc48 fix & add test for basic hot code reloading case (#21915)
fixes #21885
2023-05-26 17:07:37 +02:00
Zoom
656706026b JS: Add some to-cstring converters for DateTime (#21912)
Add some to-cstring converters for DateTime

Changelog update
2023-05-26 16:40:53 +02:00
Juan Carlos
f2d26f2973 Fix Nimgrab (#21918)
* .

* Fix nimgrab client not closing

* Fix nimgrab client not closing

* Fix nimgrab client not closing
2023-05-26 14:37:59 +02:00
SirOlaf
b50babd0ae Atlas: Actually use deps for use command (#21922)
Co-authored-by: SirOlaf <>
2023-05-26 14:36:20 +02:00
ringabout
ab4d044a81 fixes #21887; Type conversion on overloaded enum field does not always call (#21908)
* fixes #21887; Type conversion on overloaded enum field does not always call

* remove comments

* add a test case

* restrict it to enums
2023-05-26 09:24:43 +02:00
Andreas Rumpf
908e971732 Atlas: misc (#21919)
* Atlas: misc

* Atlas: use the lockfile if one exists
2023-05-26 09:24:01 +02:00
heterodoxic
609bf3d7c8 fix #21501 by making --app:lib and --app:staticLib imply --noMain (#21910) 2023-05-26 03:20:56 +02:00
Andreas Rumpf
0eb508e434 atlas: better docs (#21911)
* atlas: better docs

* better workspace/project handling

* make tests green again

* bugfix
2023-05-25 22:23:07 +02:00
Jake Leahy
a8718d8a9e Fix const in async regression (#21898)
* Add test case for a const being used inside an async proc

* Use `typeof` to get the type of the block instead of overloaded templates

This removes the problem with the symbol having different types

I am unsure why I didn't use this in the first place. IIRC I had problems with `typeof` when I first tried to use it in the original implementation
2023-05-25 07:08:36 +02:00
Juan Carlos
b7925bf5c9 Remove GC (#21904)
* .

* Remove GC v2
2023-05-25 07:06:31 +02:00
metagn
446e5fbbb3 when T is both a type symbol and a routine symbol in scope of a generic proc do not account for the type symbol when doing a.T() (#21899)
fix #21883
2023-05-24 20:39:40 +02:00
Juan Carlos
cb3f6fdc66 Improve times (#21901)
* .

* Improve times
2023-05-24 17:55:48 +02:00
metagn
4d6be458a0 js -r defines nodejs & program result undeclared if unavailable (#21849)
* js -r defines nodejs & program result undefined if unavailable

fixes #16985, fixes #16074

* fix

* add changelog too

* minor word change
2023-05-24 17:55:09 +02:00
Juan M Gómez
c7f2541914 actually fixes #21889 "constructor pragma doing nothing in globals" (#21897)
actually fixes #21889
2023-05-24 16:42:53 +02:00
Andreas Rumpf
b63b5c930e Atlas: added 'use' command (#21902)
* Atlas: added 'use' command

* typo
2023-05-24 16:39:58 +02:00
Bung
266cc69f19 fix #21896 asign parameter to global variable generates invalid code (#21900) 2023-05-24 15:30:14 +02:00
ringabout
761b927e47 fixes #21863; Incorrect enum field access can cause internal error (#21886)
fixes 21863; Incorrect enum field access can cause internal error
2023-05-24 07:43:30 +02:00
Andreas Rumpf
9493e67291 Atlas: first lockfiles implementation; cleared up upated vs updateWor… (#21895)
Atlas: first lockfiles implementation; cleared up upated vs updateWorkspace commands
2023-05-23 23:48:00 +02:00
Juan M Gómez
bdccc9fef9 small refactor in preparation to fix #21889 (#21892) 2023-05-23 20:10:24 +02:00
Andreas Rumpf
1252070193 minor atlas improvements (#21888)
* minor atlas improvements

* atlas: support a _deps workspace subdirectory
2023-05-23 13:47:51 +02:00
Juan Carlos
d372ad3ee6 Fix jsgen (#21880)
* .

* Fix jsgen FrameInfo

* Fix jsgen FrameInfo

* .

* Move to PProc
2023-05-23 09:59:21 +02:00
Bung
76a98fee65 fix #21251 Compiler SIGSEGV when using SharedTable (#21876)
fix #21251
2023-05-23 09:39:44 +02:00
Andreas Rumpf
d696ef5ad7 Atlas tool: search github too, no need to register your project at pa… (#21884)
* Atlas tool: search github too, no need to register your project at packages.json

* added missing file
2023-05-22 20:35:27 +02:00
Juan M Gómez
ee3650b29e documents changes on byref and bycopy (#21882) 2023-05-22 17:39:54 +02:00
ringabout
b14043c39e revert #21808 (#21881) 2023-05-22 12:53:50 +08:00
Carlo Capocasa
9c2d2773ec Weekday parse/format (replacement) (#21857)
* parsing capability for iso week year

* remove outdated test
2023-05-21 20:12:05 +02:00
Jason Beetham
28a116a477 Fixed generic parameters failing to be used in inheritance (#21866) 2023-05-21 20:10:32 +02:00
Juan M Gómez
5606702e6d implements: "Allow bycopy to work in params #21874" (#21877)
* implements: "Allow bycopy to work in params #21874"

* Update compiler/pragmas.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-21 04:44:43 +02:00
Juan M Gómez
44f059c75e implements allow byref to work in params #21873 (#21875) 2023-05-21 00:19:09 +02:00
metagn
016aa1d98c remove legacy define for zero_functional tests (#21871)
test remove legacy define for zero_functional tests
2023-05-21 00:13:30 +02:00
Juan M Gómez
fcf2dcf099 Moves virtual under its own section manual_experimental.md (#21870) 2023-05-20 23:52:21 +02:00
metagn
641e34bcb2 fix #14254 (#21837)
* fix #14254

* use temporary PR branch for neo

* fix url
2023-05-20 21:09:16 +02:00
Juan M Gómez
a852b2e9cf refactor gettypedesc so it accepts its own kind instead of symkind (#21867) 2023-05-19 21:31:57 +02:00
heterodoxic
476e032004 potential fix for C++ codegen with ARC/ORC and goto exceptions fixes #21579, fixes #21862 (#21868)
potential fix for C++ codegen with ARC/ORC and goto exceptions
2023-05-19 21:24:37 +02:00
noah edward hall
4186529ff7 Update threadpool.nim with correct link to typedthreads module (#21865) 2023-05-19 21:23:44 +02:00
Juan M Gómez
21ff10b882 documents virtual (#21860)
* documents virtual

* Apply suggestions from code review

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-19 21:23:29 +02:00
Juan M Gómez
02a10ec379 Cpp Vfunctions draft (#21790)
* introduces virtual pragma, modifies proc def, prevents proc decl

* marks virtual procs as infix

* forward declare vfuncs inside the typedef

* adds naked callConv to virtual

* virtual proc error if not defined in the same top level scope as the type

* first param is now this. extracts genvirtualheaderproc

* WIP syntax

* supports obj. Removes the need for the prefix

* parameter count starts as this. Cleanup

* clean up

* sem tests

* adds integration tests

* uses constraint to store the virtual content

* introduces genVirtualProcParams

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-17 11:44:42 +02:00
Andreas Rumpf
1314ea7516 tasks that support return values (#21859)
tasks.nim: Code cleanups and support expressions that produce a value
2023-05-17 06:02:11 +02:00
ringabout
f22e5067c5 fixes #21847; let parseFloat behave like strtod (#21854) 2023-05-17 00:21:34 +02:00
ringabout
eecf12c4b5 fixes #21708; skip colons for tuples in VM (#21850)
* fixes #21708; skip colon for tuples in VM

* skip nimnodes

* fixes types
2023-05-17 00:20:40 +02:00
ringabout
ce1ba91573 close #19990; adds a test case (#21853) 2023-05-15 21:17:06 +02:00
heterodoxic
cf1ab2a30b fix #21848 (#21852) 2023-05-15 21:16:49 +02:00
Andreas Rumpf
f4a9b258c3 isolation spec update; WIP (#21843)
* isolation spec update; WIP

* wip

* docs update, WIP

* progress

* Update doc/manual.md
2023-05-14 16:58:28 +02:00
ringabout
0ece98620f closes #7590; add a test case (#21846) 2023-05-14 13:59:41 +08:00
ringabout
ddce555998 improve wasMoved hooks; allow reset to use the overridden wasMoved hook (#21831)
* improve `wasMoved` hooks

* Because `wasMoved` is lifted
2023-05-12 15:24:14 +02:00
Ecorous
871e4af6ef add getDataDir to std/appdirs.nim (#21754)
* add getDataDir to std/appdirs.nim

* reuse `osappdirs.getDataDir`

* Update lib/std/appdirs.nim

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-05-12 20:44:29 +08:00
ringabout
9c40dd2406 fixes #21840; nested local template lookup regression (#21841)
* fixes #21840; nested local template lookup regression

* use original types

* fixes js vm tests
2023-05-12 19:38:10 +08:00
metagn
161f50643a make deprecated statement a no-op (#21836) 2023-05-12 10:05:38 +02:00
ringabout
c6e2dc1919 fixes nightlies regressions; disable build-id=none on macos (#21839)
* fixes nightlies regressions; disable `build-id=none` on macos

* fixes typos
2023-05-12 10:03:41 +02:00
Matt Wilson
ea39c600ab Add minmax to comparisons (#21820)
* Add `minmax` to sequtils

This adds a `minmax` proc to complement `min` and `max`; it computes
both results in a single pass for efficiency.

* Update lib/pure/collections/sequtils.nim

* Add minmax note to changelog.

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-12 14:02:09 +08:00
metagn
9810b8cf7f just set CallNodes = nnkCallKinds, follows up #21829 (#21833)
These sets are now equal
2023-05-11 20:50:01 +02:00
ringabout
ebbad9e960 cursor fields cannot form reference cycles (#21832)
* cursor fields cannot form a reference cycle

* fixes typo

* fixes position
2023-05-11 20:49:47 +02:00
Tanguy
c004483581 Bootstrap: Allow to override number of CPUs (#21823)
* Allow to override number of cpu

* NCPU -> NIMCORES
2023-05-11 16:50:18 +02:00
ringabout
f7ed293fbd switch to the official URL of loop-fusion in the impoerant packages (#21830)
ref https://github.com/mratsim/loop-fusion/pull/9
2023-05-11 22:04:25 +08:00
Matt Wilson
802d57c237 Add nnkHiddenCallConv to nnkCallKinds (#21781) (#21829) 2023-05-11 20:14:44 +08:00
ringabout
3b9999b93c adds documentation for =wasMoved and =dup hooks and small fixes (#21827)
* adds documentation for `=wasMoved` and `=dup` hooks and small fixes

* Update doc/destructors.md

* Update doc/destructors.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-11 19:38:27 +08:00
Juan Carlos
fa5e7dc44a Improve nimsuggest (#21825)
Small improvement for nimsuggest
2023-05-11 10:49:19 +02:00
ringabout
71dc929ad7 bring #21802 back; fixes #21753 [backport] (#21815)
* bring #21802 back; fixes #21753 [backport]

* adds tests and multiple fixes

* add test cases

* refactor and remove startId

* fixes custom hooks and adds tests

* handle tyUncheckedArray better
2023-05-11 10:29:11 +02:00
metagn
02be212dae clean up SOME pending/xxx/issue link comments (#21826)
* clean up SOME pending/xxx/issue link comments

* great
2023-05-11 10:23:52 +02:00
Juan Carlos
3a08e2e6ac Remove LineTooLong (#21819)
* LineTooLong refactor to make it actually useful
* Improve error message
* changelog wording
* Fix typo
2023-05-11 10:10:51 +02:00
ringabout
055a00a6ef make reset use the =destroy and wasMoved pair (#21821)
* make reset use the `=destroy` and `waMoved` pair

* fixes a space

* fixes `shrink` instead

* tiny fix

* fixes vm

* suppress the annotations since it breaks some important packages
2023-05-11 09:02:29 +02:00
ringabout
71439c2891 fixes links of generic define pragma (#21828) 2023-05-11 15:00:30 +08:00
Andreas Rumpf
f3a4cc584e make ORC threadlocal, take two (#21818)
* ORC: make rootsThreshold thread local [backport]

* fixes the regression
2023-05-10 12:54:43 +02:00
ringabout
deaf684375 fix #9423 followup #17594: distinct generics now work in VM (#21816)
* fix #9423 distinct generics now work in vm

* fixes cpp tests

---------

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
2023-05-10 11:06:14 +02:00
metagn
4b76037e5f ignore inline hint for dynlib procs in codegen [backport] (#21817) 2023-05-09 21:44:47 +02:00
metagn
5592d1ef2c fix nimrtl and nimhcr on arc/orc (#21814)
* fix/workaround for nimrtl and nimhcr on arc/orc

fixes #21803

* try fix clang, debug linux failure

* just make duplicated procs not rtl

* actual fix for duplicated procs
2023-05-09 20:34:39 +02:00
Jordan Gillard
b169dad1e5 Improve and refactor cellseqs_v2 in Nim standard library (#21796)
* Refactor and optimize cellseqs_v2 in Nim standard library

* Extract resizing logic into a separate 'resize' procedure for better readability and separation of concerns
* Implement realloc for non-threaded cases to improve memory operations efficiency
* Use ',' instead of ';' between parameters in 'add' procedure for consistency with other Nim code

* Respond to Araq's feedback: Refactor resize function to use reallocShared

This commit replaces the usage of allocShared and deallocShared with reallocShared to optimize memory allocation and deallocation while resizing the CellSeq.
2023-05-09 20:33:35 +02:00
metagn
5491e0c274 re-enable badssl test (#21775)
test reenable badssl
2023-05-09 21:37:32 +08:00
Juan Carlos
4ee70165f1 Add build-id=none for GCC when build for Release (#21808)
* Add build-id=none to GCC/Clang, unneeded metadata in binaries

* Add build-id=none to GCC/Clang, unneeded metadata in binaries

* Add build-id=none to Clang

* Fix

* Fix

* Add build-id=none to GCC
2023-05-08 18:53:32 +02:00
Andreas Rumpf
ec3bca8fab Windows: use __declspec(thread) TLS implementation, it is MUCH faster… (#21810)
* Windows: use __declspec(thread) TLS implementation, it is MUCH faster than _Thread_local [backport]

* Update lib/nimbase.h

* better fix
2023-05-08 18:52:47 +02:00
Juan M Gómez
e45eb39ef7 documents codegendecl for object types (#21811) 2023-05-08 17:04:27 +02:00
ringabout
4533e894ad adds an experimental mm:atomicArc switch (#21798) 2023-05-08 16:25:47 +02:00
ringabout
ebdff1c7d3 fixes #21801; object field initialization with overloaded functions (#21805)
* fixes #21801; object field initialization with overloaded functions

* use the correct type
2023-05-08 13:52:28 +02:00
Jordan Gillard
71f2e1a502 🚀 Enhancing CellSeq for Better Readability and Maintainability (#21797)
Refactor and improve readability of CellSeq in system directory

* Use half-open range in the contains procedure for better readability and to avoid potential off-by-one errors
* Extract resizing logic from add procedure into a separate resize procedure for better code readability and separation of concerns
2023-05-07 09:25:25 +02:00
ringabout
4a94f3606e revert #21799 and #21802 which don't pass the tests (#21804)
* Revert "ORC: make rootsThreshold thread local [backport] (#21799)"

This reverts commit b74d49c037.

* Revert "fixes #21752 [backport] (#21802)"

This reverts commit d0c62fa169.
2023-05-07 09:22:42 +02:00
ringabout
8cf5643621 fixes #21280; Enum with int64.high() value crashes compiler (#21285)
* fixes #21280; Enum with int64.high() value crashes compiler

* Update tests/enum/tenum.nim

* Update tests/enum/tenum.nim

* fixes tests

* Update tests/enum/tenum.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-06 21:38:17 +02:00
ringabout
b562e1e6d8 implement =dup hook eliminating wasMoved and =copy pairs (#21586)
* import `=dup` hook eliminating `wasMoved` and `=copy` pairs

* add dup

* add a test for dup

* fixes documentation

* fixes signature

* resolve comments

* fixes tests

* fixes tests

* clean up
2023-05-06 21:36:57 +02:00
metagn
ba698d37c3 some Token refactors (#21762)
* test some Token refactors

* fix CI

* showcase for more reductions, will revert

* Revert "showcase for more reductions, will revert"

This reverts commit 5ba48591f4.

* make line and column int32

* remove int32 change
2023-05-06 21:27:28 +02:00
Andreas Rumpf
d0c62fa169 fixes #21753 [backport] (#21802) 2023-05-06 21:25:45 +02:00
quantimnot
365a753eed Fix some styleCheck bugs (#20095)
refs #19822

Fixes these bugs:

* Style check violations in generics defined in foreign packages are raised.
* Builtin pragma usage style check violations in foreign packages are raised.
* User pragma definition style check violations are not raised.

Co-authored-by: quantimnot <quantimnot@users.noreply.github.com>
2023-05-06 19:10:13 +02:00
ringabout
53c15f24e9 fixes #21704; remove nfIsRef for genLit in VM (#21765)
* fixes #21704; remove `nfIsRef` for genLit

* remove nfIsRef from the output of macros

* make the logic better

* try again

* act together

* excl nfIsRef
2023-05-06 18:04:08 +02:00
Andreas Rumpf
b74d49c037 ORC: make rootsThreshold thread local [backport] (#21799) 2023-05-06 17:58:00 +02:00
Tomohiro
10328e50a5 Document about size pragma (#21794)
* Document about size pragma

* Fix typos

* Fix manual.md

* Update doc/manual.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-05-06 12:03:45 +02:00
Daniel Belmes
85dbfc68b5 Update the Nim Manual compile pragma with the second tuple form (#21773)
* Update the nim manual compile pragma with the second tuple form of

* Incorrectly put 'two' forms
2023-05-05 14:27:33 +02:00
ringabout
07233ceca0 fixes #21792; enable checks for sum, prod, cumsummed and cumsum (#21793)
* enable checks for sum, prod, cumsummed  and cumsum

* fixes #21792

* add test cases
2023-05-05 14:23:38 +02:00
ringabout
724866b14f adds koch --skipIntegrityCheck boot support (#21795)
add `koch --skipIntegrityCheck boot` support
2023-05-05 13:58:29 +02:00
metagn
e92d7681bb consistent use of scForceOpen for generic dot field symbols (#21738)
* always force open generic dot field symbols?

fixes #21724 but might break code

* alternative, should fix CI

* other alternative, add test for previous CI failure

* not needed

* make sure call doesn't compile too

* ok actual second test

* ok final actual correct test

* apply performance idea

* don't make fromDotExpr static
2023-05-05 07:28:06 +02:00
ringabout
62f1ad54ae build documentation for checksums/md5 and checksums/sha1 (#21791)
* build documentation for md5 and sha1

* fixes documentation reference
2023-05-04 17:40:37 +02:00
Andreas Rumpf
79ac242c72 fixes #21780 [backport:1.6] (#21785)
* fixes #21780 [backport:1.6]

* complete patch
2023-05-04 16:42:04 +02:00
Federico Ceratto
acfa7849d3 Benchmark CI: drop id (#21787) 2023-05-04 20:30:58 +08:00
heterodoxic
a929e513fa amends #21690 to fix broken Nim to C++ source line mappings (#21784)
resync fork
2023-05-04 20:09:53 +08:00
ringabout
c34950f8f5 minor cleanup vmprofiler (#21783) 2023-05-04 15:44:46 +08:00
ringabout
34b78be396 adds checksums to important packages (#21782) 2023-05-04 15:10:49 +08:00
metagn
44736d26cd error on user pragma args (#21776)
closes #20978
2023-05-03 14:18:55 +02:00
ringabout
f37ecbb994 closes #21778; document threading/channels (#21779) 2023-05-03 19:25:07 +08:00
ringabout
1d80dc7df6 closes #21771; fixes the link (#21777)
closes #21771
2023-05-03 18:54:40 +08:00
ringabout
a154950570 closes #10108; add a test case (#21770) 2023-05-03 06:42:32 +02:00
metagn
e5d0907a42 line info for strformat + fix issue with typed templates (#21761)
* line info in strformat

* also fix #20381
2023-05-02 11:28:52 +02:00
metagn
ca82b4ea16 underscore as special word (#21766)
* underscore as special word

* fix really hard to notice error
2023-05-02 11:15:06 +02:00
metagn
c2bcfd8cd9 cheap fix for #10853 + better tuple subscript error message (#21767)
* cheap fix for #10853

* also better tuple subscript error message

* weird
2023-05-02 11:13:38 +02:00
ringabout
afc30ca879 fixes #19863; move sha1, md5 to nimble packages for 2.0 (#21702)
* move sha1, md5 to nimble packages

* boot the compiler

* fixes tests

* build the documentation

* fixes docs

* lol, I forgot koch.nim

* add `nimHasChecksums` define

* clone checksums but maybe copying is better

* bump nimble hash

* use ChecksumsStableCommit

* fixes tests

* deprecate them

* fixes paths

* fixes koch
2023-05-02 10:49:17 +02:00
Amjad Ben Hedhili
2844ac8b5e Ignore pkgs folder (#21755) 2023-05-02 10:41:59 +02:00
Juan M Gómez
3e82a315fc implements #21747 (#21748) 2023-05-02 10:10:51 +02:00
ringabout
aec5a4c474 fixes #20144; fixes asyncnet ssl on bsds (#21763)
fixes asyncnet on bsds
2023-05-01 15:42:53 +02:00
ringabout
8e0f336f6d fixes #21483; fixes nim doc skips documentation of annotated elements of objects (#21743)
* fixes #21483; skipPragmaExpr

* add a test case for #21483

* fixes HTML
2023-04-29 15:30:44 +02:00
Al Hoang
a593e40ad6 fix build on haiku (#21752)
* missing maxDescriptors
2023-04-29 09:50:46 +02:00
Federico Ceratto
77093bf7b9 Save and restore ci_bench cache (#21750) 2023-04-29 15:01:23 +08:00
ringabout
43f29842fc closes #21745 (#21746) 2023-04-28 20:26:21 +08:00
heterodoxic
91abf35442 improve C/C++ debug output readability (1/N) (#21690)
* hacky attempt to reconcile default explicit constructors with enforcement of brace initialization, instead of memsetting imported objects to 0

* improve C/C++ debug output readability (1/N)
2023-04-28 10:30:16 +02:00
ringabout
560fa9a1fe handle quoted routine symbols and non symbols expressions as before (#21740) 2023-04-28 10:25:31 +02:00
Andreas Rumpf
220b450489 fixes #21245; warn about destructors that can raise (#21726)
* fixes #21245; warn about destructors that can raise

* doc update

* progress

* typo
2023-04-26 22:32:10 +02:00
ringabout
8f79a124c9 fixes broken CI (#21732)
* fixes broken CI

* Update testament/important_packages.nim
2023-04-26 16:00:43 +08:00
ringabout
69c193e5e2 fixes #21731; fixes #21537; disable warnBareExcept by default [backport] (#21728)
* disable warnBareExcept for default

* fixes a typo
2023-04-26 08:04:13 +02:00
metagn
0032322ea8 fix #21727 (#21729) 2023-04-26 08:02:44 +02:00
Federico Ceratto
f0ae1ed544 Add benchmarking based on Minimize (#21566)
* Add benchmarking based on Minimize

* Update .github/workflows/ci_bench.yml

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-04-25 19:29:17 +08:00
Juan M Gómez
897dff69dd documents #21628 (#21723)
* documents #21628

* Update doc/manual.md

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-04-24 18:09:07 +02:00
Juan M Gómez
4754c51f1b Pragma to force the exportc of a type. #21645 (#21648)
exportc export all types not just those used by exported proc/globals

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-04-24 17:44:29 +02:00
ringabout
0f226c0e48 fixes #21703; moveOrCopy should consider when vm (#21721) 2023-04-24 14:57:48 +02:00
Andreas Rumpf
20b011de19 refactoring in preparation for better, simpler name mangling that wor… (#21667)
* refactoring in preparation for better, simpler name mangling that works with IC flawlessly

* use new disamb field

* see if this makes tests green

* make tests green again
2023-04-24 06:52:37 +02:00
metagn
380dafcc32 fix iterator equality + add test for proc equality + fix sameType (#21707)
* fix iterator equality + add test also for procs

fixes #21706

* all targets

* and isNil and repr

* separate overloads, fix sameType

* more restricted sameType?

* merge overloads again??

* remove sametype change for now

* fix sameType anyway (CI failure was not related)

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-04-23 17:43:59 +08:00
ringabout
265a340e80 fixes booting warnings (#21711)
follow up https://github.com/nim-lang/Nim/pull/21604
2023-04-23 15:34:46 +08:00
metagn
6ad246b215 temporarily disable badssl tests (#21710)
* temporarily disable badssl tests

refs #21709

* fix
2023-04-23 07:09:25 +02:00
metagn
63d29ddd69 alias syntax fixes, improvements and tests (#21671)
* alias syntax fixes, improvements and tests

* even better, cannot use alias syntax with generics

* more type tests, improve comment

* fix again

* consistent error message + make t5167_5 work

* more comments, remove {.noalias.}
2023-04-22 09:11:56 +02:00
Juan M Gómez
c136ebf1ed implements #21620: allowing to import multiple modules with shared names (#21628) 2023-04-21 15:40:13 +02:00
ringabout
4fa86422c0 stdlib tests now check refc too (#21664)
* stdlib tests now check refc too

* typo

* fixes line numbers

* disable cpp

* do not touch
2023-04-21 15:37:58 +02:00
Raynei
48de0d0cf4 Documented path substitution by compiler (#21662)
Document compiler path substitution (nim-lang#19928)
2023-04-21 15:37:21 +02:00
ringabout
b54b03d04f tweak spellsuggest; three counts for equal distances candidates by default (#21700)
* tweak spellsuggest; three counts for equal distances candidates

* only suggest typos when length > 3
2023-04-21 15:36:18 +02:00
quantimnot
175a83c2de refact: Remove assertion effect hiding workaround (#21472)
refact: Remove asseertion effect hiding workaround

There was a code comment to remove after bootstrapping with `nim >= 1.4.0`.

Co-authored-by: quantimnot <quantimnot@users.noreply.github.com>
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-04-21 18:06:20 +08:00
Bung
d76458a6cd add test for #13764 (#21699) 2023-04-21 18:05:50 +08:00
Yardanico
418e54452b Fix json.to for float fields that are not present (#21695) 2023-04-21 06:11:30 +02:00
ringabout
f9477396a6 static link pthread correctly (#21693) 2023-04-20 17:35:15 +02:00
Thiago
ed7c6cdc98 Fixed window.find return (#21621)
https://developer.mozilla.org/en-US/docs/Web/API/Window/find
2023-04-19 21:51:23 +02:00
ringabout
135b677704 fixes nightlies regression (#21689)
* fixes nightlies regression

ref https://github.com/nim-lang/Nim/pull/21659
ref https://github.com/nim-lang/nightlies/actions/runs/4727252660/jobs/8387899690

> /home/runner/work/nightlies/nightlies/nim-1.9.3/lib/std/sysrand.nim(198, 12) Error: cannot evaluate at compile time: EINTR

Because EINTR is not a const on i386

* Update lib/std/sysrand.nim
2023-04-19 11:56:12 +02:00
ringabout
9cb06d357e fixes #21540; deref block at transf phase to make injectdestructors function properly (#21688)
* fixes #21540; deref block at transf phase to make injectdestructors function properly

* add a test case

* add one more test

* fixes the type of block

* transform block
2023-04-19 11:55:54 +02:00
Bung
0d6b994bee fix #20997 (#21165)
* fix #20997

* use ptr UncheckedArray[uint8] instead
2023-04-19 09:50:49 +02:00
ringabout
d2d849db8e docuement case statement breaking changes in the changelog (#21686)
Reported on Discord 
follow up https://github.com/nim-lang/Nim/pull/20862
2023-04-19 14:19:30 +08:00
Andrey Makarov
24b6378382 Fix RST/Markdown false heading detection (#21685) 2023-04-18 10:37:47 +02:00
metagn
2f547afb0f import brackets support as and prefixes [backport] (#21636)
* import brackets support `as` and prefixes

fixes #21635

* copyTree -> copyNode
2023-04-18 10:35:35 +02:00
metagn
9dc1f2dd0f actually fix #19015 (#21680)
* actually fix #19015

* more tests

* round out
2023-04-17 20:56:52 +02:00
metagn
202b190473 revert #21227 (#21681)
* revert #21227 but keep test

* add test for #21677

* don't export

* delete test
2023-04-17 20:56:11 +02:00
metagn
b0a98cc01e warn on set types bigger than max size, default to 0..255 for int literals (#21659)
* test implicitly huge set types

refs https://github.com/nim-lang/RFCs/issues/298

* oh my god

* boot at least

* don't error, fix remaining issues, no 2 len arrays

* fix runnable example

* test assuming 0..255 for int literal

* test refactor, add changelog, test
2023-04-17 20:55:22 +02:00
Emery Hemingway
2621f78b68 compiler/docgen: pass --path:… to runnableExamples (#21669) 2023-04-17 20:53:42 +02:00
ringabout
65223e6f59 fixes #21674; lent can be used in the fields or the cast type as a parameter (#21684)
* fixes #21674; `lent` can be used in the fields or the cast type as a parameter

* add a test case

* fix the test
2023-04-18 00:31:47 +08:00
ringabout
91e4381a20 fixes #20155; repr range with distinct types is broken in ORC (#21682)
fixes #20155; repr range with distinct types is broken with ORC
2023-04-17 17:08:53 +02:00
metagn
8c4b7129b5 fix small mistake from #21629 (#21672) 2023-04-17 17:07:09 +02:00
Jaremy Creechley
1af21c2668 change compile pragma to use mangled compile objects (#21678)
change compile pragma to use mangle
2023-04-17 14:17:02 +02:00
Mamy Ratsimbazafy
938f5c5e99 LTO improvements - fix #15578 (#21679) 2023-04-17 13:02:34 +02:00
Andrey Makarov
a0da74ed4c Update nim 2.0 documentation for docgen & nimgrep (#21665)
* Update nim 2.0 documentation for docgen & nimgrep

* [skip ci] Update changelogs/changelog_2_0_0.md

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* [skip ci] expand section on Markdown migration and `doctype`

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-04-17 10:57:51 +02:00
Andreas Rumpf
ea8aafa7c9 minor codegen bugfix (#21670) 2023-04-15 01:17:17 +02:00
ringabout
512517c223 fixes #18146; fixes #19372; disable tlsEmulation on windows; static link pthreads with mingw (#21668)
* fixes #18146; disable tlsEmulation on windows; static link libwinthreads DLL

* whatever
2023-04-14 22:52:35 +02:00
metagn
1a99bcd6ab runnableExamples imports std/assertions by default (#21658)
closes https://github.com/nim-lang/RFCs/issues/499
2023-04-14 12:39:23 +02:00
metagn
2a0d8a9a06 make grammar a bit more honest (#21655)
* test if expr parsing expr

refs #19802

* in any case

* just be honest

* fix symbol/keyword issue too
2023-04-14 12:34:49 +02:00
metagn
c694d8e4fd custom pragmas: correct error condition, remove outdated symkind whitelist (#21653)
* test not restricting custom pragma applied symbols

fixes #21652

* fix other test

* different patch

* fix tests

* actually test #18212 and other routines
2023-04-13 12:50:43 +02:00
ringabout
16f42084d3 fixes #20900; Calling template through from generic function across module fails to build (#21649)
* fixes #20900; Calling template through from generic function across module fails to build

* sanother way
2023-04-13 12:11:06 +02:00
metagn
3f51b6f73d set module symbol type to None instead of nil for discard check (#21657)
* set module symbol type to None instead of nil

fixes #19225

* alright
2023-04-13 11:56:16 +02:00
ringabout
c33ab0ba38 stops building nimsuggest twice and nim_dbg in tests; saves 3 * 5 minutes CI time (#21654)
stop building nimsuggest twice and nim_dbg in tests; saving 3 * 5 minutes CI time
2023-04-13 11:52:24 +02:00
ringabout
1ed54b7718 fixes #21632; enforce deref for wasMoved in ORC (#21647)
fixes #21632; enforce deref for `wasMoved`
2023-04-12 10:45:45 +02:00
metagn
f05387045d int64/uint64 as bigint in JS (#21613)
* int64/uint64 as bigint in JS

* fix CI

* convert to compile option

* fix lie

* smaller diff, changelog entry
2023-04-11 21:20:20 +02:00
metagn
be06446ffe fix #15691 (#21623)
`semProcAux` has a check for `checkMinSonsLen(n, bodyPos + 1)`
2023-04-11 09:37:53 +02:00
metagn
1bb117cd7a proc typeclass accounts for iterator, call conventions + nil fix + document typeclass AST (#21629)
* test fix #16546 #16548 + another issue

* please don't tell me other packages do this

* fix CI + test typeclass callconv pragma

* better logic in parser

* docs and changelog
2023-04-11 09:23:41 +02:00
Andrey Makarov
420b0c14eb Fix option lists with additional indentation in Markdown (#21633)
This is more Markdown-ish way to fix issue #21055, then PR #21625.
It does not enable RST definition lists, instead it makes
adding additional indentation (less than 4) right after a paragraph
be ignored, as it's done for all block elements in Markdown.
(In this case this tenet is applied to option lists that are not
part of CommonMark spec by themselves).
2023-04-11 06:40:20 +02:00
ringabout
4c073cffbe disable i386 tests for now; help wanted (#21642)
I have done some investigations but still cannot figure it out in https://github.com/nim-lang/Nim/pull/21637, https://github.com/nim-lang/Nim/pull/21612 and https://forum.nim-lang.org/t/10069. If someone has a clue, please enlighten me.
2023-04-11 06:39:31 +02:00
ringabout
5e016e4466 fixes #21638; fromJson should support empty objects (#21641)
* fixes #21638; `fromJson` should supports empty objects

* complete the logic
2023-04-11 06:38:30 +02:00
Etan Kissling
75205fee93 terminal size env-vars have precendence in POSIX (#21643)
In POSIX Base Definitions Section 8.1 Environment Variable Definition,
it is explained that the `COLUMNS` and `LINES` environment variables,
if present, take precedence over any other implementation-defined method
to determine the terminal size. This is useful, for example, to capture
output programmatically in simulations for various terminal sizes.
2023-04-11 11:43:21 +08:00
ringabout
4d683fc689 fixes booting warnings (#21583) 2023-04-10 09:43:12 +02:00
metagn
16bc546aea remove useVersion (#21626)
test removing useVersion
2023-04-08 11:42:17 +02:00
Jason Beetham
686c75cef0 for loop expression can now have generated iterator's called (#21627)
A for expression now can have a generated iterator, allowing for more composable iterables
2023-04-08 11:40:43 +02:00
ringabout
a37a83cbff fixes #21617; createTypeBoundOps with PContext in order to instantiate generics (#21619)
* fixes #21617; createTypeBoundOps with PContext in order to instantiate generics

* keep idgen
2023-04-07 22:18:09 +02:00
metagn
814d3e6818 fix #19430 (#21603) 2023-04-06 13:36:21 +02:00
metagn
4898b054ce warn against a, b = val in routine arguments (#21604)
closes https://github.com/nim-lang/RFCs/issues/480
2023-04-06 13:21:48 +02:00
ringabout
baa577e9e8 switch to the official regex URL (#21616)
ref https://github.com/nitely/nim-regex/pull/119
2023-04-06 15:06:06 +08:00
ringabout
c71192043b fixes #21392; document nimble develop breaking changes (#21614) 2023-04-04 20:37:01 +02:00
ringabout
3575f2bf9c fix #20972 fixes invalid and UB codegen case object transitions for both refc and ORC [backport] (#21611)
fix #20972 fixes invalid and UB codegen case object transitions for refc and ORC
2023-04-04 12:18:43 +02:00
chmod222
31d3606fe8 fixes #21564; std/bitops: Add explicit type masking for the JS target (#21598)
* std/bitops: Add explicit type masking for the JS target

Typecasts on the JavaScript backend do not function the same way as they
do on C and C++ backends, so for bitwise operations we may need to mask them
back down into their allowed range when they get shifted outside it.

Since they do work as expected on the other backends, a default bitmask
of all 1's is casted down into the target type as an easily optimizable
"& 0xFF" operation for these backends.

* Fixup: this should still be a func

* Run test case on js target

* Adapt testcase to contributor guide and best practices

* Simplify constrain logic and turn into actual no-op for the C side
2023-04-03 05:22:31 +02:00
Tomohiro
6ec9c7f683 Fix example code of proc add*[T](x: var seq[T], y: sink openArray[T]) (#21607)
* Fix example code in system.nim

* Add example code to lib/system.nim

* Fix compile error

* Fix example code that can be unsafe
2023-04-03 05:15:14 +02:00
Andrey Makarov
63b4b3c5b8 Fix nim doc crash with group referencing & include (#21600)
This fixes a regression introduced in #20990 . When a group referencing
is used and one of the overloaded symbols is in `include`d file, then
`nim doc` crashes. The fix is in distinguishing (the index of) module
and file where the symbol is defined, and using only module as the
key in hash table for group referencing.
2023-04-02 10:32:36 +02:00
chmod222
0c6f14af04 macros: Extend treeTraverse intVal range to nnkUInt64Lit (#21597)
* Extend intVal range to nnkUInt64Lit

Fixes #21593

* Properly cast intVal as unsigned

* Add testcase for #21593
2023-04-01 20:29:28 +02:00
ringabout
a80f1a324f fixes #21592; create type bound operations for calls in the method dispatcher for ORC (#21594)
* fixes #21592; create type operations for the method dispatcher

* add a test case
2023-04-01 17:08:45 +02:00
ringabout
1c7fd71720 fixes changelog (#21590) 2023-03-31 15:51:37 +08:00
Andreas Rumpf
d5719c47dc make --exceptions:quirky work with C++ (#21581)
* make --exceptions:quirky work with C++

* make tests green again
2023-03-31 04:16:09 +02:00
Miran
2e4ba4ad93 bump NimVersion to 1.9.3 (#21587) 2023-03-30 20:25:14 +02:00
Yardanico
b865f6a5f0 Remove the "This module" suffix and reword some entries from the stdlib overview (#21580)
Remove a lot of "This module x" and reword some entries
2023-03-30 15:35:17 +02:00
Andreas Rumpf
72ca444122 hopefully easier to understand error message (#21585) 2023-03-30 15:35:00 +02:00
metagn
ecf9efa397 document general use of _, error message, fixes (#21584)
* document general use of `_`, error message, fixes

fixes #20687, fixes #21435

Documentation and changelog updated to clarify new universal behavior
of `_`. Also new error message for attempting to use `_`, new tests,
and fixes with overloadable symbols and
implicit generics.

* add test for #21435
2023-03-30 15:34:42 +02:00
tersec
51ced0d684 remove seq[T] setLen undefined behavior (#21582)
remove seq[T] setLen UB
2023-03-29 12:00:00 +02:00
Jason Beetham
c06623bf8c Fix segfault caused by ensuring valueless statics are not evaluated (#21577) 2023-03-29 04:50:56 +02:00
metagn
2315b01ae6 tuple unpacking for vars as just sugar, allowing nesting (#21563)
* tuple unpacking for vars as just sugar, allowing nesting

* set temp symbol AST

* hopeful fix some issues, add test for #19364

* always use temp for consts

* document, fix small issue

* fix manual indentation

* actually fix manual

* use helper proc

* don't resem temp tuple assignment
2023-03-28 17:52:23 +02:00
Zoom
4fc9f0c3a3 Docs: Mention Source Code Filters in lib/String handling (#21570)
Mention Source Code Filters in `String handling`

...as a viable solution for templating
2023-03-28 13:37:49 +02:00
Andreas Rumpf
115cec1745 fixes #20993 [backport:1.6] (#21574)
* fixes #20993 [backport:1.6]

* proper line endings for the test file
2023-03-28 13:27:17 +02:00
metagn
0630c649c6 disable google request in thttpclient (#21572)
was breaking macos CI
2023-03-28 16:34:30 +08:00
ringabout
ff5ed1dbb1 Revert "Add cursor to lists iterator variables" (#21571)
Revert "Add `cursor` to lists iterator variables (#21527)"

This reverts commit 3936071772.
2023-03-28 14:29:12 +08:00
heterodoxic
7d83dfd0d1 fixes #21505 (overload resolution of explicit constructors for imported C++ types) (#21511)
hacky attempt to reconcile default explicit constructors with enforcement of brace initialization, instead of memsetting imported objects to 0
2023-03-27 17:20:20 +02:00
Amjad Ben Hedhili
3936071772 Add cursor to lists iterator variables (#21527)
* followup #21507
2023-03-27 17:10:51 +02:00
ringabout
55636a2913 fixes #14255; Crash in compiler when using system.any by accident. (#21562)
fixes #14255; Crash in compiler when using system.any by accident.
2023-03-23 16:10:14 +01:00
tersec
e8a70ff179 don't access void* out of alignment in refc GC to avoid UB (#21560) 2023-03-22 22:05:20 +01:00
Andreas Rumpf
d84b02f0e0 atlas tool: 'update' command (#21557) 2023-03-21 15:24:57 +01:00
ringabout
c814c4d993 fixes #3770; templates with untyped parameters resolve private fields wrongly in generics (#21554)
* fixes #3770; templates with untyped parameters resolve private fields wrongly

* add a test case for #3770

* rename to `nfSkipFieldChecking`
2023-03-21 15:22:07 +01:00
Andreas Rumpf
f7e3af0c2d mitigates #21272; but it's not the final fix because the first round … (#21462)
mitigates #21272; but it's not the final fix because the first round of overload resolution should already match
2023-03-20 22:53:13 +01:00
Peter Munch-Ellingsen
c155e20796 Fix infinite recursion introduced in 7031ea6 [backport 1.6] (#21555)
Fix infinite recursion introduced in 7031ea6
2023-03-20 22:43:42 +01:00
ringabout
274d61865f closes #21536; fixes manual (#21552)
fixes manual
2023-03-20 22:42:57 +01:00
Federico Ceratto
9df8ca0d81 Add URI parsing warning (#21547)
Related to CVE-2021-41259
https://github.com/nim-lang/security/security/advisories/GHSA-3gg2-rw3q-qwgc
https://github.com/nim-lang/Nim/pull/19128#issuecomment-1181944367
2023-03-20 18:51:58 +01:00
Eric N. Vander Weele
da7833c68b fixes #21538; expand len template parameter once in newSeqWith (#21543)
`len` could contain side effects and may result in different values when
substituted twice in the template expansion. Instead, capture the result
of substituting `len` once.

closes: #21538
2023-03-20 18:51:31 +01:00
Mark Leyva
285ea3c48e Fix: #21541. Add support for xnVerbatimText (#21542)
to text and text= procs. Remove unnecessary LF for xnVerbatimText
in $ proc.
2023-03-20 18:50:58 +01:00
Ivan Yonchovski
fb00b482eb Avoid calling build_all* when nim binary is present (#21522)
- `nimble` will build `nim` using `bin/nim` and if it is already present we can
reuse it.
2023-03-20 18:49:59 +01:00
Regis Caillaud
ba22826e9b Add check for nimMaxJeap on occupied memory + allocation size (#21521)
* fix nimMAxHeap checks

* move check to alloc pages

* remove debug trace

* Fix bad indentation

How the hell did that pass through CI ?
2023-03-20 18:49:18 +01:00
Jake Leahy
741fed716e Use analyseIfAddressTaken logic for checking if address is taken in converter (#21533)
* Add a test case

There are way more test cases (See all branches of analyseIfAddressTaken but this covers at least a second branch

* Port analyseIfAddressTaken from semexprs to sigmatch

This was done since we cannot import sem or semexprs (circular import) but we need the rest of the logic. In needs to be done here since the converter isn't semmed afterwards and so we can't just leave the process til later use the version from semexprs

* Less hacky solution which has the checking be done in analyseIfAddressTakenInCall

This was done instead of the recommendation on removing it since sfAddrTaken is used in places other than the backend

* Remove weird whitespace

* Still check nkHiddenAddr if we are checking a converter
2023-03-20 18:48:13 +01:00
Hiroki Noda
ae06c6623d NuttX: use posix_spawn for osproc (#21539)
NuttX has standard posix_spawn interface, and can be used with it.

* https://nuttx.apache.org/docs/12.0.0/reference/user/01_task_control.html#c.posix_spawn
2023-03-20 18:43:10 +01:00
Hiroki Noda
0c1d595fae NuttX: use accept4 (#21544)
NuttX supports accept4 since 48c9d10336
2023-03-20 18:41:25 +01:00
Joey
cae539996a Update LLDB debug script + Add Custom Nim formatters (#21517)
* Fix custom objects, fix handling of nil variables

* Rename because lldb complains about dashes in filename

* Add example of how to use custom type formatting from Nim

* Add synthetic objects with dynamic fields and add an example
2023-03-19 06:28:00 +01:00
Jason Beetham
a9d0124b5d Made generic type classes work with types using static parameters (#21528) 2023-03-17 10:17:08 +01:00
ringabout
fd4e3ae3e4 add a prepass for codeReordering (#21513)
* add a prepass for codeReordering

* simplify

* fixes
2023-03-17 08:02:48 +01:00
ringabout
b5ee81fd23 fix #18977; disallow change branch of an object variant in ORC (#21526)
* fix #18977 disallow change branch of an object variant in ORC

* check errors for goto exception

* fixes conditions

* fixes tests

* add a test case for #18977
2023-03-16 16:06:26 +01:00
ringabout
6552a27ec1 fixes #19857; Exception raised in closure may be "skipped" in ORC (#21530)
fixes #19857; Exception raised in closure may be "skipped"
2023-03-16 21:07:54 +08:00
Hiroki Noda
c43ac90390 Add NuttX for thread stack size doc (#21529) 2023-03-16 18:03:43 +08:00
Amjad Ben Hedhili
26b7a74a45 Optimize cgen.addIndent (#21508)
* Optimize `cgen.addIndent`

* Avoid temporaries
2023-03-13 17:32:20 +01:00
Amjad Ben Hedhili
c52e44d845 Add cursor annotations to lists iterator variables (#21507)
Add `cursor` annotations to iterator variables

* See https://nim-lang.github.io/Nim/destructors.html#the-cursor-pragma
2023-03-13 08:43:45 +01:00
ringabout
b2c1dcbbc9 fixes explicit globals in macros (#21502) 2023-03-12 20:03:46 +01:00
ringabout
ffadc75afe fixes #21496; Ambiguous calls compiles when module name are equal (#21500)
* fixes #21496; Ambiguous calls compiles when module name are equal

* add a test case
2023-03-12 20:03:14 +01:00
ringabout
af086b68f2 fixes sinkinference documentation, which has been disabled (#21470)
since https://github.com/nim-lang/Nim/pull/15105
2023-03-12 13:01:12 +08:00
Andreas Rumpf
46d2161c23 minor refactoring (#21499) 2023-03-10 14:20:30 +01:00
ringabout
f2dad94902 fixes #21306; fixes #20485; don't transform yields in the var section when introducing new local vars [backport: 1.6] (#21489)
* fixes #21306;  don't transform yields in the var section when introducing new local vars

* adds `inVarSection` so the var section in the var section is freshed

* use `isIntroducingNewLocalVars` to avoid yield transformations in var sections

* fixes comments
2023-03-10 14:19:31 +01:00
ringabout
0319824322 fixes #21023; Segfault when mixing seqs, orc, variants and futures (#21497)
* fixes #21023; Segfault when mixing seqs, orc, variants and futures

* fixes none of the branches were explicitly selected

* add one more test

* one more test
2023-03-10 09:28:51 +01:00
ringabout
72e262666b fixes quoted variables with typedesc types (#21493) 2023-03-09 08:09:08 +01:00
ghost
8e9fc5e639 a better message if graphviz's dot/nodejs is not found in PATH (#21488)
* finish issue #21474: a better message if dot is not found locally when using gendepend

* fix a typo in compiler

* trim empty path reported in `findNodeJs`

* compiler/main.nim: switch raise to simply quit
2023-03-08 22:34:59 +01:00
ringabout
2f89f1eb78 closes #8295; add a test case (#21486) 2023-03-07 20:17:05 +08:00
ringabout
6ef9430153 closes #6231; add a test case (#21485) 2023-03-07 17:34:02 +08:00
Jake Leahy
25eef64fe1 Remove Defect from raises list in std/times (#21473)
* Remove Defect from raises list

Since defects aren't tracked anymore this causes a hint to pop up mentioning it

* Still track Defect when getting ran with an older Nim version

The raises followed a pattern so moving them into a pragma didn't seem to cause any extra problems
2023-03-06 15:31:53 +01:00
ringabout
64a0355f3f fixes #21377; fixes @[] and {} type inference as returns in generics (#21475)
* fixes `@[]` type inference in generics

* add issue links

* fixes macros and iterators

* refactor

* add one more test
2023-03-06 15:30:22 +01:00
ringabout
2d9af2bd55 closes #20704; add a test case (#21480) 2023-03-06 17:34:41 +08:00
ringabout
4d76725299 closes #16654; add a test case (#21478) 2023-03-06 14:12:47 +08:00
Joey
05e8a60bb4 Add line directives for C code variables (#21466)
* Add line directives for C code variables

* Refactor genCLineDir to only use toFullPath if necessary
2023-03-05 20:14:59 +01:00
SirOlaf
7bde421e4d Fix #21272: Rewrite parts of pickBestCandidate (#21465)
* Make pickBestCandidate store syms

* Remove useless cursor

* Try making pickBestCandidate more readable

* Fix advance order

* Revert back to seq with lots of comments

---------

Co-authored-by: SirOlaf <>
2023-03-05 11:56:51 +01:00
Sultan Al Isaiee
04a494f8cf Add warning to specify timeout value in milliseconds, Fix #21449 (#21471)
a warning message been added to the documentation to remind users that the timeout parameter is expressed in milliseconds, not seconds. to help prevent confusion and unexpected behaviours.
2023-03-04 15:53:57 +01:00
ringabout
d950e5f3a8 remove nosinks hacks from compiler (#21469) 2023-03-04 20:07:33 +08:00
quantimnot
6994e1b1d7 --embedsrc for JavaScript (#21467)
Co-authored-by: quantimnot <quantimnot@users.noreply.github.com>
2023-03-04 07:57:30 +01:00
Arnaud Moura
b2c5f8a05f fixes #21461 (#21463)
* fixes #21461; Move nim-gdb.py and add nim-lldb.py

* fixes bad path for nim-gdb.py
2023-03-03 23:37:12 +01:00
ringabout
2e2affb13c test DLL generation with ORC (#21445)
* test DLL generation with ORC

* fixes

* fixes refc

* Update testament/categories.nim
2023-03-03 23:13:27 +08:00
ringabout
d51a392149 replaces implicit passes array registed at runtime with explicit function calls; simplify compilation pipeline (#21444)
* abolish using passes in the compiler; simplify compilation pipeline

* duplicate code

* Really cool to have the same signature...

* haul

* unify other backends

* refactor process

* introduce PipelinePhase

* refactor compiler

* fixes passes

* fixes nimsuggest

* add a sentinel

* enable docs checkj

* activate doc testing

* clean up

* complete cleanups
2023-03-03 07:36:38 +01:00
Jake Leahy
d4d28f2ffe Allow futureLogging in release builds (#21448)
* Add test case

* Fixes 21447: Keeps stackTrace around when using futureLogging

* Remove extra whitespace
2023-03-02 14:27:10 -05:00
ringabout
38d299dfc0 fixes #20139; hash types based on its path relative to its package path (#21274) [backport:1.6]
* fixes #20139; hash types based on its path relative its project

* add a test case

* fixes procs

* better implementation and test case

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-03-02 09:16:28 +01:00
Andreas Rumpf
50baf21eac fixes #20422; emit nimPrepareStrMutationV2 for toOpenArray to keep th… (#21459)
fixes #20422; emit nimPrepareStrMutationV2 for toOpenArray to keep the abstraction of mutable strings which have immutable string literals
2023-03-02 08:36:02 +01:00
tersec
612abda4f4 remove decades-deprecated Win32 API *A function support (#21315) 2023-03-02 05:51:54 +01:00
Ivan Yonchovski
9b5ae2b2eb Define the version of nim package without using system module (#21415)
This is follow up from https://github.com/nim-lang/Nim/pull/21313
2023-03-02 05:30:55 +01:00
ringabout
a137e50150 fixes #19291; implements wasMoved hook (#21303)
* fixes #19291; implements `wasMoved` hook

* basics

* checkpoint

* finish `wasMoved`

* add a test for #19291

* add documentation and changelog

* work `attachedWasMoved` with generics

* fixes optimizer

* register `=wasMoved`

* handle wasMoved magcis

* check another round

* some patches

* try `op == nil`

* nicer

* generate `wasMoved` before `destroy`

* try again

* fixes tests

* default wasMoved

* Update tests/destructor/tv2_cast.nim

* Update tests/destructor/tv2_cast.nim

* Update tests/arc/topt_refcursors.nim
2023-03-02 05:29:40 +01:00
ringabout
9948fed919 fixes #21326; fixes #7375; fixes #11986; fixes #9607; rework quote do; getAst uses type info to annotate the type of quoted variables; no more type erasures for quoted variables (#21433)
* fixes #21326; getAst uses type info to annotateType quoted variables

* simplify logics; sem types first

* fixes important packages

* add testcases

* tiny
2023-03-02 05:25:55 +01:00
Anna
070938720a tests/errmsgs/tcall_with_default_arg.nim: sync (#21237) 2023-03-01 21:29:23 +01:00
Anna
cf083af262 tests: explicitly enable stack traces where needed (#21236)
* tests/assert/tassert_c.nim: explicitly enable stack traces

* tests/errmsgs: explicitly enable stack traces
2023-03-01 18:01:58 +01:00
Anna
89d8c0b246 tests/stylecheck: make sure necessary hints are enabled (#21240) 2023-03-01 18:00:58 +01:00
ringabout
1b1412f3d1 fixes #10938; fixes #13312; fixes #13918; fixes #20985; always initializes global variables with null values in VM (#21351)
* fixes #10938; always initialize global variable in VM

* fixes importc vars

* there is a pre-existing issue regarding closure types in the VM

* add tests
2023-03-01 17:18:09 +01:00
heterodoxic
c4dd0c4301 suggestion for a simple fix for #21279 (#21378) 2023-03-01 17:17:05 +01:00
Constantine Molchanov
39d0a93d0e Fix #21452; enable Norm in important packages. (#21455)
* fix #21452; enable Norm in important packages.

* Run test that doesn't require SQLite.
2023-03-01 10:30:38 +08:00
Century Systems
dd629c8f45 asyncdispatch: for NuttX, add destructor to clear global dispatcher. (#21432)
* asyncdispatch: for NuttX, add destructor to clear global dispatcher using atexit().

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>

* std: exitprocs: remove "when defined(nuttx)" block.

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>

---------

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>
2023-02-28 14:38:50 +01:00
Antonis Geralis
83e3320725 Use a cast to suppress KeyError raises (#21451) 2023-02-28 14:17:21 +01:00
ringabout
6fea221d65 Overrides =copy for PackedSets (#21417) 2023-02-27 00:57:36 +01:00
Ikko Eltociear Ashimine
89a60939f8 Fix typo in sourcemap.nim (#21438)
seperated -> separated
2023-02-27 00:57:02 +01:00
Constantine Molchanov
4ae598762e fixes #21439; Add tyOpenArray to genTypeInfo. (#21440)
* fixes #21439; Add tyOpenArray to genTypeInfo.

* Add test.
2023-02-27 00:56:43 +01:00
PhilippMDoerner
425225119a Add mention of breaking change about [_] in generics to changelog (#21437)
Add mention of breaking change to changelog

As described by #21435 , generic proc declarations making use of `_` as generic
parameter are no longer possible. This is a change that was introduced by 
#21192 . During the debate over if this should be part of the intended spec in
#21435 we concluded that it is and thus should be mentioned as a breaking
change in the changelogs.
2023-02-26 16:57:51 +08:00
Dmitry Arkhipenko
b2edfe7a02 Fix: nintendoswitch compilation (#21368)
* Fix: make nintendoswitch someGcc, remove symlink support for nintendoswitch, add getAppFilename for nintendoswitch

* Fix: use getApplHeuristic on nintendoswitch
2023-02-25 11:47:19 +01:00
ringabout
d4782c9e42 closes #17864; add a test case (#21434) 2023-02-25 00:53:04 +08:00
Francis Thérien
7837e57e93 Disable threads for os:any (#21425) 2023-02-24 09:07:35 +01:00
ringabout
bbb6d2c69d fixes #20695; fixes object with distinct defaults and tables (#21428) 2023-02-24 09:02:44 +01:00
Andreas Rumpf
8a19ac2070 fixes #21393 and misc style changes (#21419)
* fixes #21393 and misc style changes

* progress

---------

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-02-24 09:02:15 +01:00
Francis Thérien
7dc80a7fef Mitigate issues related to compiler options when cross-compiling (#21330)
* Document C compiler options config when cross-compiling

* Allow empty string to override default
2023-02-22 21:10:02 +01:00
ringabout
38f876dd48 fixes #19795; fixes #11852; fixes #19974; remove parsing pipeline, Nim now parses the whole module at one time (#21379)
* fixes #19795; remove parse pipeline

* isScript

* fixes nimscriptapi

* don't touch reorder

* check script

* fixes tests

* it seems implicit imports of system cause troubles

* access the first child of `nkStmtList`

* ignore comments

* minor messages

* perhaps increases hloLoopDetector

* the module is a stmtList, which changes the errors

* fixes nimdoc

* fixes tlinter

* fixes nim  secret tests

* fixes arc_misc

* fixes nim secret tests again

* safe; fixes one more test

* GlobalError is the root cause too

* fixes parsing errors

* put emit types to the cfsForwardTypes section

* fixes #11852; `{.push checks:off}` now works in procs

* disable navigator

* fixes nimdoc

* add tests for JS

* fixes nimsuggest
2023-02-22 20:34:20 +01:00
c-blake
fdd7520257 Fix the TODO portion of recently added posix_fallocate on OS X. (#21387) 2023-02-22 13:54:04 -05:00
Century Systems
ab1d4a5d58 ioselectors_epoll: for NuttX, limit initial numFD to configured value. (#21421)
ioselectors: ioselectors_epoll: for NuttX, limit initial numFD to configured value.

In the NuttX build config, there is a setting called "FS_NEPOLL_DESCRIPTORS".

--------
config FS_NEPOLL_DESCRIPTORS
	int "Maximum number of default epoll descriptors for epoll_create1(2)"
	default 8
	---help---
		The maximum number of default epoll descriptors for epoll_create1(2)
--------

For NuttX, change the number of fd arrays allocated by newSelector() to that value.

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>
2023-02-22 13:53:04 -05:00
Benji York
64a788cafb Fix a couple of small keyword issues. (#21416)
In this section of the manual, "if" should be enclosed in backticks and "elif" should be lower case.
2023-02-22 12:12:10 +01:00
ringabout
a3603c8a6e saves one unnecessary compare which is also a small regression (#21413)
saves one unnecessary compare which is also a sall regression

follow up d30c6419a0
2023-02-21 23:42:28 +01:00
Jake Leahy
0a45543cc1 Specify that address is taken when converter takes a var parameter (#21391)
* Add test case

* closes #21247 Add the sfAddrTaken flag to var parameters in converters

This allows the JS backend to properly pass the parameter as a fat pointer
2023-02-21 12:27:12 +01:00
Ecorous
de65b380ed Add getDataDir proc (#21408)
* Add getDataDir()

* Update lib/std/private/osappdirs.nim

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-02-21 12:14:41 +01:00
Jake Leahy
6d423f1856 Make Time work with std/strformat (#21409)
* Add test case

* Remove formatValue template for `Time`

It didn't handle empty specifier correctly which caused it to be blank with strformat
2023-02-21 12:04:27 +01:00
Jake Leahy
e54d3cc418 Support tuples in nim-gdb (#21410)
* Support for printing tuple types

* Add test of printing a tuple

* Add support for printing tuples in GDB

* Forgot to [skip ci]
2023-02-21 12:02:42 +01:00
ringabout
bdc850916f improve invalid module names errors (#21412)
I have seen these questions: "Why I got an invalid module name errors?". To eliminate this kind of questions, We might improve th error messages. Though, the question might evolve into "What is a valid Nim identifier", which should be more searchable on the Internet.
2023-02-21 11:46:50 +01:00
ringabout
ffd6bc8749 csources_v2 can build the ORC-booted compiler; building now uses strict mode (#21411)
* csources_v2 can build the ORC-booted compiler; building now uses strict mode

* test booting in refc
2023-02-21 08:58:45 +01:00
ringabout
f7bd2088aa corrects the linkerexe of riscv64 in config (#21292) 2023-02-21 11:27:42 +08:00
Century Systems
c73c76fdc6 NuttX added supports getrlimit(RLIMIT_NOFILE), so remove NuttX specific codes. (#21385)
async: NuttX added supports getrlimit(RLIMIT_NOFILE), so remove NuttX-specific codes.

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>
2023-02-21 10:38:25 +08:00
Jake Leahy
c66dc913ce Support new runtime with nim-gdb (#21400)
* Add support for orc strings

* Cleaned up testing script

Enums now printing properly

Merged both old and new strings into the one printer

Moving onto sets which seem kinda difficult

* Sets working

Instead of trying to imitate how Nim represents enums, I just call the dollar proc for each enum value

While this runs into problems if the user doesn't call the dollar proc anywhere, I believe its a decent tradeoff

I've cleaned up the error message for when it cannot find dollar proc (Might add in proper message on how to fix)

* Support sequences

V2 runtime seems to have sequences that don't have a len (Guessing its some kind of short seq optimisation?) but I've rolled
the implementation into normal sequences since the implementation is practically the same

* Clean up test program so it isn't using diff

Also don't redirect the first nim compile to /dev/null so that we can check for any compilation errors

I found the diff to be annoying to read (Seeing as the test script already performs diffing)

* Tables are now supported

* Add colours to test output

It was getting difficult to tell apart test output from GDB output so I added colour to better tell them apart

* Both old and new runtime are working

Set exit code in python test script so that this could possibly be added to the CI. Only issue is that it can be flaky (GDB crashes randomly for some reason)

* Remove old code that was commented out

If I need it later I'll just use git

* Remove branch that never runs

* Remove the old test output [skip ci]
2023-02-20 21:19:46 +01:00
ringabout
e896977bd1 closes #1072; add a test case (#21396) 2023-02-19 14:49:19 +08:00
Matt Haggard
6b93db7070 Fix long link commands on macOS (v2) (#21382)
Handle long link commands on macOS with a script, since ar does not support response files
2023-02-17 11:25:15 +01:00
Jake Leahy
13711b101d std/xmltree Add the type of the node when the assertion fails (#21383)
Print the type of the node when the assertion fails

This way the user actually knows what the type was instead of just knowing it failed
2023-02-17 11:24:25 +01:00
Qinsi (James) ZHU
03dd853815 add .replace() with callback to jsre (#21371) 2023-02-16 18:12:48 +01:00
Century Systems
3b9e9fd7b2 Add support for NuttX RTOS. (#21372)
* Add support for NuttX RTOS.

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>

* lib: pure: asyncdispatch: assign to result.

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>

* lib: std: typedthreads: add support for parameters to adjust Thread Stack Size.

Like FreeRTOS/Zephyr, add support for following configurations.

  -d:nimThreadStackSize=xxxxx
  -d:nimThreadStackGuard=yyyy

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>

---------

Signed-off-by: Takeyoshi Kikuchi <kikuchi@centurysys.co.jp>
2023-02-16 13:47:52 +01:00
ringabout
93e4f278a1 add deprecated warnings for {.deadcodeelim: on.} (#21277) 2023-02-16 13:34:32 +08:00
ringabout
fc7385bfda fixes #21360; discarding empty seqs/arrays now raises errors (#21374)
* discarding empty seqs now raises errors

* the same goes for sets
2023-02-16 10:23:35 +08:00
c-blake
c91ef1a09f Fix closeHandle bug, add setFileSize, make resize work on Windows (#21375)
* Add general purpose `setFileSize` (unexported for now).  Use to simplify
`memfiles.open` as well as make robust (via hard allocation, not merely
`ftruncate` address space allocation) on systems with `posix_fallocate`.

As part of this, fix a bad `closeHandle` return check bug on Windows and
add `MemFile.resize` for Windows now that setFileSize makes that easier.

* Adapt existing test to exercise newly portable `MemFile.resize`.

* Since Apple has never provided `posix_fallocate`, provide a fallback.
This is presently written in terms of `ftruncate`, but it can be
improved to use `F_PREALLOCATE` instead, as mentioned in a comment.
2023-02-15 17:41:28 +01:00
ringabout
e24d0e5faf remove legacy code; the first iteration now can build Nim with cpp backend (#21373) 2023-02-15 13:03:11 +01:00
ringabout
56a4d246a4 Refines raises list in osproc (#21323)
* Remove Exception from raises in closeImpl

* Update osproc.nim

* refine errors

* add ValueError

* cast raises

* refactor raises lists

* Update lib/pure/osproc.nim

* Update lib/pure/osproc.nim

---------

Co-authored-by: Antonis Geralis <43617260+planetis-m@users.noreply.github.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-02-14 13:11:14 +01:00
Jake Leahy
cac49694c0 std/asyncjs allow transforming proc types (#21356)
* Add test case

* Implement JS async transform for nnkProcTy
2023-02-14 08:14:19 +01:00
c-blake
1d06c2b6cf This adds parseutils.parseSize, an inverse to strutils.formatSize (#21349)
* This adds `parseutils.parseSize`, an inverse to `strutils.formatSize`
which has existed since 2017.

It is useful for parsing the compiler's own output logs (like SuccessX)
or many other scenarios where "human readable" units have been chosen.
The doc comment and tests explain accepted syntax in detail.

Big units lead to small numbers, often with a fractional part, but we
parse into an `int64` since that is what `formatSize` stringifies and
this is an inverse over partial function slots.  Although metric
prefixes z & y for zettabyte & yottabyte are accepted, these will
saturate the result at `int64.high` unless the qualified number is a
small fraction.  This should not be much of a problem until such sizes
are common (at which point another overload with the parse result
either `float64` or `int128` could be added).

Tests avoids `test()` because of a weakly related static: test() failure
as mentioned in https://github.com/nim-lang/Nim/pull/21325. This is a
more elemental VM failure.  As such, it needs its own failure exhibition
issue that is a smaller test case.  (I am working on that, but unless
there is a burning need to `parseSize` at compile-time before run-time
it need not hold up this PR.)

* This worked with `int` but fails with `int64`.  Try for green tests.

* Lift 2-result matching into a `checkParseSize` template and format as a
table of input & 2 expected outputs which seems nicer and to address
https://github.com/nim-lang/Nim/pull/21349#pullrequestreview-1294407679

* Fix (probably) the i386 trouble by using `int64` consistently.

* Improve documentation by mentioning saturation.

* Improve documentation with `runnableExamples` and a little more detail in
the main doc comment based on excellent code review by @juancarlospaco:
https://github.com/nim-lang/Nim/pull/21349#pullrequestreview-1294564155

* Address some more @juancarlospaco code review concerns.

* Remove a stray space.

* Mention milli-bytes in docs to maybe help clarify why wild conventions
are so prone to going case-insensitive-metric.

* Add some parens.
2023-02-14 08:00:30 +01:00
ringabout
406d302131 allow omitting stmts using finally as post expr blocks; make it consistent with else, except etc. (#21361)
allow omitting stmts using `finally` as post expr blocks
2023-02-14 07:29:30 +01:00
ringabout
684c3b3aeb fixes comments about type bound operations (#21365) 2023-02-14 07:00:29 +01:00
Gabriel Huber
6c15958a83 Change the default stdlib location for Linux packaging (#21328)
* Correctly evaluate the Nim prefix on Posix

* Document new packaging layout
2023-02-12 16:41:27 +01:00
Juan M Gómez
642136ec4f Adds an extra optional argument to vcc: vctoolset Fixes #21335 (#21336) 2023-02-09 16:19:05 -05:00
ringabout
51f410e1d5 megatest now checks refc too (#21341)
* megatest now checks refc too

* fixes refc
2023-02-09 16:14:39 -05:00
ringabout
be4912681f add nimib to important packages (#20697)
r

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2023-02-09 20:00:56 +08:00
Andreas Rumpf
9fb4c2b3c7 fixes #21333; bad codegen for the at operator; [backport:1.6] (#21344) 2023-02-08 20:55:01 +01:00
ringabout
cbb6001d1e fixes backticks in the documentation (#21340) 2023-02-08 18:27:44 +08:00
Ikko Eltociear Ashimine
9f651f05d5 nimgrep: fix typo (#21337)
occurences -> occurrences
2023-02-07 16:15:44 +08:00
ringabout
8e53fba083 replaces pairs with keys and items; saves 8 bytes (#21319)
replace `pairs` with `keys` and `items`
2023-02-02 13:11:20 -05:00
ringabout
17115cbc73 fixes SSL version check logic [backport] (#21324)
* fixed version check logic [backport]

* add ciphersuites

* debug nimble

* fixes returns omission

* finally

* remove debug message

* add ciphersuites

---------

Co-authored-by: Araq <rumpf_a@web.de>
2023-02-02 16:44:14 +01:00
Ivan Yonchovski
43b1b9d077 Fix the nimble build on Windows (#21314)
Fix the build on Windows

- `nimble install` fails on Windows, the `./` is not needed.
2023-02-01 10:38:22 +01:00
Jake Leahy
900fe8f501 Add contains to std/macrocache (#21304)
* Add test cases

* Implement contains for CacheSeq

* Implement contains for CacheTable

* Fix implementation of hasKey

* Remove contains for CacheSeq

Fix runnable examples

I was accidently using --doccmd:skip so I didn't spot the failure locally

* Implement hasKey as a VM callback instead of magic

* Implement suggestions from PR

Co-Authored-By: ringabout <ringabout@users.noreply.github.com>

* Update lib/core/macrocache.nim

---------

Co-authored-by: ringabout <ringabout@users.noreply.github.com>
Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-02-01 10:00:10 +01:00
ringabout
ff8ab06720 fixes #19396; Nimdoc hide nonexported fields (#21305)
* suppresses non-exported fields of types and adds command-line option to re-enable this if desired

* corrected the doctest that produced a CI error

* an embarrassingly bad error in reasoning

* modified a nimdoc test to reflect updated behavior

* needed another change to bring utils.html doctest in sync with update

* add info

* fix nimdoc

* lint

* render postfix

* fixes a problem

* fixes nimdoc

* fix nimdoc

---------

Co-authored-by: johnperry-math <john.perry@usm.edu>
Co-authored-by: johnperry-math <devotus@yahoo.com>
2023-02-01 08:13:40 +01:00
ringabout
cbf3ed9d92 fixes #21317; 1.6.4 regression; etyBaseIndex should return fat pointers [backport 1.6] (#21320)
fixes #21317; regression; etyBaseIndex should return fat pointers
2023-02-01 07:58:12 +01:00
ringabout
b5f64f55d0 fixes #16790; fixes #19075; put big arrays on the constant seqs; don't inline them in the VM; big performance boost (#21318)
* don't inline arrays in VM

* add a test for #19075
2023-01-31 19:22:10 +01:00
ringabout
ebaa07b955 remove md5_old (#21312) 2023-01-31 16:11:44 +01:00
ringabout
4459c272ec remove enumUtilsExist defines (#21309) 2023-01-29 15:11:24 +01:00
ringabout
1431f90d8c Revert "Fix #13093 C++ Atomics: operator= is implicitly deleted because the default definition would be ill-formed " (#21307)
Revert "Fix #13093 C++ Atomics: operator= is implicitly deleted because the default definition would be ill-formed  (#21169)"

This reverts commit a7bae919ad.
2023-01-27 21:41:59 +01:00
Bung
a7bae919ad Fix #13093 C++ Atomics: operator= is implicitly deleted because the default definition would be ill-formed (#21169)
* add test

* fix #17982 Invalid C++ code generation when returning discardable var T

* fix #13093

* cpp atomic good example

* clearify the condition
2023-01-27 09:50:44 +01:00
Ivan Yonchovski
7031ea65cd Implemented basic macro expand functionality (#20579)
* Implemented level based macro expand functionality

- it can handle single macro call or expand whole function/proc/etc and it

- In addition, I have altered the parser to provide the endInfo for the node.
The usefulness of the `endInfo` is not limited to the `expandMacro`
functionality but also it is useful for `ideOutline` functionality and I have
altered the ideOutline functionality to use `endInfo`. Note `endInfo` most of
the time is lost during the AST transformation thus in `nimsuggest.nim` I am
using freshly parsed tree to get the location information.

* Make sure we stop expanding correctly

* Test CI

* Fix tv3_outline.nim
2023-01-27 07:11:30 +01:00
ringabout
4647c7b596 fixes #14409; fixes #10674 VM callbacks switch to table-index seqs (#21297)
* fixes #14409; fixes#10674 VM callbacks switch to table-index seqs

* fixes package name

* reduce runtime cost
2023-01-26 23:49:04 +01:00
ringabout
fc068ee06d fixes #18134; registers formatBiggestFloat in VM (#21299)
fixes #18134; registers formatBiggestFloat in vmops

strformat supports float format in VM
2023-01-26 23:03:59 +01:00
Heechul Ryu
23bd812b0c Update nims.md to use nim e instead of nim in advanced shebang (#21301)
Update nims.md

- suggest a better shebang that works with any filename
- related to https://github.com/nim-lang/Nim/issues/17190
2023-01-26 12:43:55 +01:00
ringabout
af0f3639ec remove dead code in VM (#21296)
remove deadcode in VM
2023-01-25 14:58:52 -05:00
ringabout
c4d3d650ba fixes #21273; fixes an io.readLine off by one bug [backport 1.0] (#21276)
fixes #21273; io.readLine off by one
2023-01-25 14:56:19 -05:00
ringabout
d54a7f078d fixes #21261; always checking nimTestErrorFlag in the main module (#21288)
* fixes #21261; always checking nimTestErrorFlag in the main module

* add a test
2023-01-24 15:37:22 +01:00
ringabout
5e7f7109e1 fixes #21290; deindent if the last same level is a text node (#21293)
* fixes #21290; deindent if the last same level is a text node

* add one more test
2023-01-24 13:35:19 +01:00
ringabout
36e489e69b add md2html, md2tex to cmd helpers (#21295) 2023-01-24 13:33:13 +01:00
ghais
f5ec4fbde3 Update the reference to parseSpec (#21289)
The current reference pointed to the wrong location
2023-01-21 18:07:40 +08:00
ringabout
b82b5d44af fixes #21278; deques.shrink off by one bug (#21284)
fixes #21278; deques.shrink off ny one bug
2023-01-20 11:43:45 +01:00
ringabout
4c74b9b54c switch to official chronos URL (#21283)
ref https://github.com/status-im/nim-chronos/pull/348
2023-01-20 12:48:12 +08:00
Yuriy Glukhov
9afb466d73 Force lambda lifting for getImplTransformed. Hacky. Fixes #19818 (#21031) 2023-01-19 11:46:41 +01:00
metagn
ac982d8a96 close #21257 (#21275)
* close #21257

* fix generics
2023-01-18 21:40:00 +01:00
Ivan Yonchovski
7c6dcfd968 Implicitly set noNimblePath when nimble.lock is present (#21266)
Fixes https://github.com/nim-lang/nimble/issues/1004
2023-01-18 21:38:48 +01:00
Andreas Rumpf
00ef27f4d1 minor parseopt.nim improvements (#21256)
* minor parseopt.nim improvements

* attempt to make CI happy

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2023-01-18 21:37:26 +01:00
Phil Krylov
f04f3e8bf7 std/parsesql: Add OFFSET keyword support. (#21255)
Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2023-01-18 13:11:15 -05:00
ringabout
fc5b7a01ec fixes #21243; ships build_all.sh on Unix [backport] (#21264)
fixes #21243; ships `build_all.sh` on Unix
2023-01-18 13:10:34 -05:00
PhilippMDoerner
fd207827c5 Add docs informing about gotcha of clients (#21262)
* Add docs informing about gotcha of clients

It is a hidden problem that AsyncHttpClient-instances *can not* deal with multiple requests at once.
Similar to normal HttpClients they can only deal with sending one request at a time.
This is not told anywhere in the documentation, but critical information that should be available to the user.

* Update lib/pure/httpclient.nim

fixes typo

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2023-01-18 13:10:05 -05:00
ringabout
fc35f83eee fixes #21260; add check for illegal recursion for defaults (#21270)
* fixes #21260; add check for illegal recursion for defaults

* fixes differently
2023-01-18 11:52:18 +01:00
ringabout
c4035d7f7c fixes unittest warnings (#21271) 2023-01-18 09:03:03 +01:00
ringabout
cc08a9015e fixes #21263; consider all candidates for concept matches (#21265) 2023-01-17 23:15:23 +01:00
ringabout
30da566d9d switch to official DelaunayNim URL (#21269)
follow up https://github.com/Nycto/DelaunayNim/pull/4#event-8240077930
2023-01-17 12:09:26 +08:00
ringabout
71c60bf6f7 bump nimble (#21259) 2023-01-14 12:30:02 +01:00
Bung
5f41be3b45 fix #20253 (#21174)
* fix #20253

* change NimbleStableCommit

* Update koch.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-01-13 15:36:13 +01:00
Jake Leahy
1e52423774 Fix getting custom pragma from generic object (#20481)
* Merge devel

Add another test case

* Fix test

Use getCustomPragmaVal instead of hasCustomPragma

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2023-01-11 20:44:33 -05:00
Anna
e4e947232b testament: make valgrind optional (#21238)
Add a simple switch to enable/disable valgrind support. On by default
2023-01-11 12:23:43 -05:00
Russell Brinson
8be46f3d16 parseopt.nim documentation clarity - default values & cmdEnd in getopt (#21047)
parseopt.nim documentation clarity

Added example for default values to cmd line parameters.
Additionally, added lines in getopt documentation about case switching still requiring the `cmdEnd` kind. Hopefully this clears up any vagueness for those following along in the example but omitting the `cmdEnd` in the case because the documentation said it wasn't needed.
2023-01-11 12:20:39 -05:00
Bung
b68b28fd24 fix typeRel of typeDesc (#21227) 2023-01-09 07:34:51 +01:00
ringabout
a55604a3d8 fixes #21232; highlite.getNextToken() returns gtOperator for '/' in C (#21234) 2023-01-08 15:40:27 +01:00
ringabout
76e4f8afb1 fixes #21209; exclude threads options for JS (#21233) 2023-01-08 15:39:25 +01:00
ringabout
24d297b437 disable bump (#21241) 2023-01-08 16:37:40 +08:00
metagn
05c6db6500 underscores for routine parameters (#21192)
* underscores for routine parameters

fixes #13443, fixes #13804, refs #21121

* add changelog + more tests

* support generics and ensure inferred lambdas work
2023-01-08 06:49:49 +01:00
ringabout
b34412ff0f adds changelog for more architectures support and fixes a link (#21229) 2023-01-06 06:24:58 +01:00
Andrey Makarov
2620da9bf9 docgen: implement cross-document links (#20990)
* docgen: implement cross-document links

Fully implements https://github.com/nim-lang/RFCs/issues/125
Follow-up of: https://github.com/nim-lang/Nim/pull/18642 (for internal links)
and https://github.com/nim-lang/Nim/issues/20127.

Overview
--------

Explicit import-like directive is required, called `.. importdoc::`.
(the syntax is % RST, Markdown will use it for a while).

Then one can reference any symbols/headings/anchors, as if they
were in the local file (but they will be prefixed with a module name
or markup document in link text).
It's possible to reference anything from anywhere (any direction
in `.nim`/`.md`/`.rst` files).

See `doc/docgen.md` for full description.

Working is based on `.idx` files, hence one needs to generate
all `.idx` beforehand. A dedicated option `--index:only` is introduced
(and a separate stage for `--index:only` is added to `kochdocs.nim`).

Performance note
----------------

Full run for `./koch docs` now takes 185% of the time before this PR.
(After: 315 s, before: 170 s on my PC).
All the time seems to be spent on `--index:only` run, which takes
almost as much (85%) of normal doc run -- it seems that most time
is spent on file parsing, turning off HTML generation phase has not
helped much.
(One could avoid it by specifying list of files that can be referenced
and pre-processing only them. But it can become error-prone and I assume
that these linke will be **everywhere** in the repository anyway,
especially considering https://github.com/nim-lang/RFCs/issues/478.
So every `.nim`/`.md` file is processed for `.idx` first).

But that's all without significant part of repository converted to
cross-module auto links. To estimate impact I checked the time for
`doc`ing a few files (after all indexes have been generated), and
everywhere difference was **negligible**.
E.g. for `lib/std/private/osfiles.nim` that `importdoc`s large
`os.idx` and hence should have been a case with relatively large
performance impact, but:

* After: 0.59 s.
* Before: 0.59 s.

So Nim compiler works so slow that doc part basically does not matter :-)

Testing
-------

1) added `extlinks` test to `nimdoc/`
2) checked that `theindex.html` is still correct
2) fixed broken auto-links for modules that were derived from `os.nim`
   by adding appropriate ``importdoc``

Implementation note
-------------------

Parsing and formating of `.idx` entries is moved into a dedicated
`rstidx.nim` module from `rstgen.nim`.

`.idx` file format changed:

* fields are not escaped in most cases because we need original
  strings for referencing, not HTML ones
  (the exception is linkTitle for titles and headings).
  Escaping happens later -- on the stage of `rstgen` buildIndex, etc.
* all lines have fixed number of columns 6
* added discriminator tag as a first column,
  it always allows distinguish Nim/markup entries, titles/headings, etc.
  `rstgen` does not rely any more (in most cases) on ad-hoc logic
  to determine what type each entry is.
* there is now always a title entry added at the first line.
* add a line number as 6th column
* linkTitle (4th) column has a different format: before it was like
  `module: funcName()`, now it's `proc funcName()`.
  (This format is also propagated to `theindex.html` and search results,
  I kept it that way since I like it more though it's discussible.)
  This column is what used for Nim symbols resolution.
* also changed details on column format for headings and titles:
  "keyword" is original, "linkTitle" is HTML one

* fix paths on Windows + more clear code

* Update compiler/docgen.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

* Handle .md and .nim paths uniformly in findRefFile

* handle titles better + more comments

* don't allow markup overwrite index title for .nim files

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2023-01-04 15:19:01 -05:00
Bung
b2328b44ba make it printer friendly (#21218) 2023-01-04 15:10:44 -05:00
ringabout
81b7f9108f fixes #21207; reports redefinition error in the definition of enums (#21217)
* fixes #21207;  reports redefinition in the enums

* add a test
2023-01-03 08:15:10 +01:00
ringabout
3b965f463b bump csource_v2 to include fix for linking parameter maximum length (#21216)
> If accepted, I believe it should be used in csources_v2 and also backport 2.0

ref https://github.com/nim-lang/Nim/pull/21186
2023-01-02 22:10:26 +08:00
Andreas Rumpf
cf1b16ef8b minor code cleanups (#21215) 2023-01-02 10:39:17 +01:00
Chavdar Ivanov
e9ed090c33 Update nim.cfg (#21204)
tlsEmulation:on under NetBSD-10Beta and NetBSD-current produces an executable which crashes immediately as follows:

Core was generated by `koch'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000047b4c2 in nimZeroMem ()
(gdb) bt
#0  0x000000000047b4c2 in nimZeroMem ()
#1  0x00000000004897b2 in threadVarAlloc__system_2162 ()
#2  0x000000000048980e in initThreadVarsEmulation ()
#3  0x0000000000489848 in PreMain ()
#4  0x000000000048986a in NimMain ()
#5  0x00000000004898a9 in main ()

I can't speak about the other BSDs.
2023-01-02 09:16:18 +01:00
ringabout
5b20f0685c fixes pragmas reorder (#21205) 2023-01-01 10:25:04 +01:00
ringabout
4032eb4baa fixes #20906; update copyright year [backport 1.6] (#21210) 2023-01-01 16:51:58 +08:00
rockcavera
e5639408d5 avoiding unnecessary allocation for dollar IpAddress (#21199)
* avoiding allocating an unnecessary byte for IPv4

The inet.h file uses 16 as the string in C needs the last null byte
1b929c02af/include/linux/inet.h (L49)

However, strings in Nim do not need this. So one byte is being allocated unnecessary and will never be used.

* avoid unnecessary allocation in IPv6 dollar

It is currently allocating 48 bytes. However, the Nim implementation for IPv6 will print a maximum of 39 characters. Nim does not implement IPv6 "0000:0000:0000:0000:0000:ffff:255.255.255.255" (45 characters) nor "0000:0000:0000:0000:0000:ffff:255.255.255.255%3" (47 characters). 

The indication in inet.h for 48 is due to the maximum use of 47 characters of a C string that needs a null byte at the end. So 48.
1b929c02af/include/linux/inet.h (L50)
2022-12-30 09:20:32 +01:00
Bung
c598d0b6ec fix #15117 zero size array cause incorrect codegen for VCC compiler (#21197)
fix #15117
2022-12-30 00:50:12 +01:00
ringabout
ebd1c678be fixes #21195; std/assertions continue to use sysFatal when nimPreviewSlimSystem is not defined (#21196)
* fixes #21195; `std/assertions` continue to use `sysFatal`

* try includes

* make `std/assertions` self-contained

* fixes tests

* fixes tests
2022-12-29 14:15:08 -05:00
ringabout
705da9d452 fixes #14444; add genLineDir before assignment (#21201)
* fixes #14444; add `genLineDir` before raises

* add a test case

* fixes differently
2022-12-29 17:06:57 +01:00
ringabout
e602ebeb66 fixes #19997; ships changelogs directory for a release (#21200)
fixes #19997; ship changelogs directory for a release
2022-12-29 08:29:40 +01:00
ringabout
761c5a0830 less verbose type mismatch messages (#21191)
* less verbose type mismatch messages

* Update compiler/types.nim

* fixes i386

* fixes i386
2022-12-28 20:54:15 +01:00
ringabout
646932b3f3 fixes warnings when building csources (#21194)
* replace `symbolfiles` with `incremental`; fixes warnings when build csources

* fixes self conversion warnings
2022-12-28 20:41:27 +01:00
ringabout
4b63ac4b87 fixes #21171; dynamic acyclic refs need to use dyn decRef (#21184)
* fixes #21171; dyn destructors for acyclic inherited  refs

* add a test

* Update compiler/liftdestructors.nim
2022-12-28 16:23:37 +01:00
Bung
7a74c2dc3a fix #14667 (#21190) 2022-12-28 08:28:48 +01:00
Jake Leahy
3d5dbf8f96 Fix nimsuggest not suggesting fields in when theres static parameters (#21189)
Don't check against empty arguments

Add test case
2022-12-28 07:35:11 +01:00
rockcavera
9efa56a8bb [backport: 2.0] prevents the jsonscript command from exceeding the maximum length of a command line during linking (#21186) 2022-12-28 10:40:17 +08:00
Phil Krylov
9e35631191 std/encodings: Fix open() documentation in regard to exception raised (#21187) 2022-12-28 10:26:52 +08:00
metagn
5684093135 fix for bad error message with const in case statement (#21182)
* preliminary fix for bad error message with const

* add test case

* fix tmatrixconcept and tmatrixlib
2022-12-27 21:24:00 +01:00
Andreas Rumpf
82d80e6e2c atlas: minor doc improvements (#21183)
* closes #20808

* atlas: better docs
2022-12-27 14:30:26 +01:00
Bung
f232329bb1 add test case for #20289 (#21180) 2022-12-27 12:07:15 +01:00
rockcavera
9b4516fbcb fix in msg doAssert() to update grammar.txt (#21179) 2022-12-27 12:13:05 +08:00
ringabout
f7c203fb6c remove legacy code (#21134)
* remove legacy code

* fixes
2022-12-26 13:20:05 +01:00
ringabout
b08c50bb55 sync some changes from release notes (#21173) 2022-12-26 06:52:40 +01:00
ringabout
9323cb7b2a enforce void for nkWhileStmt [backport: 2.0] (#21170)
enforce void for nkWhileStmt
2022-12-24 10:37:32 +01:00
Jake Leahy
86a6c90c9e Make search results be relative to documentation root (#21145)
Use Nim instead of JS for searching
2022-12-23 13:20:51 -05:00
ringabout
ac5a36c0a4 re and nre now link to regex and tinyre (#21161) 2022-12-23 10:50:07 -05:00
ringabout
0ffc322cf6 add the cpp target (#21164)
The issue is related to cpp codegen, the previous test doesn't test cpp backend, which will join into the megatest.
2022-12-23 22:31:53 +08:00
Bung
0b319fee3d fix #20997 calling system.card[T](x: set[T]) with T of int8 or uint8 … (#21010)
* fix #20997 calling system.card[T](x: set[T]) with T of int8 or uint8 uses mismatched C array sizes
* fullfil set variant
2022-12-23 12:20:25 +01:00
Bung
ca9c74391a fix #11634 (#21146) 2022-12-23 11:32:03 +01:00
Bung
13251c2ac9 fix #12946 Bad C++ codegen on distinct generics C++ types (#21157) 2022-12-23 09:47:01 +01:00
Jaremy Creechley
3bba2b34fd fix socket send for string types (#21155)
* fix socket send for string types

* include windows version

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2022-12-22 21:43:27 +01:00
Jake Leahy
18c115c8d0 Don't repeat suggestions for same symbol (#21140)
* Track seen module graphs so symbols from the same module aren't repeated
Add test case

* Track symbols instead of modules

* Don't show duplicate symbols in spell checker

Removes the declared location from the message. Since we don't show duplicates anymore it would be a bit misleading if we only show the location for the first declaration of the symbol
2022-12-22 14:44:10 +01:00
metagn
37daed3897 remove misleading slimsystem deprecated warnings (#21156)
refs #20967
2022-12-22 09:54:41 +01:00
Peder Bergebakken Sundt
314a24472e add link to setutils in system module docs (#21130) 2022-12-22 09:54:17 +01:00
Michael Voronin
7931bdac95 Feature/xmltree additions (#20988)
* [change] add/insert/delete family of xmltree expanded with several variations. Added replace methods family

* [change] Lifted child limitations on insert methods (consulted with @araq)

* [tests] add/insert/replace/delete of xmltree XmlNodes tests added
2022-12-22 08:32:12 +01:00
ringabout
93b59da490 fixes #20244; fixes castSizes warnings (#21102)
* fixes #20244; fixes castSizes warnings

* fixes js

* fixes js

* fixes js

* fixes

* typo

* extend using uint64

* Update lib/std/syncio.nim
2022-12-22 08:27:11 +01:00
Jake Leahy
70fe360456 Use ErrorColor when a warning that is turned into an error is raised (#21131)
Use ErrorColor when a warning that is turned into an error is raised
2022-12-22 08:25:24 +01:00
Bung
c5a72ebddd fix #16541 (#21148) 2022-12-22 06:16:25 +01:00
Peter Munch-Ellingsen
613829f7a4 Implement setLineInfo (#21153)
* Implement setLineInfo

* Add tests
2022-12-22 04:34:36 +01:00
ringabout
d0721eadf8 fixes #21144; try expression will not match the less indentation except (#21152)
fixes #21144; try expression will not match the less indent except
2022-12-21 21:46:14 +01:00
ringabout
81d8ea95af bump csource_v2 to include fixes for macos m1 (#21147) 2022-12-21 17:18:47 +08:00
Luca Guzzon
8a77798dac ucpu fix-up for arm64 value on macos m1 (#21142) 2022-12-20 20:29:42 +01:00
ringabout
0aec095b26 fixes #19292; fixes #21122; fixes putEnv and setEnv with vcc (#21143)
* fixes #19292; fixes 21122; fixes putEnv and setEnv with vcc

* add a test
2022-12-20 20:26:32 +01:00
Bung
40b5c4c4c3 fix #20248;fix #6215;turns into simple CT error (#21141) 2022-12-20 20:23:48 +01:00
ringabout
886572a516 disable "Warning: gc is deprecated" in compiler (#21137)
* disable "Warning: gc is deprecated" in compiler

* Apply @tersec 's suggestion
2022-12-20 15:04:13 +08:00
Bung
e278a781fc fix #21109 (#21127) 2022-12-19 12:35:15 +01:00
ringabout
70c575095e add changelog for the new strict function checking algorithm (#21129)
add changelog for the new strict function checking
2022-12-19 17:56:49 +08:00
ringabout
53eed2be45 close #11705; add a testcase (#21128) 2022-12-18 22:31:13 +08:00
ringabout
100b304ac2 fixes misplaced changelog entries; pre-existing issue (#21125)
* move misplaced changelog entries to the right place

* fixes misplaced changelog
2022-12-17 21:42:29 +08:00
ringabout
b8d200683a remove unused imports (#21126) 2022-12-17 20:44:30 +08:00
ringabout
ae4645e8df add 2.0 changelog (#21107)
[backport: 2.0] add v2.0 changelog
2022-12-17 09:28:59 +01:00
ringabout
d83f66a24d fixes #21116; always mangles the param (#21121)
* fixes #21116; always mangles the param

* idOrSig

* fixes tests

* Apply suggestions from code review
2022-12-17 09:10:56 +01:00
ringabout
7fa983f5e6 Nim now ships nimble with 0.14.1 version (#21120)
* Nimble now uses latest patch

* Update koch.nim
2022-12-17 00:21:07 +08:00
ringabout
296e7f598e Bump the devel version to 1.9.1 (#21117) 2022-12-16 19:49:26 +08:00
ringabout
84200f28a1 bump csource_v2 hash (#21118) 2022-12-16 16:42:31 +08:00
Bung
a9bd78d579 fix #12122 (#21096) 2022-12-16 08:01:15 +01:00
ringabout
8a3b76b287 csource building prefers bin/nim (#21115) 2022-12-16 07:59:18 +01:00
ringabout
644318ad9c the devel branch now uses csources_v2 (#21108)
* the devel branch now uses csources_v2

* fixes hash

* bump csources_v2
2022-12-16 07:58:40 +01:00
ringabout
78b68421da fixes chronicles (#21114) 2022-12-16 11:36:52 +08:00
Jake Leahy
d00477dffb Check file exists in {.compile.} pragma (#21105)
* Add test

* Check file exists before adding it into compilation

* Make error message look like other error messages

i.e. following the format `error msg: file`
2022-12-15 19:22:45 +01:00
Bung
8054be6e52 fix #20588 (#21104) 2022-12-15 16:12:17 +01:00
Jake Leahy
d88f46df38 Make async stacktraces less verbose (#21091)
* Name iterators something human readable

Remove intermediate async procs from stacktraces

Clean async traceback message from reraises message

* Remove unused import/variable

* Fix failing tests

Don't add {.stackTrace: off.} to anonymous procs (They already don't appear in stacktrace)

* Fix failing tests in pragma category

Now check that the nim is a routine type first so we don't run into any assertion defects

* Hide stack trace pragma in docs and update doc tests

User doesn't need to know if something won't appear so this more becomes verbose noise

If this is a bad idea we can always add a `when defined(nimdoc)` switch so we don't add {.stackTrace: off.} to the Future[T] returning proc for docs
2022-12-15 16:05:34 +01:00
ringabout
91ce8c385d fix #19580; add warning for bare except: clause (#21099)
* fix #19580; add warning for bare except: clause

* fixes some easy ones

* Update doc/manual.md

* fixes docs

* Update changelog.md

* addition

* Apply suggestions from code review

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>

* Update doc/tut2.md

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>
2022-12-15 06:45:36 +01:00
metagn
9a50033d5b generic define pragma + string alias (#20979)
* generic `define` pragma + string alias

* clean

* add tests and document

* remove char/float, minimize changelog
2022-12-13 21:20:55 +01:00
Aditya Siram
2564b5c938 Fix #20416. Enable the recursion limit for ref/ptr types. (#21092) 2022-12-13 22:57:07 +08:00
Xavier Noria
e4aadcf1c1 Document that system:pop() may raise IndexDefect (#21070)
* Document system:pop() may raise IndexDefect

* Add backticks to KeyError
2022-12-13 08:47:01 +01:00
Jake Leahy
7ae7832f76 JS backend properly extends string with setLen (#21087)
* Add test case

* Extend string with '0' when setting length to be longer
2022-12-13 08:43:37 +01:00
Jake Leahy
1fefb8e92a Refactor JS sourcemap generator (#21053)
* Parse the new line format

* Fix pattern

Didn't have space after the path

* Remove duplicate sources

Sources would sometimes double up with a new line at the end

* Remove unused variable

* Refactor sourcemap.nim

Removes the multiple translations needed, now goes from single high level type to the final SourceMap

Adds documentation for procs

* Line numbers line up properly now

Files aren't linking correctly though

* Files now link up correctly

Lines are sometimes off but overall seems pretty good

Just need to implement parser

* Add column info to output

Add sourceMappingURL to rope directly to prevent copy

* Properly handle columns

* Remove debug lines

* Add testcase

* Finish testcase

* Use the outdir folder instead of the folder the test is in to find the sourcemap

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
2022-12-13 12:21:51 +08:00
ringabout
d84f64d2e7 add CI for version-2-0 branch (#21084) 2022-12-13 09:52:35 +08:00
Jake Leahy
b0a850adbf Nimsuggest now defines the backends symbol (#21083)
* Add testcase

* Define the backend symbol

* Remove unneeded whitespace
2022-12-12 22:19:02 +01:00
ringabout
4388636010 fixes #21043; fixes a named exception in the infixAs expression which generate an implicit uninitialized let statement (#21081)
* fixes #21043; fixes a named exception in the infixAs expression which generate an implicit uninitialized let statement

* Update compiler/sempass2.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2022-12-12 23:14:44 +08:00
ringabout
584cfa6af8 remove implicitDeref feature enum (#21075)
remove implicitDeref feature
2022-12-12 15:59:09 +01:00
ringabout
fd7da7da62 add a changelog for nimble (#21078) 2022-12-12 14:57:27 +01:00
ringabout
19923aa8b7 work around chronos (#21079)
* work around chronos

chronos has tests against the devel branch, it will be eventually fine.

* Apply suggestions from code review

* Update testament/important_packages.nim
2022-12-12 21:14:24 +08:00
Andreas Rumpf
28bed059aa closes #20808 (#21077) 2022-12-12 11:46:51 +01:00
Jake Leahy
cbeefc877c Docs expand using parameters (#21076)
* Trying to fix by changing renderer

* add renderExpandUsing flag

This flag makes the renderer expand parameters that use using statement to have their full type

* Update docs

* Make comment better explain why checking for nkSym

* Fix nil access when macro/template has parameter with no type

* Fix nil access when node is not semmed yet
2022-12-12 07:44:17 +01:00
ringabout
b981f3eeb7 ship a modern nimble with lock files support (#21061)
* change `include genode/env` to an import 

ref 0b262e9496 (diff-8718bd20d8f61d6638d3d64b19efc31bcd40a6d5be8215b2a1f0b75ed93e8d56)

* fixes comments

* ship a modern nimble with lock files support

* not sure whether the latest nimble has a regression

now I'm trying  0.14.0

* change `pkgs` to `pkgs2` (#21073)

* overwrite problematic packages

* Apply suggestions from code review

* Apply suggestions from code review

* Apply suggestions from code review
2022-12-12 07:25:39 +01:00
Bung
5917c2d5b7 fix #15836 proc arg return type auto unexpectly match proc with concr… (#21065)
* fix #15836 proc arg return type auto unexpectly match proc with concrete type

* fix #16244

* add test case for #12869
2022-12-12 06:26:18 +01:00
Andreas Rumpf
3812d91390 alternative, much simpler algorithm for strict func checking (#21066)
* alternative, much simpler algorithm for strict func checking

* forgot to git add new compiler module

* new spec is incredibly simple to describe

* fixes bigints regression

* typos

* closes #16305; closes #17387; closes #20863
2022-12-11 16:58:50 +01:00
Jake Leahy
c7493bbdd0 multisync now allows tuples in return type (#21074)
* Add test case

* Use .toStrLit() on param node first

This means that more complex types are fully rendered
2022-12-11 14:44:41 +01:00
Bung
1585bfec3b fix #16758 Nim crashes in fixAbstractType (#20855)
* fix #16758 Nim crashes in fixAbstractType

* Update compiler/semexprs.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2022-12-11 06:58:29 +01:00
ringabout
07be1791ba fix #21045; getTime with vmopsDanger is broken; alternative to #21054 (#21056)
* fix #21045 getTime with vmopsDanger is broken; alternative to #21054

* typo
2022-12-10 18:57:19 +01:00
ringabout
7a18c1ef44 clean up the documentation of threads (#21067)
* clean up the documentation of threads

* cleanup
2022-12-10 23:23:31 +08:00
Andreas Rumpf
b59c657be3 fixes #21062 (#21068) 2022-12-10 16:21:43 +01:00
Andreas Rumpf
2ebd71bfd4 tiny refactoring related to sink parameter inference logic (#21064)
* tiny refactoring related to sink parameter inference logic

* Update compiler/sempass2.nim
2022-12-10 15:42:22 +01:00
Jake Leahy
f330b33e2b Use a unique name for template in async macro return (#21058)
Use unique template name
2022-12-10 09:15:45 +08:00
ringabout
db56fc3bcb Revert "fix #15836 proc arg return type auto unexpectly match proc with concr…" (#21057)
Revert "fix #15836 proc arg return type auto unexpectly match proc with concr… (#21044)"

This reverts commit 0cd9bdcf9f.
2022-12-09 21:38:55 +01:00
Jake Leahy
da3274d1b3 Implicit return working for async proc (#20933)
* Implicit return working for asyncdispatch proc

Closes #11558

* Test case

* Test that return value is actually used

* Update tests/async/t11558.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2022-12-09 18:10:33 +01:00
Bung
0cd9bdcf9f fix #15836 proc arg return type auto unexpectly match proc with concr… (#21044)
fix #15836 proc arg return type auto unexpectly match proc with concrete type
2022-12-09 18:01:13 +01:00
ringabout
ef190f349d remove duplicate assignment (#21050)
`newNodeIT` has already assigned `n.typ` to x.
2022-12-09 08:50:35 +08:00
Juan Carlos
f8e64d879c Remove deprecated rightSize (#21011)
* Remove deprecated rightSize nop

* Remove deprecated rightSize nop
2022-12-08 15:26:58 +01:00
Vindaar
0a1d4ba842 fix issue #20922 by handling missing expr in exprList for tkOf (#20930)
* fix issue #20922 by handling missing expr in `exprList` for `tkOf`

* fix line numbers in test case

* rewrite exprList requiring expr, add optionalExprList for except

As suggested by @metagn.

* update test case to reflect new code

* update grammar.txt

* update line numbers in test case taking into account nimout

Given the number of errors that are produced it seems easier to do it
this way instead of using `tt.Error`.
2022-12-08 10:59:13 +01:00
Xavier Noria
e669835665 Mention toSet in the docs of the set type (#21037) 2022-12-08 10:58:00 +01:00
Emery Hemingway
696def2bf7 macros.customPragmaNode: walk brackets on brackets (#21040) 2022-12-08 10:57:26 +01:00
ringabout
c5eb3fd4f0 fixes #9839; fixes noReturn pragma doesn't work for non-simple templates (#21048) 2022-12-08 10:37:02 +01:00
ringabout
4480fd3e93 fixes #16656; add nre to lib.md (#21042) 2022-12-08 08:51:31 +01:00
ringabout
4da3ead294 fixes strictnotnil documentation; comment unfinished sections (#21041)
fixes documentation; comment unfinished sections
2022-12-08 10:06:48 +08:00
ringabout
53fbb497e9 add a changelog for std/cmdline (#21039)
for a changelog for `std/cmdline`
2022-12-08 10:06:25 +08:00
ringabout
d6b485493d switch to the official URL of nimquery (#21038)
ref 3f728fb480
2022-12-07 11:33:31 +08:00
ringabout
9ba07edb2e build the documentation of official packages (#20986)
* remove db stuffs

* remove punycode

* remove

* fixes script

* add cloner

* patches

* disable

* patch

* fixes external packages

* disable two packages

* preview documentation build

* try again

* fixes URL

* fixes a bug

* simplify

* fixes documentaion

* fixes

* Apply suggestions from code review
2022-12-06 22:37:16 +08:00
metagn
4ca2dcb404 Named arguments in commands + many grammar fixes (#20994)
* Breaking parser changes, implement https://github.com/nim-lang/RFCs/issues/442

Types are separated from expressions and better reflected in the grammar.

* add test

* more accurate grammar

* fix keyword typedescs

* accept expressions in proc argument lists

* CI "fixes"

* fixes

* allow full ref expressions again, adapt old tests

* cleanup, fix some tests

* improve grammar, try and revert semtypes change

* restrict sigil binding to identOrLiteral

* fix, should have caught this immediately

* add changelog entry, fix double not nil bug

* correct grammar

* change section

* fix

* real fix hopefully

* fix test

* support LL(1) for tuples

* make grammar.txt too
2022-12-06 13:11:56 +01:00
ringabout
1564ae650f fixes #21027; cast expressions need a type (#21029)
* fixes #21027; cast expressions need a type

* Apply suggestions from code review

Thanks to @beef331
2022-12-06 13:09:50 +01:00
ringabout
b2c7019006 definite assignment analysis for let (#21024)
* draft for let daa

* patch

* fixes bugs

* errors for global let variable reassignments

* checkpoint

* out param accepts let

* add more tests

* add documentation

* merge tests
2022-12-06 10:19:12 +01:00
metagn
6d8cf25bd7 deprecate do: meaning do (): + misc cleanup (#20927)
* test disable do: block lambda lifting

* fix last test [skip ci]

* deprecate `do:` meaning `do ():` + misc cleanup

closes https://github.com/nim-lang/RFCs/issues/486

* oops

* fix

* no idea what could be causing nimsuggest failure other than this

* ensure ci works
2022-12-06 09:44:26 +01:00
metagn
739e1badb6 stdlib organization & documentation improvements (#20971)
* stdlib organization & documentation improvements

* fix CI

* Update doc/lib.md

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>

* fix ci, remove jshttpcore, export in jsfetch instead

* fix alphabetical order violations

* add cmdline, db_odbc

Co-authored-by: Juan Carlos <juancarlospaco@gmail.com>
2022-12-06 09:37:03 +01:00
Bung
5d469686b0 fix #20829 Regression in int64 type matching since (#21019)
fix #20829 Regression in int64 type matching
2022-12-06 07:44:54 +01:00
ringabout
feb0481ba3 Revert "fixes #20883; Unspecified generic on default value segfaults the compiler" (#21028)
Revert "fixes #20883; Unspecified generic on default value segfaults the compiler (#20917)"

This reverts commit 10b6e4f5b4.
2022-12-06 12:50:16 +08:00
metagn
e98efdcc5e fix #16639 (#21017) 2022-12-05 22:52:49 +01:00
Yuriy Glukhov
c47d5196be Dont produce initing moves for sfNoInit variables in closure env (#21026) 2022-12-05 22:49:31 +01:00
ringabout
b83bd282dc fixes #20954; bounchecks for len(toOpenArray()) [backport] (#20956)
* bounchecks for len(toOpenArray())

* add a testcase
2022-12-05 22:27:18 +01:00
ringabout
a8090f7d65 fixes isLocalVarSym; an implicit global is a global nonetheless (#21025)
fixes isLocalVarSym; an implicit global is a global nonetheless
2022-12-05 22:24:36 +01:00
Dmitry Arkhipenko
794bcc8029 Add: missing nintendo-switch define (#21009) 2022-12-05 07:24:24 +01:00
ringabout
6f96c4bc96 ref #20846; give a deprecation message for overriding = hook (#21020)
give a deprecation message for overriding `=` hook
2022-12-05 07:13:51 +01:00
Juan Carlos
1b5e03f975 Remove deprecated posix.CLONE_STOPPED (#21012)
* Remove deprecated CLONE_STOPPED

* Remove deprecated CLONE_STOPPED
2022-12-05 06:53:40 +01:00
ringabout
78b387d948 fixes deprecation message by update action versions (#21021) 2022-12-05 12:37:23 +08:00
metagn
5536f74992 fix #20996 (#21016)
* fix #20996

* hopefully fix
2022-12-04 20:37:23 +01:00
ringabout
55373e65b4 unpublic arrayWith and rename it to nimArrayWith (#21006)
* unpublic arrayWith

* unindent
2022-12-04 15:39:14 +08:00
Michal Maršálek
83493e4294 Update prelude example (#21005)
comment to match what's actually being imported.
2022-12-03 21:25:49 +08:00
ringabout
ece41d2605 minor cleanup; correct the module name (#21001)
* minor cleanup 

follow up https://github.com/nim-lang/Nim/pull/20946

* Update lib/std/cmdline.nim

* Update lib/std/cmdline.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2022-12-02 15:10:08 -05:00
metagn
79ec6d677c Add back error message to tprevent_forloopvar_mutations (#20992) 2022-12-02 16:19:26 +08:00
ringabout
10b6e4f5b4 fixes #20883; Unspecified generic on default value segfaults the compiler (#20917)
test CI
2022-12-01 22:04:11 +01:00
ringabout
8266750497 [unittest] remove unnecessay export for testing (#20868) 2022-12-01 14:31:48 -05:00
Ikko Ashimine
a104aa4714 IC: fix typo in rodfiles.nim (#20989)
preceeded -> preceded
2022-12-01 14:26:59 -05:00
Bung
658b28dc57 tyInt tyUint fit target int bit width (#20829) 2022-12-01 13:34:00 +01:00
ringabout
a70d3abd37 replace data init function with consts for typeinfov2 (#20977)
* replace data initial function with consts for typeinfov2

* fixes

* fixes

* workaround C++

* C++ keeps the previous implementaion

* fixes
2022-12-01 13:29:58 +01:00
1265 changed files with 33598 additions and 21237 deletions

69
.github/stale.yml vendored
View File

@@ -1,69 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 365
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- ARC
- bounty
- Codegen
- Crash
- Generics
- High Priority
- Macros
- Next release
- Showstopper
- Static[T]
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity.
If you think it is still a valid PR, please rebase it on the latest devel;
otherwise it will be closed. Thank you for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 20
# Limit to only `issues` or `pulls`
only: pulls
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

23
.github/workflows/bisects.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
# See https://github.com/juancarlospaco/nimrun-action/issues/3#issuecomment-1607344901
name: issue comments bisects
on:
issue_comment:
types: created
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# nimrun-action requires Nim installed.
- uses: jiro4989/setup-nim-action@v1
with:
nim-version: 'devel'
- name: Install Dependencies
run: sudo apt-get install --no-install-recommends -yq valgrind
- uses: juancarlospaco/nimrun-action@nim
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

115
.github/workflows/ci_bench.yml vendored Normal file
View File

@@ -0,0 +1,115 @@
name: Benchmarks CI
on:
pull_request:
push:
branches:
- 'devel'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04]
cpu: [amd64]
name: '${{ matrix.os }}'
runs-on: ${{ matrix.os }}
timeout-minutes: 60 # refs bug #18178
steps:
- name: 'Checkout'
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'
run: |
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends -yq \
libcurl4-openssl-dev libgc-dev libsdl1.2-dev libsfml-dev \
valgrind libc6-dbg libblas-dev xorg-dev
- name: 'Add build binaries to PATH'
shell: bash
run: echo "${{ github.workspace }}/bin" >> "${GITHUB_PATH}"
- name: 'Build csourcesAny'
shell: bash
run: . ci/funs.sh && nimBuildCsourcesIfNeeded CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build Nim'
shell: bash
run: ./koch boot -d:release -d:nimStrictMode --lib:lib
- name: 'Build Nimble'
shell: bash
run: ./koch nimble
- name: 'Action'
shell: bash
run: nim c -r -d:release ci/action.nim
- name: 'Checkout minimize'
uses: actions/checkout@v3
with:
repository: 'nim-lang/ci_bench'
path: minimize
- name: 'Run minimize benchmarks'
shell: bash
run: ./minimize/minimize ci-bench
- name: 'Restore minimize cached database'
uses: actions/cache/restore@v3
with:
path: minimize.csv
key: minimize-db-key
- name: 'Update minimize db'
shell: bash
run: ./minimize/minimize update-db
- name: 'Save minimize cached database'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
uses: actions/cache/save@v3
with:
path: minimize.csv
key: minimize-db-key
- name: 'Generate minimize report'
shell: bash
run: ./minimize/minimize generate-report
- name: 'Archive minimize report'
uses: actions/upload-artifact@v3
with:
name: minimize-report
path: |
minimize/minimize.html
minimize/minimize.csv
# Requires additional permissions, see:
# https://github.com/nim-lang/Nim/actions/runs/4778177321/jobs/8494423792?pr=21566
# - name: 'Publish HTML report'
# uses: rossjrw/pr-preview-action@v1
# with:
# source-dir: minimize
# umbrella-dir: minimize
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Extract md summary
run: |
cat minimize/summary.md >> $GITHUB_STEP_SUMMARY

View File

@@ -47,7 +47,7 @@ jobs:
- target: windows
os: windows-2019
- target: osx
os: macos-11
os: macos-12
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- 'devel'
- 'version-2-0'
- 'version-1-6'
- 'version-1-2'
@@ -16,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-11]
os: [ubuntu-20.04, macos-12]
cpu: [amd64]
batch: ["allowed_failures", "0_3", "1_3", "2_3"] # list of `index_num`
name: '${{ matrix.os }} (batch: ${{ matrix.batch }})'
@@ -27,14 +28,14 @@ jobs:
NIM_TESTAMENT_BATCH: ${{ matrix.batch }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v2
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'

View File

@@ -17,14 +17,14 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: 'Install node.js 16.x'
uses: actions/setup-node@v2
- name: 'Install node.js 20.x'
uses: actions/setup-node@v4
with:
node-version: '16.x'
node-version: '20.x'
- name: 'Install dependencies (Linux amd64)'
if: runner.os == 'Linux' && matrix.cpu == 'amd64'

25
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
# https://github.com/actions/stale#usage
name: Stale pull requests
on:
schedule:
- cron: '0 0 * * *' # Midnight.
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
days-before-pr-stale: 365
days-before-pr-close: 30
days-before-issue-stale: -1
days-before-issue-close: -1
exempt-pr-labels: "ARC,bounty,Codegen,Crash,Generics,High Priority,Macros,Next release,Showstopper,Static[T]"
exempt-issue-labels: "Showstopper,Severe,bounty,Compiler Crash,Medium Priority"
stale-pr-message: >
This pull request is stale because it has been open for 1 year with no activity.
Contribute more commits on the pull request and rebase it on the latest devel,
or it will be closed in 30 days. Thank you for your contributions.
close-pr-message: >
This pull request has been marked as stale and closed due to inactivity after 395 days.

3
.gitignore vendored
View File

@@ -67,6 +67,7 @@ testament.db
/csources
/csources_v1
/csources_v2
/dist/
# /lib/fusion # fusion is now unbundled; `git status` should reveal if it's there so users can act on it
@@ -109,3 +110,5 @@ htmldocs
nimdoc.out.css
# except here:
!/nimdoc/testproject/expected/*
pkgs/
/compiler/compiler/

View File

@@ -1,62 +0,0 @@
# xxx unused, out of date
image: ubuntu:18.04
stages:
- pre-build
- build
- deploy
- test
.linux_set_path: &linux_set_path_def
before_script:
- export PATH=$(pwd)/bin${PATH:+:$PATH}
tags:
- linux
.windows_set_path: &win_set_path_def
before_script:
- set PATH=%CD%\bin;%PATH%
tags:
- windows
build-windows:
stage: build
script:
- ci\build.bat
artifacts:
paths:
- bin\nim.exe
- bin\nimd.exe
- compiler\nim.exe
- koch.exe
expire_in: 1 week
tags:
- windows
deploy-windows:
stage: deploy
script:
- koch.exe winrelease
artifacts:
paths:
- build/*.exe
- build/*.zip
expire_in: 1 week
tags:
- windows
- fast
test-windows:
stage: test
<<: *win_set_path_def
script:
- call ci\deps.bat
- nim c testament\tester
- testament\tester.exe all
tags:
- windows
- fast

View File

@@ -23,16 +23,16 @@ jobs:
vmImage: 'ubuntu-20.04'
CPU: amd64
# regularly breaks, refs bug #17325
Linux_i386:
# on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
vmImage: 'ubuntu-18.04'
CPU: i386
# Linux_i386:
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
# vmImage: 'ubuntu-18.04'
# CPU: i386
OSX_amd64:
vmImage: 'macOS-11'
vmImage: 'macOS-12'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-11'
vmImage: 'macOS-12'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64_batch0_3:

View File

@@ -14,7 +14,7 @@ else
fi
# Find out where the pretty printer Python module is
GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/debug/nim-gdb.py"
# Run GDB with the additional arguments that load the pretty printers
# Set the environment variable `NIM_GDB` to overwrite the call to a

View File

@@ -3,7 +3,7 @@ for %%i in (nim.exe) do (set NIM_BIN=%%~dp$PATH:i)
for %%i in ("%NIM_BIN%\..\") do (set NIM_ROOT=%%~fi)
set @GDB_PYTHON_MODULE_PATH=%NIM_ROOT%\tools\nim-gdb.py
set @GDB_PYTHON_MODULE_PATH=%NIM_ROOT%\tools\debug\nim-gdb.py
set @NIM_GDB=gdb.exe
@echo source %@GDB_PYTHON_MODULE_PATH%> wingdbcommand.txt

View File

@@ -1,273 +1,130 @@
# v2.0.0 - yyyy-mm-dd
# v2.2.0 - yyyy-mm-dd
## Changes affecting backward compatibility
- `httpclient.contentLength` default to `-1` if the Content-Length header is not set in the response, it followed Apache HttpClient(Java), http(go) and .Net HttpWebResponse(C#) behavior. Previously it raised `ValueError`.
- `addr` is now available for all addressable locations,
`unsafeAddr` is now deprecated and an alias for `addr`.
- Certain definitions from the default `system` module have been moved to
the following new modules:
- `std/syncio`
- `std/assertions`
- `std/formatfloat`
- `std/objectdollar`
- `std/widestrs`
- `std/typedthreads`
- `std/sysatomics`
In the future, these definitions will be removed from the `system` module,
and their respective modules will have to be imported to use them.
Currently, to make these imports required, the `-d:nimPreviewSlimSystem` option
may be used.
- Enabling `-d:nimPreviewSlimSystem` also removes the following deprecated
symbols in the `system` module:
- Aliases with `Error` suffix to exception types that have a `Defect` suffix
(see [exceptions](https://nim-lang.org/docs/exceptions.html)):
`ArithmeticError`, `DivByZeroError`, `OverflowError`,
`AccessViolationError`, `AssertionError`, `OutOfMemError`, `IndexError`,
`FieldError`, `RangeError`, `StackOverflowError`, `ReraiseError`,
`ObjectAssignmentError`, `ObjectConversionError`, `FloatingPointError`,
`FloatOverflowError`, `FloatUnderflowError`, `FloatInexactError`,
`DeadThreadError`, `NilAccessError`
- `addQuitProc`, replaced by `exitprocs.addExitProc`
- Legacy unsigned conversion operations: `ze`, `ze64`, `toU8`, `toU16`, `toU32`
- `TaintedString`, formerly a distinct alias to `string`
- `PInt32`, `PInt64`, `PFloat32`, `PFloat64`, aliases to
`ptr int32`, `ptr int64`, `ptr float32`, `ptr float64`
- Enabling `-d:nimPreviewSlimSystem` removes the import of `channels_builtin` in
in the `system` module.
- Enabling `-d:nimPreviewCstringConversion`, `ptr char`, `ptr array[N, char]` and `ptr UncheckedArray[N, char]` don't support conversion to cstring anymore.
- The `gc:v2` option is removed.
- The `mainmodule` and `m` options are removed.
- The `threads:on` option is now the default.
- Optional parameters in combination with `: body` syntax (RFC #405) are now opt-in via
`experimental:flexibleOptionalParams`.
- Automatic dereferencing (experimental feature) is removed.
- The `Math.trunc` polyfill for targeting Internet Explorer was
previously included in most JavaScript output files.
Now, it is only included with `-d:nimJsMathTruncPolyfill`.
If you are targeting Internet Explorer, you may choose to enable this option
or define your own `Math.trunc` polyfill using the [`emit` pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-emit-pragma).
Nim uses `Math.trunc` for the division and modulo operators for integers.
- `shallowCopy` and `shallow` are removed for ARC/ORC. Use `move` when possible or combine assignment and
`sink` for optimization purposes.
- The `nimPreviewDotLikeOps` define is going to be removed or deprecated.
- The `{.this.}` pragma, deprecated since 0.19, has been removed.
- `nil` literals can no longer be directly assigned to variables or fields of `distinct` pointer types. They must be converted instead.
```nim
type Foo = distinct ptr int
# Before:
var x: Foo = nil
# After:
var x: Foo = Foo(nil)
```
- Removed two type pragma syntaxes deprecated since 0.20, namely
`type Foo = object {.final.}`, and `type Foo {.final.} [T] = object`.
- [Overloadable enums](https://nim-lang.github.io/Nim/manual.html#overloadable-enum-value-names) and Unicode Operators
are no longer experimental.
- Removed the `nimIncrSeqV3` define.
- `macros.getImpl` for `const` symbols now returns the full definition node
(as `nnkConstDef`) rather than the AST of the constant value.
- Lock levels are deprecated, now a noop.
- ORC is now the default memory management strategy. Use
`--mm:refc` for a transition period.
- `strictEffects` are no longer experimental.
Use `legacy:laxEffects` to keep backward compatibility.
- The `gorge`/`staticExec` calls will now return a descriptive message in the output
if the execution fails for whatever reason. To get back legacy behaviour use `-d:nimLegacyGorgeErrors`.
- Pointer to `cstring` conversion now triggers a `[PtrToCstringConv]` warning.
This warning will become an error in future versions! Use a `cast` operation
like `cast[cstring](x)` instead.
- `logging` will default to flushing all log level messages. To get the legacy behaviour of only flushing Error and Fatal messages, use `-d:nimV1LogFlushBehavior`.
- Object fields now support default values, see https://nim-lang.github.io/Nim/manual.html#types-default-values-for-object-fields for details.
- Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead.
- `-d:nimStrictDelete` becomes the default. An index error is produced when the index passed to `system.delete` was out of bounds. Use `-d:nimAuditDelete` to mimic the old behavior for backwards compatibility.
- The default user-agent in `std/httpclient` has been changed to `Nim-httpclient/<version>` instead of `Nim httpclient/<version>` which was incorrect according to the HTTP spec.
- With `-d:nimPreviewNonVarDestructor`, non-var destructors become the default.
## Standard library additions and changes
[//]: # "Changes:"
- OpenSSL 3 is now supported.
- `macros.parseExpr` and `macros.parseStmt` now accept an optional
filename argument for more informative errors.
- Module `colors` expanded with missing colors from the CSS color standard.
`colPaleVioletRed` and `colMediumPurple` have also been changed to match the CSS color standard.
- Fixed `lists.SinglyLinkedList` being broken after removing the last node ([#19353](https://github.com/nim-lang/Nim/pull/19353)).
- The `md5` module now works at compile time and in JavaScript.
- Changed `mimedb` to use an `OrderedTable` instead of `OrderedTableRef` to support `const` tables.
- `strutils.find` now uses and defaults to `last = -1` for whole string searches,
making limiting it to just the first char (`last = 0`) valid.
- `random.rand` now works with `Ordinal`s.
- Undeprecated `os.isvalidfilename`.
- `std/oids` now uses `int64` to store time internally (before it was int32).
- `std/uri.Uri` dollar `$` improved, precalculates the `string` result length from the `Uri`.
- `std/uri.Uri.isIpv6` is now exported.
- `std/logging.ConsoleLogger` and `FileLogger` now have a `flushThreshold` attribute to set what log message levels are automatically flushed. For Nim v1 use `-d:nimFlushAllLogs` to automatically flush all message levels. Flushing all logs is the default behavior for Nim v2.
- `std/net.IpAddress` dollar `$` improved, uses a fixed capacity for the `string` result based from the `IpAddressFamily`.
- `std/jsfetch.newFetchOptions` now has default values for all parameters
- `std/jsformdata` now accepts `Blob` data type.
[//]: # "Additions:"
- Added ISO 8601 week date utilities in `times`:
- Added `IsoWeekRange`, a range type for weeks in a week-based year.
- Added `IsoYear`, a distinct type for a week-based year in contrast to a regular year.
- Added a `initDateTime` overload to create a datetime from an ISO week date.
- Added `getIsoWeekAndYear` to get an ISO week number and week-based year from a datetime.
- Added `getIsoWeeksInYear` to return the number of weeks in a week-based year.
- Added new modules which were part of `std/os`:
- Added `std/oserrors` for OS error reporting. Added `std/envvars` for environment variables handling.
- Added `std/paths`, `std/dirs`, `std/files`, `std/symlinks` and `std/appdirs`.
- Added `sep` parameter in `std/uri` to specify the query separator.
- Added bindings to [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
and [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
in `jscore` for JavaScript targets.
- Added `UppercaseLetters`, `LowercaseLetters`, `PunctuationChars`, `PrintableChars` sets to `std/strutils`.
- Added `complex.sgn` for obtaining the phase of complex numbers.
- Added `insertAdjacentText`, `insertAdjacentElement`, `insertAdjacentHTML`,
`after`, `before`, `closest`, `append`, `hasAttributeNS`, `removeAttributeNS`,
`hasPointerCapture`, `releasePointerCapture`, `requestPointerLock`,
`replaceChildren`, `replaceWith`, `scrollIntoViewIfNeeded`, `setHTML`,
`toggleAttribute`, and `matches` to `std/dom`.
- Added [`jsre.hasIndices`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/hasIndices)
- Added `capacity` for `string` and `seq` to return the current capacity, see https://github.com/nim-lang/RFCs/issues/460
- Added `openArray[char]` overloads for `std/parseutils` allowing more code reuse.
- Added `openArray[char]` overloads for `std/unicode` allowing more code reuse.
- Added `safe` parameter to `base64.encodeMime`.
- Added `newStringUninit` to system, which creates a new string of length `len` like `newString` but with uninitialized content.
- Added `setLenUninit` to system, which doesn't initalize
slots when enlarging a sequence.
- Added `hasDefaultValue` to `std/typetraits` to check if a type has a valid default value.
- Added Viewport API for the JavaScript targets in the `dom` module.
[//]: # "Deprecations:"
- Deprecated `selfExe` for Nimscript.
- Deprecated `std/sums`.
- Deprecated `std/base64.encode` for collections of arbitrary integer element type.
Now only `byte` and `char` are supported.
[//]: # "Removals:"
- Removed deprecated module `parseopt2`.
- Removed deprecated module `sharedstrings`.
- Removed deprecated module `dom_extensions`.
- Removed deprecated module `LockFreeHash`.
- Removed deprecated module `events`.
- Removed deprecated `oids.oidToString`.
- Removed define `nimExperimentalAsyncjsThen` for `std/asyncjs.then` and `std/jsfetch`.
- Removed deprecated `jsre.test` and `jsre.toString`.
- Removed deprecated `math.c_frexp`.
- Removed deprecated `` httpcore.`==` ``.
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that takes wrong argument types.
- Removed deprecated `osproc.poDemon`, symbol with typo.
## Language changes
- [Tag tracking](https://nim-lang.github.io/Nim/manual.html#effect-system-tag-tracking) supports the definition of forbidden tags by the `.forbids` pragma
which can be used to disable certain effects in proc types.
- [Case statement macros](https://nim-lang.github.io/Nim/manual.html#macros-case-statement-macros) are no longer experimental,
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
for the right-hand side of type definitions in type sections. Previously
they would error with "invalid indentation".
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
In the command line, this is defined as `-d:a.b.c`. Older versions can
use accents as in ``defined(`a.b.c`)`` to access such defines.
- [Macro pragmas](https://nim-lang.github.io/Nim/manual.html#userminusdefined-pragmas-macro-pragmas) changes:
- Templates now accept macro pragmas.
- Macro pragmas for var/let/const sections have been redesigned in a way that works
similarly to routine macro pragmas. The new behavior is documented in the
[experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#extended-macro-pragmas).
- Pragma macros on type definitions can now return `nnkTypeSection` nodes as well as `nnkTypeDef`,
allowing multiple type definitions to be injected in place of the original type definition.
```nim
import macros
macro multiply(amount: static int, s: untyped): untyped =
let name = $s[0].basename
result = newNimNode(nnkTypeSection)
for i in 1 .. amount:
result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
type
Foo = object
Bar {.multiply: 3.} = object
x, y, z: int
Baz = object
# becomes
type
Foo = object
Bar1 = object
x, y, z: int
Bar2 = object
x, y, z: int
Bar3 = object
x, y, z: int
Baz = object
```
- Redefining templates with the same signature implicitly was previously
allowed to support certain macro code. A `{.redefine.}` pragma has been
added to make this work explicitly, and a warning is generated in the case
where it is implicit. This behavior only applies to templates, redefinition
is generally disallowed for other symbols.
- The experimental option `--experimental:openSym` has been added to allow
captured symbols in generic routine and template bodies respectively to be
replaced by symbols injected locally by templates/macros at instantiation
time. `bind` may be used to keep the captured symbols over the injected ones
regardless of enabling the option, but other methods like renaming the
captured symbols should be used instead so that the code is not affected by
context changes.
- A new form of type inference called [top-down inference](https://nim-lang.github.io/Nim/manual_experimental.html#topminusdown-type-inference)
has been implemented for a variety of basic cases. For example, code like the following now compiles:
Since this change may affect runtime behavior, the experimental switch
`openSym` needs to be enabled; and a warning is given in the case where an
injected symbol would replace a captured symbol not bound by `bind` and
the experimental switch isn't enabled.
```nim
let foo: seq[(float, byte, cstring)] = @[(1, 2, "abc")]
const value = "captured"
template foo(x: int, body: untyped): untyped =
let value {.inject.} = "injected"
body
proc old[T](): string =
foo(123):
return value # warning: a new `value` has been injected, use `bind` or turn on `experimental:openSym`
echo old[int]() # "captured"
template oldTempl(): string =
block:
foo(123):
value # warning: a new `value` has been injected, use `bind` or turn on `experimental:openSym`
echo oldTempl() # "captured"
{.experimental: "openSym".}
proc bar[T](): string =
foo(123):
return value
assert bar[int]() == "injected" # previously it would be "captured"
proc baz[T](): string =
bind value
foo(123):
return value
assert baz[int]() == "captured"
template barTempl(): string =
block:
foo(123):
value
assert barTempl() == "injected" # previously it would be "captured"
template bazTempl(): string =
bind value
block:
foo(123):
value
assert bazTempl() == "captured"
```
- `cstring` is now accepted as a selector in `case` statements, removing the
need to convert to `string`. On the JS backend, this is translated directly
to a `switch` statement.
This option also generates a new node kind `nnkOpenSym` which contains
exactly 1 `nnkSym` node. In the future this might be merged with a slightly
modified `nnkOpenSymChoice` node but macros that want to support the
experimental feature should still handle `nnkOpenSym`, as the node kind would
simply not be generated as opposed to being removed.
- Nim now supports `out` parameters and ["strict definitions"](https://nim-lang.github.io/Nim/manual_experimental.html#strict-definitions-and-nimout-parameters).
- Nim now offers a [strict mode](https://nim-lang.github.io/Nim/manual_experimental.html#strict-case-objects) for `case objects`.
Another experimental switch `genericsOpenSym` exists that enables this behavior
at instantiation time, meaning templates etc can enable it specifically when
they are being called. However this does not generate `nnkOpenSym` nodes
(unless the other switch is enabled) and so doesn't reflect the regular
behavior of the switch.
```nim
const value = "captured"
template foo(x: int, body: untyped): untyped =
let value {.inject.} = "injected"
{.push experimental: "genericsOpenSym".}
body
{.pop.}
proc bar[T](): string =
foo(123):
return value
echo bar[int]() # "injected"
template barTempl(): string =
block:
var res: string
foo(123):
res = value
res
assert barTempl() == "injected"
```
## Compiler changes
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
reality better. (Nim moved away from all techniques based on "tracing".)
- Defines the `gcRefc` symbol which allows writing specific code for the refc GC.
- `nim` can now compile version 1.4.0 as follows: `nim c --lib:lib --stylecheck:off compiler/nim`,
without requiring `-d:nimVersion140` which is now a noop.
- `--styleCheck`, `--hintAsError` and `--warningAsError` now only apply to the current package.
- The switch `--nimMainPrefix:prefix` has been added to add a prefix to the names of `NimMain` and
related functions produced on the backend. This prevents conflicts with other Nim
static libraries.
- When compiling for Release the flag `-fno-math-errno` is used for GCC.
## Tool changes
- Nim now supports Nimble version 0.14 which added support for lock-files. This is done by
a simple configuration change setting that you can do yourself too. In `$nim/config/nim.cfg`
replace `pkgs` by `pkgs2`.
- koch now allows bootstrapping with `-d:nimHasLibFFI`, replacing the older option of building the compiler directly w/ the `libffi` nimble package in tow.

View File

@@ -1,33 +0,0 @@
# v1.xx.x - yyyy-mm-dd
## Changes affecting backward compatibility
## Standard library additions and changes
- `std/sharedlist` and `std/sharedtables` are now deprecated, see RFC [#433](https://github.com/nim-lang/RFCs/issues/433).
### New compile flag (`-d:nimNoGetRandom`) when building `std/sysrand` to remove dependency on linux `getrandom` syscall
This compile flag only affects linux builds and is necessary if either compiling on a linux kernel version < 3.17, or if code built will be executing on kernel < 3.17.
On linux kernels < 3.17 (such as kernel 3.10 in RHEL7 and CentOS7), the `getrandom` syscall was not yet introduced. Without this, the `std/sysrand` module will not build properly, and if code is built on a kernel >= 3.17 without the flag, any usage of the `std/sysrand` module will fail to execute on a kernel < 3.17 (since it attempts to perform a syscall to `getrandom`, which isn't present in the current kernel). A compile flag has been added to force the `std/sysrand` module to use /dev/urandom (available since linux kernel 1.3.30), rather than the `getrandom` syscall. This allows for use of a cryptographically secure PRNG, regardless of kernel support for the `getrandom` syscall.
When building for RHEL7/CentOS7 for example, the entire build process for nim from a source package would then be:
```sh
$ yum install devtoolset-8 # Install GCC version 8 vs the standard 4.8.5 on RHEL7/CentOS7. Alternatively use -d:nimEmulateOverflowChecks. See issue #13692 for details
$ scl enable devtoolset-8 bash # Run bash shell with default toolchain of gcc 8
$ sh build.sh # per unix install instructions
$ bin/nim c koch # per unix install instructions
$ ./koch boot -d:release # per unix install instructions
$ ./koch tools -d:nimNoGetRandom # pass the nimNoGetRandom flag to compile std/sysrand without support for getrandom syscall
```
This is necessary to pass when building nim on kernel versions < 3.17 in particular to avoid an error of "SYS_getrandom undeclared" during the build process for stdlib (sysrand in particular).
## Language changes
## Compiler changes
## Tool changes

View File

@@ -0,0 +1,330 @@
# v2.0.0 - 2023-08-01
Version 2.0 is a big milestone with too many changes to list them all here.
For a full list see [details](changelog_2_0_0_details.html).
## New features
### Better tuple unpacking
Tuple unpacking for variables is now treated as syntax sugar that directly
expands into multiple assignments. Along with this, tuple unpacking for
variables can now be nested.
```nim
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
# Now nesting is supported!
let (x, (_, y), _, z) = returnsNestedTuple()
```
### Improved type inference
A new form of type inference called [top-down inference](https://nim-lang.github.io/Nim/manual_experimental.html#topminusdown-type-inference) has been implemented for a variety of basic cases.
For example, code like the following now compiles:
```nim
let foo: seq[(float, byte, cstring)] = @[(1, 2, "abc")]
```
### Forbidden Tags
[Tag tracking](https://nim-lang.github.io/Nim/manual.html#effect-system-tag-tracking) now supports the definition
of forbidden tags by the `.forbids` pragma which can be used to disable certain effects in proc types.
For example:
```nim
type IO = object ## input/output effect
proc readLine(): string {.tags: [IO].} = discard
proc echoLine(): void = discard
proc no_IO_please() {.forbids: [IO].} =
# this is OK because it didn't define any tag:
echoLine()
# the compiler prevents this:
let y = readLine()
```
### New standard library modules
The famous `os` module got an overhaul. Several of its features are available
under a new interface that introduces a `Path` abstraction. A `Path` is
a `distinct string`, which improves the type safety when dealing with paths, files
and directories.
Use:
- `std/oserrors` for OS error reporting.
- `std/envvars` for environment variables handling.
- `std/paths` for path handling.
- `std/dirs` for directory creation/deletion/traversal.
- `std/files` for file existence checking, file deletions and moves.
- `std/symlinks` for symlink handling.
- `std/appdirs` for accessing configuration/home/temp directories.
- `std/cmdline` for reading command line parameters.
### Consistent underscore handling
The underscore identifier (`_`) is now generally not added to scope when
used as the name of a definition. While this was already the case for
variables, it is now also the case for routine parameters, generic
parameters, routine declarations, type declarations, etc. This means that the following code now does not compile:
```nim
proc foo(_: int): int = _ + 1
echo foo(1)
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
echo foo[int]()
proc _() = echo "_"
_()
type _ = int
let x: _ = 3
```
Whereas the following code now compiles:
```nim
proc foo(_, _: int): int = 123
echo foo(1, 2)
proc foo[_, _](): int = 123
echo foo[int, bool]()
proc foo[T, U](_: typedesc[T], _: typedesc[U]): (T, U) = (default(T), default(U))
echo foo(int, bool)
proc _() = echo "one"
proc _() = echo "two"
type _ = int
type _ = float
```
### JavaScript codegen improvement
The JavaScript backend now uses [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
for 64-bit integer types (`int64` and `uint64`) by default. As this affects
JS code generation, code using these types to interface with the JS backend
may need to be updated. Note that `int` and `uint` are not affected.
For compatibility with [platforms that do not support BigInt](https://caniuse.com/bigint)
and in the case of potential bugs with the new implementation, the
old behavior is currently still supported with the command line option
`--jsbigint64:off`.
## Docgen improvements
`Markdown` is now the default markup language of doc comments (instead
of the legacy `RstMarkdown` mode). In this release we begin to separate
RST and Markdown features to better follow specification of each
language, with the focus on Markdown development.
See also [the docs](https://nim-lang.github.io/Nim/markdown_rst.html).
* Added a `{.doctype: Markdown | RST | RstMarkdown.}` pragma allowing to
select the markup language mode in the doc comments of the current `.nim`
file for processing by `nim doc`:
1. `Markdown` (default) is basically CommonMark (standard Markdown) +
some Pandoc Markdown features + some RST features that are missing
in our current implementation of CommonMark and Pandoc Markdown.
2. `RST` closely follows the RST spec with few additional Nim features.
3. `RstMarkdown` is a maximum mix of RST and Markdown features, which
is kept for the sake of compatibility and ease of migration.
* Added separate `md2html` and `rst2html` commands for processing
standalone `.md` and `.rst` files respectively (and also `md2tex`/`rst2tex`).
* Added Pandoc Markdown bracket syntax `[...]` for making anchor-less links.
* Docgen now supports concise syntax for referencing Nim symbols:
instead of specifying HTML anchors directly one can use original
Nim symbol declarations (adding the aforementioned link brackets
`[...]` around them).
* To use this feature across modules, a new `importdoc` directive was added.
Using this feature for referencing also helps to ensure that links
(inside one module or the whole project) are not broken.
* Added support for RST & Markdown quote blocks (blocks starting with `>`).
* Added a popular Markdown definition lists extension.
* Added Markdown indented code blocks (blocks indented by >= 4 spaces).
* Added syntax for additional parameters to Markdown code blocks:
```nim test="nim c $1"
...
```
## C++ interop enhancements
Nim 2.0 takes C++ interop to the next level. With the new [virtual](https://nim-lang.github.io/Nim/manual_experimental.html#virtual-pragma) pragma and the extended [constructor](https://nim-lang.github.io/Nim/manual_experimental.html#constructor-pragma) pragma.
Now one can define constructors and virtual procs that maps to C++ constructors and virtual methods, allowing one to further customize
the interoperability. There is also extended support for the [codeGenDecl](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-codegendecl-pragma) pragma, so that it works on types.
It's a common pattern in C++ to use inheritance to extend a library. Some even use multiple inheritance as a mechanism to make interfaces.
Consider the following example:
```cpp
struct Base {
int someValue;
Base(int inValue) {
someValue = inValue;
};
};
class IPrinter {
public:
virtual void print() = 0;
};
```
```nim
type
Base* {.importcpp, inheritable.} = object
someValue*: int32
IPrinter* {.importcpp.} = object
const objTemplate = """
struct $1 : public $3, public IPrinter {
$2
};
""";
type NimChild {.codegenDecl: objTemplate .} = object of Base
proc makeNimChild(val: int32): NimChild {.constructor: "NimClass('1 #1) : Base(#1)".} =
echo "It calls the base constructor passing " & $this.someValue
this.someValue = val * 2 # Notice how we can access `this` inside the constructor. It's of the type `ptr NimChild`.
proc print*(self: NimChild) {.virtual.} =
echo "Some value is " & $self.someValue
let child = makeNimChild(10)
child.print()
```
It outputs:
```
It calls the base constructor passing 10
Some value is 20
```
## ARC/ORC refinements
With the 2.0 release, the ARC/ORC model got refined once again and is now finally complete:
1. Programmers now have control over the "item was moved from" state as `=wasMoved` is overridable.
2. There is a new `=dup` hook which is more efficient than the old combination of `=wasMoved(tmp); =copy(tmp, x)` operations.
3. Destructors now take a parameter of the attached object type `T` directly and don't have to take a `var T` parameter.
With these important optimizations we improved the runtime of the compiler and important benchmarks by 0%! Wait ... what?
Yes, unfortunately it turns out that for a modern optimizer like in GCC or LLVM there is no difference.
But! This refined model is more efficient once separate compilation enters the picture. In other words, as we think of
providing a stable ABI it is important not to lose any efficiency in the calling conventions.
## Tool changes
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs` before). Use `nimble develop --global` to create an old style link file in the special links directory documented at https://github.com/nim-lang/nimble#nimble-develop.
- nimgrep now offers the option `--inContext` (and `--notInContext`), which
allows to filter only matches with the context block containing a given pattern.
- nimgrep: names of options containing "include/exclude" are deprecated,
e.g. instead of `--includeFile` and `--excludeFile` we have
`--filename` and `--notFilename` respectively.
Also, the semantics are now consistent for such positive/negative filters.
- Nim now ships with an alternative package manager called Atlas. More on this in upcoming versions.
## Porting guide
### Block and Break
Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead. In other words, turn:
```nim
block:
a()
if cond:
break
b()
```
Into:
```nim
block maybePerformB:
a()
if cond:
break maybePerformB
b()
```
### Strict funcs
The definition of `"strictFuncs"` was changed.
The old definition was roughly: "A store to a ref/ptr deref is forbidden unless it's coming from a `var T` parameter".
The new definition is: "A store to a ref/ptr deref is forbidden."
This new definition is much easier to understand, the price is some expressitivity. The following code used to be
accepted:
```nim
{.experimental: "strictFuncs".}
type Node = ref object
s: string
func create(s: string): Node =
result = Node()
result.s = s # store to result[]
```
Now it has to be rewritten to:
```nim
{.experimental: "strictFuncs".}
type Node = ref object
s: string
func create(s: string): Node =
result = Node(s: s)
```
### Standard library
Several standard library modules have been moved to nimble packages, use `nimble` or `atlas` to install them:
- `std/punycode` => `punycode`
- `std/asyncftpclient` => `asyncftpclient`
- `std/smtp` => `smtp`
- `std/db_common` => `db_connector/db_common`
- `std/db_sqlite` => `db_connector/db_sqlite`
- `std/db_mysql` => `db_connector/db_mysql`
- `std/db_postgres` => `db_connector/db_postgres`
- `std/db_odbc` => `db_connector/db_odbc`
- `std/md5` => `checksums/md5`
- `std/sha1` => `checksums/sha1`
- `std/sums` => `sums`

View File

@@ -0,0 +1,560 @@
# v2.0.0 - 2023-08-01
## Changes affecting backward compatibility
- ORC is now the default memory management strategy. Use
`--mm:refc` for a transition period.
- The `threads:on` option is now the default.
- `httpclient.contentLength` default to `-1` if the Content-Length header is not set in the response. It follows Apache's `HttpClient` (Java), `http` (go) and .NET `HttpWebResponse` (C#) behaviors. Previously it raised a `ValueError`.
- `addr` is now available for all addressable locations,
`unsafeAddr` is now deprecated and an alias for `addr`.
- Certain definitions from the default `system` module have been moved to
the following new modules:
- `std/syncio`
- `std/assertions`
- `std/formatfloat`
- `std/objectdollar`
- `std/widestrs`
- `std/typedthreads`
- `std/sysatomics`
In the future, these definitions will be removed from the `system` module,
and their respective modules will have to be imported to use them.
Currently, to make these imports required, the `-d:nimPreviewSlimSystem` option
may be used.
- Enabling `-d:nimPreviewSlimSystem` also removes the following deprecated
symbols in the `system` module:
- Aliases with an `Error` suffix to exception types that have a `Defect` suffix
(see [exceptions](https://nim-lang.github.io/Nim/exceptions.html)):
`ArithmeticError`, `DivByZeroError`, `OverflowError`,
`AccessViolationError`, `AssertionError`, `OutOfMemError`, `IndexError`,
`FieldError`, `RangeError`, `StackOverflowError`, `ReraiseError`,
`ObjectAssignmentError`, `ObjectConversionError`, `FloatingPointError`,
`FloatOverflowError`, `FloatUnderflowError`, `FloatInexactError`,
`DeadThreadError`, `NilAccessError`
- `addQuitProc`, replaced by `exitprocs.addExitProc`
- Legacy unsigned conversion operations: `ze`, `ze64`, `toU8`, `toU16`, `toU32`
- `TaintedString`, formerly a distinct alias to `string`
- `PInt32`, `PInt64`, `PFloat32`, `PFloat64`, aliases to
`ptr int32`, `ptr int64`, `ptr float32`, `ptr float64`
- Enabling `-d:nimPreviewSlimSystem` removes the import of `channels_builtin` in
in the `system` module, which is replaced by [threading/channels](https://github.com/nim-lang/threading/blob/master/threading/channels.nim). Use the command `nimble install threading` and import `threading/channels`.
- Enabling `-d:nimPreviewCstringConversion` causes `ptr char`, `ptr array[N, char]` and `ptr UncheckedArray[N, char]` to not support conversion to `cstring` anymore.
- Enabling `-d:nimPreviewProcConversion` causes `proc` to not support conversion to
`pointer` anymore. `cast` may be used instead.
- The `gc:v2` option is removed.
- The `mainmodule` and `m` options are removed.
- Optional parameters in combination with `: body` syntax ([RFC #405](https://github.com/nim-lang/RFCs/issues/405))
are now opt-in via `experimental:flexibleOptionalParams`.
- Automatic dereferencing (experimental feature) is removed.
- The `Math.trunc` polyfill for targeting Internet Explorer was
previously included in most JavaScript output files.
Now, it is only included with `-d:nimJsMathTruncPolyfill`.
If you are targeting Internet Explorer, you may choose to enable this option
or define your own `Math.trunc` polyfill using the [`emit` pragma](https://nim-lang.org/docs/manual.html#implementation-specific-pragmas-emit-pragma).
Nim uses `Math.trunc` for the division and modulo operators for integers.
- `shallowCopy` and `shallow` are removed for ARC/ORC. Use `move` when possible or combine assignment and
`sink` for optimization purposes.
- The experimental `nimPreviewDotLikeOps` switch is going to be removed or deprecated because it didn't fulfill its promises.
- The `{.this.}` pragma, deprecated since 0.19, has been removed.
- `nil` literals can no longer be directly assigned to variables or fields of `distinct` pointer types. They must be converted instead.
```nim
type Foo = distinct ptr int
# Before:
var x: Foo = nil
# After:
var x: Foo = Foo(nil)
```
- Removed two type pragma syntaxes deprecated since 0.20, namely
`type Foo = object {.final.}`, and `type Foo {.final.} [T] = object`. Instead,
use `type Foo[T] {.final.} = object`.
- `foo a = b` now means `foo(a = b)` rather than `foo(a) = b`. This is consistent
with the existing behavior of `foo a, b = c` meaning `foo(a, b = c)`.
This decision was made with the assumption that the old syntax was used rarely;
if your code used the old syntax, please be aware of this change.
- [Overloadable enums](https://nim-lang.github.io/Nim/manual.html#overloadable-enum-value-names) and Unicode Operators
are no longer experimental.
- `macros.getImpl` for `const` symbols now returns the full definition node
(as `nnkConstDef`) rather than the AST of the constant value.
- Lock levels are deprecated, now a noop.
- `strictEffects` are no longer experimental.
Use `legacy:laxEffects` to keep backward compatibility.
- The `gorge`/`staticExec` calls will now return a descriptive message in the output
if the execution fails for whatever reason. To get back legacy behaviour, use `-d:nimLegacyGorgeErrors`.
- Pointer to `cstring` conversions now trigger a `[PtrToCstringConv]` warning.
This warning will become an error in future versions! Use a `cast` operation
like `cast[cstring](x)` instead.
- `logging` will default to flushing all log level messages. To get the legacy behaviour of only flushing Error and Fatal messages, use `-d:nimV1LogFlushBehavior`.
- Redefining templates with the same signature was previously
allowed to support certain macro code. To do this explicitly, the
`{.redefine.}` pragma has been added. Note that this is only for templates.
Implicit redefinition of templates is now deprecated and will give an error in the future.
- Using an unnamed break in a block is deprecated. This warning will become an error in future versions! Use a named block with a named break instead.
- Several Standard libraries have been moved to nimble packages, use `nimble` to install them:
- `std/punycode` => `punycode`
- `std/asyncftpclient` => `asyncftpclient`
- `std/smtp` => `smtp`
- `std/db_common` => `db_connector/db_common`
- `std/db_sqlite` => `db_connector/db_sqlite`
- `std/db_mysql` => `db_connector/db_mysql`
- `std/db_postgres` => `db_connector/db_postgres`
- `std/db_odbc` => `db_connector/db_odbc`
- `std/md5` => `checksums/md5`
- `std/sha1` => `checksums/sha1`
- `std/sums` => `std/sums`
- Previously, calls like `foo(a, b): ...` or `foo(a, b) do: ...` where the final argument of
`foo` had type `proc ()` were assumed by the compiler to mean `foo(a, b, proc () = ...)`.
This behavior is now deprecated. Use `foo(a, b) do (): ...` or `foo(a, b, proc () = ...)` instead.
- When `--warning[BareExcept]:on` is enabled, if an `except` specifies no exception or any exception not inheriting from `Defect` or `CatchableError`, a `warnBareExcept` warning will be triggered. For example, the following code will emit a warning:
```nim
try:
discard
except: # Warning: The bare except clause is deprecated; use `except CatchableError:` instead [BareExcept]
discard
```
- The experimental `strictFuncs` feature now disallows a store to the heap via a `ref` or `ptr` indirection.
- The underscore identifier (`_`) is now generally not added to scope when
used as the name of a definition. While this was already the case for
variables, it is now also the case for routine parameters, generic
parameters, routine declarations, type declarations, etc. This means that the following code now does not compile:
```nim
proc foo(_: int): int = _ + 1
echo foo(1)
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
echo foo[int]()
proc _() = echo "_"
_()
type _ = int
let x: _ = 3
```
Whereas the following code now compiles:
```nim
proc foo(_, _: int): int = 123
echo foo(1, 2)
proc foo[_, _](): int = 123
echo foo[int, bool]()
proc foo[T, U](_: typedesc[T], _: typedesc[U]): (T, U) = (default(T), default(U))
echo foo(int, bool)
proc _() = echo "one"
proc _() = echo "two"
type _ = int
type _ = float
```
- Added the `--legacy:verboseTypeMismatch` switch to get legacy type mismatch error messages.
- The JavaScript backend now uses [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
for 64-bit integer types (`int64` and `uint64`) by default. As this affects
JS code generation, code using these types to interface with the JS backend
may need to be updated. Note that `int` and `uint` are not affected.
For compatibility with [platforms that do not support BigInt](https://caniuse.com/bigint)
and in the case of potential bugs with the new implementation, the
old behavior is currently still supported with the command line option
`--jsbigint64:off`.
- The `proc` and `iterator` type classes now respectively only match
procs and iterators. Previously both type classes matched any of
procs or iterators.
```nim
proc prc(): int =
123
iterator iter(): int =
yield 123
proc takesProc[T: proc](x: T) = discard
proc takesIter[T: iterator](x: T) = discard
# always compiled:
takesProc(prc)
takesIter(iter)
# no longer compiles:
takesProc(iter)
takesIter(prc)
```
- The `proc` and `iterator` type classes now accept a calling convention pragma
(i.e. `proc {.closure.}`) that must be shared by matching proc or iterator
types. Previously, pragmas were parsed but discarded if no parameter list
was given.
This is represented in the AST by an `nnkProcTy`/`nnkIteratorTy` node with
an `nnkEmpty` node in the place of the `nnkFormalParams` node, and the pragma
node in the same place as in a concrete `proc` or `iterator` type node. This
state of the AST may be unexpected to existing code, both due to the
replacement of the `nnkFormalParams` node as well as having child nodes
unlike other type class AST.
- Signed integer literals in `set` literals now default to a range type of
`0..255` instead of `0..65535` (the maximum size of sets).
- `case` statements with `else` branches put before `elif`/`of` branches in macros
are rejected with "invalid order of case branches".
- Destructors now default to `.raises: []` (i.e. destructors must not raise
unlisted exceptions) and explicitly raising destructors are implementation
defined behavior.
- The very old, undocumented `deprecated` pragma statement syntax for
deprecated aliases is now a no-op. The regular deprecated pragma syntax is
generally sufficient instead.
```nim
# now does nothing:
{.deprecated: [OldName: NewName].}
# instead use:
type OldName* {.deprecated: "use NewName instead".} = NewName
const oldName* {.deprecated: "use newName instead".} = newName
```
`defined(nimalias)` can be used to check for versions when this syntax was
available; however since code that used this syntax is usually very old,
these deprecated aliases are likely not used anymore and it may make sense
to simply remove these statements.
- `getProgramResult` and `setProgramResult` in `std/exitprocs` are no longer
declared when they are not available on the backend. Previously it would call
`doAssert false` at runtime despite the condition being checkable at compile-time.
- Custom destructors now supports non-var parameters, e.g. ``proc `=destroy`[T: object](x: T)`` is valid. ``proc `=destroy`[T: object](x: var T)`` is deprecated.
- Relative imports will not resolve to searched paths anymore, e.g. `import ./tables` now reports an error properly.
## Standard library additions and changes
[//]: # "Changes:"
- OpenSSL 3 is now supported.
- `macros.parseExpr` and `macros.parseStmt` now accept an optional
`filename` argument for more informative errors.
- The `colors` module is expanded with missing colors from the CSS color standard.
`colPaleVioletRed` and `colMediumPurple` have also been changed to match the CSS color standard.
- Fixed `lists.SinglyLinkedList` being broken after removing the last node ([#19353](https://github.com/nim-lang/Nim/pull/19353)).
- The `md5` module now works at compile time and in JavaScript.
- Changed `mimedb` to use an `OrderedTable` instead of `OrderedTableRef`, to support `const` tables.
- `strutils.find` now uses and defaults to `last = -1` for whole string searches,
making limiting it to just the first char (`last = 0`) valid.
- `strutils.split` and `strutils.rsplit` now return the source string as a single element for an empty separator.
- `random.rand` now works with `Ordinal`s.
- Undeprecated `os.isvalidfilename`.
- `std/oids` now uses `int64` to store time internally (before, it was int32).
- `std/uri.Uri` dollar (`$`) improved, precalculates the `string` result length from the `Uri`.
- `std/uri.Uri.isIpv6` is now exported.
- `std/logging.ConsoleLogger` and `FileLogger` now have a `flushThreshold` attribute to set what log message levels are automatically flushed. For Nim v1 use `-d:nimFlushAllLogs` to automatically flush all message levels. Flushing all logs is the default behavior for Nim v2.
- `std/jsfetch.newFetchOptions` now has default values for all parameters.
- `std/jsformdata` now accepts the `Blob` data type.
- `std/sharedlist` and `std/sharedtables` are now deprecated, see [RFC #433](https://github.com/nim-lang/RFCs/issues/433).
- There is a new compile flag (`-d:nimNoGetRandom`) when building `std/sysrand` to remove the dependency on the Linux `getrandom` syscall.
This compile flag only affects Linux builds and is necessary if either compiling on a Linux kernel version < 3.17, or if code built will be executing on kernel < 3.17.
On Linux kernels < 3.17 (such as kernel 3.10 in RHEL7 and CentOS7), the `getrandom` syscall was not yet introduced. Without this, the `std/sysrand` module will not build properly, and if code is built on a kernel >= 3.17 without the flag, any usage of the `std/sysrand` module will fail to execute on a kernel < 3.17 (since it attempts to perform a syscall to `getrandom`, which isn't present in the current kernel). A compile flag has been added to force the `std/sysrand` module to use /dev/urandom (available since Linux kernel 1.3.30), rather than the `getrandom` syscall. This allows for use of a cryptographically secure PRNG, regardless of kernel support for the `getrandom` syscall.
When building for RHEL7/CentOS7 for example, the entire build process for nim from a source package would then be:
```sh
$ yum install devtoolset-8 # Install GCC version 8 vs the standard 4.8.5 on RHEL7/CentOS7. Alternatively use -d:nimEmulateOverflowChecks. See issue #13692 for details
$ scl enable devtoolset-8 bash # Run bash shell with default toolchain of gcc 8
$ sh build.sh # per unix install instructions
$ bin/nim c koch # per unix install instructions
$ ./koch boot -d:release # per unix install instructions
$ ./koch tools -d:nimNoGetRandom # pass the nimNoGetRandom flag to compile std/sysrand without support for getrandom syscall
```
This is necessary to pass when building Nim on kernel versions < 3.17 in particular to avoid an error of "SYS_getrandom undeclared" during the build process for the stdlib (`sysrand` in particular).
[//]: # "Additions:"
- Added ISO 8601 week date utilities in `times`:
- Added `IsoWeekRange`, a range type for weeks in a week-based year.
- Added `IsoYear`, a distinct type for a week-based year in contrast to a regular year.
- Added an `initDateTime` overload to create a `DateTime` from an ISO week date.
- Added `getIsoWeekAndYear` to get an ISO week number and week-based year from a datetime.
- Added `getIsoWeeksInYear` to return the number of weeks in a week-based year.
- Added new modules which were previously part of `std/os`:
- Added `std/oserrors` for OS error reporting.
- Added `std/envvars` for environment variables handling.
- Added `std/cmdline` for reading command line parameters.
- Added `std/paths`, `std/dirs`, `std/files`, `std/symlinks` and `std/appdirs`.
- Added `sep` parameter in `std/uri` to specify the query separator.
- Added `UppercaseLetters`, `LowercaseLetters`, `PunctuationChars`, `PrintableChars` sets to `std/strutils`.
- Added `complex.sgn` for obtaining the phase of complex numbers.
- Added `insertAdjacentText`, `insertAdjacentElement`, `insertAdjacentHTML`,
`after`, `before`, `closest`, `append`, `hasAttributeNS`, `removeAttributeNS`,
`hasPointerCapture`, `releasePointerCapture`, `requestPointerLock`,
`replaceChildren`, `replaceWith`, `scrollIntoViewIfNeeded`, `setHTML`,
`toggleAttribute`, and `matches` to `std/dom`.
- Added [`jsre.hasIndices`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/hasIndices).
- Added `capacity` for `string` and `seq` to return the current capacity, see [RFC #460](https://github.com/nim-lang/RFCs/issues/460).
- Added `openArray[char]` overloads for `std/parseutils` and `std/unicode`, allowing for more code reuse.
- Added a `safe` parameter to `base64.encodeMime`.
- Added `parseutils.parseSize` - inverse to `strutils.formatSize` - to parse human readable sizes.
- Added `minmax` to `sequtils`, as a more efficient `(min(_), max(_))` over sequences.
- `std/jscore` for the JavaScript target:
+ Added bindings to [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
and [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask).
+ Added `toDateString`, `toISOString`, `toJSON`, `toTimeString`, `toUTCString` converters for `DateTime`.
- Added `BackwardsIndex` overload for `CacheSeq`.
- Added support for nested `with` blocks in `std/with`.
- Added `ensureMove` to the system module. It ensures that the passed argument is moved, otherwise an error is given at the compile time.
[//]: # "Deprecations:"
- Deprecated `selfExe` for Nimscript.
- Deprecated `std/base64.encode` for collections of arbitrary integer element type.
Now only `byte` and `char` are supported.
[//]: # "Removals:"
- Removed deprecated module `parseopt2`.
- Removed deprecated module `sharedstrings`.
- Removed deprecated module `dom_extensions`.
- Removed deprecated module `LockFreeHash`.
- Removed deprecated module `events`.
- Removed deprecated `oids.oidToString`.
- Removed define `nimExperimentalAsyncjsThen` for `std/asyncjs.then` and `std/jsfetch`.
- Removed deprecated `jsre.test` and `jsre.toString`.
- Removed deprecated `math.c_frexp`.
- Removed deprecated `` httpcore.`==` ``.
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that take wrong argument types.
- Removed deprecated `osproc.poDemon`, symbol with typo.
- Removed deprecated `tables.rightSize`.
- Removed deprecated `posix.CLONE_STOPPED`.
## Language changes
- [Tag tracking](https://nim-lang.github.io/Nim/manual.html#effect-system-tag-tracking) now supports the definition of forbidden tags by the `.forbids` pragma
which can be used to disable certain effects in proc types.
- [Case statement macros](https://nim-lang.github.io/Nim/manual.html#macros-case-statement-macros) are no longer experimental,
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.
- Full command syntax and block arguments i.e. `foo a, b: c` are now allowed
for the right-hand side of type definitions in type sections. Previously
they would error with "invalid indentation".
- Compile-time define changes:
- `defined` now accepts identifiers separated by dots, i.e. `defined(a.b.c)`.
In the command line, this is defined as `-d:a.b.c`. Older versions can
use backticks as in ``defined(`a.b.c`)`` to access such defines.
- [Define pragmas for constants](https://nim-lang.github.io/Nim/manual.html#implementation-specific-pragmas-compileminustime-define-pragmas)
now support a string argument for qualified define names.
```nim
# -d:package.FooBar=42
const FooBar {.intdefine: "package.FooBar".}: int = 5
echo FooBar # 42
```
This was added to help disambiguate similar define names for different packages.
In older versions, this could only be achieved with something like the following:
```nim
const FooBar = block:
const `package.FooBar` {.intdefine.}: int = 5
`package.FooBar`
```
- A generic `define` pragma for constants has been added that interprets
the value of the define based on the type of the constant value.
See the [experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#generic-nimdefine-pragma)
for a list of supported types.
- [Macro pragmas](https://nim-lang.github.io/Nim/manual.html#userminusdefined-pragmas-macro-pragmas) changes:
- Templates now accept macro pragmas.
- Macro pragmas for var/let/const sections have been redesigned in a way that works
similarly to routine macro pragmas. The new behavior is documented in the
[experimental manual](https://nim-lang.github.io/Nim/manual_experimental.html#extended-macro-pragmas).
- Pragma macros on type definitions can now return `nnkTypeSection` nodes as well as `nnkTypeDef`,
allowing multiple type definitions to be injected in place of the original type definition.
```nim
import macros
macro multiply(amount: static int, s: untyped): untyped =
let name = $s[0].basename
result = newNimNode(nnkTypeSection)
for i in 1 .. amount:
result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
type
Foo = object
Bar {.multiply: 3.} = object
x, y, z: int
Baz = object
# becomes
type
Foo = object
Bar1 = object
x, y, z: int
Bar2 = object
x, y, z: int
Bar3 = object
x, y, z: int
Baz = object
```
- A new form of type inference called [top-down inference](https://nim-lang.github.io/Nim/manual_experimental.html#topminusdown-type-inference)
has been implemented for a variety of basic cases. For example, code like the following now compiles:
```nim
let foo: seq[(float, byte, cstring)] = @[(1, 2, "abc")]
```
- `cstring` is now accepted as a selector in `case` statements, removing the
need to convert to `string`. On the JS backend, this is translated directly
to a `switch` statement.
- Nim now supports `out` parameters and ["strict definitions"](https://nim-lang.github.io/Nim/manual_experimental.html#strict-definitions-and-nimout-parameters).
- Nim now offers a [strict mode](https://nim-lang.github.io/Nim/manual_experimental.html#strict-case-objects) for `case objects`.
- IBM Z architecture and macOS m1 arm64 architecture are supported.
- `=wasMoved` can now be overridden by users.
- There is a new pragma called [quirky](https://nim-lang.github.io/Nim/manual_experimental.html#quirky-routines) that can be used to affect the code
generation of goto based exception handling. It can improve the produced code size but its effects can be subtle so use it with care.
- Tuple unpacking for variables is now treated as syntax sugar that directly
expands into multiple assignments. Along with this, tuple unpacking for
variables can now be nested.
```nim
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
let (x, (_, y), _, z) = returnsNestedTuple()
# roughly becomes
let
tmpTup1 = returnsNestedTuple()
x = tmpTup1[0]
tmpTup2 = tmpTup1[1]
y = tmpTup2[1]
z = tmpTup1[3]
```
As a result `nnkVarTuple` nodes in variable sections will no longer be
reflected in `typed` AST.
- C++ interoperability:
- New [`virtual`](https://nim-lang.github.io/Nim/manual_experimental.html#virtual-pragma) pragma added.
- Improvements to [`constructor`](https://nim-lang.github.io/Nim/manual_experimental.html#constructor-pragma) pragma.
## Compiler changes
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
reality better. (Nim moved away from all techniques based on "tracing".)
- Defines the `gcRefc` symbol which allows writing specific code for the refc GC.
- `nim` can now compile version 1.4.0 as follows: `nim c --lib:lib --stylecheck:off compiler/nim`,
without requiring `-d:nimVersion140` which is now a noop.
- `--styleCheck`, `--hintAsError` and `--warningAsError` now only apply to the current package.
- The switch `--nimMainPrefix:prefix` has been added to add a prefix to the names of `NimMain` and
related functions produced on the backend. This prevents conflicts with other Nim
static libraries.
- When compiling for release, the flag `-fno-math-errno` is used for GCC.
- Removed deprecated `LineTooLong` hint.
- Line numbers and file names of source files work correctly inside templates for JavaScript targets.
- Removed support for LCC (Local C), Pelles C, Digital Mars and Watcom compilers.
## Docgen
- `Markdown` is now the default markup language of doc comments (instead
of the legacy `RstMarkdown` mode). In this release we begin to separate
RST and Markdown features to better follow specification of each
language, with the focus on Markdown development.
See also [the docs](https://nim-lang.github.io/Nim/markdown_rst.html).
* Added a `{.doctype: Markdown | RST | RstMarkdown.}` pragma allowing to
select the markup language mode in the doc comments of the current `.nim`
file for processing by `nim doc`:
1. `Markdown` (default) is basically CommonMark (standard Markdown) +
some Pandoc Markdown features + some RST features that are missing
in our current implementation of CommonMark and Pandoc Markdown.
2. `RST` closely follows the RST spec with few additional Nim features.
3. `RstMarkdown` is a maximum mix of RST and Markdown features, which
is kept for the sake of compatibility and ease of migration.
* Added separate `md2html` and `rst2html` commands for processing
standalone `.md` and `.rst` files respectively (and also `md2tex`/`rst2tex`).
- Added Pandoc Markdown bracket syntax `[...]` for making anchor-less links.
- Docgen now supports concise syntax for referencing Nim symbols:
instead of specifying HTML anchors directly one can use original
Nim symbol declarations (adding the aforementioned link brackets
`[...]` around them).
* To use this feature across modules, a new `importdoc` directive was added.
Using this feature for referencing also helps to ensure that links
(inside one module or the whole project) are not broken.
- Added support for RST & Markdown quote blocks (blocks starting with `>`).
- Added a popular Markdown definition lists extension.
- Added Markdown indented code blocks (blocks indented by >= 4 spaces).
- Added syntax for additional parameters to Markdown code blocks:
```nim test="nim c $1"
...
```
## Tool changes
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs` before). Use `nimble develop --global` to create an old style link file in the special links directory documented at https://github.com/nim-lang/nimble#nimble-develop.
- nimgrep added the option `--inContext` (and `--notInContext`), which
allows to filter only matches with the context block containing a given pattern.
- nimgrep: names of options containing "include/exclude" are deprecated,
e.g. instead of `--includeFile` and `--excludeFile` we have
`--filename` and `--notFilename` respectively.
Also the semantics are now consistent for such positive/negative filters.
- koch now supports the `--skipIntegrityCheck` option. The command `koch --skipIntegrityCheck boot -d:release` always builds the compiler twice.

View File

@@ -58,7 +58,11 @@ _nimNumCpu(){
# FreeBSD | macOS: $(sysctl -n hw.ncpu)
# OpenBSD: $(sysctl -n hw.ncpuonline)
# windows: $NUMBER_OF_PROCESSORS ?
echo $(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
if env | grep -q '^NIMCORES='; then
echo $NIMCORES
else
echo $(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
fi
}
_nimBuildCsourcesIfNeeded(){

View File

@@ -10,7 +10,7 @@
# abstract syntax tree + symbol table
import
lineinfos, hashes, options, ropes, idents, int128, tables
lineinfos, hashes, options, ropes, idents, int128, tables, wordrecg
from strutils import toLowerAscii
when defined(nimPreviewSlimSystem):
@@ -227,11 +227,12 @@ type
nkModuleRef # for .rod file support: A (moduleId, itemId) pair
nkReplayAction # for .rod file support: A replay action
nkNilRodNode # for .rod file support: a 'nil' PNode
nkOpenSym # container for captured sym that can be overriden by local symbols
TNodeKinds* = set[TNodeKind]
type
TSymFlag* = enum # 49 flags!
TSymFlag* = enum # 52 flags!
sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed
@@ -283,7 +284,7 @@ type
sfNamedParamCall, # symbol needs named parameter call syntax in target
# language; for interfacing with Objective C
sfDiscardable, # returned value may be discarded implicitly
sfOverriden, # proc is overridden
sfOverridden, # proc is overridden
sfCallsite # A flag for template symbols to tell the
# compiler it should use line information from
# the calling side of the macro, not from the
@@ -303,6 +304,8 @@ type
sfUsedInFinallyOrExcept # symbol is used inside an 'except' or 'finally'
sfSingleUsedTemp # For temporaries that we know will only be used once
sfNoalias # 'noalias' annotation, means C's 'restrict'
# for templates and macros, means cannot be called
# as a lone symbol (cannot use alias syntax)
sfEffectsDelayed # an 'effectsDelayed' parameter
sfGeneratedType # A anonymous generic type that is generated by the compiler for
# objects that do not have generic parameters in case one of the
@@ -310,6 +313,10 @@ type
#
# This is disallowed but can cause the typechecking to go into
# an infinite loop, this flag is used as a sentinel to stop it.
sfVirtual # proc is a C++ virtual function
sfByCopy # param is marked as pass bycopy
sfCodegenDecl # type, proc, global or proc param is marked as codegenDecl
sfWasGenSym # symbol was 'gensym'ed
TSymFlags* = set[TSymFlag]
@@ -335,8 +342,8 @@ const
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
sfExperimental* = sfOverriden # module uses the .experimental switch
sfGoto* = sfOverriden # var is used for 'goto' code generation
sfExperimental* = sfOverridden # module uses the .experimental switch
sfGoto* = sfOverridden # var is used for 'goto' code generation
sfWrittenTo* = sfBorrow # param is assigned to
# currently unimplemented
sfBase* = sfDiscriminant
@@ -510,10 +517,13 @@ type
nfLastRead # this node is a last read
nfFirstWrite # this node is a first write
nfHasComment # node has a comment
nfUseDefaultField # node has a default value (object constructor)
nfSkipFieldChecking # node skips field visable checking
nfDisabledOpenSym # temporary: node should be nkOpenSym but cannot
# because openSym experimental switch is disabled
# gives warning instead
TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 46)
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 47)
tfVarargs, # procedure has C styled varargs
# tyArray type represeting a varargs list
tfNoSideEffect, # procedure type does not allow side effects
@@ -583,6 +593,8 @@ type
tfIsConstructor
tfEffectSystemWorkaround
tfIsOutParam
tfSendable
tfImplicitStatic
TTypeFlags* = set[TTypeFlag]
@@ -618,13 +630,12 @@ type
# file (it is loaded on demand, which may
# mean: never)
skPackage, # symbol is a package (used for canonicalization)
skAlias # an alias (needs to be resolved immediately)
TSymKinds* = set[TSymKind]
const
routineKinds* = {skProc, skFunc, skMethod, skIterator,
skConverter, skMacro, skTemplate}
ExportableSymKinds* = {skVar, skLet, skConst, skType, skEnumField, skStub, skAlias} + routineKinds
ExportableSymKinds* = {skVar, skLet, skConst, skType, skEnumField, skStub} + routineKinds
tfUnion* = tfNoSideEffect
tfGcSafe* = tfThread
@@ -685,7 +696,7 @@ type
mIsPartOf, mAstToStr, mParallel,
mSwap, mIsNil, mArrToSeq, mOpenArrayToSeq,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy, mTrace,
mMove, mEnsureMove, mWasMoved, mDup, mDestroy, mTrace,
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mAccessTypeField, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
@@ -706,13 +717,13 @@ type
mNctPut, mNctLen, mNctGet, mNctHasNext, mNctNext,
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetStrVal, mNLineInfo,
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mNSigHash, mNSizeOf,
mNBindSym, mNCallSite,
mEqIdent, mEqNimrodNode, mSameNodeType, mGetImpl, mNGenSym,
mNHint, mNWarning, mNError,
mInstantiationInfo, mGetTypeInfo, mGetTypeInfoV2,
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mRunnableExamples,
mNimvm, mIntDefine, mStrDefine, mBoolDefine, mGenericDefine, mRunnableExamples,
mException, mBuiltinType, mSymOwner, mUncheckedArray, mGetImplTransf,
mSymIsInstantiationOf, mNodeId, mPrivateAccess, mZeroDefault
@@ -796,6 +807,8 @@ type
ident*: PIdent
else:
sons*: TNodeSeq
when defined(nimsuggest):
endInfo*: TLineInfo
TStrTable* = object # a table[PIdent] of PSym
counter*: int
@@ -816,9 +829,6 @@ type
locOther # location is something other
TLocFlag* = enum
lfIndirect, # backend introduced a pointer
lfFullExternalName, # only used when 'conf.cmd == cmdNimfix': Indicates
# that the symbol has been imported via 'importc: "fullname"' and
# no format string.
lfNoDeepCopy, # no need for a deep copy
lfNoDecl, # do not declare it in C
lfDynamicLib, # link symbol to dynamic library
@@ -853,7 +863,7 @@ type
# keep in sync with PackedLib
kind*: TLibKind
generated*: bool # needed for the backends:
isOverriden*: bool
isOverridden*: bool
name*: Rope
path*: PNode # can be a string literal!
@@ -892,6 +902,9 @@ type
typ*: PType
name*: PIdent
info*: TLineInfo
when defined(nimsuggest):
endInfo*: TLineInfo
hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
owner*: PSym
flags*: TSymFlags
ast*: PNode # syntax tree of proc, iterator, etc.:
@@ -913,7 +926,9 @@ type
# for modules, an unique index corresponding
# to the module's fileIdx
# for variables a slot index for the evaluator
offset*: int # offset of record field
offset*: int32 # offset of record field
disamb*: int32 # disambiguation number; the basic idea is that
# `<procname>__<module>_<disamb>`
loc*: TLoc
annex*: PLib # additional fields (seldom used, so we use a
# reference to another object to save space)
@@ -921,7 +936,7 @@ type
cname*: string # resolved C declaration name in importc decl, e.g.:
# proc fun() {.importc: "$1aux".} => cname = funaux
constraint*: PNode # additional constraints like 'lit|result'; also
# misused for the codegenDecl pragma in the hope
# misused for the codegenDecl and virtual pragmas in the hope
# it won't cause problems
# for skModule the string literal to output for
# deprecated modules.
@@ -931,8 +946,10 @@ type
TTypeSeq* = seq[PType]
TTypeAttachedOp* = enum ## as usual, order is important here
attachedWasMoved,
attachedDestructor,
attachedAsgn,
attachedDup,
attachedSink,
attachedTrace,
attachedDeepCopy
@@ -1076,7 +1093,8 @@ const
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
nfFromTemplate, nfDefaultRefsParam,
nfExecuteOnReload, nfLastRead,
nfFirstWrite, nfUseDefaultField}
nfFirstWrite, nfSkipFieldChecking,
nfDisabledOpenSym}
namePos* = 0
patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2
@@ -1092,7 +1110,7 @@ const
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
nkCommand, nkCallStrLit, nkHiddenCallConv}
nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice,
nkClosedSymChoice}
nkClosedSymChoice, nkOpenSym}
nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit}
nkLiterals* = {nkCharLit..nkTripleStrLit}
@@ -1116,11 +1134,11 @@ const
proc getPIdent*(a: PNode): PIdent {.inline.} =
## Returns underlying `PIdent` for `{nkSym, nkIdent}`, or `nil`.
# xxx consider whether also returning the 1st ident for {nkOpenSymChoice, nkClosedSymChoice}
# which may simplify code.
case a.kind
of nkSym: a.sym.name
of nkIdent: a.ident
of nkOpenSymChoice, nkClosedSymChoice: a.sons[0].sym.name
of nkOpenSym: getPIdent(a.sons[0])
else: nil
const
@@ -1136,13 +1154,17 @@ type
symId*: int32
typeId*: int32
sealed*: bool
disambTable*: CountTable[PIdent]
const
PackageModuleId* = -3'i32
proc idGeneratorFromModule*(m: PSym): IdGenerator =
assert m.kind == skModule
result = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0)
result = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0, disambTable: initCountTable[PIdent]())
proc idGeneratorForPackage*(nextIdWillBe: int32): IdGenerator =
result = IdGenerator(module: PackageModuleId, symId: nextIdWillBe - 1'i32, typeId: 0, disambTable: initCountTable[PIdent]())
proc nextSymId*(x: IdGenerator): ItemId {.inline.} =
assert(not x.sealed)
@@ -1236,8 +1258,11 @@ proc getDeclPragma*(n: PNode): PNode =
proc extractPragma*(s: PSym): PNode =
## gets the pragma node of routine/type/var/let/const symbol `s`
if s.kind in routineKinds:
result = s.ast[pragmasPos]
if s.kind in routineKinds: # bug #24167
if s.ast[pragmasPos] != nil and s.ast[pragmasPos].kind != nkEmpty:
result = s.ast[pragmasPos]
else:
result = nil
elif s.kind in {skType, skVar, skLet, skConst}:
if s.ast != nil and s.ast.len > 0:
if s.ast[0].kind == nkPragmaExpr and s.ast[0].len > 1:
@@ -1334,11 +1359,15 @@ when false:
echo k
echo v
proc newSym*(symKind: TSymKind, name: PIdent, id: ItemId, owner: PSym,
proc newSym*(symKind: TSymKind, name: PIdent, idgen: IdGenerator; owner: PSym,
info: TLineInfo; options: TOptions = {}): PSym =
# generates a symbol and initializes the hash field too
assert not name.isNil
let id = nextSymId idgen
result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id,
options: options, owner: owner, offset: defaultOffset)
options: options, owner: owner, offset: defaultOffset,
disamb: getOrDefault(idgen.disambTable, name).int32)
idgen.disambTable.inc name
when false:
if id.module == 48 and id.item == 39:
writeStackTrace()
@@ -1431,6 +1460,9 @@ proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
result.typ = sym.typ
result.info = info
proc newOpenSym*(n: PNode): PNode {.inline.} =
result = newTreeI(nkOpenSym, n.info, n)
proc newIntNode*(kind: TNodeKind, intVal: BiggestInt): PNode =
result = newNode(kind)
result.intVal = intVal
@@ -1439,7 +1471,42 @@ proc newIntNode*(kind: TNodeKind, intVal: Int128): PNode =
result = newNode(kind)
result.intVal = castToInt64(intVal)
proc lastSon*(n: Indexable): Indexable = n.sons[^1]
proc lastSon*(n: Indexable): Indexable {.inline.} = n.sons[^1]
template setLastSon*(n: PNode, s: PNode) = n.sons[^1] = s
template firstSon*(n: PNode): PNode = n.sons[0]
template secondSon*(n: PNode): PNode = n.sons[1]
template hasSon*(n: PNode): bool = n.len > 0
template has2Sons*(n: PNode): bool = n.len > 1
proc replaceFirstSon*(n, newson: PNode) {.inline.} =
n.sons[0] = newson
proc replaceSon*(n: PNode; i: int; newson: PNode) {.inline.} =
n.sons[i] = newson
proc last*(n: PType): PType {.inline.} = n.sons[^1]
proc elementType*(n: PType): PType {.inline.} = n.sons[^1]
proc skipModifier*(n: PType): PType {.inline.} = n.sons[^1]
proc indexType*(n: PType): PType {.inline.} = n.sons[0]
proc baseClass*(n: PType): PType {.inline.} = n.sons[0]
proc base*(t: PType): PType {.inline.} =
result = t.sons[0]
proc returnType*(n: PType): PType {.inline.} = n.sons[0]
proc setReturnType*(n, r: PType) {.inline.} = n.sons[0] = r
proc setIndexType*(n, idx: PType) {.inline.} = n.sons[0] = idx
proc firstParamType*(n: PType): PType {.inline.} = n.sons[1]
proc firstGenericParam*(n: PType): PType {.inline.} = n.sons[1]
proc typeBodyImpl*(n: PType): PType {.inline.} = n.sons[^1]
proc genericHead*(n: PType): PType {.inline.} = n.sons[0]
proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
## Used throughout the compiler code to test whether a type tree contains or
@@ -1447,7 +1514,7 @@ proc skipTypes*(t: PType, kinds: TTypeKinds): PType =
## last child nodes of a type tree need to be searched. This is a really hot
## path within the compiler!
result = t
while result.kind in kinds: result = lastSon(result)
while result.kind in kinds: result = last(result)
proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
let kind = skipTypes(typ, abstractVarRange).kind
@@ -1498,7 +1565,7 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
const
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
"=destroy", "=copy", "=sink", "=trace", "=deepcopy"]
"=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"]
proc `$`*(s: PSym): string =
if s != nil:
@@ -1506,6 +1573,107 @@ proc `$`*(s: PSym): string =
else:
result = "<nil>"
when false:
iterator items*(t: PType): PType =
for i in 0..<t.sons.len: yield t.sons[i]
iterator pairs*(n: PType): tuple[i: int, n: PType] =
for i in 0..<n.sons.len: yield (i, n.sons[i])
when true:
proc len*(n: PType): int {.inline.} =
result = n.sons.len
proc sameTupleLengths*(a, b: PType): bool {.inline.} =
result = a.sons.len == b.sons.len
iterator tupleTypePairs*(a, b: PType): (int, PType, PType) =
for i in 0 ..< a.sons.len:
yield (i, a.sons[i], b.sons[i])
iterator underspecifiedPairs*(a, b: PType; start = 0; without = 0): (PType, PType) =
# XXX Figure out with what typekinds this is called.
for i in start ..< min(a.sons.len, b.sons.len) + without:
yield (a.sons[i], b.sons[i])
proc signatureLen*(t: PType): int {.inline.} =
result = t.sons.len
proc paramsLen*(t: PType): int {.inline.} =
result = t.sons.len - 1
proc genericParamsLen*(t: PType): int {.inline.} =
assert t.kind == tyGenericInst
result = t.sons.len - 2 # without 'head' and 'body'
proc genericInvocationParamsLen*(t: PType): int {.inline.} =
assert t.kind == tyGenericInvocation
result = t.sons.len - 1 # without 'head'
proc kidsLen*(t: PType): int {.inline.} =
result = t.sons.len
proc genericParamHasConstraints*(t: PType): bool {.inline.} = t.sons.len > 0
proc hasElementType*(t: PType): bool {.inline.} = t.sons.len > 0
proc isEmptyTupleType*(t: PType): bool {.inline.} = t.sons.len == 0
proc isSingletonTupleType*(t: PType): bool {.inline.} = t.sons.len == 1
proc genericConstraint*(t: PType): PType {.inline.} = t.sons[0]
iterator genericInstParams*(t: PType): (bool, PType) =
for i in 1..<t.sons.len-1:
yield (i!=1, t.sons[i])
iterator genericInstParamPairs*(a, b: PType): (int, PType, PType) =
for i in 1..<min(a.sons.len, b.sons.len)-1:
yield (i-1, a.sons[i], b.sons[i])
iterator genericInvocationParams*(t: PType): (bool, PType) =
for i in 1..<t.sons.len:
yield (i!=1, t.sons[i])
iterator genericInvocationAndBodyElements*(a, b: PType): (PType, PType) =
for i in 1..<a.sons.len:
yield (a.sons[i], b.sons[i-1])
iterator genericInvocationParamPairs*(a, b: PType): (bool, PType, PType) =
for i in 1..<a.sons.len:
if i >= b.sons.len:
yield (false, nil, nil)
else:
yield (true, a.sons[i], b.sons[i])
iterator genericBodyParams*(t: PType): (int, PType) =
for i in 0..<t.sons.len-1:
yield (i, t.sons[i])
iterator userTypeClassInstParams*(t: PType): (bool, PType) =
for i in 1..<t.sons.len-1:
yield (i!=1, t.sons[i])
iterator ikids*(t: PType): (int, PType) =
for i in 0..<t.sons.len: yield (i, t.sons[i])
const
FirstParamAt* = 1
FirstGenericParamAt* = 1
iterator paramTypes*(t: PType): (int, PType) =
for i in FirstParamAt..<t.sons.len: yield (i, t.sons[i])
iterator paramTypePairs*(a, b: PType): (PType, PType) =
for i in FirstParamAt..<a.sons.len: yield (a.sons[i], b.sons[i])
template paramTypeToNodeIndex*(x: int): int = x
iterator kids*(t: PType): PType =
for i in 0..<t.sons.len: yield t.sons[i]
iterator signature*(t: PType): PType =
# yields return type + parameter types
for i in 0..<t.sons.len: yield t.sons[i]
proc newType*(kind: TTypeKind, id: ItemId; owner: PSym): PType =
result = PType(kind: kind, owner: owner, size: defaultSize,
align: defaultAlignment, itemId: id,
@@ -1552,8 +1720,8 @@ proc copyType*(t: PType, id: ItemId, owner: PSym): PType =
proc exactReplica*(t: PType): PType =
result = copyType(t, t.itemId, t.owner)
proc copySym*(s: PSym; id: ItemId): PSym =
result = newSym(s.kind, s.name, id, s.owner, s.info, s.options)
proc copySym*(s: PSym; idgen: IdGenerator): PSym =
result = newSym(s.kind, s.name, idgen, s.owner, s.info, s.options)
#result.ast = nil # BUGFIX; was: s.ast which made problems
result.typ = s.typ
result.flags = s.flags
@@ -1568,9 +1736,9 @@ proc copySym*(s: PSym; id: ItemId): PSym =
result.bitsize = s.bitsize
result.alignment = s.alignment
proc createModuleAlias*(s: PSym, id: ItemId, newIdent: PIdent, info: TLineInfo;
proc createModuleAlias*(s: PSym, idgen: IdGenerator, newIdent: PIdent, info: TLineInfo;
options: TOptions): PSym =
result = newSym(s.kind, newIdent, id, s.owner, info, options)
result = newSym(s.kind, newIdent, idgen, s.owner, info, options)
# keep ID!
result.ast = s.ast
#result.id = s.id # XXX figure out what to do with the ID.
@@ -1616,7 +1784,7 @@ proc skipTypes*(t: PType, kinds: TTypeKinds; maxIters: int): PType =
result = t
var i = maxIters
while result.kind in kinds:
result = lastSon(result)
result = last(result)
dec i
if i == 0: return nil
@@ -1625,7 +1793,7 @@ proc skipTypesOrNil*(t: PType, kinds: TTypeKinds): PType =
result = t
while result != nil and result.kind in kinds:
if result.len == 0: return nil
result = lastSon(result)
result = last(result)
proc isGCedMem*(t: PType): bool {.inline.} =
result = t.kind in {tyString, tyRef, tySequence} or
@@ -1690,6 +1858,8 @@ proc copyNode*(src: PNode): PNode =
of nkIdent: result.ident = src.ident
of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
else: discard
when defined(nimsuggest):
result.endInfo = src.endInfo
template transitionNodeKindCommon(k: TNodeKind) =
let obj {.inject.} = n[]
@@ -1742,6 +1912,8 @@ template copyNodeImpl(dst, src, processSonsStmt) =
if src == nil: return
dst = newNode(src.kind)
dst.info = src.info
when defined(nimsuggest):
result.endInfo = src.endInfo
dst.typ = src.typ
dst.flags = src.flags * PersistentNodeFlags
dst.comment = src.comment
@@ -1890,13 +2062,15 @@ proc skipGenericOwner*(s: PSym): PSym =
## Generic instantiations are owned by their originating generic
## symbol. This proc skips such owners and goes straight to the owner
## of the generic itself (the module or the enclosing proc).
result = if s.kind in skProcKinds and sfFromGeneric in s.flags:
result = if s.kind == skModule:
s
elif s.kind in skProcKinds and sfFromGeneric in s.flags and s.owner.kind != skModule:
s.owner.owner
else:
s.owner
proc originatingModule*(s: PSym): PSym =
result = s.owner
result = s
while result.kind != skModule: result = result.owner
proc isRoutine*(s: PSym): bool {.inline.} =
@@ -1906,20 +2080,6 @@ proc isCompileTimeProc*(s: PSym): bool {.inline.} =
result = s.kind == skMacro or
s.kind in {skProc, skFunc} and sfCompileTime in s.flags
proc isRunnableExamples*(n: PNode): bool =
# Templates and generics don't perform symbol lookups.
result = n.kind == nkSym and n.sym.magic == mRunnableExamples or
n.kind == nkIdent and n.ident.s == "runnableExamples"
proc requiredParams*(s: PSym): int =
# Returns the number of required params (without default values)
# XXX: Perhaps we can store this in the `offset` field of the
# symbol instead?
for i in 1..<s.typ.len:
if s.typ.n[i].sym.ast != nil:
return i - 1
return s.typ.len - 1
proc hasPattern*(s: PSym): bool {.inline.} =
result = isRoutine(s) and s.ast[patternPos].kind != nkEmpty
@@ -1972,7 +2132,7 @@ proc toObject*(typ: PType): PType =
## cases should be a ``tyObject``).
## Otherwise ``typ`` is simply returned as-is.
let t = typ.skipTypes({tyAlias, tyGenericInst})
if t.kind == tyRef: t.lastSon
if t.kind == tyRef: t.elementType
else: typ
proc toObjectFromRefPtrGeneric*(typ: PType): PType =
@@ -1989,11 +2149,11 @@ proc toObjectFromRefPtrGeneric*(typ: PType): PType =
result = typ
while true:
case result.kind
of tyGenericBody: result = result.lastSon
of tyGenericBody: result = result.last
of tyRef, tyPtr, tyGenericInst, tyGenericInvocation, tyAlias: result = result[0]
# automatic dereferencing is deep, refs #18298.
else: break
assert result.sym != nil
# result does not have to be object type
proc isImportedException*(t: PType; conf: ConfigRef): bool =
assert t != nil
@@ -2007,7 +2167,7 @@ proc isImportedException*(t: PType; conf: ConfigRef): bool =
result = true
proc isInfixAs*(n: PNode): bool =
return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s == "as"
return n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.id == ord(wAs)
proc skipColon*(n: PNode): PNode =
result = n
@@ -2015,10 +2175,12 @@ proc skipColon*(n: PNode): PNode =
result = n[1]
proc findUnresolvedStatic*(n: PNode): PNode =
# n.typ == nil: see issue #14802
if n.kind == nkSym and n.typ != nil and n.typ.kind == tyStatic and n.typ.n == nil:
return n
if n.typ != nil and n.typ.kind == tyTypeDesc:
let t = skipTypes(n.typ, {tyTypeDesc})
if t.kind == tyGenericParam and t.len == 0:
return n
for son in n:
let n = son.findUnresolvedStatic
if n != nil: return n
@@ -2047,12 +2209,21 @@ template detailedInfo*(sym: PSym): string =
proc isInlineIterator*(typ: PType): bool {.inline.} =
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv != ccClosure
proc isIterator*(typ: PType): bool {.inline.} =
typ.kind == tyProc and tfIterator in typ.flags
proc isClosureIterator*(typ: PType): bool {.inline.} =
typ.kind == tyProc and tfIterator in typ.flags and typ.callConv == ccClosure
proc isClosure*(typ: PType): bool {.inline.} =
typ.kind == tyProc and typ.callConv == ccClosure
proc isNimcall*(s: PSym): bool {.inline.} =
s.typ.callConv == ccNimCall
proc isExplicitCallConv*(s: PSym): bool {.inline.} =
tfExplicitCallConv in s.typ.flags
proc isSinkParam*(s: PSym): bool {.inline.} =
s.kind == skParam and (s.typ.kind == tySink or tfHasOwned in s.typ.flags)

View File

@@ -20,9 +20,6 @@ import strutils except addf
when defined(nimPreviewSlimSystem):
import std/assertions
when not defined(nimHasCursor):
{.pragma: cursor.}
proc hashNode*(p: RootRef): Hash
proc treeToYaml*(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope
# Convert a tree into its YAML representation; this is used by the
@@ -333,7 +330,7 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
sonsRope = rope("null")
elif containsOrIncl(marker, n.id):
sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
strutils.toHex(cast[int](n), sizeof(n) * 2))]
else:
if n.len > 0:
sonsRope = rope("[")

View File

@@ -24,6 +24,12 @@ proc addDeclaredLoc*(result: var string, conf: ConfigRef; typ: PType) =
result.add " declared in " & toFileLineCol(conf, typ.sym.info)
result.add "]"
proc addTypeNodeDeclaredLoc*(result: var string, conf: ConfigRef; typ: PType) =
result.add " [$1" % typ.kind.toHumanStr
if typ.sym != nil:
result.add " declared in " & toFileLineCol(conf, typ.sym.info)
result.add "]"
proc addDeclaredLocMaybe*(result: var string, conf: ConfigRef; typ: PType) =
if optDeclaredLocs in conf.globalOptions: addDeclaredLoc(result, conf, typ)

View File

@@ -0,0 +1,25 @@
import pragmas, options, ast, trees
proc pushBackendOption(optionsStack: var seq[TOptions], options: var TOptions) =
optionsStack.add options
proc popBackendOption(optionsStack: var seq[TOptions], options: var TOptions) =
options = optionsStack[^1]
optionsStack.setLen(optionsStack.len-1)
proc processPushBackendOption*(optionsStack: var seq[TOptions], options: var TOptions,
n: PNode, start: int) =
pushBackendOption(optionsStack, options)
for i in start..<n.len:
let it = n[i]
if it.kind in nkPragmaCallKinds and it.len == 2 and it[1].kind == nkIntLit:
let sw = whichPragma(it[0])
let opts = pragmaToOptions(sw)
if opts != {}:
if it[1].intVal != 0:
options.incl opts
else:
options.excl opts
template processPopBackendOption*(optionsStack: var seq[TOptions], options: var TOptions) =
popBackendOption(optionsStack, options)

View File

@@ -68,7 +68,7 @@ proc copyHalf[Key, Val](h, result: Node[Key, Val]) =
result.links[j] = h.links[Mhalf + j]
else:
for j in 0..<Mhalf:
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
result.vals[j] = move h.vals[Mhalf + j]
else:
shallowCopy(result.vals[j], h.vals[Mhalf + j])
@@ -91,7 +91,7 @@ proc insert[Key, Val](h: Node[Key, Val], key: Key, val: Val): Node[Key, Val] =
if less(key, h.keys[j]): break
inc j
for i in countdown(h.entries, j+1):
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
h.vals[i] = move h.vals[i-1]
else:
shallowCopy(h.vals[i], h.vals[i-1])

View File

@@ -24,6 +24,7 @@ proc canRaiseDisp(p: BProc; n: PNode): bool =
proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
proc locationEscapes(p: BProc; le: PNode; inTryStmt: bool): bool =
result = false
var n = le
while true:
# do NOT follow nkHiddenDeref here!
@@ -82,6 +83,10 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
# getUniqueType() is too expensive here:
var typ = skipTypes(ri[0].typ, abstractInst)
if typ[0] != nil:
var flags: TAssignmentFlags = {}
if typ[0].kind in {tyOpenArray, tyVarargs}:
# perhaps generate no temp if the call doesn't have side effects
flags.incl needTempForOpenArray
if isInvalidReturnType(p.config, typ):
if params.len != 0: pl.add(", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
@@ -129,7 +134,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
genAssignment(p, d, list, flags) # no need for deep copying
if canRaise: raiseExit(p)
else:
var tmp: TLoc
@@ -137,7 +142,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, tmp, list, {}) # no need for deep copying
genAssignment(p, tmp, list, flags) # no need for deep copying
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {})
else:
@@ -145,26 +150,37 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
line(p, cpsStmts, pl)
if canRaise: raiseExit(p)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType)
proc reifiedOpenArray(n: PNode): bool {.inline.} =
var x = n
while x.kind in {nkAddr, nkHiddenAddr, nkHiddenStdConv, nkHiddenDeref}:
x = x[0]
while true:
case x.kind
of {nkAddr, nkHiddenAddr, nkHiddenDeref}:
x = x[0]
of nkHiddenStdConv:
x = x[1]
else:
break
if x.kind == nkSym and x.sym.kind == skParam:
result = false
else:
result = true
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType): (Rope, Rope) =
proc genOpenArraySlice(p: BProc; q: PNode; formalType, destType: PType; prepareForMutation = false): (Rope, Rope) =
var a, b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
initLocExpr(p, q[3], c)
# bug #23321: In the function mapType, ptrs (tyPtr, tyVar, tyLent, tyRef)
# are mapped into ctPtrToArray, the dereference of which is skipped
# in the `genDeref`. We need to skip these ptrs here
let ty = skipTypes(a.t, abstractVar+{tyPtr, tyRef})
# but first produce the required index checks:
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
genBoundsCheck(p, a, b, c, ty)
if prepareForMutation:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
let dest = getTypeDesc(p.module, destType)
let lengthExpr = "($1)-($2)+1" % [rdLoc(c), rdLoc(b)]
case ty.kind
@@ -267,7 +283,7 @@ proc withTmpIfNeeded(p: BProc, a: TLoc, needsTmp: bool): TLoc =
# Bug https://github.com/status-im/nimbus-eth2/issues/1549
# Aliasing is preferred over stack overflows.
# Also don't regress for non ARC-builds, too risky.
if needsTmp and a.lode.typ != nil and p.config.selectedGC in {gcArc, gcOrc} and
if needsTmp and a.lode.typ != nil and p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc} and
getSize(p.config, a.lode.typ) < 1024:
getTemp(p, a.lode.typ, result, needsInit=false)
genAssignment(p, result, a, {})
@@ -290,7 +306,8 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
var n = if n.kind != nkHiddenAddr: n else: n[0]
openArrayLoc(p, param.typ, n, result)
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]) and
(optByRef notin param.options or not p.module.compileToCpp):
initLocExpr(p, n, a)
if n.kind in {nkCharLit..nkNilLit}:
addAddrLoc(p.config, literalsNeedsTmp(p, a), result)
@@ -298,18 +315,33 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
addAddrLoc(p.config, withTmpIfNeeded(p, a, needsTmp), result)
elif p.module.compileToCpp and param.typ.kind in {tyVar} and
n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n[0], a)
# bug #23748: we need to introduce a temporary here. The expression type
# will be a reference in C++ and we cannot create a temporary reference
# variable. Thus, we create a temporary pointer variable instead.
let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray
if needsIndirect:
n.typ = n.typ.exactReplica
n.typ.flags.incl tfVarIsPtr
initLocExprSingleUse(p, n, a)
a = withTmpIfNeeded(p, a, needsTmp)
if needsIndirect: a.flags.incl lfIndirect
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
# means '*T'. See posix.nim for lots of examples that do that in the wild.
let callee = call[0]
if callee.kind == nkSym and
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {} and
needsIndirect:
addAddrLoc(p.config, a, result)
else:
addRdLoc(a, result)
else:
initLocExprSingleUse(p, n, a)
if param.typ.kind in abstractPtrs:
let typ = skipTypes(param.typ, abstractPtrs)
if typ.sym != nil and sfImportc in typ.sym.flags:
a.r = "(($1) ($2))" %
[getTypeDesc(p.module, param.typ), rdCharLoc(a)]
addRdLoc(withTmpIfNeeded(p, a, needsTmp), result)
#assert result != nil
@@ -391,9 +423,11 @@ proc genParams(p: BProc, ri: PNode, typ: PType; result: var Rope) =
if not needTmp[i - 1]:
needTmp[i - 1] = potentialAlias(n, potentialWrites)
getPotentialWrites(ri[i], false, potentialWrites)
if ri[i].kind in {nkHiddenAddr, nkAddr}:
# Optimization: don't use a temp, if we would only take the address anyway
needTmp[i - 1] = false
when false:
# this optimization is wrong, see bug #23748
if ri[i].kind in {nkHiddenAddr, nkAddr}:
# Optimization: don't use a temp, if we would only take the address anyway
needTmp[i - 1] = false
var oldLen = result.len
for i in 1..<ri.len:
@@ -473,6 +507,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
discard "resetLoc(p, d)"
pl.add(addrLoc(p.config, d))
genCallPattern()
if canRaise: raiseExit(p)
else:
var tmp: TLoc
getTemp(p, typ[0], tmp, needsInit=true)

View File

@@ -285,15 +285,23 @@ proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
linefmt(p, cpsStmts, "#genericAssign((void*)$1, (void*)$2, $3);$n",
[addrLoc(p.config, dest), addrLoc(p.config, src), genTypeInfoV1(p.module, dest.t, dest.lode.info)])
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc) =
proc genOpenArrayConv(p: BProc; d: TLoc; a: TLoc; flags: TAssignmentFlags) =
assert d.k != locNone
# getTemp(p, d.t, d)
case a.t.skipTypes(abstractVar).kind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(a.lode):
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), a.rdLoc])
if needTempForOpenArray in flags:
var tmp: TLoc
getTemp(p, a.t, tmp)
linefmt(p, cpsStmts, "$2 = $1; $n",
[a.rdLoc, tmp.rdLoc])
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), tmp.rdLoc])
else:
linefmt(p, cpsStmts, "$1.Field0 = $2.Field0; $1.Field1 = $2.Field1;$n",
[rdLoc(d), a.rdLoc])
else:
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $2Len_0;$n",
[rdLoc(d), a.rdLoc])
@@ -336,7 +344,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
of tyString:
if optSeqDestructors in p.config.globalOptions:
genGenericAsgn(p, dest, src, flags)
elif (needToCopy notin flags and src.storage != OnStatic) or canMove(p, src.lode, dest):
elif ({needToCopy, needToCopySinkParam} * flags == {} and src.storage != OnStatic) or canMove(p, src.lode, dest):
genRefAssign(p, dest, src)
else:
if (dest.storage == OnStack and p.config.selectedGC != gcGo) or not usesWriteBarrier(p.config):
@@ -382,7 +390,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
else:
linefmt(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
of tyArray:
if containsGarbageCollectedRef(dest.t) and p.config.selectedGC notin {gcArc, gcOrc, gcHooks}:
if containsGarbageCollectedRef(dest.t) and p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc, gcHooks}:
genGenericAsgn(p, dest, src, flags)
else:
linefmt(p, cpsStmts,
@@ -392,7 +400,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
# open arrays are always on the stack - really? What if a sequence is
# passed to an open array?
if reifiedOpenArray(dest.lode):
genOpenArrayConv(p, dest, src)
genOpenArrayConv(p, dest, src, flags)
elif containsGarbageCollectedRef(dest.t):
linefmt(p, cpsStmts, # XXX: is this correct for arrays?
"#genericAssignOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
@@ -401,7 +409,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
else:
linefmt(p, cpsStmts,
# bug #4799, keep the nimCopyMem for a while
#"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n",
#"#nimCopyMem((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);\n",
"$1 = $2;$n",
[rdLoc(dest), rdLoc(src)])
of tySet:
@@ -450,9 +458,10 @@ proc genDeepCopy(p: BProc; dest, src: TLoc) =
[addrLoc(p.config, dest), rdLoc(src),
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tyOpenArray, tyVarargs:
let source = addrLocOrTemp(src)
linefmt(p, cpsStmts,
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $1Len_0, $3);$n",
[addrLoc(p.config, dest), addrLocOrTemp(src),
"#genericDeepCopyOpenArray((void*)$1, (void*)$2, $2->Field1, $3);$n",
[addrLoc(p.config, dest), source,
genTypeInfoV1(p.module, dest.t, dest.lode.info)])
of tySet:
if mapSetType(p.config, ty) == ctArray:
@@ -593,7 +602,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
# skipping 'range' is correct here as we'll generate a proper range check
# later via 'chckRange'
let t = e.typ.skipTypes(abstractRange)
if optOverflowCheck notin p.options:
if optOverflowCheck notin p.options or (m in {mSucc, mPred} and t.kind in {tyUInt..tyUInt64}):
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
putIntoDest(p, d, e, res)
else:
@@ -615,7 +624,7 @@ proc binaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
if t.kind == tyInt64: prc64[m] else: prc[m])
putIntoDest(p, d, e, "($#)($#)" % [getTypeDesc(p.module, e.typ), res])
else:
let res = "($1)($2 $3 $4)" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
let res = "($1)(($2) $3 ($4))" % [getTypeDesc(p.module, e.typ), rdLoc(a), rope(opr[m]), rdLoc(b)]
putIntoDest(p, d, e, res)
proc unaryArithOverflow(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
@@ -752,23 +761,8 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
skipTypes(typ, abstractInstOwned).kind in {tyVar} and
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
proc derefBlock(p: BProc, e: PNode, d: var TLoc) =
# We transform (block: x)[] to (block: x[])
let e0 = e[0]
var n = shallowCopy(e0)
n.typ = e.typ
for i in 0 ..< e0.len - 1:
n[i] = e0[i]
n[e0.len-1] = newTreeIT(nkHiddenDeref, e.info, e.typ, e0[e0.len-1])
expr p, n, d
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
if e.kind == nkHiddenDeref and e[0].kind in {nkBlockExpr, nkBlockStmt}:
# bug #20107. Watch out to not deref the pointer too late.
derefBlock(p, e, d)
return
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]))
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam)
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:
# XXX the amount of hacks for C's arrays is incredible, maybe we should
# simply wrap them in a struct? --> Losing auto vectorization then?
@@ -836,8 +830,10 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
initLocExpr(p, e[0], a)
putIntoDest(p, d, e, "&" & a.r, a.storage)
#Message(e.info, warnUser, "HERE NEW &")
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0])) == ctArray or isCppRef(p, e.typ):
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ):
expr(p, e[0], d)
# bug #19497
d.lode = e
else:
var a: TLoc
initLocExpr(p, e[0], a)
@@ -945,10 +941,17 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
var discIndex = newRopeAppender()
rdSetElemLoc(p.config, v, u.t, discIndex)
if optTinyRtti in p.config.globalOptions:
# not sure how to use `genEnumToStr` here
if p.config.getStdlibVersion < (1, 5, 1):
const code = "{ #raiseFieldError($1); "
linefmt(p, cpsStmts, code, [strLit])
let base = disc.typ.skipTypes(abstractInst+{tyRange})
case base.kind
of tyEnum:
const code = "{ #raiseFieldErrorStr($1, $2); "
let toStrProc = getToStringProc(p.module.g.graph, base)
# XXX need to modify this logic for IC.
# need to analyze nkFieldCheckedExpr and marks procs "used" like range checks in dce
var toStr: TLoc
expr(p, newSymNode(toStrProc), toStr)
let enumStr = "$1($2)" % [rdLoc(toStr), rdLoc(v)]
linefmt(p, cpsStmts, code, [strLit, enumStr])
else:
const code = "{ #raiseFieldError2($1, (NI)$2); "
linefmt(p, cpsStmts, code, [strLit, discIndex])
@@ -959,12 +962,8 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) =
var firstLit = newRopeAppender()
int64Literal(cast[int](first), firstLit)
let discName = genTypeInfo(p.config, p.module, disc.sym.typ, e.info)
if p.config.getStdlibVersion < (1,5,1):
const code = "{ #raiseFieldError($1); "
linefmt(p, cpsStmts, code, [strLit])
else:
const code = "{ #raiseFieldError2($1, #reprDiscriminant(((NI)$2) + (NI)$3, $4)); "
linefmt(p, cpsStmts, code, [strLit, discIndex, firstLit, discName])
const code = "{ #raiseFieldError2($1, #reprDiscriminant(((NI)$2) + (NI)$3, $4)); "
linefmt(p, cpsStmts, code, [strLit, discIndex, firstLit, discName])
raiseInstr(p, p.s(cpsStmts))
linefmt p, cpsStmts, "}$n", []
@@ -1040,8 +1039,8 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
putIntoDest(p, d, n,
ropecg(p.module, "$1[$2]", [rdLoc(a), rdCharLoc(b)]), a.storage)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
let ty = skipTypes(arr.t, abstractVarRange)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc; arrTyp: PType) =
let ty = arrTyp
case ty.kind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(arr.lode):
@@ -1427,7 +1426,7 @@ proc rawGenNew(p: BProc, a: var TLoc, sizeExpr: Rope; needsInit: bool) =
p.module.s[cfsTypeInit3].addf("$1->finalizer = (void*)$2;$n", [ti, rdLoc(f)])
if a.storage == OnHeap and usesWriteBarrier(p.config):
if canFormAcycle(a.t):
if canFormAcycle(p.module.g.graph, a.t):
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [a.rdLoc])
else:
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [a.rdLoc])
@@ -1464,7 +1463,7 @@ proc genNewSeqAux(p: BProc, dest: TLoc, length: Rope; lenIsZero: bool) =
var call: TLoc
initLoc(call, locExpr, dest.lode, OnHeap)
if dest.storage == OnHeap and usesWriteBarrier(p.config):
if canFormAcycle(dest.t):
if canFormAcycle(p.module.g.graph, dest.t):
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefRC1($1); $1 = NIM_NIL; }$n", [dest.rdLoc])
else:
linefmt(p, cpsStmts, "if ($1) { #nimGCunrefNoCycle($1); $1 = NIM_NIL; }$n", [dest.rdLoc])
@@ -1507,11 +1506,12 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) =
initLocExpr(p, e[1], a)
if optSeqDestructors in p.config.globalOptions:
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false)
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayload($2, sizeof($3), NIM_ALIGNOF($3));$n",
linefmt(p, cpsStmts, "$1.len = 0; $1.p = ($4*) #newSeqPayloadUninit($2, sizeof($3), NIM_ALIGNOF($3));$n",
[d.rdLoc, a.rdLoc, getTypeDesc(p.module, seqtype.lastSon),
getSeqPayloadType(p.module, seqtype),
])
else:
if d.k == locNone: getTemp(p, e.typ, d, needsInit=false) # bug #22560
putIntoDest(p, d, e, ropecg(p.module,
"($1)#nimNewSeqOfCap($2, $3)", [
getTypeDesc(p.module, seqtype),
@@ -1561,6 +1561,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
var tmp: TLoc
var r: Rope
let needsZeroMem = p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc} or nfAllFieldsSet notin e.flags
if useTemp:
getTemp(p, t, tmp)
r = rdLoc(tmp)
@@ -1569,10 +1570,13 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
t = t.lastSon.skipTypes(abstractInstOwned)
r = "(*$1)" % [r]
gcUsage(p.config, e)
else:
elif needsZeroMem:
constructLoc(p, tmp)
else:
genObjectInit(p, cpsStmts, t, tmp, constructObj)
else:
resetLoc(p, d)
if needsZeroMem: resetLoc(p, d)
else: genObjectInit(p, cpsStmts, d.t, d, if isRef: constructRefObj else: constructObj)
r = rdLoc(d)
discard getTypeDesc(p.module, t)
let ty = getUniqueType(t)
@@ -1647,6 +1651,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
return
if d.k == locNone:
getTemp(p, n.typ, d)
initLocExpr(p, n[1], a)
# generate call to newSeq before adding the elements per hand:
let L = toInt(lengthOrd(p.config, n[1].typ))
if optSeqDestructors in p.config.globalOptions:
@@ -1658,7 +1663,6 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
var lit = newRopeAppender()
intLiteral(L, lit)
genNewSeqAux(p, d, lit, L == 0)
initLocExpr(p, n[1], a)
# bug #5007; do not produce excessive C source code:
if L < 10:
for i in 0..<L:
@@ -1704,7 +1708,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Rope) =
if optTinyRtti in p.config.globalOptions:
let token = $genDisplayElem(MD5Digest(hashType(dest)))
let token = $genDisplayElem(MD5Digest(hashType(dest, p.config)))
appcg(p.module, result, "#isObjDisplayCheck($#.m_type, $#, $#)", [a, getObjDepth(dest), token])
else:
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
@@ -1879,20 +1883,33 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
# Bug #9279, len(toOpenArray()) has to work:
if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice:
# magic: pass slice to openArray:
var m: TLoc
var b, c: TLoc
initLocExpr(p, a[1], m)
initLocExpr(p, a[2], b)
initLocExpr(p, a[3], c)
if optBoundsCheck in p.options:
genBoundsCheck(p, m, b, c, skipTypes(m.t, abstractVarRange))
if op == mHigh:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1))", [rdLoc(b), rdLoc(c)]))
else:
putIntoDest(p, d, e, ropecg(p.module, "($2)-($1)+1", [rdLoc(b), rdLoc(c)]))
putIntoDest(p, d, e, ropecg(p.module, "(($2)-($1)+1)", [rdLoc(b), rdLoc(c)]))
else:
if not reifiedOpenArray(a):
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
else: unaryExpr(p, e, d, "$1Len_0")
else:
if op == mHigh: unaryExpr(p, e, d, "($1.Field1-1)")
else: unaryExpr(p, e, d, "$1.Field1")
let isDeref = a.kind in {nkHiddenDeref, nkDerefExpr}
if op == mHigh:
if isDeref:
unaryExpr(p, e, d, "($1->Field1-1)")
else:
unaryExpr(p, e, d, "($1.Field1-1)")
else:
if isDeref:
unaryExpr(p, e, d, "$1->Field1")
else:
unaryExpr(p, e, d, "$1.Field1")
of tyCstring:
if op == mHigh: unaryExpr(p, e, d, "($1 ? (#nimCStrLen($1)-1) : -1)")
else: unaryExpr(p, e, d, "($1 ? #nimCStrLen($1) : 0)")
@@ -1917,10 +1934,6 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ)))
else: internalError(p.config, e.info, "genArrayLen()")
proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
result = newType(tyPtr, nextTypeId idgen, baseType.owner)
addSonSkipIntLit(result, baseType, idgen)
proc makeAddr(n: PNode; idgen: IdGenerator): PNode =
if n.kind == nkHiddenAddr:
result = n
@@ -1943,7 +1956,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
initLoc(call, locCall, e, OnHeap)
if not p.module.compileToCpp:
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)"
call.r = ropecg(p.module, setLenPattern, [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
@@ -2203,8 +2216,15 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
var lbl = p.labels.rope
var tmp: TLoc
tmp.r = "LOC$1.source" % [lbl]
linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
[getTypeDesc(p.module, e[1].typ), getTypeDesc(p.module, e.typ), lbl])
let destsize = getSize(p.config, destt)
let srcsize = getSize(p.config, srct)
if destsize > srcsize:
linefmt(p, cpsLocals, "union { $1 dest; $2 source; } LOC$3;$n #nimZeroMem(&LOC$3, sizeof(LOC$3));$n",
[getTypeDesc(p.module, e.typ), getTypeDesc(p.module, e[1].typ), lbl])
else:
linefmt(p, cpsLocals, "union { $1 source; $2 dest; } LOC$3;$n",
[getTypeDesc(p.module, e[1].typ), getTypeDesc(p.module, e.typ), lbl])
tmp.k = locExpr
tmp.lode = lodeTyp srct
tmp.storage = OnStack
@@ -2335,7 +2355,7 @@ proc genWasMoved(p: BProc; n: PNode) =
if p.withinBlockLeaveActions > 0 and notYetAlive(n1):
discard
else:
initLocExpr(p, n1, a)
initLocExpr(p, n1, a, {lfEnforceDeref})
resetLoc(p, a)
#linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
@@ -2352,8 +2372,38 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
linefmt(p, cpsStmts, "}$n$1.len = $2.len; $1.p = $2.p;$n", [rdLoc(a), rdLoc(src)])
else:
if d.k == locNone: getTemp(p, n.typ, d)
genAssignment(p, d, a, {})
resetLoc(p, a)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
genAssignment(p, d, a, {})
var op = getAttachedOp(p.module.g.graph, n.typ, attachedWasMoved)
if op == nil:
resetLoc(p, a)
else:
var b: TLoc
initLocExpr(p, newSymNode(op), b)
case skipTypes(a.t, abstractVar+{tyStatic}).kind
of tyOpenArray, tyVarargs: # todo fixme generated `wasMoved` hooks for
# openarrays, but it probably shouldn't?
var s: string
if reifiedOpenArray(a.lode):
if a.t.kind in {tyVar, tyLent}:
s = "$1->Field0, $1->Field1" % [rdLoc(a)]
else:
s = "$1.Field0, $1.Field1" % [rdLoc(a)]
else:
s = "$1, $1Len_0" % [rdLoc(a)]
linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), s])
else:
linefmt(p, cpsStmts, "$1($2);$n", [rdLoc(b), byRefLoc(p, a)])
else:
if n[1].kind == nkSym and isSinkParam(n[1].sym):
var tmp: TLoc
getTemp(p, n[1].typ.skipTypes({tySink}), tmp)
genAssignment(p, tmp, a, {needToCopySinkParam})
genAssignment(p, d, tmp, {})
resetLoc(p, tmp)
else:
genAssignment(p, d, a, {})
resetLoc(p, a)
proc genDestroy(p: BProc; n: PNode) =
if optSeqDestructors in p.config.globalOptions:
@@ -2404,7 +2454,10 @@ proc genDispose(p: BProc; n: PNode) =
lineCg(p, cpsStmts, ["#nimDestroyAndDispose($#)", rdLoc(a)])
proc genSlice(p: BProc; e: PNode; d: var TLoc) =
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon)
let (x, y) = genOpenArraySlice(p, e, e.typ, e.typ.lastSon,
prepareForMutation = e[1].kind == nkHiddenDeref and
e[1].typ.skipTypes(abstractInst).kind == tyString and
p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc})
if d.k == locNone: getTemp(p, e.typ, d)
linefmt(p, cpsStmts, "$1.Field0 = $2; $1.Field1 = $3;$n", [rdLoc(d), x, y])
when false:
@@ -2511,10 +2564,10 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mNewSeqOfCap: genNewSeqOfCap(p, e, d)
of mSizeOf:
let t = e[1].typ.skipTypes({tyTypeDesc})
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t, skVar)])
putIntoDest(p, d, e, "((NI)sizeof($1))" % [getTypeDesc(p.module, t, dkVar)])
of mAlignOf:
let t = e[1].typ.skipTypes({tyTypeDesc})
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t, skVar)])
putIntoDest(p, d, e, "((NI)NIM_ALIGNOF($1))" % [getTypeDesc(p.module, t, dkVar)])
of mOffsetOf:
var dotExpr: PNode
if e[1].kind == nkDotExpr:
@@ -2524,7 +2577,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
else:
internalError(p.config, e.info, "unknown ast")
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
let tname = getTypeDesc(p.module, t, skVar)
let tname = getTypeDesc(p.module, t, dkVar)
let member =
if t.kind == tyTuple:
"Field" & rope(dotExpr[1].sym.position)
@@ -2586,9 +2639,9 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
let n = semparallel.liftParallel(p.module.g.graph, p.module.idgen, p.module.module, e)
expr(p, n, d)
of mDeepCopy:
if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions:
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions:
localError(p.config, e.info,
"for --gc:arc|orc 'deepcopy' support has to be enabled with --deepcopy:on")
"for --mm:arc|atomicArc|orc 'deepcopy' support has to be enabled with --deepcopy:on")
var a, b: TLoc
let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
@@ -2603,6 +2656,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mAccessTypeField: genAccessTypeField(p, e, d)
of mSlice: genSlice(p, e, d)
of mTrace: discard "no code to generate"
of mEnsureMove:
expr(p, e[1], d)
else:
when defined(debugMagics):
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
@@ -2673,15 +2728,30 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
if not handleConstExpr(p, n, d):
let t = n.typ
discard getTypeDesc(p.module, t) # so that any fields are initialized
if d.k == locNone: getTemp(p, t, d)
var tmp: TLoc
# bug #16331
let doesAlias = lhsDoesAlias(d.lode, n)
let dest = if doesAlias: addr(tmp) else: addr(d)
if doesAlias:
getTemp(p, n.typ, tmp)
elif d.k == locNone:
getTemp(p, n.typ, d)
for i in 0..<n.len:
var it = n[i]
if it.kind == nkExprColonExpr: it = it[1]
initLoc(rec, locExpr, it, d.storage)
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
initLoc(rec, locExpr, it, dest[].storage)
rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
rec.flags.incl(lfEnforceDeref)
expr(p, it, rec)
if doesAlias:
if d.k == locNone:
d = tmp
else:
genAssignment(p, d, tmp, {})
proc isConstClosure(n: PNode): bool {.inline.} =
result = n[0].kind == nkSym and isRoutine(n[0].sym) and
n[1].kind == nkNilLit
@@ -2772,7 +2842,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
rdMType(p, a, nilCheck, r)
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(dest)
let token = $genDisplayElem(MD5Digest(hashType(dest)))
let token = $genDisplayElem(MD5Digest(hashType(dest, p.config)))
if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObjDisplayCheck($2, $3, $4)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor, token])
@@ -2839,7 +2909,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
# expression not found in the cache:
inc(p.module.labels)
p.module.s[cfsData].addf("static NIM_CONST $1 $2 = ",
[getTypeDesc(p.module, t, skConst), tmp])
[getTypeDesc(p.module, t, dkConst), tmp])
genBracedInit(p, n, isConst = true, t, p.module.s[cfsData])
p.module.s[cfsData].addf(";$n", [])
@@ -2866,13 +2936,13 @@ proc genConstHeader(m, q: BModule; p: BProc, sym: PSym) =
if not genConstSetup(p, sym): return
assert(sym.loc.r != "", $sym.name.s & $sym.itemId)
if m.hcrOn:
m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, skVar), sym.loc.r]);
m.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(m, sym.loc.t, dkVar), sym.loc.r]);
m.initProc.procSec(cpsLocals).addf(
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.r,
getTypeDesc(m, sym.loc.t, skVar), getModuleDllPath(q, sym)])
getTypeDesc(m, sym.loc.t, dkVar), getModuleDllPath(q, sym)])
else:
let headerDecl = "extern NIM_CONST $1 $2;$n" %
[getTypeDesc(m, sym.loc.t, skVar), sym.loc.r]
[getTypeDesc(m, sym.loc.t, dkVar), sym.loc.r]
m.s[cfsData].add(headerDecl)
if sfExportc in sym.flags and p.module.g.generatedHeader != nil:
p.module.g.generatedHeader.s[cfsData].add(headerDecl)
@@ -2888,7 +2958,7 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
q.s[cfsData].add data
if q.hcrOn:
# generate the global pointer with the real name
q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, skVar), sym.loc.r])
q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, dkVar), sym.loc.r])
# register it (but ignore the boolean result of hcrRegisterGlobal)
q.initProc.procSec(cpsLocals).addf(
"\thcrRegisterGlobal($1, \"$2\", sizeof($3), NULL, (void**)&$2);$n",
@@ -3196,6 +3266,8 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) =
result.add "}"
of tyTuple:
result.add "{"
if p.vccAndC and t.len == 0:
result.add "0"
for i in 0..<t.len:
if i > 0: result.add ", "
getDefaultValue(p, t[i], info, result)
@@ -3244,7 +3316,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
getNullValueAux(p, t, it, constOrNil, result, count, isConst, info)
of nkRecCase:
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
if count > 0: result.add ", "
var res = ""
if count > 0: res.add ", "
var branch = Zero
if constOrNil != nil:
## find kind value, default is zero if not specified
@@ -3258,18 +3331,21 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
break
let selectedBranch = caseObjDefaultBranch(obj, branch)
result.add "{"
res.add "{"
var countB = 0
let b = lastSon(obj[selectedBranch])
# designated initilization is the only way to init non first element of unions
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
result.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {"
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
result.add "}"
res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {"
getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info)
res.add "}"
elif b.kind == nkSym:
result.add "." & mangleRecFieldName(p.module, b.sym) & " = "
getNullValueAux(p, t, b, constOrNil, result, countB, isConst, info)
res.add "." & mangleRecFieldName(p.module, b.sym) & " = "
getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info)
else:
return
result.add res
result.add "}"
of nkSym:
@@ -3279,6 +3355,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
if constOrNil != nil:
for i in 1..<constOrNil.len:
if constOrNil[i].kind == nkExprColonExpr:
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
if constOrNil[i][0].sym.name.id == field.name.id:
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
return
@@ -3324,6 +3401,8 @@ proc genConstObjConstr(p: BProc; n: PNode; isConst: bool; result: var Rope) =
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Rope) =
result.add "{"
if p.vccAndC and n.len == 0 and n.typ.kind == tyArray:
getDefaultValue(p, n.typ[1], n.info, result)
for i in 0..<n.len:
let it = n[i]
if i > 0: result.add ",\n"
@@ -3333,6 +3412,8 @@ proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Rope) =
proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Rope) =
result.add "{"
if p.vccAndC and n.len == 0:
result.add "0"
for i in 0..<n.len:
let it = n[i]
if i > 0: result.add ",\n"
@@ -3366,18 +3447,19 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Rope)
proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Rope) =
let base = t.skipTypes(abstractInst)[0]
var data = rope"{"
for i in 0..<n.len:
if i > 0: data.addf(",$n", [])
genBracedInit(p, n[i], isConst, base, data)
data.add("}")
var data = rope""
if n.len > 0:
data.add(", {")
for i in 0..<n.len:
if i > 0: data.addf(",$n", [])
genBracedInit(p, n[i], isConst, base, data)
data.add("}")
let payload = getTempName(p.module)
appcg(p.module, cfsStrData,
"static $5 struct {$n" &
" NI cap; $1 data[$2];$n" &
"} $3 = {$2 | NIM_STRLIT_FLAG, $4};$n", [
"} $3 = {$2 | NIM_STRLIT_FLAG$4};$n", [
getTypeDesc(p.module, base), n.len, payload, data,
if isConst: "const" else: ""])
result.add "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload]

View File

@@ -83,7 +83,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
lineCg(p, cpsStmts, "$1.ClP_0 = NIM_NIL;$n", [accessor])
else:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
of tyChar, tyBool, tyEnum, tyInt..tyUInt64:
of tyChar, tyBool, tyEnum, tyRange, tyInt..tyUInt64:
lineCg(p, cpsStmts, "$1 = 0;$n", [accessor])
of tyCstring, tyPointer, tyPtr, tyVar, tyLent:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [accessor])
@@ -97,7 +97,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
else:
doAssert false, "unexpected set type kind"
of {tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,
tyGenericParam, tyOrdinal, tyRange, tyOpenArray, tyForward, tyVarargs,
tyGenericParam, tyOrdinal, tyOpenArray, tyForward, tyVarargs,
tyUncheckedArray, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot,
tyAnything, tyStatic, tyFromExpr, tyConcept, tyVoid, tyIterable}:

View File

@@ -8,7 +8,6 @@
#
# included from cgen.nim
const
RangeExpandLimit = 256 # do not generate ranges
# over 'RangeExpandLimit' elements
@@ -36,7 +35,9 @@ proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
if n.kind == nkEmpty:
result = false
elif n.kind in nkCallKinds and n[0] != nil and n[0].typ != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc:
if isInvalidReturnType(conf, n[0].typ, true):
if n[0].kind == nkSym and sfConstructor in n[0].sym.flags:
result = true
elif isInvalidReturnType(conf, n[0].typ, true):
# var v = f()
# is transformed into: var v; f(addr v)
# where 'f' **does not** initialize the result!
@@ -289,11 +290,28 @@ proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Rope) =
#echo "New code produced for ", v.name.s, " ", p.config $ value.info
genBracedInit(p, value, isConst = false, v.typ, result)
proc genCppVarForCtor(p: BProc, v: PSym; vn, value: PNode; decl: var Rope) =
var params = newRopeAppender()
var argsCounter = 0
let typ = skipTypes(value[0].typ, abstractInst)
assert(typ.kind == tyProc)
for i in 1..<value.len:
assert(typ.len == typ.n.len)
genOtherArg(p, value, i, typ, params, argsCounter)
if params.len == 0:
decl = runtimeFormat("$#;\n", [decl])
else:
decl = runtimeFormat("$#($#);\n", [decl, params])
proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
if sfGoto in v.flags:
# translate 'var state {.goto.} = X' into 'goto LX':
genGotoVar(p, value)
return
let imm = isAssignedImmediately(p.config, value)
let isCppCtorCall = p.module.compileToCpp and imm and
value.kind in nkCallKinds and value[0].kind == nkSym and
v.typ.kind != tyPtr and sfConstructor in value[0].sym.flags
var targetProc = p
var valueAsRope = ""
potentialValueInit(p, v, value, valueAsRope)
@@ -305,7 +323,11 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
if sfPure in v.flags:
# v.owner.kind != skModule:
targetProc = p.module.preInitProc
assignGlobalVar(targetProc, vn, valueAsRope)
if isCppCtorCall and not containsHiddenPointer(v.typ):
callGlobalVarCppCtor(targetProc, v, vn, value)
else:
assignGlobalVar(targetProc, vn, valueAsRope)
# XXX: be careful here.
# Global variables should not be zeromem-ed within loops
# (see bug #20).
@@ -314,7 +336,6 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
# global variables will be initialized to zero.
if valueAsRope.len == 0:
var loc = v.loc
# When the native TLS is unavailable, a global thread-local variable needs
# one more layer of indirection in order to access the TLS block.
# Only do this for complex types that may need a call to `objectInit`
@@ -328,31 +349,21 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
genVarPrototype(p.module.g.generatedHeader, vn)
registerTraverseProc(p, v)
else:
let imm = isAssignedImmediately(p.config, value)
if imm and p.module.compileToCpp and p.splitDecls == 0 and
not containsHiddenPointer(v.typ):
not containsHiddenPointer(v.typ) and
nimErrorFlagAccessed notin p.flags:
# C++ really doesn't like things like 'Foo f; f = x' as that invokes a
# parameterless constructor followed by an assignment operator. So we
# generate better code here: 'Foo f = x;'
genLineDir(p, vn)
let decl = localVarDecl(p, vn)
var decl = localVarDecl(p, vn)
var tmp: TLoc
if value.kind in nkCallKinds and value[0].kind == nkSym and
sfConstructor in value[0].sym.flags:
var params = newRopeAppender()
var argsCounter = 0
let typ = skipTypes(value[0].typ, abstractInst)
assert(typ.kind == tyProc)
for i in 1..<value.len:
assert(typ.len == typ.n.len)
genOtherArg(p, value, i, typ, params, argsCounter)
if params.len == 0:
lineF(p, cpsStmts, "$#;$n", [decl])
else:
lineF(p, cpsStmts, "$#($#);$n", [decl, params])
if isCppCtorCall:
genCppVarForCtor(p, v, vn, value, decl)
line(p, cpsStmts, decl)
else:
initLocExprSingleUse(p, value, tmp)
lineF(p, cpsStmts, "$# = $#;$n", [decl, tmp.rdLoc])
lineF(p, cpsStmts, "$# = $#;\n", [decl, tmp.rdLoc])
return
assignLocalVar(p, vn)
initLocalVar(p, v, imm)
@@ -379,7 +390,8 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
startBlock(targetProc)
if value.kind != nkEmpty and valueAsRope.len == 0:
genLineDir(targetProc, vn)
loadInto(targetProc, vn, value, v.loc)
if not isCppCtorCall:
loadInto(targetProc, vn, value, v.loc)
if forHcr:
endBlock(targetProc)
@@ -614,7 +626,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
lineF(p, cpsStmts, "if (!$1) goto ", [rdLoc(a)])
assignLabel(p.blocks[p.breakIdx], p.s(cpsStmts))
lineF(p, cpsStmts, ";$n", [])
appcg(p, cpsStmts, ";$n", [])
genStmts(p, loopBody)
if optProfiler in p.options:
@@ -654,7 +666,7 @@ proc genParForStmt(p: BProc, t: PNode) =
#initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
#discard mangleName(forLoopVar)
let call = t[1]
assert(call.len in {4, 5})
assert(call.len == 4 or call.len == 5)
initLocExpr(p, call[1], rangeA)
initLocExpr(p, call[2], rangeB)
@@ -767,11 +779,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
else:
finallyActions(p)
genLineDir(p, t)
# reraise the last exception:
if p.config.exc == excCpp:
line(p, cpsStmts, "throw;\n")
else:
linefmt(p, cpsStmts, "#reraiseException();$n", [])
linefmt(p, cpsStmts, "#reraiseException();$n", [])
raiseInstr(p, p.s(cpsStmts))
template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
@@ -963,8 +971,11 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
hasDefault = true
exprBlock(p, branch.lastSon, d)
lineF(p, cpsStmts, "break;$n", [])
if (hasAssume in CC[p.config.cCompiler].props) and not hasDefault:
lineF(p, cpsStmts, "default: __assume(0);$n", [])
if not hasDefault:
if hasBuiltinUnreachable in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __builtin_unreachable();$n", [])
elif hasAssume in CC[p.config.cCompiler].props:
lineF(p, cpsStmts, "default: __assume(0);$n", [])
lineF(p, cpsStmts, "}$n", [])
if lend != "": fixLabel(p, lend)
@@ -997,7 +1008,7 @@ proc genRestoreFrameAfterException(p: BProc) =
proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
#[ code to generate:
std::exception_ptr error = nullptr;
std::exception_ptr error;
try {
body;
} catch (Exception e) {
@@ -1028,7 +1039,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
inc(p.labels, 2)
let etmp = p.labels
p.procSec(cpsInit).add(ropecg(p.module, "\tstd::exception_ptr T$1_ = nullptr;", [etmp]))
lineCg(p, cpsStmts, "std::exception_ptr T$1_;$n", [etmp])
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
p.nestedTryStmts.add((fin, false, 0.Natural))
@@ -1062,7 +1073,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
if hasIf: lineF(p, cpsStmts, "else ", [])
startBlock(p)
# we handled the error:
linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp])
expr(p, t[i][0], d)
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
endBlock(p)
@@ -1082,7 +1092,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(typeNode.typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(typeNode.typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(typeNode.typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, typeNode.typ, typeNode.info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1125,7 +1135,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
if t[i].len == 1:
# general except section:
startBlock(p, "catch (...) {", [])
startBlock(p, "catch (...) {$n", [])
genExceptBranchBody(t[i][0])
endBlock(p)
catchAllPresent = true
@@ -1151,7 +1161,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
# general finally block:
if t.len > 0 and t[^1].kind == nkFinally:
if not catchAllPresent:
startBlock(p, "catch (...) {", [])
startBlock(p, "catch (...) {$n", [])
genRestoreFrameAfterException(p)
linefmt(p, cpsStmts, "T$1_ = std::current_exception();$n", [etmp])
endBlock(p)
@@ -1301,7 +1311,8 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)",
[memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1446,7 +1457,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1538,7 +1549,7 @@ proc determineSection(n: PNode): TCFileSection =
result = cfsProcHeaders
if n.len >= 1 and n[0].kind in {nkStrLit..nkTripleStrLit}:
let sec = n[0].strVal
if sec.startsWith("/*TYPESECTION*/"): result = cfsTypes
if sec.startsWith("/*TYPESECTION*/"): result = cfsForwardTypes # TODO WORKAROUND
elif sec.startsWith("/*VARSECTION*/"): result = cfsVars
elif sec.startsWith("/*INCLUDESECTION*/"): result = cfsHeaders
@@ -1555,9 +1566,14 @@ proc genEmit(p: BProc, t: PNode) =
line(p, cpsStmts, s)
proc genPragma(p: BProc, n: PNode) =
for it in n.sons:
for i in 0..<n.len:
let it = n[i]
case whichPragma(it)
of wEmit: genEmit(p, it)
of wPush:
processPushBackendOption(p.optionsStack, p.options, n, i+1)
of wPop:
processPopBackendOption(p.optionsStack, p.options)
else: discard
@@ -1575,6 +1591,8 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),
lit])
if p.config.exc == excGoto:
raiseExit(p)
when false:
proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLoc) =
@@ -1599,7 +1617,7 @@ proc asgnFieldDiscriminant(p: BProc, e: PNode) =
initLocExpr(p, e[0], a)
getTemp(p, a.t, tmp)
expr(p, e[1], tmp)
if optTinyRtti notin p.config.globalOptions and p.inUncheckedAssignSection == 0:
if p.inUncheckedAssignSection == 0:
let field = dotExpr[1].sym
genDiscriminantCheck(p, a, tmp, dotExpr[0].typ, field)
message(p.config, e.info, warnCaseTransition)
@@ -1616,10 +1634,11 @@ proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
let le = e[0]
let ri = e[1]
var a: TLoc
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs), skVar)
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs), dkVar)
initLoc(a, locNone, le, OnUnknown)
a.flags.incl(lfEnforceDeref)
a.flags.incl(lfPrepareForMutation)
genLineDir(p, le) # it can be a nkBracketExpr, which may raise
expr(p, le, a)
a.flags.excl(lfPrepareForMutation)
if fastAsgn: incl(a.flags, lfNoDeepCopy)

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,8 @@ import
ast, types, hashes, strutils, msgs, wordrecg,
platform, trees, options, cgendata
import std/[hashes, strutils, formatfloat]
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -53,7 +55,7 @@ proc hashString*(conf: ConfigRef; s: string): BiggestInt =
a = a + (a shl 3)
a = a xor (a shr 11)
a = a + (a shl 15)
result = cast[Hash](a)
result = cast[Hash](uint(a))
template getUniqueType*(key: PType): PType = key
@@ -122,13 +124,19 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
var pt = skipTypes(s.typ, typedescInst)
assert skResult != s.kind
if tfByRef in pt.flags: return true
#note precedence: params override types
if optByRef in s.options: return true
elif sfByCopy in s.flags: return false
elif tfByRef in pt.flags: return true
elif tfByCopy in pt.flags: return false
case pt.kind
of tyObject:
if s.typ.sym != nil and sfForward in s.typ.sym.flags:
# forwarded objects are *always* passed by pointers for consistency!
result = true
elif s.typ.kind == tySink and conf.selectedGC notin {gcArc, gcAtomicArc, gcOrc, gcHooks}:
# bug #23354:
result = false
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
result = true # requested anyway
elif (tfFinal in pt.flags) and (pt[0] == nil):
@@ -145,3 +153,64 @@ proc ccgIntroducedPtr*(conf: ConfigRef; s: PSym, retType: PType): bool =
result = not (pt.kind in {tyVar, tyArray, tyOpenArray, tyVarargs, tyRef, tyPtr, tyPointer} or
pt.kind == tySet and mapSetType(conf, pt) == ctArray)
proc encodeName*(name: string): string =
result = mangle(name)
result = $result.len & result
proc makeUnique(m: BModule; s: PSym, name: string = ""): string =
result = if name == "": s.name.s else: name
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_u"
result.add $s.itemId.item
proc encodeSym*(m: BModule; s: PSym; makeUnique: bool = false): string =
#Module::Type
var name = s.name.s
if makeUnique:
name = makeUnique(m, s, name)
"N" & encodeName(s.skipGenericOwner.name.s) & encodeName(name) & "E"
proc elementType*(n: PType): PType {.inline.} = n.sons[^1]
proc encodeType*(m: BModule; t: PType): string =
result = ""
var kindName = ($t.kind)[2..^1]
kindName[0] = toLower($kindName[0])[0]
case t.kind
of tyObject, tyEnum, tyDistinct, tyUserTypeClass, tyGenericParam:
result = encodeSym(m, t.sym)
of tyGenericInst, tyUserTypeClassInst, tyGenericBody:
result = encodeName(t[0].sym.name.s)
result.add "I"
for i in 1..<t.len - 1:
result.add encodeType(m, t[i])
result.add "E"
of tySequence, tyOpenArray, tyArray, tyVarargs, tyTuple, tyProc, tySet, tyTypeDesc,
tyPtr, tyRef, tyVar, tyLent, tySink, tyStatic, tyUncheckedArray, tyOr, tyAnd, tyBuiltInTypeClass:
result =
case t.kind:
of tySequence: encodeName("seq")
else: encodeName(kindName)
result.add "I"
for i in 0..<t.len:
let s = t[i]
if s.isNil: continue
result.add encodeType(m, s)
result.add "E"
of tyRange:
var val = "range_"
if t.n[0].typ.kind in {tyFloat..tyFloat128}:
val.addFloat t.n[0].floatVal
val.add "_"
val.addFloat t.n[1].floatVal
else:
val.add $t.n[0].intVal & "_" & $t.n[1].intVal
result = encodeName(val)
of tyString..tyUInt64, tyPointer, tyBool, tyChar, tyVoid, tyAnything, tyNil, tyEmpty:
result = encodeName(kindName)
of tyAlias, tyInferred, tyOwned:
result = encodeType(m, t.elementType)
else:
assert false, "encodeType " & $t.kind

View File

@@ -12,10 +12,12 @@
import
ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
nversion, nimsets, msgs, bitsets, idents, types,
ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
ccgutils, os, ropes, math, wordrecg, treetab, cgmeth,
rodutils, renderer, cgendata, aliases,
lowerings, tables, sets, ndi, lineinfos, pathutils, transf,
injectdestructors, astmsgs, modulepaths
injectdestructors, astmsgs, modulepaths, backendpragmas
import pipelineutils
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -28,6 +30,12 @@ import strutils except `%`, addf # collides with ropes.`%`
from ic / ic import ModuleBackendFlag
import dynlib
const
# we use some ASCII control characters to insert directives that will be converted to real code in a postprocessing pass
postprocessDirStart = '\1'
postprocessDirSep = '\31'
postprocessDirEnd = '\23'
when not declared(dynlib.libCandidates):
proc libCandidates(s: string, dest: var seq[string]) =
## given a library name pattern `s` write possible library names to `dest`.
@@ -59,12 +67,12 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
var ms = getModule(s)
result = m.g.modules[ms.position]
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}) =
result.k = k
result.storage = s
result.lode = lode
result.r = ""
result.flags = {}
result.flags = flags
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) {.inline.} =
# fills the loc if it is not already initialized
@@ -214,20 +222,20 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
elif frmt[i] == '#' and frmt[i+1] == '#':
inc(i, 2)
strLit.add("#")
var start = i
while i < frmt.len:
if frmt[i] != '$' and frmt[i] != '#': inc(i)
else: break
if i - 1 >= start:
strLit.add(substr(frmt, start, i - 1))
else:
strLit.add(frmt[i])
inc(i)
flushStrLit()
result.add newCall(ident"rope", resVar)
proc addIndent(p: BProc; result: var Rope) =
for i in 0..<p.blocks.len:
result.add "\t".rope
var i = result.len
let newLen = i + p.blocks.len
result.setLen newLen
while i < newLen:
result[i] = '\t'
inc i
template appcg(m: BModule, c: var Rope, frmt: FormatStr,
args: untyped) =
@@ -264,14 +272,28 @@ proc safeLineNm(info: TLineInfo): int =
result = toLinenumber(info)
if result < 0: result = 0 # negative numbers are not allowed in #line
proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) =
proc genPostprocessDir(field1, field2, field3: string): string =
result = postprocessDirStart & field1 & postprocessDirSep & field2 & postprocessDirSep & field3 & postprocessDirEnd
proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; conf: ConfigRef) =
assert line >= 0
if optLineDir in conf.options and line > 0:
r.addf("$N#line $2 $1$N",
[rope(makeSingleLineCString(filename)), rope(line)])
if fileIdx == InvalidFileIdx:
r.add(rope("\n#line " & $line & " \"generated_not_to_break_here\"\n"))
else:
r.add(rope("\n#line " & $line & " FX_" & $fileIdx.int32 & "\n"))
proc genCLineDir(r: var Rope, fileIdx: FileIndex, line: int; p: BProc; info: TLineInfo; lastFileIndex: FileIndex) =
assert line >= 0
if optLineDir in p.config.options and line > 0:
if fileIdx == InvalidFileIdx:
r.add(rope("\n#line " & $line & " \"generated_not_to_break_here\"\n"))
else:
r.add(rope("\n#line " & $line & " FX_" & $fileIdx.int32 & "\n"))
proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) =
genCLineDir(r, toFullPath(conf, info), info.safeLineNm, conf)
if optLineDir in conf.options:
genCLineDir(r, info.fileIndex, info.safeLineNm, conf)
proc freshLineInfo(p: BProc; info: TLineInfo): bool =
if p.lastLineInfo.line != info.line or
@@ -280,17 +302,25 @@ proc freshLineInfo(p: BProc; info: TLineInfo): bool =
p.lastLineInfo.fileIndex = info.fileIndex
result = true
proc genCLineDir(r: var Rope, p: BProc, info: TLineInfo; conf: ConfigRef) =
if optLineDir in conf.options:
let lastFileIndex = p.lastLineInfo.fileIndex
if freshLineInfo(p, info):
genCLineDir(r, info.fileIndex, info.safeLineNm, p, info, lastFileIndex)
proc genLineDir(p: BProc, t: PNode) =
let line = t.info.safeLineNm
if optEmbedOrigSrc in p.config.globalOptions:
p.s(cpsStmts).add("//" & sourceLine(p.config, t.info) & "\L")
genCLineDir(p.s(cpsStmts), toFullPath(p.config, t.info), line, p.config)
let lastFileIndex = p.lastLineInfo.fileIndex
let freshLine = freshLineInfo(p, t.info)
if freshLine:
genCLineDir(p.s(cpsStmts), t.info.fileIndex, line, p, t.info, lastFileIndex)
if ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and
(p.prc == nil or sfPure notin p.prc.flags) and t.info.fileIndex != InvalidFileIdx:
if freshLineInfo(p, t.info):
linefmt(p, cpsStmts, "nimln_($1, $2);$n",
[line, quotedFilename(p.config, t.info)])
if freshLine:
line(p, cpsStmts, genPostprocessDir("nimln", $line, $t.info.fileIndex.int32))
proc accessThreadLocalVar(p: BProc, s: PSym)
proc emulatedThreadVars(conf: ConfigRef): bool {.inline.}
@@ -349,19 +379,19 @@ template mapTypeChooser(n: PNode): TSymKind =
template mapTypeChooser(a: TLoc): TSymKind = mapTypeChooser(a.lode)
proc addAddrLoc(conf: ConfigRef; a: TLoc; result: var Rope) =
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a) == skParam) != ctArray:
result.add "(&" & a.r & ")"
else:
result.add a.r
proc addrLoc(conf: ConfigRef; a: TLoc): Rope =
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a)) != ctArray:
if lfIndirect notin a.flags and mapType(conf, a.t, mapTypeChooser(a) == skParam) != ctArray:
result = "(&" & a.r & ")"
else:
result = a.r
proc byRefLoc(p: BProc; a: TLoc): Rope =
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a)) != ctArray and not
if lfIndirect notin a.flags and mapType(p.config, a.t, mapTypeChooser(a) == skParam) != ctArray and not
p.module.compileToCpp:
result = "(&" & a.r & ")"
else:
@@ -376,6 +406,8 @@ proc rdCharLoc(a: TLoc): Rope =
type
TAssignmentFlag = enum
needToCopy
needToCopySinkParam
needTempForOpenArray
TAssignmentFlags = set[TAssignmentFlag]
proc genObjConstr(p: BProc, e: PNode, d: var TLoc)
@@ -413,7 +445,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
rawConstExpr(p, newNodeIT(nkType, a.lode.info, objType), tmp)
linefmt(p, cpsStmts,
"#nimCopyMem((void*)$1, (NIM_CONST void*)&$2, sizeof($3));$n",
[rdLoc(a), rdLoc(tmp), getTypeDesc(p.module, objType, mapTypeChooser(a))])
[rdLoc(a), rdLoc(tmp), getTypeDesc(p.module, objType, descKindFromSymKind mapTypeChooser(a))])
else:
rawConstExpr(p, newNodeIT(nkType, a.lode.info, t), tmp)
genAssignment(p, a, tmp, {})
@@ -475,7 +507,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
# so we use getTypeDesc here rather than rdLoc(loc)
linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
[addrLoc(p.config, loc),
getTypeDesc(p.module, loc.t, mapTypeChooser(loc))])
getTypeDesc(p.module, loc.t, descKindFromSymKind mapTypeChooser(loc))])
# XXX: We can be extra clever here and call memset only
# on the bytes following the m_type field?
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
@@ -492,14 +524,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
genRefAssign(p, loc, nilLoc)
else:
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
getTypeDesc(p.module, typ, descKindFromSymKind mapTypeChooser(loc))])
else:
if not isTemp or containsGarbageCollectedRef(loc.t):
# don't use nimZeroMem for temporary values for performance if we can
# avoid it:
if not isImportedCppType(typ):
if not isOrHasImportedCppType(typ):
linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
[addrLoc(p.config, loc), getTypeDesc(p.module, typ, mapTypeChooser(loc))])
[addrLoc(p.config, loc), getTypeDesc(p.module, typ, descKindFromSymKind mapTypeChooser(loc))])
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
@@ -517,7 +549,10 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
inc(p.labels)
result.r = "T" & rope(p.labels) & "_"
linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t, skVar), result.r])
if p.module.compileToCpp and isOrHasImportedCppType(t):
linefmt(p, cpsLocals, "$1 $2{};$n", [getTypeDesc(p.module, t, dkVar), result.r])
else:
linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t, dkVar), result.r])
result.k = locTemp
result.lode = lodeTyp t
result.storage = OnStack
@@ -535,7 +570,7 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) =
inc(p.labels)
result.r = "T" & rope(p.labels) & "_"
linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t, skVar), result.r, value])
linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t, dkVar), result.r, value])
result.k = locTemp
result.lode = lodeTyp t
result.storage = OnStack
@@ -558,8 +593,11 @@ proc localVarDecl(p: BProc; n: PNode): Rope =
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
result.addf("NIM_ALIGN($1) ", [rope(s.alignment)])
result.add getTypeDesc(p.module, s.typ, skVar)
if s.constraint.isNil:
genCLineDir(result, p, n.info, p.config)
result.add getTypeDesc(p.module, s.typ, dkVar)
if sfCodegenDecl notin s.flags:
if sfRegister in s.flags: result.add(" register")
#elif skipTypes(s.typ, abstractInst).kind in GcTypeKinds:
# decl.add(" GC_GUARD")
@@ -574,8 +612,8 @@ proc assignLocalVar(p: BProc, n: PNode) =
#assert(s.loc.k == locNone) # not yet assigned
# this need not be fulfilled for inline procs; they are regenerated
# for each module that uses them!
let nl = if optLineDir in p.config.options: "" else: "\L"
let decl = localVarDecl(p, n) & ";" & nl
let nl = if optLineDir in p.config.options: "" else: "\n"
let decl = localVarDecl(p, n) & (if p.module.compileToCpp and isOrHasImportedCppType(n.typ): "{};" else: ";") & nl
line(p, cpsLocals, decl)
include ccgthreadvars
@@ -588,6 +626,40 @@ proc treatGlobalDifferentlyForHCR(m: BModule, s: PSym): bool =
# and s.owner.kind == skModule # owner isn't always a module (global pragma on local var)
# and s.loc.k == locGlobalVar # loc isn't always initialized when this proc is used
proc genGlobalVarDecl(p: BProc, n: PNode; td, value: Rope; decl: var Rope) =
let s = n.sym
if sfCodegenDecl notin s.flags:
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
if p.hcrOn: decl.add("static ")
elif sfImportc in s.flags: decl.add("extern ")
elif lfExportLib in s.loc.flags: decl.add("N_LIB_EXPORT_VAR ")
else: decl.add("N_LIB_PRIVATE ")
if s.kind == skLet and value != "": decl.add("NIM_CONST ")
decl.add(td)
if p.hcrOn: decl.add("*")
if sfRegister in s.flags: decl.add(" register")
if sfVolatile in s.flags: decl.add(" volatile")
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
else:
if value != "":
decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
else:
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
proc genCppVarForCtor(p: BProc, v: PSym; vn, value: PNode; decl: var Rope)
proc callGlobalVarCppCtor(p: BProc; v: PSym; vn, value: PNode) =
let s = vn.sym
fillBackendName(p.module, s)
fillLoc(s.loc, locGlobalVar, vn, OnHeap)
var decl: Rope
let td = getTypeDesc(p.module, vn.sym.typ, dkVar)
genGlobalVarDecl(p, vn, td, "", decl)
decl.add " " & $s.loc.r
genCppVarForCtor(p, v, vn, value, decl)
p.module.s[cfsVars].add decl
proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
let s = n.sym
if s.loc.k == locNone:
@@ -613,29 +685,30 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
internalError(p.config, n.info, ".threadvar variables cannot have a value")
else:
var decl: Rope = ""
var td = getTypeDesc(p.module, s.loc.t, skVar)
let td = getTypeDesc(p.module, s.loc.t, dkVar)
genGlobalVarDecl(p, n, td, value, decl)
if s.constraint.isNil:
if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "NIM_ALIGN($1) ", [rope(s.alignment)]
if p.hcrOn: decl.add("static ")
elif sfImportc in s.flags: decl.add("extern ")
elif lfExportLib in s.loc.flags: decl.add("N_LIB_EXPORT_VAR ")
else: decl.add("N_LIB_PRIVATE ")
if s.kind == skLet and value != "": decl.add("NIM_CONST ")
decl.add(td)
if p.hcrOn: decl.add("*")
if sfRegister in s.flags: decl.add(" register")
if sfVolatile in s.flags: decl.add(" volatile")
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
if value != "":
decl.addf(" $1 = $2;$n", [s.loc.r, value])
if p.module.compileToCpp and value.startsWith "{{}":
# TODO: taking this branch, re"\{\{\}(,\s\{\})*\}" might be emitted, resulting in
# either warnings (GCC 12.2+) or errors (Clang 15, MSVC 19.3+) of C++11+ compilers **when
# explicit constructors are around** due to overload resolution rules in place [^0][^1][^2]
# *Workaround* here: have C++'s static initialization mechanism do the default init work,
# for us lacking a deeper knowledge of an imported object's constructors' ex-/implicitness
# (so far) *and yet* trying to achieve default initialization.
# Still, generating {}s in genConstObjConstr() just to omit them here is faaaar from ideal;
# need to figure out a better way, possibly by keeping around more data about the
# imported objects' contructors?
#
# [^0]: https://en.cppreference.com/w/cpp/language/aggregate_initialization
# [^1]: https://cplusplus.github.io/CWG/issues/1518.html
# [^2]: https://eel.is/c++draft/over.match.ctor
decl.addf(" $1;$n", [s.loc.r])
else:
decl.addf(" $1 = $2;$n", [s.loc.r, value])
else:
decl.addf(" $1;$n", [s.loc.r])
else:
if value != "":
decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
else:
decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
p.module.s[cfsVars].add(decl)
if p.withinLoop > 0 and value == "":
# fixes tests/run/tzeroarray:
@@ -656,7 +729,7 @@ proc getLabel(p: BProc): TLabel =
result = "LA" & rope(p.labels) & "_"
proc fixLabel(p: BProc, labl: TLabel) =
lineF(p, cpsStmts, "$1: ;$n", [labl])
p.s(cpsStmts).add("$1: ;$n" % [labl])
proc genVarPrototype(m: BModule, n: PNode)
proc requestConstImpl(p: BProc, sym: PSym)
@@ -669,8 +742,8 @@ proc genLiteral(p: BProc, n: PNode; result: var Rope)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
proc raiseExit(p: BProc)
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, e, OnUnknown)
proc initLocExpr(p: BProc, e: PNode, result: var TLoc, flags: TLocFlags = {}) =
initLoc(result, locNone, e, OnUnknown, flags)
expr(p, e, result)
proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
@@ -698,8 +771,12 @@ $1define nimfr_(proc, file) \
struct {TFrame* prev;NCSTRING procname;NI line;NCSTRING filename;NI len;VarSlot s[slots];} FR_; \
FR_.procname = proc; FR_.filename = file; FR_.line = 0; FR_.len = length; #nimFrame((TFrame*)&FR_);
$1define nimln_(n, file) \
$1define nimln_(n) \
FR_.line = n;
$1define nimlf_(n, file) \
FR_.line = n; FR_.filename = file;
"""
if p.module.s[cfsFrameDefines].len == 0:
appcg(p.module, p.module.s[cfsFrameDefines], frameDefines, ["#"])
@@ -765,7 +842,7 @@ proc loadDynamicLib(m: BModule, lib: PLib) =
initLoc(dest, locTemp, lib.path, OnStack)
dest.r = getTempName(m)
appcg(m, m.s[cfsDynLibInit],"$1 $2;$n",
[getTypeDesc(m, lib.path.typ, skVar), rdLoc(dest)])
[getTypeDesc(m, lib.path.typ, dkVar), rdLoc(dest)])
expr(p, lib.path, dest)
m.s[cfsVars].add(p.s(cpsLocals))
@@ -805,7 +882,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
params.add(rdLoc(a))
params.add(", ")
let load = "\t$1 = ($2) ($3$4));$n" %
[tmp, getTypeDesc(m, sym.typ, skVar), params, makeCString($extname)]
[tmp, getTypeDesc(m, sym.typ, dkVar), params, makeCString($extname)]
var last = lastSon(n)
if last.kind == nkHiddenStdConv: last = last[1]
internalAssert(m.config, last.kind == nkStrLit)
@@ -819,8 +896,8 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
else:
appcg(m, m.s[cfsDynLibInit],
"\t$1 = ($2) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ, skVar), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t, skVar)])
[tmp, getTypeDesc(m, sym.typ, dkVar), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2 $1;$n", [sym.loc.r, getTypeDesc(m, sym.loc.t, dkVar)])
proc varInDynamicLib(m: BModule, sym: PSym) =
var lib = sym.annex
@@ -832,9 +909,9 @@ proc varInDynamicLib(m: BModule, sym: PSym) =
inc(m.labels, 2)
appcg(m, m.s[cfsDynLibInit],
"$1 = ($2*) #nimGetProcAddr($3, $4);$n",
[tmp, getTypeDesc(m, sym.typ, skVar), lib.name, makeCString($extname)])
[tmp, getTypeDesc(m, sym.typ, dkVar), lib.name, makeCString($extname)])
m.s[cfsVars].addf("$2* $1;$n",
[sym.loc.r, getTypeDesc(m, sym.loc.t, skVar)])
[sym.loc.r, getTypeDesc(m, sym.loc.t, dkVar)])
proc symInDynamicLibPartial(m: BModule, sym: PSym) =
sym.loc.r = mangleDynLibProc(sym)
@@ -865,7 +942,9 @@ proc cgsymValue(m: BModule, name: string): Rope =
result.addActualSuffixForHCR(m.module, sym)
proc generateHeaders(m: BModule) =
m.s[cfsHeaders].add("\L#include \"nimbase.h\"\L")
var nimbase = m.config.nimbasePattern
if nimbase == "": nimbase = "nimbase.h"
m.s[cfsHeaders].addf("\L#include \"$1\"\L", [nimbase])
for it in m.headerFiles:
if it[0] == '#':
@@ -914,11 +993,19 @@ proc closureSetup(p: BProc, prc: PSym) =
linefmt(p, cpsStmts, "$1 = ($2) ClE_0;$n",
[rdLoc(env.loc), getTypeDesc(p.module, env.typ)])
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs
proc containsResult(n: PNode): bool =
result = false
case n.kind
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkFormalParams:
of succ(nkEmpty)..pred(nkSym), succ(nkSym)..nkNilLit, harmless:
discard
of nkReturnStmt:
for i in 0..<n.len:
if containsResult(n[i]): return true
result = n.len > 0 and n[0].kind == nkEmpty
of nkSym:
if n.sym.kind == skResult:
result = true
@@ -926,10 +1013,6 @@ proc containsResult(n: PNode): bool =
for i in 0..<n.len:
if containsResult(n[i]): return true
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt, nkFormalParams} +
declarativeDefs
proc easyResultAsgn(n: PNode): PNode =
case n.kind
of nkStmtList, nkStmtListExpr:
@@ -949,7 +1032,7 @@ proc easyResultAsgn(n: PNode): PNode =
type
InitResultEnum = enum Unknown, InitSkippable, InitRequired
proc allPathsAsgnResult(n: PNode): InitResultEnum =
proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
# Exceptions coming from calls don't have not be considered here:
#
# proc bar(): string = raise newException(...)
@@ -964,7 +1047,7 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
# echo "a was not written to"
#
template allPathsInBranch(it) =
let a = allPathsAsgnResult(it)
let a = allPathsAsgnResult(p, it)
case a
of InitRequired: return InitRequired
of InitSkippable: discard
@@ -976,14 +1059,20 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
case n.kind
of nkStmtList, nkStmtListExpr:
for it in n:
result = allPathsAsgnResult(it)
result = allPathsAsgnResult(p, it)
if result != Unknown: return result
of nkAsgn, nkFastAsgn, nkSinkAsgn:
if n[0].kind == nkSym and n[0].sym.kind == skResult:
if not containsResult(n[1]): result = InitSkippable
if not containsResult(n[1]):
if allPathsAsgnResult(p, n[1]) == InitRequired:
result = InitRequired
else:
result = InitSkippable
else: result = InitRequired
elif containsResult(n):
result = InitRequired
else:
result = allPathsAsgnResult(p, n[1])
of nkReturnStmt:
if n.len > 0:
if n[0].kind == nkEmpty and result != InitSkippable:
@@ -992,7 +1081,7 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
# initialized. This avoids cases like #9286 where this heuristic lead to
# wrong code being generated.
result = InitRequired
else: result = allPathsAsgnResult(n[0])
else: result = allPathsAsgnResult(p, n[0])
of nkIfStmt, nkIfExpr:
var exhaustive = false
result = InitSkippable
@@ -1018,9 +1107,9 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
of nkWhileStmt:
# some dubious code can assign the result in the 'while'
# condition and that would be fine. Everything else isn't:
result = allPathsAsgnResult(n[0])
result = allPathsAsgnResult(p, n[0])
if result == Unknown:
result = allPathsAsgnResult(n[1])
result = allPathsAsgnResult(p, n[1])
# we cannot assume that the 'while' loop is really executed at least once:
if result == InitSkippable: result = Unknown
of harmless:
@@ -1045,9 +1134,21 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
allPathsInBranch(n[0])
for i in 1..<n.len:
if n[i].kind == nkFinally:
result = allPathsAsgnResult(n[i].lastSon)
result = allPathsAsgnResult(p, n[i].lastSon)
else:
allPathsInBranch(n[i].lastSon)
of nkCallKinds:
if canRaiseDisp(p, n[0]):
result = InitRequired
else:
for i in 0..<n.safeLen:
allPathsInBranch(n[i])
of nkRaiseStmt:
result = InitRequired
of nkChckRangeF, nkChckRange64, nkChckRange:
# TODO: more checks might need to be covered like overflow, indexDefect etc.
# bug #22852
result = InitRequired
else:
for i in 0..<n.safeLen:
allPathsInBranch(n[i])
@@ -1062,7 +1163,7 @@ proc getProcTypeCast(m: BModule, prc: PSym): Rope =
proc genProcBody(p: BProc; procBody: PNode) =
genStmts(p, procBody) # modifies p.locals, p.init, etc.
if {nimErrorFlagAccessed, nimErrorFlagDeclared} * p.flags == {nimErrorFlagAccessed}:
if {nimErrorFlagAccessed, nimErrorFlagDeclared, nimErrorFlagDisabled} * p.flags == {nimErrorFlagAccessed}:
p.flags.incl nimErrorFlagDeclared
p.blocks[0].sections[cpsLocals].add(ropecg(p.module, "NIM_BOOL* nimErr_;$n", []))
p.blocks[0].sections[cpsInit].add(ropecg(p.module, "nimErr_ = #nimErrorFlag();$n", []))
@@ -1070,10 +1171,13 @@ proc genProcBody(p: BProc; procBody: PNode) =
proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
sfNoReturn in s.flags and m.config.exc != excGoto
proc genProcAux(m: BModule, prc: PSym) =
proc genProcAux*(m: BModule, prc: PSym) =
var p = newProc(prc, m)
var header = newRopeAppender()
genProcHeader(m, prc, header)
if m.config.backend == backendCpp and {sfVirtual, sfConstructor} * prc.flags != {}:
genMemberProcHeader(m, prc, header)
else:
genProcHeader(m, prc, header)
var returnStmt: Rope = ""
assert(prc.ast != nil)
@@ -1081,12 +1185,15 @@ proc genProcAux(m: BModule, prc: PSym) =
if sfInjectDestructors in prc.flags:
procBody = injectDestructorCalls(m.g.graph, m.idgen, prc, procBody)
let tmpInfo = prc.info
discard freshLineInfo(p, prc.info)
if sfPure notin prc.flags and prc.typ[0] != nil:
if resultPos >= prc.ast.len:
internalError(m.config, prc.info, "proc has no result symbol")
let resNode = prc.ast[resultPos]
let res = resNode.sym # get result symbol
if not isInvalidReturnType(m.config, prc.typ):
if not isInvalidReturnType(m.config, prc.typ) and sfConstructor notin prc.flags:
if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil):
var decl = localVarDecl(p, resNode)
@@ -1097,8 +1204,16 @@ proc genProcAux(m: BModule, prc: PSym) =
# declare the result symbol:
assignLocalVar(p, resNode)
assert(res.loc.r != "")
initLocalVar(p, res, immediateAsgn=false)
if p.config.selectedGC in {gcArc, gcAtomicArc, gcOrc} and
allPathsAsgnResult(p, procBody) == InitSkippable:
# In an ideal world the codegen could rely on injectdestructors doing its job properly
# and then the analysis step would not be required.
discard "result init optimized out"
else:
initLocalVar(p, res, immediateAsgn=false)
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
elif sfConstructor in prc.flags:
fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)
else:
fillResult(p.config, resNode, prc.typ)
assignParam(p, res, prc.typ[0])
@@ -1109,7 +1224,7 @@ proc genProcAux(m: BModule, prc: PSym) =
# global is either 'nil' or points to valid memory and so the RC operation
# succeeds without touching not-initialized memory.
if sfNoInit in prc.flags: discard
elif allPathsAsgnResult(procBody) == InitSkippable: discard
elif allPathsAsgnResult(p, procBody) == InitSkippable: discard
else:
resetLoc(p, res.loc)
if skipTypes(res.typ, abstractInst).kind == tyArray:
@@ -1123,6 +1238,8 @@ proc genProcAux(m: BModule, prc: PSym) =
closureSetup(p, prc)
genProcBody(p, procBody)
prc.info = tmpInfo
var generatedProc: Rope
generatedProc.genCLineDir prc.info, m.config
if isNoReturn(p.module, prc):
@@ -1174,7 +1291,7 @@ proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} =
proc genProcPrototype(m: BModule, sym: PSym) =
useHeader(m, sym)
if lfNoDecl in sym.loc.flags: return
if lfNoDecl in sym.loc.flags or {sfVirtual, sfConstructor} * sym.flags != {}: return
if lfDynamicLib in sym.loc.flags:
if sym.itemId.module != m.module.position and
not containsOrIncl(m.declaredThings, sym.id):
@@ -1210,6 +1327,20 @@ proc genProcNoForward(m: BModule, prc: PSym) =
if lfNoDecl in prc.loc.flags:
fillProcLoc(m, prc.ast[namePos])
genProcPrototype(m, prc)
elif lfDynamicLib in prc.loc.flags:
var q = findPendingModule(m, prc)
fillProcLoc(q, prc.ast[namePos])
genProcPrototype(m, prc)
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
symInDynamicLib(q, prc)
# register the procedure even though it is in a different dynamic library and will not be
# reloadable (and has no _actual suffix) - other modules will need to be able to get it through
# the hcr dynlib (also put it in the DynLibInit section - right after it gets loaded)
if isReloadable(q, prc):
q.s[cfsDynLibInit].addf("\t$1 = ($2) hcrRegisterProc($3, \"$1\", (void*)$1);$n",
[prc.loc.r, getTypeDesc(q, prc.loc.t), getModuleDllPath(m, q.module)])
else:
symInDynamicLibPartial(m, prc)
elif prc.typ.callConv == ccInline:
# We add inline procs to the calling module to enable C based inlining.
# This also means that a check with ``q.declaredThings`` is wrong, we need
@@ -1228,20 +1359,6 @@ proc genProcNoForward(m: BModule, prc: PSym) =
# prc.loc.r = mangleName(m, prc)
genProcPrototype(m, prc)
genProcAux(m, prc)
elif lfDynamicLib in prc.loc.flags:
var q = findPendingModule(m, prc)
fillProcLoc(q, prc.ast[namePos])
genProcPrototype(m, prc)
if q != nil and not containsOrIncl(q.declaredThings, prc.id):
symInDynamicLib(q, prc)
# register the procedure even though it is in a different dynamic library and will not be
# reloadable (and has no _actual suffix) - other modules will need to be able to get it through
# the hcr dynlib (also put it in the DynLibInit section - right after it gets loaded)
if isReloadable(q, prc):
q.s[cfsDynLibInit].addf("\t$1 = ($2) hcrRegisterProc($3, \"$1\", (void*)$1);$n",
[prc.loc.r, getTypeDesc(q, prc.loc.t), getModuleDllPath(m, q.module)])
else:
symInDynamicLibPartial(m, prc)
elif sfImportc notin prc.flags:
var q = findPendingModule(m, prc)
fillProcLoc(q, prc.ast[namePos])
@@ -1305,14 +1422,14 @@ proc genVarPrototype(m: BModule, n: PNode) =
if sym.owner.id != m.module.id:
# else we already have the symbol generated!
assert(sym.loc.r != "")
incl(m.declaredThings, sym.id)
if sfThread in sym.flags:
declareThreadVar(m, sym, true)
else:
incl(m.declaredThings, sym.id)
if sym.kind in {skLet, skVar, skField, skForVar} and sym.alignment > 0:
m.s[cfsVars].addf "NIM_ALIGN($1) ", [rope(sym.alignment)]
m.s[cfsVars].add(if m.hcrOn: "static " else: "extern ")
m.s[cfsVars].add(getTypeDesc(m, sym.loc.t, skVar))
m.s[cfsVars].add(getTypeDesc(m, sym.loc.t, dkVar))
if m.hcrOn: m.s[cfsVars].add("*")
if lfDynamicLib in sym.loc.flags: m.s[cfsVars].add("*")
if sfRegister in sym.flags: m.s[cfsVars].add(" register")
@@ -1321,7 +1438,7 @@ proc genVarPrototype(m: BModule, n: PNode) =
m.s[cfsVars].addf(" $1;$n", [sym.loc.r])
if m.hcrOn: m.initProc.procSec(cpsLocals).addf(
"\t$1 = ($2*)hcrGetGlobal($3, \"$1\");$n", [sym.loc.r,
getTypeDesc(m, sym.loc.t, skVar), getModuleDllPath(m, sym)])
getTypeDesc(m, sym.loc.t, dkVar), getModuleDllPath(m, sym)])
proc addNimDefines(result: var Rope; conf: ConfigRef) {.inline.} =
result.addf("#define NIM_INTBITS $1\L", [
@@ -1397,20 +1514,23 @@ proc genMainProc(m: BModule) =
[handle, strLit])
preMainCode.add(loadLib("hcr_handle", "hcrGetProc"))
preMainCode.add("\tvoid* rtl_handle;\L")
preMainCode.add(loadLib("rtl_handle", "nimGC_setStackBottom"))
preMainCode.add(hcrGetProcLoadCode(m, "nimGC_setStackBottom", "nimrtl_", "rtl_handle", "nimGetProcAddr"))
preMainCode.add("\tinner = PreMain;\L")
preMainCode.add("\tinitStackBottomWith_actual((void *)&inner);\L")
preMainCode.add("\t(*inner)();\L")
if m.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
preMainCode.add("\t$1PreMain();\L" % [rope m.config.nimMainPrefix])
else:
preMainCode.add("\tvoid* rtl_handle;\L")
preMainCode.add(loadLib("rtl_handle", "nimGC_setStackBottom"))
preMainCode.add(hcrGetProcLoadCode(m, "nimGC_setStackBottom", "nimrtl_", "rtl_handle", "nimGetProcAddr"))
preMainCode.add("\tinner = $1PreMain;\L" % [rope m.config.nimMainPrefix])
preMainCode.add("\tinitStackBottomWith_actual((void *)&inner);\L")
preMainCode.add("\t(*inner)();\L")
else:
preMainCode.add("\t$1PreMain();\L" % [rope m.config.nimMainPrefix])
var posixCmdLine: Rope
if optNoMain notin m.config.globalOptions:
posixCmdLine.add "\tN_LIB_PRIVATE int cmdCount;\L"
posixCmdLine.add "\tN_LIB_PRIVATE char** cmdLine;\L"
posixCmdLine.add "\tN_LIB_PRIVATE char** gEnv;\L"
posixCmdLine.add "N_LIB_PRIVATE int cmdCount;\L"
posixCmdLine.add "N_LIB_PRIVATE char** cmdLine;\L"
posixCmdLine.add "N_LIB_PRIVATE char** gEnv;\L"
const
# The use of a volatile function pointer to call Pre/NimMainInner
@@ -1423,15 +1543,15 @@ proc genMainProc(m: BModule) =
"}$N$N" &
"$4" &
"N_LIB_PRIVATE void $3PreMain(void) {$N" &
"\t##if $5$N" & # 1 for volatile call, 0 for non-volatile
"##if $5$N" & # 1 for volatile call, 0 for non-volatile
"\tvoid (*volatile inner)(void);$N" &
"\tinner = $3PreMainInner;$N" &
"$1" &
"\t(*inner)();$N" &
"\t##else$N" &
"##else$N" &
"$1" &
"\t$3PreMainInner();$N" &
"\t##endif$N" &
"##endif$N" &
"}$N$N"
MainProcs =
@@ -1446,17 +1566,17 @@ proc genMainProc(m: BModule) =
NimMainProc =
"N_CDECL(void, $5NimMain)(void) {$N" &
"\t##if $6$N" & # 1 for volatile call, 0 for non-volatile
"##if $6$N" & # 1 for volatile call, 0 for non-volatile
"\tvoid (*volatile inner)(void);$N" &
"$4" &
"\tinner = $5NimMainInner;$N" &
"$2" &
"\t(*inner)();$N" &
"\t##else$N" &
"##else$N" &
"$4" &
"$2" &
"\t$5NimMainInner();$N" &
"\t##endif$N" &
"##endif$N" &
"}$N$N"
NimMainBody = NimMainInner & NimMainProc
@@ -1487,7 +1607,7 @@ proc genMainProc(m: BModule) =
WinCDllMain =
"BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $N" &
" LPVOID lpvReserved) {$N" &
"\tif(fwdreason == DLL_PROCESS_ATTACH) {$N" & MainProcs & "}$N" &
"\tif (fwdreason == DLL_PROCESS_ATTACH) {$N" & MainProcs & "\t}$N" &
"\treturn 1;$N}$N$N"
PosixNimDllMain = WinNimDllMain
@@ -1521,11 +1641,11 @@ proc genMainProc(m: BModule) =
m.includeHeader("<libc/component.h>")
let initStackBottomCall =
if m.config.target.targetOS == osStandalone or m.config.selectedGC in {gcNone, gcArc, gcOrc}: "".rope
if m.config.target.targetOS == osStandalone or m.config.selectedGC in {gcNone, gcArc, gcAtomicArc, gcOrc}: "".rope
else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", [])
inc(m.labels)
let isVolatile = if m.config.selectedGC notin {gcNone, gcArc, gcOrc}: "1" else: "0"
let isVolatile = if m.config.selectedGC notin {gcNone, gcArc, gcAtomicArc, gcOrc}: "1" else: "0"
appcg(m, m.s[cfsProcs], PreMainBody, [m.g.mainDatInit, m.g.otherModsInit, m.config.nimMainPrefix, posixCmdLine, isVolatile])
if m.config.target.targetOS == osWindows and
@@ -1624,7 +1744,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
hcrModuleMeta.addf("\t\"\"};$n", [])
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$n",
[($sigHash(m.module)).rope])
[($sigHash(m.module, m.config)).rope])
if sfMainModule in m.module.flags:
g.mainModProcs.add(hcrModuleMeta)
g.mainModProcs.addf("static void* hcr_handle;$N", [])
@@ -1665,7 +1785,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
if sfSystemModule in m.module.flags:
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
g.mainDatInit.add(ropecg(m, "\t#initThreadVarsEmulation();$N", []))
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcAtomicArc, gcOrc}:
g.mainDatInit.add(ropecg(m, "\t#initStackBottomWith((void *)&inner);$N", []))
if m.s[cfsInitProc].len > 0:
@@ -1690,7 +1810,7 @@ proc genDatInitCode(m: BModule) =
# we don't want to break into such init code - could happen if a line
# directive from a function written by the user spills after itself
genCLineDir(prc, "generated_not_to_break_here", 999999, m.config)
genCLineDir(prc, InvalidFileIdx, 999999, m.config)
for i in cfsTypeInit1..cfsDynLibInit:
if m.s[i].len != 0:
@@ -1716,10 +1836,10 @@ proc hcrGetProcLoadCode(m: BModule, sym, prefix, handle, getProcFunc: string): R
prc.typ.sym = nil
if not containsOrIncl(m.declaredThings, prc.id):
m.s[cfsVars].addf("static $2 $1;$n", [prc.loc.r, getTypeDesc(m, prc.loc.t, skVar)])
m.s[cfsVars].addf("static $2 $1;$n", [prc.loc.r, getTypeDesc(m, prc.loc.t, dkVar)])
result = "\t$1 = ($2) $3($4, $5);$n" %
[tmp, getTypeDesc(m, prc.typ, skVar), getProcFunc.rope, handle.rope, makeCString(prefix & sym)]
[tmp, getTypeDesc(m, prc.typ, dkVar), getProcFunc.rope, handle.rope, makeCString(prefix & sym)]
proc genInitCode(m: BModule) =
## this function is called in cgenWriteModules after all modules are closed,
@@ -1731,7 +1851,7 @@ proc genInitCode(m: BModule) =
[rope(if m.hcrOn: "N_LIB_EXPORT" else: "N_LIB_PRIVATE"), initname]
# we don't want to break into such init code - could happen if a line
# directive from a function written by the user spills after itself
genCLineDir(prc, "generated_not_to_break_here", 999999, m.config)
genCLineDir(prc, InvalidFileIdx, 999999, m.config)
if m.typeNodes > 0:
if m.hcrOn:
appcg(m, m.s[cfsTypeInit1], "\t#TNimNode* $1;$N", [m.typeNodesName])
@@ -1795,12 +1915,15 @@ proc genInitCode(m: BModule) =
if beforeRetNeeded in m.initProc.flags:
prc.add("\tBeforeRet_: ;\n")
if sfMainModule in m.module.flags and m.config.exc == excGoto:
if m.config.exc == excGoto:
if getCompilerProc(m.g.graph, "nimTestErrorFlag") != nil:
m.appcg(prc, "\t#nimTestErrorFlag();$n", [])
if optStackTrace in m.initProc.options and preventStackTrace notin m.flags:
prc.add(deinitFrame(m.initProc))
elif m.config.exc == excGoto:
if getCompilerProc(m.g.graph, "nimTestErrorFlag") != nil:
m.appcg(prc, "\t#nimTestErrorFlag();$n", [])
prc.addf("}$N", [])
@@ -1843,6 +1966,40 @@ proc genInitCode(m: BModule) =
registerModuleToMain(m.g, m)
proc postprocessCode(conf: ConfigRef, r: var Rope) =
# find the first directive
var f = r.find(postprocessDirStart)
if f == -1:
return
var
nimlnDirLastF = ""
var res: Rope = r.substr(0, f - 1)
while f != -1:
var
e = r.find(postprocessDirEnd, f + 1)
dir = r.substr(f + 1, e - 1).split(postprocessDirSep)
case dir[0]
of "nimln":
if dir[2] == nimlnDirLastF:
res.add("nimln_(" & dir[1] & ");")
else:
res.add("nimlf_(" & dir[1] & ", " & quotedFilename(conf, dir[2].parseInt.FileIndex) & ");")
nimlnDirLastF = dir[2]
else:
raiseAssert "unexpected postprocess directive"
# find the next directive
f = r.find(postprocessDirStart, e + 1)
# copy the code until the next directive
if f != -1:
res.add(r.substr(e + 1, f - 1))
else:
res.add(r.substr(e + 1))
r = res
proc genModule(m: BModule, cfile: Cfile): Rope =
var moduleIsEmpty = true
@@ -1855,8 +2012,6 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
openNamespaceNim(m.config.cppCustomNamespace, result)
if m.s[cfsFrameDefines].len > 0:
result.add(m.s[cfsFrameDefines])
else:
result.add("#define nimfr_(x, y)\n#define nimln_(x, y)\n")
for i in cfsForwardTypes..cfsProcs:
if m.s[i].len > 0:
@@ -1873,9 +2028,17 @@ proc genModule(m: BModule, cfile: Cfile): Rope =
if m.config.cppCustomNamespace.len > 0:
closeNamespaceNim(result)
if optLineDir in m.config.options:
var srcFileDefs = ""
for fi in 0..m.config.m.fileInfos.high:
srcFileDefs.add("#define FX_" & $fi & " " & makeSingleLineCString(toFullPath(m.config, fi.FileIndex)) & "\n")
result = srcFileDefs & result
if moduleIsEmpty:
result = ""
postprocessCode(m.config, result)
proc initProcOptions(m: BModule): TOptions =
let opts = m.config.options
if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts
@@ -1929,10 +2092,7 @@ template injectG() {.dirty.} =
graph.backend = newModuleList(graph)
let g = BModuleList(graph.backend)
when not defined(nimHasSinkInference):
{.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
proc setupCgen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
injectG()
result = newModule(g, module, graph.config)
result.idgen = idgen
@@ -2000,7 +2160,7 @@ proc addHcrInitGuards(p: BProc, n: PNode, inInitGuard: var bool) =
proc genTopLevelStmt*(m: BModule; n: PNode) =
## Also called from `ic/cbackend.nim`.
if passes.skipCodegen(m.config, n): return
if pipelineutils.skipCodegen(m.config, n): return
m.initProc.options = initProcOptions(m)
#softRnl = if optLineDir in m.config.options: noRnl else: rnl
# XXX replicate this logic!
@@ -2013,12 +2173,6 @@ proc genTopLevelStmt*(m: BModule; n: PNode) =
else:
genProcBody(m.initProc, transformedN)
proc myProcess(b: PPassContext, n: PNode): PNode =
result = n
if b != nil:
var m = BModule(b)
genTopLevelStmt(m, n)
proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
if optForceFullMake notin m.config.globalOptions:
if not moduleHasChanged(m.g.graph, m.module):
@@ -2084,7 +2238,7 @@ proc updateCachedModule(m: BModule) =
cf.flags = {CfileFlag.Cached}
addFileToCompile(m.config, cf)
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode): PNode =
## Also called from IC.
if sfMainModule in m.module.flags:
# phase ordering problem here: We need to announce this
@@ -2095,7 +2249,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
if {optGenStaticLib, optGenDynLib, optNoMain} * m.config.globalOptions == {}:
for i in countdown(high(graph.globalDestructors), 0):
n.add graph.globalDestructors[i]
if passes.skipCodegen(m.config, n): return
if pipelineutils.skipCodegen(m.config, n): return
if moduleHasChanged(graph, m.module):
# if the module is cached, we don't regenerate the main proc
# nor the dispatchers? But if the dispatchers changed?
@@ -2106,7 +2260,10 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
if m.hcrOn:
# make sure this is pulled in (meaning hcrGetGlobal() is called for it during init)
cgsym(m, "programResult")
let sym = magicsys.getCompilerProc(m.g.graph, "programResult")
# ignore when not available, could be a module imported early in `system`
if sym != nil:
cgsymImpl m, sym
if m.inHcrInitGuard:
endBlock(m.initProc)
@@ -2123,25 +2280,18 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
cgsym(m, "rawWrite")
# raise dependencies on behalf of genMainProc
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcOrc}:
if m.config.target.targetOS != osStandalone and m.config.selectedGC notin {gcNone, gcArc, gcAtomicArc, gcOrc}:
cgsym(m, "initStackBottomWith")
if emulatedThreadVars(m.config) and m.config.target.targetOS != osStandalone:
cgsym(m, "initThreadVarsEmulation")
if m.g.forwardedProcs.len == 0:
incl m.flags, objHasKidsValid
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
result = generateMethodDispatchers(graph, m.idgen)
let mm = m
m.g.modulesClosed.add mm
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
result = n
if b == nil: return
finalCodegenActions(graph, BModule(b), n)
proc genForwardedProcs(g: BModuleList) =
# Forward declared proc:s lack bodies when first encountered, so they're given
# a second pass here
@@ -2168,5 +2318,3 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
m.writeModule(pending=true)
writeMapping(config, g.mapping)
if g.generatedHeader != nil: writeHeader(g.generatedHeader)
const cgenPass* = makePass(myOpen, myProcess, myClose)

View File

@@ -86,6 +86,7 @@ type
options*: TOptions # options that should be used for code
# generation; this is the same as prc.options
# unless prc == nil
optionsStack*: seq[TOptions]
module*: BModule # used to prevent excessive parameter passing
withinLoop*: int # > 0 if we are within a loop
splitDecls*: int # > 0 if we are in some context for C++ that
@@ -134,6 +135,7 @@ type
# unconditionally...
# nimtvDeps is VERY hard to cache because it's
# not a list of IDs nor can it be made to be one.
mangledPrcs*: HashSet[string]
TCGen = object of PPassContext # represents a C source file
s*: TCFileSections # sections of the C file
@@ -147,7 +149,7 @@ type
typeABICache*: HashSet[SigHash] # cache for ABI checks; reusing typeCache
# would be ideal but for some reason enums
# don't seem to get cached so it'd generate
# 1 ABI check per occurence in code
# 1 ABI check per occurrence in code
forwTypeCache*: TypeCache # cache for forward declarations of types
declaredThings*: IntSet # things we have declared in this .c file
declaredProtos*: IntSet # prototypes we have declared in this .c file
@@ -172,6 +174,7 @@ type
template config*(m: BModule): ConfigRef = m.g.config
template config*(p: BProc): ConfigRef = p.module.g.config
template vccAndC*(p: BProc): bool = p.module.config.cCompiler == ccVcc and p.module.config.backend == backendC
proc includeHeader*(this: BModule; header: string) =
if not this.headerFiles.contains header:
@@ -191,15 +194,17 @@ proc initBlock*(): TBlock =
result.sections[i] = newRopeAppender()
proc newProc*(prc: PSym, module: BModule): BProc =
new(result)
result.prc = prc
result.module = module
result.options = if prc != nil: prc.options
else: module.config.options
result.blocks = @[initBlock()]
result.nestedTryStmts = @[]
result.finallySafePoints = @[]
result.sigConflicts = initCountTable[string]()
result = BProc(
prc: prc,
module: module,
optionsStack: if module.initProc != nil: module.initProc.optionsStack
else: @[],
options: if prc != nil: prc.options
else: module.config.options,
blocks: @[initBlock()],
sigConflicts: initCountTable[string]())
if optQuirky in result.options:
result.flags = {nimErrorFlagDisabled}
proc newModuleList*(g: ModuleGraph): BModuleList =
BModuleList(typeInfoMarker: initTable[SigHash, tuple[str: Rope, owner: int32]](),

View File

@@ -95,7 +95,8 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
return No
if result == Yes:
# check for return type:
if not sameTypeOrNil(a.typ[0], b.typ[0]):
# ignore flags of return types; # bug #22673
if not sameTypeOrNil(a.typ[0], b.typ[0], {IgnoreFlags}):
if b.typ[0] != nil and b.typ[0].kind == tyUntyped:
# infer 'auto' from the base to make it consistent:
b.typ[0] = a.typ[0]
@@ -113,7 +114,7 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) =
s.ast[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym; g: ModuleGraph; idgen: IdGenerator): PSym =
var disp = copySym(s, nextSymId(idgen))
var disp = copySym(s, idgen)
incl(disp.flags, sfDispatcher)
excl(disp.flags, sfExported)
let old = disp.typ
@@ -127,7 +128,7 @@ proc createDispatcher(s: PSym; g: ModuleGraph; idgen: IdGenerator): PSym =
disp.loc.r = ""
if s.typ[0] != nil:
if disp.ast.len > resultPos:
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextSymId(idgen))
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, idgen)
else:
# We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will
@@ -213,7 +214,7 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
a[j] = v
if h == 1: break
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet; idgen: IdGenerator): PSym =
var base = methods[0].ast[dispatcherPos].sym
result = base
var paramLen = base.typ.len
@@ -272,7 +273,7 @@ proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PS
nilchecks.flags.incl nfTransf # should not be further transformed
result.ast[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
proc generateMethodDispatchers*(g: ModuleGraph, idgen: IdGenerator): PNode =
result = newNode(nkStmtList)
for bucket in 0..<g.methods.len:
var relevantCols = initIntSet()
@@ -282,4 +283,4 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode =
# if multi-methods are not enabled, we are interested only in the first field
break
sortBucket(g.methods[bucket].methods, relevantCols)
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols, idgen))

View File

@@ -183,7 +183,7 @@ proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
result = newSym(skVar, getIdent(ctx.g.cache, name), nextSymId(ctx.idgen), ctx.fn, ctx.fn.info)
result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.idgen, ctx.fn, ctx.fn.info)
result.typ = typ
assert(not typ.isNil)
@@ -855,7 +855,9 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
case n.kind
of nkReturnStmt:
# We're somewhere in try, transform to finally unrolling
assert(ctx.nearestFinally != 0)
if ctx.nearestFinally == 0:
# return is within the finally
return
result = newNodeI(nkStmtList, n.info)
@@ -1348,7 +1350,7 @@ proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
let idefs = copyNode(it)
for v in 0..it.len-3:
if it[v].kind == nkSym:
let x = copySym(it[v].sym, nextSymId(c.idgen))
let x = copySym(it[v].sym, c.idgen)
c.tab[it[v].sym.id] = x
idefs.add newSymNode(x)
else:
@@ -1389,7 +1391,7 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
discard c.finallys.pop()
of nkWhileStmt, nkBlockStmt:
if n.hasYields == false: return n
if not n.hasYields: return n
c.blocks.add((n, c.finallys.len))
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
@@ -1431,9 +1433,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
# Lambda lifting was not done yet. Use temporary :state sym, which will
# be handled specially by lambda lifting. Local temp vars (if needed)
# should follow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), nextSymId(idgen), fn, fn.info)
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), idgen, fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn, idgen)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), nextSymId(idgen), fn, fn.info)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), idgen, fn, fn.info)
var pc = PreprocessContext(finallys: @[], config: g.config, idgen: idgen)
var n = preprocess(pc, n.toStmtList)
#echo "transformed into ", n
@@ -1466,9 +1468,10 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
result = ctx.transformStateAssignments(result)
result = ctx.wrapIntoStateLoop(result)
# echo "TRANSFORM TO STATES: "
# echo renderTree(result)
when false:
echo "TRANSFORM TO STATES: "
echo renderTree(result)
# echo "exception table:"
# for i, e in ctx.exceptionTable:
# echo i, " -> ", e
echo "exception table:"
for i, e in ctx.exceptionTable:
echo i, " -> ", e

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
## Helpers for binaries that use compiler passes, e.g.: nim, nimsuggest, nimfix
## Helpers for binaries that use compiler passes, e.g.: nim, nimsuggest
import
options, idents, nimconf, extccomp, commands, msgs,
@@ -55,6 +55,11 @@ proc loadConfigsAndProcessCmdLine*(self: NimProg, cache: IdentCache; conf: Confi
if conf.cmd == cmdNimscript:
incl(conf.globalOptions, optWasNimscript)
loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files
# restores `conf.notes` after loading config files
# because it has overwrites the notes when compiling the system module which
# is a foreign module compared to the project
if conf.cmd in cmdBackends:
conf.notes = conf.mainPackageNotes
if not self.suggestMode:
let scriptFile = conf.projectFull.changeFileExt("nims")

View File

@@ -205,7 +205,11 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
# unfortunately, hintUser and warningUser clash, otherwise implementation would simplify a bit
let x = findStr(noteMin, noteMax, id, errUnknown)
if x != errUnknown: notes = {TNoteKind(x)}
else: localError(conf, info, "unknown $#: $#" % [name, id])
else:
if isSomeHint:
message(conf, info, hintUnknownHint, id)
else:
localError(conf, info, "unknown $#: $#" % [name, id])
case id.normalize
of "all": # other note groups would be easy to support via additional cases
notes = if isSomeHint: {hintMin..hintMax} else: {warnMin..warnMax}
@@ -238,9 +242,9 @@ proc processCompile(conf: ConfigRef; filename: string) =
extccomp.addExternalFileToCompile(conf, found)
const
errNoneBoehmRefcExpectedButXFound = "'arc', 'orc', 'markAndSweep', 'boehm', 'go', 'none', 'regions', or 'refc' expected, but '$1' found"
errNoneBoehmRefcExpectedButXFound = "'arc', 'orc', 'atomicArc', 'markAndSweep', 'boehm', 'go', 'none', 'regions', or 'refc' expected, but '$1' found"
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console', 'lib' or 'staticlib' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
template warningOptionNoop(switch: string) =
@@ -262,6 +266,7 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "stack", "regions": result = conf.selectedGC == gcRegions
of "atomicarc": result = conf.selectedGC == gcAtomicArc
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
of "opt":
case arg.normalize
@@ -336,6 +341,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
of "nilseqs", "nilchecks", "taintmode": warningOptionNoop(switch)
of "panics": result = contains(conf.globalOptions, optPanics)
of "jsbigint64": result = contains(conf.globalOptions, optJsBigInt64)
else: invalidCmdLineOption(conf, passCmd1, switch, info)
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
@@ -515,14 +521,7 @@ proc initOrcDefines*(conf: ConfigRef) =
if conf.exc == excNone and conf.backend != backendCpp:
conf.exc = excGoto
proc registerArcOrc(pass: TCmdLinePass, conf: ConfigRef, isOrc: bool) =
if isOrc:
conf.selectedGC = gcOrc
defineSymbol(conf.symbols, "gcorc")
else:
conf.selectedGC = gcArc
defineSymbol(conf.symbols, "gcarc")
proc registerArcOrc(pass: TCmdLinePass, conf: ConfigRef) =
defineSymbol(conf.symbols, "gcdestructors")
incl conf.globalOptions, optSeqDestructors
incl conf.globalOptions, optTinyRtti
@@ -532,10 +531,11 @@ proc registerArcOrc(pass: TCmdLinePass, conf: ConfigRef, isOrc: bool) =
if conf.exc == excNone and conf.backend != backendCpp:
conf.exc = excGoto
proc unregisterArcOrc(conf: ConfigRef) =
proc unregisterArcOrc*(conf: ConfigRef) =
undefSymbol(conf.symbols, "gcdestructors")
undefSymbol(conf.symbols, "gcarc")
undefSymbol(conf.symbols, "gcorc")
undefSymbol(conf.symbols, "gcatomicarc")
undefSymbol(conf.symbols, "nimSeqsV2")
undefSymbol(conf.symbols, "nimV2")
excl conf.globalOptions, optSeqDestructors
@@ -561,9 +561,17 @@ proc processMemoryManagementOption(switch, arg: string, pass: TCmdLinePass,
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors", "arc":
registerArcOrc(pass, conf, false)
conf.selectedGC = gcArc
defineSymbol(conf.symbols, "gcarc")
registerArcOrc(pass, conf)
of "orc":
registerArcOrc(pass, conf, true)
conf.selectedGC = gcOrc
defineSymbol(conf.symbols, "gcorc")
registerArcOrc(pass, conf)
of "atomicarc":
conf.selectedGC = gcAtomicArc
defineSymbol(conf.symbols, "gcatomicarc")
registerArcOrc(pass, conf)
of "hooks":
conf.selectedGC = gcHooks
defineSymbol(conf.symbols, "gchooks")
@@ -610,6 +618,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
var path = processPath(conf, arg, info, notRelativeToProj=true)
let nimbleDir = AbsoluteDir getEnv("NIMBLE_DIR")
if not nimbleDir.isEmpty and pass == passPP:
path = nimbleDir / RelativeDir"pkgs2"
nimblePath(conf, path, info)
path = nimbleDir / RelativeDir"pkgs"
nimblePath(conf, path, info)
of "nonimblepath", "nobabelpath":
@@ -649,6 +659,11 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "backend", "b":
let backend = parseEnum(arg.normalize, TBackend.default)
if backend == TBackend.default: localError(conf, info, "invalid backend: '$1'" % arg)
if backend == backendJs: # bug #21209
conf.globalOptions.excl {optThreadAnalysis, optThreads}
if optRun in conf.globalOptions:
# for now, -r uses nodejs, so define nodejs
defineSymbol(conf.symbols, "nodejs")
conf.backend = backend
of "doccmd": conf.docCmd = arg
of "define", "d":
@@ -796,6 +811,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
defineSymbol(conf.symbols, "dll")
of "staticlib":
incl(conf.globalOptions, optGenStaticLib)
incl(conf.globalOptions, optNoMain)
excl(conf.globalOptions, optGenGuiApp)
defineSymbol(conf.symbols, "library")
defineSymbol(conf.symbols, "staticlib")
@@ -819,8 +835,16 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "header":
if conf != nil: conf.headerFile = arg
incl(conf.globalOptions, optGenIndex)
of "nimbasepattern":
if conf != nil: conf.nimbasePattern = arg
of "index":
processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info)
case arg.normalize
of "", "on": conf.globalOptions.incl {optGenIndex}
of "only": conf.globalOptions.incl {optGenIndexOnly, optGenIndex}
of "off": conf.globalOptions.excl {optGenIndex, optGenIndexOnly}
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
of "noimportdoc":
processOnOffSwitchG(conf, {optNoImportdoc}, arg, pass, info)
of "import":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd2, passPP}:
@@ -853,6 +877,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
setTarget(conf.target, conf.target.targetOS, cpu)
of "run", "r":
processOnOffSwitchG(conf, {optRun}, arg, pass, info)
if conf.backend == backendJs:
# for now, -r uses nodejs, so define nodejs
defineSymbol(conf.symbols, "nodejs")
of "maxloopiterationsvm":
expectArg(conf, switch, arg, pass, info)
conf.maxLoopIterationsVM = parseInt(arg)
@@ -867,7 +894,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "verbosity":
expectArg(conf, switch, arg, pass, info)
let verbosity = parseInt(arg)
if verbosity notin {0..3}:
if verbosity notin 0..3:
localError(conf, info, "invalid verbosity level: '$1'" % arg)
conf.verbosity = verbosity
var verb = NotesVerbosity[conf.verbosity]
@@ -1000,6 +1027,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
expectNoArg(conf, switch, arg, pass, info)
conf.exc = low(ExceptionSystem)
defineSymbol(conf.symbols, "noCppExceptions")
of "shownonexports":
expectNoArg(conf, switch, arg, pass, info)
showNonExportedFields(conf)
of "exceptions":
case arg.normalize
of "cpp": conf.exc = excCpp
@@ -1054,29 +1084,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "expandarc":
expectArg(conf, switch, arg, pass, info)
conf.arcToExpand[arg] = "T"
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
of "1.0":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "0")
# old behaviors go here:
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
undefSymbol(conf.symbols, "nimDoesntTrackDefects")
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
conf.globalOptions.incl optNimV1Emulation
of "1.2":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "2")
conf.globalOptions.incl optNimV12Emulation
of "1.6":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "6")
conf.globalOptions.incl optNimV16Emulation
else:
localError(conf, info, "unknown Nim version; currently supported values are: `1.0`, `1.2`")
# always be compatible with 1.x.100:
defineSymbol(conf.symbols, "NimPatch", "100")
of "benchmarkvm":
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
of "profilevm":
@@ -1090,6 +1097,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
if optPanics in conf.globalOptions:
defineSymbol(conf.symbols, "nimPanics")
of "jsbigint64":
processOnOffSwitchG(conf, {optJsBigInt64}, arg, pass, info)
of "sourcemap": # xxx document in --fullhelp
conf.globalOptions.incl optSourcemap
conf.options.incl optLineDir

28
compiler/compiler.nimble Normal file
View File

@@ -0,0 +1,28 @@
include "../lib/system/compilation.nim"
version = $NimMajor & "." & $NimMinor & "." & $NimPatch
author = "Andreas Rumpf"
description = "Compiler package providing the compiler sources as a library."
license = "MIT"
skipDirs = @["."]
installDirs = @["compiler"]
import os
var compilerDir = ""
before install:
rmDir("compiler")
let
files = listFiles(".")
dirs = listDirs(".")
mkDir("compiler")
for f in files:
cpFile(f, "compiler" / f)
for d in dirs:
cpDir(d, "compiler" / d)
requires "nim"

View File

@@ -27,7 +27,7 @@ const
proc declareSelf(c: PContext; info: TLineInfo) =
## Adds the magical 'Self' symbols to the current scope.
let ow = getCurrOwner(c)
let s = newSym(skType, getIdent(c.cache, "Self"), nextSymId(c.idgen), ow, info)
let s = newSym(skType, getIdent(c.cache, "Self"), c.idgen, ow, info)
s.typ = newType(tyTypeDesc, nextTypeId(c.idgen), ow)
s.typ.flags.incl {tfUnresolved, tfPacked}
s.typ.add newType(tyEmpty, nextTypeId(c.idgen), ow)
@@ -62,7 +62,7 @@ proc semConceptDecl(c: PContext; n: PNode): PNode =
result[i] = n[i]
result[^1] = semConceptDecl(c, n[^1])
of nkCommentStmt:
discard
result = n
else:
localError(c.config, n.info, "unexpected construct in the new-styled concept: " & renderTree(n))
result = n
@@ -274,7 +274,7 @@ proc matchSym(c: PContext; candidate: PSym, n: PNode; m: var MatchCon): bool =
proc matchSyms(c: PContext, n: PNode; kinds: set[TSymKind]; m: var MatchCon): bool =
## Walk the current scope, extract candidates which the same name as 'n[namePos]',
## 'n' is the nkProcDef or similar from the concept that we try to match.
let candidates = searchInScopesFilterBy(c, n[namePos].sym.name, kinds)
let candidates = searchInScopesAllCandidatesFilterBy(c, n[namePos].sym.name, kinds)
for candidate in candidates:
#echo "considering ", typeToString(candidate.typ), " ", candidate.magic
m.magic = candidate.magic
@@ -306,13 +306,15 @@ proc conceptMatchNode(c: PContext; n: PNode; m: var MatchCon): bool =
result = matchSyms(c, n, {skMethod}, m)
of nkIteratorDef:
result = matchSyms(c, n, {skIterator}, m)
of nkCommentStmt:
result = true
else:
# error was reported earlier.
result = false
proc conceptMatch*(c: PContext; concpt, arg: PType; bindings: var TIdTable; invocation: PType): bool =
## Entry point from sigmatch. 'concpt' is the concept we try to match (here still a PType but
## we extract its AST via 'concpt.n.lastSon'). 'arg' is the type that might fullfill the
## we extract its AST via 'concpt.n.lastSon'). 'arg' is the type that might fulfill the
## concept's requirements. If so, we return true and fill the 'bindings' with pairs of
## (typeVar, instance) pairs. ('typeVar' is usually simply written as a generic 'T'.)
## 'invocation' can be nil for atomic concepts. For non-atomic concepts, it contains the

View File

@@ -25,7 +25,7 @@ proc undefSymbol*(symbols: StringTableRef; symbol: string) =
# result = if isDefined(symbol): gSymbols[symbol] else: nil
iterator definedSymbolNames*(symbols: StringTableRef): string =
for key, val in pairs(symbols):
for key in keys(symbols):
yield key
proc countDefinedSymbols*(symbols: StringTableRef): int =
@@ -45,10 +45,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNewTypedesc") # deadcode
defineSymbol("nimrequiresnimframe") # deadcode
defineSymbol("nimparsebiggestfloatmagic") # deadcode
defineSymbol("nimalias") # deadcode
defineSymbol("nimlocks") # deadcode
defineSymbol("nimnode") # deadcode pending `nimnode` reference in opengl package
# refs https://github.com/nim-lang/opengl/pull/79
defineSymbol("nimnode") # deadcode
defineSymbol("nimvarargstyped") # deadcode
defineSymbol("nimtypedescfixed") # deadcode
defineSymbol("nimKnowsNimvm") # deadcode
@@ -84,10 +82,24 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasSignatureHashInMacro") # deadcode
defineSymbol("nimHasDefault") # deadcode
defineSymbol("nimMacrosSizealignof") # deadcode
defineSymbol("nimNoZeroExtendMagic") # deadcode
defineSymbol("nimMacrosGetNodeId") # deadcode
defineSymbol("nimFixedForwardGeneric") # deadcode
defineSymbol("nimToOpenArrayCString") # deadcode
defineSymbol("nimHasUsed") # deadcode
defineSymbol("nimnomagic64") # deadcode
defineSymbol("nimNewShiftOps") # deadcode
defineSymbol("nimHasCursor") # deadcode
defineSymbol("nimAlignPragma") # deadcode
defineSymbol("nimHasExceptionsQuery") # deadcode
defineSymbol("nimHasIsNamedTuple") # deadcode
defineSymbol("nimHashOrdinalFixed") # deadcode
defineSymbol("nimHasSinkInference") # deadcode
defineSymbol("nimNewIntegerOps") # deadcode
defineSymbol("nimHasInvariant") # deadcode
# > 0.20.0
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in Feature:
defineSymbol("nimHas" & $f)
@@ -98,31 +110,18 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
defineSymbol("nimToOpenArrayCString")
defineSymbol("nimHasUsed")
defineSymbol("nimFixedForwardGeneric")
defineSymbol("nimnomagic64")
defineSymbol("nimNewShiftOps")
defineSymbol("nimHasCursor")
defineSymbol("nimAlignPragma")
defineSymbol("nimHasExceptionsQuery")
defineSymbol("nimHasIsNamedTuple")
defineSymbol("nimHashOrdinalFixed")
when defined(nimHasLibFFI):
# Renaming as we can't conflate input vs output define flags; e.g. this
# will report the right thing regardless of whether user adds
# `-d:nimHasLibFFI` in his user config.
defineSymbol("nimHasLibFFIEnabled")
defineSymbol("nimHasLibFFIEnabled") # deadcode
defineSymbol("nimHasSinkInference")
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")
defineSymbol("nimHasStacktraceMsgs") # deadcode
defineSymbol("nimDoesntTrackDefects")
defineSymbol("nimHasLentIterators")
defineSymbol("nimHasDeclaredMagic")
defineSymbol("nimHasStacktracesModule")
defineSymbol("nimHasLentIterators") # deadcode
defineSymbol("nimHasDeclaredMagic") # deadcode
defineSymbol("nimHasStacktracesModule") # deadcode
defineSymbol("nimHasEffectTraitsModule")
defineSymbol("nimHasCastPragmaBlocks")
defineSymbol("nimHasDeclaredLocs")
@@ -133,8 +132,8 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasCustomLiterals")
defineSymbol("nimHasUnifiedTuple")
defineSymbol("nimHasIterable")
defineSymbol("nimHasTypeofVoid")
defineSymbol("nimHasDragonBox")
defineSymbol("nimHasTypeofVoid") # deadcode
defineSymbol("nimHasDragonBox") # deadcode
defineSymbol("nimHasHintAll")
defineSymbol("nimHasTrace")
defineSymbol("nimHasEffectsOf")
@@ -144,8 +143,23 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasTemplateRedefinitionPragma")
defineSymbol("nimHasCstringCase")
defineSymbol("nimHasCallsitePragma")
defineSymbol("nimHasAmbiguousEnumHint")
defineSymbol("nimHasWarnCastSizes") # deadcode
defineSymbol("nimHasOutParams")
defineSymbol("nimHasSystemRaisesDefect")
defineSymbol("nimHasWarnUnnamedBreak")
defineSymbol("nimHasGenericDefine")
defineSymbol("nimHasDefineAliases")
defineSymbol("nimHasWarnBareExcept")
defineSymbol("nimHasDup")
defineSymbol("nimHasChecksums")
defineSymbol("nimHasSendable")
defineSymbol("nimAllowNonVarDestructor")
defineSymbol("nimHasQuirky")
defineSymbol("nimHasEnsureMove")
defineSymbol("nimHasNoReturnError")
defineSymbol("nimHasCastExtendedVm")
defineSymbol("nimHasGenericsOpenSym2")
defineSymbol("nimHasNolineTooLong")
defineSymbol("nimHasGenericsOpenSym3")

View File

@@ -9,7 +9,7 @@
# This module implements a dependency file generator.
import options, ast, ropes, passes, pathutils, msgs, lineinfos
import options, ast, ropes, pathutils, msgs, lineinfos
import modulegraphs
@@ -63,12 +63,16 @@ proc toNimblePath(s: string, isStdlib: bool): string =
sub.add "/pkgs/"
var start = s.find(sub)
if start < 0:
result = s
else:
start += sub.len
start += skipUntil(s, '/', start)
start += 1
result = pkgPrefix & s[start..^1]
sub[^1] = '2'
sub.add '/'
start = s.find(sub) # /pkgs2
if start < 0:
return s
start += sub.len
start += skipUntil(s, '/', start)
start += 1
result = pkgPrefix & s[start..^1]
proc addDependency(c: PPassContext, g: PGen, b: Backend, n: PNode) =
doAssert n.kind == nkSym, $n.kind
@@ -79,7 +83,7 @@ proc addDependency(c: PPassContext, g: PGen, b: Backend, n: PNode) =
let child = nativeToUnixPath(path.dir / path.name).toNimblePath(belongsToStdlib(g.graph, n.sym))
addDependencyAux(b, parent, child)
proc addDotDependency(c: PPassContext, n: PNode): PNode =
proc addDotDependency*(c: PPassContext, n: PNode): PNode =
result = n
let g = PGen(c)
let b = Backend(g.graph.backend)
@@ -100,10 +104,7 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
rope(project.splitFile.name), b.dotGraph],
changeFileExt(project, "dot"))
when not defined(nimHasSinkInference):
{.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
proc setupDependPass*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
var g: PGen
new(g)
g.module = module
@@ -112,6 +113,3 @@ proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext
if graph.backend == nil:
graph.backend = Backend(dotGraph: "")
result = g
const gendependPass* = makePass(open = myOpen, process = addDotDependency)

View File

@@ -264,7 +264,8 @@ proc genBreakOrRaiseAux(c: var Con, i: int, n: PNode) =
c.blocks[i].raiseFixups.add lab1
else:
var trailingFinales: seq[PNode]
if c.inTryStmt > 0: #Ok, we are in a try, lets see which (if any) try's we break out from:
if c.inTryStmt > 0:
# Ok, we are in a try, lets see which (if any) try's we break out from:
for b in countdown(c.blocks.high, i):
if c.blocks[b].isTryBlock:
trailingFinales.add c.blocks[b].finale
@@ -385,7 +386,8 @@ proc genCall(c: var Con; n: PNode) =
# Pass by 'out' is a 'must def'. Good enough for a move optimizer.
genDef(c, n[i])
# every call can potentially raise:
if false: # c.inTryStmt > 0 and canRaiseConservative(n[0]):
if c.inTryStmt > 0 and canRaiseConservative(n[0]):
inc c.interestingInstructions
# we generate the instruction sequence:
# fork lab1
# goto exceptionHandler (except or finally)
@@ -493,7 +495,7 @@ proc constructCfg*(s: PSym; body: PNode; root: PSym): ControlFlowGraph =
gen(c, body)
if root.kind == skResult:
genImplicitReturn(c)
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
result = c.code # will move
else:
shallowCopy(result, c.code)

View File

@@ -7,13 +7,17 @@
# distribution, for details about the copyright.
#
# This is the documentation generator. Cross-references are generated
# by knowing how the anchors are going to be named.
## This is the Nim documentation generator. Cross-references are generated
## by knowing how the anchors are going to be named.
##
## .. importdoc:: ../docgen.md
##
## For corresponding users' documentation see [Nim DocGen Tools Guide].
import
ast, strutils, strtabs, algorithm, sequtils, options, msgs, os, idents,
wordrecg, syntaxes, renderer, lexer,
packages/docutils/[rst, rstgen, dochelpers],
packages/docutils/[rst, rstidx, rstgen, dochelpers],
json, xmltree, trees, types,
typesrenderer, astalgo, lineinfos, intsets,
pathutils, tables, nimpaths, renderverbatim, osproc, packages
@@ -91,7 +95,7 @@ type
jEntriesFinal: JsonNode # final JSON after RST pass 2 and rendering
types: TStrTable
sharedState: PRstSharedState
standaloneDoc: bool
standaloneDoc: bool # is markup (.rst/.md) document?
conf*: ConfigRef
cache*: IdentCache
exampleCounter: int
@@ -108,13 +112,16 @@ type
proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst)
proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str)
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
proc addRstFileIndex(d: PDoc, fileIndex: lineinfos.FileIndex): rstast.FileIndex =
let invalid = rstast.FileIndex(-1)
result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid)
result = d.nimToRstFid.getOrDefault(fileIndex, default = invalid)
if result == invalid:
let fname = toFullPath(d.conf, info)
let fname = toFullPath(d.conf, fileIndex)
result = addFilename(d.sharedState, fname)
d.nimToRstFid[info.fileIndex] = result
d.nimToRstFid[fileIndex] = result
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
addRstFileIndex(d, info.fileIndex)
proc cmpDecimalsIgnoreCase(a, b: string): int =
## For sorting with correct handling of cases like 'uint8' and 'uint16'.
@@ -225,7 +232,7 @@ proc attachToType(d: PDoc; p: PSym): PSym =
if params.len > 0: check(0)
for i in 2..<params.len: check(i)
template declareClosures =
template declareClosures(currentFilename: AbsoluteFile, destFile: string) =
proc compilerMsgHandler(filename: string, line, col: int,
msgKind: rst.MsgKind, arg: string) {.gcsafe.} =
# translate msg kind:
@@ -249,9 +256,19 @@ template declareClosures =
of mwBrokenLink: k = warnRstBrokenLink
of mwUnsupportedLanguage: k = warnRstLanguageXNotSupported
of mwUnsupportedField: k = warnRstFieldXNotSupported
of mwUnusedImportdoc: k = warnRstUnusedImportdoc
of mwRstStyle: k = warnRstStyle
{.gcsafe.}:
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
let errorsAsWarnings = (roPreferMarkdown in d.sharedState.options) and
not d.standaloneDoc # not tolerate errors in .rst/.md files
if whichMsgClass(msgKind) == mcError and errorsAsWarnings:
liMessage(conf, newLineInfo(conf, AbsoluteFile filename, line, col),
k, arg, doNothing, instLoc(), ignoreError=true)
# when our Markdown parser fails, we currently can only terminate the
# parsing (and then we will return monospaced text instead of markup):
raiseRecoverableError("")
else:
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
proc docgenFindFile(s: string): string {.gcsafe.} =
result = options.findFile(conf, s).string
@@ -259,10 +276,29 @@ template declareClosures =
result = getCurrentDir() / s
if not fileExists(result): result = ""
proc docgenFindRefFile(targetRelPath: string):
tuple[targetPath: string, linkRelPath: string] {.gcsafe.} =
let fromDir = splitFile(destFile).dir # dir where we reference from
let basedir = os.splitFile(currentFilename.string).dir
let outDirPath: RelativeFile =
presentationPath(conf, AbsoluteFile(basedir / targetRelPath))
# use presentationPath because `..` path can be be mangled to `_._`
result.targetPath = string(conf.outDir / outDirPath)
if not fileExists(result.targetPath):
# this can happen if targetRelPath goes to parent directory `OUTDIR/..`.
# Trying it, this may cause ambiguities, but allows us to insert
# "packages" into each other, which is actually used in Nim repo itself.
let destPath = fromDir / targetRelPath
if destPath != result.targetPath and fileExists(destPath):
result.targetPath = destPath
result.linkRelPath = relativePath(result.targetPath.splitFile.dir,
fromDir).replace('\\', '/')
proc parseRst(text: string,
line, column: int,
conf: ConfigRef, sharedState: PRstSharedState): PRstNode =
declareClosures()
result = rstParsePass1(text, line, column, sharedState)
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
@@ -283,8 +319,10 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
outExt: string = HtmlExt, module: PSym = nil,
standaloneDoc = false, preferMarkdown = true,
hasToc = true): PDoc =
declareClosures()
let destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
new(result)
let d = result # pass `d` to `declareClosures`:
declareClosures(currentFilename = filename, destFile = destFile)
result.module = module
result.conf = conf
result.cache = cache
@@ -298,7 +336,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
result.hasToc = hasToc
result.sharedState = newRstSharedState(
options, filename.string,
docgenFindFile, compilerMsgHandler, hasToc)
docgenFindFile, docgenFindRefFile, compilerMsgHandler, hasToc)
initRstGenerator(result[], (if conf.isLatexCmd: outLatex else: outHtml),
conf.configVars, filename.string,
docgenFindFile, compilerMsgHandler)
@@ -373,7 +411,7 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
if gotten != status:
rawMessage(conf, errGenerated, "snippet failed: cmd: '$1' status: $2 expected: $3 output: $4" % [cmd, $gotten, $status, output])
result.emitted = initIntSet()
result.destFile = getOutFile2(conf, presentationPath(conf, filename), outExt, false).string
result.destFile = destFile
result.thisDir = result.destFile.AbsoluteFile.splitFile.dir
template dispA(conf: ConfigRef; dest: var string, xml, tex: string,
@@ -390,16 +428,19 @@ proc getVarIdx(varnames: openArray[string], id: string): int =
proc genComment(d: PDoc, n: PNode): PRstNode =
if n.comment.len > 0:
d.sharedState.currFileIdx = addRstFileIndex(d, n.info)
result = parseRst(n.comment,
toLinenumber(n.info),
toColumn(n.info) + DocColOffset,
d.conf, d.sharedState)
try:
result = parseRst(n.comment,
toLinenumber(n.info),
toColumn(n.info) + DocColOffset,
d.conf, d.sharedState)
except ERecoverableError:
result = newRstNode(rnLiteralBlock, @[newRstLeaf(n.comment)])
proc genRecCommentAux(d: PDoc, n: PNode): PRstNode =
if n == nil: return nil
result = genComment(d, n)
if result == nil:
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef,
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef, nkTypeClassTy,
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn, nkSinkAsgn, nkHiddenStdConv}:
# notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
for i in 0..<n.len:
@@ -537,10 +578,13 @@ proc runAllExamples(d: PDoc) =
# most useful semantics is that `docCmd` comes after `rdoccmd`, so that we can (temporarily) override
# via command line
# D20210224T221756:here
let cmd = "$nim $backend -r --lib:$libpath --warning:UnusedImport:off --path:$path --nimcache:$nimcache $rdoccmd $docCmd $file" % [
var pathArgs = "--path:$path" % [ "path", quoteShell(d.conf.projectPath) ]
for p in d.conf.searchPaths:
pathArgs = "$args --path:$path" % [ "args", pathArgs, "path", quoteShell(p) ]
let cmd = "$nim $backend -r --lib:$libpath --warning:UnusedImport:off $pathArgs --nimcache:$nimcache $rdoccmd $docCmd $file" % [
"nim", quoteShell(os.getAppFilename()),
"backend", $d.conf.backend,
"path", quoteShell(d.conf.projectPath),
"pathArgs", pathArgs,
"libpath", quoteShell(d.conf.libpath),
"nimcache", quoteShell(outputDir),
"file", quoteShell(outp),
@@ -558,7 +602,7 @@ proc runAllExamples(d: PDoc) =
proc quoted(a: string): string = result.addQuoted(a)
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): auto =
proc toInstantiationInfo(conf: ConfigRef, info: TLineInfo): (string, int, int) =
# xxx expose in compiler/lineinfos.nim
(conf.toMsgFilename(info), info.line.int, info.col.int + ColOffset)
@@ -575,7 +619,6 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
let useRenderModule = false
let loc = d.conf.toFileLineCol(n.info)
let code = extractRunnableExamplesSource(d.conf, n)
let codeIndent = extractRunnableExamplesSource(d.conf, n, indent = 2)
if d.conf.errorCounter > 0:
return (rdoccmd, code)
@@ -591,6 +634,7 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
docComment.comment = comment
var runnableExamples = newTree(nkStmtList,
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, "std/assertions")),
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
for a in n.lastSon: runnableExamples.add a
@@ -604,6 +648,7 @@ proc prepareExample(d: PDoc; n: PNode, topLevel: bool): tuple[rdoccmd: string, c
else:
var code2 = code
if code.len > 0 and "codeReordering" notin code:
let codeIndent = extractRunnableExamplesSource(d.conf, n, indent = 2)
# hacky but simplest solution, until we devise a way to make `{.line.}`
# work without introducing a scope
code2 = """
@@ -614,6 +659,7 @@ $#
#[
$#
]#
import std/assertions
import $#
$#
""" % [comment, d.filename.quoted, code2]
@@ -765,21 +811,24 @@ proc isVisible(d: PDoc; n: PNode): bool =
elif n.kind == nkPragmaExpr:
result = isVisible(d, n[0])
proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
proc getName(n: PNode): string =
case n.kind
of nkPostfix: result = getName(d, n[1], splitAfter)
of nkPragmaExpr: result = getName(d, n[0], splitAfter)
of nkSym: result = esc(d.target, n.sym.renderDefinitionName, splitAfter)
of nkIdent: result = esc(d.target, n.ident.s, splitAfter)
of nkPostfix: result = getName(n[1])
of nkPragmaExpr: result = getName(n[0])
of nkSym: result = n.sym.renderDefinitionName
of nkIdent: result = n.ident.s
of nkAccQuoted:
result = esc(d.target, "`")
for i in 0..<n.len: result.add(getName(d, n[i], splitAfter))
result.add esc(d.target, "`")
of nkOpenSymChoice, nkClosedSymChoice:
result = getName(d, n[0], splitAfter)
result = "`"
for i in 0..<n.len: result.add(getName(n[i]))
result = "`"
of nkOpenSymChoice, nkClosedSymChoice, nkOpenSym:
result = getName(n[0])
else:
result = ""
proc getNameEsc(d: PDoc, n: PNode): string =
esc(d.target, getName(n))
proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
case n.kind
of nkPostfix: result = getNameIdent(cache, n[1])
@@ -790,7 +839,7 @@ proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
var r = ""
for i in 0..<n.len: r.add(getNameIdent(cache, n[i]).s)
result = getIdent(cache, r)
of nkOpenSymChoice, nkClosedSymChoice:
of nkOpenSymChoice, nkClosedSymChoice, nkOpenSym:
result = getNameIdent(cache, n[0])
else:
result = nil
@@ -804,7 +853,7 @@ proc getRstName(n: PNode): PRstNode =
of nkAccQuoted:
result = getRstName(n[0])
for i in 1..<n.len: result.text.add(getRstName(n[i]).text)
of nkOpenSymChoice, nkClosedSymChoice:
of nkOpenSymChoice, nkClosedSymChoice, nkOpenSym:
result = getRstName(n[0])
else:
result = nil
@@ -928,6 +977,13 @@ proc symbolPriority(k: TSymKind): int =
else: 0 # including skProc which have higher priority
# documentation itself has even higher priority 1
proc getTypeKind(n: PNode): string =
case n[2].kind
of nkEnumTy: "enum"
of nkObjectTy: "object"
of nkTupleTy: "tuple"
else: ""
proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
## Converts symbol info (names/types/parameters) in `n` into format
## `LangSymbol` convenient for ``rst.nim``/``dochelpers.nim``.
@@ -962,7 +1018,7 @@ proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
var literal = ""
var r: TSrcGen
initTokRender(r, genNode, {renderNoBody, renderNoComments,
renderNoPragmas, renderNoProcDefs})
renderNoPragmas, renderNoProcDefs, renderExpandUsing})
var kind = tkEof
while true:
getNextTok(r, kind, literal)
@@ -971,17 +1027,13 @@ proc toLangSymbol(k: TSymKind, n: PNode, baseName: string): LangSymbol =
if kind != tkSpaces:
result.generics.add(literal.nimIdentNormalize)
if k == skType:
case n[2].kind
of nkEnumTy: result.symTypeKind = "enum"
of nkObjectTy: result.symTypeKind = "object"
of nkTupleTy: result.symTypeKind = "tuple"
else: discard
if k == skType: result.symTypeKind = getTypeKind(n)
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags, nonExports: bool = false) =
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
let
name = getName(d, nameNode)
name = getName(nameNode)
nameEsc = esc(d.target, name)
var plainDocstring = getPlainDocstring(n) # call here before genRecComment!
var result = ""
var literal, plainName = ""
@@ -995,7 +1047,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
var r: TSrcGen
# Obtain the plain rendered string for hyperlink titles.
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments,
renderNoPragmas, renderNoProcDefs})
renderNoPragmas, renderNoProcDefs, renderExpandUsing})
while true:
getNextTok(r, kind, literal)
if kind == tkEof:
@@ -1008,9 +1060,12 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
inc(d.id)
let
plainNameEsc = esc(d.target, plainName.strip)
detailedName = k.toHumanStr & " " & (
typeDescr =
if k == skType and getTypeKind(n) != "": getTypeKind(n)
else: k.toHumanStr
detailedName = typeDescr & " " & (
if k in routineKinds: plainName else: name)
uniqueName = if k in routineKinds: plainNameEsc else: name
uniqueName = if k in routineKinds: plainNameEsc else: nameEsc
sortName = if k in routineKinds: plainName.strip else: name
cleanPlainSymbol = renderPlainSymbolName(nameNode)
complexSymbol = complexName(k, n, cleanPlainSymbol)
@@ -1024,11 +1079,16 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
let lineinfo = rstast.TLineInfo(
line: nameNode.info.line, col: nameNode.info.col,
fileIndex: addRstFileIndex(d, nameNode.info))
addAnchorNim(d.sharedState, refn = symbolOrId, tooltip = detailedName,
rstLangSymbol, priority = symbolPriority(k), info = lineinfo)
addAnchorNim(d.sharedState, external = false, refn = symbolOrId,
tooltip = detailedName, langSym = rstLangSymbol,
priority = symbolPriority(k), info = lineinfo,
module = addRstFileIndex(d, FileIndex d.module.position))
nodeToHighlightedHtml(d, n, result, {renderNoBody, renderNoComments,
renderDocComments, renderSyms}, symbolOrIdEnc)
let renderFlags =
if nonExports: {renderNoBody, renderNoComments, renderDocComments, renderSyms,
renderExpandUsing, renderNonExportedFields}
else: {renderNoBody, renderNoComments, renderDocComments, renderSyms, renderExpandUsing}
nodeToHighlightedHtml(d, n, result, renderFlags, symbolOrIdEnc)
let seeSrc = genSeeSrc(d, toFullPath(d.conf, n.info), n.info.line.int)
@@ -1060,8 +1120,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
if e.sym.kind != skEnumField: continue
let plain = renderPlainSymbolName(e)
let symbolOrId = d.newUniquePlainSymbol(plain)
setIndexTerm(d[], external, symbolOrId, plain, nameNode.sym.name.s & '.' & plain,
xmltree.escape(getPlainDocstring(e).docstringSummary))
setIndexTerm(d[], ieNim, htmlFile = external, id = symbolOrId,
term = plain, linkTitle = nameNode.sym.name.s & '.' & plain,
linkDesc = xmltree.escape(getPlainDocstring(e).docstringSummary),
line = n.info.line.int)
d.tocSimple[k].add TocItem(
sortName: sortName,
@@ -1076,25 +1138,23 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
"itemSymOrID", symbolOrId.replace(",", ",<wbr>"),
"itemSymOrIDEnc", symbolOrIdEnc])
# Ironically for types the complexSymbol is *cleaner* than the plainName
# because it doesn't include object fields or documentation comments. So we
# use the plain one for callable elements, and the complex for the rest.
var linkTitle = changeFileExt(extractFilename(d.filename), "") & ": "
if n.kind in routineDefs: linkTitle.add(xmltree.escape(plainName.strip))
else: linkTitle.add(xmltree.escape(complexSymbol.strip))
setIndexTerm(d[], external, symbolOrId, name, linkTitle,
xmltree.escape(plainDocstring.docstringSummary))
setIndexTerm(d[], ieNim, htmlFile = external, id = symbolOrId, term = name,
linkTitle = detailedName,
linkDesc = xmltree.escape(plainDocstring.docstringSummary),
line = n.info.line.int)
if k == skType and nameNode.kind == nkSym:
d.types.strTableAdd nameNode.sym
proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonItem =
proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind, nonExports = false): JsonItem =
if not isVisible(d, nameNode): return
var
name = getName(d, nameNode)
name = getNameEsc(d, nameNode)
comm = genRecComment(d, n)
r: TSrcGen
initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments})
renderFlags = {renderNoBody, renderNoComments, renderDocComments, renderExpandUsing}
if nonExports:
renderFlags.incl renderNonExportedFields
initTokRender(r, n, renderFlags)
result.json = %{ "name": %name, "type": %($k), "line": %n.info.line.int,
"col": %n.info.col}
if comm != nil:
@@ -1279,12 +1339,13 @@ proc documentRaises*(cache: IdentCache; n: PNode) =
if p5 != nil: n[pragmasPos].add p5
if p6 != nil: n[pragmasPos].add p6
proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
proc generateDoc*(d: PDoc, n, orig: PNode, config: ConfigRef, docFlags: DocFlags = kDefault) =
## Goes through nim nodes recursively and collects doc comments.
## Main function for `doc`:option: command,
## which is implemented in ``docgen2.nim``.
template genItemAux(skind) =
genItem(d, n, n[namePos], skind, docFlags)
let showNonExports = optShowNonExportedFields in config.globalOptions
case n.kind
of nkPragma:
let pragmaNode = findPragma(n, wDeprecated)
@@ -1311,20 +1372,20 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
genItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)), docFlags)
succ(skType, ord(n.kind)-ord(nkTypeSection)), docFlags, showNonExports)
of nkStmtList:
for i in 0..<n.len: generateDoc(d, n[i], orig)
for i in 0..<n.len: generateDoc(d, n[i], orig, config)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n[0][0]):
generateDoc(d, lastSon(n[0]), orig)
generateDoc(d, lastSon(n[0]), orig, config)
of nkImportStmt:
for it in n: traceDeps(d, it)
of nkExportStmt:
for it in n:
if it.kind == nkSym:
if d.module != nil and d.module == it.sym.owner:
generateDoc(d, it.sym.ast, orig, kForceExport)
generateDoc(d, it.sym.ast, orig, config, kForceExport)
elif it.sym.ast != nil:
exportSym(d, it.sym)
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
@@ -1337,9 +1398,31 @@ proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
proc overloadGroupName(s: string, k: TSymKind): string =
## Turns a name like `f` into anchor `f-procs-all`
#s & " " & k.toHumanStr & "s all"
s & "-" & k.toHumanStr & "s-all"
proc setIndexTitle(d: PDoc, useMetaTitle: bool) =
let titleKind = if d.standaloneDoc: ieMarkupTitle else: ieNimTitle
let external = AbsoluteFile(d.destFile)
.relativeTo(d.conf.outDir, '/')
.changeFileExt(HtmlExt)
.string
var term, linkTitle: string
if useMetaTitle and d.meta[metaTitle].len != 0:
term = d.meta[metaTitleRaw]
linkTitle = d.meta[metaTitleRaw]
else:
let filename = extractFilename(d.filename)
term =
if d.standaloneDoc: filename # keep .rst/.md extension
else: changeFileExt(filename, "") # rm .nim extension
linkTitle =
if d.standaloneDoc: term # keep .rst/.md extension
else: canonicalImport(d.conf, AbsoluteFile d.filename)
if not d.standaloneDoc:
linkTitle = "module " & linkTitle
setIndexTerm(d[], titleKind, htmlFile = external, id = "",
term = term, linkTitle = linkTitle)
proc finishGenerateDoc*(d: var PDoc) =
## Perform 2nd RST pass for resolution of links/footnotes/headings...
# copy file map `filenames` to ``rstgen.nim`` for its warnings
@@ -1352,7 +1435,24 @@ proc finishGenerateDoc*(d: var PDoc) =
firstRst = fragment.rst
break
d.hasToc = d.hasToc or d.sharedState.hasToc
preparePass2(d.sharedState, firstRst)
# in --index:only mode we do NOT want to load other .idx, only write ours:
let importdoc = optGenIndexOnly notin d.conf.globalOptions and
optNoImportdoc notin d.conf.globalOptions
preparePass2(d.sharedState, firstRst, importdoc)
if optGenIndexOnly in d.conf.globalOptions:
# Top-level doc.comments may contain titles and :idx: statements:
for fragment in d.modDescPre:
if fragment.isRst:
traverseForIndex(d[], fragment.rst)
setIndexTitle(d, useMetaTitle = d.standaloneDoc)
# Symbol-associated doc.comments may contain :idx: statements:
for k in TSymKind:
for _, overloadChoices in d.section[k].secItems:
for item in overloadChoices:
for fragment in item.descRst:
if fragment.isRst:
traverseForIndex(d[], fragment.rst)
# add anchors to overload groups before RST resolution
for k in TSymKind:
@@ -1362,13 +1462,25 @@ proc finishGenerateDoc*(d: var PDoc) =
let refn = overloadGroupName(plainName, k)
let tooltip = "$1 ($2 overloads)" % [
k.toHumanStr & " " & plainName, $overloadChoices.len]
addAnchorNim(d.sharedState, refn, tooltip,
let name = nimIdentBackticksNormalize(plainName)
# save overload group to ``.idx``
let external = d.destFile.AbsoluteFile.relativeTo(d.conf.outDir, '/').
changeFileExt(HtmlExt).string
setIndexTerm(d[], ieNimGroup, htmlFile = external, id = refn,
term = name, linkTitle = k.toHumanStr,
linkDesc = "", line = overloadChoices[0].info.line.int)
if optGenIndexOnly in d.conf.globalOptions: continue
addAnchorNim(d.sharedState, external=false, refn, tooltip,
LangSymbol(symKind: k.toHumanStr,
name: nimIdentBackticksNormalize(plainName),
name: name,
isGroup: true),
priority = symbolPriority(k),
# select index `0` just to have any meaningful warning:
info = overloadChoices[0].info)
info = overloadChoices[0].info,
module = addRstFileIndex(d, FileIndex d.module.position))
if optGenIndexOnly in d.conf.globalOptions:
return
# Finalize fragments of ``.nim`` or ``.rst`` file
proc renderItemPre(d: PDoc, fragments: ItemPre, result: var string) =
@@ -1421,10 +1533,13 @@ proc finishGenerateDoc*(d: var PDoc) =
d.jEntriesFinal.add entry.json # generates docs
setIndexTitle(d, useMetaTitle = d.standaloneDoc)
completePass2(d.sharedState)
proc add(d: PDoc; j: JsonItem) =
if j.json != nil or j.rst != nil: d.jEntriesPre.add j
proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
proc generateJson*(d: PDoc, n: PNode, config: ConfigRef, includeComments: bool = true) =
case n.kind
of nkPragma:
let doctypeNode = findPragma(n, wDoctype)
@@ -1456,18 +1571,18 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
d.add genJsonItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
succ(skType, ord(n.kind)-ord(nkTypeSection)), optShowNonExportedFields in config.globalOptions)
of nkStmtList:
for i in 0..<n.len:
generateJson(d, n[i], includeComments)
generateJson(d, n[i], config, includeComments)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n[0][0]):
generateJson(d, lastSon(n[0]), includeComments)
generateJson(d, lastSon(n[0]), config, includeComments)
else: discard
proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
result = getName(d, nameNode) & "\n"
result = getNameEsc(d, nameNode) & "\n"
proc generateTags*(d: PDoc, n: PNode, r: var string) =
case n.kind
@@ -1574,13 +1689,7 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
# Extract the title. Non API modules generate an entry in the index table.
if d.meta[metaTitle].len != 0:
title = d.meta[metaTitle]
let external = AbsoluteFile(d.destFile)
.relativeTo(d.conf.outDir, '/')
.changeFileExt(HtmlExt)
.string
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
title = canonicalImport(d.conf, AbsoluteFile d.filename)
title = esc(d.target, title)
var subtitle = ""
@@ -1614,16 +1723,22 @@ proc genOutFile(d: PDoc, groupedToc = false): string =
"moduledesc", d.modDescFinal, "date", getDateStr(), "time", getClockStr(),
"content", content, "author", d.meta[metaAuthor],
"version", esc(d.target, d.meta[metaVersion]), "analytics", d.analytics,
"deprecationMsg", d.modDeprecationMsg]
"deprecationMsg", d.modDeprecationMsg, "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
else:
code = content
result = code
proc indexFile(d: PDoc): AbsoluteFile =
let dir = d.conf.outDir
result = dir / changeFileExt(presentationPath(d.conf,
AbsoluteFile d.filename),
IndexExt)
let (finalDir, _, _) = result.string.splitFile
createDir(finalDir)
proc generateIndex*(d: PDoc) =
if optGenIndex in d.conf.globalOptions:
let dir = d.conf.outDir
createDir(dir)
let dest = dir / changeFileExt(presentationPath(d.conf, AbsoluteFile d.filename), IndexExt)
let dest = indexFile(d)
writeIndexFile(d[], dest.string)
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
@@ -1634,6 +1749,9 @@ proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
d.conf.outFile = splitPath(d.conf.outFile.string)[1].RelativeFile
proc writeOutput*(d: PDoc, useWarning = false, groupedToc = false) =
if optGenIndexOnly in d.conf.globalOptions:
d.conf.outFile = indexFile(d).relativeTo(d.conf.outDir) # just for display
return
runAllExamples(d)
var content = genOutFile(d, groupedToc)
if optStdout in d.conf.globalOptions:
@@ -1698,7 +1816,7 @@ proc commandDoc*(cache: IdentCache, conf: ConfigRef) =
var ast = parseFile(conf.projectMainIdx, cache, conf)
if ast == nil: return
var d = newDocumentor(conf.projectFull, cache, conf, hasToc = true)
generateDoc(d, ast, ast)
generateDoc(d, ast, ast, conf)
finishGenerateDoc(d)
writeOutput(d)
generateIndex(d)
@@ -1709,13 +1827,16 @@ proc commandRstAux(cache: IdentCache, conf: ConfigRef;
var filen = addFileExt(filename, "txt")
var d = newDocumentor(filen, cache, conf, outExt, standaloneDoc = true,
preferMarkdown = preferMarkdown, hasToc = false)
let rst = parseRst(readFile(filen.string),
line=LineRstInit, column=ColRstInit,
conf, d.sharedState)
d.modDescPre = @[ItemFragment(isRst: true, rst: rst)]
finishGenerateDoc(d)
writeOutput(d)
generateIndex(d)
try:
let rst = parseRst(readFile(filen.string),
line=LineRstInit, column=ColRstInit,
conf, d.sharedState)
d.modDescPre = @[ItemFragment(isRst: true, rst: rst)]
finishGenerateDoc(d)
writeOutput(d)
generateIndex(d)
except ERecoverableError:
discard "already reported the error"
proc commandRst2Html*(cache: IdentCache, conf: ConfigRef,
preferMarkdown=false) =
@@ -1734,7 +1855,7 @@ proc commandJson*(cache: IdentCache, conf: ConfigRef) =
status: int; content: string) {.gcsafe.} =
localError(conf, newLineInfo(conf, AbsoluteFile d.filename, -1, -1),
warnUser, "the ':test:' attribute is not supported by this backend")
generateJson(d, ast)
generateJson(d, ast, conf)
finishGenerateDoc(d)
let json = d.jEntriesFinal
let content = pretty(json)
@@ -1746,7 +1867,7 @@ proc commandJson*(cache: IdentCache, conf: ConfigRef) =
let filename = getOutFile(conf, RelativeFile conf.projectName, JsonExt)
try:
writeFile(filename, content)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandTags*(cache: IdentCache, conf: ConfigRef) =
@@ -1768,10 +1889,12 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
let filename = getOutFile(conf, RelativeFile conf.projectName, TagsExt)
try:
writeFile(filename, content)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
if optGenIndexOnly in conf.globalOptions:
return
var content = mergeIndexes(dir)
var outFile = outFile
@@ -1784,12 +1907,12 @@ proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"")
"title", "Index",
"subtitle", "", "tableofcontents", "", "moduledesc", "",
"date", getDateStr(), "time", getClockStr(),
"content", content, "author", "", "version", "", "analytics", ""]
"content", content, "author", "", "version", "", "analytics", "", "nimVersion", $NimMajor & "." & $NimMinor & "." & $NimPatch]
# no analytics because context is not available
try:
writeFile(filename, code)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndexJson*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
@@ -1803,5 +1926,5 @@ proc commandBuildIndexJson*(conf: ConfigRef, dir: string, outFile = RelativeFile
try:
writeFile(filename, $body)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)

View File

@@ -11,7 +11,7 @@
# semantic checking.
import
options, ast, msgs, passes, docgen, lineinfos, pathutils, packages
options, ast, msgs, docgen, lineinfos, pathutils, packages
from modulegraphs import ModuleGraph, PPassContext
@@ -38,25 +38,25 @@ template closeImpl(body: untyped) {.dirty.} =
except IOError:
discard
proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
proc closeDoc*(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
writeOutput(g.doc, useWarning, groupedToc)
proc closeJson(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
proc closeJson*(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
writeOutputJson(g.doc, useWarning)
proc processNode(c: PPassContext, n: PNode): PNode =
proc processNode*(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
if shouldProcess(g):
generateDoc(g.doc, n, n)
generateDoc(g.doc, n, n, g.config)
proc processNodeJson(c: PPassContext, n: PNode): PNode =
proc processNodeJson*(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
if shouldProcess(g):
generateJson(g.doc, n, false)
generateJson(g.doc, n, g.config, false)
template myOpenImpl(ext: untyped) {.dirty.} =
var g: PGen
@@ -68,20 +68,11 @@ template myOpenImpl(ext: untyped) {.dirty.} =
g.doc = d
result = g
proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
proc openHtml*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
myOpenImpl(HtmlExt)
proc myOpenTex(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
proc openTex*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
myOpenImpl(TexExt)
proc myOpenJson(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
proc openJson*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
myOpenImpl(JsonExt)
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
const docgen2TexPass* = makePass(open = myOpenTex, process = processNode,
close = close)
const docgen2JsonPass* = makePass(open = myOpenJson, process = processNodeJson,
close = closeJson)
proc finishDoc2Pass*(project: string) =
discard

View File

@@ -6,12 +6,12 @@ when defined(nimPreviewSlimSystem):
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "$"), nextSymId idgen, t.owner, info)
result = newSym(skProc, getIdent(g.cache, "$"), idgen, t.owner, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), nextSymId idgen, result, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), idgen, result, info)
dest.typ = t
let res = newSym(skResult, getIdent(g.cache, "result"), nextSymId idgen, result, info)
let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info)
res.typ = getSysType(g, info, tyString)
result.typ = newType(tyProc, nextTypeId idgen, t.owner)
@@ -67,12 +67,12 @@ proc searchObjCase(t: PType; field: PSym): PNode =
doAssert result != nil
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), nextSymId idgen, t.owner, info)
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), idgen, t.owner, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), nextSymId idgen, result, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), idgen, result, info)
dest.typ = field.typ
let res = newSym(skResult, getIdent(g.cache, "result"), nextSymId idgen, result, info)
let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info)
res.typ = getSysType(g, info, tyUInt8)
result.typ = newType(tyProc, nextTypeId idgen, t.owner)

View File

@@ -77,7 +77,7 @@ proc importcSymbol*(conf: ConfigRef, sym: PSym): PNode =
theAddr = dllhandle.symAddr(name.cstring)
if theAddr.isNil: globalError(conf, sym.info,
"cannot import symbol: " & name & " from " & libPathMsg)
result.intVal = cast[ByteAddress](theAddr)
result.intVal = cast[int](theAddr)
proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.Type =
if t == nil: return addr libffi.type_void
@@ -113,7 +113,7 @@ proc mapCallConv(conf: ConfigRef, cc: TCallingConvention, info: TLineInfo): TABI
template rd(typ, p: untyped): untyped = (cast[ptr typ](p))[]
template wr(typ, p, v: untyped): untyped = (cast[ptr typ](p))[] = v
template `+!`(x, y: untyped): untyped =
cast[pointer](cast[ByteAddress](x) + y)
cast[pointer](cast[int](x) + y)
proc packSize(conf: ConfigRef, v: PNode, typ: PType): int =
## computes the size of the blob
@@ -369,13 +369,13 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
# in their unboxed representation so nothing it to be unpacked:
result = n
else:
awi(nkPtrLit, cast[ByteAddress](p))
awi(nkPtrLit, cast[int](p))
of tyPtr, tyRef, tyVar, tyLent:
let p = rd(pointer, x)
if p.isNil:
setNil()
elif n == nil or n.kind == nkPtrLit:
awi(nkPtrLit, cast[ByteAddress](p))
awi(nkPtrLit, cast[int](p))
elif n != nil and n.len == 1:
internalAssert(conf, n.kind == nkRefTy)
n[0] = unpack(conf, p, typ.lastSon, n[0])

View File

@@ -10,7 +10,7 @@
## Template evaluation engine. Now hygienic.
import
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents, trees
type
TemplCtx = object
@@ -49,13 +49,14 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
var x = PSym(idTableGet(c.mapping, s))
if x == nil:
x = copySym(s, nextSymId(c.idgen))
x = copySym(s, c.idgen)
# sem'check needs to set the owner properly later, see bug #9476
x.owner = nil # c.genSymOwner
#if x.kind == skParam and x.owner.kind == skModule:
# internalAssert c.config, false
idTablePut(c.mapping, s, x)
if sfGenSym in s.flags:
# TODO: getIdent(c.ic, "`" & x.name.s & "`gensym" & $c.instID)
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $c.instID),
if c.instLines: actual.info else: templ.info)
else:

View File

@@ -14,12 +14,14 @@
import ropes, platform, condsyms, options, msgs, lineinfos, pathutils, modulepaths
import std/[os, osproc, sha1, streams, sequtils, times, strtabs, json, jsonutils, sugar, parseutils]
import std/[os, osproc, streams, sequtils, times, strtabs, json, jsonutils, sugar, parseutils]
import std / strutils except addf
when defined(nimPreviewSlimSystem):
import std/syncio
import std/[syncio, assertions]
import ../dist/checksums/src/checksums/sha1
type
TInfoCCProp* = enum # properties of the C compiler:
@@ -31,6 +33,7 @@ type
hasGnuAsm, # CC's asm uses the absurd GNU assembler syntax
hasDeclspec, # CC has __declspec(X)
hasAttribute, # CC has __attribute__((X))
hasBuiltinUnreachable # CC has __builtin_unreachable
TInfoCCProps* = set[TInfoCCProp]
TInfoCC* = tuple[
name: string, # the short name of the compiler
@@ -93,7 +96,7 @@ compiler gcc:
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++17 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
hasAttribute, hasBuiltinUnreachable})
# GNU C and C++ Compiler
compiler nintendoSwitchGCC:
@@ -120,7 +123,7 @@ compiler nintendoSwitchGCC:
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++17 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
hasAttribute, hasBuiltinUnreachable})
# LLVM Frontend for GCC/G++
compiler llvmGcc:
@@ -328,7 +331,9 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
platform.OS[conf.target.targetOS].name & '.' &
CC[c].name & fullSuffix
result = getConfigVar(conf, fullCCname)
if result.len == 0:
if existsConfigVar(conf, fullCCname):
result = getConfigVar(conf, fullCCname)
else:
# not overridden for this cross compilation setting?
result = getConfigVar(conf, CC[c].name & fullSuffix)
else:
@@ -528,7 +533,7 @@ proc ccHasSaneOverflow*(conf: ConfigRef): bool =
var exe = getConfigVar(conf, conf.cCompiler, ".exe")
if exe.len == 0: exe = CC[conf.cCompiler].compilerExe
# NOTE: should we need the full version, use -dumpfullversion
let (s, exitCode) = try: execCmdEx(exe & " -dumpversion") except: ("", 1)
let (s, exitCode) = try: execCmdEx(exe & " -dumpversion") except IOError, OSError, ValueError: ("", 1)
if exitCode == 0:
var major: int
discard parseInt(s, major)
@@ -576,7 +581,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
compilePattern = joinPath(conf.cCompilerPath, exe)
else:
compilePattern = getCompilerExe(conf, c, isCpp)
compilePattern = exe
includeCmd.add(join([CC[c].includeCmd, quoteShell(conf.projectPath.string)]))
@@ -830,10 +835,22 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
else:
writeFile(linkerArgs, args)
try:
execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
when defined(macosx):
execLinkCmd(conf, "xargs " & cmd.substr(0, last) & " < " & linkerArgs)
else:
execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
finally:
removeFile(linkerArgs)
proc linkViaShellScript(conf: ConfigRef; cmd: string) =
let linkerScript = conf.projectName & "_" & "linkerScript.sh"
writeFile(linkerScript, cmd)
let shell = getEnv("SHELL")
try:
execLinkCmd(conf, shell & " " & linkerScript)
finally:
removeFile(linkerScript)
proc getObjFilePath(conf: ConfigRef, f: Cfile): string =
if noAbsolutePaths(conf): f.obj.extractFilename
else: f.obj.string
@@ -851,6 +868,20 @@ proc displayProgressCC(conf: ConfigRef, path, compileCmd: string): string =
else:
result = MsgKindToStr[hintCC] % demangleModuleName(path.splitFile.name)
proc preventLinkCmdMaxCmdLen(conf: ConfigRef, linkCmd: string) =
# Prevent linkcmd from exceeding the maximum command line length.
# Windows's command line limit is about 8K (8191 characters) so C compilers on
# Windows support a feature where the command line can be passed via ``@linkcmd``
# to them.
const MaxCmdLen = when defined(windows): 8_000 elif defined(macosx): 260_000 else: 32_000
if linkCmd.len > MaxCmdLen:
when defined(macosx):
linkViaShellScript(conf, linkCmd)
else:
linkViaResponseFile(conf, linkCmd)
else:
execLinkCmd(conf, linkCmd)
proc callCCompiler*(conf: ConfigRef) =
var
linkCmd: string
@@ -927,14 +958,7 @@ proc callCCompiler*(conf: ConfigRef) =
linkCmd = getLinkCmd(conf, mainOutput, objfiles, removeStaticFile = true)
extraCmds = getExtraCmds(conf, mainOutput)
if optCompileOnly notin conf.globalOptions:
const MaxCmdLen = when defined(windows): 8_000 else: 32_000
if linkCmd.len > MaxCmdLen:
# Windows's command line limit is about 8K (don't laugh...) so C compilers on
# Windows support a feature where the command line can be passed via ``@linkcmd``
# to them.
linkViaResponseFile(conf, linkCmd)
else:
execLinkCmd(conf, linkCmd)
preventLinkCmdMaxCmdLen(conf, linkCmd)
for cmd in extraCmds:
execExternalProgram(conf, cmd, hintExecuting)
else:
@@ -969,7 +993,7 @@ type BuildCache = object
depfiles: seq[(string, string)]
nimexe: string
proc writeJsonBuildInstructions*(conf: ConfigRef) =
proc writeJsonBuildInstructions*(conf: ConfigRef; deps: StringTableRef) =
var linkFiles = collect(for it in conf.externalToLink:
var it = it
if conf.noAbsolutePaths: it = it.extractFilename
@@ -990,10 +1014,14 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
currentDir: getCurrentDir())
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
bcache.cmdline = conf.commandLine
bcache.depfiles = collect(for it in conf.m.fileInfos:
for it in conf.m.fileInfos:
let path = it.fullPath.string
if isAbsolute(path): # TODO: else?
(path, $secureHashFile(path)))
if path in deps:
bcache.depfiles.add (path, deps[path])
else: # backup for configs etc.
bcache.depfiles.add (path, $secureHashFile(path))
bcache.nimexe = hashNimExe()
conf.jsonBuildFile = conf.jsonBuildInstructionsFile
conf.jsonBuildFile.string.writeFile(bcache.toJson.pretty)
@@ -1018,7 +1046,7 @@ proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; jsonFile: Absolute
proc runJsonBuildInstructions*(conf: ConfigRef; jsonFile: AbsoluteFile) =
var bcache: BuildCache
try: bcache.fromJson(jsonFile.string.parseFile)
except:
except ValueError, KeyError, JsonKindError:
let e = getCurrentException()
conf.quitOrRaise "\ncaught exception:\n$#\nstacktrace:\n$#error evaluating JSON file: $#" %
[e.msg, e.getStackTrace(), jsonFile.string]
@@ -1035,7 +1063,7 @@ proc runJsonBuildInstructions*(conf: ConfigRef; jsonFile: AbsoluteFile) =
cmds.add cmd
prettyCmds.add displayProgressCC(conf, name, cmd)
execCmdsInParallel(conf, cmds, prettyCb)
execLinkCmd(conf, bcache.linkcmd)
preventLinkCmdMaxCmdLen(conf, bcache.linkcmd)
for cmd in bcache.extraCmds: execExternalProgram(conf, cmd, hintExecuting)
proc genMappingFiles(conf: ConfigRef; list: CfileList): Rope =

View File

@@ -9,12 +9,14 @@
## Module that implements ``gorge`` for the compiler.
import msgs, std / sha1, os, osproc, streams, options,
import msgs, os, osproc, streams, options,
lineinfos, pathutils
when defined(nimPreviewSlimSystem):
import std/syncio
import ../dist/checksums/src/checksums/sha1
proc readOutput(p: Process): (string, int) =
result[0] = ""
var output = p.outputStream

View File

@@ -10,9 +10,6 @@
# This include implements the high level optimization pass.
# included from sem.nim
when defined(nimPreviewSlimSystem):
import std/assertions
proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =

View File

@@ -50,7 +50,10 @@ proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var Alive
let n = unpackTree(g, m.module.position, m.fromDisk.topLevel, p)
cgen.genTopLevelStmt(bmod, n)
finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
let disps = finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
if disps != nil:
for disp in disps:
genProcAux(bmod, disp.sym)
m.fromDisk.backendFlags = cgen.whichInitProcs(bmod)
proc replayTypeInfo(g: ModuleGraph; m: var LoadedModule; origin: FileIndex) =

View File

@@ -7,13 +7,15 @@
# distribution, for details about the copyright.
#
import hashes, tables, intsets, std/sha1
import hashes, tables, intsets
import packed_ast, bitabs, rodfiles
import ".." / [ast, idents, lineinfos, msgs, ropes, options,
pathutils, condsyms, packages, modulepaths]
#import ".." / [renderer, astalgo]
from os import removeFile, isAbsolute
import ../../dist/checksums/src/checksums/sha1
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, formatfloat]
@@ -372,7 +374,7 @@ proc toPackedLib(l: PLib; c: var PackedEncoder; m: var PackedModule): PackedLib
if l.isNil: return
result.kind = l.kind
result.generated = l.generated
result.isOverriden = l.isOverriden
result.isOverridden = l.isOverridden
result.name = toLitId($l.name, m)
storeNode(result, l, path)
@@ -390,7 +392,7 @@ proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId
assert sfForward notin s.flags
var p = PackedSym(kind: s.kind, flags: s.flags, info: s.info.toPackedInfo(c, m), magic: s.magic,
position: s.position, offset: s.offset, options: s.options,
position: s.position, offset: s.offset, disamb: s.disamb, options: s.options,
name: s.name.s.toLitId(m))
storeNode(p, s, ast)
@@ -419,7 +421,7 @@ proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pac
## add a remote symbol reference to the tree
let info = n.info.toPackedInfo(c, m)
ir.nodes.add PackedNode(kind: nkModuleRef, operand: 3.int32, # spans 3 nodes in total
typeId: storeTypeLater(n.typ, c, m), info: info)
typeId: storeTypeLater(n.typ, c, m), info: info, flags: n.flags)
ir.nodes.add PackedNode(kind: nkInt32Lit, info: info,
operand: toLitId(n.sym.itemId.module.FileIndex, c, m).int32)
ir.nodes.add PackedNode(kind: nkInt32Lit, info: info,
@@ -766,6 +768,8 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
result.ident = getIdent(c.cache, g[thisModule].fromDisk.strings[n.litId])
of nkSym:
result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree.nodes[n.int].operand))
if result.typ == nil:
result.typ = result.sym.typ
of directIntLit:
result.intVal = tree.nodes[n.int].operand
of externIntLit:
@@ -780,6 +784,8 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
assert n2.kind == nkInt32Lit
transitionNoneToSym(result)
result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree.nodes[n2.int].operand))
if result.typ == nil:
result.typ = result.sym.typ
else:
for n0 in sonsReadonly(tree, n):
result.addAllowNil loadNodes(c, g, thisModule, tree, n0)
@@ -830,6 +836,7 @@ proc symHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
options: s.options,
position: if s.kind in {skForVar, skVar, skLet, skTemp}: 0 else: s.position,
offset: if s.kind in routineKinds: defaultOffset else: s.offset,
disamb: s.disamb,
name: getIdent(c.cache, g[si].fromDisk.strings[s.name])
)
@@ -847,7 +854,7 @@ proc loadLib(c: var PackedDecoder; g: var PackedModuleGraph;
if l.name.int == 0:
result = nil
else:
result = PLib(generated: l.generated, isOverriden: l.isOverriden,
result = PLib(generated: l.generated, isOverridden: l.isOverridden,
kind: l.kind, name: rope g[si].fromDisk.strings[l.name])
loadAstBody(l, path)

View File

@@ -45,7 +45,7 @@ type
PackedLib* = object
kind*: TLibKind
generated*: bool
isOverriden*: bool
isOverridden*: bool
name*: LitId
path*: NodeId
@@ -63,7 +63,8 @@ type
alignment*: int # for alignment
options*: TOptions
position*: int
offset*: int
offset*: int32
disamb*: int32
externalName*: LitId # instead of TLoc
locFlags*: TLocFlags
annex*: PackedLib

View File

@@ -24,7 +24,7 @@ when defined(nimPreviewSlimSystem):
## `RodFile` represents a Rod File (versioned binary format), and the
## associated data for common interactions such as IO and error tracking
## (`RodFileError`). The file format broken up into sections (`RodSection`)
## and preceeded by a header (see: `cookie`). The precise layout, section
## and preceded by a header (see: `cookie`). The precise layout, section
## ordering and data following the section are determined by the user. See
## `ic.loadRodFile`.
##

View File

@@ -228,10 +228,15 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym; im
for i in 0..n.safeLen-1:
importForwarded(c, n[i], exceptSet, fromMod, importSet)
proc addUnique[T](x: var seq[T], y: sink T) {.noSideEffect.} =
for i in 0..high(x):
if x[i] == y: return
x.add y
proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool): PSym =
result = realModule
template createModuleAliasImpl(ident): untyped =
createModuleAlias(realModule, nextSymId c.idgen, ident, n.info, c.config.options)
createModuleAlias(realModule, c.idgen, ident, n.info, c.config.options)
if n.kind != nkImportAs: discard
elif n.len != 2 or n[1].kind != nkIdent:
localError(c.config, n.info, "module alias must be an identifier")
@@ -245,6 +250,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool)
result.options.incl optImportHidden
c.unusedImports.add((result, n.info))
c.importModuleMap[result.id] = realModule.id
c.importModuleLookup.mgetOrPut(result.name.id, @[]).addUnique realModule.id
proc transformImportAs(c: PContext; n: PNode): tuple[node: PNode, importHidden: bool] =
var ret: typeof(result)
@@ -298,7 +304,15 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym =
var prefix = ""
if realModule.constraint != nil: prefix = realModule.constraint.strVal & "; "
message(c.config, n.info, warnDeprecated, prefix & realModule.name.s & " is deprecated")
suggestSym(c.graph, n.info, result, c.graph.usageSym, false)
proc suggestMod(n: PNode; s: PSym) =
if n.kind == nkImportAs:
suggestMod(n[0], realModule)
elif n.kind == nkInfix:
suggestMod(n[2], s)
else:
suggestSym(c.graph, n.info, s, c.graph.usageSym, false)
suggestMod(n, result)
importStmtResult.add newSymNode(result, n.info)
#newStrNode(toFullPath(c.config, f), n.info)
@@ -323,22 +337,26 @@ proc evalImport*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
for i in 0..<n.len:
let it = n[i]
if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
let sep = it[0]
let dir = it[1]
var imp = newNodeI(nkInfix, it.info)
imp.add sep
imp.add dir
imp.add sep # dummy entry, replaced in the loop
for x in it[2]:
if it.kind in {nkInfix, nkPrefix} and it[^1].kind == nkBracket:
let lastPos = it.len - 1
var imp = copyNode(it)
newSons(imp, it.len)
for i in 0 ..< lastPos: imp[i] = it[i]
imp[lastPos] = imp[0] # dummy entry, replaced in the loop
for x in it[lastPos]:
# transform `a/b/[c as d]` to `/a/b/c as d`
if x.kind == nkInfix and x[0].ident.s == "as":
let impAs = copyTree(x)
imp[2] = x[1]
var impAs = copyNode(x)
newSons(impAs, 3)
impAs[0] = x[0]
imp[lastPos] = x[1]
impAs[1] = imp
impMod(c, imp, result)
impAs[2] = x[2]
impAs.info = x[2].info
impMod(c, impAs, result)
else:
imp[2] = x
imp[lastPos] = x
imp.info = x.info
impMod(c, imp, result)
else:
impMod(c, it, result)

View File

@@ -17,12 +17,12 @@ import
intsets, strtabs, ast, astalgo, msgs, renderer, magicsys, types, idents,
strutils, options, lowerings, tables, modulegraphs,
lineinfos, parampatterns, sighashes, liftdestructors, optimizer,
varpartitions, aliasanalysis, dfa
varpartitions, aliasanalysis, dfa, wordrecg
when defined(nimPreviewSlimSystem):
import std/assertions
from trees import exprStructuralEquivalent, getRoot
from trees import exprStructuralEquivalent, getRoot, whichPragma
type
Con = object
@@ -35,6 +35,8 @@ type
idgen: IdGenerator
body: PNode
otherUsage: TLineInfo
inUncheckedAssignSection: int
inEnsureMove: int
Scope = object # we do scope-based memory management.
# a scope is comparable to an nkStmtListExpr like
@@ -65,11 +67,11 @@ proc hasDestructor(c: Con; t: PType): bool {.inline.} =
result = ast.hasDestructor(t)
when toDebug.len > 0:
# for more effective debugging
if not result and c.graph.config.selectedGC in {gcArc, gcOrc}:
if not result and c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
assert(not containsGarbageCollectedRef(t))
proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), nextSymId c.idgen, c.owner, info)
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.idgen, c.owner, info)
sym.typ = typ
s.vars.add(sym)
result = newSymNode(sym)
@@ -77,11 +79,11 @@ proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
proc nestedScope(parent: var Scope; body: PNode): Scope =
Scope(vars: @[], locals: @[], wasMoved: @[], final: @[], body: body, needsTry: false, parent: addr(parent))
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}): PNode
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}; inReturn = false): PNode
type
MoveOrCopyFlag = enum
IsDecl, IsExplicitSink
IsDecl, IsExplicitSink, IsReturn
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; flags: set[MoveOrCopyFlag] = {}): PNode
@@ -159,7 +161,8 @@ proc isLastReadImpl(n: PNode; c: var Con; scope: var Scope): bool =
result = false
proc isLastRead(n: PNode; c: var Con; s: var Scope): bool =
if not hasDestructor(c, n.typ): return true
# bug #23354; an object type could have a non-trival assignements when it is passed to a sink parameter
if not hasDestructor(c, n.typ) and (n.typ.kind != tyObject or isTrival(getAttachedOp(c.graph, n.typ, attachedAsgn))): return true
let m = skipConvDfa(n)
result = (m.kind == nkSym and sfSingleUsedTemp in m.sym.flags) or
@@ -183,11 +186,16 @@ proc isCursor(n: PNode): bool =
template isUnpackedTuple(n: PNode): bool =
## we move out all elements of unpacked tuples,
## hence unpacked tuples themselves don't need to be destroyed
(n.kind == nkSym and n.sym.kind == skTemp and n.sym.typ.kind == tyTuple)
## except it's already a cursor
(n.kind == nkSym and n.sym.kind == skTemp and
n.sym.typ.kind == tyTuple and sfCursor notin n.sym.flags)
proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string; inferredFromCopy = false) =
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
if (opname == "=" or opname == "=copy") and ri != nil:
if inferredFromCopy:
m.add ", which is inferred from unavailable '=copy'"
if (opname == "=" or opname == "=copy" or opname == "=dup") and ri != nil:
m.add "; requires a copy because it's not the last read of '"
m.add renderTree(ri)
m.add '\''
@@ -209,15 +217,19 @@ proc makePtrType(c: var Con, baseType: PType): PType =
addSonSkipIntLit(result, baseType, c.idgen)
proc genOp(c: var Con; op: PSym; dest: PNode): PNode =
let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
addrExp.add(dest)
var addrExp: PNode
if op.typ != nil and op.typ.len > 1 and op.typ[1].kind != tyVar:
addrExp = dest
else:
addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
addrExp.add(dest)
result = newTree(nkCall, newSymNode(op), addrExp)
proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
var op = getAttachedOp(c.graph, t, kind)
if op == nil or op.ast.isGenericRoutine:
# give up and find the canonical type instead:
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
let h = sighashes.hashType(t, c.graph.config, {CoType, CoConsiderOwned, CoDistinct})
let canon = c.graph.canonTypes.getOrDefault(h)
if canon != nil:
op = getAttachedOp(c.graph, canon, kind)
@@ -248,10 +260,20 @@ proc canBeMoved(c: Con; t: PType): bool {.inline.} =
proc isNoInit(dest: PNode): bool {.inline.} =
result = dest.kind == nkSym and sfNoInit in dest.sym.flags
proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
proc deepAliases(dest, ri: PNode): bool =
case ri.kind
of nkCallKinds, nkStmtListExpr, nkBracket, nkTupleConstr, nkObjConstr,
nkCast, nkConv, nkObjUpConv, nkObjDownConv:
for r in ri:
if deepAliases(dest, r): return true
return false
else:
return aliases(dest, ri) != no
proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
isNoInit(dest):
isNoInit(dest) or IsReturn in flags:
# optimize sink call into a bitwise memcopy
result = newTree(nkFastAsgn, dest, ri)
else:
@@ -262,12 +284,19 @@ proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNod
else:
# the default is to use combination of `=destroy(dest)` and
# and copyMem(dest, source). This is efficient.
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
if deepAliases(dest, ri):
# consider: x = x + y, it is wrong to destroy the destination first!
# tmp to support self assignments
let tmp = c.getTemp(s, dest.typ, dest.info)
result = newTree(nkStmtList, newTree(nkFastAsgn, tmp, dest), newTree(nkFastAsgn, dest, ri),
c.genDestroy(tmp))
else:
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
proc isCriticalLink(dest: PNode): bool {.inline.} =
#[
Lins's idea that only "critical" links can introduce a cycle. This is
critical for the performance gurantees that we strive for: If you
critical for the performance guarantees that we strive for: If you
traverse a data structure, no tracing will be performed at all.
ORC is about this promise: The GC only touches the memory that the
mutator touches too.
@@ -284,16 +313,17 @@ proc isCriticalLink(dest: PNode): bool {.inline.} =
]#
result = dest.kind != nkSym
proc finishCopy(c: var Con; result, dest: PNode; isFromSink: bool) =
if c.graph.config.selectedGC == gcOrc:
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
if cyclicType(t):
proc finishCopy(c: var Con; result, dest: PNode; flags: set[MoveOrCopyFlag]; isFromSink: bool) =
if c.graph.config.selectedGC == gcOrc and IsExplicitSink notin flags:
# add cyclic flag, but not to sink calls, which IsExplicitSink generates
let t = dest.typ.skipTypes(tyUserTypeClasses + {tyGenericInst, tyAlias, tySink, tyDistinct})
if cyclicType(c.graph, t):
result.add boolLit(c.graph, result.info, isFromSink or isCriticalLink(dest))
proc genMarkCyclic(c: var Con; result, dest: PNode) =
if c.graph.config.selectedGC == gcOrc:
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
if cyclicType(t):
if cyclicType(c.graph, t):
if t.kind == tyRef:
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, dest)
else:
@@ -307,6 +337,9 @@ proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode =
assert ri.typ != nil
proc genCopy(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag]): PNode =
if c.inEnsureMove > 0:
localError(c.graph.config, ri.info, errFailedMove, "cannot move '" & $ri &
"', which introduces an implicit copy")
let t = dest.typ
if tfHasOwned in t.flags and ri.kind != nkNilLit:
# try to improve the error message here:
@@ -335,30 +368,38 @@ proc genDiscriminantAsgn(c: var Con; s: var Scope; n: PNode): PNode =
if hasDestructor(c, objType):
if getAttachedOp(c.graph, objType, attachedDestructor) != nil and
sfOverriden in getAttachedOp(c.graph, objType, attachedDestructor).flags:
sfOverridden in getAttachedOp(c.graph, objType, attachedDestructor).flags:
localError(c.graph.config, n.info, errGenerated, """Assignment to discriminant for objects with user defined destructor is not supported, object must have default destructor.
It is best to factor out piece of object that needs custom destructor into separate object or not use discriminator assignment""")
result.add newTree(nkFastAsgn, le, tmp)
return
# generate: if le != tmp: `=destroy`(le)
let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info, c.idgen)
let cond = newNodeIT(nkInfix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info))
cond.add le
cond.add tmp
let notExpr = newNodeIT(nkPrefix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
notExpr.add newSymNode(createMagic(c.graph, c.idgen, "not", mNot))
notExpr.add cond
result.add newTree(nkIfStmt, newTree(nkElifBranch, notExpr, c.genOp(branchDestructor, le)))
if c.inUncheckedAssignSection != 0:
let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info, c.idgen)
let cond = newNodeIT(nkInfix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info))
cond.add le
cond.add tmp
let notExpr = newNodeIT(nkPrefix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
notExpr.add newSymNode(createMagic(c.graph, c.idgen, "not", mNot))
notExpr.add cond
result.add newTree(nkIfStmt, newTree(nkElifBranch, notExpr, c.genOp(branchDestructor, le)))
result.add newTree(nkFastAsgn, le, tmp)
proc genWasMoved(c: var Con, n: PNode): PNode =
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, c.idgen, "wasMoved", mWasMoved)))
result.add copyTree(n) #mWasMoved does not take the address
#if n.kind != nkSym:
# message(c.graph.config, n.info, warnUser, "wasMoved(" & $n & ")")
let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink})
let op = getAttachedOp(c.graph, n.typ, attachedWasMoved)
if op != nil:
if sfError in op.flags:
c.checkForErrorPragma(n.typ, n, "=wasMoved")
result = genOp(c, op, n)
else:
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, c.idgen, "`=wasMoved`", mWasMoved)))
result.add copyTree(n) #mWasMoved does not take the address
#if n.kind != nkSym:
# message(c.graph.config, n.info, warnUser, "wasMoved(" & $n & ")")
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
result = newNodeI(nkCall, info)
@@ -367,13 +408,16 @@ proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
# generate: (let tmp = v; reset(v); tmp)
if not hasDestructor(c, n.typ):
assert n.kind != nkSym or not hasDestructor(c, n.sym.typ)
if (not hasDestructor(c, n.typ)) and c.inEnsureMove == 0:
assert n.kind != nkSym or not hasDestructor(c, n.sym.typ) or
(n.typ.kind == tyPtr and n.sym.typ.kind == tyRef)
# bug #23505; transformed by `transf`: addr (deref ref) -> ptr
# we know it's really a pointer; so here we assign it directly
result = copyTree(n)
else:
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), nextSymId c.idgen, c.owner, n.info)
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.idgen, c.owner, n.info)
temp.typ = n.typ
var v = newNodeI(nkLetSection, n.info)
let tempAsNode = newSymNode(temp)
@@ -386,7 +430,8 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
result.add v
let nn = skipConv(n)
c.genMarkCyclic(result, nn)
if hasDestructor(c, n.typ):
c.genMarkCyclic(result, nn)
let wasMovedCall = c.genWasMoved(nn)
result.add wasMovedCall
result.add tempAsNode
@@ -397,21 +442,46 @@ proc isCapturedVar(n: PNode): bool =
proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
let tmp = c.getTemp(s, n.typ, n.info)
if hasDestructor(c, n.typ):
result.add c.genWasMoved(tmp)
var m = c.genCopy(tmp, n, {})
m.add p(n, c, s, normal)
c.finishCopy(m, n, isFromSink = true)
result.add m
if isLValue(n) and not isCapturedVar(n) and n.typ.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0:
let nTyp = n.typ.skipTypes(tyUserTypeClasses)
let tmp = c.getTemp(s, nTyp, n.info)
if hasDestructor(c, nTyp):
let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink})
let op = getAttachedOp(c.graph, typ, attachedDup)
if op != nil and tfHasOwned notin typ.flags:
if sfError in op.flags:
c.checkForErrorPragma(nTyp, n, "=dup")
else:
let copyOp = getAttachedOp(c.graph, typ, attachedAsgn)
if copyOp != nil and sfError in copyOp.flags and
sfOverridden notin op.flags:
c.checkForErrorPragma(nTyp, n, "=dup", inferredFromCopy = true)
let src = p(n, c, s, normal)
var newCall = newTreeIT(nkCall, src.info, src.typ,
newSymNode(op),
src)
c.finishCopy(newCall, n, {}, isFromSink = true)
result.add newTreeI(nkFastAsgn,
src.info, tmp,
newCall
)
else:
result.add c.genWasMoved(tmp)
var m = c.genCopy(tmp, n, {})
m.add p(n, c, s, normal)
c.finishCopy(m, n, {}, isFromSink = true)
result.add m
if isLValue(n) and not isCapturedVar(n) and nTyp.skipTypes(abstractInst).kind != tyRef and c.inSpawn == 0:
message(c.graph.config, n.info, hintPerformance,
("passing '$1' to a sink parameter introduces an implicit copy; " &
"if possible, rearrange your program's control flow to prevent it") % $n)
if c.inEnsureMove > 0:
localError(c.graph.config, n.info, errFailedMove,
("cannot move '$1', passing '$1' to a sink parameter introduces an implicit copy") % $n)
else:
if c.graph.config.selectedGC in {gcArc, gcOrc}:
assert(not containsManagedMemory(n.typ))
if n.typ.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
if c.graph.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
assert(not containsManagedMemory(nTyp))
if nTyp.skipTypes(abstractInst).kind in {tyOpenArray, tyVarargs}:
localError(c.graph.config, n.info, "cannot create an implicit openArray copy to be passed to a sink parameter")
result.add newTree(nkAsgn, tmp, p(n, c, s, normal))
# Since we know somebody will take over the produced copy, there is
@@ -427,7 +497,7 @@ proc containsConstSeq(n: PNode): bool =
return true
result = false
case n.kind
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkCast:
result = containsConstSeq(n[1])
of nkObjConstr, nkClosure:
for i in 1..<n.len:
@@ -445,14 +515,14 @@ proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
# This was already done in the sink parameter handling logic.
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
let tmp = c.getTemp(s, arg.typ, arg.info)
result.add c.genSink(tmp, arg, {IsDecl})
result.add c.genSink(s, tmp, arg, {IsDecl})
result.add tmp
s.final.add c.genDestroy(tmp)
else:
result = arg
proc cycleCheck(n: PNode; c: var Con) =
if c.graph.config.selectedGC != gcArc: return
if c.graph.config.selectedGC notin {gcArc, gcAtomicArc}: return
var value = n[1]
if value.kind == nkClosure:
value = value[1]
@@ -525,7 +595,9 @@ template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: unt
# tricky because you would have to intercept moveOrCopy at a certain point
let tmp = c.getTemp(s.parent[], ret.typ, ret.info)
tmp.sym.flags = tmpFlags
let cpy = if hasDestructor(c, ret.typ):
let cpy = if hasDestructor(c, ret.typ) and
ret.typ.kind notin {tyOpenArray, tyVarargs}:
# bug #23247 we don't own the data, so it's harmful to destroy it
s.parent[].final.add c.genDestroy(tmp)
moveOrCopy(tmp, ret, c, s, {IsDecl})
else:
@@ -653,6 +725,24 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false,
of nkWhen: # This should be a "when nimvm" node.
result = copyTree(n)
result[1][0] = processCall(n[1][0], s)
of nkPragmaBlock:
var inUncheckedAssignSection = 0
let pragmaList = n[0]
for pi in pragmaList:
if whichPragma(pi) == wCast:
case whichPragma(pi[1])
of wUncheckedAssign:
inUncheckedAssignSection = 1
else:
discard
result = shallowCopy(n)
inc c.inUncheckedAssignSection, inUncheckedAssignSection
for i in 0 ..< n.len-1:
result[i] = p(n[i], c, s, normal)
result[^1] = maybeVoid(n[^1], s)
dec c.inUncheckedAssignSection, inUncheckedAssignSection
else: assert(false)
proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
@@ -665,7 +755,7 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
let tmp = c.getTemp(s, n[0].typ, n.info)
var m = c.genCopyNoCheck(tmp, n[0], attachedAsgn)
m.add p(n[0], c, s, normal)
c.finishCopy(m, n[0], isFromSink = false)
c.finishCopy(m, n[0], {}, isFromSink = false)
result = newTree(nkStmtList, c.genWasMoved(tmp), m)
var toDisarm = n[0]
if toDisarm.kind == nkStmtListExpr: toDisarm = toDisarm.lastSon
@@ -680,9 +770,21 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
result.add copyNode(n[0])
s.needsTry = true
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}): PNode =
template isCustomDestructor(c: Con, t: PType): bool =
hasDestructor(c, t) and
getAttachedOp(c.graph, t, attachedDestructor) != nil and
sfOverridden in getAttachedOp(c.graph, t, attachedDestructor).flags
proc hasCustomDestructor(c: Con, t: PType): bool =
result = isCustomDestructor(c, t)
var obj = t
while obj.len > 0 and obj[0] != nil:
obj = skipTypes(obj[0], abstractPtrs)
result = result or isCustomDestructor(c, obj)
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}; inReturn = false): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt}:
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt, nkPragmaBlock}:
template process(child, s): untyped = p(child, c, s, mode)
handleNestedTempl(n, process, tmpFlags = tmpFlags)
elif mode == sinkArg:
@@ -693,7 +795,15 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
result = passCopyToSink(n, c, s)
elif n.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure, nkNilLit} +
nkCallKinds + nkLiterals:
result = p(n, c, s, consumed)
if n.kind in nkCallKinds and n[0].kind == nkSym:
if n[0].sym.magic == mEnsureMove:
inc c.inEnsureMove
result = p(n[1], c, s, sinkArg)
dec c.inEnsureMove
else:
result = p(n, c, s, consumed)
else:
result = p(n, c, s, consumed)
elif ((n.kind == nkSym and isSinkParam(n.sym)) or isAnalysableFieldAccess(n, c.owner)) and
isLastRead(n, c, s) and not (n.kind == nkSym and isCursor(n)):
# Sinked params can be consumed only once. We need to reset the memory
@@ -713,6 +823,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
elif n.kind in {nkObjDownConv, nkObjUpConv}:
result = copyTree(n)
result[0] = p(n[0], c, s, sinkArg)
elif n.kind == nkCast and n.typ.skipTypes(abstractInst).kind in {tyString, tySequence}:
result = copyTree(n)
result[1] = p(n[1], c, s, sinkArg)
elif n.typ == nil:
# 'raise X' can be part of a 'case' expression. Deal with it here:
result = p(n, c, s, normal)
@@ -762,9 +875,15 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
result[i][1] = p(n[i][1], c, s, m)
else:
result[i] = p(n[i], c, s, m)
if mode == normal and isRefConstr:
if mode == normal and (isRefConstr or hasCustomDestructor(c, t)):
result = ensureDestruction(result, n, c, s)
of nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mEnsureMove:
inc c.inEnsureMove
result = p(n[1], c, s, sinkArg)
dec c.inEnsureMove
return
let inSpawn = c.inSpawn
if n[0].kind == nkSym and n[0].sym.magic == mSpawn:
c.inSpawn.inc
@@ -795,14 +914,17 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
if n[0].kind == nkSym and n[0].sym.magic in {mNew, mNewFinalize}:
result[0] = copyTree(n[0])
if c.graph.config.selectedGC in {gcHooks, gcArc, gcOrc}:
if c.graph.config.selectedGC in {gcHooks, gcArc, gcAtomicArc, gcOrc}:
let destroyOld = c.genDestroy(result[1])
result = newTree(nkStmtList, destroyOld, result)
else:
result[0] = p(n[0], c, s, normal)
if canRaise(n[0]): s.needsTry = true
if mode == normal:
result = ensureDestruction(result, n, c, s)
if result.typ != nil and result.typ.kind notin {tyOpenArray, tyVarargs}:
# Returns of openarray types shouldn't be destroyed
# bug #19435; # bug #23247
result = ensureDestruction(result, n, c, s)
of nkDiscardStmt: # Small optimization
result = shallowCopy(n)
if n[0].kind != nkEmpty:
@@ -829,7 +951,10 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
if ri.kind != nkEmpty:
result.add moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {})
elif ri.kind == nkEmpty and c.inLoop > 0:
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, if v.kind == nkSym: {IsDecl} else: {})
let skipInit = v.kind == nkDotExpr and # Closure var
sfNoInit in v[1].sym.flags
if not skipInit:
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, if v.kind == nkSym: {IsDecl} else: {})
else: # keep the var but transform 'ri':
var v = copyNode(n)
var itCopy = copyNode(it)
@@ -847,7 +972,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
cycleCheck(n, c)
assert n[1].kind notin {nkAsgn, nkFastAsgn, nkSinkAsgn}
let flags = if n.kind == nkSinkAsgn: {IsExplicitSink} else: {}
var flags = if n.kind == nkSinkAsgn: {IsExplicitSink} else: {}
if inReturn:
flags.incl(IsReturn)
result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s, flags)
elif isDiscriminantField(n[0]):
result = c.genDiscriminantAsgn(s, n)
@@ -867,7 +994,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
result = n
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange, nkPragmaBlock:
of nkStringToCString, nkCStringToString, nkChckRangeF, nkChckRange64, nkChckRange:
result = shallowCopy(n)
for i in 0 ..< n.len:
result[i] = p(n[i], c, s, normal)
@@ -931,7 +1058,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
of nkReturnStmt:
result = shallowCopy(n)
for i in 0..<n.len:
result[i] = p(n[i], c, s, mode)
result[i] = p(n[i], c, s, mode, inReturn=true)
s.needsTry = true
of nkCast:
result = shallowCopy(n)
@@ -949,7 +1076,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
proc sameLocation*(a, b: PNode): bool =
proc sameConstant(a, b: PNode): bool =
a.kind in nkLiterals and a.intVal == b.intVal
a.kind in nkLiterals and b.kind in nkLiterals and a.intVal == b.intVal
const nkEndPoint = {nkSym, nkDotExpr, nkCheckedFieldExpr, nkBracketExpr}
if a.kind in nkEndPoint and b.kind in nkEndPoint:
@@ -973,9 +1100,9 @@ proc sameLocation*(a, b: PNode): bool =
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b)
else: false
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
proc genFieldAccessSideEffects(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
# with side effects
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), nextSymId c.idgen, c.owner, ri[1].info)
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), c.idgen, c.owner, ri[1].info)
temp.typ = ri[1].typ
var v = newNodeI(nkLetSection, ri[1].info)
let tempAsNode = newSymNode(temp)
@@ -990,14 +1117,22 @@ proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCop
newAccess.add ri[0]
newAccess.add tempAsNode
var snk = c.genSink(dest, newAccess, flags)
var snk = c.genSink(s, dest, newAccess, flags)
result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess))
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopyFlag] = {}): PNode =
var ri = ri
var isEnsureMove = 0
if ri.kind in nkCallKinds and ri[0].kind == nkSym and ri[0].sym.magic == mEnsureMove:
ri = ri[1]
isEnsureMove = 1
if sameLocation(dest, ri):
# rule (self-assignment-removal):
result = newNodeI(nkEmpty, dest.info)
elif isCursor(dest):
elif isCursor(dest) or dest.typ.kind in {tyOpenArray, tyVarargs}:
# hoisted openArray parameters might end up here
# openArray types don't have a lifted assignment operation (it's empty)
# bug #22132
case ri.kind:
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
@@ -1006,53 +1141,60 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
else:
result = newTree(nkFastAsgn, dest, p(ri, c, s, normal))
else:
case ri.kind
let ri2 = if ri.kind == nkWhen: ri[1][0] else: ri
case ri2.kind
of nkCallKinds:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkBracketExpr:
if isUnpackedTuple(ri[0]):
# unpacking of tuple: take over the elements
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s):
if aliases(dest, ri) == no:
# Rule 3: `=sink`(x, z); wasMoved(z)
if isAtom(ri[1]):
var snk = c.genSink(dest, ri, flags)
var snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
result = genFieldAccessSideEffects(c, dest, ri, flags)
result = genFieldAccessSideEffects(c, s, dest, ri, flags)
else:
result = c.genSink(dest, destructiveMoveVar(ri, c, s), flags)
result = c.genSink(s, dest, destructiveMoveVar(ri, c, s), flags)
else:
inc c.inEnsureMove, isEnsureMove
result = c.genCopy(dest, ri, flags)
dec c.inEnsureMove, isEnsureMove
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
c.finishCopy(result, dest, flags, isFromSink = false)
of nkBracket:
# array constructor
if ri.len > 0 and isDangerousSeq(ri.typ):
inc c.inEnsureMove, isEnsureMove
result = c.genCopy(dest, ri, flags)
dec c.inEnsureMove, isEnsureMove
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
c.finishCopy(result, dest, flags, isFromSink = false)
else:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkSym:
if isSinkParam(ri.sym) and isLastRead(ri, c, s):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
inc c.inEnsureMove, isEnsureMove
result = c.genCopy(dest, ri, flags)
dec c.inEnsureMove, isEnsureMove
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
c.finishCopy(result, dest, flags, isFromSink = false)
of nkHiddenSubConv, nkHiddenStdConv, nkConv, nkObjDownConv, nkObjUpConv, nkCast:
result = c.genSink(dest, p(ri, c, s, sinkArg), flags)
result = c.genSink(s, dest, p(ri, c, s, sinkArg), flags)
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
# We know the result will be a stmt so we use that fact to optimize
@@ -1063,12 +1205,14 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s) and
canBeMoved(c, dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
inc c.inEnsureMove, isEnsureMove
result = c.genCopy(dest, ri, flags)
dec c.inEnsureMove, isEnsureMove
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
c.finishCopy(result, dest, flags, isFromSink = false)
when false:
proc computeUninit(c: var Con) =

View File

@@ -10,7 +10,7 @@ Platforms: """
macosx: i386;amd64;powerpc64;arm64
solaris: i386;amd64;sparc;sparc64
freebsd: i386;amd64;powerpc64;arm;arm64;riscv64;sparc64;mips;mipsel;mips64;mips64el;powerpc;powerpc64el
netbsd: i386;amd64
netbsd: i386;amd64;arm64
openbsd: i386;amd64;arm;arm64
dragonfly: i386;amd64
crossos: amd64
@@ -65,11 +65,12 @@ Files: "compiler"
Files: "doc"
Files: "doc/html"
Files: "tools"
Files: "tools/nim-gdb.py"
Files: "tools/debug/nim-gdb.py"
Files: "nimpretty"
Files: "testament"
Files: "nimsuggest"
Files: "nimsuggest/tests/*.nim"
Files: "changelogs/*.md"
[Lib]
Files: "lib"
@@ -77,6 +78,7 @@ Files: "lib"
[Other]
Files: "examples"
Files: "dist/nimble"
Files: "dist/checksums"
Files: "tests"
@@ -90,6 +92,7 @@ Files: "bin/nimgrab.exe"
Files: "bin/nimpretty.exe"
Files: "bin/testament.exe"
Files: "bin/nim-gdb.bat"
Files: "bin/atlas.exe"
Files: "koch.exe"
Files: "finish.exe"
@@ -120,6 +123,7 @@ Files: "bin/nim"
InstallScript: "yes"
UninstallScript: "yes"
Files: "bin/nim-gdb"
Files: "build_all.sh"
[InnoSetup]

View File

@@ -33,26 +33,27 @@ template high*(t: typedesc[Int128]): Int128 = Max
proc `$`*(a: Int128): string
proc toInt128*[T: SomeInteger | bool](arg: T): Int128 =
when T is bool: result.sdata(0) = int32(arg)
elif T is SomeUnsignedInt:
when sizeof(arg) <= 4:
result.udata[0] = uint32(arg)
{.noSideEffect.}:
when T is bool: result.sdata(0) = int32(arg)
elif T is SomeUnsignedInt:
when sizeof(arg) <= 4:
result.udata[0] = uint32(arg)
else:
result.udata[0] = uint32(arg and T(0xffffffff))
result.udata[1] = uint32(arg shr 32)
elif sizeof(arg) <= 4:
result.sdata(0) = int32(arg)
if arg < 0: # sign extend
result.sdata(1) = -1
result.sdata(2) = -1
result.sdata(3) = -1
else:
result.udata[0] = uint32(arg and T(0xffffffff))
result.udata[1] = uint32(arg shr 32)
elif sizeof(arg) <= 4:
result.sdata(0) = int32(arg)
if arg < 0: # sign extend
result.sdata(1) = -1
result.sdata(2) = -1
result.sdata(3) = -1
else:
let tmp = int64(arg)
result.udata[0] = uint32(tmp and 0xffffffff)
result.sdata(1) = int32(tmp shr 32)
if arg < 0: # sign extend
result.sdata(2) = -1
result.sdata(3) = -1
let tmp = int64(arg)
result.udata[0] = uint32(tmp and 0xffffffff)
result.sdata(1) = int32(tmp shr 32)
if arg < 0: # sign extend
result.sdata(2) = -1
result.sdata(3) = -1
template isNegative(arg: Int128): bool =
arg.sdata(3) < 0

View File

@@ -72,6 +72,69 @@ proc isValueOnlyType(t: PType): bool =
proc wrap(t: PType): bool {.nimcall.} = t.kind in {tyRef, tyPtr, tyVar, tyLent}
result = not types.searchTypeFor(t, wrap)
type
SearchResult = enum
NotFound, Abort, Found
proc containsDangerousRefAux(t: PType; marker: var IntSet): SearchResult
proc containsDangerousRefAux(n: PNode; marker: var IntSet): SearchResult =
result = NotFound
case n.kind
of nkRecList:
for i in 0..<n.len:
result = containsDangerousRefAux(n[i], marker)
if result == Found: return result
of nkRecCase:
assert(n[0].kind == nkSym)
result = containsDangerousRefAux(n[0], marker)
if result == Found: return result
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = containsDangerousRefAux(lastSon(n[i]), marker)
if result == Found: return result
else: discard
of nkSym:
result = containsDangerousRefAux(n.sym.typ, marker)
else: discard
proc containsDangerousRefAux(t: PType; marker: var IntSet): SearchResult =
result = NotFound
if t == nil: return result
if containsOrIncl(marker, t.id): return result
if t.kind == tyRef or (t.kind == tyProc and t.callConv == ccClosure):
result = Found
elif tfSendable in t.flags:
result = Abort
else:
# continue the type traversal:
result = NotFound
if result != NotFound: return result
case t.kind
of tyObject:
if t[0] != nil:
result = containsDangerousRefAux(t[0].skipTypes(skipPtrs), marker)
if result == NotFound: result = containsDangerousRefAux(t.n, marker)
of tyGenericInst, tyDistinct, tyAlias, tySink:
result = containsDangerousRefAux(lastSon(t), marker)
of tyArray, tySet, tyTuple, tySequence:
for i in 0..<t.len:
result = containsDangerousRefAux(t[i], marker)
if result == Found: return result
else:
discard
proc containsDangerousRef(t: PType): bool =
# a `ref` type is "dangerous" if it occurs not within a type that is like `Isolated[T]`.
# For example:
# `ref int` # dangerous
# `Isolated[ref int]` # not dangerous
var marker = initIntSet()
result = containsDangerousRefAux(t, marker) == Found
proc canAlias*(arg, ret: PType): bool =
if isValueOnlyType(arg):
# can alias only with addr(arg.x) and we don't care if it is not safe
@@ -80,12 +143,15 @@ proc canAlias*(arg, ret: PType): bool =
var marker = initIntSet()
result = canAlias(arg, ret, marker)
const
SomeVar = {skForVar, skParam, skVar, skLet, skConst, skResult, skTemp}
proc containsVariable(n: PNode): bool =
case n.kind
of nodesToIgnoreSet:
result = false
of nkSym:
result = n.sym.kind in {skForVar, skParam, skVar, skLet, skConst, skResult, skTemp}
result = n.sym.kind in SomeVar
else:
for ch in n:
if containsVariable(ch): return true
@@ -109,7 +175,7 @@ proc checkIsolate*(n: PNode): bool =
discard "fine, it is isolated already"
else:
let argType = n[i].typ
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
if argType != nil and not isCompileTimeOnly(argType) and containsDangerousRef(argType):
if argType.canAlias(n.typ) or containsVariable(n[i]):
# bug #19013: Alias information is not enough, we need to check for potential
# "overlaps". I claim the problem can only happen by reading again from a location
@@ -143,6 +209,12 @@ proc checkIsolate*(n: PNode): bool =
result = checkIsolate(n[^1])
else:
result = false
of nkSym:
result = true
if n.sym.kind in SomeVar:
let argType = n.typ
if argType != nil and not isCompileTimeOnly(argType) and containsDangerousRef(argType):
result = false
else:
# unanalysable expression:
result = false

View File

@@ -31,9 +31,11 @@ implements the required case distinction.
import
ast, trees, magicsys, options,
nversion, msgs, idents, types,
ropes, passes, ccgutils, wordrecg, renderer,
ropes, ccgutils, wordrecg, renderer,
cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf, injectdestructors, sourcemap, astmsgs
transf, injectdestructors, sourcemap, astmsgs, backendpragmas
import pipelineutils
import json, sets, math, tables, intsets
import strutils except addf
@@ -48,6 +50,7 @@ type
graph: ModuleGraph
config: ConfigRef
sigConflicts: CountTable[SigHash]
initProc: PProc
BModule = ref TJSGen
TJSTypeKind = enum # necessary JS "types"
@@ -98,6 +101,7 @@ type
prc: PSym
globals, locals, body: Rope
options: TOptions
optionsStack: seq[TOptions]
module: BModule
g: PGlobals
generatedParamCopies: IntSet
@@ -107,6 +111,7 @@ type
extraIndent: int
up: PProc # up the call chain; required for closure support
declaredGlobals: IntSet
previousFileName: string # For frameInfo inside templates.
template config*(p: PProc): ConfigRef = p.module.config
@@ -154,6 +159,8 @@ proc newProc(globals: PGlobals, module: BModule, procDef: PNode,
options: TOptions): PProc =
result = PProc(
blocks: @[],
optionsStack: if module.initProc != nil: module.initProc.optionsStack
else: @[],
options: options,
module: module,
procDef: procDef,
@@ -261,7 +268,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
if m.config.hcrOn:
# When hot reloading is enabled, we must ensure that the names
# of functions and types will be preserved across rebuilds:
result.add(idOrSig(s, m.module.name.s, m.sigConflicts))
result.add(idOrSig(s, m.module.name.s, m.sigConflicts, m.config))
else:
result.add("_")
result.add(rope(s.id))
@@ -552,28 +559,36 @@ template binaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string,
r.res = frmt % [a, b, tmp, tmp2]
r.kind = resExpr
proc unsignedTrimmerJS(size: BiggestInt): Rope =
proc unsignedTrimmer(size: BiggestInt): string =
case size
of 1: rope"& 0xff"
of 2: rope"& 0xffff"
of 4: rope">>> 0"
else: rope""
of 1: "& 0xff"
of 2: "& 0xffff"
of 4: ">>> 0"
else: ""
template unsignedTrimmer(size: BiggestInt): Rope =
size.unsignedTrimmerJS
proc signedTrimmer(size: BiggestInt): string =
# sign extension is done by shifting to the left and then back to the right
"<< $1 >> $1" % [$(32 - size * 8)]
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
reassign: static[bool] = false) =
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
let size = n[1].typ.skipTypes(abstractRange).size
when reassign:
let (a, tmp) = maybeMakeTempAssignable(p, n[1], x)
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
if size == 8 and optJsBigInt64 in p.config.globalOptions:
r.res = "$1 = BigInt.asUintN(64, ($4 $2 $3))" % [a, rope op, y.rdLoc, tmp]
else:
let trimmer = unsignedTrimmer(size)
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
if size == 8 and optJsBigInt64 in p.config.globalOptions:
r.res = "BigInt.asUintN(64, ($1 $2 $3))" % [x.rdLoc, rope op, y.rdLoc]
else:
let trimmer = unsignedTrimmer(size)
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
r.kind = resExpr
template ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
@@ -614,32 +629,103 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
template applyFormat(frmtA, frmtB) =
if i == 0: applyFormat(frmtA) else: applyFormat(frmtB)
template bitwiseExpr(op: string) =
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.kind in {tyUInt, tyUInt32}:
r.res = "(($1 $2 $3) >>> 0)" % [xLoc, op, yLoc]
else:
r.res = "($1 $2 $3)" % [xLoc, op, yLoc]
case op
of mAddI: applyFormat("addInt($1, $2)", "($1 + $2)")
of mSubI: applyFormat("subInt($1, $2)", "($1 - $2)")
of mMulI: applyFormat("mulInt($1, $2)", "($1 * $2)")
of mDivI: applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
of mModI: applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
of mAddI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "addInt64")
applyFormat("addInt64($1, $2)")
else:
applyFormat("addInt($1, $2)")
else:
applyFormat("($1 + $2)")
of mSubI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "subInt64")
applyFormat("subInt64($1, $2)")
else:
applyFormat("subInt($1, $2)")
else:
applyFormat("($1 - $2)")
of mMulI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "mulInt64")
applyFormat("mulInt64($1, $2)")
else:
applyFormat("mulInt($1, $2)")
else:
applyFormat("($1 * $2)")
of mDivI:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "divInt64")
applyFormat("divInt64($1, $2)", "$1 / $2")
else:
applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
of mModI:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "modInt64")
applyFormat("modInt64($1, $2)", "$1 % $2")
else:
applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
of mSucc: applyFormat("addInt($1, $2)", "($1 + $2)")
of mPred: applyFormat("subInt($1, $2)", "($1 - $2)")
of mAddF64: applyFormat("($1 + $2)", "($1 + $2)")
of mSubF64: applyFormat("($1 - $2)", "($1 - $2)")
of mMulF64: applyFormat("($1 * $2)", "($1 * $2)")
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
of mShrI: applyFormat("", "")
of mShrI:
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asIntN(64, BigInt.asUintN(64, $1) >> BigInt($2))")
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("($1 >> BigInt($2))")
else:
if typ.kind in {tyInt..tyInt32}:
let trimmerU = unsignedTrimmer(typ.size)
let trimmerS = signedTrimmer(typ.size)
r.res = "((($1 $2) >>> $3) $4)" % [xLoc, trimmerU, yLoc, trimmerS]
else:
applyFormat("($1 >>> $2)")
of mShlI:
if n[1].typ.size <= 4:
applyFormat("($1 << $2)", "($1 << $2)")
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.size == 8:
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asIntN(64, $1 << BigInt($2))")
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asUintN(64, $1 << BigInt($2))")
else:
applyFormat("($1 * Math.pow(2, $2))")
else:
applyFormat("($1 * Math.pow(2, $2))", "($1 * Math.pow(2, $2))")
if typ.kind in {tyUInt..tyUInt32}:
let trimmer = unsignedTrimmer(typ.size)
r.res = "(($1 << $2) $3)" % [xLoc, yLoc, trimmer]
else:
let trimmer = signedTrimmer(typ.size)
r.res = "(($1 << $2) $3)" % [xLoc, yLoc, trimmer]
of mAshrI:
if n[1].typ.size <= 4:
applyFormat("($1 >> $2)", "($1 >> $2)")
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.size == 8:
if optJsBigInt64 in p.config.globalOptions:
applyFormat("($1 >> BigInt($2))")
else:
applyFormat("Math.floor($1 / Math.pow(2, $2))")
else:
applyFormat("Math.floor($1 / Math.pow(2, $2))", "Math.floor($1 / Math.pow(2, $2))")
of mBitandI: applyFormat("($1 & $2)", "($1 & $2)")
of mBitorI: applyFormat("($1 | $2)", "($1 | $2)")
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
if typ.kind in {tyUInt..tyUInt32}:
applyFormat("($1 >>> $2)")
else:
applyFormat("($1 >> $2)")
of mBitandI: bitwiseExpr("&")
of mBitorI: bitwiseExpr("|")
of mBitxorI: bitwiseExpr("^")
of mMinI: applyFormat("nimMin($1, $2)", "nimMin($1, $2)")
of mMaxI: applyFormat("nimMax($1, $2)", "nimMax($1, $2)")
of mAddU: applyFormat("", "")
@@ -675,7 +761,16 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mAbsI: applyFormat("absInt($1)", "Math.abs($1)")
of mNot: applyFormat("!($1)", "!($1)")
of mUnaryPlusI: applyFormat("+($1)", "+($1)")
of mBitnotI: applyFormat("~($1)", "~($1)")
of mBitnotI:
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.kind in {tyUInt..tyUInt64}:
if typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asUintN(64, ~($1))")
else:
let trimmer = unsignedTrimmer(typ.size)
r.res = "(~($1) $2)" % [xLoc, trimmer]
else:
applyFormat("~($1)")
of mUnaryPlusF64: applyFormat("+($1)", "+($1)")
of mUnaryMinusF64: applyFormat("-($1)", "-($1)")
of mCharToStr: applyFormat("nimCharToStr($1)", "nimCharToStr($1)")
@@ -694,17 +789,14 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mMulU: binaryUintExpr(p, n, r, "*")
of mDivU:
binaryUintExpr(p, n, r, "/")
if n[1].typ.skipTypes(abstractRange).size == 8:
if optJsBigInt64 notin p.config.globalOptions and
n[1].typ.skipTypes(abstractRange).size == 8:
# bigint / already truncates
r.res = "Math.trunc($1)" % [r.res]
of mDivI:
arithAux(p, n, r, op)
of mModI:
arithAux(p, n, r, op)
of mShrI:
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr, mStrToStr, mEnumToStr:
arithAux(p, n, r, op)
of mEqRef:
@@ -724,17 +816,24 @@ proc hasFrameInfo(p: PProc): bool =
((p.prc == nil) or not (sfPure in p.prc.flags))
proc lineDir(config: ConfigRef, info: TLineInfo, line: int): Rope =
ropes.`%`("/* line $2 \"$1\" */$n",
[rope(toFullPath(config, info)), rope(line)])
"/* line $2:$3 \"$1\" */$n" % [
rope(toFullPath(config, info)), rope(line), rope(info.toColumn)
]
proc genLineDir(p: PProc, n: PNode) =
let line = toLinenumber(n.info)
if line < 0:
return
if optEmbedOrigSrc in p.config.globalOptions:
lineF(p, "//$1$n", [sourceLine(p.config, n.info)])
if optLineDir in p.options or optLineDir in p.config.options:
lineF(p, "$1", [lineDir(p.config, n.info, line)])
if hasFrameInfo(p):
lineF(p, "F.line = $1;$n", [rope(line)])
let currentFileName = toFilename(p.config, n.info)
if p.previousFileName != currentFileName:
lineF(p, "F.filename = $1;$n", [makeJSString(currentFileName)])
p.previousFileName = currentFileName
proc genWhileStmt(p: PProc, n: PNode) =
var cond: TCompRes
@@ -1099,7 +1198,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool =
return y.kind in nodeKindsNeedNoCopy or
((mapType(y.typ) != etyBaseIndex or (y.kind == nkSym and y.sym.kind == skParam)) and
(skipTypes(y.typ, abstractInst).kind in
{tyRef, tyPtr, tyLent, tyVar, tyCstring, tyProc, tyOwned} + IntegralTypes))
{tyRef, tyPtr, tyLent, tyVar, tyCstring, tyProc, tyOwned, tyOpenArray} + IntegralTypes))
proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
var a, b: TCompRes
@@ -1758,15 +1857,25 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
createRecordVarAux(p, t.n, excludedFieldIDs, output)
t = t[0]
proc arrayTypeForElemType(typ: PType): string =
proc arrayTypeForElemType(conf: ConfigRef; typ: PType): string =
let typ = typ.skipTypes(abstractRange)
case typ.kind
of tyInt, tyInt32: "Int32Array"
of tyInt16: "Int16Array"
of tyInt8: "Int8Array"
of tyInt64:
if optJsBigInt64 in conf.globalOptions:
"BigInt64Array"
else:
""
of tyUInt, tyUInt32: "Uint32Array"
of tyUInt16: "Uint16Array"
of tyUInt8, tyChar, tyBool: "Uint8Array"
of tyUInt64:
if optJsBigInt64 in conf.globalOptions:
"BigUint64Array"
else:
""
of tyFloat32: "Float32Array"
of tyFloat64, tyFloat: "Float64Array"
of tyEnum:
@@ -1780,11 +1889,18 @@ proc arrayTypeForElemType(typ: PType): string =
proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
var t = skipTypes(typ, abstractInst)
case t.kind
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar:
of tyInt8..tyInt32, tyUInt8..tyUInt32, tyEnum, tyChar:
result = putToSeq("0", indirect)
of tyInt, tyUInt:
if $t.sym.loc.r == "bigint":
result = putToSeq("0n", indirect)
else:
result = putToSeq("0", indirect)
of tyInt64, tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
result = putToSeq("0n", indirect)
else:
result = putToSeq("0", indirect)
of tyFloat..tyFloat128:
result = putToSeq("0.0", indirect)
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
@@ -1798,7 +1914,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
of tyArray:
let length = toInt(lengthOrd(p.config, t))
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
let jsTyp = arrayTypeForElemType(p.config, e)
if jsTyp.len > 0:
result = "new $1($2)" % [rope(jsTyp), rope(length)]
elif length > 32:
@@ -1836,7 +1952,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
result = putToSeq("null", indirect)
of tySequence, tyString:
result = putToSeq("[]", indirect)
of tyCstring, tyProc:
of tyCstring, tyProc, tyOpenArray:
result = putToSeq("null", indirect)
of tyStatic:
if t.n != nil:
@@ -1973,7 +2089,11 @@ proc genNewSeq(p: PProc, n: PNode) =
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
case skipTypes(n[1].typ, abstractVar + abstractRange).kind
of tyEnum, tyInt..tyUInt64, tyChar: gen(p, n[1], r)
of tyEnum, tyInt..tyInt32, tyUInt..tyUInt32, tyChar: gen(p, n[1], r)
of tyInt64, tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
unaryExpr(p, n, r, "", "Number($1)")
else: gen(p, n[1], r)
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1 : 0)")
else: internalError(p.config, n.info, "genOrd")
@@ -2085,6 +2205,13 @@ proc genMove(p: PProc; n: PNode; r: var TCompRes) =
genReset(p, n)
#lineF(p, "$1 = $2;$n", [dest.rdLoc, src.rdLoc])
proc genDup(p: PProc; n: PNode; r: var TCompRes) =
var a: TCompRes
r.kind = resVal
r.res = p.getTemp()
gen(p, n[1], a)
lineF(p, "$1 = $2;$n", [r.rdLoc, a.rdLoc])
proc genJSArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
var a: TCompRes
r.res = rope("[")
@@ -2196,19 +2323,41 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
r.res = "($1).length - 1" % [x.rdLoc]
r.kind = resExpr
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
let typ = n[1].typ.skipTypes(abstractVarRange)
case typ.kind
of tyUInt..tyUInt32:
binaryUintExpr(p, n, r, "+", true)
of tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 + BigInt($2))", true)
else: binaryUintExpr(p, n, r, "+", true)
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if optOverflowCheck notin p.options:
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 + BigInt($2))", true)
else: binaryExpr(p, n, r, "addInt64", "$1 = addInt64($3, BigInt($2))", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($3, $2)", true)
of ast.mDec:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
let typ = n[1].typ.skipTypes(abstractVarRange)
case typ.kind
of tyUInt..tyUInt32:
binaryUintExpr(p, n, r, "-", true)
of tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 - BigInt($2))", true)
else: binaryUintExpr(p, n, r, "+", true)
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if optOverflowCheck notin p.options:
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 - BigInt($2))", true)
else: binaryExpr(p, n, r, "subInt64", "$1 = subInt64($3, BigInt($2))", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)", true)
of mSetLengthStr:
binaryExpr(p, n, r, "mnewString", "($1.length = $2)")
binaryExpr(p, n, r, "mnewString",
"""if ($1.length < $2) { for (var i = $3.length; i < $4; ++i) $3.push(0); }
else {$3.length = $4; }""")
of mSetLengthSeq:
var x, y: TCompRes
gen(p, n[1], x)
@@ -2257,6 +2406,10 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
r.kind = resExpr
of mMove:
genMove(p, n, r)
of mDup:
genDup(p, n, r)
of mEnsureMove:
gen(p, n[1], r)
else:
genCall(p, n, r)
#else internalError(p.config, e.info, 'genMagic: ' + magicToStr[op]);
@@ -2295,7 +2448,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
## Nim sequence maps to JS array.
var t = skipTypes(n.typ, abstractInst)
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
let jsTyp = arrayTypeForElemType(p.config, e)
if skipTypes(n.typ, abstractVarRange).kind != tySequence and jsTyp.len > 0:
# generate typed array
# for example Nim generates `new Uint8Array([1, 2, 3])` for `[byte(1), 2, 3]`
@@ -2376,7 +2529,29 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
r.res = "(!!($1))" % [r.res]
r.kind = resExpr
elif toInt:
r.res = "(($1) | 0)" % [r.res]
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
else:
r.res = "(($1) | 0)" % [r.res]
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyUInt64:
r.res = "BigInt.asIntN(64, $1)" % [r.res]
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
if fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif fromInt: # could be negative
r.res = "BigInt.asUintN(64, BigInt($1))" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt.asUintN(64, BigInt(Math.trunc($1)))" % [r.res]
elif src.kind == tyInt64:
r.res = "BigInt.asUintN(64, $1)" % [r.res]
elif toUint or dest.kind in tyFloat..tyFloat64:
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
else:
# TODO: What types must we handle here?
discard
@@ -2387,7 +2562,11 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
var a, b: TCompRes
gen(p, n[0], r)
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
let src = skipTypes(n[0].typ, abstractVarRange)
let dest = skipTypes(n.typ, abstractVarRange)
if src.kind in {tyInt64, tyUInt64} and dest.kind notin {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
checkUnsignedConversions notin p.config.legacyFeatures):
discard "XXX maybe emit masking instructions here"
else:
@@ -2481,17 +2660,18 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
if prc.typ[0] != nil and sfPure notin prc.flags:
resultSym = prc.ast[resultPos].sym
let mname = mangleName(p.module, resultSym)
let returnAddress = not isIndirect(resultSym) and
# otherwise uses "fat pointers"
let useRawPointer = not isIndirect(resultSym) and
resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
mapType(p, resultSym.typ) == etyBaseIndex
if returnAddress:
if useRawPointer:
resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
else:
let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
gen(p, prc.ast[resultPos], a)
if returnAddress:
if mapType(p, resultSym.typ) == etyBaseIndex:
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
else:
returnStmt = "return $#;$n" % [a.res]
@@ -2553,9 +2733,14 @@ proc genStmt(p: PProc, n: PNode) =
if r.res != "": lineF(p, "$#;$n", [r.res])
proc genPragma(p: PProc, n: PNode) =
for it in n.sons:
for i in 0..<n.len:
let it = n[i]
case whichPragma(it)
of wEmit: genAsmOrEmitStmt(p, it[1])
of wPush:
processPushBackendOption(p.optionsStack, p.options, n, i+1)
of wPop:
processPopBackendOption(p.optionsStack, p.options)
else: discard
proc genCast(p: PProc, n: PNode, r: var TCompRes) =
@@ -2570,24 +2755,35 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
let fromInt = (src.kind in tyInt..tyInt32)
let fromUint = (src.kind in tyUInt..tyUInt32)
if toUint and (fromInt or fromUint):
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
if toUint:
if fromInt or fromUint:
r.res = "Number(BigInt.asUintN($1, BigInt($2)))" % [$(dest.size * 8), r.res]
elif src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number(BigInt.asUintN($1, $2))" % [$(dest.size * 8), r.res]
elif toInt:
if fromInt:
return
elif fromUint:
if src.size == 4 and dest.size == 4:
# XXX prevent multi evaluations
r.res = "($1 | 0)" % [r.res]
else:
let trimmer = unsignedTrimmer(dest.size)
let minuend = case dest.size
of 1: "0xfe"
of 2: "0xfffe"
of 4: "0xfffffffe"
else: ""
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
if fromInt or fromUint:
r.res = "Number(BigInt.asIntN($1, BigInt($2)))" % [$(dest.size * 8), r.res]
elif src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number(BigInt.asIntN($1, $2))" % [$(dest.size * 8), r.res]
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyUInt64:
r.res = "BigInt.asIntN(64, $1)" % [r.res]
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
if fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif fromInt: # could be negative
r.res = "BigInt.asUintN(64, BigInt($1))" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt.asUintN(64, BigInt(Math.trunc($1)))" % [r.res]
elif src.kind == tyInt64:
r.res = "BigInt.asUintN(64, $1)" % [r.res]
elif dest.kind in tyFloat..tyFloat64:
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
r.address = r.res
r.res = "null"
@@ -2606,10 +2802,25 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkSym:
genSym(p, n, r)
of nkCharLit..nkUInt64Lit:
if n.typ.kind == tyBool:
case n.typ.skipTypes(abstractVarRange).kind
of tyBool:
r.res = if n.intVal == 0: rope"false" else: rope"true"
of tyUInt64:
r.res = rope($cast[BiggestUInt](n.intVal))
if optJsBigInt64 in p.config.globalOptions:
r.res.add('n')
of tyInt64:
let wrap = n.intVal < 0 # wrap negative integers with parens
if wrap: r.res.add '('
r.res.addInt n.intVal
if optJsBigInt64 in p.config.globalOptions:
r.res.add('n')
if wrap: r.res.add ')'
else:
r.res = rope(n.intVal)
let wrap = n.intVal < 0 # wrap negative integers with parens
if wrap: r.res.add '('
r.res.addInt n.intVal
if wrap: r.res.add ')'
r.kind = resExpr
of nkNilLit:
if isEmptyType(n.typ):
@@ -2803,7 +3014,7 @@ proc genModule(p: PProc, n: PNode) =
if p.config.hcrOn and n.kind == nkStmtList:
let moduleSym = p.module.module
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" &
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts)
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts, p.config)
lineF(p, "var $1;$n", [moduleLoadedVar])
var inGuardedBlock = false
@@ -2820,14 +3031,15 @@ proc genModule(p: PProc, n: PNode) =
if optStackTrace in p.options:
p.body.add(frameDestroy(p))
proc myProcess(b: PPassContext, n: PNode): PNode =
proc processJSCodeGen*(b: PPassContext, n: PNode): PNode =
## Generate JS code for a node.
result = n
let m = BModule(b)
if passes.skipCodegen(m.config, n): return n
if pipelineutils.skipCodegen(m.config, n): return n
if m.module == nil: internalError(m.config, n.info, "myProcess")
let globals = PGlobals(m.graph.backend)
var p = newInitProc(globals, m)
m.initProc = p
p.unique = globals.unique
genModule(p, n)
p.g.code.add(p.locals)
@@ -2841,7 +3053,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
var p = newInitProc(globals, m)
attachProc(p, prc)
var disp = generateMethodDispatchers(graph)
var disp = generateMethodDispatchers(graph, m.idgen)
for i in 0..<disp.len:
let prc = disp[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id):
@@ -2859,7 +3071,7 @@ proc getClassName(t: PType): Rope =
if s.loc.r != "": result = s.loc.r
else: result = rope(s.name.s)
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
proc finalJSCodeGen*(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
## Finalize JS code generation of a Nim module.
## Param `n` may contain nodes returned from the last module close call.
var m = BModule(b)
@@ -2869,14 +3081,14 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
for i in countdown(high(graph.globalDestructors), 0):
n.add graph.globalDestructors[i]
# Process any nodes left over from the last call to `myClose`.
result = myProcess(b, n)
result = processJSCodeGen(b, n)
# Some codegen is different (such as no stacktraces; see `initProcOptions`)
# when `std/system` is being processed.
if sfSystemModule in m.module.flags:
PGlobals(graph.backend).inSystem = false
# Check if codegen should continue before any files are generated.
# It may bail early is if too many errors have been raised.
if passes.skipCodegen(m.config, n): return n
if pipelineutils.skipCodegen(m.config, n): return n
# Nim modules are compiled into a single JS file.
# If this is the main module, then this is the final call to `myClose`.
if sfMainModule in m.module.flags:
@@ -2885,7 +3097,8 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
# Generate an optional source map.
if optSourcemap in m.config.globalOptions:
var map: SourceMap
(code, map) = genSourceMap($(code), outFile.string)
map = genSourceMap($code, outFile.string)
code &= "\n//# sourceMappingURL=$#.map" % [outFile.string]
writeFile(outFile.string & ".map", $(%map))
# Check if the generated JS code matches the output file, or else
# write it to the file.
@@ -2893,9 +3106,6 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if not writeRope(code, outFile):
rawMessage(m.config, errCannotOpenFile, outFile.string)
proc myOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext =
## Create the JS backend pass context `BModule` for a Nim module.
proc setupJSgen*(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext =
result = newModule(graph, s)
result.idgen = idgen
const JSgenPass* = makePass(myOpen, myProcess, myClose)

View File

@@ -133,7 +133,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s)
of tyVar, tyLent, tyRef, tyPtr, tySequence, tyRange, tySet:
of tyVar, tyLent, tyRef, tyPtr, tySequence, tyRange, tySet, tyOpenArray:
var s =
"var $1 = {size: 0, kind: $2, base: null, node: null, finalizer: null};$n" %
[result, rope(ord(t.kind))]

View File

@@ -140,7 +140,7 @@ proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator)
rawAddSon(result, intType)
proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
result = newSym(skField, getIdent(g.cache, ":state"), nextSymId(idgen), iter, iter.info)
result = newSym(skField, getIdent(g.cache, ":state"), idgen, iter, iter.info)
result.typ = createClosureIterStateType(g, iter, idgen)
proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
@@ -154,7 +154,7 @@ proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym
result = iter.ast[resultPos].sym
else:
# XXX a bit hacky:
result = newSym(skResult, getIdent(g.cache, ":result"), nextSymId(idgen), iter, iter.info, {})
result = newSym(skResult, getIdent(g.cache, ":result"), idgen, iter, iter.info, {})
result.typ = iter.typ[0]
incl(result.flags, sfUsed)
iter.ast.add newSymNode(result)
@@ -258,8 +258,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PN
let iter = n.sym
assert iter.isIterator
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
result = newNodeIT(nkStmtListExpr, n.info, iter.typ)
let hp = getHiddenParam(g, iter)
var env: PNode
if owner.isIterator:
@@ -267,7 +266,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PN
addUniqueField(it.typ.skipTypes({tyOwned})[0], hp, g.cache, idgen)
env = indirectAccess(newSymNode(it), hp, hp.info)
else:
let e = newSym(skLet, iter.name, nextSymId(idgen), owner, n.info)
let e = newSym(skLet, iter.name, idgen, owner, n.info)
e.typ = hp.typ
e.flags = hp.flags
env = newSymNode(e)
@@ -293,23 +292,26 @@ proc freshVarForClosureIter*(g: ModuleGraph; s: PSym; idgen: IdGenerator; owner:
proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
let s = n.sym
let isEnv = s.name.id == getIdent(g.cache, ":env").id
if illegalCapture(s):
localError(g.config, n.info,
("'$1' is of type <$2> which cannot be captured as it would violate memory" &
" safety, declared here: $3; using '-d:nimNoLentIterators' helps in some cases." &
" Consider using a <ref $2> which can be captured.") %
[s.name.s, typeToString(s.typ), g.config$s.info])
elif not (owner.typ.callConv == ccClosure or owner.typ.callConv == ccNimCall and tfExplicitCallConv notin owner.typ.flags):
elif not (owner.typ.isClosure or owner.isNimcall and not owner.isExplicitCallConv or isEnv):
localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
[s.name.s, owner.name.s, $owner.typ.callConv])
incl(owner.typ.flags, tfCapturesEnv)
owner.typ.callConv = ccClosure
if not isEnv:
owner.typ.callConv = ccClosure
type
DetectionPass = object
processed, capturedVars: IntSet
ownerToType: Table[int, PType]
somethingToDo: bool
inTypeOf: bool
graph: ModuleGraph
idgen: IdGenerator
@@ -380,7 +382,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
if c.graph.config.selectedGC == gcDestructors and sfCursor notin upField.flags:
localError(c.graph.config, dep.info, "internal error: up reference is not a .cursor")
else:
let result = newSym(skField, upIdent, nextSymId(c.idgen), obj.owner, obj.owner.info)
let result = newSym(skField, upIdent, c.idgen, obj.owner, obj.owner.info)
result.typ = fieldType
when false:
if c.graph.config.selectedGC == gcDestructors:
@@ -413,12 +415,15 @@ Consider:
"""
proc isTypeOf(n: PNode): bool =
n.kind == nkSym and n.sym.magic in {mTypeOf, mType}
proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
var cp = getEnvParam(fn)
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
let t = c.getEnvTypeForOwner(owner, info)
if cp == nil:
cp = newSym(skParam, getIdent(c.graph.cache, paramName), nextSymId(c.idgen), fn, fn.info)
cp = newSym(skParam, getIdent(c.graph.cache, paramName), c.idgen, fn, fn.info)
incl(cp.flags, sfFromGeneric)
cp.typ = t
addHiddenParam(fn, cp)
@@ -444,12 +449,15 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
let body = transformBody(c.graph, c.idgen, s, useCache)
detectCapturedVars(body, s, c)
let ow = s.skipGenericOwner
let innerClosure = innerProc and s.typ.callConv == ccClosure and not s.isIterator
let interested = interestingVar(s)
if ow == owner:
if owner.isIterator:
c.somethingToDo = true
addClosureParam(c, owner, n.info)
if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id):
if not c.capturedVars.contains(s.id):
if not c.inTypeOf: c.capturedVars.incl(s.id)
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
@@ -458,7 +466,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
else:
discard addField(obj, s, c.graph.cache, c.idgen)
# direct or indirect dependency:
elif (innerProc and not s.isIterator and s.typ.callConv == ccClosure) or interestingVar(s):
elif innerClosure or interested:
discard """
proc outer() =
var x: int
@@ -475,10 +483,12 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
addClosureParam(c, owner, n.info)
#echo "capturing ", n.info
# variable 's' is actually captured:
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
discard addField(obj, s, c.graph.cache, c.idgen)
if interestingVar(s):
if not c.capturedVars.contains(s.id):
if not c.inTypeOf: c.capturedVars.incl(s.id)
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
discard addField(obj, s, c.graph.cache, c.idgen)
# create required upFields:
var w = owner.skipGenericOwner
if isInnerProc(w) or owner.isIterator:
@@ -510,9 +520,14 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
detectCapturedVars(n[namePos], owner, c)
of nkReturnStmt:
detectCapturedVars(n[0], owner, c)
of nkIdentDefs:
detectCapturedVars(n[^1], owner, c)
else:
if n.isCallExpr and n[0].isTypeOf:
c.inTypeOf = true
for i in 0..<n.len:
detectCapturedVars(n[i], owner, c)
c.inTypeOf = false
type
LiftingPass = object
@@ -545,7 +560,7 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result = n
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo; idgen: IdGenerator): PNode =
var v = newSym(skVar, getIdent(cache, envName), nextSymId(idgen), owner, info)
var v = newSym(skVar, getIdent(cache, envName), idgen, owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = typ
result = newSymNode(v)
@@ -569,7 +584,7 @@ proc setupEnvVar(owner: PSym; d: var DetectionPass;
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info, d.idgen)
c.envVars[owner.id] = result
if optOwnedRefs in d.graph.config.globalOptions:
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), nextSymId d.idgen, owner, info)
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), d.idgen, owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = envVarType
c.unownedEnvVars[owner.id] = newSymNode(v)
@@ -653,7 +668,7 @@ proc closureCreationForIter(iter: PNode;
d: var DetectionPass; c: var LiftingPass): PNode =
result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ)
let owner = iter.sym.skipGenericOwner
var v = newSym(skVar, getIdent(d.graph.cache, envName), nextSymId(d.idgen), owner, iter.info)
var v = newSym(skVar, getIdent(d.graph.cache, envName), d.idgen, owner, iter.info)
incl(v.flags, sfShadowed)
v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ)
var vnode: PNode
@@ -792,6 +807,8 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
of nkTypeOfExpr:
result = n
else:
if n.isCallExpr and n[0].isTypeOf:
return
if owner.isIterator:
if nfLL in n.flags:
# special case 'when nimVm' due to bug #3636:
@@ -859,7 +876,7 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType;
fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
idgen: IdGenerator): PNode =
idgen: IdGenerator, force: bool): PNode =
# XXX backend == backendJs does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ...
@@ -868,7 +885,7 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
if body.kind == nkEmpty or (
g.config.backend == backendJs and not isCompileTime) or
fn.skipGenericOwner.kind != skModule:
(fn.skipGenericOwner.kind != skModule and not force):
# ignore forward declaration:
result = body
@@ -943,7 +960,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym):
let iter = op.sym
let hp = getHiddenParam(g, iter)
env = newSym(skLet, iter.name, nextSymId(idgen), owner, body.info)
env = newSym(skLet, iter.name, idgen, owner, body.info)
env.typ = hp.typ
env.flags = hp.flags
@@ -971,12 +988,15 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym):
# gather vars in a tuple:
var v2 = newNodeI(nkLetSection, body.info)
var vpart = newNodeI(if body.len == 3: nkIdentDefs else: nkVarTuple, body.info)
for i in 0..<body.len-2:
if body[i].kind == nkSym:
body[i].sym.transitionToLet()
vpart.add body[i]
if body.len == 3 and body[0].kind == nkVarTuple:
vpart = body[0] # fixes for (i,j) in walk() # bug #15924
else:
for i in 0..<body.len-2:
if body[i].kind == nkSym:
body[i].sym.transitionToLet()
vpart.add body[i]
vpart.add newNodeI(nkEmpty, body.info) # no explicit type
vpart.add newNodeI(nkEmpty, body.info) # no explicit type
if not env.isNil:
call[0] = makeClosure(g, idgen, call[0].sym, env.newSymNode, body.info)
vpart.add call

View File

@@ -510,7 +510,7 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
rememberSplit(splitComma)
wrSpace em
of openPars:
if tok.strongSpaceA and not em.endsInWhite and
if tsLeading in tok.spacing and not em.endsInWhite and
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
wrSpace em
wr(em, $tok.tokType, ltSomeParLe)
@@ -528,7 +528,7 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
wr(em, $tok.tokType, ltOther)
if not em.inquote: wrSpace(em)
of tkOpr, tkDotDot:
if em.inquote or (((not tok.strongSpaceA) and tok.strongSpaceB == tsNone) and
if em.inquote or (tok.spacing == {} and
tok.ident.s notin ["<", ">", "<=", ">=", "==", "!="]):
# bug #9504: remember to not spacify a keyword:
lastTokWasTerse = true
@@ -538,7 +538,7 @@ proc emitTok*(em: var Emitter; L: Lexer; tok: Token) =
if not em.endsInWhite: wrSpace(em)
wr(em, tok.ident.s, ltOpr)
template isUnary(tok): bool =
tok.strongSpaceB == tsNone and tok.strongSpaceA
tok.spacing == {tsLeading}
if not isUnary(tok):
rememberSplit(splitBinary)

View File

@@ -23,7 +23,6 @@ when defined(nimPreviewSlimSystem):
import std/[assertions, formatfloat]
const
MaxLineLength* = 80 # lines longer than this lead to a warning
numChars*: set[char] = {'0'..'9', 'a'..'z', 'A'..'Z'}
SymChars*: set[char] = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
SymStartChars*: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
@@ -94,19 +93,18 @@ type
base2, base8, base16
TokenSpacing* = enum
tsNone, tsTrailing, tsEof
tsLeading, tsTrailing, tsEof
Token* = object # a Nim token
tokType*: TokType # the type of the token
base*: NumericalBase # the numerical base; only valid for int
# or float literals
spacing*: set[TokenSpacing] # spaces around token
indent*: int # the indentation; != -1 if the token has been
# preceded with indentation
ident*: PIdent # the parsed identifier
iNumber*: BiggestInt # the parsed integer literal
fNumber*: BiggestFloat # the parsed floating point literal
base*: NumericalBase # the numerical base; only valid for int
# or float literals
strongSpaceA*: bool # leading spaces of an operator
strongSpaceB*: TokenSpacing # trailing spaces of an operator
literal*: string # the parsed (string) literal; and
# documentation comments are here too
line*, col*: int
@@ -127,6 +125,8 @@ type
cache*: IdentCache
when defined(nimsuggest):
previousToken: TLineInfo
tokenEnd*: TLineInfo
previousTokenEnd*: TLineInfo
config*: ConfigRef
proc getLineInfo*(L: Lexer, tok: Token): TLineInfo {.inline.} =
@@ -176,7 +176,7 @@ proc initToken*(L: var Token) =
L.tokType = tkInvalid
L.iNumber = 0
L.indent = 0
L.strongSpaceA = false
L.spacing = {}
L.literal = ""
L.fNumber = 0.0
L.base = base10
@@ -189,7 +189,7 @@ proc fillToken(L: var Token) =
L.tokType = tkInvalid
L.iNumber = 0
L.indent = 0
L.strongSpaceA = false
L.spacing = {}
setLen(L.literal, 0)
L.fNumber = 0.0
L.base = base10
@@ -735,10 +735,6 @@ proc handleCRLF(L: var Lexer, pos: int): int =
template registerLine =
let col = L.getColNumber(pos)
when not defined(nimpretty):
if col > MaxLineLength:
lexMessagePos(L, hintLineTooLong, pos)
case L.buf[pos]
of CR:
registerLine()
@@ -958,13 +954,15 @@ proc getOperator(L: var Lexer, tok: var Token) =
tokenEnd(tok, pos-1)
# advance pos but don't store it in L.bufpos so the next token (which might
# be an operator too) gets the preceding spaces:
tok.strongSpaceB = tsNone
tok.spacing = tok.spacing - {tsTrailing, tsEof}
var trailing = false
while L.buf[pos] == ' ':
inc pos
if tok.strongSpaceB != tsTrailing:
tok.strongSpaceB = tsTrailing
trailing = true
if L.buf[pos] in {CR, LF, nimlexbase.EndOfFile}:
tok.strongSpaceB = tsEof
tok.spacing.incl(tsEof)
elif trailing:
tok.spacing.incl(tsTrailing)
proc getPrecedence*(tok: Token): int =
## Calculates the precedence of the given token.
@@ -1075,7 +1073,6 @@ proc skipMultiLineComment(L: var Lexer; tok: var Token; start: int;
when defined(nimpretty): tok.literal.add "\L"
if isDoc:
when not defined(nimpretty): tok.literal.add "\n"
inc tok.iNumber
var c = toStrip
while L.buf[pos] == ' ' and c > 0:
inc pos
@@ -1094,8 +1091,6 @@ proc skipMultiLineComment(L: var Lexer; tok: var Token; start: int;
proc scanComment(L: var Lexer, tok: var Token) =
var pos = L.bufpos
tok.tokType = tkComment
# iNumber contains the number of '\n' in the token
tok.iNumber = 0
assert L.buf[pos+1] == '#'
when defined(nimpretty):
tok.commentOffsetA = L.offsetBase + pos
@@ -1138,7 +1133,6 @@ proc scanComment(L: var Lexer, tok: var Token) =
while L.buf[pos] == ' ' and c > 0:
inc pos
dec c
inc tok.iNumber
else:
if L.buf[pos] > ' ':
L.indentAhead = indent
@@ -1151,7 +1145,7 @@ proc scanComment(L: var Lexer, tok: var Token) =
proc skip(L: var Lexer, tok: var Token) =
var pos = L.bufpos
tokenBegin(tok, pos)
tok.strongSpaceA = false
tok.spacing.excl(tsLeading)
when defined(nimpretty):
var hasComment = false
var commentIndent = L.currLineIndent
@@ -1162,8 +1156,7 @@ proc skip(L: var Lexer, tok: var Token) =
case L.buf[pos]
of ' ':
inc(pos)
if not tok.strongSpaceA:
tok.strongSpaceA = true
tok.spacing.incl(tsLeading)
of '\t':
if not L.allowTabs: lexMessagePos(L, errGenerated, pos, "tabs are not allowed, use spaces instead")
inc(pos)
@@ -1185,7 +1178,7 @@ proc skip(L: var Lexer, tok: var Token) =
pos = L.bufpos
else:
break
tok.strongSpaceA = false
tok.spacing.excl(tsLeading)
when defined(nimpretty):
if L.buf[pos] == '#' and tok.line < 0: commentIndent = indent
if L.buf[pos] > ' ' and (L.buf[pos] != '#' or L.buf[pos+1] == '#'):
@@ -1224,6 +1217,10 @@ proc skip(L: var Lexer, tok: var Token) =
proc rawGetTok*(L: var Lexer, tok: var Token) =
template atTokenEnd() {.dirty.} =
when defined(nimsuggest):
L.previousTokenEnd.line = L.tokenEnd.line
L.previousTokenEnd.col = L.tokenEnd.col
L.tokenEnd.line = tok.line.uint16
L.tokenEnd.col = getColNumber(L, L.bufpos).int16
# we attach the cursor to the last *strong* token
if tok.tokType notin weakTokens:
L.previousToken.line = tok.line.uint16

View File

@@ -8,7 +8,7 @@
#
## This module implements lifting for type-bound operations
## (``=sink``, ``=``, ``=destroy``, ``=deepCopy``).
## (`=sink`, `=copy`, `=destroy`, `=deepCopy`, `=wasMoved`, `=dup`).
import modulegraphs, lineinfos, idents, ast, renderer, semdata,
sighashes, lowerings, options, types, msgs, magicsys, tables, ccgutils
@@ -34,11 +34,12 @@ type
template destructor*(t: PType): PSym = getAttachedOp(c.g, t, attachedDestructor)
template assignment*(t: PType): PSym = getAttachedOp(c.g, t, attachedAsgn)
template dup*(t: PType): PSym = getAttachedOp(c.g, t, attachedDup)
template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink)
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator): PSym
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym
proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
idgen: IdGenerator)
@@ -49,9 +50,9 @@ proc at(a, i: PNode, elemType: PType): PNode =
result[1] = i
result.typ = elemType
proc destructorOverriden(g: ModuleGraph; t: PType): bool =
proc destructorOverridden(g: ModuleGraph; t: PType): bool =
let op = getAttachedOp(g, t, attachedDestructor)
op != nil and sfOverriden in op.flags
op != nil and sfOverridden in op.flags
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
for i in 0..<t.len:
@@ -82,12 +83,14 @@ proc genBuiltin(c: var TLiftCtx; magic: TMagic; name: string; i: PNode): PNode =
result = genBuiltin(c.g, c.idgen, magic, name, i)
proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink, attachedDup}:
body.add newAsgnStmt(x, y)
elif c.kind == attachedDestructor and c.addMemReset:
let call = genBuiltin(c, mDefault, "default", x)
call.typ = t
body.add newAsgnStmt(x, call)
elif c.kind == attachedWasMoved:
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc genAddr(c: var TLiftCtx; x: PNode): PNode =
if x.kind == nkHiddenDeref:
@@ -137,25 +140,34 @@ proc genContainerOf(c: var TLiftCtx; objType: PType, field, x: PSym): PNode =
proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
var destroy = newNodeIT(nkCall, x.info, op.typ[0])
destroy.add(newSymNode(op))
destroy.add genAddr(c, x)
if op.typ[1].kind != tyVar:
destroy.add x
else:
destroy.add genAddr(c, x)
if sfNeverRaises notin op.flags:
c.canRaise = true
if c.addMemReset:
result = newTree(nkStmtList, destroy, genBuiltin(c, mWasMoved, "wasMoved", x))
result = newTree(nkStmtList, destroy, genBuiltin(c, mWasMoved, "`=wasMoved`", x))
else:
result = destroy
proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool) =
proc genWasMovedCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ[0])
result.add(newSymNode(op))
result.add genAddr(c, x)
proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool, enforceWasMoved = false) =
case n.kind
of nkSym:
if c.filterDiscriminator != nil: return
let f = n.sym
let b = if c.kind == attachedTrace: y else: y.dotField(f)
if (sfCursor in f.flags and f.typ.skipTypes(abstractInst).kind in {tyRef, tyProc} and
c.g.config.selectedGC in {gcArc, gcOrc, gcHooks}) or
if (sfCursor in f.flags and c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc, gcHooks}) or
enforceDefaultOp:
defaultOp(c, f.typ, body, x.dotField(f), b)
else:
if enforceWasMoved:
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x.dotField(f))
fillBody(c, f.typ, body, x.dotField(f), b)
of nkNilLit: discard
of nkRecCase:
@@ -194,7 +206,7 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
branch[^1] = newNodeI(nkStmtList, c.info)
fillBodyObj(c, n[i].lastSon, branch[^1], x, y,
enforceDefaultOp = localEnforceDefaultOp)
enforceDefaultOp = localEnforceDefaultOp, enforceWasMoved = c.kind == attachedAsgn)
if branch[^1].len == 0: inc emptyBranches
caseStmt.add(branch)
if emptyBranches != n.len-1:
@@ -205,13 +217,16 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool)
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
c.filterDiscriminator = oldfilterDiscriminator
of nkRecList:
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp)
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp, enforceWasMoved)
else:
illFormedAstLocal(n, c.g.config)
proc fillBodyObjTImpl(c: var TLiftCtx; t: PType, body, x, y: PNode) =
if t.len > 0 and t[0] != nil:
fillBody(c, skipTypes(t[0], abstractPtrs), body, x, y)
let obj = newNodeIT(nkHiddenSubConv, c.info, t[0])
obj.add newNodeI(nkEmpty, c.info)
obj.add x
fillBody(c, skipTypes(t[0], abstractPtrs), body, obj, y)
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
@@ -236,7 +251,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
# for every field (dependent on dest.kind):
# `=` dest.field, src.field
# =destroy(blob)
var dummy = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info)
var dummy = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
dummy.typ = y.typ
if ccgIntroducedPtr(c.g.config, dummy, y.typ):
# Because of potential aliasing when the src param is passed by ref, we need to check for equality here,
@@ -245,7 +260,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x), newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y))
cond.typ = getSysType(c.g, x.info, tyBool)
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
temp.typ = x.typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info)
@@ -255,7 +270,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
#body.add newAsgnStmt(blob, x)
var wasMovedCall = newNodeI(nkCall, c.info)
wasMovedCall.add(newSymNode(createMagic(c.g, c.idgen, "wasMoved", mWasMoved)))
wasMovedCall.add(newSymNode(createMagic(c.g, c.idgen, "`=wasMoved`", mWasMoved)))
wasMovedCall.add x # mWasMoved does not take the address
body.add wasMovedCall
@@ -268,6 +283,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
c.kind = attachedDestructor
fillBodyObjTImpl(c, t, body, blob, y)
c.kind = prevKind
else:
fillBodyObjTImpl(c, t, body, x, y)
@@ -276,7 +292,7 @@ proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
result.typ = getSysType(g, info, tyBool)
proc getCycleParam(c: TLiftCtx): PNode =
assert c.kind == attachedAsgn
assert c.kind in {attachedAsgn, attachedDup}
if c.fn.typ.len == 4:
result = c.fn.typ.n.lastSon
assert result.kind == nkSym
@@ -315,6 +331,9 @@ proc newOpCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
proc newDeepCopyCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(c, op, y))
proc newDupCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(c, op, y))
proc usesBuiltinArc(t: PType): bool =
proc wrap(t: PType): bool {.nimcall.} = ast.isGCedMem(t)
result = types.searchTypeFor(t, wrap)
@@ -339,9 +358,9 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
field: var PSym): bool =
if optSeqDestructors in c.g.config.globalOptions:
var op = field
let destructorOverriden = destructorOverriden(c.g, t)
let destructorOverridden = destructorOverridden(c.g, t)
if op != nil and op != c.fn and
(sfOverriden in op.flags or destructorOverriden):
(sfOverridden in op.flags or destructorOverridden):
if sfError in op.flags:
incl c.fn.flags, sfError
#else:
@@ -349,7 +368,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
onUse(c.info, op)
body.add newHookCall(c, op, x, y)
result = true
elif op == nil and destructorOverriden:
elif op == nil and destructorOverridden:
op = produceSym(c.g, c.c, t, c.kind, c.info, c.idgen)
body.add newHookCall(c, op, x, y)
result = true
@@ -387,7 +406,7 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
let t = orig.skipTypes(abstractInst - {tyDistinct})
var op = t.destructor
if op != nil and sfOverriden in op.flags:
if op != nil and sfOverridden in op.flags:
if op.ast.isGenericRoutine:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
@@ -410,7 +429,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
case c.kind
of attachedDestructor:
var op = t.destructor
if op != nil and sfOverriden in op.flags:
if op != nil and sfOverridden in op.flags:
if op.ast.isGenericRoutine:
# patch generic destructor:
@@ -424,7 +443,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
#result = addDestructorCall(c, t, body, x)
of attachedAsgn, attachedSink, attachedTrace:
var op = getAttachedOp(c.g, t, c.kind)
if op != nil and sfOverriden in op.flags:
if op != nil and sfOverridden in op.flags:
if op.ast.isGenericRoutine:
# patch generic =trace:
op = instantiateGeneric(c, op, t, t.typeInst)
@@ -442,8 +461,36 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
body.add newDeepCopyCall(c, op, x, y)
result = true
of attachedWasMoved:
var op = getAttachedOp(c.g, t, attachedWasMoved)
if op != nil and sfOverridden in op.flags:
if op.ast.isGenericRoutine:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
setAttachedOp(c.g, c.idgen.module, t, attachedWasMoved, op)
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add genWasMovedCall(c, op, x)
result = true
of attachedDup:
var op = getAttachedOp(c.g, t, attachedDup)
if op != nil and sfOverridden in op.flags:
if op.ast.isGenericRoutine:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
setAttachedOp(c.g, c.idgen.module, t, attachedDup, op)
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newDupCall(c, op, x, y)
result = true
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId(c.idgen), c.fn, c.info)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
temp.typ = getSysType(c.g, body.info, tyInt)
incl(temp.flags, sfFromGeneric)
@@ -453,7 +500,7 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
body.add v
proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId(c.idgen), c.fn, c.info)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
temp.typ = value.typ
incl(temp.flags, sfFromGeneric)
@@ -500,14 +547,28 @@ proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
else:
body.sons.setLen counterIdx
proc checkSelfAssignment(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var cond = callCodegenProc(c.g, "sameSeqPayload", c.info,
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x),
newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y)
)
cond.typ = getSysType(c.g, c.info, tyBool)
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedDup:
body.add setLenSeqCall(c, t, x, y)
forallElements(c, t, body, x, y)
of attachedAsgn, attachedDeepCopy:
# we generate:
# if x.p == y.p:
# return
# setLen(dest, y.len)
# var i = 0
# while i < y.len: dest[i] = y[i]; inc(i)
# This is usually more efficient than a destroy/create pair.
checkSelfAssignment(c, t, body, x, y)
body.add setLenSeqCall(c, t, x, y)
forallElements(c, t, body, x, y)
of attachedSink:
@@ -521,17 +582,18 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
forallElements(c, t, body, x, y)
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
if canFormAcycle(t.elemType):
if canFormAcycle(c.g, t.elemType):
# follow all elements:
forallElements(c, t, body, x, y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
createTypeBoundOps(c.g, c.c, t, body.info, c.idgen)
# recursions are tricky, so we might need to forward the generated
# operation here:
var t = t
if t.assignment == nil or t.destructor == nil:
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
if t.assignment == nil or t.destructor == nil or t.dup == nil:
let h = sighashes.hashType(t,c.g.config, {CoType, CoConsiderOwned, CoDistinct})
let canon = c.g.canonTypes.getOrDefault(h)
if canon != nil: t = canon
@@ -556,15 +618,22 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
doAssert t.destructor != nil
body.add destructorCall(c, t.destructor, x)
of attachedTrace:
if t.kind != tyString and canFormAcycle(t.elemType):
if t.kind != tyString and canFormAcycle(c.g, t.elemType):
let op = getAttachedOp(c.g, t, c.kind)
if op == nil:
return # protect from recursion
body.add newHookCall(c, op, x, y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
# XXX: replace these with assertions.
let op = getAttachedOp(c.g, t, c.kind)
if op == nil:
return # protect from recursion
body.add newDupCall(c, op, x, y)
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
of attachedAsgn, attachedDeepCopy:
of attachedAsgn, attachedDeepCopy, attachedDup:
body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y)
of attachedSink:
let moveCall = genBuiltin(c, mMove, "move", x)
@@ -576,10 +645,11 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
discard "strings are atomic and have no inner elements that are to trace"
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc cyclicType*(t: PType): bool =
proc cyclicType*(g: ModuleGraph, t: PType): bool =
case t.kind
of tyRef: result = types.canFormAcycle(t.lastSon)
of tyRef: result = types.canFormAcycle(g, t.lastSon)
of tyProc: result = t.callConv == ccClosure
else: result = false
@@ -607,10 +677,15 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let elemType = t.lastSon
createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen)
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(elemType)
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(c.g, elemType)
let isInheritableAcyclicRef = c.g.config.selectedGC == gcOrc and
(not isPureObject(elemType)) and
tfAcyclic in skipTypes(elemType, abstractInst+{tyOwned}-{tyTypeDesc}).flags
# dynamic Acyclic refs need to use dyn decRef
let tmp =
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}:
declareTempOf(c, body, x)
else:
x
@@ -632,6 +707,8 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
elif isInheritableAcyclicRef:
cond = callCodegenProc(c.g, "nimDecRefIsLastDyn", c.info, x)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
cond.typ = getSysType(c.g, x.info, tyBool)
@@ -667,6 +744,16 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x, c.idgen), y)
#echo "can follow ", elemType, " static ", isFinal(elemType)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, y, callCodegenProc(c.g,
"nimIncRefCyclic", c.info, y, getCycleParam(c)))
else:
body.add newAsgnStmt(x, y)
body.add genIf(c, y, callCodegenProc(c.g,
"nimIncRef", c.info, y))
proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
## Closures are really like refs except they always use a virtual destructor
@@ -676,7 +763,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let isCyclic = c.g.config.selectedGC == gcOrc
let tmp =
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}:
declareTempOf(c, body, xenv)
else:
xenv
@@ -710,11 +797,21 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedDup:
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
yenv.typ = getSysType(c.g, c.info, tyPointer)
if isCyclic:
body.add newAsgnStmt(x, y)
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
else:
body.add newAsgnStmt(x, y)
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRef", c.info, yenv))
of attachedDestructor:
body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
@@ -727,6 +824,9 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
body.add newAsgnStmt(x, y)
of attachedDup:
body.add newAsgnStmt(x, y)
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
of attachedDestructor:
# it's better to prepend the destruction of weak refs in order to
# prevent wrong "dangling refs exist" problems:
@@ -739,6 +839,7 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var actions = newNodeI(nkStmtList, c.info)
@@ -760,10 +861,13 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedSink, attachedAsgn:
body.add genIf(c, x, actions)
body.add newAsgnStmt(x, y)
of attachedDup:
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, x, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind == attachedDeepCopy:
@@ -775,7 +879,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
call[1] = y
body.add newAsgnStmt(x, call)
elif (optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options) or c.g.config.selectedGC in {gcArc, gcOrc}:
optRefCheck in c.g.config.options) or c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.g, c.info, tyPointer)
case c.kind
@@ -790,6 +894,11 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
body.add newAsgnStmt(x, y)
of attachedDup:
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
yy.typ = getSysType(c.g, c.info, tyPointer)
body.add newAsgnStmt(x, y)
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
of attachedDestructor:
let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
if body.len == 0:
@@ -798,6 +907,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
@@ -809,10 +919,13 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedSink, attachedAsgn:
body.add genIf(c, xx, actions)
body.add newAsgnStmt(x, y)
of attachedDup:
body.add newAsgnStmt(x, y)
of attachedDestructor:
body.add genIf(c, xx, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind
@@ -821,7 +934,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
tyPtr, tyUncheckedArray, tyVar, tyLent:
defaultOp(c, t, body, x, y)
of tyRef:
if c.g.config.selectedGC in {gcArc, gcOrc}:
if c.g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
atomicRefOp(c, t, body, x, y)
elif (optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options):
@@ -830,7 +943,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyProc:
if t.callConv == ccClosure:
if c.g.config.selectedGC in {gcArc, gcOrc}:
if c.g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc}:
atomicClosureOp(c, t, body, x, y)
else:
closureOp(c, t, body, x, y)
@@ -876,10 +989,25 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyObject:
if not considerUserDefinedOp(c, t, body, x, y):
if c.kind in {attachedAsgn, attachedSink} and t.sym != nil and sfImportc in t.sym.flags:
body.add newAsgnStmt(x, y)
if t.sym != nil and sfImportc in t.sym.flags:
case c.kind
of {attachedAsgn, attachedSink, attachedDup}:
body.add newAsgnStmt(x, y)
of attachedWasMoved:
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
else:
fillBodyObjT(c, t, body, x, y)
else:
fillBodyObjT(c, t, body, x, y)
if c.kind == attachedDup:
var op2 = getAttachedOp(c.g, t, attachedAsgn)
if op2 != nil and sfOverridden in op2.flags:
#markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op2)
body.add newHookCall(c, t.assignment, x, y)
else:
fillBodyObjT(c, t, body, x, y)
else:
fillBodyObjT(c, t, body, x, y)
of tyDistinct:
if not considerUserDefinedOp(c, t, body, x, y):
fillBody(c, t[0], body, x, y)
@@ -908,19 +1036,62 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
assert typ.kind == tyDistinct
let baseType = typ[0]
if getAttachedOp(g, baseType, kind) == nil:
discard produceSym(g, c, baseType, kind, info, idgen)
# TODO: fixme `isDistinct` is a fix for #23552; remove it after
# `-d:nimPreviewNonVarDestructor` becomes the default
discard produceSym(g, c, baseType, kind, info, idgen, isDistinct = true)
result = getAttachedOp(g, baseType, kind)
setAttachedOp(g, idgen.module, typ, kind, result)
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator): PSym =
let procname = getIdent(g.cache, AttachedOpToStr[kind])
result = newSym(skProc, procname, idgen, owner, info)
let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info)
let src = newSym(skParam, getIdent(g.cache, "src"),
idgen, result, info)
res.typ = typ
src.typ = typ
result.typ = newType(tyProc, nextTypeId idgen, owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
result.typ.n.add newNodeI(nkEffectList, info)
result.typ.addParam src
if g.config.selectedGC == gcOrc and
cyclicType(g, typ.skipTypes(abstractInst)):
let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"),
idgen, result, info)
cycleParam.typ = getSysType(g, info, tyBool)
result.typ.addParam cycleParam
var n = newNodeI(nkProcDef, info, bodyPos+2)
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = newNodeI(nkStmtList, info)
n[resultPos] = newSymNode(res)
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfGeneratedOp
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator; isDiscriminant = false; isDistinct = false): PSym =
if kind == attachedDup:
return symDupPrototype(g, typ, owner, kind, info, idgen)
let procname = getIdent(g.cache, AttachedOpToStr[kind])
result = newSym(skProc, procname, nextSymId(idgen), owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), nextSymId(idgen), result, info)
result = newSym(skProc, procname, idgen, owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), idgen, result, info)
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
nextSymId(idgen), result, info)
dest.typ = makeVarType(typ.owner, typ, idgen)
idgen, result, info)
if kind == attachedDestructor and g.config.selectedGC in {gcArc, gcOrc, gcAtomicArc} and
((g.config.isDefined("nimPreviewNonVarDestructor") and not isDiscriminant) or (typ.kind in {tyRef, tyString, tySequence} and not isDistinct)):
dest.typ = typ
else:
dest.typ = makeVarType(typ.owner, typ, idgen)
if kind == attachedTrace:
src.typ = getSysType(g, info, tyPointer)
else:
@@ -928,13 +1099,13 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
result.typ = newProcType(info, nextTypeId(idgen), owner)
result.typ.addParam dest
if kind != attachedDestructor:
if kind notin {attachedDestructor, attachedWasMoved}:
result.typ.addParam src
if kind == attachedAsgn and g.config.selectedGC == gcOrc and
cyclicType(typ.skipTypes(abstractInst)):
cyclicType(g, typ.skipTypes(abstractInst)):
let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"),
nextSymId(idgen), result, info)
idgen, result, info)
cycleParam.typ = getSysType(g, info, tyBool)
result.typ.addParam cycleParam
@@ -946,6 +1117,9 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfGeneratedOp
if kind == attachedWasMoved:
incl result.flags, sfNoSideEffect
incl result.typ.flags, tfNoSideEffect
proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xx = genBuiltin(c, mAccessTypeField, "accessTypeField", x)
@@ -955,33 +1129,36 @@ proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add newAsgnStmt(xx, yy)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo; idgen: IdGenerator): PSym =
info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym =
if typ.kind == tyDistinct:
return produceSymDistinctType(g, c, typ, kind, info, idgen)
result = getAttachedOp(g, typ, kind)
if result == nil:
result = symPrototype(g, typ, typ.owner, kind, info, idgen)
result = symPrototype(g, typ, typ.owner, kind, info, idgen, isDistinct = isDistinct)
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType: typ, idgen: idgen,
fn: result)
let dest = result.typ.n[1].sym
let d = newDeref(newSymNode(dest))
let src = if kind == attachedDestructor: newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
let dest = if kind == attachedDup: result.ast[resultPos].sym else: result.typ.n[1].sym
let d = if result.typ[1].kind == tyVar: newDeref(newSymNode(dest)) else: newSymNode(dest)
let src = case kind
of {attachedDestructor, attachedWasMoved}: newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
of attachedDup: newSymNode(result.typ.n[1].sym)
else: newSymNode(result.typ.n[2].sym)
# register this operation already:
setAttachedOpPartial(g, idgen.module, typ, kind, result)
if kind == attachedSink and destructorOverriden(g, typ):
if kind == attachedSink and destructorOverridden(g, typ):
## compiler can use a combination of `=destroy` and memCopy for sink op
dest.flags.incl sfCursor
result.ast[bodyPos].add newOpCall(a, getAttachedOp(g, typ, attachedDestructor), d[0])
let op = getAttachedOp(g, typ, attachedDestructor)
result.ast[bodyPos].add newOpCall(a, op, if op.typ[1].kind == tyVar: d[0] else: d)
result.ast[bodyPos].add newAsgnStmt(d, src)
else:
var tk: TTypeKind
if g.config.selectedGC in {gcArc, gcOrc, gcHooks}:
if g.config.selectedGC in {gcArc, gcOrc, gcHooks, gcAtomicArc}:
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
else:
tk = tyNone # no special casing for strings and seqs
@@ -992,18 +1169,24 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
fillStrOp(a, typ, result.ast[bodyPos], d, src)
else:
fillBody(a, typ, result.ast[bodyPos], d, src)
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy} and not lacksMTypeField(typ):
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy, attachedDup} and not lacksMTypeField(typ):
# bug #19205: Do not forget to also copy the hidden type field:
genTypeFieldCopy(a, typ, result.ast[bodyPos], d, src)
if not a.canRaise: incl result.flags, sfNeverRaises
if not a.canRaise:
incl result.flags, sfNeverRaises
result.ast[pragmasPos] = newNodeI(nkPragma, info)
result.ast[pragmasPos].add newTree(nkExprColonExpr,
newIdentNode(g.cache.getIdent("raises"), info), newNodeI(nkBracket, info))
completePartialOp(g, idgen.module, typ, kind, result)
proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
info: TLineInfo; idgen: IdGenerator): PSym =
assert(typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject)
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info, idgen)
# discrimantor assignments needs pointers to destroy fields; alas, we cannot use non-var destructor here
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info, idgen, isDiscriminant = true)
var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ, idgen: idgen,
fn: result)
a.asgnForType = typ
@@ -1011,7 +1194,7 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
a.addMemReset = true
let discrimantDest = result.typ.n[1].sym
let dst = newSym(skVar, getIdent(g.cache, "dest"), nextSymId(idgen), result, info)
let dst = newSym(skVar, getIdent(g.cache, "dest"), idgen, result, info)
dst.typ = makePtrType(typ.owner, typ, idgen)
let dstSym = newSymNode(dst)
let d = newDeref(dstSym)
@@ -1037,7 +1220,7 @@ proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo; idgen: Id
if op != nil:
if op.ast.isGenericRoutine:
internalError(g.config, info, "resolved destructor is generic")
if op.magic == mDestroy:
if op.magic == mDestroy and t.kind != tyString:
internalError(g.config, info, "patching mDestroy with mDestroy?")
n[0] = newSymNode(op)
for x in n: patchBody(g, c, x, info, idgen)
@@ -1047,13 +1230,7 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I
let op = getAttachedOp(g, t, kind)
if op != nil and op.ast != nil and op.ast.isGenericRoutine:
if t.typeInst != nil:
var a: TLiftCtx
a.info = info
a.g = g
a.kind = kind
a.c = c
a.idgen = idgen
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, idgen: idgen)
let opInst = instantiateGeneric(a, op, t, t.typeInst)
if opInst.ast != nil:
patchBody(g, c, opInst.ast, info, a.idgen)
@@ -1061,7 +1238,7 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I
else:
localError(g.config, info, "unresolved generic parameter")
proc isTrival(s: PSym): bool {.inline.} =
proc isTrival*(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo;
@@ -1075,7 +1252,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
let h = sighashes.hashType(skipped, g.config, {CoType, CoConsiderOwned, CoDistinct})
var canon = g.canonTypes.getOrDefault(h)
if canon == nil:
g.canonTypes[h] = skipped
@@ -1096,15 +1273,15 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
# bug #15122: We need to produce all prototypes before entering the
# mind boggling recursion. Hacks like these imply we should rewrite
# this module.
var generics: array[attachedDestructor..attachedTrace, bool]
for k in attachedDestructor..lastAttached:
var generics: array[attachedWasMoved..attachedTrace, bool]
for k in attachedWasMoved..lastAttached:
generics[k] = getAttachedOp(g, canon, k) != nil
if not generics[k]:
setAttachedOp(g, idgen.module, canon, k,
symPrototype(g, canon, canon.owner, k, info, idgen))
# we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..lastAttached:
for k in attachedWasMoved..lastAttached:
if not generics[k]:
discard produceSym(g, c, canon, k, info, idgen)
else:

View File

@@ -44,6 +44,7 @@ type
errRstSandboxedDirective,
errProveInit, # deadcode
errGenerated,
errFailedMove,
errUser,
# warnings
warnCannotOpenFile = "CannotOpenFile", warnOctalEscape = "OctalEscape",
@@ -57,6 +58,7 @@ type
warnRstBrokenLink = "BrokenLink",
warnRstLanguageXNotSupported = "LanguageXNotSupported",
warnRstFieldXNotSupported = "FieldXNotSupported",
warnRstUnusedImportdoc = "UnusedImportdoc",
warnRstStyle = "warnRstStyle",
warnCommentXIgnored = "CommentXIgnored",
warnTypelessParam = "TypelessParam",
@@ -82,14 +84,18 @@ type
warnCstringConv = "CStringConv",
warnPtrToCstringConv = "PtrToCstringConv",
warnEffect = "Effect",
warnCastSizes = "CastSizes"
warnTemplateRedefinition = "TemplateRedefinition",
warnCastSizes = "CastSizes", # deadcode
warnAboveMaxSizeSet = "AboveMaxSizeSet",
warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition",
warnUnnamedBreak = "UnnamedBreak",
warnStmtListLambda = "StmtListLambda",
warnBareExcept = "BareExcept",
warnImplicitDefaultValue = "ImplicitDefaultValue",
warnIgnoredSymbolInjection = "IgnoredSymbolInjection",
warnUser = "User",
# hints
hintSuccess = "Success", hintSuccessX = "SuccessX",
hintCC = "CC",
hintLineTooLong = "LineTooLong",
hintXDeclaredButNotUsed = "XDeclaredButNotUsed", hintDuplicateModuleImport = "DuplicateModuleImport",
hintXCannotRaiseY = "XCannotRaiseY", hintConvToBaseNotNeeded = "ConvToBaseNotNeeded",
hintConvFromXtoItselfNotNeeded = "ConvFromXtoItselfNotNeeded", hintExprAlwaysX = "ExprAlwaysX",
@@ -99,10 +105,10 @@ type
hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
hintAmbiguousEnum = "AmbiguousEnum",
hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
hintMsgOrigin = "MsgOrigin", # since 1.3.5
hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
hintUnknownHint = "UnknownHint"
const
MsgKindToStr*: array[TMsgKind, string] = [
@@ -124,6 +130,7 @@ const
errRstSandboxedDirective: "disabled directive: '$1'",
errProveInit: "Cannot prove that '$1' is initialized.", # deadcode
errGenerated: "$1",
errFailedMove: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored",
@@ -140,6 +147,7 @@ const
warnRstBrokenLink: "broken link '$1'",
warnRstLanguageXNotSupported: "language '$1' not supported",
warnRstFieldXNotSupported: "field '$1' not supported",
warnRstUnusedImportdoc: "importdoc for '$1' is not used",
warnRstStyle: "RST style: $1",
warnCommentXIgnored: "comment '$1' ignored",
warnTypelessParam: "", # deadcode
@@ -178,17 +186,21 @@ const
warnAnyEnumConv: "$1",
warnHoleEnumConv: "$1",
warnCstringConv: "$1",
warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; this will become a compile time error in the future",
warnPtrToCstringConv: "unsafe conversion to 'cstring' from '$1'; Use a `cast` operation like `cast[cstring](x)`; this will become a compile time error in the future",
warnEffect: "$1",
warnCastSizes: "$1",
warnTemplateRedefinition: "template '$1' is implicitly redefined, consider adding an explicit .redefine pragma",
warnCastSizes: "$1", # deadcode
warnAboveMaxSizeSet: "$1",
warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma",
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
warnBareExcept: "$1",
warnImplicitDefaultValue: "$1",
warnIgnoredSymbolInjection: "$1",
warnUser: "$1",
hintSuccess: "operation successful: $#",
# keep in sync with `testament.isSuccess`
hintSuccessX: "$build\n$loc lines; ${sec}s; $mem; proj: $project; out: $output",
hintCC: "CC: $1",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintDuplicateModuleImport: "$1",
hintXCannotRaiseY: "$1",
@@ -215,12 +227,12 @@ const
hintGCStats: "$1",
hintGlobalVar: "global variable declared here",
hintExpandMacro: "expanded macro: $1",
hintAmbiguousEnum: "$1",
hintUser: "$1",
hintUserRaw: "$1",
hintExtendedContext: "$1",
hintMsgOrigin: "$1",
hintDeclaredLoc: "$1",
hintUnknownHint: "unknown hint: $1"
]
const
@@ -238,7 +250,7 @@ type
TNoteKinds* = set[TNoteKind]
proc computeNotesVerbosity(): array[0..3, TNoteKinds] =
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed, warnAnyEnumConv}
result[3] = {low(TNoteKind)..high(TNoteKind)} - {warnObservableStores, warnResultUsed, warnAnyEnumConv, warnBareExcept}
result[2] = result[3] - {hintStackTrace, hintExtendedContext, hintDeclaredLoc, hintProcessingStmt}
result[1] = result[2] - {warnProveField, warnProveIndex,
warnGcUnsafe, hintPath, hintDependency, hintCodeBegin, hintCodeEnd,
@@ -269,7 +281,7 @@ type
# and parsed; usually "" but is used
# for 'nimsuggest'
hash*: string # the checksum of the file
dirty*: bool # for 'nimfix' / 'nimpretty' like tooling
dirty*: bool # for 'nimpretty' like tooling
when defined(nimpretty):
fullContent*: string
FileIndex* = distinct int32

View File

@@ -95,7 +95,7 @@ template styleCheckDef*(ctx: PContext; info: TLineInfo; sym: PSym; k: TSymKind)
if optStyleCheck in ctx.config.options and # ignore if styleChecks are off
{optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # check only if hint/error is enabled
hintName in ctx.config.notes and # ignore if name checks are not requested
ctx.config.belongsToProjectPackage(ctx.module) and # ignore foreign packages
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
optStyleUsages notin ctx.config.globalOptions and # ignore if requested to only check name usage
sym.kind != skResult and # ignore `result`
sym.kind != skTemp and # ignore temporary variables created by the compiler
@@ -136,7 +136,7 @@ template styleCheckUse*(ctx: PContext; info: TLineInfo; sym: PSym) =
## Check symbol uses match their definition's style.
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
hintName in ctx.config.notes and # ignore if name checks are not requested
ctx.config.belongsToProjectPackage(ctx.module) and # ignore foreign packages
ctx.config.belongsToProjectPackage(sym) and # ignore foreign packages
sym.kind != skTemp and # ignore temporary variables created by the compiler
sym.name.s[0] in Letters and # ignore operators TODO: what about unicode symbols???
sfAnon notin sym.flags: # ignore temporary variables created by the compiler
@@ -147,6 +147,10 @@ proc checkPragmaUseImpl(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragm
if pragmaName != wanted:
lintReport(conf, info, wanted, pragmaName)
template checkPragmaUse*(conf: ConfigRef; info: TLineInfo; w: TSpecialWord; pragmaName: string) =
if {optStyleHint, optStyleError} * conf.globalOptions != {}:
checkPragmaUseImpl(conf, info, w, pragmaName)
template checkPragmaUse*(ctx: PContext; info: TLineInfo; w: TSpecialWord; pragmaName: string, sym: PSym) =
## Check builtin pragma uses match their definition's style.
## Note: This only applies to builtin pragmas, not user pragmas.
if {optStyleHint, optStyleError} * ctx.config.globalOptions != {} and # ignore if styleChecks are off
hintName in ctx.config.notes and # ignore if name checks are not requested
(sym != nil and ctx.config.belongsToProjectPackage(sym)): # ignore foreign packages
checkPragmaUseImpl(ctx.config, info, w, pragmaName)

View File

@@ -8,14 +8,14 @@
#
# This module implements lookup helpers.
import std/[algorithm, strutils]
import std/[algorithm, strutils, tables]
when defined(nimPreviewSlimSystem):
import std/assertions
import
intsets, ast, astalgo, idents, semdata, types, msgs, options,
renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs
renderer, lineinfos, modulegraphs, astmsgs, sets, wordrecg
proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
@@ -48,7 +48,7 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
case x.kind
of nkIdent: id.add(x.ident.s)
of nkSym: id.add(x.sym.name.s)
of nkSymChoices:
of nkSymChoices, nkOpenSym:
if x[0].kind == nkSym:
id.add(x[0].sym.name.s)
else:
@@ -61,6 +61,8 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
result = n[0].sym.name
else:
handleError(n, origin)
of nkOpenSym:
result = considerQuotedIdent(c, n[0], origin)
else:
handleError(n, origin)
@@ -94,17 +96,6 @@ iterator localScopesFrom*(c: PContext; scope: PScope): PScope =
if s == c.topLevelScope: break
yield s
proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym =
if s == nil or s.kind != skAlias:
result = s
else:
result = s.owner
if conf.cmd == cmdNimfix:
prettybase.replaceDeprecated(conf, n.info, s, result)
else:
message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " &
s.name.s & " is deprecated")
proc isShadowScope*(s: PScope): bool {.inline.} =
s.parent != nil and s.parent.depthLevel == s.depthLevel
@@ -170,6 +161,7 @@ iterator allSyms*(c: PContext): (PSym, int, bool) =
# really iterate over all symbols in all the scopes. This is expensive
# and only used by suggest.nim.
var isLocal = true
var scopeN = 0
for scope in allScopes(c.currentScope):
if scope == c.topLevelScope: isLocal = false
@@ -184,6 +176,17 @@ iterator allSyms*(c: PContext): (PSym, int, bool) =
assert s != nil
yield (s, scopeN, isLocal)
iterator uniqueSyms*(c: PContext): (PSym, int, bool) =
## Like [allSyms] except only returns unique symbols (Uniqueness determined by line + name)
# Track seen symbols so we don't duplicate them.
# The int is for the symbols name, and line info is
# to be able to tell apart symbols with same name but on different lines
var seen = initHashSet[(TLineInfo, int)]()
for res in allSyms(c):
if not seen.containsOrIncl((res[0].info, res[0].name.id)):
yield res
proc someSymFromImportTable*(c: PContext; name: PIdent; ambiguous: var bool): PSym =
var marked = initIntSet()
var symSet = OverloadableSyms
@@ -216,6 +219,23 @@ proc debugScopes*(c: PContext; limit=0, max = int.high) {.deprecated.} =
if i == limit: return
inc i
proc searchInScopesAllCandidatesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSym] =
result = @[]
for scope in allScopes(c.currentScope):
var ti: TIdentIter
var candidate = initIdentIter(ti, scope.symbols, s)
while candidate != nil:
if candidate.kind in filter:
result.add candidate
candidate = nextIdentIter(ti, scope.symbols)
if result.len == 0:
var marked = initIntSet()
for im in c.imports.mitems:
for s in symbols(im, marked, s, c.graph):
if s.kind in filter:
result.add s
proc searchInScopesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSym] =
result = @[]
block outer:
@@ -236,8 +256,63 @@ proc searchInScopesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSy
if s.kind in filter:
result.add s
proc errorSym*(c: PContext, n: PNode): PSym =
proc cmpScopes*(ctx: PContext, s: PSym): int =
# Do not return a negative number
if s.originatingModule == ctx.module:
result = 2
var owner = s
while true:
owner = owner.skipGenericOwner
if owner.kind == skModule: break
inc result
else:
result = 1
proc isAmbiguous*(c: PContext, s: PIdent, filter: TSymKinds, sym: var PSym): bool =
result = false
block outer:
for scope in allScopes(c.currentScope):
var ti: TIdentIter
var candidate = initIdentIter(ti, scope.symbols, s)
var scopeHasCandidate = false
while candidate != nil:
if candidate.kind in filter:
if scopeHasCandidate:
# 2 candidates in same scope, ambiguous
return true
else:
scopeHasCandidate = true
sym = candidate
candidate = nextIdentIter(ti, scope.symbols)
if scopeHasCandidate:
# scope had a candidate but wasn't ambiguous
return false
var importsHaveCandidate = false
var marked = initIntSet()
for im in c.imports.mitems:
for s in symbols(im, marked, s, c.graph):
if s.kind in filter:
if importsHaveCandidate:
# 2 candidates among imports, ambiguous
return true
else:
importsHaveCandidate = true
sym = s
if importsHaveCandidate:
# imports had a candidate but wasn't ambiguous
return false
proc errorSym*(c: PContext, ident: PIdent, info: TLineInfo): PSym =
## creates an error symbol to avoid cascading errors (for IDE support)
result = newSym(skError, ident, c.idgen, getCurrOwner(c), info, {})
result.typ = errorType(c)
incl(result.flags, sfDiscardable)
# pretend it's from the top level scope to prevent cascading errors:
if c.config.cmd != cmdInteractive and c.compilesContextId == 0:
c.moduleScope.addSym(result)
proc errorSym*(c: PContext, n: PNode): PSym =
var m = n
# ensure that 'considerQuotedIdent' can't fail:
if m.kind == nkDotExpr: m = m[1]
@@ -245,12 +320,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
considerQuotedIdent(c, m)
else:
getIdent(c.cache, "err:" & renderTree(m))
result = newSym(skError, ident, nextSymId(c.idgen), getCurrOwner(c), n.info, {})
result.typ = errorType(c)
incl(result.flags, sfDiscardable)
# pretend it's from the top level scope to prevent cascading errors:
if c.config.cmd != cmdInteractive and c.compilesContextId == 0:
c.moduleScope.addSym(result)
result = errorSym(c, ident, n.info)
type
TOverloadIterMode* = enum
@@ -311,15 +381,18 @@ proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string;
# xxx pending bootstrap >= 1.4, replace all those overloads with a single one:
# proc addDecl*(c: PContext, sym: PSym, info = sym.info, scope = c.currentScope) {.inline.} =
proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) =
if sym.name.id == ord(wUnderscore): return
let conflict = scope.addUniqueSym(sym)
if conflict != nil:
if sym.kind == skModule and conflict.kind == skModule and sym.owner == conflict.owner:
if sym.kind == skModule and conflict.kind == skModule:
# e.g.: import foo; import foo
# xxx we could refine this by issuing a different hint for the case
# where a duplicate import happens inside an include.
localError(c.config, info, hintDuplicateModuleImport,
"duplicate import of '$1'; previous import here: $2" %
[sym.name.s, c.config $ conflict.info])
if c.importModuleMap[sym.id] == c.importModuleMap[conflict.id]:
#only hints if the conflict is the actual module not just a shared name
localError(c.config, info, hintDuplicateModuleImport,
"duplicate import of '$1'; previous import here: $2" %
[sym.name.s, c.config $ conflict.info])
else:
wrongRedefinition(c, info, sym.name.s, conflict.info, errGenerated)
@@ -365,11 +438,12 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) =
if fn.kind notin OverloadableSyms:
internalError(c.config, fn.info, "addOverloadableSymAt")
return
let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(c, fn.info, fn.name.s, check.info)
else:
scope.addSym(fn)
if fn.name.id != ord(wUnderscore):
let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(c, fn.info, fn.name.s, check.info)
else:
scope.addSym(fn)
proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
## adds an overloadable symbol on the scope and the interface if appropriate
@@ -406,13 +480,6 @@ proc mergeShadowScope*(c: PContext) =
else:
c.addInterfaceDecl(sym)
when false:
# `nimfix` used to call `altSpelling` and prettybase.replaceDeprecated(n.info, ident, alt)
proc altSpelling(c: PContext, x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(c.cache, toLowerAscii(x.s[0]) & x.s.substr(1))
of 'a'..'z': result = getIdent(c.cache, toLowerAscii(x.s[0]) & x.s.substr(1))
else: result = x
import std/editdistance, heapqueue
@@ -422,7 +489,7 @@ type SpellCandidate = object
msg: string
sym: PSym
template toOrderTup(a: SpellCandidate): auto =
template toOrderTup(a: SpellCandidate): (int, int, string) =
# `dist` is first, to favor nearby matches
# `depth` is next, to favor nearby enclosing scopes among ties
# `sym.name.s` is last, to make the list ordered and deterministic among ties
@@ -435,7 +502,7 @@ proc mustFixSpelling(c: PContext): bool {.inline.} =
result = c.config.spellSuggestMax != 0 and c.compilesContextId == 0
# don't slowdown inside compiles()
proc fixSpelling(c: PContext, n: PNode, ident: PIdent, result: var string) =
proc fixSpelling(c: PContext, ident: PIdent, result: var string) =
## when we cannot find the identifier, suggest nearby spellings
var list = initHeapQueue[SpellCandidate]()
let name0 = ident.s.nimIdentNormalize
@@ -445,29 +512,29 @@ proc fixSpelling(c: PContext, n: PNode, ident: PIdent, result: var string) =
let dist = editDistance(name0, sym.name.s.nimIdentNormalize)
var msg: string
msg.add "\n ($1, $2): '$3'" % [$dist, $depth, sym.name.s]
addDeclaredLoc(msg, c.config, sym) # `msg` needed for deterministic ordering.
list.push SpellCandidate(dist: dist, depth: depth, msg: msg, sym: sym)
if list.len == 0: return
let e0 = list[0]
var count = 0
var
count = 0
last: PIdent = nil
while true:
# pending https://github.com/timotheecour/Nim/issues/373 use more efficient `itemsSorted`.
if list.len == 0: break
let e = list.pop()
if c.config.spellSuggestMax == spellSuggestSecretSauce:
const
smallThres = 2
maxCountForSmall = 4
# avoids ton of operator matches when mis-matching short symbols such as `i`
# other heuristics could be devised, such as only suggesting operators if `name0`
# is an operator (likewise with non-operators).
if e.dist > e0.dist or (name0.len <= smallThres and count >= maxCountForSmall): break
minLengthForSuggestion = 4
maxCount = 3 # avoids ton of matches; three counts for equal distances
if e.dist > e0.dist or count >= maxCount or name0.len < minLengthForSuggestion: break
elif count >= c.config.spellSuggestMax: break
if count == 0:
result.add "\ncandidates (edit distance, scope distance); see '--spellSuggest': "
result.add e.msg
count.inc
if e.sym.name != last:
result.add e.msg
count.inc
last = e.sym.name
proc errorUseQualifier(c: PContext; info: TLineInfo; s: PSym; amb: var bool): PSym =
var err = "ambiguous identifier: '" & s.name.s & "'"
@@ -493,7 +560,7 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
var amb: bool
discard errorUseQualifier(c, info, s, amb)
proc errorUseQualifier(c: PContext; info: TLineInfo; candidates: seq[PSym]; prefix = "use one of") =
proc errorUseQualifier*(c: PContext; info: TLineInfo; candidates: seq[PSym]; prefix = "use one of") =
var err = "ambiguous identifier: '" & candidates[0].name.s & "'"
var i = 0
for candidate in candidates:
@@ -512,36 +579,44 @@ proc errorUseQualifier*(c: PContext; info:TLineInfo; choices: PNode) =
errorUseQualifier(c, info, candidates, prefix)
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extra = "") =
var err = "undeclared identifier: '" & name & "'" & extra
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency:\n"
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = ""
var err: string
if name == "_":
err = "the special identifier '_' is ignored in declarations and cannot be used"
else:
err = "undeclared identifier: '" & name & "'"
if "`gensym" in name:
err.add "; if declared in a template, this identifier may be inconsistently marked inject or gensym"
if extra.len != 0:
err.add extra
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency:\n"
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = ""
localError(c.config, info, errGenerated, err)
proc errorUndeclaredIdentifierHint*(c: PContext; n: PNode, ident: PIdent): PSym =
proc errorUndeclaredIdentifierHint*(c: PContext; ident: PIdent; info: TLineInfo): PSym =
var extra = ""
if c.mustFixSpelling: fixSpelling(c, n, ident, extra)
errorUndeclaredIdentifier(c, n.info, ident.s, extra)
result = errorSym(c, n)
if c.mustFixSpelling: fixSpelling(c, ident, extra)
errorUndeclaredIdentifier(c, info, ident.s, extra)
result = errorSym(c, ident, info)
proc lookUp*(c: PContext, n: PNode): PSym =
# Looks up a symbol. Generates an error in case of nil.
var amb = false
case n.kind
of nkIdent:
result = searchInScopes(c, n.ident, amb).skipAlias(n, c.config)
if result == nil: result = errorUndeclaredIdentifierHint(c, n, n.ident)
result = searchInScopes(c, n.ident, amb)
if result == nil: result = errorUndeclaredIdentifierHint(c, n.ident, n.info)
of nkSym:
result = n.sym
of nkAccQuoted:
var ident = considerQuotedIdent(c, n)
result = searchInScopes(c, ident, amb).skipAlias(n, c.config)
if result == nil: result = errorUndeclaredIdentifierHint(c, n, ident)
result = searchInScopes(c, ident, amb)
if result == nil: result = errorUndeclaredIdentifierHint(c, ident, n.info)
else:
internalError(c.config, n.info, "lookUp")
return
return nil
if amb:
#contains(c.ambiguousSymbols, result.id):
result = errorUseQualifier(c, n.info, result, amb)
@@ -552,36 +627,45 @@ type
TLookupFlag* = enum
checkAmbiguity, checkUndeclared, checkModule, checkPureEnumFields
const allExceptModule = {low(TSymKind)..high(TSymKind)} - {skModule, skPackage}
proc lookUpCandidates*(c: PContext, ident: PIdent, filter: set[TSymKind]): seq[PSym] =
result = searchInScopesFilterBy(c, ident, filter)
if result.len == 0:
result.add allPureEnumFields(c, ident)
proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
const allExceptModule = {low(TSymKind)..high(TSymKind)} - {skModule, skPackage}
case n.kind
of nkIdent, nkAccQuoted:
var amb = false
var ident = considerQuotedIdent(c, n)
if checkModule in flags:
result = searchInScopes(c, ident, amb).skipAlias(n, c.config)
result = searchInScopes(c, ident, amb)
if result == nil:
let candidates = allPureEnumFields(c, ident)
if candidates.len > 0:
result = candidates[0]
amb = candidates.len > 1
if amb and checkAmbiguity in flags:
errorUseQualifier(c, n.info, candidates)
else:
let candidates = searchInScopesFilterBy(c, ident, allExceptModule) #.skipAlias(n, c.config)
let candidates = lookUpCandidates(c, ident, allExceptModule)
if candidates.len > 0:
result = candidates[0]
amb = candidates.len > 1
if amb and checkAmbiguity in flags:
errorUseQualifier(c, n.info, candidates)
if result == nil:
let candidates = allPureEnumFields(c, ident)
if candidates.len > 0:
result = candidates[0]
amb = candidates.len > 1
if amb and checkAmbiguity in flags:
errorUseQualifier(c, n.info, candidates)
else:
result = nil
if result == nil and checkUndeclared in flags:
result = errorUndeclaredIdentifierHint(c, n, ident)
result = errorUndeclaredIdentifierHint(c, ident, n.info)
elif checkAmbiguity in flags and result != nil and amb:
result = errorUseQualifier(c, n.info, result, amb)
c.isAmbiguous = amb
of nkSym:
result = n.sym
of nkOpenSym:
result = qualifiedLookUp(c, n[0], flags)
of nkDotExpr:
result = nil
var m = qualifiedLookUp(c, n[0], (flags * {checkUndeclared}) + {checkModule})
@@ -593,13 +677,20 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
ident = considerQuotedIdent(c, n[1])
if ident != nil:
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n, c.config)
result = strTableGet(c.topLevelScope.symbols, ident)
else:
result = someSym(c.graph, m, ident).skipAlias(n, c.config)
if c.importModuleLookup.getOrDefault(m.name.id).len > 1:
var amb: bool
result = errorUseQualifier(c, n.info, m, amb)
else:
result = someSym(c.graph, m, ident)
if result == nil and checkUndeclared in flags:
result = errorUndeclaredIdentifierHint(c, n[1], ident)
result = errorUndeclaredIdentifierHint(c, ident, n[1].info)
elif n[1].kind == nkSym:
result = n[1].sym
if result.owner != nil and result.owner != m and checkUndeclared in flags:
# dotExpr in templates can end up here
result = errorUndeclaredIdentifierHint(c, result.name, n[1].info)
elif checkUndeclared in flags and
n[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n[1].info, "identifier expected, but got: " &
@@ -611,6 +702,10 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
if result != nil and result.kind == skStub: loadStub(result)
proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
if n.kind == nkOpenSym:
# maybe the logic in semexprs should be mirrored here instead
# for now it only seems this is called for `pickSym` in `getTypeIdent`
return initOverloadIter(o, c, n[0])
o.importIdx = -1
o.marked = initIntSet()
case n.kind
@@ -619,7 +714,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
var scope = c.currentScope
o.mode = oimNoQualifier
while true:
result = initIdentIter(o.it, scope.symbols, ident).skipAlias(n, c.config)
result = initIdentIter(o.it, scope.symbols, ident)
if result != nil:
o.currentScope = scope
break
@@ -627,7 +722,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
scope = scope.parent
if scope == nil:
for i in 0..c.imports.high:
result = initIdentIter(o.mit, o.marked, c.imports[i], ident, c.graph).skipAlias(n, c.config)
result = initIdentIter(o.mit, o.marked, c.imports[i], ident, c.graph)
if result != nil:
o.currentScope = nil
o.importIdx = i
@@ -650,10 +745,10 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
if o.m == c.module:
# a module may access its private members:
result = initIdentIter(o.it, c.topLevelScope.symbols,
ident).skipAlias(n, c.config)
ident)
o.mode = oimSelfModule
else:
result = initModuleIter(o.mit, c.graph, o.m, ident).skipAlias(n, c.config)
result = initModuleIter(o.mit, c.graph, o.m, ident)
else:
noidentError(c.config, n[1], n)
result = errorSym(c, n[1])
@@ -686,7 +781,7 @@ proc nextOverloadIterImports(o: var TOverloadIter, c: PContext, n: PNode): PSym
var idx = o.importIdx+1
o.importIdx = c.imports.len # assume the other imported modules lack this symbol too
while idx < c.imports.len:
result = initIdentIter(o.mit, o.marked, c.imports[idx], o.it.name, c.graph).skipAlias(n, c.config)
result = initIdentIter(o.mit, o.marked, c.imports[idx], o.it.name, c.graph)
if result != nil:
# oh, we were wrong, some other module had the symbol, so remember that:
o.importIdx = idx
@@ -696,7 +791,7 @@ proc nextOverloadIterImports(o: var TOverloadIter, c: PContext, n: PNode): PSym
proc symChoiceExtension(o: var TOverloadIter; c: PContext; n: PNode): PSym =
assert o.currentScope == nil
while o.importIdx < c.imports.len:
result = initIdentIter(o.mit, o.marked, c.imports[o.importIdx], o.it.name, c.graph).skipAlias(n, c.config)
result = initIdentIter(o.mit, o.marked, c.imports[o.importIdx], o.it.name, c.graph)
#while result != nil and result.id in o.marked:
# result = nextIdentIter(o.it, o.marked, c.imports[o.importIdx])
if result != nil:
@@ -711,29 +806,29 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimNoQualifier:
if o.currentScope != nil:
assert o.importIdx < 0
result = nextIdentIter(o.it, o.currentScope.symbols).skipAlias(n, c.config)
result = nextIdentIter(o.it, o.currentScope.symbols)
while result == nil:
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
result = initIdentIter(o.it, o.currentScope.symbols, o.it.name).skipAlias(n, c.config)
result = initIdentIter(o.it, o.currentScope.symbols, o.it.name)
# BUGFIX: o.it.name <-> n.ident
else:
o.importIdx = 0
if c.imports.len > 0:
result = initIdentIter(o.mit, o.marked, c.imports[o.importIdx], o.it.name, c.graph).skipAlias(n, c.config)
result = initIdentIter(o.mit, o.marked, c.imports[o.importIdx], o.it.name, c.graph)
if result == nil:
result = nextOverloadIterImports(o, c, n)
break
elif o.importIdx < c.imports.len:
result = nextIdentIter(o.mit, o.marked, c.imports[o.importIdx], c.graph).skipAlias(n, c.config)
result = nextIdentIter(o.mit, o.marked, c.imports[o.importIdx], c.graph)
if result == nil:
result = nextOverloadIterImports(o, c, n)
else:
result = nil
of oimSelfModule:
result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n, c.config)
result = nextIdentIter(o.it, c.topLevelScope.symbols)
of oimOtherModule:
result = nextModuleIter(o.mit, c.graph).skipAlias(n, c.config)
result = nextModuleIter(o.mit, c.graph)
of oimSymChoice:
if o.symChoiceIndex < n.len:
result = n[o.symChoiceIndex].sym
@@ -744,12 +839,12 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoiceLocalLookup
o.currentScope = c.currentScope
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked).skipAlias(n, c.config)
n[0].sym.name, o.marked)
while result == nil:
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked).skipAlias(n, c.config)
n[0].sym.name, o.marked)
else:
o.importIdx = 0
result = symChoiceExtension(o, c, n)
@@ -758,12 +853,12 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
incl o.marked, result.id
of oimSymChoiceLocalLookup:
if o.currentScope != nil:
result = nextIdentExcluding(o.it, o.currentScope.symbols, o.marked).skipAlias(n, c.config)
result = nextIdentExcluding(o.it, o.currentScope.symbols, o.marked)
while result == nil:
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked).skipAlias(n, c.config)
n[0].sym.name, o.marked)
else:
o.importIdx = 0
result = symChoiceExtension(o, c, n)
@@ -772,10 +867,10 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
incl o.marked, result.id
elif o.importIdx < c.imports.len:
result = nextIdentIter(o.mit, o.marked, c.imports[o.importIdx], c.graph).skipAlias(n, c.config)
result = nextIdentIter(o.mit, o.marked, c.imports[o.importIdx], c.graph)
#assert result.id notin o.marked
#while result != nil and result.id in o.marked:
# result = nextIdentIter(o.it, c.imports[o.importIdx]).skipAlias(n, c.config)
# result = nextIdentIter(o.it, c.imports[o.importIdx])
if result == nil:
inc o.importIdx
result = symChoiceExtension(o, c, n)

View File

@@ -79,7 +79,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: P
if avoidTemp:
tempAsNode = value
else:
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen,
owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric)
@@ -100,7 +100,7 @@ proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): P
## freely, multiple times. This is frequently required and such a builtin would also be
## handy to have in macros.nim. The value that can be reused is 'result.lastSon'!
result = newNodeIT(nkStmtListExpr, value.info, value.typ)
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), idgen,
owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric)
@@ -122,29 +122,10 @@ proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
proc newTryFinally*(body, final: PNode): PNode =
result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final))
proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
let value = n.lastSon
result = newNodeI(nkStmtList, n.info)
var temp = newSym(skTemp, getIdent(g.cache, "_"), nextSymId(idgen), owner, value.info, owner.options)
var v = newNodeI(nkLetSection, value.info)
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, value.info)
vpart[2] = value
v.add vpart
result.add(v)
let lhs = n[0]
for i in 0..<lhs.len:
result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i))
proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
result = newNodeI(nkStmtList, n.info)
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextSymId(idgen), owner, n.info, owner.options)
var temp = newSym(skVar, getIdent(g.cache, genPrefix), idgen, owner, n.info, owner.options)
temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric)
incl(temp.flags, sfGenSym)
@@ -171,8 +152,7 @@ proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
result.n = newNodeI(nkRecList, info)
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
nextSymId(idgen),
owner, info, owner.options)
idgen, owner, info, owner.options)
incl s.flags, sfAnon
s.typ = result
result.sym = s
@@ -234,10 +214,13 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym
# because of 'gensym' support, we have to mangle the name with its ID.
# This is hacky but the clean solution is much more complex than it looks.
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len),
nextSymId(idgen), s.owner, s.info, s.options)
idgen, s.owner, s.info, s.options)
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
field.typ = t
if s.kind in {skLet, skVar, skField, skForVar}:
#field.bitsize = s.bitsize
field.alignment = s.alignment
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = obj.n.len
@@ -250,7 +233,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.itemId)
if result == nil:
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextSymId(idgen),
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), idgen,
s.owner, s.info, s.options)
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
@@ -347,7 +330,8 @@ proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
proc callCodegenProc*(g: ModuleGraph; name: string;
info: TLineInfo = unknownLineInfo;
arg1, arg2, arg3, optionalArgs: PNode = nil): PNode =
arg1: PNode = nil, arg2: PNode = nil,
arg3: PNode = nil, optionalArgs: PNode = nil): PNode =
result = newNodeI(nkCall, info)
let sym = magicsys.getCompilerProc(g, name)
if sym == nil:

View File

@@ -26,9 +26,8 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym =
result = systemModuleSym(g, getIdent(g.cache, name))
if result == nil:
localError(g.config, info, "system module needs: " & name)
result = newSym(skError, getIdent(g.cache, name), nextSymId(g.idgen), g.systemModule, g.systemModule.info, {})
result = newSym(skError, getIdent(g.cache, name), g.idgen, g.systemModule, g.systemModule.info, {})
result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule)
if result.kind == skAlias: result = result.owner
proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym =
let id = getIdent(g.cache, name)
@@ -39,7 +38,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy
result = r
if result != nil: return result
localError(g.config, info, "system module needs: " & name)
result = newSym(skError, id, nextSymId(g.idgen), g.systemModule, g.systemModule.info, {})
result = newSym(skError, id, g.idgen, g.systemModule, g.systemModule.info, {})
result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule)
proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType =

View File

@@ -13,12 +13,12 @@ when not defined(nimcore):
{.error: "nimcore MUST be defined for Nim's core tooling".}
import
std/[strutils, os, times, tables, sha1, with, json],
std/[strutils, os, times, tables, with, json],
llstream, ast, lexer, syntaxes, options, msgs,
condsyms,
sem, idents, passes, extccomp,
idents, extccomp,
cgen, nversion,
platform, nimconf, passaux, depends, vm,
platform, nimconf, depends,
modules,
modulegraphs, lineinfos, pathutils, vmprofiler
@@ -29,12 +29,12 @@ when defined(nimPreviewSlimSystem):
import ic / [cbackend, integrity, navigator]
from ic / ic import rodViewer
when not defined(leanCompiler):
import jsgen, docgen, docgen2
import ../dist/checksums/src/checksums/sha1
proc semanticPasses(g: ModuleGraph) =
registerPass g, verbosePass
registerPass g, semPass
import pipelines
when not defined(leanCompiler):
import docgen
proc writeDepsFile(g: ModuleGraph) =
let fname = g.config.nimcacheDir / RelativeFile(g.config.projectName & ".deps")
@@ -68,12 +68,18 @@ proc writeCMakeDepsFile(conf: ConfigRef) =
fl.close()
proc commandGenDepend(graph: ModuleGraph) =
semanticPasses(graph)
registerPass(graph, gendependPass)
compileProject(graph)
setPipeLinePass(graph, GenDependPass)
compilePipelineProject(graph)
let project = graph.config.projectFull
writeDepsFile(graph)
generateDot(graph, project)
# dot in graphivz tool kit is required
let graphvizDotPath = findExe("dot")
if graphvizDotPath.len == 0:
quit("gendepend: Graphviz's tool dot is required," &
"see https://graphviz.org/download for downloading")
execExternalProgram(graph.config, "dot -Tpng -o" &
changeFileExt(project, "png").string &
' ' & changeFileExt(project, "dot").string)
@@ -87,8 +93,8 @@ proc commandCheck(graph: ModuleGraph) =
defineSymbol(conf.symbols, "nimconfig")
elif conf.backend == backendJs:
setTarget(conf.target, osJS, cpuJS)
semanticPasses(graph) # use an empty backend for semantic checking only
compileProject(graph)
setPipeLinePass(graph, SemPass)
compilePipelineProject(graph)
if conf.symbolFiles != disabledSf:
case conf.ideCmd
@@ -102,22 +108,20 @@ when not defined(leanCompiler):
proc commandDoc2(graph: ModuleGraph; ext: string) =
handleDocOutputOptions graph.config
graph.config.setErrorMaxHighMaybe
semanticPasses(graph)
case ext:
of TexExt: registerPass(graph, docgen2TexPass)
of JsonExt: registerPass(graph, docgen2JsonPass)
of HtmlExt: registerPass(graph, docgen2Pass)
of TexExt:
setPipeLinePass(graph, Docgen2TexPass)
of JsonExt:
setPipeLinePass(graph, Docgen2JsonPass)
of HtmlExt:
setPipeLinePass(graph, Docgen2Pass)
else: doAssert false, $ext
compileProject(graph)
finishDoc2Pass(graph.config.projectName)
compilePipelineProject(graph)
proc commandCompileToC(graph: ModuleGraph) =
let conf = graph.config
extccomp.initVars(conf)
semanticPasses(graph)
if conf.symbolFiles == disabledSf:
registerPass(graph, cgenPass)
if {optRun, optForceFullMake} * conf.globalOptions == {optRun} or isDefined(conf, "nimBetterRun"):
if not changeDetectedViaJsonBuildInstructions(conf, conf.jsonBuildInstructionsFile):
# nothing changed
@@ -127,7 +131,11 @@ proc commandCompileToC(graph: ModuleGraph) =
if not extccomp.ccHasSaneOverflow(conf):
conf.symbols.defineSymbol("nimEmulateOverflowChecks")
compileProject(graph)
if conf.symbolFiles == disabledSf:
setPipeLinePass(graph, CgenPass)
else:
setPipeLinePass(graph, SemPass)
compilePipelineProject(graph)
if graph.config.errorCounter > 0:
return # issue #9933
if conf.symbolFiles == disabledSf:
@@ -143,7 +151,7 @@ proc commandCompileToC(graph: ModuleGraph) =
extccomp.callCCompiler(conf)
# for now we do not support writing out a .json file with the build instructions when HCR is on
if not conf.hcrOn:
extccomp.writeJsonBuildInstructions(conf)
extccomp.writeJsonBuildInstructions(conf, graph.cachedFiles)
if optGenScript in graph.config.globalOptions:
writeDepsFile(graph)
if optGenCDeps in graph.config.globalOptions:
@@ -160,33 +168,27 @@ proc commandCompileToJS(graph: ModuleGraph) =
conf.exc = excCpp
setTarget(conf.target, osJS, cpuJS)
defineSymbol(conf.symbols, "ecmascript") # For backward compatibility
semanticPasses(graph)
registerPass(graph, JSgenPass)
compileProject(graph)
setPipeLinePass(graph, JSgenPass)
compilePipelineProject(graph)
if optGenScript in conf.globalOptions:
writeDepsFile(graph)
proc interactivePasses(graph: ModuleGraph) =
proc commandInteractive(graph: ModuleGraph) =
graph.config.setErrorMaxHighMaybe
initDefines(graph.config.symbols)
defineSymbol(graph.config.symbols, "nimscript")
# note: seems redundant with -d:nimHasLibFFI
when hasFFI: defineSymbol(graph.config.symbols, "nimffi")
registerPass(graph, verbosePass)
registerPass(graph, semPass)
registerPass(graph, evalPass)
proc commandInteractive(graph: ModuleGraph) =
graph.config.setErrorMaxHighMaybe
interactivePasses(graph)
compileSystemModule(graph)
setPipeLinePass(graph, InterpreterPass)
compilePipelineSystemModule(graph)
if graph.config.commandArgs.len > 0:
discard graph.compileModule(fileInfoIdx(graph.config, graph.config.projectFull), {})
discard graph.compilePipelineModule(fileInfoIdx(graph.config, graph.config.projectFull), {})
else:
var m = graph.makeStdinModule()
incl(m.flags, sfMainModule)
var idgen = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0)
let s = llStreamOpenStdIn(onPrompt = proc() = flushDot(graph.config))
processModule(graph, m, idgen, s)
discard processPipelineModule(graph, m, idgen, s)
proc commandScan(cache: IdentCache, config: ConfigRef) =
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
@@ -241,8 +243,6 @@ proc mainCommand*(graph: ModuleGraph) =
let conf = graph.config
let cache = graph.cache
# In "nim serve" scenario, each command must reset the registered passes
clearPasses(graph)
conf.lastCmdTime = epochTime()
conf.searchPaths.add(conf.libpath)
@@ -417,7 +417,7 @@ proc mainCommand*(graph: ModuleGraph) =
of cmdJsonscript:
setOutFile(graph.config)
commandJsonScript(graph)
of cmdUnknown, cmdNone, cmdIdeTools, cmdNimfix:
of cmdUnknown, cmdNone, cmdIdeTools:
rawMessage(conf, errGenerated, "invalid command: " & conf.command)
if conf.errorCounter == 0 and conf.cmd notin {cmdTcc, cmdDump, cmdNop}:

View File

@@ -1,297 +0,0 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2010 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# `std/md5` without VM and JavaScript support, to circumvent a bug with
# openarrays on Nim < 1.4.
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
type
MD5State = array[0..3, uint32]
MD5Block = array[0..15, uint32]
MD5CBits = array[0..7, uint8]
MD5Digest* = array[0..15, uint8]
## MD5 checksum of a string, obtained with the `toMD5 proc <#toMD5,string>`_.
MD5Buffer = array[0..63, uint8]
MD5Context* {.final.} = object
state: MD5State
count: array[0..1, uint32]
buffer: MD5Buffer
const
padding: array[0..63, uint8] = [
0x80'u8, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
]
proc F(x, y, z: uint32): uint32 {.inline.} =
result = (x and y) or ((not x) and z)
proc G(x, y, z: uint32): uint32 {.inline.} =
result = (x and z) or (y and (not z))
proc H(x, y, z: uint32): uint32 {.inline.} =
result = x xor y xor z
proc I(x, y, z: uint32): uint32 {.inline.} =
result = y xor (x or (not z))
proc rot(x: var uint32, n: uint8) {.inline.} =
x = (x shl n) or (x shr (32'u32 - n))
proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a + F(b, c, d) + x + ac
rot(a, s)
a = a + b
proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a + G(b, c, d) + x + ac
rot(a, s)
a = a + b
proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a + H(b, c, d) + x + ac
rot(a, s)
a = a + b
proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
a = a + I(b, c, d) + x + ac
rot(a, s)
a = a + b
proc encode(dest: var MD5Block, src: openArray[uint8]) =
var j = 0
for i in 0..high(dest):
dest[i] = uint32(ord(src[j])) or
uint32(ord(src[j+1])) shl 8 or
uint32(ord(src[j+2])) shl 16 or
uint32(ord(src[j+3])) shl 24
inc(j, 4)
proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
var i = 0
for j in 0..high(src):
dest[i] = uint8(src[j] and 0xff'u32)
dest[i+1] = uint8(src[j] shr 8 and 0xff'u32)
dest[i+2] = uint8(src[j] shr 16 and 0xff'u32)
dest[i+3] = uint8(src[j] shr 24 and 0xff'u32)
inc(i, 4)
template slice(s: string | cstring, a, b): openArray[uint8] =
s.toOpenArrayByte(a, b)
template slice(s: openArray[uint8], a, b): openArray[uint8] =
s.toOpenArray(a, b)
proc transform(buffer: openArray[uint8], state: var MD5State) =
var
myBlock: MD5Block
encode(myBlock, buffer)
var a = state[0]
var b = state[1]
var c = state[2]
var d = state[3]
FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
state[0] = state[0] + a
state[1] = state[1] + b
state[2] = state[2] + c
state[3] = state[3] + d
proc md5Init*(c: var MD5Context) {.raises: [], tags: [], gcsafe.}
proc md5Update*(c: var MD5Context, input: openArray[uint8]) {.raises: [],
tags: [], gcsafe.}
proc md5Final*(c: var MD5Context, digest: var MD5Digest) {.raises: [], tags: [], gcsafe.}
proc md5Update*(c: var MD5Context, input: cstring, len: int) {.raises: [],
tags: [], gcsafe.} =
## Updates the `MD5Context` with the `input` data of length `len`.
##
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
## function explicitly.
md5Update(c, input.slice(0, len - 1))
proc toMD5*(s: string): MD5Digest =
## Computes the `MD5Digest` value for a string `s`.
##
## **See also:**
## * `getMD5 proc <#getMD5,string>`_ which returns a string representation
## of the `MD5Digest`
## * `$ proc <#$,MD5Digest>`_ for converting MD5Digest to string
runnableExamples:
assert $toMD5("abc") == "900150983cd24fb0d6963f7d28e17f72"
var c: MD5Context
md5Init(c)
md5Update(c, s.slice(0, s.len - 1))
md5Final(c, result)
proc `$`*(d: MD5Digest): string =
## Converts a `MD5Digest` value into its string representation.
const digits = "0123456789abcdef"
result = ""
for i in 0..15:
add(result, digits[(d[i].int shr 4) and 0xF])
add(result, digits[d[i].int and 0xF])
proc getMD5*(s: string): string =
## Computes an MD5 value of `s` and returns its string representation.
##
## **See also:**
## * `toMD5 proc <#toMD5,string>`_ which returns the `MD5Digest` of a string
runnableExamples:
assert getMD5("abc") == "900150983cd24fb0d6963f7d28e17f72"
var
c: MD5Context
d: MD5Digest
md5Init(c)
md5Update(c, s.slice(0, s.len - 1))
md5Final(c, d)
result = $d
proc `==`*(D1, D2: MD5Digest): bool =
## Checks if two `MD5Digest` values are identical.
for i in 0..15:
if D1[i] != D2[i]: return false
return true
proc clearBuffer(c: var MD5Context) {.inline.} =
zeroMem(addr(c.buffer), sizeof(MD5Buffer))
proc md5Init*(c: var MD5Context) =
## Initializes an `MD5Context`.
##
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
## function explicitly.
c.state[0] = 0x67452301'u32
c.state[1] = 0xEFCDAB89'u32
c.state[2] = 0x98BADCFE'u32
c.state[3] = 0x10325476'u32
c.count[0] = 0'u32
c.count[1] = 0'u32
clearBuffer(c)
proc writeBuffer(c: var MD5Context, index: int,
input: openArray[uint8], inputIndex, len: int) {.inline.} =
copyMem(addr(c.buffer[index]), unsafeAddr(input[inputIndex]), len)
proc md5Update*(c: var MD5Context, input: openArray[uint8]) =
## Updates the `MD5Context` with the `input` data.
##
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
## function explicitly.
var Index = int((c.count[0] shr 3) and 0x3F)
c.count[0] = c.count[0] + (uint32(input.len) shl 3)
if c.count[0] < (uint32(input.len) shl 3): c.count[1] = c.count[1] + 1'u32
c.count[1] = c.count[1] + (uint32(input.len) shr 29)
var PartLen = 64 - Index
if input.len >= PartLen:
writeBuffer(c, Index, input, 0, PartLen)
transform(c.buffer, c.state)
var i = PartLen
while i + 63 < input.len:
transform(input.slice(i, i + 63), c.state)
inc(i, 64)
if i < input.len:
writeBuffer(c, 0, input, i, input.len - i)
elif input.len > 0:
writeBuffer(c, Index, input, 0, input.len)
proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
## Finishes the `MD5Context` and stores the result in `digest`.
##
## If you use the `toMD5 proc <#toMD5,string>`_, there's no need to call this
## function explicitly.
var
Bits: MD5CBits
PadLen: int
decode(Bits, c.count)
var Index = int((c.count[0] shr 3) and 0x3F)
if Index < 56: PadLen = 56 - Index
else: PadLen = 120 - Index
md5Update(c, padding.slice(0, PadLen - 1))
md5Update(c, Bits)
decode(digest, c.state)
clearBuffer(c)
when defined(nimHasStyleChecks):
{.pop.} #{.push styleChecks: off.}

View File

@@ -11,7 +11,8 @@
## represents a complete Nim project. Single modules can either be kept in RAM
## or stored in a rod-file.
import intsets, tables, hashes, md5_old
import std/[intsets, tables, hashes, strtabs]
import ../dist/checksums/src/checksums/md5
import ast, astalgo, options, lineinfos,idents, btrees, ropes, msgs, pathutils, packages
import ic / [packed_ast, ic]
@@ -56,6 +57,19 @@ type
SymInfoPair* = object
sym*: PSym
info*: TLineInfo
isDecl*: bool
PipelinePass* = enum
NonePass
SemPass
JSgenPass
CgenPass
EvalPass
InterpreterPass
GenDependPass
Docgen2TexPass
Docgen2JsonPass
Docgen2Pass
ModuleGraph* {.acyclic.} = ref object
ifaces*: seq[Iface] ## indexed by int32 fileIdx
@@ -66,6 +80,7 @@ type
procInstCache*: Table[ItemId, seq[LazyInstantiation]] # A symbol's ItemId.
attachedOps*: array[TTypeAttachedOp, Table[ItemId, LazySym]] # Type ID, destructors, etc.
methodsPerType*: Table[ItemId, seq[(int, LazySym)]] # Type ID, attached methods
memberProcsPerType*: Table[ItemId, seq[PSym]] # Type ID, attached member procs (only c++, virtual and ctor so far)
enumToStringProcs*: Table[ItemId, LazySym]
emittedTypeInfo*: Table[string, FileIndex]
@@ -104,6 +119,7 @@ type
cacheCounters*: Table[string, BiggestInt] # IC: implemented
cacheTables*: Table[string, BTree[string, PNode]] # IC: implemented
passes*: seq[TPass]
pipelinePass*: PipelinePass
onDefinition*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
@@ -113,6 +129,8 @@ type
idgen*: IdGenerator
operators*: Operators
cachedFiles*: StringTableRef
TPassContext* = object of RootObj # the pass's context
idgen*: IdGenerator
PPassContext* = ref TPassContext
@@ -398,7 +416,7 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
result = g.doStopCompile != nil and g.doStopCompile()
proc createMagic*(g: ModuleGraph; idgen: IdGenerator; name: string, m: TMagic): PSym =
result = newSym(skProc, getIdent(g.cache, name), nextSymId(idgen), nil, unknownLineInfo, {})
result = newSym(skProc, getIdent(g.cache, name), idgen, nil, unknownLineInfo, {})
result.magic = m
result.flags = {sfNeverRaises}
@@ -464,6 +482,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
result.symBodyHashes = initTable[int, SigHash]()
result.operators = initOperators(result)
result.emittedTypeInfo = initTable[string, FileIndex]()
result.cachedFiles = newStringTable()
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph()

View File

@@ -36,11 +36,18 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
localError(n.info, "only '/' supported with $package notation")
result = ""
else:
let modname = getModuleName(conf, n[2])
# hacky way to implement 'x / y /../ z':
result = getModuleName(conf, n1)
result.add renderTree(n0, {renderNoComments}).replace(" ")
result.add modname
if n0.kind in nkIdentKinds:
let ident = n0.getPIdent
if ident != nil and ident.s[0] == '/':
let modname = getModuleName(conf, n[2])
# hacky way to implement 'x / y /../ z':
result = getModuleName(conf, n1)
result.add renderTree(n0, {renderNoComments}).replace(" ")
result.add modname
else:
result = ""
else:
result = ""
of nkPrefix:
when false:
if n[0].kind == nkIdent and n[0].ident.s == "$":

View File

@@ -11,13 +11,11 @@
import
ast, magicsys, msgs, options,
idents, lexer, passes, syntaxes, llstream, modulegraphs,
lineinfos, pathutils, tables, packages
idents, lexer, syntaxes, modulegraphs,
lineinfos, pathutils
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions]
import ic / replayer
import ../dist/checksums/src/checksums/sha1
import std/strtabs
proc resetSystemArtifacts*(g: ModuleGraph) =
magicsys.resetSysTypes(g)
@@ -25,12 +23,12 @@ proc resetSystemArtifacts*(g: ModuleGraph) =
template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
getIdent(graph.cache, splitFile(filename).name)
proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
proc partialInitModule*(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
let packSym = getPackage(graph, fileIdx)
result.owner = packSym
result.position = int fileIdx
proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
proc newModule*(graph: ModuleGraph; fileIdx: FileIndex): PSym =
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
# We cannot call ``newSym`` here, because we have to circumvent the ID
# mechanism, which we do in order to assign each module a persistent ID.
@@ -38,103 +36,23 @@ proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
name: getModuleIdent(graph, filename),
info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s):
rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
rawMessage(graph.config, errGenerated, "invalid module name: '" & result.name.s &
"'; a module name must be a valid Nim identifier.")
partialInitModule(result, graph, fileIdx, filename)
graph.registerModule(result)
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym =
var flags = flags
if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
result = graph.getModule(fileIdx)
template processModuleAux(moduleStatus) =
onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule)
var s: PLLStream
if sfMainModule in flags:
if graph.config.projectIsStdin: s = stdin.llStreamOpen
elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput)
discard processModule(graph, result, idGeneratorFromModule(result), s)
if result == nil:
var cachedModules: seq[FileIndex]
result = moduleFromRodFile(graph, fileIdx, cachedModules)
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
if result == nil:
result = newModule(graph, fileIdx)
result.flags.incl flags
registerModule(graph, result)
processModuleAux("import")
else:
if sfSystemModule in flags:
graph.systemModule = result
partialInitModule(result, graph, fileIdx, filename)
for m in cachedModules:
registerModuleById(graph, m)
replayStateChanges(graph.packed[m.int].module, graph)
replayGenericCacheInformation(graph, m.int)
elif graph.isDirty(result):
result.flags.excl sfDirty
# reset module fields:
initStrTables(graph, result)
result.ast = nil
processModuleAux("import(dirty)")
graph.markClientsDirty(fileIdx)
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# this is called by the semantic checking phase
assert graph.config != nil
result = compileModule(graph, fileIdx, {}, s)
graph.addDep(s, fileIdx)
# keep track of import relationships
if graph.config.hcrOn:
graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
#if sfSystemModule in result.flags:
# localError(result.info, errAttemptToRedefine, result.name.s)
# restore the notes for outer module:
graph.config.notes =
if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode =
result = syntaxes.parseFile(fileIdx, graph.cache, graph.config)
graph.addDep(s, fileIdx)
graph.addIncludeDep(s.position.FileIndex, fileIdx)
proc connectCallbacks*(graph: ModuleGraph) =
graph.includeFileCallback = includeModule
graph.importModuleCallback = importModule
proc compileSystemModule*(graph: ModuleGraph) =
if graph.systemModule == nil:
connectCallbacks(graph)
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
graph.config.libpath / RelativeFile"system.nim")
discard graph.compileModule(graph.config.m.systemFileIdx, {sfSystemModule})
let path = toFullPath(graph.config, fileIdx)
graph.cachedFiles[path] = $secureHashFile(path)
proc wantMainModule*(conf: ConfigRef) =
if conf.projectFull.isEmpty:
fatal(conf, gCmdLineInfo, "command expects a filename")
conf.projectMainIdx = fileInfoIdx(conf, addFileExt(conf.projectFull, NimExt))
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
configComplete(graph)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
conf.projectMainIdx2 = projectFile
let packSym = getPackage(graph, projectFile)
graph.config.mainPackageId = packSym.getPackageId
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
else:
graph.compileSystemModule()
discard graph.compileModule(projectFile, {sfMainModule})
proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym =
result = graph.newModule(fileInfoIdx(graph.config, filename))
registerModule(graph, result)

View File

@@ -128,6 +128,13 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile): FileIndex =
var dummy: bool
result = fileInfoIdx(conf, filename, dummy)
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile; isKnownFile: var bool): FileIndex =
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), isKnownFile)
proc fileInfoIdx*(conf: ConfigRef; filename: RelativeFile): FileIndex =
var dummy: bool
fileInfoIdx(conf, AbsoluteFile expandFilename(filename.string), dummy)
proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo =
result.fileIndex = fileInfoIdx
if line < int high(uint16):
@@ -219,7 +226,7 @@ proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile)
proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) =
assert fileIdx.int32 >= 0
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
conf.m.fileInfos[fileIdx.int32].hash = hash
else:
shallowCopy(conf.m.fileInfos[fileIdx.int32].hash, hash)
@@ -227,7 +234,7 @@ proc setHash*(conf: ConfigRef; fileIdx: FileIndex; hash: string) =
proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
assert fileIdx.int32 >= 0
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
result = conf.m.fileInfos[fileIdx.int32].hash
else:
shallowCopy(result, conf.m.fileInfos[fileIdx.int32].hash)
@@ -422,7 +429,8 @@ To create a stacktrace, rerun compilation with './koch temp $1 <file>', see $2 f
proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string, ignoreMsg: bool) =
if msg in fatalMsgs:
if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg)
if conf.cmd != cmdIdeTools or msg != errFatal:
quit(conf, msg)
if msg >= errMin and msg <= errMax or
(msg in warnMin..hintMax and msg in conf.warningAsErrors and not ignoreMsg):
inc(conf.errorCounter)
@@ -430,7 +438,11 @@ proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string,
if conf.errorCounter >= conf.errorMax:
# only really quit when we're not in the new 'nim check --def' mode:
if conf.ideCmd == ideNone:
quit(conf, msg)
when defined(nimsuggest):
#we need to inform the user that something went wrong when initializing NimSuggest
raiseRecoverableError(s)
else:
quit(conf, msg)
elif eh == doAbort and conf.cmd != cmdIdeTools:
quit(conf, msg)
elif eh == doRaise:
@@ -504,7 +516,8 @@ proc formatMsg*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string): s
conf.toFileLineCol(info) & " " & title & getMessageStr(msg, arg)
proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
eh: TErrorHandling, info2: InstantiationInfo, isRaw = false) {.gcsafe, noinline.} =
eh: TErrorHandling, info2: InstantiationInfo, isRaw = false,
ignoreError = false) {.gcsafe, noinline.} =
var
title: string
color: ForegroundColor
@@ -534,19 +547,21 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
ignoreMsg = not conf.hasWarn(msg)
if not ignoreMsg and msg in conf.warningAsErrors:
title = ErrorTitle
color = ErrorColor
else:
title = WarningTitle
color = WarningColor
if not ignoreMsg: writeContext(conf, info)
color = WarningColor
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
ignoreMsg = not conf.hasHint(msg)
if not ignoreMsg and msg in conf.warningAsErrors:
title = ErrorTitle
color = ErrorColor
else:
title = HintTitle
color = HintColor
color = HintColor
inc(conf.hintCounter)
let s = if isRaw: arg else: getMessageStr(msg, arg)
@@ -568,7 +583,8 @@ proc liMessage*(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
" compiler msg initiated here", KindColor,
KindFormat % $hintMsgOrigin,
resetStyle, conf.unitSep)
handleError(conf, msg, eh, s, ignoreMsg)
if not ignoreError:
handleError(conf, msg, eh, s, ignoreMsg)
if msg in fatalMsgs:
# most likely would have died here but just in case, we restore state
conf.m.errorOutputs = errorOutputsOld
@@ -633,13 +649,16 @@ template lintReport*(conf: ConfigRef; info: TLineInfo, beau, got: string, extraM
let msg = if optStyleError in conf.globalOptions: errGenerated else: hintName
liMessage(conf, info, msg, m, doNothing, instLoc())
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
if i.fileIndex.int32 < 0:
proc quotedFilename*(conf: ConfigRef; fi: FileIndex): Rope =
if fi.int32 < 0:
result = makeCString "???"
elif optExcessiveStackTrace in conf.globalOptions:
result = conf.m.fileInfos[i.fileIndex.int32].quotedFullName
result = conf.m.fileInfos[fi.int32].quotedFullName
else:
result = conf.m.fileInfos[i.fileIndex.int32].quotedName
result = conf.m.fileInfos[fi.int32].quotedName
proc quotedFilename*(conf: ConfigRef; i: TLineInfo): Rope =
quotedFilename(conf, i.fileIndex)
template listMsg(title, r) =
msgWriteln(conf, title, {msgNoUnitSep})

View File

@@ -909,7 +909,7 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode =
else: ""
var cache = newIdentCache()
var op = newSym(skVar, cache.getIdent(name), nextSymId ctx.idgen, nil, r.info)
var op = newSym(skVar, cache.getIdent(name), ctx.idgen, nil, r.info)
op.magic = magic
result = nkInfix.newTree(
@@ -920,7 +920,7 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode =
proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
var cache = newIdentCache()
var op = newSym(skVar, cache.getIdent("not"), nextSymId ctx.idgen, nil, node.info)
var op = newSym(skVar, cache.getIdent("not"), ctx.idgen, nil, node.info)
op.magic = mNot
result = nkPrefix.newTree(

View File

@@ -7,14 +7,15 @@ define:nimcore
define:nimPreviewFloatRoundtrip
define:nimPreviewSlimSystem
define:nimPreviewCstringConversion
define:nimPreviewProcConversion
define:nimPreviewRangeDefault
define:nimPreviewNonVarDestructor
threads:off
#import:"$projectpath/testability"
@if windows:
cincludes: "$lib/wrappers/libffi/common"
tlsEmulation:off
@end
define:useStdoutAsStdmsg
@@ -31,6 +32,7 @@ define:useStdoutAsStdmsg
warning[ObservableStores]:off
@end
@if nimHasWarningAsError:
warningAsError[GcUnsafe2]:on
@end
@@ -38,3 +40,7 @@ define:useStdoutAsStdmsg
@if nimHasWarnUnnamedBreak:
warningAserror[UnnamedBreak]:on
@end
@if nimHasWarnBareExcept:
warningAserror[BareExcept]:on
@end

View File

@@ -12,10 +12,7 @@ import std/[os, strutils, parseopt]
when defined(nimPreviewSlimSystem):
import std/assertions
when defined(windows) and not defined(nimKochBootstrap):
# remove workaround pending bootstrap >= 1.5.1
# refs https://github.com/nim-lang/Nim/issues/18334#issuecomment-867114536
# alternative would be to prepend `currentSourcePath.parentDir.quoteShell`
when defined(windows):
when defined(gcc):
when defined(x86):
{.link: "../icons/nim.res".}
@@ -41,6 +38,15 @@ when defined(profiler) or defined(memProfiler):
{.hint: "Profiling support is turned on!".}
import nimprof
proc nimbleLockExists(config: ConfigRef): bool =
const nimbleLock = "nimble.lock"
let pd = if not config.projectPath.isEmpty: config.projectPath else: AbsoluteDir(getCurrentDir())
if optSkipParentConfigFiles notin config.globalOptions:
for dir in parentDirs(pd.string, fromRoot=true, inclusive=false):
if fileExists(dir / nimbleLock):
return true
return fileExists(pd.string / nimbleLock)
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
@@ -74,6 +80,11 @@ proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
config.arguments.len > 0 and config.cmd notin {cmdTcc, cmdNimscript, cmdCrun}:
rawMessage(config, errGenerated, errArgsNeedRunOption)
if config.nimbleLockExists:
# disable nimble path if nimble.lock is present.
# see https://github.com/nim-lang/nimble/issues/1004
disableNimblePath(config)
proc getNimRunExe(conf: ConfigRef): string =
# xxx consider defining `conf.getConfigVar("nimrun.exe")` to allow users to
# customize the binary to run the command with, e.g. for custom `nodejs` or `wine`.

View File

@@ -10,11 +10,13 @@
## Implements some helper procs for Nimble (Nim's package manager) support.
import parseutils, strutils, os, options, msgs, sequtils, lineinfos, pathutils,
std/sha1, tables
tables
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions]
import ../dist/checksums/src/checksums/sha1
proc addPath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
if not conf.searchPaths.contains(path):
conf.searchPaths.insert(path, 0)

View File

@@ -9,10 +9,16 @@
## exposes the Nim VM to clients.
import
ast, astalgo, modules, passes, condsyms,
options, sem, llstream, lineinfos, vm,
ast, modules, condsyms,
options, llstream, lineinfos, vm,
vmdef, modulegraphs, idents, os, pathutils,
passaux, scriptconfig, std/compilesettings
scriptconfig, std/[compilesettings, tables]
import pipelines
when defined(nimPreviewSlimSystem):
import std/[assertions, syncio]
type
Interpreter* = ref object ## Use Nim as an interpreter with this object
@@ -72,11 +78,14 @@ proc evalScript*(i: Interpreter; scriptStream: PLLStream = nil) =
assert i != nil
assert i.mainModule != nil, "no main module selected"
initStrTables(i.graph, i.mainModule)
i.graph.cacheSeqs.clear()
i.graph.cacheCounters.clear()
i.graph.cacheTables.clear()
i.mainModule.ast = nil
let s = if scriptStream != nil: scriptStream
else: llStreamOpen(findFile(i.graph.config, i.scriptName), fmRead)
processModule(i.graph, i.mainModule, i.idgen, s)
discard processPipelineModule(i.graph, i.mainModule, i.idgen, s)
proc findNimStdLib*(): string =
## Tries to find a path to a valid "system.nim" file.
@@ -109,12 +118,10 @@ proc createInterpreter*(scriptName: string;
var conf = newConfigRef()
var cache = newIdentCache()
var graph = newModuleGraph(cache, conf)
connectCallbacks(graph)
connectPipelineCallbacks(graph)
initDefines(conf.symbols)
for define in defines:
defineSymbol(conf.symbols, define[0], define[1])
registerPass(graph, semPass)
registerPass(graph, evalPass)
for p in searchPaths:
conf.searchPaths.add(AbsoluteDir p)
@@ -129,7 +136,8 @@ proc createInterpreter*(scriptName: string;
if registerOps:
vm.registerAdditionalOps() # Required to register parts of stdlib modules
graph.vm = vm
graph.compileSystemModule()
setPipeLinePass(graph, EvalPass)
graph.compilePipelineSystemModule()
result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName, idgen: idgen)
proc destroyInterpreter*(i: Interpreter) =
@@ -159,13 +167,11 @@ proc runRepl*(r: TLLRepl;
defineSymbol(conf.symbols, "nimscript")
if supportNimscript: defineSymbol(conf.symbols, "nimconfig")
when hasFFI: defineSymbol(graph.config.symbols, "nimffi")
registerPass(graph, verbosePass)
registerPass(graph, semPass)
registerPass(graph, evalPass)
var m = graph.makeStdinModule()
incl(m.flags, sfMainModule)
var idgen = idGeneratorFromModule(m)
if supportNimscript: graph.vm = setupVM(m, cache, "stdin", graph, idgen)
graph.compileSystemModule()
processModule(graph, m, idgen, llStreamOpenStdIn(r))
setPipeLinePass(graph, InterpreterPass)
graph.compilePipelineSystemModule()
discard processPipelineModule(graph, m, idgen, llStreamOpenStdIn(r))

View File

@@ -1,111 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
import strutils, os, parseopt
import compiler/[options, commands, modules, sem,
passes, passaux, linter,
msgs, nimconf,
extccomp, condsyms,
modulegraphs, idents]
const Usage = """
Nimfix - Tool to patch Nim code
Usage:
nimfix [options] projectfile.nim
Options:
--overwriteFiles:on|off overwrite the original nim files.
DEFAULT is ON!
--wholeProject overwrite every processed file.
--checkExtern:on|off style check also extern names
--styleCheck:on|off|auto performs style checking for identifiers
and suggests an alternative spelling;
'auto' corrects the spelling.
--bestEffort try to fix the code even when there
are errors.
In addition, all command line options of Nim are supported.
"""
proc mainCommand =
registerPass verbosePass
registerPass semPass
conf.setCmd cmdNimfix
searchPaths.add options.libpath
if gProjectFull.len != 0:
# current path is always looked first for modules
searchPaths.insert(gProjectPath, 0)
compileProject(newModuleGraph(), newIdentCache())
pretty.overwriteFiles()
proc processCmdLine*(pass: TCmdLinePass, cmd: string, config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
gOnlyMainfile = true
while true:
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongoption, cmdShortOption:
case p.key.normalize
of "overwritefiles":
case p.val.normalize
of "on": gOverWrite = true
of "off": gOverWrite = false
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "checkextern":
case p.val.normalize
of "on": gCheckExtern = true
of "off": gCheckExtern = false
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "stylecheck":
case p.val.normalize
of "off": gStyleCheck = StyleCheck.None
of "on": gStyleCheck = StyleCheck.Warn
of "auto": gStyleCheck = StyleCheck.Auto
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "wholeproject": gOnlyMainfile = false
of "besteffort": msgs.gErrorMax = high(int) # don't stop after first error
else:
processSwitch(pass, p, config)
of cmdArgument:
options.gProjectName = unixToNativePath(p.key)
# if processArgument(pass, p, argsCount): break
proc handleCmdLine(config: ConfigRef) =
if paramCount() == 0:
stdout.writeLine(Usage)
else:
processCmdLine(passCmd1, "", config)
if gProjectName != "":
try:
gProjectFull = canonicalizePath(gProjectName)
except OSError:
gProjectFull = gProjectName
var p = splitFile(gProjectFull)
gProjectPath = p.dir
gProjectName = p.name
else:
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig, config) # load all config files
# now process command line arguments again, because some options in the
# command line can overwrite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "", config)
mainCommand()
when compileOption("gc", "refc"):
GC_disableMarkAndSweep()
condsyms.initDefines()
defineSymbol "nimfix"
handleCmdline newConfigRef()

View File

@@ -1,17 +0,0 @@
# Special configuration file for the Nim project
# gc:markAndSweep
hint[XDeclaredButNotUsed]:off
path:"$projectPath/.."
path:"$lib/packages/docutils"
path:"$nim"
define:useStdoutAsStdmsg
symbol:nimfix
define:nimfix
cs:partial
#define:useNodeIds
define:booting
define:noDocgen

View File

@@ -1,45 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2015 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import strutils except Letters
import ".." / [ast, msgs, lineinfos, idents, options, linter]
proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PIdent) =
let line = sourceLine(conf, info)
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if line[first] == '`': inc first
let last = first+identLen(line, first)-1
if cmpIgnoreStyle(line[first..last], oldSym.s) == 0:
var x = line.substr(0, first-1) & newSym.s & line.substr(last+1)
when defined(gcArc) or defined(gcOrc):
conf.m.fileInfos[info.fileIndex.int32].lines[info.line.int-1] = move x
else:
system.shallowCopy(conf.m.fileInfos[info.fileIndex.int32].lines[info.line.int-1], x)
conf.m.fileInfos[info.fileIndex.int32].dirty = true
#if newSym.s == "File": writeStackTrace()
proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PSym) =
replaceDeprecated(conf, info, oldSym.name, newSym.name)
proc replaceComment*(conf: ConfigRef; info: TLineInfo) =
let line = sourceLine(conf, info)
var first = info.col.int
if line[first] != '#': inc first
var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape
when defined(gcArc) or defined(gcOrc):
conf.m.fileInfos[info.fileIndex.int32].lines[info.line.int-1] = move x
else:
system.shallowCopy(conf.m.fileInfos[info.fileIndex.int32].lines[info.line.int-1], x)
conf.m.fileInfos[info.fileIndex.int32].dirty = true

View File

@@ -7,4 +7,4 @@ proc findNodeJs*(): string {.inline.} =
result = findExe("node")
if result.len == 0:
echo "Please install NodeJS first, see https://nodejs.org/en/download"
raise newException(IOError, "NodeJS not found in PATH: " & result)
raise newException(IOError, "NodeJS not found in PATH")

View File

@@ -12,6 +12,8 @@
const
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
DefaultSetElements* = 1 shl 8
## assumed set element count when using int literals
VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes!

View File

@@ -16,6 +16,8 @@ import
from trees import exprStructuralEquivalent
import std/strutils
const
nfMarkForDeletion = nfNone # faster than a lookup table
@@ -110,16 +112,17 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
var reverse = false
if n[0].kind == nkSym:
let s = n[0].sym
if s.magic == mWasMoved:
let name = s.name.s.normalize
if name == "=wasmoved":
b.wasMovedLocs.add n
special = true
elif s.name.s == "=destroy":
elif name == "=destroy":
if c.inFinally > 0 and (b.hasReturn or b.hasBreak):
discard "cannot optimize away the destructor"
else:
c.wasMovedDestroyPair b, n
special = true
elif s.name.s == "=sink":
elif name == "=sink":
reverse = true
if not special:

View File

@@ -24,7 +24,7 @@ const
useEffectSystem* = true
useWriteTracking* = false
hasFFI* = defined(nimHasLibFFI)
copyrightYear* = "2022"
copyrightYear* = "2023"
nimEnableCovariance* = defined(nimEnableCovariance)
@@ -49,6 +49,7 @@ type # please make sure we have under 32 options
optSinkInference # 'sink T' inference
optCursorInference
optImportHidden
optQuirky
TOptions* = set[TOption]
TGlobalOption* = enum
@@ -78,6 +79,8 @@ type # please make sure we have under 32 options
optThreadAnalysis, # thread analysis pass
optTlsEmulation, # thread var emulation turned on
optGenIndex # generate index file for documentation;
optGenIndexOnly # generate only index file for documentation
optNoImportdoc # disable loading external documentation files
optEmbedOrigSrc # embed the original source in the generated code
# also: generate header file
optIdeDebug # idetools: debug mode
@@ -100,12 +103,11 @@ type # please make sure we have under 32 options
optBenchmarkVM # Enables cpuTime() in the VM
optProduceAsm # produce assembler code
optPanics # turn panics (sysFatal) into a process termination
optNimV1Emulation # emulate Nim v1.0
optNimV12Emulation # emulate Nim v1.2
optNimV16Emulation # emulate Nim v1.6
optSourcemap
optProfileVM # enable VM profiler
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
optShowNonExportedFields # for documentation: show fields that are not exported
optJsBigInt64 # use bigints for 64-bit integers in JS
TGlobalOptions* = set[TGlobalOption]
@@ -165,7 +167,6 @@ type
cmdInteractive # start interactive session
cmdNop
cmdJsonscript # compile a .json build file
cmdNimfix
# old unused: cmdInterpret, cmdDef: def feature (find definition for IDEs)
const
@@ -183,6 +184,7 @@ type
gcRegions = "regions"
gcArc = "arc"
gcOrc = "orc"
gcAtomicArc = "atomicArc"
gcMarkAndSweep = "markAndSweep"
gcHooks = "hooks"
gcRefc = "refc"
@@ -193,10 +195,9 @@ type
IdeCmd* = enum
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideChkFile, ideMod,
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject, ideGlobalSymbols,
ideRecompile, ideChanged, ideType, ideDeclaration
ideRecompile, ideChanged, ideType, ideDeclaration, ideExpand, ideInlayHints
Feature* = enum ## experimental features; DO NOT RENAME THESE!
implicitDeref, # deadcode; remains here for backwards compatibility
dotOperators,
callOperator,
parallel,
@@ -219,7 +220,10 @@ type
unicodeOperators, # deadcode
flexibleOptionalParams,
strictDefs,
strictCaseObjects
strictCaseObjects,
openSym, # remove nfDisabledOpenSym when this is default
# alternative to above:
genericsOpenSym
LegacyFeature* = enum
allowSemcheckedAstModification,
@@ -232,6 +236,7 @@ type
## are not anymore.
laxEffects
## Lax effects system prior to Nim 2.0.
verboseTypeMismatch
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest
@@ -276,8 +281,26 @@ type
scope*, localUsages*, globalUsages*: int # more usages is better
tokenLen*: int
version*: int
endLine*: uint16
endCol*: int
inlayHintInfo*: SuggestInlayHint
Suggestions* = seq[Suggest]
SuggestInlayHintKind* = enum
sihkType = "Type",
sihkParameter = "Parameter"
SuggestInlayHint* = ref object
kind*: SuggestInlayHintKind
line*: int # Starts at 1
column*: int # Starts at 0
label*: string
paddingLeft*: bool
paddingRight*: bool
allowInsert*: bool
tooltip*: string
ProfileInfo* = object
time*: float
count*: int
@@ -329,6 +352,7 @@ type
cppDefines*: HashSet[string] # (*)
headerFile*: string
nimbasePattern*: string # pattern to find nimbase.h
features*: set[Feature]
legacyFeatures*: set[LegacyFeature]
arguments*: string ## the arguments to be passed to the program that
@@ -406,6 +430,14 @@ type
nimMainPrefix*: string
vmProfileData*: ProfileData
expandProgress*: bool
expandLevels*: int
expandNodeResult*: string
expandPosition*: TLineInfo
clientProcessId*: int
proc parseNimVersion*(a: string): NimVer =
# could be moved somewhere reusable
if a.len > 0:
@@ -457,7 +489,7 @@ when false:
fn(globalOptions)
fn(selectedGC)
const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
const oldExperimentalFeatures* = {dotOperators, callOperator, parallel}
const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
@@ -468,7 +500,8 @@ const
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
optTrMacros, optStyleCheck, optCursorInference}
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace}
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
optJsBigInt64}
proc getSrcTimestamp(): DateTime =
try:
@@ -610,7 +643,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr}
osAndroid, osNintendoSwitch, osFreeRTOS, osCrossos, osZephyr, osNuttX}
of "linux":
result = conf.target.targetOS in {osLinux, osAndroid}
of "bsd":
@@ -632,6 +665,8 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
result = conf.target.targetOS == osFreeRTOS
of "zephyr":
result = conf.target.targetOS == osZephyr
of "nuttx":
result = conf.target.targetOS == osNuttX
of "littleendian": result = CPU[conf.target.targetCPU].endian == littleEndian
of "bigendian": result = CPU[conf.target.targetCPU].endian == bigEndian
of "cpu8": result = CPU[conf.target.targetCPU].bit == 8
@@ -706,22 +741,24 @@ proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
## clone or using installed nim, so that these exist: `result/doc/advopt.txt`
## and `result/lib/system.nim`
if not conf.prefixDir.isEmpty: result = conf.prefixDir
else: result = AbsoluteDir splitPath(getAppDir()).head
else:
let binParent = AbsoluteDir splitPath(getAppDir()).head
when defined(posix):
if binParent == AbsoluteDir"/usr":
result = AbsoluteDir"/usr/lib/nim"
elif binParent == AbsoluteDir"/usr/local":
result = AbsoluteDir"/usr/local/lib/nim"
else:
result = binParent
else:
result = binParent
proc setDefaultLibpath*(conf: ConfigRef) =
# set default value (can be overwritten):
if conf.libpath.isEmpty:
# choose default libpath:
var prefix = getPrefixDir(conf)
when defined(posix):
if prefix == AbsoluteDir"/usr":
conf.libpath = AbsoluteDir"/usr/lib/nim"
elif prefix == AbsoluteDir"/usr/local":
conf.libpath = AbsoluteDir"/usr/local/lib/nim"
else:
conf.libpath = prefix / RelativeDir"lib"
else:
conf.libpath = prefix / RelativeDir"lib"
conf.libpath = prefix / RelativeDir"lib"
# Special rule to support other tools (nimble) which import the compiler
# modules and make use of them.
@@ -851,21 +888,14 @@ template patchModule(conf: ConfigRef) {.dirty.} =
let ov = conf.moduleOverrides[key]
if ov.len > 0: result = AbsoluteFile(ov)
when (NimMajor, NimMinor) < (1, 1) or not declared(isRelativeTo):
proc isRelativeTo(path, base: string): bool =
# pending #13212 use os.isRelativeTo
let path = path.normalizedPath
let base = base.normalizedPath
let ret = relativePath(path, base)
result = path.len > 0 and not ret.startsWith ".."
const stdlibDirs* = [
"pure", "core", "arch",
"pure/collections",
"pure/concurrency",
"pure/unidecode", "impure",
"wrappers", "wrappers/linenoise",
"windows", "posix", "js"]
"windows", "posix", "js",
"deprecated/pure"]
const
pkgPrefix = "pkg/"
@@ -902,6 +932,7 @@ proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile
proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFile =
# returns path to module
var m = addFileExt(modulename, NimExt)
var hasRelativeDot = false
if m.startsWith(pkgPrefix):
result = findFile(conf, m.substr(pkgPrefix.len), suppressStdlib = true)
else:
@@ -915,7 +946,11 @@ proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFi
else: # If prefixed with std/ why would we add the current module path!
let currentPath = currentModule.splitFile.dir
result = AbsoluteFile currentPath / m
if not fileExists(result):
if m.startsWith('.') and not fileExists(result):
result = AbsoluteFile ""
hasRelativeDot = true
if not fileExists(result) and not hasRelativeDot:
result = findFile(conf, m)
patchModule(conf)
@@ -993,6 +1028,12 @@ proc isDynlibOverride*(conf: ConfigRef; lib: string): bool =
result = optDynlibOverrideAll in conf.globalOptions or
conf.dllOverrides.hasKey(lib.canonDynlibName)
proc showNonExportedFields*(conf: ConfigRef) =
incl(conf.globalOptions, optShowNonExportedFields)
proc expandDone*(conf: ConfigRef): bool =
result = conf.ideCmd == ideExpand and conf.expandLevels == 0 and conf.expandProgress
proc parseIdeCmd*(s: string): IdeCmd =
case s:
of "sug": ideSug
@@ -1032,9 +1073,11 @@ proc `$`*(c: IdeCmd): string =
of ideProject: "project"
of ideGlobalSymbols: "globalSymbols"
of ideDeclaration: "declaration"
of ideExpand: "expand"
of ideRecompile: "recompile"
of ideChanged: "changed"
of ideType: "type"
of ideInlayHints: "inlayHints"
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.

View File

@@ -8,7 +8,7 @@
#
## Package related procs.
##
##
## See Also:
## * `packagehandling` for package path handling
## * `modulegraphs.getPackage`
@@ -22,7 +22,7 @@ when defined(nimPreviewSlimSystem):
proc getPackage*(conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): PSym =
## Return a new package symbol.
##
##
## See Also:
## * `modulegraphs.getPackage`
let
@@ -31,7 +31,7 @@ proc getPackage*(conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): PSym =
info = newLineInfo(fileIdx, 1, 1)
pkgName = getPackageName(conf, filename.string)
pkgIdent = getIdent(cache, pkgName)
newSym(skPackage, pkgIdent, ItemId(module: PackageModuleId, item: int32(fileIdx)), nil, info)
newSym(skPackage, pkgIdent, idGeneratorForPackage(int32(fileIdx)), nil, info)
func getPackageSymbol*(sym: PSym): PSym =
## Return the owning package symbol.
@@ -47,7 +47,7 @@ func getPackageId*(sym: PSym): int =
func belongsToProjectPackage*(conf: ConfigRef, sym: PSym): bool =
## Return whether the symbol belongs to the project's package.
##
##
## See Also:
## * `modulegraphs.belongsToStdlib`
conf.mainPackageId == sym.getPackageId

View File

@@ -280,8 +280,15 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
result = isAssignable(owner, n[0])
of nkCallKinds:
# builtin slice keeps lvalue-ness:
if getMagic(n) in {mArrGet, mSlice}:
let m = getMagic(n)
if m == mSlice:
# builtin slice keeps l-value-ness
# except for pointers because slice dereferences
if n[1].typ.kind == tyPtr:
result = arLValue
else:
result = isAssignable(owner, n[1])
elif m == mArrGet:
result = isAssignable(owner, n[1])
elif n.typ != nil:
case n.typ.kind

File diff suppressed because it is too large Load Diff

View File

@@ -14,13 +14,22 @@ import
options, ast, llstream, msgs,
idents,
syntaxes, modulegraphs, reorder,
lineinfos, pathutils, packages
lineinfos,
pipelineutils,
modules, pathutils, packages,
sem, semdata
import ic/replayer
export skipCodegen, resolveMod, prepareConfigNotes
when defined(nimsuggest):
import std/sha1
import ../dist/checksums/src/checksums/sha1
when defined(nimPreviewSlimSystem):
import std/syncio
import std/[syncio, assertions]
import std/tables
type
TPassData* = tuple[input: PNode, closeOutput: PNode]
@@ -38,12 +47,6 @@ proc makePass*(open: TPassOpen = nil,
result.process = process
result.isFrontend = isFrontend
proc skipCodegen*(config: ConfigRef; n: PNode): bool {.inline.} =
# can be used by codegen passes to determine whether they should do
# something with `n`. Currently, this ignores `n` and uses the global
# error count instead.
result = config.errorCounter > 0
const
maxPasses = 10
@@ -80,13 +83,6 @@ proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray)
if isNil(m): return false
result = true
proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
let fullPath = findModule(conf, module, relativeTo)
if fullPath.isEmpty:
result = InvalidFileIdx
else:
result = fileInfoIdx(conf, fullPath)
proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
a: var TPassContextArray; m: PSym) =
# XXX fixme this should actually be relative to the config file!
@@ -100,23 +96,6 @@ proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNod
importStmt.add str
if not processTopLevelStmt(graph, importStmt, a): break
const
imperativeCode = {low(TNodeKind)..high(TNodeKind)} - {nkTemplateDef, nkProcDef, nkMethodDef,
nkMacroDef, nkConverterDef, nkIteratorDef, nkFuncDef, nkPragma,
nkExportStmt, nkExportExceptStmt, nkFromStmt, nkImportStmt, nkImportExceptStmt}
proc prepareConfigNotes(graph: ModuleGraph; module: PSym) =
# don't be verbose unless the module belongs to the main package:
if graph.config.belongsToProjectPackage(module):
graph.config.notes = graph.config.mainPackageNotes
else:
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
graph.config.notes = graph.config.foreignPackageNotes
proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
result = true
#module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange")
proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
stream: PLLStream): bool {.discardable.} =
if graph.stopCompile(): return true
@@ -143,7 +122,7 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
while true:
openParser(p, fileIdx, s, graph.cache, graph.config)
if not belongsToStdlib(graph, module) or (belongsToStdlib(graph, module) and module.name.s == "distros"):
if (not belongsToStdlib(graph, module)) or module.name.s == "distros":
# XXX what about caching? no processing then? what if I change the
# modules to include between compilation runs? we'd need to track that
# in ROD files. I think we should enable this feature only
@@ -153,43 +132,22 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
checkFirstLineIndentation(p)
while true:
if graph.stopCompile(): break
block processCode:
if graph.stopCompile(): break processCode
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
if (sfSystemModule notin module.flags and
({sfNoForward, sfReorder} * module.flags != {} or
codeReordering in graph.config.features)):
# read everything, no streaming possible
var sl = newNodeI(nkStmtList, n.info)
if n.kind == nkEmpty: break processCode
# read everything, no streaming possible
var sl = newNodeI(nkStmtList, n.info)
sl.add n
while true:
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
sl.add n
while true:
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
sl.add n
if sfReorder in module.flags or codeReordering in graph.config.features:
sl = reorder(graph, sl, module)
discard processTopLevelStmt(graph, sl, a)
break
elif n.kind in imperativeCode:
# read everything until the next proc declaration etc.
var sl = newNodeI(nkStmtList, n.info)
sl.add n
var rest: PNode = nil
while true:
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty or n.kind notin imperativeCode:
rest = n
break
sl.add n
#echo "-----\n", sl
if not processTopLevelStmt(graph, sl, a): break
if rest != nil:
#echo "-----\n", rest
if not processTopLevelStmt(graph, rest, a): break
else:
#echo "----- single\n", n
if not processTopLevelStmt(graph, n, a): break
if sfReorder in module.flags or codeReordering in graph.config.features:
sl = reorder(graph, sl, module)
discard processTopLevelStmt(graph, sl, a)
closeParser(p)
if s.kind != llsStdIn: break
closePasses(graph, a)
@@ -199,3 +157,99 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
# They are responsible for closing the rod files. See `cbackend.nim`.
closeRodFile(graph, module)
result = true
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym =
var flags = flags
if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
result = graph.getModule(fileIdx)
template processModuleAux(moduleStatus) =
onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule)
var s: PLLStream
if sfMainModule in flags:
if graph.config.projectIsStdin: s = stdin.llStreamOpen
elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput)
discard processModule(graph, result, idGeneratorFromModule(result), s)
if result == nil:
var cachedModules: seq[FileIndex]
result = moduleFromRodFile(graph, fileIdx, cachedModules)
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
if result == nil:
result = newModule(graph, fileIdx)
result.flags.incl flags
registerModule(graph, result)
processModuleAux("import")
else:
if sfSystemModule in flags:
graph.systemModule = result
partialInitModule(result, graph, fileIdx, filename)
for m in cachedModules:
registerModuleById(graph, m)
replayStateChanges(graph.packed[m.int].module, graph)
replayGenericCacheInformation(graph, m.int)
elif graph.isDirty(result):
result.flags.excl sfDirty
# reset module fields:
initStrTables(graph, result)
result.ast = nil
processModuleAux("import(dirty)")
graph.markClientsDirty(fileIdx)
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# this is called by the semantic checking phase
assert graph.config != nil
result = compileModule(graph, fileIdx, {}, s)
graph.addDep(s, fileIdx)
# keep track of import relationships
if graph.config.hcrOn:
graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
#if sfSystemModule in result.flags:
# localError(result.info, errAttemptToRedefine, result.name.s)
# restore the notes for outer module:
graph.config.notes =
if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc connectCallbacks*(graph: ModuleGraph) =
graph.includeFileCallback = modules.includeModule
graph.importModuleCallback = importModule
proc compileSystemModule*(graph: ModuleGraph) =
if graph.systemModule == nil:
connectCallbacks(graph)
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
graph.config.libpath / RelativeFile"system.nim")
discard graph.compileModule(graph.config.m.systemFileIdx, {sfSystemModule})
proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
configComplete(graph)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
conf.projectMainIdx2 = projectFile
let packSym = getPackage(graph, projectFile)
graph.config.mainPackageId = packSym.getPackageId
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compileModule(projectFile, {sfMainModule, sfSystemModule})
else:
graph.compileSystemModule()
discard graph.compileModule(projectFile, {sfMainModule})
proc mySemOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
result = preparePContext(graph, module, idgen)
proc mySemClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
var c = PContext(context)
closePContext(graph, c, n)
proc mySemProcess(context: PPassContext, n: PNode): PNode =
result = semWithPContext(PContext(context), n)
const semPass* = makePass(mySemOpen, mySemProcess, mySemClose,
isFrontend = true)

View File

@@ -10,7 +10,7 @@
## Path handling utilities for Nim. Strictly typed code in order
## to avoid the never ending time sink in getting path handling right.
import os, pathnorm
import os, pathnorm, strutils
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions]
@@ -102,3 +102,52 @@ when true:
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
proc skipHomeDir(x: string): int =
when defined(windows):
if x.continuesWith("Users/", len("C:/")):
result = 3
else:
result = 0
else:
if x.startsWith("/home/") or x.startsWith("/Users/"):
result = 3
elif x.startsWith("/mnt/") and x.continuesWith("/Users/", len("/mnt/c")):
result = 5
else:
result = 0
proc relevantPart(s: string; afterSlashX: int): string =
result = newStringOfCap(s.len - 8)
var slashes = afterSlashX
for i in 0..<s.len:
if slashes == 0:
result.add s[i]
elif s[i] == '/':
dec slashes
template canonSlashes(x: string): string =
when defined(windows):
x.replace('\\', '/')
else:
x
proc customPathImpl(x: string): string =
# Idea: Encode a "protocol" via "//protocol/path" which is not ambiguous
# as path canonicalization would have removed the double slashes.
# /mnt/X/Users/Y
# X:\\Users\Y
# /home/Y
# -->
# //user/
if not isAbsolute(x):
result = customPathImpl(canonSlashes(getCurrentDir() / x))
else:
let slashes = skipHomeDir(x)
if slashes > 0:
result = "//user/" & relevantPart(x, slashes)
else:
result = x
proc customPath*(x: string): string =
customPathImpl canonSlashes x

299
compiler/pipelines.nim Normal file
View File

@@ -0,0 +1,299 @@
import sem, cgen, modulegraphs, ast, llstream, parser, msgs,
lineinfos, reorder, options, semdata, cgendata, modules, pathutils,
packages, syntaxes, depends, vm, pragmas, idents, lookups, wordrecg,
liftdestructors
import pipelineutils
import ../dist/checksums/src/checksums/sha1
when not defined(leanCompiler):
import jsgen, docgen2
import std/[syncio, objectdollar, assertions, tables, strutils, strtabs]
import renderer
import ic/replayer
proc setPipeLinePass*(graph: ModuleGraph; pass: PipelinePass) =
graph.pipelinePass = pass
proc processPipeline(graph: ModuleGraph; semNode: PNode; bModule: PPassContext): PNode =
case graph.pipelinePass
of CgenPass:
result = semNode
if bModule != nil:
genTopLevelStmt(BModule(bModule), result)
of JSgenPass:
when not defined(leanCompiler):
result = processJSCodeGen(bModule, semNode)
of GenDependPass:
result = addDotDependency(bModule, semNode)
of SemPass:
result = graph.emptyNode
of Docgen2Pass, Docgen2TexPass:
when not defined(leanCompiler):
result = processNode(bModule, semNode)
of Docgen2JsonPass:
when not defined(leanCompiler):
result = processNodeJson(bModule, semNode)
of EvalPass, InterpreterPass:
result = interpreterCode(bModule, semNode)
of NonePass:
doAssert false, "use setPipeLinePass to set a proper PipelinePass"
proc processImplicitImports(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
m: PSym, ctx: PContext, bModule: PPassContext, idgen: IdGenerator,
) =
# XXX fixme this should actually be relative to the config file!
let relativeTo = toFullPath(graph.config, m.info)
for module in items(implicits):
# implicit imports should not lead to a module importing itself
if m.position != resolveMod(graph.config, module, relativeTo).int32:
var importStmt = newNodeI(nodeKind, m.info)
var str = newStrNode(nkStrLit, module)
str.info = m.info
importStmt.add str
message(graph.config, importStmt.info, hintProcessingStmt, $idgen[])
let semNode = semWithPContext(ctx, importStmt)
if semNode == nil or processPipeline(graph, semNode, bModule) == nil:
break
proc prePass(c: PContext; n: PNode) =
for son in n:
if son.kind == nkPragma:
for s in son:
var key = if s.kind in nkPragmaCallKinds and s.len > 1: s[0] else: s
if key.kind in {nkBracketExpr, nkCast} or key.kind notin nkIdentKinds:
continue
let ident = whichKeyword(considerQuotedIdent(c, key))
case ident
of wReorder:
pragmaNoForward(c, s, flag = sfReorder)
of wExperimental:
if isTopLevel(c) and s.kind in nkPragmaCallKinds and s.len == 2:
let name = c.semConstExpr(c, s[1])
case name.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
let feature = parseEnum[Feature](name.strVal)
if feature == codeReordering:
c.features.incl feature
c.module.flags.incl sfReorder
except ValueError:
discard
else:
discard
else:
discard
proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
stream: PLLStream): bool =
if graph.stopCompile(): return true
var
p: Parser
s: PLLStream
fileIdx = module.fileIdx
prepareConfigNotes(graph, module)
let ctx = preparePContext(graph, module, idgen)
let bModule: PPassContext =
case graph.pipelinePass
of CgenPass:
setupCgen(graph, module, idgen)
of JSgenPass:
when not defined(leanCompiler):
setupJSgen(graph, module, idgen)
else:
nil
of EvalPass, InterpreterPass:
setupEvalGen(graph, module, idgen)
of GenDependPass:
setupDependPass(graph, module, idgen)
of Docgen2Pass:
when not defined(leanCompiler):
openHtml(graph, module, idgen)
else:
nil
of Docgen2TexPass:
when not defined(leanCompiler):
openTex(graph, module, idgen)
else:
nil
of Docgen2JsonPass:
when not defined(leanCompiler):
openJson(graph, module, idgen)
else:
nil
of SemPass:
nil
of NonePass:
doAssert false, "use setPipeLinePass to set a proper PipelinePass"
nil
if stream == nil:
let filename = toFullPathConsiderDirty(graph.config, fileIdx)
s = llStreamOpen(filename, fmRead)
if s == nil:
rawMessage(graph.config, errCannotOpenFile, filename.string)
return false
else:
s = stream
while true:
syntaxes.openParser(p, fileIdx, s, graph.cache, graph.config)
if not belongsToStdlib(graph, module) or (belongsToStdlib(graph, module) and module.name.s == "distros"):
# XXX what about caching? no processing then? what if I change the
# modules to include between compilation runs? we'd need to track that
# in ROD files. I think we should enable this feature only
# for the interactive mode.
if module.name.s != "nimscriptapi":
processImplicitImports graph, graph.config.implicitImports, nkImportStmt, module, ctx, bModule, idgen
processImplicitImports graph, graph.config.implicitIncludes, nkIncludeStmt, module, ctx, bModule, idgen
checkFirstLineIndentation(p)
block processCode:
if graph.stopCompile(): break processCode
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break processCode
# read everything, no streaming possible
var sl = newNodeI(nkStmtList, n.info)
sl.add n
while true:
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
sl.add n
prePass(ctx, sl)
if sfReorder in module.flags or codeReordering in graph.config.features:
sl = reorder(graph, sl, module)
if graph.pipelinePass != EvalPass:
message(graph.config, sl.info, hintProcessingStmt, $idgen[])
var semNode = semWithPContext(ctx, sl)
discard processPipeline(graph, semNode, bModule)
closeParser(p)
if s.kind != llsStdIn: break
let finalNode = closePContext(graph, ctx, nil)
case graph.pipelinePass
of CgenPass:
if bModule != nil:
let disps = finalCodegenActions(graph, BModule(bModule), finalNode)
if disps != nil:
let ctx = preparePContext(graph, module, idgen)
for disp in disps:
let retTyp = disp.sym.typ[0]
if retTyp != nil:
# todo properly semcheck the code of dispatcher?
createTypeBoundOps(graph, ctx, retTyp, disp.info, idgen)
genProcAux(BModule(bModule), disp.sym)
discard closePContext(graph, ctx, nil)
of JSgenPass:
when not defined(leanCompiler):
discard finalJSCodeGen(graph, bModule, finalNode)
of EvalPass, InterpreterPass:
discard interpreterCode(bModule, finalNode)
of SemPass, GenDependPass:
discard
of Docgen2Pass, Docgen2TexPass:
when not defined(leanCompiler):
discard closeDoc(graph, bModule, finalNode)
of Docgen2JsonPass:
when not defined(leanCompiler):
discard closeJson(graph, bModule, finalNode)
of NonePass:
doAssert false, "use setPipeLinePass to set a proper PipelinePass"
if graph.config.backend notin {backendC, backendCpp, backendObjc}:
# We only write rod files here if no C-like backend is active.
# The C-like backends have been patched to support the IC mechanism.
# They are responsible for closing the rod files. See `cbackend.nim`.
closeRodFile(graph, module)
result = true
proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags, fromModule: PSym = nil): PSym =
var flags = flags
if fileIdx == graph.config.projectMainIdx2: flags.incl sfMainModule
result = graph.getModule(fileIdx)
template processModuleAux(moduleStatus) =
onProcessing(graph, fileIdx, moduleStatus, fromModule = fromModule)
var s: PLLStream
if sfMainModule in flags:
if graph.config.projectIsStdin: s = stdin.llStreamOpen
elif graph.config.projectIsCmd: s = llStreamOpen(graph.config.cmdInput)
discard processPipelineModule(graph, result, idGeneratorFromModule(result), s)
if result == nil:
var cachedModules: seq[FileIndex]
result = moduleFromRodFile(graph, fileIdx, cachedModules)
let path = toFullPath(graph.config, fileIdx)
let filename = AbsoluteFile path
if fileExists(filename): # it could be a stdinfile
graph.cachedFiles[path] = $secureHashFile(path)
if result == nil:
result = newModule(graph, fileIdx)
result.flags.incl flags
registerModule(graph, result)
processModuleAux("import")
else:
if sfSystemModule in flags:
graph.systemModule = result
partialInitModule(result, graph, fileIdx, filename)
for m in cachedModules:
registerModuleById(graph, m)
replayStateChanges(graph.packed[m.int].module, graph)
replayGenericCacheInformation(graph, m.int)
elif graph.isDirty(result):
result.flags.excl sfDirty
# reset module fields:
initStrTables(graph, result)
result.ast = nil
processModuleAux("import(dirty)")
graph.markClientsDirty(fileIdx)
proc importPipelineModule(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym =
# this is called by the semantic checking phase
assert graph.config != nil
result = compilePipelineModule(graph, fileIdx, {}, s)
graph.addDep(s, fileIdx)
# keep track of import relationships
if graph.config.hcrOn:
graph.importDeps.mgetOrPut(FileIndex(s.position), @[]).add(fileIdx)
#if sfSystemModule in result.flags:
# localError(result.info, errAttemptToRedefine, result.name.s)
# restore the notes for outer module:
graph.config.notes =
if graph.config.belongsToProjectPackage(s) or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc connectPipelineCallbacks*(graph: ModuleGraph) =
graph.includeFileCallback = modules.includeModule
graph.importModuleCallback = importPipelineModule
proc compilePipelineSystemModule*(graph: ModuleGraph) =
if graph.systemModule == nil:
connectPipelineCallbacks(graph)
graph.config.m.systemFileIdx = fileInfoIdx(graph.config,
graph.config.libpath / RelativeFile"system.nim")
discard graph.compilePipelineModule(graph.config.m.systemFileIdx, {sfSystemModule})
proc compilePipelineProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
connectPipelineCallbacks(graph)
let conf = graph.config
wantMainModule(conf)
configComplete(graph)
let systemFileIdx = fileInfoIdx(conf, conf.libpath / RelativeFile"system.nim")
let projectFile = if projectFileIdx == InvalidFileIdx: conf.projectMainIdx else: projectFileIdx
conf.projectMainIdx2 = projectFile
let packSym = getPackage(graph, projectFile)
graph.config.mainPackageId = packSym.getPackageId
graph.importStack.add projectFile
if projectFile == systemFileIdx:
discard graph.compilePipelineModule(projectFile, {sfMainModule, sfSystemModule})
else:
graph.compilePipelineSystemModule()
discard graph.compilePipelineModule(projectFile, {sfMainModule})

View File

@@ -0,0 +1,26 @@
import ast, options, lineinfos, pathutils, msgs, modulegraphs, packages
proc skipCodegen*(config: ConfigRef; n: PNode): bool {.inline.} =
# can be used by codegen passes to determine whether they should do
# something with `n`. Currently, this ignores `n` and uses the global
# error count instead.
result = config.errorCounter > 0
proc resolveMod*(conf: ConfigRef; module, relativeTo: string): FileIndex =
let fullPath = findModule(conf, module, relativeTo)
if fullPath.isEmpty:
result = InvalidFileIdx
else:
result = fileInfoIdx(conf, fullPath)
proc prepareConfigNotes*(graph: ModuleGraph; module: PSym) =
# don't be verbose unless the module belongs to the main package:
if graph.config.belongsToProjectPackage(module):
graph.config.notes = graph.config.mainPackageNotes
else:
if graph.config.mainPackageNotes == {}: graph.config.mainPackageNotes = graph.config.notes
graph.config.notes = graph.config.foreignPackageNotes
proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
result = true
#module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange")

View File

@@ -26,7 +26,8 @@ type
osNone, osDos, osWindows, osOs2, osLinux, osMorphos, osSkyos, osSolaris,
osIrix, osNetbsd, osFreebsd, osOpenbsd, osDragonfly, osCrossos, osAix, osPalmos, osQnx,
osAmiga, osAtari, osNetware, osMacos, osMacosx, osIos, osHaiku, osAndroid, osVxWorks
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osZephyr, osAny
osGenode, osJS, osNimVM, osStandalone, osNintendoSwitch, osFreeRTOS, osZephyr,
osNuttX, osAny
type
TInfoOSProp* = enum
@@ -193,6 +194,10 @@ const
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospPosix}),
(name: "NuttX", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",
props: {ospPosix}),
(name: "Any", parDir: "..", dllFrmt: "lib$1.so", altDirSep: "/",
objExt: ".o", newLine: "\x0A", pathSep: ":", dirSep: "/",
scriptExt: ".sh", curDir: ".", exeExt: "", extSep: ".",

View File

@@ -31,7 +31,7 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode =
return
let body = liftIterToProc(c.graph, iter.sym, getBody(c.graph, iter.sym), t, c.idgen)
let prc = newSym(skProc, n[3].ident, nextSymId c.idgen, iter.sym.owner, iter.sym.info)
let prc = newSym(skProc, n[3].ident, c.idgen, iter.sym.owner, iter.sym.info)
prc.typ = copyType(iter.sym.typ, nextTypeId c.idgen, prc)
excl prc.typ.flags, tfCapturesEnv
prc.typ.n.add newSymNode(getEnvParam(iter.sym))

View File

@@ -26,7 +26,7 @@ proc semLocals*(c: PContext, n: PNode): PNode =
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
if it.owner == owner:
var field = newSym(skField, it.name, nextSymId c.idgen, owner, n.info)
var field = newSym(skField, it.name, c.idgen, owner, n.info)
field.typ = it.typ.skipTypes({tyVar})
field.position = counter
inc(counter)

View File

@@ -12,7 +12,7 @@
import
os, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
types, lookups, lineinfos, pathutils, linter
types, lookups, lineinfos, pathutils, linter, modulepaths
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -34,7 +34,7 @@ const
wAsmNoStackFrame, wDiscardable, wNoInit, wCodegenDecl,
wGensym, wInject, wRaises, wEffectsOf, wTags, wForbids, wLocks, wDelegator, wGcSafe,
wConstructor, wLiftLocals, wStackTrace, wLineTrace, wNoDestroy,
wRequires, wEnsures, wEnforceNoRaises, wSystemRaisesDefect}
wRequires, wEnsures, wEnforceNoRaises, wSystemRaisesDefect, wVirtual, wQuirky}
converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
@@ -71,7 +71,8 @@ const
wPure, wHeader, wCompilerProc, wCore, wFinal, wSize, wShallow,
wIncompleteStruct, wCompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wCppNonPod, wBorrow, wGcSafe, wPartial, wExplain, wPackage}
wCppNonPod, wBorrow, wGcSafe, wPartial, wExplain, wPackage, wCodegenDecl,
wSendable}
fieldPragmas* = declPragmas + {wGuard, wBitsize, wCursor,
wRequiresInit, wNoalias, wAlign} - {wExportNims, wNodecl} # why exclude these?
varPragmas* = declPragmas + {wVolatile, wRegister, wThreadVar,
@@ -81,8 +82,9 @@ const
wGuard, wGoto, wCursor, wNoalias, wAlign}
constPragmas* = declPragmas + {wHeader, wMagic,
wGensym, wInject,
wIntDefine, wStrDefine, wBoolDefine, wCompilerProc, wCore}
paramPragmas* = {wNoalias, wInject, wGensym}
wIntDefine, wStrDefine, wBoolDefine, wDefine,
wCompilerProc, wCore}
paramPragmas* = {wNoalias, wInject, wGensym, wByRef, wByCopy, wCodegenDecl}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNoSideEffect,
wThread, wRaises, wEffectsOf, wLocks, wTags, wForbids, wGcSafe,
@@ -115,7 +117,15 @@ const
proc invalidPragma*(c: PContext; n: PNode) =
localError(c.config, n.info, "invalid pragma: " & renderTree(n, {renderNoComments}))
proc illegalCustomPragma*(c: PContext, n: PNode, s: PSym) =
localError(c.config, n.info, "cannot attach a custom pragma to '" & s.name.s & "'")
var msg = "cannot attach a custom pragma to '" & s.name.s & "'"
if s != nil:
msg.add("; custom pragmas are not supported for ")
case s.kind
of skForVar: msg.add("`for` loop variables")
of skEnumField: msg.add("enum fields")
of skModule: msg.add("modules")
else: msg.add("symbol kind " & $s.kind)
localError(c.config, n.info, msg)
proc pragmaProposition(c: PContext, n: PNode) =
if n.kind notin nkPragmaCallKinds or n.len != 2:
@@ -130,7 +140,7 @@ proc pragmaEnsures(c: PContext, n: PNode) =
openScope(c)
let o = getCurrOwner(c)
if o.kind in routineKinds and o.typ != nil and o.typ.sons[0] != nil:
var s = newSym(skResult, getIdent(c.cache, "result"), nextSymId(c.idgen), o, n.info)
var s = newSym(skResult, getIdent(c.cache, "result"), c.idgen, o, n.info)
s.typ = o.typ.sons[0]
incl(s.flags, sfUsed)
addDecl(c, s)
@@ -164,9 +174,7 @@ proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) =
localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)")
when hasFFI:
s.cname = $s.loc.r
if c.config.cmd == cmdNimfix and '$' notin extname:
# note that '{.importc.}' is transformed into '{.importc: "$1".}'
s.loc.flags.incl(lfFullExternalName)
proc makeExternImport(c: PContext; s: PSym, extname: string, info: TLineInfo) =
setExternName(c, s, extname, info)
@@ -201,9 +209,9 @@ proc processImportObjC(c: PContext; s: PSym, extname: string, info: TLineInfo) =
let m = s.getModule()
incl(m.flags, sfCompileToObjc)
proc newEmptyStrNode(c: PContext; n: PNode): PNode {.noinline.} =
proc newEmptyStrNode(c: PContext; n: PNode, strVal: string = ""): PNode {.noinline.} =
result = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString))
result.strVal = ""
result.strVal = strVal
proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind notin nkPragmaCallKinds or n.len != 2:
@@ -235,8 +243,17 @@ proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
if n.kind in nkPragmaCallKinds: result = expectStrLit(c, n)
else: result = defaultStr
proc processVirtual(c: PContext, n: PNode, s: PSym) =
s.constraint = newEmptyStrNode(c, n, getOptionalStr(c, n, "$1"))
s.constraint.strVal = s.constraint.strVal % s.name.s
s.flags.incl {sfVirtual, sfInfixCall, sfExportc, sfMangleCpp}
s.typ.callConv = ccNoConvention
incl c.config.globalOptions, optMixedMode
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
sym.constraint = getStrLitNode(c, n)
sym.flags.incl sfCodegenDecl
proc processMagic(c: PContext, n: PNode, s: PSym) =
#if sfSystemModule notin c.module.flags:
@@ -269,7 +286,7 @@ proc onOff(c: PContext, n: PNode, op: TOptions, resOptions: var TOptions) =
if isTurnedOn(c, n): resOptions.incl op
else: resOptions.excl op
proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
proc pragmaNoForward*(c: PContext, n: PNode; flag=sfNoForward) =
if isTurnedOn(c, n):
incl(c.module.flags, flag)
c.features.incl codeReordering
@@ -301,7 +318,7 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
result.path = path
c.libs.add result
if path.kind in {nkStrLit..nkTripleStrLit}:
result.isOverriden = options.isDynlibOverride(c.config, path.strVal)
result.isOverridden = options.isDynlibOverride(c.config, path.strVal)
proc expectDynlibNode(c: PContext, n: PNode): PNode =
if n.kind notin nkPragmaCallKinds or n.len != 2:
@@ -313,7 +330,7 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
# {.dynlib: myGetProcAddr(...).}
result = c.semExpr(c, n[1])
if result.kind == nkSym and result.sym.kind == skConst:
result = result.sym.astdef # look it up
result = c.semConstExpr(c, result) # fold const
if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}:
localError(c.config, n.info, errStringLiteralExpected)
result = newEmptyStrNode(c, n)
@@ -321,12 +338,12 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule):
let lib = getLib(c, libDynamic, expectDynlibNode(c, n))
if not lib.isOverriden:
if not lib.isOverridden:
c.optionStack[^1].dynlib = lib
else:
if n.kind in nkPragmaCallKinds:
var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
if not lib.isOverriden:
if not lib.isOverridden:
addToLib(lib, sym)
incl(sym.loc.flags, lfDynamicLib)
else:
@@ -363,7 +380,7 @@ proc processNote(c: PContext, n: PNode) =
else: invalidPragma(c, n)
else: invalidPragma(c, n)
proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
proc pragmaToOptions*(w: TSpecialWord): TOptions {.inline.} =
case w
of wChecks: ChecksOptions
of wObjChecks: {optObjCheck}
@@ -389,6 +406,7 @@ proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
of wImplicitStatic: {optImplicitStatic}
of wPatterns, wTrMacros: {optTrMacros}
of wSinkInference: {optSinkInference}
of wQuirky: {optQuirky}
else: {}
proc processExperimental(c: PContext; n: PNode) =
@@ -450,6 +468,18 @@ proc processOption(c: PContext, n: PNode, resOptions: var TOptions) =
# calling conventions (boring...):
localError(c.config, n.info, "option expected")
proc checkPushedPragma(c: PContext, n: PNode) =
let keyDeep = n.kind in nkPragmaCallKinds and n.len > 1
var key = if keyDeep: n[0] else: n
if key.kind in nkIdentKinds:
let ident = considerQuotedIdent(c, key)
var userPragma = strTableGet(c.userPragmas, ident)
if userPragma == nil:
let k = whichKeyword(ident)
# TODO: might as well make a list which is not accepted by `push`: emit, cast etc.
if k == wEmit:
localError(c.config, n.info, "an 'emit' pragma cannot be pushed")
proc processPush(c: PContext, n: PNode, start: int) =
if n[start-1].kind in nkPragmaCallKinds:
localError(c.config, n.info, "'push' cannot have arguments")
@@ -457,6 +487,7 @@ proc processPush(c: PContext, n: PNode, start: int) =
for i in start..<n.len:
if not tryProcessOption(c, n[i], c.config.options):
# simply store it somewhere:
checkPushedPragma(c, n[i])
if x.otherPragmas.isNil:
x.otherPragmas = newNodeI(nkPragma, n.info)
x.otherPragmas.add n[i]
@@ -476,8 +507,16 @@ proc processPop(c: PContext, n: PNode) =
when defined(debugOptions):
echo c.config $ n.info, " POP config is now ", c.config.options
proc processDefine(c: PContext, n: PNode) =
if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
proc processDefineConst(c: PContext, n: PNode, sym: PSym, kind: TMagic) =
sym.magic = kind
if n.kind in nkPragmaCallKinds and n.len == 2:
# could also use TLib
n[1] = getStrLitNode(c, n)
proc processDefine(c: PContext, n: PNode, sym: PSym) =
if sym != nil and sym.kind == skConst:
processDefineConst(c, n, sym, mGenericDefine)
elif (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent):
defineSymbol(c.config.symbols, n[1].ident.s)
else:
invalidPragma(c, n)
@@ -500,18 +539,25 @@ proc relativeFile(c: PContext; n: PNode; ext=""): AbsoluteFile =
if result.isEmpty: result = AbsoluteFile s
proc processCompile(c: PContext, n: PNode) =
## This pragma can take two forms. The first is a simple file input:
## {.compile: "file.c".}
## The second is a tuple where the second arg is the output name strutils formatter:
## {.compile: ("file.c", "$1.o").}
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile; customArgs: string) =
var cf = Cfile(nimname: splitFile(src).name,
cname: src, obj: dest, flags: {CfileFlag.External},
customArgs: customArgs)
extccomp.addExternalFileToCompile(c.config, cf)
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
if not fileExists(src):
localError(c.config, n.info, "cannot find: " & src.string)
else:
extccomp.addExternalFileToCompile(c.config, cf)
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
proc getStrLit(c: PContext, n: PNode; i: int): string =
n[i] = c.semConstExpr(c, n[i])
case n[i].kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
when defined(gcArc) or defined(gcOrc):
when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
result = n[i].strVal
else:
shallowCopy(result, n[i].strVal)
@@ -545,7 +591,8 @@ proc processCompile(c: PContext, n: PNode) =
else:
found = findFile(c.config, s)
if found.isEmpty: found = AbsoluteFile s
let obj = toObjFile(c.config, completeCfilePath(c.config, found, false))
let mangled = completeCfilePath(c.config, mangleModuleName(c.config, found).AbsoluteFile)
let obj = toObjFile(c.config, mangled)
docompile(c, it, found, obj, customArgs)
proc processLink(c: PContext, n: PNode) =
@@ -597,7 +644,7 @@ proc pragmaEmit(c: PContext, n: PNode) =
if n1.kind == nkBracket:
var b = newNodeI(nkBracket, n1.info, n1.len)
for i in 0..<n1.len:
b[i] = c.semExpr(c, n1[i])
b[i] = c.semExprWithType(c, n1[i], {efTypeAllowed})
n[1] = b
else:
n[1] = c.semConstExpr(c, n1)
@@ -650,7 +697,8 @@ proc processPragma(c: PContext, n: PNode, i: int) =
elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
invalidPragma(c, n)
var userPragma = newSym(skTemplate, it[1].ident, nextSymId(c.idgen), c.module, it.info, c.config.options)
var userPragma = newSym(skTemplate, it[1].ident, c.idgen, c.module, it.info, c.config.options)
styleCheckDef(c, userPragma)
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
strTableAdd(c.userPragmas, userPragma)
@@ -710,19 +758,8 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) =
return
if pragma.kind != nkBracket:
localError(c.config, pragma.info, "list of key:value pairs expected"); return
for n in pragma:
if n.kind in nkPragmaCallKinds and n.len == 2:
let dest = qualifiedLookUp(c, n[1], {checkUndeclared})
if dest == nil or dest.kind in routineKinds:
localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines")
let src = considerQuotedIdent(c, n[0])
let alias = newSym(skAlias, src, nextSymId(c.idgen), dest, n[0].info, c.config.options)
incl(alias.flags, sfExported)
if sfCompilerProc in dest.flags: markCompilerProc(c, alias)
addInterfaceDecl(c, alias)
n[1] = newSymNode(dest)
else:
localError(c.config, n.info, "key:value pair expected")
message(c.config, pragma.info, warnDeprecated,
"deprecated statement is now a no-op, use regular deprecated pragma")
proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
if it.kind notin nkPragmaCallKinds or it.len != 2:
@@ -738,12 +775,12 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
# We return a dummy symbol; later passes over the type will repair it.
# Generic instantiation needs to know about this too. But we're lazy
# and perform the lookup on demand instead.
result = newSym(skUnknown, considerQuotedIdent(c, n), nextSymId(c.idgen), nil, n.info,
result = newSym(skUnknown, considerQuotedIdent(c, n), c.idgen, nil, n.info,
c.config.options)
else:
result = qualifiedLookUp(c, n, {checkUndeclared})
proc semCustomPragma(c: PContext, n: PNode): PNode =
proc semCustomPragma(c: PContext, n: PNode, sym: PSym): PNode =
var callNode: PNode
if n.kind in {nkIdent, nkSym}:
@@ -763,6 +800,11 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
invalidPragma(c, n)
return n
# we have a valid custom pragma
if sym != nil and sym.kind in {skEnumField, skForVar, skModule}:
illegalCustomPragma(c, n, sym)
return n
result = r
# Transform the nkCall node back to its original form if possible
if n.kind == nkIdent and r.len == 1:
@@ -796,7 +838,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords,
comesFromPush, isStatement: bool): bool =
var it = n[i]
var key = if it.kind in nkPragmaCallKinds and it.len > 1: it[0] else: it
let keyDeep = it.kind in nkPragmaCallKinds and it.len > 1
var key = if keyDeep: it[0] else: it
if key.kind == nkBracketExpr:
processNote(c, it)
return
@@ -810,7 +853,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
else: discard
return
elif key.kind notin nkIdentKinds:
n[i] = semCustomPragma(c, it)
n[i] = semCustomPragma(c, it, sym)
return
let ident = considerQuotedIdent(c, key)
var userPragma = strTableGet(c.userPragmas, ident)
@@ -819,17 +862,20 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
# number of pragmas increase/decrease with user pragma expansion
inc c.instCounter
defer: dec c.instCounter
if c.instCounter > 100:
globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s)
if keyDeep:
localError(c.config, it.info, "user pragma cannot have arguments")
pragma(c, sym, userPragma.ast, validPragmas, isStatement)
n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
dec c.instCounter
else:
let k = whichKeyword(ident)
if k in validPragmas:
checkPragmaUse(c.config, key.info, k, ident.s)
checkPragmaUse(c, key.info, k, ident.s, (if sym != nil: sym else: c.module))
case k
of wExportc, wExportCpp:
makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info)
@@ -917,7 +963,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wThreadVar:
noVal(c, it)
incl(sym.flags, {sfThread, sfGlobal})
of wDeadCodeElimUnused: discard # deprecated, dead code elim always on
of wDeadCodeElimUnused:
warningDeprecated(c.config, n.info, "'{.deadcodeelim: on.}' is deprecated, now a noop") # deprecated, dead code elim always on
of wNoForward: pragmaNoForward(c, it)
of wReorder: pragmaNoForward(c, it, flag = sfReorder)
of wMagic: processMagic(c, it, sym)
@@ -937,8 +984,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
# only supported for backwards compat, doesn't do anything anymore
noVal(c, it)
of wConstructor:
noVal(c, it)
incl(sym.flags, sfConstructor)
if sfImportc notin sym.flags:
sym.constraint = newEmptyStrNode(c, it, getOptionalStr(c, it, ""))
sym.constraint.strVal = sym.constraint.strVal
sym.flags.incl {sfExportc, sfMangleCpp}
sym.typ.callConv = ccNoConvention
of wHeader:
var lib = getLib(c, libHeader, getStrLitNode(c, it))
addToLib(lib, sym)
@@ -1032,6 +1083,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
if sym.typ != nil:
incl(sym.typ.flags, tfThread)
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccNimCall
of wSendable:
noVal(c, it)
if sym != nil and sym.typ != nil:
incl(sym.typ.flags, tfSendable)
else:
invalidPragma(c, it)
of wGcSafe:
noVal(c, it)
if sym != nil:
@@ -1066,15 +1123,22 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
recordPragma(c, it, "error", s)
localError(c.config, it.info, errUser, s)
of wFatal: fatal(c.config, it.info, expectStrLit(c, it))
of wDefine: processDefine(c, it)
of wDefine: processDefine(c, it, sym)
of wUndef: processUndef(c, it)
of wCompile: processCompile(c, it)
of wCompile:
let m = sym.getModule()
incl(m.flags, sfUsed)
processCompile(c, it)
of wLink: processLink(c, it)
of wPassl:
let m = sym.getModule()
incl(m.flags, sfUsed)
let s = expectStrLit(c, it)
extccomp.addLinkOption(c.config, s)
recordPragma(c, it, "passl", s)
of wPassc:
let m = sym.getModule()
incl(m.flags, sfUsed)
let s = expectStrLit(c, it)
extccomp.addCompileOption(c.config, s)
recordPragma(c, it, "passc", s)
@@ -1156,13 +1220,17 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
invalidPragma(c, it)
of wByRef:
noVal(c, it)
if sym == nil or sym.typ == nil:
if sym != nil and sym.kind == skParam:
sym.options.incl optByRef
elif sym == nil or sym.typ == nil:
processOption(c, it, c.config.options)
else:
incl(sym.typ.flags, tfByRef)
of wByCopy:
noVal(c, it)
if sym.kind != skType or sym.typ == nil: invalidPragma(c, it)
if sym.kind == skParam:
incl(sym.flags, sfByCopy)
elif sym.kind != skType or sym.typ == nil: invalidPragma(c, it)
else: incl(sym.typ.flags, tfByCopy)
of wPartial:
noVal(c, it)
@@ -1213,11 +1281,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
noVal(c, it)
sym.flags.incl sfBase
of wIntDefine:
sym.magic = mIntDefine
processDefineConst(c, n, sym, mIntDefine)
of wStrDefine:
sym.magic = mStrDefine
processDefineConst(c, n, sym, mStrDefine)
of wBoolDefine:
sym.magic = mBoolDefine
processDefineConst(c, n, sym, mBoolDefine)
of wUsed:
noVal(c, it)
if sym == nil: invalidPragma(c, it)
@@ -1227,21 +1295,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
pragmaProposition(c, it)
of wEnsures:
pragmaEnsures(c, it)
of wEnforceNoRaises:
of wEnforceNoRaises, wQuirky:
sym.flags.incl sfNeverRaises
of wSystemRaisesDefect:
sym.flags.incl sfSystemRaisesDefect
of wVirtual:
processVirtual(c, it, sym)
else: invalidPragma(c, it)
elif comesFromPush and whichKeyword(ident) != wInvalid:
discard "ignore the .push pragma; it doesn't apply"
else:
if sym == nil or (sym.kind in {skVar, skLet, skConst, skParam, skIterator,
skField, skProc, skFunc, skConverter, skMethod, skType}):
n[i] = semCustomPragma(c, it)
elif sym != nil:
illegalCustomPragma(c, it, sym)
else:
invalidPragma(c, it)
# semCustomPragma gives appropriate error for invalid pragmas
n[i] = semCustomPragma(c, it, sym)
proc overwriteLineInfo(n: PNode; info: TLineInfo) =
n.info = info

View File

@@ -4,4 +4,4 @@
- Note that this code has been translated from a bootstrapping version written in Pascal.
- So the code is **not** a poster child of good Nim code.
See [Internals of the Nim Compiler](https://nim-lang.org/docs/intern.html) for more information.
See [Internals of the Nim Compiler](https://nim-lang.github.io/Nim/intern.html) for more information.

View File

@@ -9,13 +9,12 @@
# This module implements the renderer of the standard Nim representation.
when defined(nimHasUsed):
# 'import renderer' is so useful for debugging
# that Nim shouldn't produce a warning for that:
{.used.}
# 'import renderer' is so useful for debugging
# that Nim shouldn't produce a warning for that:
{.used.}
import
lexer, options, idents, strutils, ast, msgs, lineinfos
lexer, options, idents, strutils, ast, msgs, lineinfos, wordrecg
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions, formatfloat]
@@ -24,13 +23,18 @@ type
TRenderFlag* = enum
renderNone, renderNoBody, renderNoComments, renderDocComments,
renderNoPragmas, renderIds, renderNoProcDefs, renderSyms, renderRunnableExamples,
renderIr
renderIr, renderNonExportedFields, renderExpandUsing
TRenderFlags* = set[TRenderFlag]
TRenderTok* = object
kind*: TokType
length*: int16
sym*: PSym
Section = enum
GenericParams
ObjectDef
TRenderTokSeq* = seq[TRenderTok]
TSrcGen* = object
indent*: int
@@ -45,7 +49,7 @@ type
pendingWhitespace: int
comStack*: seq[PNode] # comment stack
flags*: TRenderFlags
inGenericParams: bool
inside: set[Section] # Keeps track of contexts we are in
checkAnon: bool # we're in a context that can contain sfAnon
inPragma: int
when defined(nimpretty):
@@ -73,6 +77,16 @@ proc isKeyword*(i: PIdent): bool =
(i.id <= ord(tokKeywordHigh) - ord(tkSymbol)):
result = true
proc isExported(n: PNode): bool =
## Checks if an ident is exported.
## This is meant to be used with idents in nkIdentDefs.
case n.kind
of nkPostfix:
n[0].ident.s == "*" and n[1].kind == nkIdent
of nkPragmaExpr:
n[0].isExported()
else: false
proc renderDefinitionName*(s: PSym, noQuotes = false): string =
## Returns the definition name of the symbol.
##
@@ -85,6 +99,25 @@ proc renderDefinitionName*(s: PSym, noQuotes = false): string =
else:
result = '`' & x & '`'
template inside(g: var TSrcGen, section: Section, body: untyped) =
## Runs `body` with `section` included in `g.inside`.
## Removes it at the end of the body if `g` wasn't inside it
## before the template.
let wasntInSection = section notin g.inside
g.inside.incl section
body
if wasntInSection:
g.inside.excl section
template outside(g: var TSrcGen, section: Section, body: untyped) =
## Temporarily removes `section` from `g.inside`. Adds it back
## at the end of the body if `g` was inside it before the template
let wasInSection = section in g.inside
g.inside.excl section
body
if wasInSection:
g.inside.incl section
const
IndentWidth = 2
longIndentWid = IndentWidth * 2
@@ -121,7 +154,7 @@ proc initSrcGen(g: var TSrcGen, renderFlags: TRenderFlags; config: ConfigRef) =
g.flags = renderFlags
g.pendingNL = -1
g.pendingWhitespace = -1
g.inGenericParams = false
g.inside = {}
g.config = config
proc addTok(g: var TSrcGen, kind: TokType, s: string; sym: PSym = nil) =
@@ -379,6 +412,7 @@ proc atom(g: TSrcGen; n: PNode): string =
of nkEmpty: result = ""
of nkIdent: result = n.ident.s
of nkSym: result = n.sym.name.s
of nkClosedSymChoice, nkOpenSymChoice: result = n[0].sym.name.s
of nkStrLit: result = ""; result.addQuoted(n.strVal)
of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"'
of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
@@ -434,6 +468,24 @@ proc lsons(g: TSrcGen; n: PNode, start: int = 0, theEnd: int = - 1): int =
result = 0
for i in start..n.len + theEnd: inc(result, lsub(g, n[i]))
proc origUsingType(n: PNode): PSym {.inline.} =
## Returns the type that a parameter references. Check with referencesUsing first
## to check `n` is actually referencing a using node
# If the node is untyped the typ field will be nil
if n[0].sym.typ != nil:
n[0].sym.typ.sym
else: nil
proc referencesUsing(n: PNode): bool =
## Returns true if n references a using statement.
## e.g. proc foo(x) # x doesn't have type or def value so it references a using
result = n.kind == nkIdentDefs and
# Sometimes the node might not have been semmed (e.g. doc0) and will be nkIdent instead
n[0].kind == nkSym and
# Templates/macros can have parameters with no type (But their orig type will be nil)
n.origUsingType != nil and
n[1].kind == nkEmpty and n[2].kind == nkEmpty
proc lsub(g: TSrcGen; n: PNode): int =
# computes the length of a tree
if isNil(n): return 0
@@ -463,6 +515,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
of nkClosedSymChoice, nkOpenSymChoice:
if n.len > 0: result += lsub(g, n[0])
of nkOpenSym: result = lsub(g, n[0])
of nkTupleTy: result = lcomma(g, n) + len("tuple[]")
of nkTupleClassTy: result = len("tuple")
of nkDotExpr: result = lsons(g, n) + 1
@@ -474,8 +527,11 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkDo: result = lsons(g, n) + len("do__:_")
of nkConstDef, nkIdentDefs:
result = lcomma(g, n, 0, - 3)
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
if n.referencesUsing:
result += lsub(g, newSymNode(n.origUsingType)) + 2
else:
if n[^2].kind != nkEmpty: result += lsub(g, n[^2]) + 2
if n[^1].kind != nkEmpty: result += lsub(g, n[^1]) + 3
of nkVarTuple:
if n[^1].kind == nkEmpty:
result = lcomma(g, n, 0, - 2) + len("()")
@@ -598,7 +654,9 @@ proc isHideable(config: ConfigRef, n: PNode): bool =
# xxx compare `ident` directly with `getIdent(cache, wRaises)`, but
# this requires a `cache`.
case n.kind
of nkExprColonExpr: result = n[0].kind == nkIdent and n[0].ident.s in ["raises", "tags", "extern", "deprecated", "forbids"]
of nkExprColonExpr:
result = n[0].kind == nkIdent and
n[0].ident.s.nimIdentNormalize in ["raises", "tags", "extern", "deprecated", "forbids", "stacktrace"]
of nkIdent: result = n.ident.s in ["gcsafe", "deprecated"]
else: result = false
@@ -630,7 +688,7 @@ proc gcommaAux(g: var TSrcGen, n: PNode, ind: int, start: int = 0,
inHideable = false
proc gcomma(g: var TSrcGen, n: PNode, c: TContext, start: int = 0,
theEnd: int = - 1) =
theEnd: int = -1) =
var ind: int
if rfInConstExpr in c.flags:
ind = g.indent + IndentWidth
@@ -791,7 +849,7 @@ proc gcase(g: var TSrcGen, n: PNode) =
gsub(g, n[^1], c)
proc genSymSuffix(result: var string, s: PSym) {.inline.} =
if sfGenSym in s.flags:
if sfGenSym in s.flags and s.name.id != ord(wUnderscore):
result.add '_'
result.addInt s.id
@@ -807,19 +865,17 @@ proc gproc(g: var TSrcGen, n: PNode) =
if n[patternPos].kind != nkEmpty:
gpattern(g, n[patternPos])
let oldInGenericParams = g.inGenericParams
g.inGenericParams = true
if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
n[miscPos][1].kind != nkEmpty:
gsub(g, n[miscPos][1])
else:
gsub(g, n[genericParamsPos])
g.inGenericParams = oldInGenericParams
g.inside(GenericParams):
if renderNoBody in g.flags and n[miscPos].kind != nkEmpty and
n[miscPos][1].kind != nkEmpty:
gsub(g, n[miscPos][1])
else:
gsub(g, n[genericParamsPos])
gsub(g, n[paramsPos])
if renderNoPragmas notin g.flags:
gsub(g, n[pragmasPos])
if renderNoBody notin g.flags:
if n[bodyPos].kind != nkEmpty:
if n.len > bodyPos and n[bodyPos].kind != nkEmpty:
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
indentNL(g)
@@ -892,7 +948,7 @@ proc gasm(g: var TSrcGen, n: PNode) =
gsub(g, n[1])
proc gident(g: var TSrcGen, n: PNode) =
if g.inGenericParams and n.kind == nkSym:
if GenericParams in g.inside and n.kind == nkSym:
if sfAnon in n.sym.flags or
(n.typ != nil and tfImplicitTypeParam in n.typ.flags): return
@@ -916,7 +972,9 @@ proc gident(g: var TSrcGen, n: PNode) =
s.addInt localId
if sfCursor in n.sym.flags:
s.add "_cursor"
elif n.kind == nkSym and (renderIds in g.flags or sfGenSym in n.sym.flags or n.sym.kind == skTemp):
elif n.kind == nkSym and (renderIds in g.flags or
(sfGenSym in n.sym.flags and n.sym.name.id != ord(wUnderscore)) or
n.sym.kind == skTemp):
s.add '_'
s.addInt n.sym.id
when defined(debugMagics):
@@ -962,7 +1020,7 @@ proc bracketKind*(g: TSrcGen, n: PNode): BracketKind =
proc skipHiddenNodes(n: PNode): PNode =
result = n
while result != nil:
if result.kind in {nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv} and result.len > 1:
if result.kind in {nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv, nkOpenSym} and result.len > 1:
result = result[1]
elif result.kind in {nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString} and
result.len > 0:
@@ -983,7 +1041,7 @@ proc accentedName(g: var TSrcGen, n: PNode) =
gsub(g, n)
proc infixArgument(g: var TSrcGen, n: PNode, i: int) =
if i < 1 and i > 2: return
if i < 1 or i > 2: return
var needsParenthesis = false
let nNext = n[i].skipHiddenNodes
if nNext.kind == nkInfix:
@@ -1222,6 +1280,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
put(g, tkParRi, if n.kind == nkOpenSymChoice: "|...)" else: ")")
else:
gsub(g, n, 0)
of nkOpenSym: gsub(g, n, 0)
of nkPar, nkClosure:
put(g, tkParLe, "(")
gcomma(g, n, c)
@@ -1260,8 +1319,12 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
gsub(g, n, 0)
of nkCheckedFieldExpr, nkHiddenAddr, nkHiddenDeref, nkStringToCString, nkCStringToString:
if renderIds in g.flags:
putWithSpace(g, tkAddr, $n.kind)
put(g, tkAddr, $n.kind)
put(g, tkParLe, "(")
gsub(g, n, 0)
if renderIds in g.flags:
put(g, tkParRi, ")")
of nkLambda:
putWithSpace(g, tkProc, "proc")
gsub(g, n, paramsPos)
@@ -1276,11 +1339,32 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
gsub(g, n, pragmasPos)
put(g, tkColon, ":")
gsub(g, n, bodyPos)
of nkConstDef, nkIdentDefs:
of nkIdentDefs:
# Skip if this is a property in a type and its not exported
# (While also not allowing rendering of non exported fields)
if ObjectDef in g.inside and (not n[0].isExported() and renderNonExportedFields notin g.flags):
return
# We render the identDef without being inside the section incase we render something like
# y: proc (x: string) # (We wouldn't want to check if x is exported)
g.outside(ObjectDef):
gcomma(g, n, 0, -3)
if n.len >= 2 and n[^2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
gsub(g, n[^2], c)
elif n.referencesUsing and renderExpandUsing in g.flags:
putWithSpace(g, tkColon, ":")
gsub(g, newSymNode(n.origUsingType), c)
if n.len >= 1 and n[^1].kind != nkEmpty:
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
gsub(g, n[^1], c)
of nkConstDef:
gcomma(g, n, 0, -3)
if n.len >= 2 and n[^2].kind != nkEmpty:
putWithSpace(g, tkColon, ":")
gsub(g, n, n.len - 2)
gsub(g, n[^2], c)
if n.len >= 1 and n[^1].kind != nkEmpty:
put(g, tkSpaces, Space)
putWithSpace(g, tkEquals, "=")
@@ -1302,6 +1386,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
putWithSpace(g, tkColon, ":")
gsub(g, n, 1)
of nkInfix:
if n.len < 3:
var i = 0
put(g, tkOpr, "Too few children for nkInfix")
return
let oldLineLen = g.lineLen # we cache this because lineLen gets updated below
infixArgument(g, n, 1)
put(g, tkSpaces, Space)
@@ -1349,15 +1437,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkAccQuoted:
put(g, tkAccent, "`")
for i in 0..<n.len:
proc getStrVal(n: PNode): string =
# pending https://github.com/nim-lang/Nim/pull/17540, use `getStrVal`
case n.kind
of nkIdent: n.ident.s
of nkSym: n.sym.name.s
else: ""
proc isAlpha(n: PNode): bool =
if n.kind in {nkIdent, nkSym}:
let tmp = n.getStrVal
let tmp = n.getPIdent.s
result = tmp.len > 0 and tmp[0] in {'a'..'z', 'A'..'Z'}
var useSpace = false
if i == 1 and n[0].kind == nkIdent and n[0].ident.s in ["=", "'"]:
@@ -1442,20 +1524,20 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkObjectTy:
if n.len > 0:
putWithSpace(g, tkObject, "object")
gsub(g, n[0])
gsub(g, n[1])
gcoms(g)
gsub(g, n[2])
g.inside(ObjectDef):
gsub(g, n[0])
gsub(g, n[1])
gcoms(g)
indentNL(g)
gsub(g, n[2])
dedent(g)
else:
put(g, tkObject, "object")
of nkRecList:
indentNL(g)
for i in 0..<n.len:
optNL(g)
gsub(g, n[i], c)
gcoms(g)
dedent(g)
putNL(g)
of nkOfInherit:
putWithSpace(g, tkOf, "of")
gsub(g, n, 0)

View File

@@ -106,6 +106,7 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
if a.kind == nkExprColonExpr and a[0].kind == nkIdent and a[0].ident.s == "pragma":
# user defined pragma
decl(a[1])
for i in 1..<n.safeLen: deps(n[i])
else:
for i in 0..<n.safeLen: deps(n[i])
of nkMixinStmt, nkBindStmt: discard
@@ -318,6 +319,14 @@ proc intersects(s1, s2: IntSet): bool =
if s2.contains(a):
return true
proc hasPushOrPopPragma(n: DepN): bool =
# Checks if the tree node has some pragmas that do not
# play well with reordering, like the push/pop pragma
# no crossing for push/pop barrier
let a = n.pnode
result = a.kind == nkPragma and a[0].kind == nkIdent and
(a[0].ident.s == "push" or a[0].ident.s == "pop")
proc buildGraph(n: PNode, deps: seq[(IntSet, IntSet)]): DepG =
# Build a dependency graph
result = newSeqOfCap[DepN](deps.len)
@@ -359,6 +368,13 @@ proc buildGraph(n: PNode, deps: seq[(IntSet, IntSet)]): DepG =
for dep in deps[i][0]:
if dep in declares:
ni.expls.add "one declares \"" & idNames[dep] & "\" and the other defines it"
elif hasPushOrPopPragma(nj):
# Every node that comes after a push/pop pragma must
# depend on it; vice versa
if j < i:
ni.kids.add nj
else:
nj.kids.add ni
else:
for d in declares:
if uses.contains(d):
@@ -398,17 +414,7 @@ proc getStrongComponents(g: var DepG): seq[seq[DepN]] =
if v.idx < 0:
strongConnect(v, idx, s, result)
proc hasForbiddenPragma(n: PNode): bool =
# Checks if the tree node has some pragmas that do not
# play well with reordering, like the push/pop pragma
for a in n:
if a.kind == nkPragma and a[0].kind == nkIdent and
a[0].ident.s == "push":
return true
proc reorder*(graph: ModuleGraph, n: PNode, module: PSym): PNode =
if n.hasForbiddenPragma:
return n
var includedFiles = initIntSet()
let mpath = toFullPath(graph.config, module.fileIdx)
let n = expandIncludes(graph, module, n, mpath,

View File

@@ -21,8 +21,8 @@ type
# though it is not necessary)
Rope* = string
proc newRopeAppender*(): string {.inline.} =
result = newString(0)
proc newRopeAppender*(cap = 80): string {.inline.} =
result = newStringOfCap(cap)
proc freeze*(r: Rope) {.inline.} = discard
@@ -102,12 +102,9 @@ proc runtimeFormat*(frmt: FormatStr, args: openArray[Rope]): Rope =
inc(i)
else:
doAssert false, "invalid format string: " & frmt
var start = i
while i < frmt.len:
if frmt[i] != '$': inc(i)
else: break
if i - 1 >= start:
result.add(substr(frmt, start, i - 1))
else:
result.add(frmt[i])
inc(i)
proc `%`*(frmt: static[FormatStr], args: openArray[Rope]): Rope =
runtimeFormat(frmt, args)

Some files were not shown because too many files have changed in this diff Show More