Compare commits

..

1449 Commits

Author SHA1 Message Date
narimiran
7e83adff84 bump Nim version to 1.2.0 2020-04-03 14:17:15 +02:00
Alexander Ivanov
920add5880 sourcemaps for the JS codegen (#7508) 2020-04-03 12:06:23 +02:00
Andreas Rumpf
2b3b24a804 make bootstrapping more robust for people who have Nim inside /usr/bin (#13855) 2020-04-03 10:25:15 +02:00
itsumura-h
87e6b88f3b fix #7241 (#13779)
finalize() should run in insert()
2020-04-03 09:38:05 +02:00
Timothee Cour
93cd98dd14 move tinyc to a separate repo and allow installing external dependencency (eg tinyc) from koch / library code (#13850)
* remove tinyc
* installDeps
* update tinyc paths
2020-04-03 09:10:45 +02:00
flywind
6b9ffc7fad fix asynchttpserver content-length header (#13846) 2020-04-03 09:05:43 +02:00
Timothee Cour
d23371fdd7 std/byaddr => std/decls (#13847) 2020-04-03 09:03:13 +02:00
narimiran
7d17cd34b8 create a changelog for v1.2.0 2020-04-02 16:28:01 +02:00
Araq
8ee0771b5a return types must not be Natural for reasons I won't outline here 2020-04-02 15:01:14 +02:00
Araq
d01fca974d added an .assert pragma and mentioned the pragmas in the changelog 2020-04-02 12:57:32 +02:00
Dean Eigenmann
df8e0e7f0c feature/count (#13837) 2020-04-02 12:09:29 +02:00
Andreas Rumpf
d01245e501 renamed new std/pragmas.nim to std/byaddr.nim (#13844)
* renamed new std/pragmas.nim to std/byaddr.nim

* minor code cleanup
2020-04-02 11:52:31 +02:00
Timothee Cour
68539a2926 fix last remaining warning when building nim (intVal should be Int128) + minor cleanups (#13841) 2020-04-02 08:53:52 +02:00
Juan Carlos
c167261735 Deprecate PHP (#13838) 2020-04-02 08:48:09 +02:00
Juan Carlos
160d5fe589 Jsconsole update (#12448)
* Improve jsconsole adding the rest of the stable api as documented on the standard at https://developer.mozilla.org/docs/Web/API/Console

* Improve jsconsole, add runnableexamples
* Simplify jsconsole
2020-04-02 08:47:45 +02:00
Juan Carlos
46ca19ff18 Deprecate DCE:on (#13839) 2020-04-02 02:58:43 +02:00
Juan Carlos
afd0afe0a3 Deprecate when declared(echo):echo (#13840) 2020-04-02 02:56:18 +02:00
Juan Carlos
9102ac8c7d Documentation and Code Style inotify (#13836) 2020-04-02 01:05:55 +02:00
Juan Carlos
9599757068 Add browsers.openDefaultBrowser without URL, implements IETF RFC-6694 Section-3 (#13835) 2020-04-01 15:46:47 -04:00
Andreas Rumpf
bc37668c5a fixes #13782 (#13834) 2020-04-01 20:30:28 +02:00
Juan Carlos
4816984726 Documentation, add more examples (#13825) 2020-04-01 19:39:58 +02:00
Andreas Rumpf
484548c784 revert stdlib changes which are not required anymore 2020-04-01 19:38:44 +02:00
Zahary Karadjov
66f18037b3 Fix tests/types/tparameterizedparent0 2020-04-01 19:38:44 +02:00
Zahary Karadjov
08afa03075 The raises list can now use expressions referencing the generic params 2020-04-01 19:38:44 +02:00
Zahary Karadjov
be95f8fdfa Turn some of the errors back into warnings 2020-04-01 19:38:44 +02:00
Zahary Karadjov
ce9a4ed124 Replace tfHasRequiresInit with a more accurate mechanism
The new mechanism can deal with more complex scenarios such as
not nil field appearing in a non-default case object branch or
a field within a generic object that may depend on a when branch.

The commit also plugs another hole: the user is no longer able
to create illegal default values through seq.setLen(N).
2020-04-01 19:38:44 +02:00
Zahary Karadjov
d374c6373b Fix tests/parallel/tguard2.nim 2020-04-01 19:38:44 +02:00
Zahary Karadjov
2b66d66567 Fix a CI failure during koch doc 2020-04-01 19:38:44 +02:00
Zahary Karadjov
e63b673ce2 Fix https://github.com/nim-lang/Nim/issues/4907 2020-04-01 19:38:44 +02:00
Zahary Karadjov
06438ed143 Close https://github.com/nim-lang/Nim/issues/11428 2020-04-01 19:38:44 +02:00
Zahary Karadjov
4f3d309fb0 Perform nil checks during object construction and within compiles()
Close https://github.com/nim-lang/Nim/issues/6494
2020-04-01 19:38:44 +02:00
Zahary Karadjov
7b7e42be54 More precise error messages for uninitialized fields in the presence of inheritance 2020-04-01 19:38:44 +02:00
Zahary Karadjov
0521f98486 Hrm, the new errors highlighted some code that seems to be broken
New issue: since `Table[A, B]` allocates its backing storage with
`newSeq[KeyValuePair[A, B]]`, it's no longer legal to create a table
with `not nil` types used as either keys or values.
2020-04-01 19:38:44 +02:00
Zahary Karadjov
f3be5a716f not nil types are illegal to construct through default(T) 2020-04-01 19:38:44 +02:00
Zahary Karadjov
1b570f2b18 Turn the warning for uninitialized (result) variables into errors 2020-04-01 19:38:44 +02:00
Zahary Karadjov
e0bb78553a Fix tests/notnil/tnotnil_in_objconstr.nim 2020-04-01 19:38:44 +02:00
Zahary Karadjov
54f06427c8 Enable the requiresInit checks only for objects 2020-04-01 19:38:44 +02:00
Zahary Karadjov
8ae48292ff Plug another hole: default(T) forbidden for objects requiring initialization 2020-04-01 19:38:44 +02:00
Zahary Karadjov
05a0ec4adb Don't allow 'var x: T' for objects that require initialization 2020-04-01 19:38:44 +02:00
Zahary Karadjov
7652aede41 More sophistication; Allow requiresInit to be specified per-field 2020-04-01 19:38:44 +02:00
Zahary Karadjov
a8b6222c86 First steps, the compiler can boot with enforced requiresInit 2020-04-01 19:38:44 +02:00
Timothee Cour
216fd59c44 make usage of foo is a user-defined error more informative (#13833) 2020-04-01 17:49:29 +02:00
Timothee Cour
d3020af44d fix open file leak when running --debugger:native (#13832) 2020-04-01 17:48:17 +02:00
Araq
c2d29eb3e0 updated the changelog 2020-04-01 14:10:47 +02:00
Araq
48213c7428 encodeMIME should be encodeMime by our coding guidelines 2020-04-01 14:10:27 +02:00
Timothee Cour
fd202136b4 fix #13829 (#13831) 2020-04-01 12:46:59 +01:00
Clyybber
515b6d661e Small typo (#13824) 2020-03-31 22:59:43 +02:00
lbartoletti
567af54baf Add arm/arm64 for FreeBSD (#13822)
* Add arm and arm64 for FreeBSD

* Add arm64 with aarch64 and reorder to avoid conflict with arm
2020-03-31 22:55:25 +02:00
Andreas Rumpf
9ffec79300 DrNim (Nim compiler with Z3 integration) (#13743)
* code cleanups and feature additions
* added basic test and koch/CI integration
* make it build on Unix
* DrNim: now buildable on Unix, only takes 10 minutes, enjoy
* added basic documentation for DrNim which can also be seen as the RFC we're following
* drnim: change the build setup so that drnim.exe ends up in bin/
* makes simple floating point ranges work
* added basic float range check
* drnim: teach Z3 about Nim's range types plus code refactoring
* drnim: make unsigned numbers work
* added and fixed index checking under setLen
* first implementation of .ensures, .invariant and .assume (.requires still missing and so is proc type compatibility checking
* drnim: .requires checking implemented
* drnim: implemented .ensures properly
* more impressive test involving min()
* drnim: check for proc type compatibility and base method compatibility wrt .requires and .ensures
* testament: support for 'pattern <directory>
* koch: uses new <directory> feature of testament
* drnim: added tiny musings about 'old'
* Make testament work with old SSL versions
* koch: add support for 'koch drnim -d:release'
* drnim: preparations for the param.old notation
2020-03-31 22:54:48 +02:00
Juan Carlos
dd44701728 Tiny fix on browsers.openDefaultBrowser (#13818) 2020-03-31 21:22:24 +02:00
Juan Carlos
c6586322ba Fix a 'See XXX' on documentation, clean out (#13820) 2020-03-31 21:21:49 +02:00
cooldome
c70b3952ff fixes #13810 (#13821)
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-31 21:15:06 +02:00
Andreas Rumpf
9134bb9cfb macros for proc types, macros for types (#13778)
* new minor feature: macros for proc types, to be documented

* Finished the implementation and added tests

* [skip ci] Describe the new custom pragmas in the manual and the changelog

Co-authored-by: Zahary Karadjov <zahary@gmail.com>
2020-03-31 21:14:05 +02:00
alaviss
40898871a9 workflows/ci_docs: fix documentation deployment (#13819)
* workflows/ci_docs: fix docs publishing

It turns out that github.ref is the full ref name, so we have to be a
bit more specific.

See https://developer.github.com/v3/activity/events/types/#pushevent

Also fixed a silly typo :)

* workflows/ci_docs: run CI when there are changes to the workflow
2020-03-31 19:36:37 +02:00
c-blake
b1aa3b1eea Unwind just the "pseudorandom probing" part of recent sets,tables changes (#13816)
* Unwind just the "pseudorandom probing" (whole hash-code-keyed variable
stride double hashing) part of recent sets & tables changes (which has
still been causing bugs over a month later (e.g., two days ago
https://github.com/nim-lang/Nim/issues/13794) as well as still having
several "figure this out" implementation question comments in them (see
just diffs of this PR).

This topic has been discussed in many places:
  https://github.com/nim-lang/Nim/issues/13393
  https://github.com/nim-lang/Nim/pull/13418
  https://github.com/nim-lang/Nim/pull/13440
  https://github.com/nim-lang/Nim/issues/13794

Alternative/non-mandatory stronger integer hashes (or vice-versa opt-in
identity hashes) are a better solution that is more general (no illusion
of one hard-coded sequence solving all problems) while retaining the
virtues of linear probing such as cache obliviousness and age-less tables
under delete-heavy workloads (still untested after a month of this change).

The only real solution for truly adversarial keys is a hash keyed off of
data unobservable to attackers.  That all fits better with a few families
of user-pluggable/define-switchable hashes which can be provided in a
separate PR more about `hashes.nim`.

This PR carefully preserves the better (but still hard coded!) probing
of the  `intsets` and other recent fixes like `move` annotations, hash
order invariant tests, `intsets.missingOrExcl` fixing, and the move of
`rightSize` into `hashcommon.nim`.

* Fix `data.len` -> `dataLen` problem.
2020-03-31 19:18:45 +02:00
Euan
7abeba6aeb #13806 - getApplFreebsd might lose data (#13807)
* #13806 - first call sysctl with a null buffer to get the length, then alloc buffer and call again

* Use csize_t rather than csize

* Suggestions from @Clyybber

Co-authored-by: Euan Torano <euan.torano@bluesky-wireless.co.uk>
2020-03-31 15:50:24 +02:00
alaviss
5621ff6d09 workflows/ci_docs: lots of goodies (#13809)
* workflows/ci_docs: publish documentation to Github Pages

This should be a complete replacement for our current Travis CI setup.

* workflows/ci_docs: run docgen upon modification to the css on push

So that any changes regarding the stylesheets would be reflected on the
published docs.

* workflows/ci_docs: build the compiler in release mode

* workflows/ci_docs: set branch name for the generated docs

This makes the "Source" links work correctly.

* workflows/ci_docs: run docgen on windows and osx too

Only deploy the Linux-generated version.

* workflows/ci_docs: cache csources compiler

This should cut the time spent building csources, which is about 1-2mins
depending on OS.
2020-03-31 15:48:56 +02:00
Juan Carlos
42d2c3088e Add Documentation (#13811)
* Add more Docs and runnableExamples
2020-03-31 15:47:57 +02:00
Timothee Cour
1e4093d949 refs #13797 (#13812) 2020-03-31 15:43:35 +02:00
Huy Doan
119b0ce66f Fix telebot test failed, closes ba0f3/telebot.nim#49 [ref #13812] (#13814)
I was update telebot to version 1.0.0, update folder structure follow `nimble` guideline
2020-03-31 11:25:12 +02:00
Timothee Cour
19cab9fa51 stacktraces can now show custom runtime msgs per frame (#13351)
* stacktraces can now show custom runtime msgs
* improve tests/stdlib/tstackframes.nim
* fix test for --gc:arc
* test --stacktraceMsgs:on and --stacktraceMsgs:off
* --stacktracemsgs:off by default
2020-03-30 13:45:32 +02:00
Miran
8088633250 faster CIs (#13803)
* ttables: smaller table, 5x speedup

* thavlak: less iterations, less loops; 30% speedup

* tasyncclosestall: shorter timeout; 35% speedup

* gcleak4: less iterations, 2x speedup

* ttimes: remove deprecated stuff

* tdangerisrelease: remove cpp backend, 3x speedup

* tfrexp1: smaller range, 2x speedup

* trtree: fix warnings, less iterations, 6x speedup

* tasyncawait_cyclebreaker: smaller swarm size; 2x speedup

* trealloc: smaller number of iterations; 10x speedup

* towned_binary_tree: less iterations, 4x speedup

* tclosure: remove unused code, less iterations; 2x speedup

* twaitany: less durations; 1.4x speedup

* tasync_misc: less iterations, 2x speedup

* t8535: smaller sleep, 1.5x speedup

* tmanyjoin: smaller sleep, 2x speedup

* t12221: shorter sleeps, removed two slower tests; 1.6x speedup

* tfuturestream: smaller sleep; 1.5x speedup

* growobjcrash: less iterations; 2x speedup

* ttryrecv: smaller sleep; 1.5x speedup

* treusetvar: less threads; 2x speedup

* delete tthreadanalysis2, basically a duplicate of tthreadanalysis

* t7758: less iterations, 1.5x speedup

* tasyncawait: smaller swarm, less messages; 1.5x speedup

* tjsandnativeasync: smaller sleep, 1.5x speedup

* tpendingcheck: smaller sleep, 1.5x speedup

* remove rodfiles test category

* move tseq from its own category to 'collections' category

* remove unneeded tests and helpers from 'assert' category

* stdlib: merge tbitops2 into tbitops

* remove 'trepr2' from 'stdlib' cat

* merge 'tstreams' into one file

* remove 'tinefficient_const_table' from 'ccbugs' cat

* merge 'tcollections_to_string' into 'tcollections'

* tblocking_channel: smaller sleep, small speedup

* tconvexhull: less iterartions; 1.2x speedup

* merge 'tdeepcopy2' into 'tdeepcopy'

* merge 'tdisjoint_slice2' into 'tdisjoint_slice1'

* tmissing_deepcopy: smaller sequence

* tsendtwice: smaller arrays; 5x speedup

* remove 'tindexerrorformatbounds'

* disable multimethod tests

* remove 'gc:none' and 'refc' without 'd:useRealtimeGC' from gc tests

* koch.nim: bootstrap just with '-d:release', no need for 'csource'

* add github workflow for documentation

* testament: no need for 8 sub-second decimals
2020-03-30 13:18:12 +02:00
Andreas Rumpf
2a278f6eba '.push raises: []' now also affects proc types (#13776)
* '.push raises: []' now also affects proc types

* fixes the regression

* less disruptive bugfix

* another attempt
2020-03-29 22:00:18 +02:00
Timothee Cour
06f8c5cb6f fix #13794 HashSet leak (#13800) 2020-03-29 18:08:50 +02:00
Juan Carlos
8c719fce54 Fix #13631 (#13789) 2020-03-29 14:39:58 +02:00
Timothee Cour
cfa1a827dc fix #13730 (#13787) 2020-03-28 08:51:16 +01:00
Timothee Cour
95ab9ab75d [CI] fix recent freebsd systematic failure (#13788) 2020-03-28 01:45:22 -04:00
Andreas Rumpf
0a49fe5fad fixes #13763 (#13777) 2020-03-27 12:14:57 +01:00
alaviss
0eaacbc2c4 More fixes for Haiku (#13774)
* osproc: move fork-based code path under the when conditional

* osproc: avoid using the environ global on Haiku

* osenv: import environ from stdlib.h on Haiku

Haiku's environ is declared in `<stdlib.h>` by default, differing from
POSIX and/or Linux. Import it from there to avoid collision with anyone
importing `<stdlib.h>` from Nim.
2020-03-27 09:08:13 +01:00
Arne Döring
142c59fc37 fix typos and deprecation warnings for tconvariancerules.nim (#13772) 2020-03-27 08:36:21 +01:00
cooldome
289b31ee75 make nim_temp compile with --gc:arc --sinkInference:off (#13769)
* make nim_temp compiler with --gc:arc

* trigger build

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-26 20:15:38 +01:00
Clyybber
2925a47ae6 Fix vm.nim for --gc:arc (#13741)
* koch boot --gc:arc now passes the nim stage

... but generates invalid C code

* Move it closer to where its used

* Try something else

* Poor mans var

* Use UncheckedArray instead
2020-03-26 15:18:45 +00:00
alaviss
6162da812a ssl_certs: add Haiku support (#13761) 2020-03-26 14:47:15 +01:00
alaviss
2da438c33b asyncdispatch: fix erroneous set construction (#13765)
These constants were defined as `cint`. They can be huge on certain
systems, such as Haiku, and trigger out-of-bounds errors in
asyncdispatch.

Ref #13764.
2020-03-26 09:26:56 +01:00
zah
e50441ab33 Fix typeSym.getImpl for ref types (#13752)
* Fix typeSym.getImpl for ref types

* Fix a codegen issue affecting the test suite of nim-beacon-chain

* Fix tests/stdlib/tjsonmacro

To understand the fix better it may help to take a look
at the history of the replaced code.

The nil check that is removed in this commit was introduced
in another fix that failed to identify the root cause of the
issue - namely that we allow an object type to exist for which
no ast is present:

https://github.com/nim-lang/Nim/pull/9601/files

The original intention of the code is more obvious here:

https://github.com/nim-lang/Nim/pull/9538/files
2020-03-26 09:26:19 +01:00
Euan
1b31e08917 import macros rather than import std/macros. (#13762) 2020-03-26 09:11:32 +01:00
Timothee Cour
98753da331 distinctBase overload for values (#13746) 2020-03-25 21:47:03 +01:00
cooldome
764a81ca25 Continue bool conversion fixing (#13751)
* continue fixing #13744

* improve style

* improve test

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-25 21:36:22 +01:00
Miran
e1e062197e bump copyright year to 2020 (#13753) 2020-03-25 21:28:16 +01:00
Rory O’Kane
a8a464810e [ci skip] docs: make the syntax for generics easy to look up (#13754) 2020-03-25 21:09:23 +01:00
Rory O’Kane
febd48f343 [skip ci] docs: reword Part 3 link to communicate that it exists (#13755) 2020-03-25 21:08:24 +01:00
Rory O’Kane
84b378b94f docs: say that nil can be used as a value (#13756)
and improve wording in other ways

Showing that `nil` can be assigned helps to warn readers that variables can be `nil` even after being assigned a value.
2020-03-25 19:42:34 +01:00
Miran
5b55aa52d0 fix deprecations and other warnings (#13748) 2020-03-25 19:15:34 +01:00
cooldome
182d3c16e3 fixes #13744 (#13749)
* fixes #13744

* improve style

Co-authored-by: cooldome <ariabushenko@gmail.ru>
2020-03-25 13:44:52 +00:00
Timothee Cour
46c827be6a fix #13737 (#13738) 2020-03-24 10:14:49 +01:00
Araq
5300baae06 use nimEmulateOverflowChecks for ARM/ARM64 2020-03-24 09:46:54 +01:00
Euan
c0dbcffca6 __stderrp and friends are only on FreeBSD & DragonFlyBSD. (#13735) 2020-03-23 21:39:40 +01:00
Miran
4fb7f076d8 fix #13731, ambiguous repr of pointers (#13732) 2020-03-23 20:03:07 +01:00
Andreas Rumpf
fc5dd11b3d fixes #13722 (#13729)
* fixes #13722

* better fix
2020-03-23 15:47:10 +01:00
Araq
e05fd1d00f hotfix: make 'nim doc nimhcr' work on all platforms 2020-03-23 13:05:29 +01:00
Araq
bcccb74429 trees.nim: compare floating points by their bitpatterns because NaN comparisions are always false (WORST design in the history of computing!) 2020-03-23 12:06:33 +01:00
Araq
ee440df02d disable even more of scope based destruction handling; fixes #13709 2020-03-23 12:05:59 +01:00
Araq
28a755dc80 trees.nim: compare floating points by their bitpatterns because NaN comparisions are always false (WORST design in the history of computing!) 2020-03-23 12:05:59 +01:00
Timothee Cour
913bc95964 new syntax for lvalue references: var b {.byaddr.} = expr (#13508)
* new syntax for lvalue references: `var b {.byaddr.} = expr`
* on type mismatch, `???(0, 0)` not shown anymore
* * compiler now lowers `var a: {.foo.}: MyType = expr` to foo(a, MyType, expr)
* new pragmas.byaddr defined in pure library code exploiting this lowering
* skip `template foo() {.pragma.}`
2020-03-23 11:15:45 +01:00
Andy Davidoff
fa06203e90 add error for missing commandLineParams (#13719)
* add error for missing commandLineParams

* fixup

* rewrite
2020-03-23 11:08:37 +01:00
Andreas Rumpf
7ee08b8cf6 Revert "fix #13417 (#13712)" (#13728)
This reverts commit a5f02cac85.
2020-03-23 09:57:17 +01:00
Christian Ulrich
0ac9c7bb64 introduce getPeerCertificates, fixes #13299 (#13650)
* make i2d_X509 and d2i_X509 always available

i2d_X509 and d2i_X509 have been available in all versions of OpenSSL, so
make them available even if nimDisableCertificateValidation is set.

* introduce getPeerCertificates, fixes #13299

getPeerCertificates retrieves the verified certificate chain of the peer
we are connected to through an SSL-wrapped Socket/AsyncSocket. This
introduces the new type Certificate which stores a DER-encoded X509 certificate.
2020-03-22 21:00:37 +01:00
Araq
ef2566218e better error messages for Nim's effect system 2020-03-22 20:45:03 +01:00
Araq
4c1fdc2e8f Windows API callbacks cannot raise exceptions 2020-03-22 20:45:03 +01:00
Arne Döring
a5f02cac85 fix #13417 (#13712)
* fix #13417

* add test
2020-03-22 20:03:51 +01:00
Arne Döring
64ffa17f0f fixes #13715 (#13716)
* fixes #13715

* fix test
2020-03-22 20:01:01 +01:00
Araq
474dd98125 typo 2020-03-22 19:45:02 +01:00
Arne Döring
047d3af6da fix #13720 (#13721) 2020-03-22 19:35:55 +01:00
Hiroki Noda
86b9435138 Add EPOLLEXCLUSIVE (#13718) 2020-03-21 22:52:44 +01:00
cooldome
586ebb090b fixes #13708 (#13711)
* fixes #13708
* differentiate between arc and rest of GC

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-21 07:12:10 +01:00
narimiran
b6e04eafce [ci skip] add back unintentionally removed line 2020-03-20 17:15:48 +01:00
Federico Ceratto
5b85444244 SSL certificate verify GitHub action (#13697)
* Implement SSL/TLS certificate checking #782

* SSL: Add nimDisableCertificateValidation

Remove NIM_SSL_CERT_VALIDATION env var
tests/untestable/thttpclient_ssl.nim ran successfully on Linux with libssl 1.1.1d

* SSL: update integ test to skip flapping tests

* Revert .travis.yml change

* nimDisableCertificateValidation disable imports

Prevent loading symbols that are not defined on older SSL libs

* SSL: disable verification in net.nim

..when nimDisableCertificateValidation is set

* Update changelog

* Fix peername type

* Add define check for windows

* Disable test on windows

* Add exprimental GitHub action CI for SSL

* Test nimDisableCertificateValidation
2020-03-20 17:11:39 +01:00
Timothee Cour
1d665adecd [RFC] 'walkDir' now has a new 'checkDir' flag, to mimic behaviour of other languages (#13642)
Co-authored-by: narimiran
2020-03-20 16:39:55 +01:00
Araq
8215c57666 threadpool.nim: allow control over MaxThreadPoolSize and MaxDistinguishedThread; refs #10584 2020-03-20 15:07:11 +01:00
Joey
0f2377ebef Revert –#13658 for nim-gdb.bat. Fixes #13705 (#13707) 2020-03-20 14:38:33 +01:00
Andreas Rumpf
253e1b9e96 fixes #13698 (#13706) 2020-03-20 14:35:45 +01:00
Hayden
f4dbdd311f Detect Ubuntu by checking release() and uname() (#13704)
This will improve detection of Ubuntu when running on Ubuntu on WSL. #13703
2020-03-20 10:59:05 +01:00
Araq
dae9865b14 fight the code bloat in base64.nim 2020-03-20 10:46:58 +01:00
Araq
12ab5059a0 make 'nim check' more robust for illdefined constants 2020-03-20 10:46:40 +01:00
Juan Carlos
70d93636cb Add Base64 safe (#13672)
* Implement RFC-4648 Section-7
* https://github.com/nim-lang/Nim/pull/13672#issuecomment-600993466
2020-03-20 10:21:42 +01:00
Timothee Cour
dd362ab4c0 fix #13538 sigmatch errors are now sorted (#13701)
* fix #13538 sigmatch now sorted and has reliable order

* re-enable tests that were disabled because of that bug

* fix remaining tests and un-disable 2 other tests that were affected by this bug
2020-03-20 09:28:03 +01:00
Juan Carlos
55d3780b7b Remove 2 old deprecated files (#13702) 2020-03-20 09:24:35 +01:00
Jasper Jenkins
1037318e68 fix nimsuggest warning (#13699) 2020-03-20 09:24:04 +01:00
Jasper Jenkins
28b6b1c3fb fix nimpretty warning (#13700) 2020-03-20 09:22:40 +01:00
Andreas Rumpf
35fb38629f cycle breaker (#13593)
* cycle breaking as an alternative to cycle detection
2020-03-19 22:58:16 +01:00
Juan Carlos
705e283fef Clean 1 old deprecated empty file (#13696) 2020-03-19 20:40:52 +01:00
cooldome
b3176b8817 Attempt to finish off araq cpp exceptions (#13695)
* config update
* disable a questionable test
* remove c++ exception handling IDs, new impl doesn't require it anymore
* C++ based exceptions finally work
* fixes bootstrapping problem in C++ mode
* teach GCC it's 2020 now
* more bugfixes for C++ based exception handling
* apply cooldome's patch
* another attempt to enable C++11
* bug fix

Co-authored-by: Araq <rumpf_a@web.de>
Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-19 20:38:25 +01:00
Andreas Rumpf
034dad8e32 fixes #13691 (#13694) 2020-03-19 12:57:45 +01:00
Timothee Cour
1f2042411a fix #13412 nim now recompiles for stdin input; SuccessX now configurable; can show whether it recompiled (#13506)
* fix #13412 nim now recompiles for stdin input; SuccessX now indicates whether it recompiled
2020-03-19 10:39:18 +01:00
Timothee Cour
a17e87b516 fix #11458 oswalkdir (#13689)
* fix #11458 oswalkdir

* changelog
2020-03-19 10:23:05 +01:00
Andreas Rumpf
ba6e7c6365 added a switch -d:nimEmulateOverflowChecks for broken or old GCC versions (#13692) 2020-03-19 09:56:30 +01:00
Miran
b5c9881a30 add move to tables to prevent warnings when compiled with --gc:arc (#13684) 2020-03-19 09:09:01 +01:00
alaviss
b33335d7fd httpcore: deprecate ==(string, HttpCode) (#13682)
According to [RFC7230], the reason phrase attached to the status line is
optional and clients should not rely on it. This in turn causes the proc
to be practically useless, as clients should only inspect the return
code.

Ref #13680.

[RFC7230]: https://tools.ietf.org/html/rfc7230#section-3.1.2
2020-03-19 09:07:44 +01:00
Andreas Rumpf
c74cee4e6a gc.rst that doesn't lie (#13686) 2020-03-19 06:41:54 +01:00
Andreas Rumpf
15ba765ebd enable --tlsEmulation:on for --gc:arc (#13685)
* enable --tlsEmulation:on for --gc:arc
* make -d:useMalloc work with --gc:arc --threads:on
2020-03-18 23:52:49 +01:00
Juan Carlos
a0ccfd16a7 Documentation GC (#13109)
* Update Documentation about GC, add ARC based on code observations and https://forum.nim-lang.org/t/5734#35562

* Rephrase 'Garbage Collector' on documentation, see #13331

* Peer Review Feedbacks

* When the body of a documentation section is all for garbage collector details then add 'for garbage collectors' to the title to identify they may not apply for ARC

* Change 'GC' for 'garbage collector'.

* Move 'Memory Management Strategies' at the top, without changes

* Move the info for RefC GC from 'Introduction' to 'RefC' section without changes, make 'Introduction' about Nims 'Multi-paradigm Memory Management Strategies'.
2020-03-18 22:55:39 +01:00
Arne Döring
88566cc651 allow category nimble-packages to test a single package (#13576) 2020-03-18 21:36:48 +01:00
Andreas Rumpf
fb641483f0 arc optimizations (#13325)
* scope based destructors
* handle 'or' and 'and' expressions properly, see the new test arc/tcontrolflow.nim
* make this branch mergable, logic is disabled for now
2020-03-18 16:57:34 +01:00
Araq
a96842aaeb removed .gitattributes as it only causes trouble for me 2020-03-18 14:43:39 +01:00
Andreas Rumpf
3f29911a94 new feature: --staticBoundChecks:on to enforce static array index checking (#10965) 2020-03-18 14:25:10 +01:00
Timothee Cour
ed263e174e fix #13524 astToStr now works inside generics (#13681) 2020-03-18 13:43:32 +01:00
Andreas Rumpf
a87062393a fixes #13622 (#13679) 2020-03-18 13:42:33 +01:00
Araq
3f1a85b7f0 fixes hash(HashSet) which was wrong as it didn't respect tombstones; refs #13649 2020-03-18 10:47:58 +01:00
Andreas Rumpf
5f6997794e fixes #13671 [backport] (#13678) 2020-03-18 10:37:36 +01:00
Jasper Jenkins
51bd442b88 fix when statements in inheritable generic objects (#13667) [backport] 2020-03-17 23:44:32 +01:00
Jasper Jenkins
122751aa52 add nnkMacroDef to RoutineNodes (#13676) 2020-03-17 23:41:07 +01:00
Andreas Rumpf
fe7b1dfb2a rewritten goto based exception handling; much cleaner implementation;… (#13677)
* rewritten goto based exception handling; much cleaner implementation; fixes #13668
2020-03-17 23:18:43 +01:00
Araq
b737bb4be0 fixes a bug for 'dup' and 'with'; they can now handle nested statement lists that can result from macros 2020-03-17 18:00:11 +01:00
cooldome
35d14095ed Fixes #13659 (#13674)
* fixes #13659

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-17 16:36:38 +01:00
Timothee Cour
af9c852701 fix nim doc subdir/foo which was generating broken css; + other fixes (#13647)
* docgen: minor refactoring via docOutDir
* fix css for `nim doc subdir/foo` without --outdir nor -o
* tcompilesetting.nim: keep `git status` clean
* re-enable pkg nimgame2 that got fixed upstream
2020-03-17 13:44:37 +01:00
Jasper Jenkins
6a23452bf4 fix sets of scoped imported enums (#13666) 2020-03-17 10:47:27 +01:00
Andreas Rumpf
bec0522fca updated builds.sr.ht script according to their email (#13669) 2020-03-17 08:49:26 +01:00
Leorize
e5adaeed20 workflows/ci: disable
Since we got Azure Pipelines running, this will be a fallback pipeline.

Activate by removing the `.disabled` suffix
2020-03-17 08:48:42 +01:00
Leorize
5017320e7b gitattributes: fix tests for windows
Nim-generated files used in tests all end in LF, so we tell git to not
touch them. Should allow a Windows user to clone and run tests without
having to tweak their git settings
2020-03-17 08:48:42 +01:00
alaviss
6e4cd3e5bf .github/workflows: new CI pipeline (#13656)
* .github/workflows: new CI pipeline

As Azure Pipelines went offline, this will be our (temporary?)
replacement. This pipeline covers everything that Azure Pipelines does.

* workflows/ci: disable pipeline

* workflows/ci: properly disable the pipeline

* gitattributes: .txt used in tests should be LF-terminated

This avoids test failures when the compiler was cloned on an OS where
git attempts to convert LF->CRLF.

We target only .txt in tests/ as the minimum required to keep tests
running correctly.

* workflows/ci: re-enable for testing
2020-03-16 23:02:50 +01:00
Andreas Rumpf
955b31a7d9 fixes #13654 2020-03-16 23:00:43 +01:00
Araq
d375120c42 rename sfAlwaysReturn to sfNeverRaises 2020-03-16 19:05:33 +01:00
Andreas Rumpf
5ba5b5202a fixes #13661 (#13664) [backport] 2020-03-16 18:40:17 +01:00
Araq
b9b53b6ca1 fixes #13645 2020-03-16 16:24:50 +01:00
Andy Davidoff
0f672378ab fix .deprecated. object typedef crash (#13643)
* fix .deprecated. object typedef crash
* fixup a test that i don't understand
* disable the test rather than debug ci
2020-03-16 15:08:38 +01:00
Araq
a102eb5ef6 fixes #13646 2020-03-16 14:55:58 +01:00
Araq
3a6b470412 minor code style change 2020-03-16 14:55:58 +01:00
Araq
7205c3ebe2 minor code style changes 2020-03-16 14:55:58 +01:00
cooldome
613ea6e85e fixes #12747 [backport] (#13651)
* fixes #12747
* fix tests
* improve code style

Co-authored-by: cooldome <ariabushenko@bk.ru>
2020-03-16 13:40:40 +01:00
Kartik Saranathan
fe53f6ef4f fix typo (#13660) [ci skip] 2020-03-16 09:07:10 +01:00
Joey
fd3583803e Fix gdb scripts (#13658)
* Fix nim-gdb and rename to nim-gdb.bash
* Add symlink to nim-gdb.bash
* Fix windows debug script
* Add PR suggestions
* Make readlink check easier to maintain/understand
* Swap symlinks
2020-03-16 08:59:16 +01:00
alaviss
ae5094e143 azure-pipelines: walkaround issues with triggers (#13657)
See https://status.dev.azure.com/_event/179641421
2020-03-15 23:44:07 +01:00
Timothee Cour
6e0c06f50e fix #13218: avoid some irrelevant warnings for nim doc,rst2html,--app:lib, + other fixes (#13550)
* fix #13218: avoid some irrelevant warnings for nim doc,rst2html
* suppress warnRedefinitionOfLabel for nim doc
* lots of fixes for UnusedImport warnings
2020-03-13 20:42:41 +01:00
Timothee Cour
380a505507 azure-pipelines: use OSX 10.15 (was just enabled upstream) (#13546) 2020-03-13 14:02:47 +01:00
Araq
9eeb514dda disable nimgame2 for now 2020-03-13 11:50:39 +01:00
Andreas Rumpf
a6682de004 catchable defects (#13626)
* allow defects to be caught even for --exceptions:goto (WIP)
* implemented the new --panics:on|off switch; refs https://github.com/nim-lang/RFCs/issues/180
* new implementation for integer overflow checking
* produce a warning if a user-defined exception type inherits from Exception directly
* applied Timothee's suggestions; improved the documentation and replace the term 'checked runtime check' by 'panic'
* fixes #13627
* don't inherit from Exception directly
2020-03-12 23:44:33 +01:00
Miran
14b2354b7d rename lenTuple and lenVarargs (#13639)
* rename 'lenTuple' to 'tupleLen'

Rationale:
`lenTuple` is a tuple consisting of lengths (e.g. `(1, 5, 0)`),
`tupleLen` is a length of a tuple (e.g. `tupleLen((1, 5, 0) == 3`)

* rename 'lenVarargs' to 'varargsLen'

The same rationale as a previous commit. Consistency.
2020-03-12 20:07:02 +01:00
Clyybber
f0cd50f9c4 Change order of forwarded koch boot command line options, so as to be able to overwrite the nimcache location (#13637) 2020-03-12 16:15:46 +01:00
Timothee Cour
60a3e036f6 fix #13633 fix koch boot crashing regression (#13635) 2020-03-12 11:39:10 +01:00
Clyybber
2bb0ada797 Amend fix for #13633 (#13636) 2020-03-12 11:20:08 +01:00
Clyybber
d84c4bba9b Fix #13633 2020-03-12 11:01:03 +01:00
genotrance
bbc231f8e0 Fix #12676 (#13634) 2020-03-12 08:53:11 +01:00
Kaushal Modi
64995db4fd unicode.split: Fix the splitting when a Rune separator is used [backport] (#13629)
* unicode.split: Fix the splitting when a Rune separator is used [backport]

- Fixes https://github.com/nim-lang/Nim/issues/13628
- Ref https://irclogs.nim-lang.org/11-03-2020.html#20:01:34

* unicode.split: Remove the sepLen based logic.. resulted in wrong jumps
2020-03-12 00:41:45 +01:00
treeform
f2c7152770 Add more JS stuff to dom.nim (#13483)
* Add more JS stuff to dom.nim

* Make all links to docs doc comments.

* Fix minor textContent * space.

* Remove Selection object.

* More work on docs.

* Fixing links.

* Made the links be "see <docs>".
2020-03-11 23:24:56 +00:00
Clyybber
6b3098c378 Make listCmd honor hint:cc:off (#13606)
* Make listCmd honor hint:cc:off

* Tiny cleanup

* Tiny tiny cleanup

* VERY IMPORTANT: --hint:cc:on will overwrite --verbosity:0 :p

* Tiny cleanup

* Stupid

* Move displayProgressCC to where its required

* Tiny cleanup
2020-03-11 23:04:33 +01:00
Miran
70bd41dae0 fix #13310, Deque misbehaves on VM (#13625)
* fix #13310, Deque misbehaves on VM
* use 'when nimVM'
2020-03-11 17:30:36 +01:00
Timothee Cour
281e02fc79 fixes #13558: toDateTime buggy on 29th, 30th and 31th of each month; breaking change: do not use now to compute result, was undocumented and non-sensical (#13565) 2020-03-11 09:47:34 +01:00
Araq
f5f9243cc0 disable chronos testing for now 2020-03-11 09:28:10 +01:00
Araq
3aed8ff432 fixes async regression 2020-03-11 09:26:57 +01:00
Araq
60f8fdcdab fixes #13240 2020-03-11 09:26:57 +01:00
Araq
861a5340fe fixes #13519 2020-03-11 09:26:57 +01:00
Araq
b0684ec425 fixes #12757 2020-03-11 09:26:57 +01:00
Arne Döring
f95eef99a9 add expectIdent to macros (#12778)
* add expectIdent to macros

* apply feedback

* Update lib/core/macros.nim

Co-Authored-By: Clyybber <darkmine956@gmail.com>

* Update texpectIdent2.nim

* Update texpectIdent1.nim

Co-authored-by: Clyybber <darkmine956@gmail.com>
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
2020-03-11 08:27:31 +01:00
めぐみ発動機 (isVowel / GreenWing)
8e3a349561 fixed to jsonArrayEnd comment. (#13624)
typo: start → end
2020-03-11 08:26:10 +01:00
Arne Döring
2f557652d4 fix operators containing percent for VM usage (#13536)
* fixes #13513
* merge tarithmetics in tarithm
2020-03-11 01:01:25 +01:00
Timothee Cour
e64f1c7ee4 koch --nim:pathto/nim boot and koch boot --hint:cc:off now work (#13516)
* `koch boot --hint:cc:off` now works

* `koch --nim:pathto/nim boot` now works; code cleanup
2020-03-11 00:31:34 +01:00
Araq
3b7b017798 fixes #13607 2020-03-10 16:01:13 +01:00
Araq
9e2bce2a8c hotfix: make --useVersion:1.0 work 2020-03-10 16:01:13 +01:00
genotrance
ab5d962b50 Revert "Support cross compiling from host to host (#12859)" (#13591)
This reverts commit e4f7656772.
2020-03-10 15:58:27 +01:00
Andreas Rumpf
090ba1e3a3 fixes #13436 (#13615) 2020-03-10 00:52:46 +01:00
narimiran
7d07897a99 travis now only builds devel docs 2020-03-09 21:16:56 +01:00
Andreas Rumpf
ec5cef13cf fixes #13599 (#13614) 2020-03-09 18:12:52 +01:00
Andreas Rumpf
63af8ae53c fixes #13596 (#13612) 2020-03-09 15:32:38 +01:00
Miran
4aecc6b346 fix #12508, unaligned access on sparc64 (#13594) 2020-03-09 14:08:50 +01:00
Andreas Rumpf
dc94c81cb0 fixes #13605 (#13611) 2020-03-09 13:13:54 +01:00
Andy Davidoff
a693ce7765 surgical fix for #13319 (#13604) 2020-03-08 10:55:19 +01:00
Clyybber
eae31a7f8d Only print the link command when listCmd is active; fix docs (#13603) 2020-03-07 23:53:43 +01:00
Juan Carlos
6a5b3811e7 Add isValidFilename (#13561)
* Add os.isValidFilename

* Add os.isValidFilename

* Peer Review Feedbacks https://github.com/nim-lang/Nim/pull/13561#discussion_r388013139

* Peer Review Feedbacks https://github.com/nim-lang/Nim/pull/13561#issuecomment-595259568

* Add since to const

* Update the documentation comment

* Update the changelog

* Update lib/pure/os.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>

* Update lib/pure/os.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>

* Peer Review Feedbacks, Add more Tests

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
2020-03-07 14:10:22 +00:00
Zed
e056298ceb Implement file streaming for httpclient's MultipartData (#12982)
* Add `uploadFile` to POST files by streaming them

* Use constant for \c\L

* Formatting

* Remove uploadFile

* Implement MultipartData file streaming

* Remove unnecessary var annotations

* Call string on TaintedStrings

Fixes #12789

* Move cl constant to httpcore

* Fix `request` inconsistencies

* Update documentaion

* Clean up

* Skip multipart formatting when there's 0 entries

* Remove extraneous `cl` from multipart formatting

* Update MultipartData `$` to match old behaviour

* Update comment

* Address comments
2020-03-06 18:55:45 +00:00
Andrea Ferretti
7ae0811818 Fix #13573 and #13574 (#13575)
* Fix https://github.com/nim-lang/Nim/issues/13573 and https://github.com/nim-lang/Nim/issues/13574

* Restored asynchttpserver
2020-03-06 18:38:56 +00:00
alaviss
4bd388ad58 Revert "nimsuggest: don't add CRLF to replies (#13545)" (#13597)
This reverts commit a974684b14.

The CRLF was to separate between each response, and removing them causes
the responses to not be splitted correctly.

I didn't notice that it was in a loop when I made the #13545.
2020-03-06 19:29:28 +01:00
Dominik Picheta
ec8a17cc86 Revert broken asynchttpserver FutureStream additions.
As discussed in #13394, these changes cannot work. Reverted via

```
git revert --no-commit 5bf571f061
git revert --no-commit abd660c407
git revert --no-commit 955465e5f4
git commit
```
2020-03-06 11:52:30 +01:00
Timothee Cour
b80d293a3f close #12704 by adding a test (tuple codegen error) (#13592)
* close #12704 by adding a test

* move test to tests/metatype/ttypedesc2.nim
2020-03-06 08:55:53 +01:00
Andreas Rumpf
cb0f7c5d9e Removed simpleGetOrDefault (#13590) 2020-03-05 21:03:39 +01:00
Andreas Rumpf
83e715c5b6 fixes #5170 (#13589)
* fixes #5170

* make tests green
2020-03-05 16:02:34 +01:00
Andreas Rumpf
62c113ebc7 fix #13579 joinPath("/foo/", "../a") is now /a (#13586) 2020-03-05 15:31:22 +01:00
Varriount
357edd86b4 fix nightlies builds on Windows (#13587)
Before the files that should have been ignored weren't ignored
because of different dir separator ('\' vs '/') on Windows.
2020-03-04 14:44:42 -05:00
alaviss
a974684b14 nimsuggest: don't add CRLF to replies (#13545)
This is already sent by replTcp after the message is sent.
2020-03-04 15:56:40 +01:00
Andreas Rumpf
a0eca75182 sink parameter inference for types that have destructors (#13544)
* ensure capitalize doesn't take an inferred sink parameter

* sink parameter inference: first version, for now disabled. Changed that sink parameters can be consumed multiple times in order to adhere to our spec.

* sink inference can now be disabled with .nosinks; sometimes for proc type interop this is required

* fixes yet another critical DFA bug

* better implementation that also understands if expressions etc

* document sink parameter inference and allow for global disabling
2020-03-04 14:28:53 +01:00
Andreas Rumpf
614fb7567c std/compilesettings implementation (#13584)
* Implement compileSetting() and compileSettingSeq()
* Change from magic to vmop
* better design for querySetting

Co-authored-by: genotrance <dev@genotrance.com>
2020-03-04 13:46:42 +01:00
Juan Carlos
0809098971 Nimpretty Fix negative indent breaks code (#13580) 2020-03-04 10:27:52 +01:00
Timothee Cour
9fa070b1dc fix hintSuccess: out was wrong for nim doc without -o flag (#13569) 2020-03-04 10:26:56 +01:00
Miran
9961d1f67d fix #13531 by adding a test (#13581) 2020-03-04 10:25:59 +01:00
hlaaftana
34c16f5eca fix #13409: Document as infix operator (#13570) 2020-03-04 07:50:36 +01:00
narimiran
3ca8f0bde6 [ci skip] important_packages: change the order in commented out packages too 2020-03-04 07:15:34 +01:00
Araq
8705ee7015 ARC hotfix; proper destruction of seqs and strings after a move 2020-03-03 23:03:33 +01:00
genotrance
f8175688a3 Fix docgen snippet numbering (#13507) 2020-03-03 20:52:16 +01:00
Miran
e8c057fb27 important_packages: change the order of arguments in the template (#13577)
Leads to a cleaner and less confusing code - an empty command
doesn't mean 'nimble test' anymore.
2020-03-03 16:25:59 +01:00
Arne Döring
eb42f38088 Remove dead magics (#13551) 2020-03-03 12:42:43 +01:00
Timothee Cour
31332bca45 workaround refs #13563 freebsd CI (#13564) 2020-03-02 22:30:41 -05:00
Timothee Cour
451b724c40 make genericParams support static[T] generic params (#13433)
* make genericParams support static[T] generic params

* WrapStatic => StaticParam
2020-03-02 18:05:14 +01:00
Timothee Cour
27241fda23 fix #13528 nimgrep --word now works better with operators (#13537) 2020-03-02 17:55:17 +01:00
PMunch
05e9473f80 Add signatures object to jsondoc for routine types (#13530)
jsondoc is meant to be read by computers, but yet the signatures of
procedures where simply a string of the whole thing. This adds a
signature object that unpacks this information into an object so it's
easier to analyse the documented signatures.
2020-03-02 17:52:42 +01:00
Timothee Cour
653de5f27a fix broken nim CI, disable blscurve (#13555) 2020-03-02 10:26:10 +01:00
Timothee Cour
22d1ba4be7 fixes #13543 and added times.isLeapDay (#13547) 2020-03-01 21:56:20 +01:00
hlaaftana
525ab5a497 Document import/include outside of top level semantics (#13548) 2020-03-01 21:52:29 +01:00
cooldome
0f1a4ac96c make it possible to pass linker options for vcc (#13535) [backport] 2020-02-29 18:57:00 +01:00
cooldome
c79df2fb6a EndsInNoReturn in expressions extension, fixes #13490 (#13520)
* fix #13490
2020-02-28 09:55:06 +00:00
cooldome
25dc5f76e0 fixes #12627 (#13521)
* fixes #12627
2020-02-28 09:54:17 +00:00
Timothee Cour
1056f9ecff properly handle note override logic/verbosity/config/cmdline using modifiedyNotes, cmdlineNotes 2020-02-27 13:22:18 +01:00
Timothee Cour
c1cbf94e2d remove isCmdLine; use passCmd1 2020-02-27 13:22:18 +01:00
Timothee Cour
ce36fdc897 correctly honor cmdline --hint:conf:on/off ; correctly show Conf hints in order 2020-02-27 13:22:18 +01:00
Ganesh Viswanathan
96bffadf60 Fix #9405 - cfg and nims run in sync 2020-02-27 13:22:18 +01:00
Timothee Cour
73f5f1e80c save another 33s of CI for tests/gc/gcleak.nim 2020-02-27 13:19:31 +01:00
Timothee Cour
fdc5925cbd CI tests run faster: save 120s in azure machines, 335s on local OSX 2020-02-27 13:19:31 +01:00
Timothee Cour
9b8c9abead revert changes to tests/gc/gcleak2.nim 2020-02-27 13:19:31 +01:00
Timothee Cour
81b0718a8f make CI tests faster + more precise 2020-02-27 13:19:31 +01:00
solo989
e84e01cb8c Update pegs.nim to work at compiletime. No range errors. (#13459) 2020-02-27 11:08:57 +01:00
Timothee Cour
6a0e87eb38 cleanup Ordinal (#13501) 2020-02-27 10:43:13 +01:00
Timothee Cour
42dad3a836 tables/sharedtables/intsets/etc: fix #13496, #13504, #13505; add lots of tests (#13498) [backport]
* fix #13496 handle tombstones
* add test
* more tests
* fix #13504; add SharedTable tests
* fix #https://github.com/nim-lang/Nim/issues/13505 intsets.missingOrExcl silently gave wrong results sometimes
* add test for tintsets
2020-02-26 22:07:09 +01:00
Miran
9a93f73983 docgen: don't create compiler's docs + cleanup (#13509) 2020-02-26 20:37:27 +01:00
Andreas Rumpf
d55bbefdcc added operateOn to sugar.nim to give Nim the chaining mechanism it de… (#13092)
* implemented the with stdlib module as specified in https://github.com/nim-lang/RFCs/issues/193
* change sugar.outplace to sugar.dup according to https://github.com/nim-lang/RFCs/issues/193
* changelog update
2020-02-26 20:36:06 +01:00
Kaushal Modi
f091b5a0ee xmltree: Make indentation consistent with any num of children nodes (#13482)
Ref: https://forum.nim-lang.org/t/5972
2020-02-26 11:41:44 +01:00
Timothee Cour
0c312ad898 fix #13455 ; joinPath(a,b) now honors trailing slashes in b (or a if b = "") (#13467)
* fix #13455 ; joinPath(a,b) now honors trailing slashes in b (or a if b = "")
* fix test windows
2020-02-26 11:25:27 +01:00
Timothee Cour
11db28bc61 runCI: logs now show CPU/OS/etc info to be self contained (#13486) 2020-02-26 10:44:23 +01:00
Timothee Cour
bd90199a2f fix #8312 --hints:off and --warnings:off now honored everywhere (#13489) 2020-02-26 10:26:47 +01:00
Juan Carlos
94b0d6bb63 Documentation staticRead maximum file size limits (#13485) 2020-02-26 10:01:23 +01:00
Arne Döring
5d2483fb64 fix #13479 (#13503) 2020-02-26 09:51:07 +01:00
Kaushal Modi
e4ed19c12f [backport] tut1: Update the proc overloading examples (#13497) [skip ci] 2020-02-25 21:19:51 +01:00
Timothee Cour
db540a0223 fix #13449 texitcode flaky on windows (#13487) 2020-02-25 17:49:16 +01:00
narimiran
c444ab9a54 make devel green again: tnetdial still doesn't work on Travis 2020-02-25 08:46:08 +01:00
Timothee Cour
1cf5c280e3 only enable linenoise for -d:nimUseLinenoise (#13478)
* only enable linenoise for -d:nimUseLinenoise

* fixup
2020-02-24 11:06:39 +01:00
hlaaftana
84e78b4ffc Minor doc change in macros, future -> sugar (#13475) [ci skip] 2020-02-24 09:57:15 +01:00
Miran
3e8858d694 add more files to the ignore list, hopefully fixes nightlies on windows (#13474) 2020-02-24 09:41:28 +01:00
Andrey Makarov
3dad130034 fix 3 minor bugs in joinPath (see #13455) (#13462) [backport] 2020-02-23 20:22:46 +01:00
hlaaftana
13d292786e Remove genToArray in jsgen, a PHP remnant (#13466) 2020-02-22 20:04:46 +01:00
Lee Matos
c11b91d52d Update advopt.txt to include link to nim cache docs (#13464) 2020-02-22 09:09:04 +01:00
Timothee Cour
a43583f9c8 relativePath("foo", "foo") is now ".", not "" (#13452) 2020-02-22 09:07:53 +01:00
hlaaftana
1276e386fe Consider proc as a pointer type in options (#13460)
* Consider proc as a pointer type in options

* Add version annotation for SomePointer having proc in options

* Log procs as pointers for options in changelog
2020-02-21 23:14:55 +01:00
Andreas Rumpf
0d219d2c67 fixes #13457 (#13458) 2020-02-21 21:06:41 +01:00
Timothee Cour
e05aca8734 make unzip faster: seq[i]=val can be 7X faster than seq.add(elem) (#13448) 2020-02-21 17:26:52 +01:00
Araq
1d90d9816b fixes #13444 2020-02-21 16:58:30 +01:00
Joey
3667fd9f42 Make gdb script work on mac and linux; add windows gdb script (#13453) 2020-02-21 08:53:05 +01:00
genotrance
7a2b623d2a Fix #8648 - use parent streams to avoid hang (#13445) 2020-02-20 23:04:48 +01:00
Kaushal Modi
bb777fef76 Add sequtils.unzip to complement sequtils.zip (#13429) 2020-02-20 19:15:34 +01:00
Manav
479f4ca6a3 Fixed non-working examples in Manual: Exception Handling (#13424) 2020-02-20 15:16:19 +01:00
Clyybber
87dd19453b Remove testutils (#13435) [backport] 2020-02-19 23:02:08 +01:00
Timothee Cour
8c22518d67 [backport] pseudorandom probing for hash collision (#13418) 2020-02-19 17:19:55 +01:00
Timothee Cour
273a93581f fix incorrect lenTuple implementation (#13423) 2020-02-19 11:07:17 +01:00
alaviss
d1f9f11245 manual: documents changes regarding dynlib (#13425)
* manual: documents changes regarding dynlib

Closes #13416

* manual: clean up sentence phrasing
2020-02-18 19:44:54 +01:00
cooldome
046bb0b881 stdlib/system: add sink and move (#13283) 2020-02-18 19:43:26 +01:00
Nな人(N na hito)
8f73753a2d Update LICENSE (#13421) 2020-02-17 18:40:39 +01:00
Ico Doornekamp
73553621a1 Improved assertion error messages on usage of JsonNode iterators on wrong kinds (#13389) 2020-02-17 09:00:25 +01:00
Khronos
006fe4cfc4 Fix vertical tab in JSON. (#13399)
'\v' is not injected in JSON anymore
2020-02-17 00:39:19 +01:00
Juan Carlos
ba25f849a6 Add browsers.osOpen (#12901)
* Add osOpen alias for the operating system specific open command

* Add `--git.devel` option to the documentation
remove unused import (#12900)

fix json regression D20191212T144944 (#12902) [backport]

Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#issuecomment-565851680

Merge branch 'devel' of https://github.com/nim-lang/Nim into osopen

Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#issuecomment-565851680

Update lib/pure/browsers.nim

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>
Peer Review Feedback https://github.com/nim-lang/Nim/pull/12901#discussion_r358492316

allow typed/untyped in magic procs (#12911)

NaN floatFormat with clang_cl  (#12910)

* clang_cl nan floatFormat

* format

add $nimeq for gdb (#12909)

ARC: cycle detector (#12823)

* first implementation of the =trace and =dispose hooks for the cycle collector
* a cycle collector for ARC: progress
* manual: the .acyclic pragma is a thing once again
* gcbench: adaptations for --gc:arc
* enable valgrind tests for the strutils tests
* testament: better valgrind support
* ARC refactoring: growable jumpstacks
* ARC cycle detector: non-recursive algorithm
* moved and renamed core/ files back to system/
* refactoring: --gc:arc vs --gc:orc since 'orc' is even more experimental and we want to ship --gc:arc soonish

Cleanup leftovers of #12911(#12916)

Fix single match output (#12920)

fixes #12899 (#12921)

* fixes #12899

* fixes regression: destroy global variables in reverse declaration order, closureleak test relies on it

Implement NixOS distro check (#12914)

Better case coverage error message for alias and range enum (#12913)

fix error in assertions document (#12925) [backport]

fix cmdline bugs affecting nimBetterRun correctness (#12933) [backport]

fix #12919 tasyncclosestall flaky: Address already in use (#12934)

system.reset is no longer magic (#12937)

It has now means setting x to default for new and old runtime alike
Fix #12785 (#12943)

* Fix #12785 and add test

* better variable name

update documentation for `closureScope` and `capture` (#12886)

fixes #12735 on osx, call dsymutil for debug builds (#12931)

* fix #12735 osx: dsymutil needs to be called for debug builds
* also write dsymutil command to extraCmds in json build file

Auto-initialize deques (#12879)

case coverage error message for `char` (#12948)

lenVarargs: number of varargs elements (#12907)

docs: tiny style improvements

added guidelines for evolving Nim's stdlib

fixes a bug that kept sugar.collect from working with for loop macros [backport]

fixes #12826

fixes a regression

a better bugfix

fixes a test case

fixes a silly regression

fixes the distros.nim regression

ported channels to ARC

ported osproc.nim to ARC

ported re.nim to ARC

ARC: default to a shared heap with --threads:on

osproc: fixes regression

fixes another regression

fixes #12945 (#12959)

minor refactorings

Fixes stackoverflow links in readme (#12963) [backport]

Allow customize Host header
[ci skip] docfix .. < => ..< (#12981) [backport]

parsecfg: retain CRLF line breaks, fixes #12970 (#12971)

generic stack trace overriding mechanism (#12922)

* libbacktrace support

* switch to a generic stack trace overriding mechanism

When "nimStackTraceOverride" is defined, once of the imported modules
can register its own procedure to replace the default stack trace
generation by calling `registerStackTraceOverride(myOwnProc)`.

Tested with `./koch boot -d:release --debugger:native -d:nimStackTraceOverride --import:libbacktrace`
for the compiler itself and `./bin/nim c -r -f --stacktrace:off --debugger:native -d:nimStackTraceOverride --import:libbacktrace foo.nim`
for an external program.

* make the StackTraceOverrideProc {.noinline.}

Added fix for handling TaintedStrings in streams and httpclient (#12969)

* Added fix for taint mode in streams and httpclient

* Removed taintMode export from system.nim

Check pqntuples > 0 in getValue. Fixes #12973 (#12974)

c_fflush() the rawWrite() buffer (#12987)

Stack traces on an unbuffered stderr get out of sync with line-buffered
stdout - usually on Windows terminals or CI logs. This fixes it by
calling C's fflush() on the output buffer in the procedure used for
printing stack traces.
fixes #12989

Revert "fixes #12989"

This reverts commit 928c2fee06.

fixes #12965 (#12991)

fixes #12989 (#12992)

* fixes #12989
* Revert "remove unwanted changes"

This reverts commit 501829732a.

fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport]

--exception:goto switch for deterministic exception handling (#12977)

This implements "deterministic" exception handling for Nim based on goto instead of setjmp. This means raising an exception is much cheaper than in C++'s table based implementations. Supports hard realtime systems. Default for --gc:arc and the C target because it's generally a good idea and arc is all about deterministic behavior.

Note: This implies that fatal runtime traps are not catchable anymore! This needs to be documented.
fix #12985 {.push.} now does not apply to generic instantiations (#12986)

Sink to MemMove optimization in injectdestructors (#13002)

remove default argument for readLines (#12807) [backport]

fixes #12978 (#13012)

Fix typo (#13015) [backport]

fixes #12961 (#13019)

fixes #12956 (#13020)

fix #12988 (#13022)

fix #12988
Fixes #13026 (#13028)

fixes #12964 (#13027)

fixes #13032

VM: support importc var, ptr/pointer types, cast int <=> ptr/pointer (#12877)

* VM: allow certain hardcoded special var variables at CT
* VM: allow all importc var, cast[int](ptr)
* fix tests tests/vm/tstaticprintseq.nim, tests/cpp/t8241.nim
* VM: == works for ptr/pointer nodes
* bugfix: ==, cast now also works for pointer, not just ptr
* VM supports cast PtrLikeKinds <=> PtrLikeKinds / int
* improve cname handling
* fixup + bug fix
* VM: support cast from ref to int
* address comment: opcLdGlobalDeref => opcLdGlobalDerefFFI
* defensive check against typ == nil

fix enumtostr crash for enum-range (#13035)

fixes #13013, reverts previous changes to readLines() (#13036) [backport]

* Revert "remove default argument for readLines (#12807) [backport]"

This reverts commit c949b81efd.

reprjs: style changes

fixes #12996

Rst parser respect `:start-after:` and `:end-before:` in `include` directive (#12972)

* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module

Allow `-o` option for `buildIndex` (#13037) [backport]

Addressing #12771

This is also included in the docgen documentation [here](https://nim-lang.org/docs/docgen.html) but its not respected as reported in the issue.
[cleanup] remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits (#13041)

* remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits

* D20200105T085828 fix super strange bug that causes CI to fail: builds.sr.ht with: `Error: Settle timed out after 120 attempts`

Continue #13002 (#13021)

testament/important_packages dont run hts (#13052)

Modify the test command for nimly (nimble-package) (#13053)

clean up deprecated stuff and unused imports in tests (#13059)

--styleCheck:hint now works (#13055)

[easy] --hint🔗on now shows link cmd instead of nothing (#13056)

* --hint🔗on now shows link cmd instead of nothing

* update doc for --listCmd

add pqserverVersion,pqconnectionNeedsPassword,pqconnectionUsedPassword (#13060)

basename supports pragmaexpr (#13045)

* basename supports pragmaexpr

* update changelog

distinctBase type trait for distinct types (#13031)

make SuccessX show project file + output file (#13043)

* make SuccessX show project file + output file
* address comments
* fix test and add `result.err = reNimcCrash` otherwise hard to see where reNimcCrash used
* address comments

move entries from the wrong changelog file [ci skip]

fix crash due to errant symbols in nim.cfg (#13073) [backport]

Deleted misplaced separator (#13085) [backport]

Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
take the one good idea from --os:standalone and enable it via -d:StandaloneHeapSize (#13077)

remove all remaining warnings when build nim (with -d:nimHasLibFFI) (#13084)

* cleanup deprecations in evalffi + elsewhere

* remove dead code getOrdValue64

Use '__noinline' instead of 'noinline' for N_NOINLINE gcc attribute, this prevents clashes with systems where 'noinline' might be already defined (#13089)

Fix error check code in osproc (#13090) [backport]

fixes #13072; no test case because it will be added later with more exception handling related bugfixes

fixes #13070

typetraits: fixes #6454; genericParams; added lenTuple; added tuple type get (#13064)

[backport] system/io.nim fix wrong documentation comment [ci skip]

fixes an asyncftpclient bug; refs #13096 [backport]

System cleanup, part 1 (#13069)

* system.nim: mark what every .pop does

* system.nim: un-nest when statements

[backport] fix #12813, fix #13079 (#13099)

Correctly remove a key from CountTable when it is set to zero.
more arc features (#13098)

* config update
* ARC now supports 'repr' and 'new' with finalizers is supported

Remove some unused/disabled OpenSSL functions (#13106)

Add link to posix_utils.html in posix.nim (#13111)

VM FFI: write(stderr, msg) and fprintf(cstderr, msg) now work at CT (#13083)

fix the ftp store function read the local file bug (#13108) [backport]

* Update asyncftpclient.nim

When use newStringOfCap function not have assign memory for the string data,so if use this address the fault is rasise.

* complelete the bugfix

fix rtti sizeof for varargs in global scope (#13125) [backport]

fixes #13122 (#13126)

* fixes #13122

* moved tests to where they belong

fixes #13112 (#13127)

* improve line error information

* fixes #13112

Expose more openSSL methods. (#13131)

fixes #13100 nim doc now treats `export localSymbol` correctly (#13123) [backport]

* fix #13100 nim doc now treats `export localSymbol` correctly
* use owner instead

fixes #13119 (#13128)

* fixes #13119
* fixes a regression

fixes #13105 (#13138)

fixes #10665 (#13141) [backport]

pass platform argument only if vccexe is used (#13078)

* pass platform only if vccexe is used
* fixes #12297

fixes #13104 [backport] (#13142)

fixes #9674 [backport] (#13143)

Fix typo in doc/destructors.rst (#13148)

Added 'ansic' os support for minimal (embedded) targets (#13088)

* os:any implementation
* os:asny: omit flock/funlock calls in echoBinSafe
* Disabled default "unhandled expection" reporting for `--os:any` to reduce
code size. Added unhandledExceptionHook instead which can be used to get
a notification from Nim and handle it from the application.

System cleanup, part 2 (#13155)

* create basic_types, arithmetics, exceptions, comparisons
* create setops.nim
* create memalloc.nim
* create gc_interface.nim
* create iterators_1.nim

export normalizePathEnd (#13152)

successX now correctly shows html output for `nim doc`, `nim jsondoc`; fix #13121 (#13116)

* successX now correctly shows html output for nim doc
* fixes #13121
* fixup hintSuccessX to be less weird

ARC: misc bugfixes (#13156)

* fixes #13102
* closes #13149
* ARC: fixes a move optimizer bug (there are more left regarding array and tuple indexing)
* proper fix; fixes #12957
* fixes yet another case object '=' code generation problem

CI fix timeout error (#13134)

Remove obsolete code from osalloc (#13158)

style fix: change 'JS' to 'js' to make it consistent (#13168)

Working towards arc codegen (#13153)

fixes #13029
fixes #12998 nim doc regression (#13117)

fix tsizeof3 for aarch64 (#13169)

Cleanup DFA (#13173)

Fix docs (#13176)

fixes #13095 (#13181)

* fixes #13095

* fix typo

make case-object transitions explicit, make unknownLineInfo a const, replace a few magic numbers with consts (#13170)

ARC works for async on Windows (#13179)

make sink operator optional (#13068)

* make sink operator optional

* bug fix, add changelog entry

* Trigger build

* fix one regression

* fix test

* Trigger build

* fix typos

Fix docs for subdirs too (#13180)

* Fix doc subdirs
* Extract to helper proc, and fix on windows

followup on #10435 : should be diff, not show (#13162)

fixes #13157

refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}  (#13136)

* refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}
* put back NIM_EXTERNC for N_LIB_EXPORT; causes issues with compilerproc

fixes #13144 (#13145)

* fixup: genscript now does not copy nimbase.h but uses -I$nim/lib

times: toUnixFloat, fromUnixFloat (#13044)

maybe: allows optional chaining of field access and indexing when LHS i snil (#13023)

* maybe: allows optional chaining
* fix tools/kochdocs.nim
* improve semantics to distinguish valid from invalid values
* for now, wrapnil, isValid, unwrap are not exported

fix docs + API for fieldPairs, fields (#13189)

more on arc codegen (#13178)

* arc codegen for union type

* add more tests

* fix offsetof

* fix tsizeof test

* fix style

Add link to packaging.html (#13194)

Fixes #13186 (#13188)

fixes #13195

revert last commit

Merge branch 'devel' of https://github.com/nim-lang/Nim into devel

Revert "fixes #13195"

This reverts commit cd7904f2b2.

fixes #13110 (#13197)

fixes #13195 (#13198)

* fixes #13195

* extra fix

* fix typo

compiler/ccgtypes: hide exportc proc unless it has dynlib (#13199)

This hides most of stdlib's internal functions from resulting
binaries/libraries, where they aren't needed on *nix. Static libraries
are not affected by this change (visibility doesn't apply to them).
fix range[enum] type conversion (#13204) [backport]

Idxmin & idxmax, continuation (#13208)

* Add idxmin() which returns the index of the minimum value

* Add idxmax() which returns the index of the maximum value

* Add tests for idxmin()

* Add tests for idxmax()

* Remove initialization of result = 0

* Adds overloading for arrays (no enums indexed arrays yet)

* Add support for enum index arrays

* Fix tests with enum

* Fix tests for idxmax

* Change names of the procedures to minIndex and maxIndex

* address Araq's comments:

- remove 'array' versions
- add .since pragma
- return 'int' instead of 'Natural'
- add changelog entry

Co-authored-by: Federico A. Corazza <20555025+Imperator26@users.noreply.github.com>

fix #13211 relativePath("foo", ".") (#13213)

fixes a critical times.nim bug reported on IRC [backport] (#13216)

httpclient, maxredirects to Natural, newHttpClient/newAsyncHttpClient add headers argument instead of hardcoded empty (#13207)

added note to re constructor regarding performance (#13224)

Since I was new to regex I did not know that there is a compilation going on with ``re"[abc]"`` constructor and so I followed the other examples in the docs blindly, that is I just put the constructor directly in the arguments of match, find, etc., which was inside a loop and then wondered why my performance was so bad. Of course putting it outside the loop made it vastly more performant. People like me would benefit from the small note I added I would think :)
[backport] Documentation Fix #12251 (#13226) [ci skip]

[backport] times/getClockStr(): fix mistake in doc (#13229) [ci skip]

new os.isRelativeTo (#13212)

[backport] Fix typo and improve in code-block of 'lib/pure/parseutils.nim' (#13231) [ci skip]

[backport] fix #11440, add docs to isNil for seq types needing nilseq (#13234) [ci skip]

VM: allow overriding MaxLoopIterations without rebuilding nim (#13233)

kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes (#13221)

* kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes
* fixup after #13212 isRelativeTo got merged

fix lots of bugs with parentDir, refs #8734 (#13236)

Unexport even more symbols (#13214)

* system/gc: don't export markStackAndRegisters

* compiler/cgen: unexport internal symbols

As these functions are Nim-specific walkaround against C's optimization
schemes, they don't serve any purpose being exported.

* compiler/cgen: don't export global var unless marked

* compiler/ccgthreadvars: don't export threadvar unless marked

* tests/dll/visibility: also check for exports

This ensure that these changes don't break manual exports.

* compiler/cgen: hide all variables created for constants

* compiler/ccgtypes: don't export RTTI variables

* compiler/ccgexprs: make all complex const static

* nimbase.h: fix export for windows

* compiler/cgen, ccgthreadvars: export variables correctly

For C/C++ variables, `extern` means that the variable is defined in an
another unit. Added a new N_LIB_EXPORT_VAR to correctly export
variables.

Removed lib/system/allocators.nim. seqs_v2 and strs_v2 now uses allocShared0. (#13190)

* Cleanup, remove lib/system/allocators.nim. seqs_v2 and strs_v2 now use
allocShared0 by default.

* Fixed -d:useMalloc allocShared / reallocShared / deallocShared. These now use the alloc/dealloc/realloc implementation that also takes care of zeroing memory at realloc.

* Removed debug printfs

* Removed unpairedEnvAllocs() from tests/destructor/tnewruntime_misc

* More mmdisp cleanups. The shared allocators do not need to zero memory or throw since the regular ones already do that

* Introduced realloc0 and reallocShared0, these procs are now used by
strs_v2 and seqs_v2. This also allowed the -d:useMalloc allocator to
drop the extra header with allocation length.

* Moved strs_v2/seqs_v2 'allocated' flag into 'cap' field

* Added 'getAllocStats()' to get low level alloc/dealloc counters. Enable with -d:allocStats

* *allocShared implementations for boehm and go allocators now depend on the proper *allocImpl procs

[backport] documentation: Add channels examples (#13202) [ci skip]

[backport] Make all parseutils examples auto-checking (#13238)

- Also fix one example's output (ikString -> ikStr, ikVar instead of ikExpr)
Updated 'nim for embedded systems' section to use --os:any and --gc:arc (#13237)

* Updated 'nim for embedded systems' section to use --os:any and --gc:arc

* Added section about size optimization to embedded systems

Remove name attribute from docutils.nimble (#13239)

Fixes asyncftpclient multiline reading, fixes #4684 (#13242)

Previously, the 4th character of `result` was checked for `'-'` every time, instead of each new line.

Also made it work for taint mode.
Fix typo for literal `[` (#13243)

The literal value for the `tkBracketLe` token was incorrectly set to `]` rather than `[`. I've had a quick glance at the code and it doesn't look like this change will affect anything at all, but I haven't tested yet - let's see if the CI explodes...
Add "origin" to window.location (#13251)

Add "origin" to window location: https://www.w3schools.com/jsref/prop_loc_origin.asp
nim dump: add libpath (#13249)

contributing docs: symbols need package prefix; changed allocStats to nimAllocStats (#13247)

testament/azure: major rewrite (#13246)

This commit features a major rewrite of Azure Pipelines integration,
turning the spaghetti it originally was into something maintainable.

Key changes:
- No longer requires a ton of hooks into testament.
- Results are now cached then bulk-uploaded to prevent throttling from
  Azure Pipelines, avoiding costly timeouts.
- A low timeout is also employed to avoid inflated test time.
- The integration is now documented.
Cleaned up mmdisp.nim, moved implementations into lib/system/mm/ (#13254)

make goto based exceptions available for 'nim cpp' (#13244)

* make goto based exceptions available for 'nim cpp'
* optimize seq.add to be comparable to C++'s emplace_back

ARC: remove unnecessary code

ARC: optimize complete object constructors to use nimNewObjUninit

make nre compile with --gc:arc

Rename isNilOrWhitespace to isEmptyOrWhitespace and make it use allCharsInSet (#13258)

* Rename isNilOrWhitespace to isEmptyOrWhitespace

* Make isEmptyOrWhitespace use allCharsInSet(Whitespace)

Clearer final objects error; fixes #13256 (#13257)

scrollTop must be settable (#13263)

* scrollTop must be assignable

Make scrollTop settable

* add missing export

fixes #13219 (#13272)

fixes #13281 (#13282)

* fixes ##13281

* add comment to test

unittest add resetOutputFormatters proc (#13267)

* add resetOutputFormatters

* remove space

* resolve comments

TlSF Alloctor: use less memory for --gc:arc (#13280)

Tiny since cleanup (#13286)

nimv2 widestring indexing (#13279)

Repr v2 progress (#13268)

* progress on repr_v2

* repr progress

* add ref objects with distrinct

* fix failing tests

refactor htmldocs; gitignore it

removed unused import

fix stdout(etc) for emscripten

csize => csize_t for sysctl

Thread attributes should be destroyed using the pthread_attr_destroy() (#13293)

On some OSes (such as FreeBSD or Solaris), pthread_attr_init allocate
memory. So it is necessary to deallocate that memory by using
pthread_attr_destroy.
fix critical bug discovered by #11591 (#13290) [backport]

miscellaneous bug fixes (#13291)

* fix for emscripten etc

* add testcase for #13290

* replace deprecated isNilOrWhitespace

CT FFI: fix for windows; fix case transition; error msg shows more useful context (#13292)

* evalffi: fix case transition
* evalffi: fix for windows
* evallffi: `cannot import` errmsg now also shows which library it tried to import symbol from

refs #8391 std/os now shows runtime context for raiseOSError exceptions (#13294)

* refs #8391: fix errmsg for setCurrentDir

* raiseOSError calls for copyFile

* refs #8391 std/os now shows runtime context for raiseOSError exceptions

build_all.sh: building csources 5X faster thanks to make -j (#13300)

* build_all.sh: building csources 5X faster thanks to make -j
* fix for freebsd
* use OS-dependent formula to get number of logical cores
* make is an optional dependency

Fix capture for object types (#13315)

* Fix capture for object|tuple|... types

* Add test case

Quote nim executable before executing. (#13316) [backport]

In case nim executable is located in PATH containing spaces.

fixes #13311
ReSync with devel

Make build_all.sh more portable and a bit simpler (#13308)

koch: enable checks in the compiler when running CI (#13323)

fix #13132 tnetdial (#13318)

enable testing -d:nimHasLibFFI mode (#13091)

Fix #10717, fix #13284 (#13307)

Fixed codegen for constant cstring with --gc:arc (#13326)

* Fixed codegen for constant cstring with --gc:arc, fixes  #13321

* Added test for #13321

Option to allow the request body to be processed outside the asynchttpserver library. (#13147)

Allow the request body to be processed outside the asynchttpserver library to break big files into chunks of data. This change does not break anything.

build_all.sh update (#13320)

* Don't overload the system, don't crash when you can't determine the CPU count and don't rely on bash

* Extract to variable

* Limit number of spawned jobs for systems with weak IO

* Use proper arithmetic braces

contributing.rst: Add a special rule for 'outplace'-like features

[backport] -d:danger should imply -d:release (#13336)

nim secret: support linenoise when available (#13328)

fix #13150 `nim doc --project` now works reliably (#13223)

* fix #13150 `nim doc --project` works with duplicate names and with imports below main project file

* add to help; fixup after #13212 isRelativeTo got merged
* fix test tests/compilerapi/tcompilerapi.nim
* remove nimblePkg field; compute on the fly instead
* kochdocs: compiler docs now under compiler/
* --docRoot now has smart default: best among @pkg, @path

make monotimes have zero overhead if you don't use it (#13338) [backport]

fix #13349 regression: isNamedTuple now works with generic tuples (#13350)

fixes #13269 (#13344)

adding sqlite3 backup functions (#13346)

* adding sqlite3 backup functions

* changing sleep to sqlite3_sleep to prevent clashes

Added a basic example how to handle a Post request. (#13339)

* Added a basic example how to handle a Post request.

They were also made minor cosmetic changes.

* Minor fixes suggested by Yardanico

* Fixed a wrong value in chunkSize constant.

* Re-added the request.body for compatibility!

replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple in dollars.nim (#13347)

* replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple

* fix for bootstrap

fix #13182: `proc fun(a: varargs[Foo, conv])` now can be overloaded (#13345) [backport]

miscellaneous bug fixes (part 3) (#13304)

* fix deprecation; fix indentation

* git clone: use -q

* fix Warning: pragma before generic parameter list is deprecated; fix typo

* bugfix: sysTypeFromName("float64") was never cached

testament: introduce 'matrix' for testing multiple options (#13343)

printing float values will have one more digit. (#13276) [backport]

* printing float values will have one more digit. Fixes #13196

[backport] fix #13352

[backport] remove 'CountTable.mget' (#13355)

It didn't work, and it was an oversight to be included in v1.0.
fix #6736: templates in unittest now show actual value (#13354)

Revert "printing float values will have one more digit. (#13276) [backport]" (#13363)

This reverts commit b2c6db97f9.
Add sideEffect pragma to importC procs in posix, winlean and time module (#13370)

* Add sideEffect pragma to procs in winlean
* Add sideEffect pragma to procs in posix
* Add test for #13306
* Add sideEffect pragma to procs in times
* Fixes #13306
fixes #3339 by documenting the limitations of case-statement (#13366)

fixes #13314 (#13372)

testament: this now works: "testament r /abspath/to/test.nim" (#13358)

fix `is` with generic types; fix `genericHead(Foo[T])` (#13303)

* fix #9855, fix #9855, fix genericHead
* render TTypeKind via toHumanStr

fix #13255 (#13275) [backport]

remove outplace version of 'merge' for CountTables (#13377)

* remove outplace version of 'merge' for CountTables

* remove 'merge' tests

fix #13374 `nim c -r -` now generates $nimcache/stdinfile (#13380) [backport]

fix #9634 don't crash on execCmdEx/readLine when inside gdb/lldb (#13232)

* fix #9634 debugging a program using execCmdEx now works

* only apply EINTR to c_gets for now

This reverts commit c0f5305b5a0b46983dfd27e3d77ecbf4f8744dcc.

lib.rst: add a link for jsconsole [backport] (#13383)

Make vccexe parse response files (#13329)

expectLen now shows the length that we got (#13387)

fix several bugs with `repr`  (#13386)

fixes #13378 [backport] (#13392)

remove dead code test_nimhcr_integration.(bat,sh) (#13388)

* enable test for osx: import tests/dll/nimhcr_integration

* re-disable osx test

fix linenoise regression (#13395)

* fix nightlies linenoise regression

* fix other installers

Revert "remove dead code test_nimhcr_integration.(bat,sh) (#13388)" (#13396)

This reverts commit 90491ea0a9.
fixes #13368 (#13397)

fix bug in int128 (#13403)

isolate the build process from external config files (#13411)

add ggplotnim to important_packages (#13206)

Fix to asynchttpserver form data/body broken with #13147 (#13394)

* Fix to asynchttpserver form data/body broken with #13147
* New implementation that use a interator instance of future streams
* asynchttpserver now can handle chunks of data.

Merge branch 'devel' of https://github.com/nim-lang/Nim into osopen

Squash Commits; Peer review feedbacks https://github.com/nim-lang/Nim/pull/12901#discussion_r379694384
2020-02-15 22:31:00 +00:00
Clyybber
f3eb0a5970 capture macro now accepts variables of different types (#13356)
* Capture macro can now accept variables of different types

* Add test

* Update examples

* Use let instead of var
2020-02-15 19:53:40 +01:00
Henrique Dias
5bf571f061 Fix to asynchttpserver form data/body broken with #13147 (#13394)
* Fix to asynchttpserver form data/body broken with #13147
* New implementation that use a interator instance of future streams
* asynchttpserver now can handle chunks of data.
2020-02-14 21:59:37 +01:00
Miran
3300e317a4 add ggplotnim to important_packages (#13206) 2020-02-14 21:28:50 +01:00
Ștefan Talpalaru
3d7d06571c isolate the build process from external config files (#13411) 2020-02-14 21:15:52 +01:00
Arne Döring
ccd2e044cb fix bug in int128 (#13403) 2020-02-14 12:33:36 +01:00
cooldome
7dd787b8a3 fixes #13368 (#13397) 2020-02-14 10:13:55 +01:00
Andreas Rumpf
1e303100f8 Revert "remove dead code test_nimhcr_integration.(bat,sh) (#13388)" (#13396)
This reverts commit 90491ea0a9.
2020-02-12 13:22:26 +01:00
Timothee Cour
2b368bcdd7 fix linenoise regression (#13395)
* fix nightlies linenoise regression

* fix other installers
2020-02-12 10:35:00 +01:00
Timothee Cour
90491ea0a9 remove dead code test_nimhcr_integration.(bat,sh) (#13388)
* enable test for osx: import tests/dll/nimhcr_integration

* re-disable osx test
2020-02-12 10:21:32 +01:00
Andreas Rumpf
c446c0f57a fixes #13378 [backport] (#13392) 2020-02-11 23:48:41 +01:00
Timothee Cour
eec07b4e84 fix several bugs with repr (#13386) 2020-02-11 21:33:06 +01:00
Clyybber
f6d45b40a5 expectLen now shows the length that we got (#13387) 2020-02-11 12:31:52 +01:00
Fredrik Høisæther Rasch
8100e2e9cd Make vccexe parse response files (#13329) 2020-02-11 12:05:47 +01:00
Jjp137
84a71dad87 lib.rst: add a link for jsconsole [backport] (#13383) 2020-02-11 10:22:49 +01:00
Timothee Cour
39ba502f87 fix #9634 don't crash on execCmdEx/readLine when inside gdb/lldb (#13232)
* fix #9634 debugging a program using execCmdEx now works

* only apply EINTR to c_gets for now

This reverts commit c0f5305b5a0b46983dfd27e3d77ecbf4f8744dcc.
2020-02-11 10:16:30 +01:00
Timothee Cour
1f7c907e7d fix #13374 nim c -r - now generates $nimcache/stdinfile (#13380) [backport] 2020-02-11 00:37:40 +01:00
Miran
ceb3d5ad68 remove outplace version of 'merge' for CountTables (#13377)
* remove outplace version of 'merge' for CountTables

* remove 'merge' tests
2020-02-10 20:50:55 +01:00
Arne Döring
2fee89f7db fix #13255 (#13275) [backport] 2020-02-09 13:51:36 +01:00
Timothee Cour
7939319379 fix is with generic types; fix genericHead(Foo[T]) (#13303)
* fix #9855, fix #9855, fix genericHead
* render TTypeKind via toHumanStr
2020-02-09 13:48:55 +01:00
Timothee Cour
debe7fffd8 testament: this now works: "testament r /abspath/to/test.nim" (#13358) 2020-02-09 13:44:16 +01:00
Andreas Rumpf
240174dd81 fixes #13314 (#13372) 2020-02-09 00:22:34 +01:00
Miran
038f47e7b9 fixes #3339 by documenting the limitations of case-statement (#13366) 2020-02-08 20:11:20 +01:00
Tomohiro
2a4aa24620 Add sideEffect pragma to importC procs in posix, winlean and time module (#13370)
* Add sideEffect pragma to procs in winlean
* Add sideEffect pragma to procs in posix
* Add test for #13306
* Add sideEffect pragma to procs in times
* Fixes #13306
2020-02-08 20:09:49 +01:00
Timothee Cour
e4415422fe Revert "printing float values will have one more digit. (#13276) [backport]" (#13363)
This reverts commit b2c6db97f9.
2020-02-08 09:30:24 +01:00
Miran
f3117d350e fix #6736: templates in unittest now show actual value (#13354) 2020-02-07 22:04:08 +01:00
Miran
78b15de304 [backport] remove 'CountTable.mget' (#13355)
It didn't work, and it was an oversight to be included in v1.0.
2020-02-07 20:50:44 +01:00
narimiran
36d1ad39d0 [backport] fix #13352 2020-02-07 18:26:08 +01:00
Arne Döring
b2c6db97f9 printing float values will have one more digit. (#13276) [backport]
* printing float values will have one more digit. Fixes #13196
2020-02-07 17:10:25 +01:00
Miran
cdedb86348 testament: introduce 'matrix' for testing multiple options (#13343) 2020-02-07 16:45:49 +01:00
Timothee Cour
1f725f1d7e miscellaneous bug fixes (part 3) (#13304)
* fix deprecation; fix indentation

* git clone: use -q

* fix Warning: pragma before generic parameter list is deprecated; fix typo

* bugfix: sysTypeFromName("float64") was never cached
2020-02-07 16:37:40 +01:00
Timothee Cour
79ec8c2571 fix #13182: proc fun(a: varargs[Foo, conv]) now can be overloaded (#13345) [backport] 2020-02-07 13:29:18 +01:00
Timothee Cour
c0a2e2ed92 replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple in dollars.nim (#13347)
* replace old problematic isNamedTuple implementation by TypeTrait isNamedTuple

* fix for bootstrap
2020-02-07 13:27:28 +01:00
Henrique Dias
abd660c407 Added a basic example how to handle a Post request. (#13339)
* Added a basic example how to handle a Post request.

They were also made minor cosmetic changes.

* Minor fixes suggested by Yardanico

* Fixed a wrong value in chunkSize constant.

* Re-added the request.body for compatibility!
2020-02-07 03:59:28 -05:00
pyloor
bf3f1c3762 adding sqlite3 backup functions (#13346)
* adding sqlite3 backup functions

* changing sleep to sqlite3_sleep to prevent clashes
2020-02-07 01:11:05 -05:00
Andreas Rumpf
c87796180e fixes #13269 (#13344) 2020-02-07 06:58:57 +01:00
Timothee Cour
7481f43753 fix #13349 regression: isNamedTuple now works with generic tuples (#13350) 2020-02-07 06:58:04 +01:00
Andreas Rumpf
e24443f1bc make monotimes have zero overhead if you don't use it (#13338) [backport] 2020-02-06 16:12:54 +01:00
Timothee Cour
7ec7731f82 fix #13150 nim doc --project now works reliably (#13223)
* fix #13150 `nim doc --project` works with duplicate names and with imports below main project file

* add to help; fixup after #13212 isRelativeTo got merged
* fix test tests/compilerapi/tcompilerapi.nim
* remove nimblePkg field; compute on the fly instead
* kochdocs: compiler docs now under compiler/
* --docRoot now has smart default: best among @pkg, @path
2020-02-06 11:17:00 +01:00
Timothee Cour
574f61315d nim secret: support linenoise when available (#13328) 2020-02-05 16:44:19 +01:00
Miran
c6d5f0df8d [backport] -d:danger should imply -d:release (#13336) 2020-02-05 13:41:16 +01:00
Araq
8279da5219 contributing.rst: Add a special rule for 'outplace'-like features 2020-02-05 13:39:08 +01:00
Clyybber
ab525cc48a build_all.sh update (#13320)
* Don't overload the system, don't crash when you can't determine the CPU count and don't rely on bash

* Extract to variable

* Limit number of spawned jobs for systems with weak IO

* Use proper arithmetic braces
2020-02-04 21:26:38 +01:00
Henrique Dias
955465e5f4 Option to allow the request body to be processed outside the asynchttpserver library. (#13147)
Allow the request body to be processed outside the asynchttpserver library to break big files into chunks of data. This change does not break anything.
2020-02-04 21:13:25 +01:00
Ico Doornekamp
bfe96e069b Fixed codegen for constant cstring with --gc:arc (#13326)
* Fixed codegen for constant cstring with --gc:arc, fixes  #13321

* Added test for #13321
2020-02-04 17:39:27 +01:00
genotrance
7cc03b43f8 Fix #10717, fix #13284 (#13307) 2020-02-04 17:38:24 +01:00
Timothee Cour
e70294dff2 enable testing -d:nimHasLibFFI mode (#13091) 2020-02-04 14:08:56 +01:00
Timothee Cour
b20d7e2110 fix #13132 tnetdial (#13318) 2020-02-04 10:31:44 +01:00
alaviss
7e5c070244 koch: enable checks in the compiler when running CI (#13323) 2020-02-04 09:27:54 +01:00
Clyybber
1ab37ccfc6 Make build_all.sh more portable and a bit simpler (#13308) 2020-02-03 02:02:44 +01:00
Fredrik Høisæther Rasch
dfecc3489b Quote nim executable before executing. (#13316) [backport]
In case nim executable is located in PATH containing spaces.

fixes #13311
2020-02-02 13:54:48 +01:00
Clyybber
d43e5bef39 Fix capture for object types (#13315)
* Fix capture for object|tuple|... types

* Add test case
2020-02-02 13:52:21 +01:00
Timothee Cour
45a5c64c9a build_all.sh: building csources 5X faster thanks to make -j (#13300)
* build_all.sh: building csources 5X faster thanks to make -j
* fix for freebsd
* use OS-dependent formula to get number of logical cores
* make is an optional dependency
2020-01-31 20:00:05 +01:00
Timothee Cour
adc52b0039 refs #8391 std/os now shows runtime context for raiseOSError exceptions (#13294)
* refs #8391: fix errmsg for setCurrentDir

* raiseOSError calls for copyFile

* refs #8391 std/os now shows runtime context for raiseOSError exceptions
2020-01-30 11:06:04 +01:00
Timothee Cour
4a747f0250 CT FFI: fix for windows; fix case transition; error msg shows more useful context (#13292)
* evalffi: fix case transition
* evalffi: fix for windows
* evallffi: `cannot import` errmsg now also shows which library it tried to import symbol from
2020-01-30 11:04:06 +01:00
Timothee Cour
bf22b44b1f miscellaneous bug fixes (#13291)
* fix for emscripten etc

* add testcase for #13290

* replace deprecated isNilOrWhitespace
2020-01-30 10:54:50 +01:00
Timothee Cour
81a43791f9 fix critical bug discovered by #11591 (#13290) [backport] 2020-01-29 17:40:03 +01:00
Hiroki Noda
3ab1274231 Thread attributes should be destroyed using the pthread_attr_destroy() (#13293)
On some OSes (such as FreeBSD or Solaris), pthread_attr_init allocate
memory. So it is necessary to deallocate that memory by using
pthread_attr_destroy.
2020-01-29 17:33:21 +01:00
Timothee Cour
2ecef8f779 csize => csize_t for sysctl 2020-01-28 23:36:24 +00:00
Timothee Cour
2e20f5648b fix stdout(etc) for emscripten 2020-01-28 23:36:24 +00:00
Timothee Cour
9657a83698 removed unused import 2020-01-28 23:36:24 +00:00
Timothee Cour
5676912209 refactor htmldocs; gitignore it 2020-01-28 23:36:24 +00:00
cooldome
76ede7c198 Repr v2 progress (#13268)
* progress on repr_v2

* repr progress

* add ref objects with distrinct

* fix failing tests
2020-01-28 20:05:57 +01:00
cooldome
92010becbe nimv2 widestring indexing (#13279) 2020-01-28 20:02:39 +01:00
Clyybber
fb94836bc7 Tiny since cleanup (#13286) 2020-01-28 20:02:07 +01:00
Andreas Rumpf
be795bbf1a TlSF Alloctor: use less memory for --gc:arc (#13280) 2020-01-28 17:09:48 +01:00
cooldome
84e8477b90 unittest add resetOutputFormatters proc (#13267)
* add resetOutputFormatters

* remove space

* resolve comments
2020-01-28 14:16:03 +00:00
cooldome
46bfb590c8 fixes #13281 (#13282)
* fixes ##13281

* add comment to test
2020-01-28 14:55:54 +01:00
Andreas Rumpf
c8418651b1 fixes #13219 (#13272) 2020-01-27 22:50:10 +01:00
Jairo
32f0910f11 scrollTop must be settable (#13263)
* scrollTop must be assignable

Make scrollTop settable

* add missing export
2020-01-27 09:14:56 +01:00
hlaaftana
a71654323d Clearer final objects error; fixes #13256 (#13257) 2020-01-26 18:56:04 +01:00
hlaaftana
e7744b0909 Rename isNilOrWhitespace to isEmptyOrWhitespace and make it use allCharsInSet (#13258)
* Rename isNilOrWhitespace to isEmptyOrWhitespace

* Make isEmptyOrWhitespace use allCharsInSet(Whitespace)
2020-01-26 14:02:07 +01:00
Araq
6900da314c make nre compile with --gc:arc 2020-01-26 13:43:02 +01:00
Araq
a10cc18247 ARC: optimize complete object constructors to use nimNewObjUninit 2020-01-26 13:43:02 +01:00
Araq
ab35f07e77 ARC: remove unnecessary code 2020-01-26 13:43:02 +01:00
Andreas Rumpf
6efac70181 make goto based exceptions available for 'nim cpp' (#13244)
* make goto based exceptions available for 'nim cpp'
* optimize seq.add to be comparable to C++'s emplace_back
2020-01-25 20:00:13 +01:00
Ico Doornekamp
4f3dd33509 Cleaned up mmdisp.nim, moved implementations into lib/system/mm/ (#13254) 2020-01-25 17:14:31 +01:00
alaviss
5124b2e575 testament/azure: major rewrite (#13246)
This commit features a major rewrite of Azure Pipelines integration,
turning the spaghetti it originally was into something maintainable.

Key changes:
- No longer requires a ton of hooks into testament.
- Results are now cached then bulk-uploaded to prevent throttling from
  Azure Pipelines, avoiding costly timeouts.
- A low timeout is also employed to avoid inflated test time.
- The integration is now documented.
2020-01-25 09:32:27 +01:00
Timothee Cour
981ffc912e contributing docs: symbols need package prefix; changed allocStats to nimAllocStats (#13247) 2020-01-25 09:27:29 +01:00
Timothee Cour
4cbeddddcc nim dump: add libpath (#13249) 2020-01-24 20:06:54 +01:00
Jairo
fb74497c99 Add "origin" to window.location (#13251)
Add "origin" to window location: https://www.w3schools.com/jsref/prop_loc_origin.asp
2020-01-24 20:06:17 +01:00
Euan
ccb728a7b0 Fix typo for literal [ (#13243)
The literal value for the `tkBracketLe` token was incorrectly set to `]` rather than `[`. I've had a quick glance at the code and it doesn't look like this change will affect anything at all, but I haven't tested yet - let's see if the CI explodes...
2020-01-24 08:42:03 +00:00
hlaaftana
4656580b54 Fixes asyncftpclient multiline reading, fixes #4684 (#13242)
Previously, the 4th character of `result` was checked for `'-'` every time, instead of each new line.

Also made it work for taint mode.
2020-01-24 00:18:16 +01:00
hlaaftana
caaa8f285f Remove name attribute from docutils.nimble (#13239) 2020-01-23 18:51:25 +01:00
Ico Doornekamp
5dd2fa3e0c Updated 'nim for embedded systems' section to use --os:any and --gc:arc (#13237)
* Updated 'nim for embedded systems' section to use --os:any and --gc:arc

* Added section about size optimization to embedded systems
2020-01-23 17:17:48 +01:00
Kaushal Modi
c4ff4e553e [backport] Make all parseutils examples auto-checking (#13238)
- Also fix one example's output (ikString -> ikStr, ikVar instead of ikExpr)
2020-01-23 17:14:22 +01:00
chr v1.x
aebcbfe5ea [backport] documentation: Add channels examples (#13202) [ci skip] 2020-01-23 14:47:00 +01:00
Ico Doornekamp
b68eb1cad0 Removed lib/system/allocators.nim. seqs_v2 and strs_v2 now uses allocShared0. (#13190)
* Cleanup, remove lib/system/allocators.nim. seqs_v2 and strs_v2 now use
allocShared0 by default.

* Fixed -d:useMalloc allocShared / reallocShared / deallocShared. These now use the alloc/dealloc/realloc implementation that also takes care of zeroing memory at realloc.

* Removed debug printfs

* Removed unpairedEnvAllocs() from tests/destructor/tnewruntime_misc

* More mmdisp cleanups. The shared allocators do not need to zero memory or throw since the regular ones already do that

* Introduced realloc0 and reallocShared0, these procs are now used by
strs_v2 and seqs_v2. This also allowed the -d:useMalloc allocator to
drop the extra header with allocation length.

* Moved strs_v2/seqs_v2 'allocated' flag into 'cap' field

* Added 'getAllocStats()' to get low level alloc/dealloc counters. Enable with -d:allocStats

* *allocShared implementations for boehm and go allocators now depend on the proper *allocImpl procs
2020-01-23 14:25:22 +01:00
alaviss
f500895efe Unexport even more symbols (#13214)
* system/gc: don't export markStackAndRegisters

* compiler/cgen: unexport internal symbols

As these functions are Nim-specific walkaround against C's optimization
schemes, they don't serve any purpose being exported.

* compiler/cgen: don't export global var unless marked

* compiler/ccgthreadvars: don't export threadvar unless marked

* tests/dll/visibility: also check for exports

This ensure that these changes don't break manual exports.

* compiler/cgen: hide all variables created for constants

* compiler/ccgtypes: don't export RTTI variables

* compiler/ccgexprs: make all complex const static

* nimbase.h: fix export for windows

* compiler/cgen, ccgthreadvars: export variables correctly

For C/C++ variables, `extern` means that the variable is defined in an
another unit. Added a new N_LIB_EXPORT_VAR to correctly export
variables.
2020-01-23 13:45:31 +01:00
Timothee Cour
3a5056dc70 fix lots of bugs with parentDir, refs #8734 (#13236) 2020-01-23 13:39:41 +01:00
Timothee Cour
b8a436af93 kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes (#13221)
* kochdocs: use a glob instead of hardcoded list; generate docs for compiler/; bugfixes
* fixup after #13212 isRelativeTo got merged
2020-01-23 11:06:28 +01:00
Timothee Cour
b462baed65 VM: allow overriding MaxLoopIterations without rebuilding nim (#13233) 2020-01-23 10:53:30 +01:00
D-Nice
f12bea16ad [backport] fix #11440, add docs to isNil for seq types needing nilseq (#13234) [ci skip] 2020-01-23 07:51:53 +01:00
Mera
4a754ff392 [backport] Fix typo and improve in code-block of 'lib/pure/parseutils.nim' (#13231) [ci skip] 2020-01-23 06:49:27 +01:00
Timothee Cour
7356bc29b7 new os.isRelativeTo (#13212) 2020-01-23 00:45:16 +01:00
Milan
3e843ab335 [backport] times/getClockStr(): fix mistake in doc (#13229) [ci skip] 2020-01-22 18:22:14 +01:00
Juan Carlos
fbd7fe118c [backport] Documentation Fix #12251 (#13226) [ci skip] 2020-01-22 17:56:44 +01:00
whiterock
ef9fb39cdf added note to re constructor regarding performance (#13224)
Since I was new to regex I did not know that there is a compilation going on with ``re"[abc]"`` constructor and so I followed the other examples in the docs blindly, that is I just put the constructor directly in the arguments of match, find, etc., which was inside a loop and then wondered why my performance was so bad. Of course putting it outside the loop made it vastly more performant. People like me would benefit from the small note I added I would think :)
2020-01-22 16:02:16 +01:00
Juan Carlos
2fad7f134f httpclient, maxredirects to Natural, newHttpClient/newAsyncHttpClient add headers argument instead of hardcoded empty (#13207) 2020-01-21 19:34:47 +01:00
Andreas Rumpf
bdb7c82c6a fixes a critical times.nim bug reported on IRC [backport] (#13216) 2020-01-21 16:49:59 +01:00
Timothee Cour
b355ef2a72 fix #13211 relativePath("foo", ".") (#13213) 2020-01-21 15:48:19 +01:00
Miran
bf96d6d316 Idxmin & idxmax, continuation (#13208)
* Add idxmin() which returns the index of the minimum value

* Add idxmax() which returns the index of the maximum value

* Add tests for idxmin()

* Add tests for idxmax()

* Remove initialization of result = 0

* Adds overloading for arrays (no enums indexed arrays yet)

* Add support for enum index arrays

* Fix tests with enum

* Fix tests for idxmax

* Change names of the procedures to minIndex and maxIndex

* address Araq's comments:

- remove 'array' versions
- add .since pragma
- return 'int' instead of 'Natural'
- add changelog entry

Co-authored-by: Federico A. Corazza <20555025+Imperator26@users.noreply.github.com>
2020-01-20 16:57:34 +01:00
Jasper Jenkins
0606b6a44e fix range[enum] type conversion (#13204) [backport] 2020-01-20 16:56:59 +01:00
alaviss
470faa97c6 compiler/ccgtypes: hide exportc proc unless it has dynlib (#13199)
This hides most of stdlib's internal functions from resulting
binaries/libraries, where they aren't needed on *nix. Static libraries
are not affected by this change (visibility doesn't apply to them).
2020-01-20 10:51:21 +01:00
cooldome
da1bddb084 fixes #13195 (#13198)
* fixes #13195

* extra fix

* fix typo
2020-01-20 10:41:12 +01:00
Andreas Rumpf
41555ca86f fixes #13110 (#13197) 2020-01-19 23:30:45 +01:00
Andrii Riabushenko
6f3476d39c Revert "fixes #13195"
This reverts commit cd7904f2b2.
2020-01-19 20:33:23 +00:00
Andrii Riabushenko
e349f7ad21 Merge branch 'devel' of https://github.com/nim-lang/Nim into devel 2020-01-19 20:22:06 +00:00
Andrii Riabushenko
7576387dfe revert last commit 2020-01-19 20:21:26 +00:00
Andrii Riabushenko
cd7904f2b2 fixes #13195 2020-01-19 20:18:04 +00:00
slangmgh
13ddbc46fc Fixes #13186 (#13188) 2020-01-19 14:16:50 +01:00
Federico Ceratto
8d64550b1e Add link to packaging.html (#13194) 2020-01-19 14:15:59 +01:00
cooldome
416b4c3612 more on arc codegen (#13178)
* arc codegen for union type

* add more tests

* fix offsetof

* fix tsizeof test

* fix style
2020-01-19 14:14:26 +01:00
Timothee Cour
bc14453f69 fix docs + API for fieldPairs, fields (#13189) 2020-01-18 13:33:30 +01:00
Timothee Cour
f6ba4e81b0 maybe: allows optional chaining of field access and indexing when LHS i snil (#13023)
* maybe: allows optional chaining
* fix tools/kochdocs.nim
* improve semantics to distinguish valid from invalid values
* for now, wrapnil, isValid, unwrap are not exported
2020-01-18 12:24:56 +01:00
Timothee Cour
e11ecc8266 times: toUnixFloat, fromUnixFloat (#13044) 2020-01-18 01:24:44 +01:00
Timothee Cour
5010bc1af5 fixes #13144 (#13145)
* fixup: genscript now does not copy nimbase.h but uses -I$nim/lib
2020-01-18 01:21:13 +01:00
Timothee Cour
c56612ff96 refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.} (#13136)
* refs #13054 correctly handle {.exportc,dynlib.} and {.exportcpp,dynlib.}
* put back NIM_EXTERNC for N_LIB_EXPORT; causes issues with compilerproc
2020-01-18 01:19:20 +01:00
Araq
107352f9d7 fixes #13157 2020-01-17 17:52:06 +01:00
Timothee Cour
6c2214b7de followup on #10435 : should be diff, not show (#13162) 2020-01-17 16:56:21 +01:00
Clyybber
451c47634c Fix docs for subdirs too (#13180)
* Fix doc subdirs
* Extract to helper proc, and fix on windows
2020-01-17 16:49:37 +01:00
cooldome
f51613e262 make sink operator optional (#13068)
* make sink operator optional

* bug fix, add changelog entry

* Trigger build

* fix one regression

* fix test

* Trigger build

* fix typos
2020-01-17 11:44:06 +00:00
Andreas Rumpf
7626907401 ARC works for async on Windows (#13179) 2020-01-17 11:14:17 +01:00
Jasper Jenkins
796aafe7e0 make case-object transitions explicit, make unknownLineInfo a const, replace a few magic numbers with consts (#13170) 2020-01-17 10:34:31 +01:00
cooldome
2bf337abae fixes #13095 (#13181)
* fixes #13095

* fix typo
2020-01-17 09:17:18 +01:00
Clyybber
41cf609fc7 Fix docs (#13176) 2020-01-16 22:22:17 +01:00
Clyybber
e3acb2d12c Cleanup DFA (#13173) 2020-01-16 20:15:50 +01:00
Jasper Jenkins
d245d4cf09 fix tsizeof3 for aarch64 (#13169) 2020-01-16 14:21:12 +01:00
Timothee Cour
1b54be7779 fixes #12998 nim doc regression (#13117) 2020-01-16 14:19:58 +01:00
cooldome
5ef0494677 Working towards arc codegen (#13153)
fixes #13029
2020-01-16 14:16:17 +01:00
Miran
352232e62d style fix: change 'JS' to 'js' to make it consistent (#13168) 2020-01-16 14:14:03 +01:00
Ico Doornekamp
54bfd69a27 Remove obsolete code from osalloc (#13158) 2020-01-16 09:11:05 +01:00
Timothee Cour
d5f011d9e6 CI fix timeout error (#13134) 2020-01-15 22:54:04 +01:00
Andreas Rumpf
a5e67071d2 ARC: misc bugfixes (#13156)
* fixes #13102
* closes #13149
* ARC: fixes a move optimizer bug (there are more left regarding array and tuple indexing)
* proper fix; fixes #12957
* fixes yet another case object '=' code generation problem
2020-01-15 22:13:31 +01:00
Timothee Cour
d88b52c0bc successX now correctly shows html output for nim doc, nim jsondoc; fix #13121 (#13116)
* successX now correctly shows html output for nim doc
* fixes #13121
* fixup hintSuccessX to be less weird
2020-01-15 15:18:37 +01:00
Timothee Cour
51c072bd37 export normalizePathEnd (#13152) 2020-01-15 15:03:06 +01:00
Miran
e708d5de75 System cleanup, part 2 (#13155)
* create basic_types, arithmetics, exceptions, comparisons
* create setops.nim
* create memalloc.nim
* create gc_interface.nim
* create iterators_1.nim
2020-01-15 14:42:49 +01:00
Ico Doornekamp
79a326759a Added 'ansic' os support for minimal (embedded) targets (#13088)
* os:any implementation
* os:asny: omit flock/funlock calls in echoBinSafe
* Disabled default "unhandled expection" reporting for `--os:any` to reduce
code size. Added unhandledExceptionHook instead which can be used to get
a notification from Nim and handle it from the application.
2020-01-15 11:06:41 +01:00
Tomohiro
d31e32743f Fix typo in doc/destructors.rst (#13148) 2020-01-14 19:51:58 +01:00
Andreas Rumpf
675ca997fb fixes #9674 [backport] (#13143) 2020-01-14 16:20:48 +01:00
Andreas Rumpf
8b00586488 fixes #13104 [backport] (#13142) 2020-01-14 15:16:36 +01:00
cooldome
b4545f03de pass platform argument only if vccexe is used (#13078)
* pass platform only if vccexe is used
* fixes #12297
2020-01-14 15:02:10 +01:00
Andreas Rumpf
fadbd8f70d fixes #10665 (#13141) [backport] 2020-01-14 13:51:28 +01:00
Andreas Rumpf
9fc04a555c fixes #13105 (#13138) 2020-01-14 12:57:20 +01:00
Andreas Rumpf
d56848878c fixes #13119 (#13128)
* fixes #13119
* fixes a regression
2020-01-14 09:56:08 +01:00
Timothee Cour
49d1822c8f fixes #13100 nim doc now treats export localSymbol correctly (#13123) [backport]
* fix #13100 nim doc now treats `export localSymbol` correctly
* use owner instead
2020-01-13 22:05:38 +01:00
treeform
d9640ed075 Expose more openSSL methods. (#13131) 2020-01-13 22:04:43 +01:00
Andreas Rumpf
eadd1ba9ed fixes #13112 (#13127)
* improve line error information

* fixes #13112
2020-01-13 15:47:17 +01:00
Andreas Rumpf
abea80376a fixes #13122 (#13126)
* fixes #13122

* moved tests to where they belong
2020-01-13 14:11:51 +01:00
Jasper Jenkins
bf2e052e6d fix rtti sizeof for varargs in global scope (#13125) [backport] 2020-01-13 10:17:21 +01:00
perter lee
1f27a2f8ab fix the ftp store function read the local file bug (#13108) [backport]
* Update asyncftpclient.nim

When use newStringOfCap function not have assign memory for the string data,so if use this address the fault is rasise.

* complelete the bugfix
2020-01-13 10:16:19 +01:00
Timothee Cour
ee1563ef33 VM FFI: write(stderr, msg) and fprintf(cstderr, msg) now work at CT (#13083) 2020-01-12 13:44:43 +01:00
Federico Ceratto
1c001fe583 Add link to posix_utils.html in posix.nim (#13111) 2020-01-12 13:36:37 +01:00
treeform
01a89cc473 Remove some unused/disabled OpenSSL functions (#13106) 2020-01-11 10:58:38 +01:00
Andreas Rumpf
767592a3c3 more arc features (#13098)
* config update
* ARC now supports 'repr' and 'new' with finalizers is supported
2020-01-10 23:17:33 +01:00
Miran
c0973d1b47 [backport] fix #12813, fix #13079 (#13099)
Correctly remove a key from CountTable when it is set to zero.
2020-01-10 15:24:33 +01:00
Miran
f7ce4e8705 System cleanup, part 1 (#13069)
* system.nim: mark what every .pop does

* system.nim: un-nest when statements
2020-01-10 10:14:02 +01:00
Andreas Rumpf
3a39ab83ac fixes an asyncftpclient bug; refs #13096 [backport] 2020-01-10 09:42:21 +01:00
narimiran
e9e114058c [backport] system/io.nim fix wrong documentation comment [ci skip] 2020-01-10 08:53:44 +01:00
Timothee Cour
4cd86c0842 typetraits: fixes #6454; genericParams; added lenTuple; added tuple type get (#13064) 2020-01-10 08:51:37 +01:00
Araq
fcd2f305ad fixes #13070 2020-01-10 08:32:30 +01:00
Araq
033da35de1 fixes #13072; no test case because it will be added later with more exception handling related bugfixes 2020-01-10 08:32:30 +01:00
Tomohiro
a33b72af49 Fix error check code in osproc (#13090) [backport] 2020-01-09 18:00:41 +01:00
Ico Doornekamp
bb7273bc47 Use '__noinline' instead of 'noinline' for N_NOINLINE gcc attribute, this prevents clashes with systems where 'noinline' might be already defined (#13089) 2020-01-09 17:27:42 +01:00
Timothee Cour
3f78873898 remove all remaining warnings when build nim (with -d:nimHasLibFFI) (#13084)
* cleanup deprecations in evalffi + elsewhere

* remove dead code getOrdValue64
2020-01-09 13:19:18 +01:00
Andreas Rumpf
852170cc78 take the one good idea from --os:standalone and enable it via -d:StandaloneHeapSize (#13077) 2020-01-09 11:48:37 +01:00
Teashrock
27fee4d8b4 Deleted misplaced separator (#13085) [backport]
Misplaced separator, which was constantly breaking compilation on Haiku OS, was deleted.
2020-01-09 11:48:13 +01:00
Andy Davidoff
56fb909676 fix crash due to errant symbols in nim.cfg (#13073) [backport] 2020-01-08 22:25:25 +01:00
narimiran
5e9ebe9ec1 move entries from the wrong changelog file [ci skip] 2020-01-08 15:20:30 +01:00
Timothee Cour
15043d35b8 make SuccessX show project file + output file (#13043)
* make SuccessX show project file + output file
* address comments
* fix test and add `result.err = reNimcCrash` otherwise hard to see where reNimcCrash used
* address comments
2020-01-08 00:39:07 +01:00
cooldome
871d5e79b1 distinctBase type trait for distinct types (#13031) 2020-01-08 00:36:57 +01:00
b3liever
8bcc7e8b9e basename supports pragmaexpr (#13045)
* basename supports pragmaexpr

* update changelog
2020-01-07 11:25:51 +01:00
Bung
291608045c add pqserverVersion,pqconnectionNeedsPassword,pqconnectionUsedPassword (#13060) 2020-01-07 10:52:02 +01:00
Timothee Cour
e5ae7ceaa3 [easy] --hint🔗on now shows link cmd instead of nothing (#13056)
* --hint🔗on now shows link cmd instead of nothing

* update doc for --listCmd
2020-01-07 10:38:59 +01:00
Timothee Cour
569d4d18f8 --styleCheck:hint now works (#13055) 2020-01-07 09:53:11 +01:00
Miran
1551fff853 clean up deprecated stuff and unused imports in tests (#13059) 2020-01-07 09:49:08 +01:00
loloiccl
6a7a19eb15 Modify the test command for nimly (nimble-package) (#13053) 2020-01-07 06:47:40 +01:00
Brent Pedersen
a019cc52f6 testament/important_packages dont run hts (#13052) 2020-01-07 06:47:18 +01:00
Clyybber
ba4fbb6328 Continue #13002 (#13021) 2020-01-06 11:40:42 +00:00
Timothee Cour
72499a8d7c [cleanup] remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits (#13041)
* remove disabled (and obsolete) ttypetraits; rename ttypetraits2 => ttypetraits

* D20200105T085828 fix super strange bug that causes CI to fail: builds.sr.ht with: `Error: Settle timed out after 120 attempts`
2020-01-05 19:33:33 +01:00
BinHong Lee
2cfa8d8385 Allow -o option for buildIndex (#13037) [backport]
Addressing #12771 

This is also included in the docgen documentation [here](https://nim-lang.org/docs/docgen.html) but its not respected as reported in the issue.
2020-01-05 19:24:29 +01:00
Kamanji
9a5aaadda8 Rst parser respect :start-after: and :end-before: in include directive (#12972)
* [FEATURE] rst parser respect :start-after: in include

Rst parser now respects `:start-after:` and `:end-before:` attributes
for `include` directive.

* [DOC] include directive parsing proc update

* [TEST] Added unit tests for include rst directive in `rst` module
2020-01-05 10:01:21 +01:00
Araq
ae68ff959b fixes #12996 2020-01-05 09:42:44 +01:00
Araq
fdcea66fd9 reprjs: style changes 2020-01-05 09:42:44 +01:00
cooldome
a3df1b55f3 fixes #13013, reverts previous changes to readLines() (#13036) [backport]
* Revert "remove default argument for readLines (#12807) [backport]"

This reverts commit c949b81efd.
2020-01-05 09:22:41 +01:00
Jasper Jenkins
9474a818af fix enumtostr crash for enum-range (#13035) 2020-01-05 09:18:14 +01:00
Timothee Cour
13c08f3ab4 VM: support importc var, ptr/pointer types, cast int <=> ptr/pointer (#12877)
* VM: allow certain hardcoded special var variables at CT
* VM: allow all importc var, cast[int](ptr)
* fix tests tests/vm/tstaticprintseq.nim, tests/cpp/t8241.nim
* VM: == works for ptr/pointer nodes
* bugfix: ==, cast now also works for pointer, not just ptr
* VM supports cast PtrLikeKinds <=> PtrLikeKinds / int
* improve cname handling
* fixup + bug fix
* VM: support cast from ref to int
* address comment: opcLdGlobalDeref => opcLdGlobalDerefFFI
* defensive check against typ == nil
2020-01-05 09:11:29 +01:00
Araq
a1beeb313f fixes #13032 2020-01-04 19:33:49 +01:00
Andreas Rumpf
0f6987a86e fixes #12964 (#13027) 2020-01-04 07:40:02 +01:00
cooldome
47e7b8771c Fixes #13026 (#13028) 2020-01-04 02:33:13 +01:00
rockcavera
89570aa44b fix #12988 (#13022)
fix #12988
2020-01-03 22:41:58 +01:00
Andreas Rumpf
fb1b51f1e3 fixes #12956 (#13020) 2020-01-03 17:36:09 +01:00
Andreas Rumpf
8aadba1a2a fixes #12961 (#13019) 2020-01-03 14:30:54 +01:00
Siegfried Ehret
a577a88c36 Fix typo (#13015) [backport] 2020-01-03 10:23:28 +01:00
Andreas Rumpf
0ecb709cbe fixes #12978 (#13012) 2020-01-03 01:21:45 +01:00
cooldome
c949b81efd remove default argument for readLines (#12807) [backport] 2020-01-02 23:27:37 +01:00
cooldome
002d50f1f0 Sink to MemMove optimization in injectdestructors (#13002) 2020-01-02 22:58:01 +01:00
Timothee Cour
0ff23e696c fix #12985 {.push.} now does not apply to generic instantiations (#12986) 2020-01-02 16:49:57 +01:00
Andreas Rumpf
c3344862b0 --exception:goto switch for deterministic exception handling (#12977)
This implements "deterministic" exception handling for Nim based on goto instead of setjmp. This means raising an exception is much cheaper than in C++'s table based implementations. Supports hard realtime systems. Default for --gc:arc and the C target because it's generally a good idea and arc is all about deterministic behavior.

Note: This implies that fatal runtime traps are not catchable anymore! This needs to be documented.
2020-01-01 10:01:49 +01:00
Andy Davidoff
8a63caca07 fixes disruptek/nimph#102 multi-level nim.cfg use (#13001) [backport] 2019-12-31 22:29:19 +01:00
cooldome
584e8c8283 fixes #12989 (#12992)
* fixes #12989
* Revert "remove unwanted changes"

This reverts commit 501829732a.
2019-12-31 21:13:26 +01:00
Andreas Rumpf
ce40ed18bb fixes #12965 (#12991) 2019-12-31 09:42:18 +01:00
Andrii Riabushenko
9eeff690d5 Revert "fixes #12989"
This reverts commit 928c2fee06.
2019-12-31 00:10:02 +00:00
Andrii Riabushenko
928c2fee06 fixes #12989 2019-12-31 00:07:49 +00:00
Ștefan Talpalaru
defaf3b5a5 c_fflush() the rawWrite() buffer (#12987)
Stack traces on an unbuffered stderr get out of sync with line-buffered
stdout - usually on Windows terminals or CI logs. This fixes it by
calling C's fflush() on the output buffer in the procedure used for
printing stack traces.
2019-12-30 02:13:41 +01:00
Chris Heller
8d1a7db6ea Check pqntuples > 0 in getValue. Fixes #12973 (#12974) 2019-12-29 17:41:18 +01:00
Sam Wang
441cacf70f Added fix for handling TaintedStrings in streams and httpclient (#12969)
* Added fix for taint mode in streams and httpclient

* Removed taintMode export from system.nim
2019-12-29 17:37:22 +01:00
Ștefan Talpalaru
ee9ee297d8 generic stack trace overriding mechanism (#12922)
* libbacktrace support

* switch to a generic stack trace overriding mechanism

When "nimStackTraceOverride" is defined, once of the imported modules
can register its own procedure to replace the default stack trace
generation by calling `registerStackTraceOverride(myOwnProc)`.

Tested with `./koch boot -d:release --debugger:native -d:nimStackTraceOverride --import:libbacktrace`
for the compiler itself and `./bin/nim c -r -f --stacktrace:off --debugger:native -d:nimStackTraceOverride --import:libbacktrace foo.nim`
for an external program.

* make the StackTraceOverrideProc {.noinline.}
2019-12-29 15:46:01 +01:00
Simon Krauter
37e93eab66 parsecfg: retain CRLF line breaks, fixes #12970 (#12971) 2019-12-29 15:39:48 +01:00
Timothee Cour
8c19372690 [ci skip] docfix .. < => ..< (#12981) [backport] 2019-12-29 15:34:36 +01:00
Jack Tang
21ea1094ef Allow customize Host header 2019-12-28 17:26:02 +00:00
King Eca
b67dea7a33 Fixes stackoverflow links in readme (#12963) [backport] 2019-12-27 08:31:01 +00:00
Andreas Rumpf
1917ebf082 minor refactorings 2019-12-27 08:29:40 +01:00
cooldome
649bf326bf fixes #12945 (#12959) 2019-12-24 20:34:14 +01:00
Araq
30162908b0 fixes another regression 2019-12-24 17:33:27 +01:00
Araq
3516947642 osproc: fixes regression 2019-12-24 17:33:27 +01:00
Araq
5aa7b1a44b ARC: default to a shared heap with --threads:on 2019-12-24 17:33:27 +01:00
Araq
bafb4f119c ported re.nim to ARC 2019-12-24 17:33:27 +01:00
Araq
8f17a70fe1 ported osproc.nim to ARC 2019-12-24 17:33:27 +01:00
Araq
9faf00598f ported channels to ARC 2019-12-24 17:33:27 +01:00
Araq
fbb8052e3a fixes the distros.nim regression 2019-12-24 17:33:27 +01:00
Araq
7bcf7696f0 fixes a silly regression 2019-12-24 17:33:27 +01:00
Araq
942db8c5f3 fixes a test case 2019-12-24 17:33:27 +01:00
Araq
6152eb3be3 a better bugfix 2019-12-24 17:33:27 +01:00
Araq
767bd57289 fixes a regression 2019-12-24 17:33:27 +01:00
Araq
d1d017ae85 fixes #12826 2019-12-24 17:33:27 +01:00
Araq
a7b4b2ed54 fixes a bug that kept sugar.collect from working with for loop macros [backport] 2019-12-24 17:33:27 +01:00
Araq
fd5aa89304 added guidelines for evolving Nim's stdlib 2019-12-24 17:33:27 +01:00
Araq
2616a86d4b docs: tiny style improvements 2019-12-24 17:33:27 +01:00
Timothee Cour
a0980c88c9 lenVarargs: number of varargs elements (#12907) 2019-12-23 09:42:32 +01:00
Jasper Jenkins
2e7c9eb6a8 case coverage error message for char (#12948) 2019-12-22 10:10:46 +01:00
Ico Doornekamp
28466ce6fc Auto-initialize deques (#12879) 2019-12-21 21:01:34 +01:00
Timothee Cour
b081166685 fixes #12735 on osx, call dsymutil for debug builds (#12931)
* fix #12735 osx: dsymutil needs to be called for debug builds
* also write dsymutil command to extraCmds in json build file
2019-12-21 20:59:08 +01:00
Judd
e1d79d40f2 update documentation for closureScope and capture (#12886) 2019-12-21 08:06:32 +01:00
RSDuck
9b8afd1dbb Fix #12785 (#12943)
* Fix #12785 and add test

* better variable name
2019-12-21 07:51:19 +01:00
Clyybber
10bd7d8fa0 system.reset is no longer magic (#12937)
It has now means setting x to default for new and old runtime alike
2019-12-19 20:36:59 +01:00
Timothee Cour
e041c184d2 fix #12919 tasyncclosestall flaky: Address already in use (#12934) 2019-12-19 18:50:39 +01:00
Timothee Cour
206a4cee77 fix cmdline bugs affecting nimBetterRun correctness (#12933) [backport] 2019-12-19 14:53:01 +01:00
flywind
cb0a20b9b4 fix error in assertions document (#12925) [backport] 2019-12-18 14:29:45 +01:00
Jasper Jenkins
3c38edf563 Better case coverage error message for alias and range enum (#12913) 2019-12-18 10:29:01 +01:00
Emery Hemingway
148f6d9820 Implement NixOS distro check (#12914) 2019-12-18 08:01:58 +01:00
Andreas Rumpf
3f6df5cc34 fixes #12899 (#12921)
* fixes #12899

* fixes regression: destroy global variables in reverse declaration order, closureleak test relies on it
2019-12-18 07:54:20 +01:00
genotrance
f9f55a23bb Fix single match output (#12920) 2019-12-17 20:26:11 +01:00
Clyybber
18e2ea787e Cleanup leftovers of #12911(#12916) 2019-12-17 17:58:04 +01:00
Andreas Rumpf
83a736a34a ARC: cycle detector (#12823)
* first implementation of the =trace and =dispose hooks for the cycle collector
* a cycle collector for ARC: progress
* manual: the .acyclic pragma is a thing once again
* gcbench: adaptations for --gc:arc
* enable valgrind tests for the strutils tests
* testament: better valgrind support
* ARC refactoring: growable jumpstacks
* ARC cycle detector: non-recursive algorithm
* moved and renamed core/ files back to system/
* refactoring: --gc:arc vs --gc:orc since 'orc' is even more experimental and we want to ship --gc:arc soonish
2019-12-17 17:37:50 +01:00
Arne Döring
5848f0042c add $nimeq for gdb (#12909) 2019-12-17 11:30:01 +01:00
cooldome
7650617448 NaN floatFormat with clang_cl (#12910)
* clang_cl nan floatFormat

* format
2019-12-17 11:25:46 +01:00
Timothee Cour
e8f4586c68 allow typed/untyped in magic procs (#12911) 2019-12-17 11:07:32 +01:00
Timothee Cour
e5ed4c1b7d fix json regression D20191212T144944 (#12902) [backport] 2019-12-15 23:04:06 +01:00
Krzysztof Majk
e4e74a5565 remove unused import (#12900) 2019-12-15 22:59:08 +01:00
BinHong Lee
20a59da401 Add --git.devel option to the documentation 2019-12-15 12:45:57 +00:00
Andreas Rumpf
347a04606b fixes #12885 [backport] (#12895) 2019-12-13 19:20:29 +01:00
Andreas Rumpf
a0aa8fa857 fixes #12874 (#12890)
* fixes #12874

* fixes introduced regressions
2019-12-13 15:36:39 +01:00
cooldome
12d2b980e8 Fixes #12883 (#12894)
* fixes #12883

* fix comment

* add normalize

* fix
2019-12-13 13:30:27 +00:00
cooldome
777c9ad0ef Better clang_cl support (#12896) 2019-12-13 12:12:04 +00:00
cooldome
1e1fd73530 fixes #12882 (#12889)
* fixes #12882
2019-12-13 11:24:05 +00:00
Andreas Rumpf
22b2684608 fixes #12148 [backport] (#12888) 2019-12-12 11:05:18 +01:00
cooldome
94289161f9 invoke createTypeBoundOps for constructors (#12878) 2019-12-11 10:46:20 +00:00
Andreas Rumpf
3524944e21 ARC: fixes cycle detection and move the .cursor attribute into closures (#12872) 2019-12-11 06:57:00 +01:00
Ico Doornekamp
e61d702206 Increased TInstr field sizes: allow long jumps and 65535 VM registers (#12777)
* Increased regBx size from 16 to 24 bits to increase jump range in the VM
from 32K to 8M instructions. Fixes #12727

* Increased VM TInst register field sizes to 16 bits to allow up to 65535 VM registers per proc

* Added test case for >255 VM registers
2019-12-10 19:04:02 +01:00
Andreas Rumpf
b8152b29e8 ARC: yet another bugfix (#12871) 2019-12-10 16:44:54 +01:00
Judd
56cf3403b4 introduce capture macro (#12712)
capture works for more cases than `closureScope`.
2019-12-10 13:16:37 +01:00
PMunch
65fd95bf85 Fix AVR target to define ints properly (#12817)
* Fix AVR target to define ints properly

* Fix more than AVR target

* Test to see how robust not using stdint is

* Fix for namespaces using cstdint

* Fix for pre C++11 compilers when using namespaces
2019-12-10 12:10:33 +01:00
Andreas Rumpf
61d89aae11 completes #12799, fixes #12216 (#12870) 2019-12-10 12:09:48 +01:00
cooldome
13d232ec56 fixes #12827 (#12829) [backport] 2019-12-10 07:08:46 +01:00
Andreas Rumpf
c282cee4db feature dracula themed doc (#12816)
* Implement gorgeous Dracula themed Nim documentation

* Add color for escape sequences

* fixes the test cases

* the big CSS cleanup
2019-12-10 06:48:11 +01:00
cooldome
5929c3da21 fixes #12820 (#12828) 2019-12-09 20:03:23 +01:00
Neelesh Chandola
e4f7656772 Support cross compiling from host to host (#12859) 2019-12-09 13:39:25 +01:00
Neelesh Chandola
7ebb2baa6c Assigning template to var/let/const gives a proper error (#12851)
* Assigning template to var/let/const gives a proper error

* Fix style
2019-12-09 08:19:40 +00:00
Andy Davidoff
a3d45d0c1b add a StringTable.clear that requires no mode specification (#12853)
* add clear overload, test, changelog

* add since annotation
2019-12-09 06:58:36 +01:00
Kevin
a02d043b58 added cstrutils (#12858) [backport]
fixed for 'csuCmpIgnoreStyle' error on hotcodereloading
2019-12-09 06:58:06 +01:00
Neelesh Chandola
ff5ef95414 Fixes #12832 (#12842) [backport]
* Fix #12832
* nimVm -> nimvm in json.nim
* Use suggestSym() instead of markUsed(); Also use styleCheckUse() for finding style violations
2019-12-08 23:27:25 +01:00
Mark
73dd348ddd Manual update: custom exceptions (#12847) [backport]
Said that you can have custom exceptions and showed how to create and raise them.
2019-12-08 21:39:44 +00:00
Elliot Waite
50c1e50184 Add a 32x32 favicon (#12856) 2019-12-08 22:19:35 +01:00
KeepCoolWithCoolidge
ae7b53ec51 Fixes classify function to detect subnormal floating points (#12836)
* Fix classify to test for subnormality.
* Minor fix.
* Modified to maintain existing API.
* Minor change.
* Removed 32-bit case since float is always 64-bit.
2019-12-08 20:17:11 +01:00
Elliot Waite
5da27a891c Removing the mention of using discard for block comments (#12837) [backport]
* Remove mention of using `discard` for block comments

* Add a 32x32 alternate favicon
2019-12-08 20:16:17 +01:00
Mark
0ebc709037 deviated -> derived (#12846) [backport] 2019-12-08 20:15:19 +01:00
Mark
46144a31ab deviated -> derived (#12845) [backport] 2019-12-08 20:14:54 +01:00
Timothee Cour
23fc93fc2d VM: allow ptr setting ptr fields (#12825) 2019-12-06 22:38:53 +01:00
cooldome
7213969901 fixes #12821 (#12822) 2019-12-06 09:56:54 +01:00
Neelesh Chandola
1db21721ec Fixed objects being erroneously zeroed out before object construction (#12814) [backport] 2019-12-05 17:31:51 +01:00
Andreas Rumpf
3fbb3bfd3f ARC related bugfixes and refactorings (#12781) 2019-12-05 16:59:06 +01:00
cooldome
9b0e874687 fixes #12783 [backport] (#12810)
* fixes #12783

* Trigger build
2019-12-05 15:17:45 +01:00
Andrey Makarov
26074f594d nimgrep improvements (#12779)
* fix sticky colors in styledWrite

* nimgrep: context printing, colorthemes and other

* add context printing (lines after and before a match)
* nimgrep: add exclude/include options
* nimgrep: improve error printing & symlink handling
* nimgrep: rename dangerous `-r` argument
* add a `--newLine` style option for starting matching/context
  lines from a new line
* add color themes: 3 new themes besides default `simple`
* enable printing of multi-line matches with line numbers
* proper display of replace when there was another match replaced at
  the same line / context block
* improve cmdline arguments error reporting
2019-12-05 14:42:20 +01:00
Andreas Rumpf
0e7338d65c better support for PROGMEM like annotations for lets/vars; fixes #12216 (#12799) 2019-12-05 13:45:16 +01:00
Clyybber
267fed53ee Fix #12812 2019-12-05 13:22:40 +01:00
itsumura-h
208b018f6b fix db_mysql getRow() when column is null error raised (#12806) [backport]
* fix db_mysql getRow()
* added if y == nil [backport]
2019-12-05 10:28:47 +01:00
cooldome
0987872675 fixes #12804 (#12809) 2019-12-05 07:38:12 +01:00
Araq
de1a283383 fixes #12798 [backport] 2019-12-04 20:38:20 +01:00
Arne Döring
b0c06aa711 fix #12740 (#12774)
* fix #12740

* A different kind of a hack

* proper fix

* fix typo
2019-12-04 07:33:01 +00:00
Timothee Cour
3383985c44 osx: support nanosecond resolution for file stat (eg getLastModificationTime) (#12794) 2019-12-04 08:12:55 +01:00
cooldome
01c7409924 Fix external file recompilation (#12802) 2019-12-03 16:54:42 +01:00
Alex Mitchell
7b562dd43d Update events.nim (#12803)
Removing old username.
2019-12-03 16:54:23 +01:00
genotrance
eed328856f Path substitution for --out and --outdir (#12796)
* Enable pathSubs for --out and --outDir
* Cleanup
2019-12-03 09:26:18 +01:00
Timothee Cour
9e1fd9e46b [minor] fix doc for $(Time) (#12795) [backport] 2019-12-03 09:12:08 +01:00
Tomohiro
378289c6a8 Fixes #12734 (#12784) 2019-12-01 23:21:36 +01:00
Ico Doornekamp
6aade97fe8 Refactored VM registerlayout. The size and location of the registers in (#12775)
the instructions are now all derived from a single definition, allowing
the register layout to be changed.
2019-11-30 13:38:36 +01:00
Jasper Jenkins
0d022622e3 fix nimsuggest deprecation warnings (#12772) 2019-11-30 06:54:15 +01:00
Jasper Jenkins
b6b8d540e3 [backport] always set fileInfoIdx.isKnownFile (#12773) 2019-11-29 22:36:01 +01:00
Euan
c5c6bae2a4 #12103 - CI for FreeBSD (#12179)
* Ref #12103 - adds FreeBSD CI
* Fix getApplFreebsd - length of the string includes the null terminator byte, so minus 1 for result length
* Show last commit in setup task.
* Remove .git from repository URL
* Don't include noisy details showing last commit.
* Add FreeBSD build status badge
* Fix #12182 - disable tconsole on FreeBSD
* Disable tgetaddrinfo on FreebSD as getaddrinfo doesn't support the ICMP protocol.
* Install boehm-gc-threaded
* Use libgc-threaded.so on FreeBSD rather than libgc.so.
* Simplify build failure handling. Update alt text for CI badge.
* Disable test on FreeBSD
* Simplify build config

- use GNU make to build csources
- set PATH variable using the environment key
- remove modification of config to set CC as this is already set

* Install git which seems to be missing from current freebsd images
* Revert change to how path is set
* Add a comment explaining why the length is truncated
* Fix tconsole.
2019-11-29 21:00:54 +01:00
Araq
7e6e399d10 fixes #12669 2019-11-29 19:46:21 +01:00
Araq
b688250202 fixes #12766 2019-11-29 19:46:21 +01:00
Pierre-Jean Grenier
a114a40b57 fix httpclient.lastModified bad pattern in parsing (#12698) 2019-11-29 11:17:10 +01:00
Oscar Nihlgård
5456da3ca9 Fix sequtils.delete bug with out of bounds indexes (#12506) 2019-11-29 11:15:20 +01:00
genotrance
49db2a08ba Fixes #12767 (#12768) 2019-11-29 10:18:44 +01:00
Jasper Jenkins
9ea55eccbb make addQuoted work on nimscript (#12717) [backport] 2019-11-28 23:01:17 +01:00
Araq
0996eb174f fixes #11727 [backport] 2019-11-28 23:00:34 +01:00
Araq
87f0d534d6 fixes #12488 [backport] 2019-11-28 23:00:34 +01:00
Araq
2dea920379 ARC: implemented a simple cycle detector 2019-11-28 23:00:34 +01:00
Clyybber
7e747d11c6 Cosmetic compiler cleanup (#12718)
* Cleanup compiler code base

* Unify add calls

* Unify len invocations

* Unify range operators

* Fix oversight

* Remove {.procvar.} pragma

* initCandidate -> newCandidate where reasonable

* Unify safeLen calls
2019-11-28 17:13:04 +01:00
PMunch
b662842bd0 Fix for 16 bit platforms (#12760) [backend]
This fixes some tiny issues with using Nim on 16-bit platforms. Not
entirely sure why the AVR chip I was compiling for with "cpu = avr" was
detected as 16-bit, but that's probably another issue..
2019-11-28 17:11:56 +01:00
genotrance
010067f3cc Substitute $nimbleDir in --path flags (#12750) 2019-11-28 13:58:38 +01:00
Andreas Rumpf
abe07eb75d VM: improvements for var T/addr (#12667); fixes #12489 2019-11-28 09:56:02 +01:00
Araq
d4cae118dc fixes a flaky test for the realtime GC 2019-11-28 09:33:01 +01:00
3n-k1
0944b0f441 [backport] Fix style issues in lib/, tools/, and testament/. Fixes #12687. (#12754) 2019-11-28 08:32:11 +01:00
Brian Wignall
a7aeabb9d2 [backport] Fix spelling typos (#12755) 2019-11-28 08:30:55 +01:00
Andreas Rumpf
fd85a5ae05 more fixes for --cpu:avr [backport] (#12748) 2019-11-27 16:24:21 +01:00
Araq
80b508d337 test suite: rename tests containing 'fail' for easier search in logs 2019-11-26 16:04:28 +01:00
Araq
72237e2bcf ARC: ported the GC tests over to --gc:arc 2019-11-26 16:04:28 +01:00
Miran
879801c639 increase the timeout for 'tasyncclosestall' (#12744)
This test is very flaky, this change might help reducing the
number of failings (usually solved by restarting the test suite).

Refs https://github.com/nim-lang/Nim/pull/12694#issuecomment-557583790
2019-11-26 14:12:15 +01:00
Timothee Cour
dfe5d115fb fixes #12663 staticRead now creates a dependency for rebuilds (#12731) [backport]
* fix #12663 staticRead
* address comments
2019-11-25 14:44:13 +01:00
Arne Döring
04614a30bd fix in tests/js/tconsole (#12709) 2019-11-25 10:30:22 +01:00
Andy Davidoff
bd8f49cbd3 replace some runtime repr in stdlib for gc:arc (#12716) 2019-11-25 10:13:30 +01:00
tauplus
8debf79837 fix typo in the manual (#12723) 2019-11-25 10:08:22 +01:00
tauplus
bfad0056ab Fix wrong section hierarchy in the manual (#12724) [backport] 2019-11-25 10:06:54 +01:00
Mamy Ratsimbazafy
1f7871ea1c csize_t changes: pinToCpu didn't compile (#12725) 2019-11-25 08:42:19 +01:00
narimiran
015bec6254 Revert "ARC: another critical bugfix; temporary tuples we introduce for tuple unpackaging are not owning the data"
This reverts commit 8b2f8f5430.
2019-11-24 09:50:52 +01:00
Araq
8b2f8f5430 ARC: another critical bugfix; temporary tuples we introduce for tuple unpackaging are not owning the data 2019-11-22 21:41:45 +01:00
Arne Döring
2acf74d458 delete list comprehension (#12392)
The `lc` macro is now part of `graveyard` repository.
2019-11-22 19:57:43 +01:00
Araq
c85e266d1d ARC: yet another silly bugfix 2019-11-22 17:18:11 +01:00
Jack Tang
f0c5d99924 index out of bounds exception when data is empty (#12428) 2019-11-22 15:37:59 +01:00
b3liever
5bb6c67a45 add collect macro (#12708)
* add collect macro

* Add to changelog
2019-11-22 14:40:50 +01:00
Andreas Rumpf
e5478b32a8 fixes #11863 multipart data need $ (#12707)
* fixes #11863
* improved the code; refs #12412
2019-11-22 14:21:03 +01:00
Andreas Rumpf
64e8f050e1 implemented a new localPassc pragma (#12706) 2019-11-22 14:20:15 +01:00
Juan Carlos
c0eeea4f3c Improve head comment on JS (#12548)
* Improve comment on JSGen, replace 12+ concatenations by 1 multiline string

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12548#discussion_r340051147
2019-11-22 11:37:30 +01:00
Andreas Rumpf
f7ba7c711a added the --asm command line option for inspection of the produced assember code (#12699) 2019-11-21 22:53:51 +01:00
Araq
135774d92b thavlak.nim: more idiomatic code 2019-11-21 20:01:43 +01:00
Araq
d45a736cc8 more thavlak.nim improvements 2019-11-21 16:06:04 +01:00
Araq
f07774d064 more thavlak.nim improvements 2019-11-21 16:03:44 +01:00
Araq
48eed1f522 thavlak.nim test: improved the code style 2019-11-21 15:34:45 +01:00
Jjp137
1b2c1bc64a Remove a stray file (#12697) 2019-11-21 11:19:54 +01:00
Andreas Rumpf
78e02d174d fixes #12670 [backport] (#12693) 2019-11-20 19:08:16 +01:00
Andreas Rumpf
c98e0e22ad conversions to unsigned numbers are not checked anymore; implements /… (#12688) [backport]
* conversions to unsigned numbers are not checked anymore; implements / fixes https://github.com/nim-lang/RFCs/issues/175

* change the spec yet again to be less consistent but to make more sense; updated the changelog
2019-11-20 17:08:43 +01:00
Andreas Rumpf
85ffcd80c0 more arc improvements (#12690)
* ARC: bugfix for =destroy for inherited objects
* added code useful for debugging
2019-11-20 14:34:05 +01:00
c-blake
a88004114d Discussion both in (#12678)
https://github.com/nim-lang/Nim/pull/12600
and in
    https://forum.nim-lang.org/t/5499
indicates that everyone is happy/happier with ``pop``.

This just renames the brand new ``take``s to ``pop`` and installs inline
aliases/wrappers to preserve ``Table.take`` and ``TableRef.take``.

Update apis.rst to try to maintain consistency of remove-and-return procs.
2019-11-20 08:39:45 +01:00
Andreas Rumpf
56a00da34a fixes #12612 [backport] (#12681) 2019-11-19 12:09:36 +01:00
Arne Döring
03fa9a9041 fix regression in align (#12680)
* fix regression in align

* add test typesym without type
2019-11-19 09:58:47 +01:00
Andreas Rumpf
5278cf80eb ARC: closure bugfixes (#12677)
* ARC: closure bugfixes
* progress
* ARC closures: create =hooks for captured parameters
* ARC: always destroy constructions like tuples, arrays properly, even in edge cases
* fixes a regression
2019-11-18 12:33:44 +01:00
Dominik Picheta
bab5351d43 Fixes ambiguity errors when evaluating Nimble files. (#12674) [backport]
When trying to evaluate a Nimble file which imports a Nim module
I was getting the following errors for some reason:

```
/Users/dom/projects/nim/lib/pure/parseopt.nim(229, 46) Error: ambiguous call; both system.paramCount() [declared in /Users/dom/projects/nim/lib/system/nimscript.nim(65, 6)] and os.paramCount() [declared in /Users/dom/projects/nim/lib/pure/os.nim(2613, 8)] match for: ()
```
2019-11-18 09:26:06 +01:00
Andreas Rumpf
223e65e529 attempt to add valgrind support to the CIs and testament (#12646)
* attempt to add valgrind support to the CIs and testament

* valgrind (currently) works only on 64-bit Linux
2019-11-18 09:10:48 +01:00
Andreas Rumpf
58f3e07b1a fixes and changes the recently introduced 'alignas' to be 'align' (#12666)
* fixes and changes the recently introduced 'alignas' to be 'align'

* more improvements
2019-11-15 20:24:14 +01:00
Juan Carlos
9c46526cfa Fix htmlgen html lang (#12668) [backport]
* Fix HTMLGen enable lang on html tag
2019-11-15 20:23:03 +01:00
Gampol T
83b7656c0e fixes #12319 - change exception handling for finish.exe (#12413)
* documented behaviour of recv on bufferd socket

* fixes #12319- check exception using errorCode
2019-11-15 13:28:55 +01:00
Andreas Rumpf
76179cbec2 ARC: fixes leaking new() statement (#12665) 2019-11-15 12:38:11 +01:00
Miran
107b40f097 remove two asserts in int128.nim (#12648) [backport]
Before this PR, `tests/misc/tconv.nim` fails when the compiler
is compiled without `-d:danger` flag.
Bear in mind that even without the asserts, the values outside of
a given range are still checked and a meaningful error message
(from `compiler/semexprs.nim`) is printed.
2019-11-15 12:37:43 +01:00
David Krause
ffca3eefb5 fix documentation of $*(dt: DateTime) (#12660)
(cherry picked from commit 39122ecd93)
2019-11-15 08:06:26 +01:00
Andreas Rumpf
a14abc5708 ARC: solves phase ordering problems (#12654) 2019-11-14 23:19:18 +01:00
Araq
f22d3c75aa ARC: closure inside object constructor now works 2019-11-13 23:29:21 +01:00
Araq
bcab3ed06c ARC: handle closures like tuples consistently 2019-11-13 23:29:21 +01:00
Araq
3020e49b75 ARC: use the new .cursor annotation for 'up' pointers 2019-11-13 23:29:21 +01:00
Andreas Rumpf
6ad0238fd7 make tests green again 2019-11-13 23:29:21 +01:00
Araq
25c724d38b gc:arc: support GC_ref/unref for ref T 2019-11-13 23:29:21 +01:00
Araq
eea0cb07cf async: cleaner solution that avoids GC_ref on strings which doesn't exist for --gc:arc 2019-11-13 23:29:21 +01:00
narimiran
a1e7bf81b3 a better way to test Arraymancer 2019-11-13 16:25:43 +01:00
narimiran
8394c00300 remove long-deprecated 'mapIt' 2019-11-13 14:24:25 +01:00
Arne Döring
0496a666e2 implemented alignas pragma (#12643)
* implemented alignas pragma

* fix bootstrap

* generate c++ compatible syntax for alignas

* Make it work.

* Multiple alignof expressions. Implement top level alignof.
2019-11-13 08:22:41 +00:00
Andreas Rumpf
84861eb48a fixes #12644 2019-11-12 23:56:19 +01:00
Andreas Rumpf
dfb020b174 .cursor implementation (#12637)
* cursors: first implementation
* added currently failing test
* .cursor works for doubly linked lists
* make -d:useMalloc work again
* added code to nil out refs in a destructor
* it's now called --gc:arc
* renderer.nim: render nkBreakState properly
* make simple closure iterators work without leaking
2019-11-12 15:05:36 +01:00
Euan
7e689873e2 Fix #12135 and #12109 (#12137)
* Fix #12135 and fix #12109 - fix OpenBSD type defs

* Fix Mode definition as in #12132
2019-11-11 16:18:08 +01:00
b3liever
0c4d81241a Version of trimZeros without temp strings (#12633) 2019-11-11 12:54:17 +01:00
Araq
a4d43d7d0c --gc:destructors: bugfixes 2019-11-09 20:34:51 +01:00
Araq
e835377d3f inhibit silly warning about moving closure environments for performance 2019-11-09 20:33:23 +01:00
Andreas Rumpf
82e0765fc9 --gc:destructors improvements (#12626)
* do not cache the noDestructors transformation
* liftdestructor: improvements
* undo bugfix
2019-11-09 13:21:55 +01:00
Clyybber
144ad36974 Implemented outplace differently (#12599)
* implemented sugar.outplace; refs #12550
* Different approach, allows for chaining
2019-11-09 12:52:31 +01:00
Miran
6958248efe fix #12519: introduce OrderedTable.take, CountTable.del, CountTable.take (#12600)
* add OrderedTable.take

* add CountTable.del and CountTable.take

* add .since pragma to the introduced public procs

* add changelog entry [ci skip]
2019-11-08 16:35:27 +01:00
cooldome
1e71c13697 fix compilation warning (#12618)
* fix compilation warning

* comments incorporated
2019-11-08 09:16:44 +01:00
Volodymyr Lashko
4e841ab156 Fix crash in terminate handler (#12572) [backport]
* fix undefined behavior in terminate handler

* fix failing unit test

* Revert "fix failing unit test"

This reverts commit 0e5e385fbf.

* Revert "fix undefined behavior in terminate handler"

This reverts commit 2b582871f1.

* do not throw inside terminate handler with msvc < 1923
2019-11-07 22:00:34 +00:00
Andreas Rumpf
135e945ff0 make parsexml compatible with --gc:destructors/newruntime 2019-11-07 18:18:51 +01:00
Yanis Zafirópulos
76085e8a45 added support for openArray's for gcd and lcm (#12621) 2019-11-07 18:06:48 +01:00
Arne Döring
a2d6691af2 fix #12597 (#12604) 2019-11-07 17:16:34 +01:00
Judd
8b1ef8e07e allow random module to be used in standalone: (#12617)
proc randomized*() uses time releated function which is not available on
standalone, so disable this function for standalone.
2019-11-07 14:48:33 +01:00
cooldome
e1b1759439 fixes #5050; fixes #11826 (#12606) [backport] 2019-11-07 14:47:26 +01:00
Arne Döring
94675c2378 backtick and export marker handling in eqIdent (#12574) 2019-11-07 14:40:44 +01:00
Andreas Rumpf
372b01711e added 'since' template for further stdlib additions 2019-11-07 14:20:39 +01:00
Andreas Rumpf
f69ee294c8 bugfix that enables the 'since' template [backport] 2019-11-07 14:20:39 +01:00
Andreas Rumpf
14a0182ca6 pragmas.nim: tiny code formatting 2019-11-07 14:20:39 +01:00
narimiran
0d00bde4ea fix failing test 2019-11-07 11:04:41 +01:00
Andreas Rumpf
166048da5d osproc needs 'import linux' for -d:useClone 2019-11-07 09:51:15 +01:00
Andreas Rumpf
230c618eb9 error message: Nim calls it 'proc' 2019-11-07 09:41:04 +01:00
Dominik Picheta
675189c77f Merge pull request #12613 from nim-lang/miran-unused-imports
Remove unused imports
2019-11-06 22:08:43 +00:00
Andy Davidoff
5544a13236 restore --define🔑val in nim.cfg and fix #12367 (#12611) 2019-11-06 21:26:03 +01:00
Andy Davidoff
738c957e94 add --clearNimblePath; fixes #12601 (#12609) 2019-11-06 20:40:22 +01:00
narimiran
717da9f158 [backport] print more information for the previous commit 2019-11-06 16:14:28 +01:00
narimiran
5381c810a8 [backport] rewrite flaky runnable example 2019-11-06 15:54:21 +01:00
narimiran
c6a451c584 remove unused imports from tests 2019-11-06 14:35:45 +01:00
Tor Arvid Lund
5ccbf7e3cf [backport] doc/tut3.rst: Fix typo in Introduction (#12607) [ci skip]
Derivative of `b*pow(x, 2)` is `2*b*x`, while old version had `2*a*x`
2019-11-06 13:42:39 +01:00
narimiran
cc3e9ca164 remove unused imports 2019-11-06 12:01:00 +01:00
Andy Davidoff
61889c604a export nim.cfg parser (#12602) 2019-11-06 09:59:23 +01:00
Federico Ceratto
59c212607e [backport] Add links to packaging and distro pages (#12603) [ci skip] 2019-11-06 09:03:28 +01:00
Araq
d19206755b async: use $ and not repr in debug mode 2019-11-05 17:10:02 +01:00
Araq
1794cd477d expr -> untyped 2019-11-05 16:55:08 +01:00
jiro
0694bd47b9 Add or detectOs(Manjaro) (#12587) [backport]
Using `pacman` command in Manjaro Linux

(cherry picked from commit 1ff3494dab)
2019-11-05 16:21:28 +01:00
Andreas Rumpf
3ba3307d61 remove deprecated procs (#12535) 2019-11-05 11:05:46 +01:00
Miran
ffa9a7405f fix #8242, fix #12586: fix 'formatFloat' with 'precision = 0' (#12592)
* fix #8242, fix #12586: fix 'formatFloat' with 'precision = 0'

'formatFloat' with 'precision = 0' now gives the same result
(a number without a decimal point) in all backends.
This is compatible with Python's formatters, too.

* fix failing tests

* add changelog entry

* add version switch
2019-11-05 10:31:23 +01:00
Andreas Rumpf
46af8164c0 implement the --useVersion emulation feature 2019-11-04 21:58:26 +01:00
Kaushal Modi
b24560a140 Make sequtils.zip return seq of anonymous tuples (#12575)
* Make sequtils.zip return seq of anonymous tuples

Earlier the tuples had named fields "a" and "b" and that made it
difficult to assign the zip returned seqs to other vars which expected
seqs of tuples with field names other than "a" and "b".

* Make sequtils.zip backwards compatible with Nim 1.0.x
2019-11-04 21:11:43 +01:00
Clyybber
cf5c3f2400 Fixes #12379 (#12591) [backport] 2019-11-04 20:57:14 +01:00
alaviss
558ecd1ca6 compiler/suggest: add variable support to con (#12569)
This allows for the type of a variable to be retrieved.
2019-11-04 18:29:26 +01:00
Miran
ae32d637f7 [backport] fix #12395 (#12590)
'countBits32' is now fixed in the same way that
'countBits64' was already patched earlier (by adding 'u32
where needed).
2019-11-04 15:02:36 +01:00
Arne Döring
992f0a7756 fix conversions to uint in varints.nim (#12564) 2019-11-04 13:06:08 +01:00
Andreas Rumpf
62fc3db9d7 --os:ios needs to imply defined(macosx) [backport] (#12585) 2019-11-04 13:05:03 +01:00
narimiran
bdc2bcc36c NimPatch of devel version should be an odd number because of the earlier hacks 2019-11-03 16:04:21 +01:00
Andreas Rumpf
3f4b9971fc newruntime: only check for dangling refs when 'owned ref T' support is enabled 2019-11-03 09:46:49 +01:00
Juan Carlos
4c9a7e6f00 JS improve indent (#12581)
* JSgen make indent be all spaces, instead of mixed spaces and tabs, for generated JS
2019-11-03 08:03:03 +01:00
Andreas Rumpf
ceda586d88 fixes #12577 [backport] (#12584) 2019-11-03 07:55:55 +01:00
Tomohiro
4e0f12092e Fixes #12536 (#12568) [backport] 2019-11-02 08:21:49 +01:00
Andreas Rumpf
44a27ccfe1 --gc:destructors: simple closures work 2019-11-02 00:39:04 +01:00
Andreas Rumpf
7a4d066102 make renderIds work again 2019-11-01 21:02:44 +01:00
Andreas Rumpf
3761e62fde improve codegen quality for --gc:destructors 2019-11-01 09:59:18 +01:00
Kaushal Modi
d914e9a65f [backport] Add docs to better distinguish among getProjectPath, getCurrentDir and currentSourcePath (#12565)
Fixes https://github.com/nim-lang/Nim/issues/10477.
2019-10-31 21:00:18 +01:00
Arne Döring
99078d80d7 introduce csize_t instead of fixing csize (#12497) 2019-10-31 19:18:12 +01:00
genotrance
0c7b6c9c15 Switch mingw links (#12561) 2019-10-31 11:13:32 +01:00
Andreas Rumpf
79a262d6e9 better testing for nimcrypto; re-enable chronos testing (#12560) 2019-10-31 07:18:45 +01:00
Andreas Rumpf
1746da2d9e --gc:destructors now means Nim uses pure refcounting (#12557) 2019-10-30 16:15:17 +01:00
Juan Carlos
b5bb581642 Improve Math.Trunc code emit on JS, had weird whitespaces and indents (#12549) 2019-10-30 14:12:17 +01:00
Nindaleth
34dbc5699e fix several typos in documentation and comments (#12553) 2019-10-30 09:08:45 +01:00
Araq
1214960a1b fixes #12547 [backport] 2019-10-29 15:07:04 +01:00
zah
de5f6a07c2 Fix newLit for objects having string fields (#12542) [backport] 2019-10-28 22:45:55 +01:00
Araq
44b1ecc287 destructors.rst: added a missing 'var' to the motivating example 2019-10-28 18:15:17 +01:00
Andreas Rumpf
e58c2d261c [backport] fix #12528, fix #12525: incorrect generic type resolution for default values (#12538) 2019-10-28 16:56:38 +01:00
Andreas Rumpf
c52a2c3ab0 proof that refcounting can handle Nim's async (#12533) 2019-10-28 16:13:38 +01:00
Solitude
160c07be00 Fix code style errors (#12545) 2019-10-28 15:21:10 +01:00
Anthon van der Neut
c58aa7705d [backport] fix broken link to non-existing c2nim manual html, fixes #12537 [ci skip] (#12544) 2019-10-28 13:51:43 +01:00
Tomohiro
90376940bb Add a changelog entry related to PR #11748 [ci skip] (#12541) 2019-10-28 13:29:13 +01:00
Jjp137
ee119f7984 colors: fix 'mix' template and make most examples runnable (#12532) [backport]
* colors: fix the 'mix' template
* colors: make most examples runnable
2019-10-28 13:11:11 +01:00
Artem V L
580462c886 splitPath() behavior synchronized with splitFile() (#12481)
* splitPath() behavior synchronized with splitFile() having the expected behavior in all languages

splitPath() docstrings update, tests added for both splitPath() and splitFile()

* Path splitting refined and described
2019-10-28 12:58:02 +01:00
Tomohiro
a9d7796e1c [feature]strformat: add 2 'fmt' macros that use specified characters instead of '{}' (#11748)
* [feature]strformat: add 2 'fmt' macros that use specified chars instead of '{}'

* strformat: revert documentation comments of `&` and 'fmt'

* strformat: removed single open/close char variant of fmt
2019-10-28 12:33:44 +01:00
Arne Döring
5ed99f8d3f Extent json.to testing to VM, add workrounds for VM bugs. (#12493)
fixes #12479
2019-10-28 10:06:16 +01:00
Miran
a2ad7d4883 fix deprecation warnings related to Int128 (#12474)
* semfold: fix deprecation warnings related to Int128

* semmagic: fix deprecation warnings related to Int128

* system/io: remove unneeded conversion of TaintedString to itself
2019-10-28 09:58:39 +01:00
Arne Döring
91af075244 integer literal documentation [ci skip] (#12513)
* integer literal documentation [ci skip]

* apply feedback [ci skip]
2019-10-28 09:52:59 +01:00
Andreas Rumpf
7192b13609 some progress on bug #12443 2019-10-27 17:50:30 +01:00
Andreas Rumpf
cbbc2cc237 fixes #12502 2019-10-27 17:50:30 +01:00
Andreas Rumpf
120829155a development version should be 1.1.0 so that version checking can work properly 2019-10-27 17:50:30 +01:00
Andreas Rumpf
0631d2dccc minor improvements 2019-10-27 17:50:30 +01:00
Tomohiro
f3b56e7ac0 Add /nologo option when nim call cl.exe (#12524) 2019-10-27 11:36:38 +01:00
Arne Döring
3c567bcf20 fixes #12514 (#12520) [backport] 2019-10-27 11:34:33 +01:00
Jjp137
3a62cf29d8 Remove sentences referring to the graphics module (#12522) 2019-10-26 04:28:01 -04:00
Artem V L
60ff41a8da '#' value parcing is explained (disambiguated) (#12476) 2019-10-25 15:22:26 +02:00
Jjp137
1d42108fda sequtils: replace deprecated 'random' call within example (#12515) [backport] 2019-10-25 09:47:34 +02:00
alaviss
5b3571c9a4 compiler/semtypes: improve lineinfo for exported object fields (#12495)
The line info should now points to the `a`, not the `*`, like this:
    a*: string
    ^
Additionally this fixes nimsuggest's highlighting of exported object
fields.
2019-10-25 01:06:53 +02:00
Andreas Rumpf
e0d13abaff VM: fixes register leaks [backport] (#12510) 2019-10-25 00:45:06 +02:00
Tomohiro
8040c84615 Fix Nim specify wrong option to vccexe when vcc.options.always is set (#12490) [backport] 2019-10-24 23:43:59 +02:00
Andreas Rumpf
8a599fb571 fixes #12491 [backport] 2019-10-24 22:51:13 +02:00
alaviss
f827d75804 compiler/semcall: return the correct lineinfo for nkCallStrLit (#12484) 2019-10-24 18:21:37 +02:00
Andreas Rumpf
801a794039 VM: fixes most ran-out-registers problems [backport] (#12485) 2019-10-24 17:29:32 +02:00
Federico Ceratto
9ac062b746 [backport] Add link to posix_utils.html - related to #10723 (#12509) 2019-10-24 14:08:59 +02:00
UNIcodeX
d731646106 [backport] Clarifies experimental / parallel example on manual.rst (#12472)
* Clarifies experimental / parallel on manual.rst

Details:
Calling `useParallel()` in example fails with compiler error
  Error: 'parallel' section without 'spawn'

Adding `spawn` causes error:
  Error: internal error: (filename: "ccgexprs.nim", line: 1032, column: 17)
  No stack traceback available
  To create a stacktrace, rerun compilation with ./koch temp c <file>

Therefore a separate proc, `threadedEcho`, is added for the echo'ing
of the string, which allows the example to build, however, `sync()`
must be added so that the "echo in parallel" strings will actually
be shown on the terminal. Otherwise, the program will spawn of the
threads and exit before they can return to the main thread.

* Fixes and clarifies example for threading in manual.rst

Issue:
Calling useParallel() in example failed with compiler error
`Error: 'parallel' section without 'spawn'`

Adding spawn yielded compiler error:
```bash
Error: internal error: (filename: "ccgexprs.nim", line: 1032, column: 17)
No stack traceback available
To create a stacktrace, rerun compilation with ./koch temp c
```

Proposed Solution:
- Separate proc, threadedEcho, is added for the echo'ing
  of the string, which allows the example to build
- Added the thread number so that it can demonstrate that sometimes
  threads which were started sooner, come back after threads which
  were started later.
2019-10-24 14:08:27 +02:00
Miran
b03de8a4d9 Fix many broken links and prefer relative links within docs (#12463)
* Fix many broken links

Note that contrary to what docgen.rst currently says, the ids have
to match exactly or else most web browsers will not jump to the
intended symbol.

* Prefer relative links for Nim documentation

This is more friendly to those browsing the documentation without
a network connection. The nim-doc package in Debian allows this,
for example.

Also, the domain name being used was not consistent. It could have
been either nim-lang.org or nim-lang.github.io, and those reading
the stable docs could have found themselves suddenly reading the
devel docs instead.

* koch.rst: remove link to nonexistent section

* manual.rst: remove unintended link

cast[T](0) is interpreted as a link to id 0 with text T, so escape
the opening parentheses to display the intended output.

* asyncstreams: replace unintended link with emphasis

* Fix word wrapping
2019-10-24 14:07:43 +02:00
Juan Carlos
8f8916413f [backport] Documentation Math module (#12460) 2019-10-24 14:07:21 +02:00
narimiran
2baa21d461 disable package 'chronos' for now 2019-10-24 13:46:59 +02:00
Araq
a03a8e80ea fixes a regression that caused that Nim devel cannot compile 1.0 anymore 2019-10-24 12:27:34 +02:00
Araq
e506c1e0ea fixes a regression that caused that Nim devel cannot compile 1.0 anymore 2019-10-24 12:27:34 +02:00
Araq
619b997c31 ast.nim: slightly better documentation 2019-10-24 12:27:34 +02:00
Oscar Nihlgård
3d0c756a3c Fix JS bug in std/monotimes (#12499) [backport] 2019-10-24 11:24:26 +02:00
Oscar Nihlgård
4ac100c912 Fix jsgen bug with uninitialized seq (#12500) [backport] 2019-10-24 11:17:01 +02:00
Oscar Nihlgård
9ccfcf5dd2 Fix compiler crash caused by top level return (#12501) 2019-10-24 11:04:04 +02:00
narimiran
822078ed12 add changelog for v1.0.2 2019-10-23 14:35:31 +02:00
Arne Döring
8d3d97aa9b no html comments in issue template [skip ci] (#12496) 2019-10-23 12:08:17 +02:00
narimiran
d5cd5b00b9 disable flaky test on OSX 2019-10-23 11:24:43 +02:00
narimiran
2120fb2777 [backport] package chronos now has dependencies 2019-10-23 11:20:12 +02:00
Arne Döring
fe4a59f12b fixes #12453 (#12475) 2019-10-23 10:29:12 +02:00
narimiran
c90b4ecddc Revert "[ci skip] disable two packages until #11764 is merged"
This reverts commit 48975bb3e7.
2019-10-23 07:09:08 +02:00
Jjp137
3ad48069d3 Fix word wrapping 2019-10-22 17:59:12 -07:00
Jjp137
e6d5379b3b asyncstreams: replace unintended link with emphasis 2019-10-22 17:59:12 -07:00
Jjp137
59c1f7c87f manual.rst: remove unintended link
cast[T](0) is interpreted as a link to id 0 with text T, so escape
the opening parentheses to display the intended output.
2019-10-22 17:59:12 -07:00
Jjp137
79aa58979c koch.rst: remove link to nonexistent section 2019-10-22 17:59:12 -07:00
Jjp137
72147c9ba4 Prefer relative links for Nim documentation
This is more friendly to those browsing the documentation without
a network connection. The nim-doc package in Debian allows this,
for example.

Also, the domain name being used was not consistent. It could have
been either nim-lang.org or nim-lang.github.io, and those reading
the stable docs could have found themselves suddenly reading the
devel docs instead.
2019-10-22 17:59:12 -07:00
Jjp137
93461aee34 Fix many broken links
Note that contrary to what docgen.rst currently says, the ids have
to match exactly or else most web browsers will not jump to the
intended symbol.
2019-10-22 17:59:12 -07:00
Dominik Picheta
6bfa4eb6c5 Merge pull request #12371 from rayman22201/IOSelector_unregister_fix
Test + fix for epoll and kqueue selector modules to properly unregister event handles that have the key type "User"
2019-10-22 11:32:22 -07:00
Dominik Picheta
92fa7e0579 Merge branch 'devel' into IOSelector_unregister_fix 2019-10-22 11:31:38 -07:00
Artem V L
049032432c Docstring refined for the getSectionValue() (#12478) [backport] 2019-10-22 18:20:25 +02:00
Paul Tan
ad3c10022a guards.nim:sameTree(): handle uint literals correctly (#12483) [backport] 2019-10-22 18:18:33 +02:00
Andy Davidoff
2ccd1c3428 tweaked for clarity after editing to fix a typo (#12473) 2019-10-22 13:54:48 +02:00
Andreas Rumpf
38b3590e40 fixes #12310 [backport] (#12470) 2019-10-20 22:37:31 +02:00
Arne Döring
ec20fd3544 fix #12426 (#12462) 2019-10-20 11:52:50 +02:00
ducdetronquito
df4c339cfc Namespace unittest enums to avoid name conflicts (#12468) [backport]
* [backport] Fixes: #12465 - Unittest - Namespace the usage of TestStatus enum to avoid name conflicts.
2019-10-20 08:12:02 +02:00
Araq
0eae2217b6 first implementation of the new --seqsv2 switch 2019-10-20 08:11:07 +02:00
Araq
ed2fb36bc6 refactoring: use the new strings and seqs when optSeqDestructors is active 2019-10-20 08:11:07 +02:00
Araq
61ea85687c refactoring: --newruntime consists of 3 different switches 2019-10-20 08:11:07 +02:00
Ray Imber
91661c16a1 Update changelog.md based on feedback from Dom96 2019-10-19 14:30:10 -07:00
Andreas Rumpf
832b0a0232 fixes #12420 [backport] (#12456) 2019-10-18 22:13:24 +02:00
Tomohiro
6b157e5f73 Fix vcc linker option name (#12422) 2019-10-18 16:20:18 +02:00
Andreas Rumpf
889b745b2b Revert "Fixes #12187 (#12321)" (#12447)
This reverts commit 00c31e8766.
2019-10-18 15:59:22 +02:00
Juan Carlos
f5b4d9a2e5 Fixes #8802 (#12439)
* Fix #8802

* Peer review feedbacks https://github.com/nim-lang/Nim/pull/12439#discussion_r335905397
2019-10-18 14:27:23 +02:00
Juan Carlos
4a0debfe87 Add no-ident for GCC when -d:release (#12454) 2019-10-18 14:13:55 +02:00
Juan Carlos
0a6e0a3f38 Improve htmlgen (#12452) 2019-10-18 12:16:01 +02:00
Miran
a5ab502f08 [backport] fix type's case in random.nim (#12445) 2019-10-17 22:13:00 +02:00
Andreas Rumpf
81125e2029 [backport] add back a check that got accidentically removed; fixes #12379 (#12444) 2019-10-17 20:02:59 +02:00
Juan Carlos
4d1f69c7d2 Fixes #10824 (#12437) 2019-10-17 11:39:01 +02:00
Juan Carlos
2cfd58de48 Fix #10804 (#12438) 2019-10-17 11:37:55 +02:00
Juan Carlos
1ccf1b89c2 Improve jsconsole adding the rest of the stable api as documented on the standard at https://developer.mozilla.org/docs/Web/API/Console (#12440) 2019-10-17 11:37:08 +02:00
Arne Döring
21cbfd72ec Refactor json macro (#12391)
* closes #12316
* make tjsonmacro work at js target
* closes #12289
* closes #11988
* also fixed gdb related stuff
2019-10-17 09:55:41 +02:00
treeform
5ba932e43c About 50% faster base64 implemention. (#12436) 2019-10-17 09:50:00 +02:00
Ray Imber
bec8225448 Updated the changelog 2019-10-16 19:14:18 -07:00
Ray Imber
bef1c4437d fixes based on code review by @dom96
- For clarity: Changed the unregister if statement to use the in operator instead of
the set intersection operator in ioselectors_epoll.nim and
ioselectors_select.nim.

- Fixed unregister of Event.User case on the Android branch.
2019-10-16 14:13:09 -07:00
alaviss
37dfb7ecc6 compiler/options: only check the last folder for a candidate (#12421)
This prevents a nimble file from causing a different project to be
targeted instead of the desired one.
2019-10-16 13:03:11 +02:00
Miran
734da9e1df fixes #11764, faster hashing of (u)int (#12407) 2019-10-15 16:31:07 +02:00
Miran
5f5ac8ce16 [backport] fix #12418, fix random.randomize on JS backend (#12432) 2019-10-15 16:29:32 +02:00
Yuriy Glukhov
1aed455e7c Fixed yield in nkCheckedFieldExpr (#12429) [backport] 2019-10-15 09:16:06 +02:00
narimiran
48975bb3e7 [ci skip] disable two packages until #11764 is merged 2019-10-14 11:51:41 +02:00
Ray Imber
233455a685 Remove unnecessary change to ioselectors_kqueue.nim found by @cheatfate. 2019-10-11 12:24:29 -07:00
Alexander Ivanov
990aadc43c Fixes semCustomPragma when nkSym (#12414) [backport] 2019-10-11 18:05:23 +02:00
alaviss
94c1695be6 compiler/options: improve project file detection (#12404)
The compiler can now correctly find the project file of a nimble package.
The algorithm is based on what used by nim.nvim, which has yielded good
results.
2019-10-11 18:04:52 +02:00
alaviss
f957266574 nimsuggest: add a command that returns the project file (#12411)
This can be used to let nimsuggest users know which project is
nimsuggest being in charge of, so they can know when should a new
nimsuggest instance be spawned.

An additional feature is to debug the project file finding feature.
2019-10-11 18:00:38 +02:00
alaviss
eeffa0163f nimsuggest: add option to force finding the project file (#12409) 2019-10-11 09:55:15 +02:00
Arne Döring
7cf3395d85 refactor illegal iterator assignment detection (#12212)
* refactor illegal iterator assignment detection

* delete crappy test
2019-10-11 08:43:58 +02:00
Jasper Jenkins
245a954b25 ungeneric unsigned ops (#12230)
* ungenericise unsigned ops, remove nimNewShiftOps
* fix/remove tests
* update t6448
* fix line info
* disable on 32bit
* fix different line info
* add changelog entry
2019-10-11 08:38:08 +02:00
genotrance
9e62876647 Fixes #12286 - require explicit disabling of boehm interior pointer checking (#12406) [backport] 2019-10-11 07:39:18 +02:00
Ray Imber
4e6f2b5313 Fix drain to correctly take into account hasPendingOperations and the timeout value 2019-10-10 17:53:44 -07:00
Ray Imber
aa84d35d86 Fix io slector unregister for windows as well. 2019-10-10 16:50:36 -07:00
Euan
45030972b9 #12389: Check working directory for getAppFilename() (#12390)
* Check working directory for exe
* Expand symlinks
* Use expandFilename() to expand symlinks
* Move OpenBSD code to getApplOpenBsd()
2019-10-10 17:28:47 +02:00
Arne Döring
0a29c05a1b fix #12332 (#12402) [backport] 2019-10-10 14:35:26 +02:00
Andreas Rumpf
00e06bba28 minor improvements for htmlgen.nim 2019-10-10 13:47:55 +02:00
Andreas Rumpf
d783c0f7ff fixes a koch regression that made 'koch boot --listcmd' not work anymore [backport] (#12400) 2019-10-10 11:56:01 +02:00
Araq
7f904e2c66 fixes #12244 [backport] 2019-10-10 10:00:57 +02:00
awr1
3b1760df72 [backport] Mention "lambdas" and => in the manual (#12397) [ci skip]
(so that "lambda" can be CTRL+F'd)
2019-10-10 09:28:54 +02:00
Andreas Rumpf
f728614ef8 fixes #12366 [backport] (#12393) 2019-10-09 14:48:42 +02:00
Gampol T
82fe19769a documented behaviour of recv on bufferd socket (#12374) 2019-10-09 10:48:15 +02:00
Nindaleth
84c956d9da fix a few dead links and a missing sentence in documentation (#12387) 2019-10-08 15:24:34 -04:00
Andreas Rumpf
f30da2f266 fixes #12315 [backport]; refs #12314 (#12385) 2019-10-08 20:49:45 +02:00
Clyybber
00c31e8766 Fixes #12187 (#12321)
* Fixes #12187
* Point to fork of compactdict
Since the original repo is now archived / read-only
2019-10-08 14:15:47 +02:00
alaviss
edb24b7ce0 nimsuggest: fix tcp socket leak for epc backend (#12384) [backport]
Same as e9fa4c9b9c, but for the epc
backend which is used by emacs and vscode plugin.

Since the EPC backend only deal with one connection per nimsuggest
instance, only one socket is leaked, thus not as servere as with the tcp
backend.
2019-10-08 14:14:18 +02:00
Ray Imber
7c23522b29 Documentation improvements around the db interface (#12362)
Added more details about the limits and reasoning behind the API.
Came about from this discussion on IRC: https://irclogs.nim-lang.org/04-10-2019.html#16:58:04
2019-10-08 11:24:06 +02:00
Ridho Pratama
7ef4bffa79 renderer letAux fix only for octal literal (#12343)
* renderer letAux fix only for octal literal

* Handle when it's octal -1 for i64

* Added testcases
2019-10-08 11:12:24 +02:00
treeform
dbcffcfccb Easier build instructions for windows - just run build_all.bat. (#12276)
* Easier build instructions for windows.

* title letter

* Update build_all.bat to be like build_all.sh
2019-10-08 11:00:37 +02:00
pietroppeter
89c37fada7 [doc/tut1] removed discard discussion in comments (#12352) 2019-10-08 09:08:38 +02:00
alaviss
e9fa4c9b9c nimsuggest: fix tcp socket leak (#12377) [backport]
A new socket is created for each iteration and leak immediately thanks
to the accept() call replacing the created socket with the client socket.

This commit fixes that.
2019-10-08 08:11:18 +02:00
cooldome
0355c64b92 External file compilation improvement (#12380) 2019-10-08 08:10:55 +02:00
Tomohiro
509f53b782 On windows, os.relativePath returns path as is when roots are different (#12329)
* On windows, os.relativePath returns path as is when roots are different
* Implement os.sameRoot without windows API
* Fix compile error when compiling lib/nimhcr.nim
* Fix compile error when compiling lib/nimhcr.nim on Windows
2019-10-07 19:57:16 +02:00
Ray Imber
b347490f91 lowered the number of events in the test because some CI's have an extremely low FD limit 2019-10-07 10:07:05 -07:00
Federico Ceratto
f9d95fd6a7 Refactor closeEmitter to make it more modular (#12365) 2019-10-07 17:26:27 +02:00
Andreas Rumpf
a60f18d025 fixes #12323 [backport] 2019-10-07 06:47:30 +02:00
Andreas Rumpf
9d000c519a render typeof as typeof 2019-10-07 06:47:30 +02:00
Ray Imber
0338516e70 Additional fix for User key unregister in the KQueue backend 2019-10-06 17:33:58 -07:00
Ray Imber
adc1419499 Test + fix for epoll and kqueue selector modules to properly unregister
event handles that have the key type "User"
2019-10-06 16:02:12 -07:00
Andreas Rumpf
5be8e0b088 VM: no special casing for big endian machines; refs #9690 [backport] (#12364) 2019-10-06 19:28:53 +02:00
Federico Ceratto
a03d8ed4c2 Expose some layouter elements, improve readme (#12361)
Useful for writing linters and static code analysis
2019-10-04 22:43:47 +02:00
Ico Doornekamp
26676066cc added cpuTime to VM (#12346)
* added cpuTime to VM

* Hide VM-time cpuTime() behind --benchmarkVM flag
2019-10-04 19:32:16 +02:00
kraptor
412011eb96 Fix reference to parseSpec proc in readme (#12359) 2019-10-04 19:30:58 +02:00
Hideki Okamoto
294d5fb560 Fixes #12010; Add the description for "cc" option into --fullhelp (#12350) 2019-10-04 19:30:20 +02:00
Miran
2909e41370 [backport] bundle nimpretty on Windows (#12358) 2019-10-04 17:13:04 +02:00
Andreas Rumpf
60d64d1aef use system.move instead of system.shallowCopy if the GC mode requires it 2019-10-04 09:48:45 +02:00
Andreas Rumpf
68ce808db1 minor optimization for asynchttpserver.nim 2019-10-04 09:48:45 +02:00
Andrew Owen
64acc9dbfb [backport] Fix typo in docs (#12356) [ci skip] 2019-10-04 08:40:15 +02:00
Dominik Picheta
4ab9b6146b Change future version number in changelog 2019-10-03 21:26:20 +01:00
Ridho Pratama
678775601a Fixed sizeOf to sizeof (#12347) 2019-10-03 19:38:37 +02:00
Leorize
73c8391fd3 azure: disable failing tests 2019-10-03 18:36:18 +02:00
Leorize
acebcd7899 testament: add azure integration 2019-10-03 18:36:07 +02:00
Leorize
880df4de62 azure-pipelines: add pipelines for linux, mac and win
This is the equivalent to the current AppVeyor + Travis setup.
2019-10-03 18:35:54 +02:00
Andreas Rumpf
c51857f434 fixes #12291 [backport] (#12338) 2019-10-03 07:50:32 +02:00
Ico Doornekamp
982086dbe9 Fixed #12337, leaking pipe after gorge (#12339) 2019-10-03 00:48:31 -04:00
hlaaftana
ba43156363 Sets need copying in JS (#11392)
* Sets need copying in JS
* Fixes #11353
* Add test for #11353
2019-10-02 21:01:59 +02:00
zah
ad13e18c7c system.writeFile has been overloaded to also support openarray[byte] (#12313) 2019-10-02 20:34:03 +02:00
Timothee Cour
2446570350 fixes #12330 (#12331) 2019-10-02 17:57:24 +02:00
Andreas Rumpf
98e76a1058 fixes #12336 [backport] 2019-10-02 17:01:27 +02:00
narimiran
032c3b77db test more packages 2019-10-02 12:35:18 +02:00
Andrew Smith
0d94ee15c0 Updated the code example in the os module to use better grammar. (#12328) 2019-10-02 00:43:38 -04:00
Jasper Jenkins
c20778d2d3 Macro docs additions (#12270)
* small macros doc additions

* more changes

* fixes [ci skip]

* capitalization, couple additions

* nkNodeKind to nnkNodeKind
2019-10-01 08:55:26 -04:00
Clyybber
5f5879dc4c Refactor injectdestructors (#12295)
One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.
2019-10-01 14:09:24 +02:00
Tomohiro
64d5e25821 Fix how relativePath handle case sensitiviy (#12312) [backport] 2019-10-01 09:09:59 +02:00
Andreas Rumpf
6dd4cbc3af fixes #12240 [backport] (#12308) 2019-10-01 05:52:51 +02:00
zah
a4ade43536 macros.newLit now works for ref object types (#12307) 2019-09-30 22:24:57 +02:00
Andreas Rumpf
dd082b6ec8 fixes #12264 [backport] (#12302) 2019-09-30 21:44:24 +02:00
Andreas Rumpf
72acf5de94 fixes #12281 [backport] 2019-09-30 20:42:16 +02:00
Andreas Rumpf
1964589a29 fixes #12294 [backport] 2019-09-30 20:01:25 +02:00
narimiran
5732bb41ef [backport] run nimpretty on the remaining files 2019-09-30 13:58:17 +02:00
narimiran
34d0be2ec1 [backport] run nimpretty on os-related stuff 2019-09-30 13:58:15 +02:00
narimiran
dcf3181bd1 [backport] run nimpretty on string stuff 2019-09-30 13:58:13 +02:00
narimiran
0ca9cc7419 [backport] run nimpretty on web stuff 2019-09-30 13:58:11 +02:00
narimiran
15895ebc3f [backport] run nimpretty on hashes 2019-09-30 13:58:10 +02:00
narimiran
b17ed2ca9c [backport] run nimpretty on parsers 2019-09-30 13:58:08 +02:00
narimiran
6c994b2498 [backport] run nimpretty on numbers stuff 2019-09-30 13:58:05 +02:00
narimiran
aa513d78e7 [backport] run nimpretty on async 2019-09-30 13:57:58 +02:00
Araq
63bcbea700 JS: gensym is stricter for 'this'; refs #12246 [backport] 2019-09-30 13:21:46 +02:00
Araq
c5a1149e00 different fix for #12279 [backport] 2019-09-30 13:11:24 +02:00
Araq
0ecf3806c4 fixes #12298 2019-09-30 12:06:41 +02:00
Araq
86de2cddf6 fixes #12279 [backport] 2019-09-30 10:40:00 +02:00
Clyybber
16c39f9b2e More of StringStream now works at compile time (#12284)
* readLine of StringStream now works at compile time
* Work for js backend only at compile time
* readAll now works at CT
* readAll works in js ct now
* Add test
2019-09-29 22:20:00 +02:00
Clyybber
85db42ad8c Fixes #10514 (#12268)
* Fixes #10514

(cherry picked from commit f6f789bb4d)

* Add comment

* Add changelog entry
2019-09-28 19:50:20 +02:00
Andrey Makarov
5a65243e14 fix nimgrep color on posix #7591 (#12288) 2019-09-28 00:19:57 +02:00
narimiran
f804245087 [backport] fix nimpretty removing space before pragma 2019-09-27 10:36:22 +02:00
narimiran
e0cd52365c [backport] fix #12278, don't expose internal PCRE documentation 2019-09-27 10:13:04 +02:00
narimiran
ce4eb4ac91 Nim now has Patreon account [ci skip] 2019-09-27 08:22:46 +02:00
Federico Ceratto
39290cf88c Fix spellings (#12277) [backport] 2019-09-27 07:02:54 +02:00
Ray Imber
9dd297f613 Locks modules should give a compile error when threads are not enabled. (#12231)
* Locks modules should give a compile error when threads are not enabled.

* fix the compile flags to make the tests pass, or ignore files where necessary.

* Fixed when statement to account for doc builds.
2019-09-26 15:45:50 +02:00
John Paul Adrian Glaubitz
944fcc0e62 Add build support for Linux/hppa (#12271)
* build.sh: Enable CPU detection for hppa
* compiler: Add hppa as target architecture on Linux
* lib/system: Add platform support for hppa
2019-09-26 15:45:05 +02:00
Endeg
657e09e79d Fix #12242, replacing ":" with "@c" in packages [backport] (#12265) 2019-09-25 20:32:36 +02:00
Mathias Stearn
920f9be9aa Explicitly state that trailing underscores are banned (#12257)
It was explicit in the BNF, but the English text implied it was allowed.
2019-09-25 19:12:54 +02:00
Andreas Rumpf
5f44651769 updated the contributing.rst guidelines 2019-09-25 15:01:35 +02:00
narimiran
6b4b329f45 devel version is 1.0.99 [ci skip] 2019-09-25 09:14:38 +02:00
Jjp137
e065e51245 threadpool: fix link in docs [ci skip] (#12258) [backport]
[backport]
2019-09-25 07:12:08 +02:00
treeform
cbefb266bb Fix -d:logGC compile cerror: 'stdout not defined' (#12237) 2019-09-24 12:02:53 +02:00
Jasper Jenkins
b49fb2d90f remove nimnomagic64 (#12243) 2019-09-24 12:02:25 +02:00
Andreas Rumpf
13960066cb fixes the --verbosity:2 regression [backport] 2019-09-24 01:31:03 +02:00
narimiran
f7a8fc46c0 Revert "improvements for httpcore (#12228)"
This reverts commit b865c2a54b.
2019-09-23 19:06:55 +02:00
narimiran
5b43c98897 version 1.0 2019-09-23 14:42:19 +02:00
Andreas Rumpf
f388817a79 update the Nimble version we ship with Nim (#12236) 2019-09-23 14:24:36 +02:00
Andreas Rumpf
b865c2a54b improvements for httpcore (#12228)
* improvements for httpcore
* further improvements, now stable API but needs extensions later on
2019-09-23 12:38:35 +02:00
Ray Imber
6e681b546f fixes #9026 adds a readLineImpl to streams so that FileStreams can be fast (#12234) 2019-09-23 08:25:26 +02:00
PMunch
2565d3d102 Fix issue with long wait for passed timer [bugfix] (#12221)
* Fix issue with long wait for passed timer [bugfix]

This fixes a small issue where a timer that had been completed while
code executed would still wait for more events before being considered
completed. This would in some scenarios incur a 500ms delay to the
completion of a timer.

* Refactor logic into

* Add test case based on original issue

* Use longer timeouts to be more lenient in checking

* Revert to short timeouts, but widen the accepted range

* Widen accepted range further, it is meant to check for a 500ms delay after all

* Increase poll timeout to make it easier to detect mistakes
2019-09-22 07:24:14 +02:00
Andreas Rumpf
39185b46ca living in unix-land, eye to eye, where nothing ever works; fixes #12226 2019-09-21 19:07:25 +02:00
Andreas Rumpf
e0f2b3ba8f documentation updates 2019-09-21 11:53:09 +02:00
Andreas Rumpf
b04ef2973d cleanup importjs implementation 2019-09-21 11:19:09 +02:00
cooldome
be82d11576 fixes #12224 (#12225)
* fixes #12224

* improve test
2019-09-21 06:45:27 +02:00
Andreas Rumpf
c2fced129f makes tests green again 2019-09-21 06:43:37 +02:00
Araq
5abe880469 last stdlib cleanups 2019-09-21 06:43:37 +02:00
Araq
9776f926a2 htmlgen update; don't use deprecated callsite feature 2019-09-21 06:43:37 +02:00
Araq
908b553215 asyndispatch: removed deprecated setEvent proc 2019-09-21 06:43:37 +02:00
Araq
96b3bae99b json: removed deprecatedGet pragma 2019-09-21 06:43:37 +02:00
Araq
a404ec540a updated lib.rst and added some useful missing modules 2019-09-21 06:43:37 +02:00
Araq
dea9e38d26 removed the deprecatedGet pragma 2019-09-21 06:43:37 +02:00
Araq
c623ab62cc updated comment in ast.nim 2019-09-21 06:43:37 +02:00
Araq
f576df2bcc smtp: renamed starttls to startTls 2019-09-21 06:43:37 +02:00
Araq
05e80e1cda lib\pure\htmlgen.nim
avoid callsite for htmlgen
2019-09-21 06:43:37 +02:00
Araq
7839658323 mark events.nim as unstable 2019-09-21 06:43:37 +02:00
Araq
1b20f768c7 lib.rst cleanups and reorderings 2019-09-21 06:43:37 +02:00
Arne Döring
38ab51c445 importjs symbol (#12218)
* importjs symbol
* importjs warning message, minor warning fixes
2019-09-20 20:26:30 +02:00
Andreas Rumpf
7bc5bf8334 consistent floating point output (#12219)
* unify float printing
* makes tests green
2019-09-20 10:41:40 +02:00
Araq
04c803d6df expose more fields of TNimType 2019-09-19 20:54:17 +02:00
Andreas Rumpf
162d74db91 fixes #10981; fixes #7261 (#12217) 2019-09-19 14:34:56 +02:00
treeform
363d0ada50 Update Android and iOS cross compile docs. (#12215)
* Update Cross compilation, add noMain section.

* Small world update, note about XCode clean.
2019-09-19 13:22:07 +02:00
treeform
a948deebb3 Add --os:ios switch and docs. (#12204) 2019-09-18 20:03:51 +02:00
Arne Döring
188ce5f3ee add nodeId proc to macros (#11456)
* add nodeId proc to macros

* add doc comment.

* fix typo
2019-09-18 20:02:30 +02:00
Araq
f8000d4ba1 fixes #12186 2019-09-18 12:16:52 +02:00
Araq
48537fec81 fixes #12209 2019-09-18 12:16:52 +02:00
Arne Döring
638a4d9d9f rename cast opcodes, fix for 32bit cast, fix python pretty printer (#12207) 2019-09-18 09:04:37 +02:00
Vitor Oliveira
93f74e4f93 Fix typo (#12210) [ci skip] 2019-09-18 07:17:38 +02:00
treeform
910ed5888e Add -d:androidNDK to fix echo on Android NDK builds. (#12203)
* Add -d:echoToAndroidLog to fix echo.

* Change to androidNDK and add docs.

* Some word changes to docs.
2019-09-17 23:00:06 +02:00
Miran
618316beb9 fix #12200, cannot 'inc' CountTable by a negative value (#12208)
* fix #12200, cannot 'inc' CountTable by a negative value

* use Positive
2019-09-17 21:29:25 +02:00
Araq
ea8a049af3 fixes the testcase 2019-09-17 15:15:12 +02:00
Araq
c9f3a8b269 added a testcase for #12195; testament now supports a 'timeout' spec field 2019-09-17 15:15:12 +02:00
Araq
f1b7c0494e fixes #12195 2019-09-17 15:15:12 +02:00
Andreas Rumpf
62aa1a3cfe gc:destructors progress 2019-09-16 23:54:31 +02:00
Andreas Rumpf
77c6425e65 gc_common: typo 2019-09-16 23:54:31 +02:00
Andreas Rumpf
754531fff3 make --useVersion's documentation reflect reality 2019-09-16 23:54:31 +02:00
Andreas Rumpf
059a16b34d fixes #12193 (#12199) 2019-09-16 15:38:07 +02:00
Andreas Rumpf
2a59f499e9 some gc:destructors progress 2019-09-16 13:54:58 +02:00
Araq
6c487a6309 fixes #12196 2019-09-16 12:12:44 +02:00
Araq
8b4c17a140 better implementation 2019-09-16 12:12:44 +02:00
Andreas Rumpf
3f87453981 fixes a weird quote do regression 2019-09-16 12:12:44 +02:00
Andreas Rumpf
1c03604ec6 make tests green again 2019-09-13 20:11:01 +02:00
Araq
fd63443419 changed name mangling for generated C files 2019-09-13 19:11:48 +02:00
Araq
5018e7f304 fixes #12172 2019-09-13 18:12:38 +02:00
narimiran
ee6df5bd24 close #7104 by writing a test 2019-09-13 07:59:38 +02:00
narimiran
d79fb77974 close #6731 by writing a test case 2019-09-13 07:46:46 +02:00
Andreas Rumpf
eb241f4241 count 64 bits at a time instead of 8 (#12159)
* count 64 bits at a time

* spacing

* only do 64bts on x86

* add amd64

* use while
2019-09-12 08:20:53 +02:00
Jasper Jenkins
ca7bf3be8b no commas for empty importcpp splat params (#12183) 2019-09-12 08:19:53 +02:00
Brent Pedersen
5b923cd149 use while 2019-09-11 15:40:34 -06:00
Yuriy Glukhov
5783cd67a8 Fixed c filenames mangling (#12161) 2019-09-11 20:47:58 +02:00
Andreas Rumpf
e134a722de fixes #12152 (#12165)
* fixes #12152

* makes test green
2019-09-11 20:28:24 +02:00
Andreas Rumpf
8c81cddf7e fixes #12170 (#12176) 2019-09-11 20:01:09 +02:00
Andreas Rumpf
560eef5bbe fixes #12171 (#12173) 2019-09-11 18:35:13 +02:00
Brent Pedersen
944bab4c3c add amd64 2019-09-11 08:39:33 -06:00
Brent Pedersen
5a520a8454 only do 64bts on x86 2019-09-11 08:35:44 -06:00
Andreas Rumpf
33b8a00aa8 Revert "Refactored injectdestructors.nim (#11926)" (#12169)
This reverts commit 20dec10722.
2019-09-11 15:39:40 +02:00
Arne Döring
c55ceafd9a add tensordsl test (#12166)
* add tensordsl test

* simpler
2019-09-11 13:36:35 +02:00
Araq
99425ff21d fixes #12174 2019-09-11 11:59:12 +02:00
Benny Elgazar
ee36931f26 Fix to the relevant path of the docs. (#12162) 2019-09-10 17:50:03 +02:00
Araq
cf99c9bfb5 fixes #12051 2019-09-10 09:43:37 +02:00
Andreas Rumpf
d363eced3a closureiters.nim: finish the bugfix 2019-09-10 08:50:05 +02:00
Andreas Rumpf
1fa1024ddf typo 2019-09-10 08:36:24 +02:00
Andreas Rumpf
58077450cc parsejson: typo 2019-09-10 08:36:24 +02:00
Yuriy Glukhov
5d9c1544bf Allow ProcTy in addPragma and friends (#12158) 2019-09-10 07:54:51 +02:00
Yuriy Glukhov
60911304b4 Fixed yield in nnkChckRange (#12160) 2019-09-10 07:54:06 +02:00
Brent Pedersen
81c23bba7b spacing 2019-09-09 20:20:35 -06:00
Brent Pedersen
92f2d68802 count 64 bits at a time 2019-09-09 20:00:28 -06:00
Clyybber
ed1d41c51e Small ast.nim cleanup (#12156)
* Remove sonsLen
* Use Indexable
2019-09-09 11:54:15 +02:00
Andreas Rumpf
aa95ae6af9 Merge pull request #12153 from dumjyl/get_type-range
fix range.getType crash
2019-09-08 23:09:41 +02:00
Andreas Rumpf
f915064e07 fix #12130 ; improve naming scheme in fakePackageName (#12149)
* fix #12130 ; improve naming scheme in fakePackageName

* fix tests
2019-09-08 20:33:18 +02:00
Jasper Jenkins
e5139b0662 error for NimNode index kind (#12154) 2019-09-08 20:31:22 +02:00
Araq
18135cc194 proper bugfix 2019-09-08 13:08:41 +02:00
Araq
790f5bac01 added a simple debugging helper 2019-09-08 13:08:41 +02:00
Araq
3255b55266 fixes #11675 2019-09-08 13:08:41 +02:00
Araq
8362d92e47 fixes #12091 2019-09-08 13:08:41 +02:00
Araq
4bbafb47dc streams.nim: indentation change 2019-09-08 13:08:41 +02:00
Timothee Cour
3eb89481cb fix tests 2019-09-06 15:49:25 -07:00
Timothee Cour
4129993689 fix #12130 ; improve naming scheme in fakePackageName 2019-09-06 11:26:48 -07:00
pgkos
5a8fddf29b Fix mode_t posix definitions (fixes #12119) (#12132)
* fixes #12119
2019-09-06 20:15:07 +02:00
Andreas Rumpf
e0f3e8432a fixes a critical --gc:boehm regression 2019-09-06 18:06:08 +02:00
Euan
0e01a5f76c Fix #12133 - use libgc.so.4.0 for OpenBSD (#12134) 2019-09-06 14:31:39 +02:00
Euan
24f52d855c #12141 Define SDL lib name for OpenBSD and FreeBSD (#12143)
* Define SDL lib name for OpenBSD and FreeBSD

* Merge Linux and FreeBSD definitions
2019-09-06 12:57:38 +02:00
Timothee Cour
32769c478b exportc now mangles same as importc, fixes #10578 (#12144)
* fixes #10578
* add tests
* add changelog
* add {.exportcpp.}
2019-09-06 12:54:44 +02:00
Andreas Rumpf
8397554315 fixes #12125 (#12131)
* fixes #12125
2019-09-06 07:23:59 +02:00
Jasper Jenkins
40c5175145 fix range.getType crash 2019-09-05 15:56:44 -07:00
Andreas Rumpf
488f3ed085 fixes yet another gensym regression (#12145) 2019-09-06 00:45:00 +02:00
Araq
0882a09986 fixes a subtle tables.nim regression 2019-09-05 16:45:07 +02:00
Araq
49f63d3aae ic: update to serialize paddingAtEnd 2019-09-05 16:45:07 +02:00
Andreas Rumpf
a5e2db2ac5 allows access to .compileTime vars at runtime (#12128) 2019-09-05 11:56:32 +02:00
Andreas Rumpf
58bcf6cd46 fixes #12121 (#12126) 2019-09-05 08:21:01 +02:00
Andreas Rumpf
c2ba0ee144 Merge pull request #12124 from narimiran/nimsuggest-108
fixes nimsuggest/#108: RangeError with d:release
2019-09-05 00:31:37 +02:00
narimiran
92c012d86d fix commands for testing packages 2019-09-04 14:58:22 +02:00
narimiran
a9c7fb2fcc fixes nimsuggest/#108: RangeError with d:release 2019-09-04 13:31:59 +02:00
Araq
fa5707e7e2 fixes #11713, fixes #1034 2019-09-04 11:20:30 +02:00
Andreas Rumpf
cb0450398a introduce --oldgensym:on rather than --useVersion 2019-09-03 20:15:27 +02:00
Andreas Rumpf
07a986afa1 disable IC and the SQLite dependency for version 1 2019-09-03 18:43:57 +02:00
Andreas Rumpf
ea1a26294f prepare sqlite3 wrapper for static linking 2019-09-03 18:43:23 +02:00
Andreas Rumpf
459fbb9525 appveyor config: don't stop after testing failures; keep testing Nimble packages 2019-09-03 17:24:57 +02:00
Andreas Rumpf
4972d797e4 gcbench: better memory usage report 2019-09-03 12:39:49 +02:00
Chris Heller
35f1519ad6 Add delOutputFormatter proc to unittest.nim (#12032) 2019-09-03 08:14:19 +01:00
Andreas Rumpf
79f1b8592a Merge pull request #12107 from nim-lang/uint-range-checks
Uint range checks
2019-09-03 07:47:56 +02:00
Andreas Rumpf
ac6fcab7a4 Merge branch 'devel' into uint-range-checks 2019-09-02 22:03:10 +02:00
Andreas Rumpf
d70e292571 makes more tests green 2019-09-02 22:03:06 +02:00
Andreas Rumpf
5a03eea518 revert #12100; typeof(nil) is weird enough, don't allow it as the return type 2019-09-02 17:48:06 +02:00
narimiran
545ddf4a4f mark nimprof as used when profiling 2019-09-02 16:00:26 +02:00
Andreas Rumpf
f8f96d816c sink as lvalue (#12108) 2019-09-02 15:49:01 +02:00
Andreas Rumpf
7ef85db9a9 fixes #12020 (#12106) 2019-09-02 15:47:56 +02:00
Araq
18ca1788f0 makes test green again 2019-09-02 14:23:05 +02:00
Araq
fc7fe636e2 improvement for 'unused import' warnings 2019-09-02 12:49:31 +02:00
Araq
23c44f009a weaking unsigned/signed indexing requirements in order to not break too much existing code 2019-09-02 12:07:36 +02:00
Arne Döring
3d4ad9739c fix min/max for float numbers (#12068) 2019-09-02 11:21:26 +02:00
Andrii Riabushenko
ba18c12005 sink as lvalue 2019-09-02 10:11:51 +01:00
Araq
755c4428fe added more tests and updated the changelog 2019-09-02 11:03:08 +02:00
Araq
2396f0ee71 make test green 2019-09-02 10:56:51 +02:00
Araq
e765687646 Merge branch 'devel' into uint-range-checks 2019-09-02 10:27:35 +02:00
Araq
e6ec88d4c3 renamed and moved test 2019-09-02 10:27:33 +02:00
Araq
ad82e65387 gc:destructors progress 2019-09-01 23:28:26 +02:00
Miran
ab48d7901e hashes: implement murmur3 (#12022)
* hashes: implement murmur3
* refactoring; there is only one murmurHash and it works at compile-time via VM hooks
* fixes JS tests
* makes toOpenArrayByte work with C++
* make it bootstrap in C++ mode for 0.20
2019-09-01 00:04:10 +02:00
Oscar Nihlgård
35268c500f Fix int literals and range interaction (#11197)
* Fix int literals and range interaction

* Fix test

* remove float range fix; update changelog
2019-08-31 19:34:08 +02:00
Arne Döring
6e01be34ef fixes #11903 (#11908) 2019-08-31 19:32:59 +02:00
Andreas Rumpf
326a333c8b Merge pull request #12099 from cooldome/destructor_too_late
fixes #12092
2019-08-31 19:25:19 +02:00
Andreas Rumpf
15213028b7 Return typeof(nil) (#12100)
* Allow typeof(nil) as a return type

* $typeof(nil) is now "typeof(nil)", not "nil"
2019-08-31 19:24:44 +02:00
cooldome
2b565aad89 Support iterators returning lent T (#11938)
* lent iterators
* rebase tests
* update changelog
* fix comments, more tests
2019-08-31 19:23:54 +02:00
Albert Safin
a6428657e9 $typeof(nil) is now "typeof(nil)", not "nil" 2019-08-31 10:16:26 +00:00
Albert Safin
efe1bed82e Allow typeof(nil) as a return type 2019-08-31 10:16:26 +00:00
Andrii Riabushenko
a388c35741 support forward declared destructors 2019-08-31 09:56:39 +01:00
Andrii Riabushenko
a055f628f4 fixes #12092 2019-08-31 09:49:47 +01:00
Timothee Cour
9ae0dd611f typeToString can now show (recursively) resolved type aliases; fixes #8569 #8083 #8570 (#11678)
* nested typeToString
* typeToString: preferResolved
* add test
* fix test
* preferMixed
* fix tests
2019-08-31 08:26:45 +02:00
Clyybber
f9600b7207 Remove ENDB (#12095) 2019-08-31 07:44:53 +02:00
Andreas Rumpf
82d5e773e3 make testament a tool we ship with Nim; fixes #12084 (#12088)
* make testament a tool we ship with Nim; fixes #12084
* moved config to fit
* adapt testament tests to use the testament binary
2019-08-30 15:43:07 +02:00
narimiran
25581c796f enable testing of more packages 2019-08-30 08:47:58 +02:00
Clyybber
029dcc6259 fix #12037 (#12089) 2019-08-30 06:41:26 +02:00
Andreas Rumpf
2a3b056314 fixes #12042 (#12083)
* fixes #12042

* make tests green again
2019-08-29 19:09:54 +02:00
Araq
d0e5bd2305 fixes a critical type checking regression 2019-08-29 12:10:31 +02:00
Andreas Rumpf
9203d3a982 fixes 5870 (#11704)
* fixes #5870
* make tclosure test green again
* this check is correct but breaks some Nimble packages
2019-08-29 07:49:58 +02:00
Andreas Rumpf
cd106cf680 fixes #12074 (#12080) 2019-08-29 07:43:35 +02:00
Andreas Rumpf
5f7a6aff06 fixes #11941 (#12079) 2019-08-29 00:35:05 +02:00
Andreas Rumpf
21fc8b4d4d refactor sizealignoffset (#12077)
* small refactoring
* refactor computeObjectOffsetFoldFunction with AccumObject
* refactor packed object offstes fold function
* refactor compute union object offsets fold function
* merge normal/packed object offset fold function
* compiletime offsetof in c++ inheritance objects
* enable c++ inheritance offsetof tests
* correct alignment for big sets/enums on weird 32bit platforms
* uncomputedSize -> unknownSize
* workaround for travis
* fixes win32 alignment problems
2019-08-28 19:36:29 +02:00
Jacek Sieka
42d2e68bca only store finally block in exception stack (#11876) 2019-08-28 12:08:54 +02:00
cooldome
c9f49cbc0a lift destructor for openarray (#12073)
* destroy for sink openarray
2019-08-28 12:07:46 +02:00
Ico Doornekamp
84351da9d8 Fixes #12044 (#12071) 2019-08-28 12:05:07 +02:00
Andreas Rumpf
d4af0554c4 remove unicode.Rune16 without deprecation period; fixes https://github.com/nim-lang/RFCs/issues/151 (#12072) 2019-08-28 10:25:13 +02:00
Clyybber
20dec10722 Refactored injectdestructors.nim (#11926)
One improvement over #devel is visible in the transformation of getEnv. With this approach we move to result whenever possible.
2019-08-28 00:02:48 +02:00
Andreas Rumpf
eaebbfa785 Fix several float range issues (supersedes #11905) (#12067)
* Fix several float range issues

* address the comments
2019-08-27 23:19:41 +02:00
Arne Döring
d564130a3b Fix to int to biggest int (#12066)
* fix to(Biggest)Int
* kill toFloat magics as well
2019-08-27 23:18:46 +02:00
Vindaar
eff0837ff4 fixes #12015 by also checking kind of typeNode (#12016)
* fixes #12015 by also checking kind of `typeNode`

If a tuple field is aliased it'll appear the same as a ref type in a
call to `getType` if only for the kind of the resulting `NimNode` is
checked (that is a `nnkBracketExpr`)

* fix test case due to #12017 and add more realistic test case

Adds an additional test case, which includes generics and is closer to
the real failure I encountered

* remove previous fix and fix differently after all

The previous fix was incomplete, because it failed for generics.

Note that the `of "tuple"` is not actually needed, the
`nnkBracketExpr` branch in the `else` branch would catch it too, but I
decided to introduce it for clarity. However, the latter is actually
needed, because it seems for aliases of `seq` we end up in it.

* update comment about global `%` proc in json test
2019-08-27 22:23:47 +02:00
Andreas Rumpf
00d46ca1c0 fixes #12024 (#12065) 2019-08-27 20:05:40 +02:00
Andreas Rumpf
114da04cbb fixes #12029; finish the 'unused import' feature (#12064) 2019-08-27 19:18:56 +02:00
Artem V L
d8177a3980 Typos fixed, handleRefillChar() described (#12062) 2019-08-27 16:16:32 +02:00
Andreas Rumpf
8df745a42e fixes #12056 (#12063) 2019-08-27 16:15:37 +02:00
narimiran
3f5599b344 disable testing of 'norm' package 2019-08-27 15:03:06 +02:00
narimiran
329e169e96 address the comments 2019-08-27 14:49:32 +02:00
Oscar Nihlgård
def6234903 Fix several float range issues 2019-08-27 14:45:19 +02:00
Jacek Sieka
66a8856152 abort is noreturn (#12061) 2019-08-27 14:27:44 +02:00
Arne Döring
ab8241ad42 minor stuff 2019-08-27 12:28:18 +02:00
Araq
1ccff0324c manual: more precise rules about evaluation order 2019-08-27 12:13:06 +02:00
Araq
ddc155af64 fixes #12040 2019-08-27 10:20:12 +02:00
Andreas Rumpf
b044523c5a fixes 9195 (#12055) 2019-08-27 10:07:42 +02:00
Andreas Rumpf
5a9edb222b unicode.nim: fixed spacing to something sane 2019-08-26 23:30:35 +02:00
Andreas Rumpf
97d77bf37e semtypes.nim: more refactorings for liftParamType 2019-08-26 23:30:35 +02:00
Andreas Rumpf
0c41fd0f50 semtypes.nim: little refactoring for liftParamType 2019-08-26 23:30:35 +02:00
Andreas Rumpf
d8d2a9e985 manual: better documentation for implicit generics 2019-08-26 23:30:35 +02:00
Dominik Picheta
8117a949c5 Remove old and unused parseBody/parseResponse procs in httpclient. (#11949) 2019-08-26 20:27:44 +02:00
Arne Döring
ae9bb4474b fixes #12033 (#12039) 2019-08-26 20:14:21 +02:00
Palash Nigam
88814bbe98 fixes #11832 (#12049) 2019-08-26 20:13:41 +02:00
Andreas Rumpf
931ee0ca82 fixes #7258 (#12054) 2019-08-26 20:12:22 +02:00
Viktor Kirilov
5df7d72afe HCR: tests for the fixes for #11608 and #11996 (#12047)
* tests for #11996 and #11608

* removed unnecessary comment
2019-08-26 20:08:18 +02:00
nc-x
73dd73f961 [ci skip] Add note to nimhcr.nim (#12050) 2019-08-26 19:20:24 +02:00
Andreas Rumpf
ce7f29e8e6 fixes #11833 (#12018) 2019-08-24 06:25:47 +02:00
Viktor Kirilov
f2e8c39e85 - adding _actual as a suffix only for calls to an actual proc and not through a global function pointer - fixes https://github.com/nim-lang/Nim/issues/11996 (#12007)
- adding forward declarations for reloadable functions within a module - fix compilation errors when 2 such functions reference each other - fixes https://github.com/nim-lang/Nim/issues/11608
- preserve permissions of copied executable binaries
2019-08-23 22:50:34 +02:00
Andreas Rumpf
547fcd69c3 rdstdin: remove cruft that shouldn't have been exported or added (#12014) 2019-08-23 21:34:22 +02:00
Andreas Rumpf
c3c5839329 Add build support for FreeBSD/PowerPC64 (#12011)
* Add build support for FreeBSD PowerPC64

* Add build support for FreeBSD PowerPC64

* Add build support for FreeBSD PowerPC64
2019-08-23 18:59:52 +02:00
Andreas Rumpf
fbb2763204 fixes #11958 (#12013) 2019-08-23 18:58:55 +02:00
Andreas Rumpf
b07694cd90 new gensym handling (#11985)
* new .gensym implementation
* make astspec test green again
* introduce a --useVersion switch to group compatibility switches
* fixes #10180
* fixes #11494 
* fixes #11483
* object constructor fields and named parameters are also not gensym'ed
* disabled broken package
2019-08-23 16:15:02 +02:00
lenoil98
2212a90458 Add build support for FreeBSD PowerPC64 2019-08-23 07:56:56 -04:00
lenoil98
e1539c7344 Add build support for FreeBSD PowerPC64 2019-08-23 07:54:02 -04:00
lenoil98
806f3b592f Add build support for FreeBSD PowerPC64 2019-08-23 07:50:50 -04:00
Palash Nigam
f28a47ea7b fixes #11834 (#12000) 2019-08-23 07:42:33 +02:00
Andreas Rumpf
9aad99bdfd closes #7117 2019-08-22 19:08:35 +02:00
Andreas Rumpf
085fbcea6f fixes #10854 2019-08-22 18:57:41 +02:00
Andreas Rumpf
9eee15f668 thavlak: code style changes 2019-08-21 22:03:04 +02:00
Federico Ceratto
170cb4f4cb Update OpenSSL example (#11896)
* Update OpenSSL example

Fix privkey filename.
Bump up RSA key size.
Add ECDSA example.
2019-08-21 20:01:17 +02:00
Arne Döring
a562de2d91 squashed and merged with devel 2019-08-21 19:24:36 +02:00
Timothee Cour
2b2efe3dbe fix compiletimeFFI (#11991) 2019-08-21 09:28:16 +02:00
Arne Döring
5304b16a55 Fix typos. Apply title case. (#11987) 2019-08-21 00:04:01 +02:00
Oscar Nihlgård
4264e9576d Consider range type of runtime discrim [feature] (#11432) 2019-08-20 17:39:49 +02:00
Andreas Rumpf
d00c8febee Nimpretty: fix #11937 (#11978)
* cosmetic improvements

* remove unused imports
* make 'openPars' and 'closedPars' more readable

* nimpretty: fix #11937 (wrong indentation)
2019-08-20 16:03:04 +02:00
Araq
b1b0960c36 fixes #11972 2019-08-20 15:47:04 +02:00
Miran
75baaa5e25 nim check, fix #11927, no more empty strings (#11979) 2019-08-19 22:25:21 +02:00
narimiran
ceb742351a nimpretty: fix #11937 (wrong indentation) 2019-08-19 13:35:10 +02:00
narimiran
cf4390a24a cosmetic improvements
* remove unused imports
* make 'openPars' and 'closedPars' more readable
2019-08-19 13:29:45 +02:00
Andreas Rumpf
742862b847 more enhancements for #11618 (#11976)
* finish the Windows IO layer changes; refs #11618
* added system.getOsFileHandle which is less error-prone on Windows
* make tests green again
2019-08-18 22:57:56 +02:00
nc-x
ac7a365137 Fix HCR crash because certain procs were hcrGetProc'ed before being hcrRegisterProc'ed (#11971) 2019-08-18 14:16:51 +02:00
nc-x
d5840e1e3d Implement isExported for symbols in macros (#11963)
* Implement isExported for macros

* Reimplement isExported using VM callback mechanism

* VM does not support exceptions, use stacktrace() instead.
2019-08-18 11:51:28 +02:00
Andreas Rumpf
7cb31455ee fixes #11618 (#11969) 2019-08-17 21:19:57 +02:00
nc-x
b68380f09b fixes #11872; include now gives a proper error message for all invalid infix operators (#11965) 2019-08-17 19:45:47 +02:00
Andreas Rumpf
db9e27dffd Fixes #11118 (#11964)
* fixes #11118

* Reset closure iter exception before rethrowing
2019-08-17 10:37:38 +02:00
nc-x
cf09ef47b8 Remove duplicate line number from 'invalid forward declaration' error (#11966) 2019-08-17 10:35:25 +02:00
Andreas Rumpf
15e681ce66 fixes 'e' command handling; now only does what advopt.txt claims it does (#11961)
* fixes 'e' command handling; now only does what advopt.txt claims it does
* address Timothee's remark
2019-08-16 18:19:30 +02:00
Yuriy Glukhov
721ca3e830 Reset closure iter exception before rethrowing 2019-08-16 17:26:00 +02:00
Araq
39f4a3e418 fixes #11801 2019-08-16 15:20:39 +02:00
Araq
b9dd972c32 fixes #11770 2019-08-16 14:48:32 +02:00
Araq
7023241aaf fixes #11819 2019-08-16 14:37:52 +02:00
Araq
bebda3851f fixes #1188 2019-08-16 13:29:58 +02:00
Araq
c7e77edecc fixes #11925 2019-08-16 12:33:31 +02:00
Andreas Rumpf
ba577c7e1b better tojsstr (#11954)
* JS: rewrote toJSStr
* JS: don't raise exceptions in primitives
2019-08-16 12:18:51 +02:00
Timothee Cour
cf22dec584 genSym symbols rendered as b1_416049 instead of b1416049 (#11960) 2019-08-16 12:17:20 +02:00
Araq
1fb9a6d946 added destructors.rst spec to the build documentation 2019-08-16 12:14:39 +02:00
Yuriy Glukhov
d31404ac27 Merge branch 'cpp_reraise_fix' into yield-in-try-fix 2019-08-16 10:25:09 +02:00
Timothee Cour
922e2a5098 refs #11956 (#11957) 2019-08-16 07:19:34 +02:00
Timothee Cour
511298242d fixes #10053 (#11951) 2019-08-15 15:55:48 +02:00
pgkos
296dfae8af Fixes splitfile (#11918) [bugfix] 2019-08-15 15:22:14 +02:00
Dominik Picheta
b095203f28 Fixes regression introduced by #11904. (#11948) 2019-08-15 06:05:38 +02:00
Timothee Cour
630e18a6eb refs #11947; FieldError fixed (#11950) 2019-08-15 06:04:38 +02:00
Arne Döring
a25d43ca6b fix warnings in system.nim (#11944) 2019-08-14 17:48:11 +02:00
Arne Döring
65ed2d7fe8 fixes #11942 (#11945) 2019-08-14 17:41:44 +02:00
Clyybber
e6cb7e34ef Make name mangling reversable unambiguously (#11939) [bugfix] 2019-08-14 08:11:50 +02:00
cooldome
5ef62fcb25 newruntime for vcc (#11934) [bugfix] 2019-08-14 08:10:59 +02:00
narimiran
1874b3e786 [nobackport] add a changelog entry for the previous commit 2019-08-13 07:38:07 +02:00
Fabian Keller
83397a69fc Consistent behavior of exec; Improved docs around exec, staticExec, gorgeEx, etc. (#10967)
* improved docs around exec, staticExec, gorgeEx, etc.
* incorporate review comment; made behavior of exec consistent
2019-08-13 07:41:08 +02:00
Andreas Rumpf
433613e267 fixes #11844 (#11935) 2019-08-13 06:37:37 +02:00
Araq
322ce1872f fixes #10689 2019-08-12 14:06:48 +02:00
Araq
289b5e9ef9 fixes #11254 2019-08-12 13:58:35 +02:00
sschwarzer
c9c28bf85e Update documentation on xmltree.items/mitems (#11930)
* Update documentation on `xmltree.items`/`mitems`

So far the documentation on `items` and `mitems` wasn't explicit about whether the iteration recurses down the node's children or not. I assumed recursion, which was wrong.

* Improve wording in comment

Use the more common and shorter word "direct".
2019-08-12 11:12:22 +02:00
Andreas Rumpf
da64c8762f destructors: spec reflects reality, =sink is here to stay 2019-08-11 21:55:47 +02:00
Andreas Rumpf
212ae2f125 fixes #11891 2019-08-10 15:41:24 +02:00
Araq
0e4a8bfb28 fixes 'unused module' feature for 32 bit builds of Nim for good [nobackport] 2019-08-09 16:38:10 +02:00
Araq
da37177ac2 make tests green again on 32bit systems 2019-08-09 10:12:32 +02:00
Andreas Rumpf
3b8f721460 merged #11813 manually [bugfix] 2019-08-08 23:09:27 +02:00
Zachary Carter
082c440f13 Fixes effect error in pure/logging.nim (#11898)
* Fix effect error in pure/logging.nim

Currently calling `logging.log` will produce - `Error: can have an unlisted effect: RootEffect`. Add `RootEffect` to list of tags.

* the only tag necessary is RootEffect since all other Effects are descendants of RootEffect
2019-08-08 22:48:25 +02:00
Andreas Rumpf
81ddc67785 [refactoring] compiler: simplified markUsed 2019-08-08 22:43:58 +02:00
Andreas Rumpf
04708742e7 fixes #11809 2019-08-08 21:41:05 +02:00
Andreas Rumpf
e3c0bf48c5 tiny style change [refactoring] 2019-08-08 18:30:10 +02:00
Andreas Rumpf
0d5bd7e8b5 removed unused imports [refactoring] 2019-08-08 17:03:19 +02:00
Arne Döring
44e7a7b6c2 Lock semchecked ast for macros (#11883) [bugfix]
* reject to modify type checked AST
* add flag to back out
* Introduce legacy feature set.
2019-08-08 16:57:06 +02:00
Timothee Cour
fda51b6ca2 fix crash on sigmatch (#11913) 2019-08-08 14:41:23 +02:00
Dmitry Matveyev
756fabb979 Fix typo (#11910) 2019-08-08 13:17:53 +02:00
Arne Döring
48968f3c84 delete expensive call (#11909) [refactoring] 2019-08-08 09:16:07 +02:00
konradmb
addd7b5e20 Fix issue #10726 - HTTP response without Content-Length is not accessible (#11904)
* Add patch by @xenogenesi

* Async test for HTTP/1.1 without Content-Length

* Apply suggestions from code review

Co-Authored-By: Dominik Picheta <dominikpicheta@googlemail.com>
2019-08-08 08:41:56 +02:00
Andreas Rumpf
c8cffaf420 Incremental compilation (IC): Improvements (#11881)
* IC: C codegen is aware of IC
* manual: minor change to make VSCode's RST plugin render it properly
* IC: minor refactoring
* testament: code refactorings
* rodutils: removed dead code
* IC: always build the compiler with the IC feature
* IC: C codegen improvements
* IC: implement the undocumented -d:nimMustCache option for testing purposes
* IC: added first basic tests
* IC: extensive testing of the deserialization feature
* testament: refactoring; better IC tests
* IC: removes 'nimMustCache' flag; readonly does the same
* testament: minor refactoring
* update Nimble version
* testament: removed dead code and imports; IC: added simple test
* IC: progress
2019-08-08 08:41:05 +02:00
Andreas Rumpf
c0d240b8cd fixes #11807 (#11900)
* fixes #11807
* make tests green again
2019-08-07 22:40:58 +02:00
amzak
f34ae81971 Fixed handling of empty strings for encodings conversions (#11897) 2019-08-07 19:56:42 +02:00
awr1
9321b33cd2 Typeclass/Variant clarification in Manual (#11901)
* [Docs] clarified what type classes do in manual

* [Docs] fixed 'dynamism', added to object variant section
2019-08-07 16:03:32 +02:00
Arne Döring
afbcd1b330 int128 on firstOrd, lastOrd and lengthOrd (#11701)
* fixes #11847
2019-08-07 15:53:16 +02:00
Andy Davidoff
8407a57499 note set[T].len alias in future changelog (#11893)
per comments in #11885
2019-08-06 21:07:26 +02:00
amzak
3d7d5cf121 Fixed utf8<->utf16 conversions on windows (#11888) 2019-08-06 03:30:47 -04:00
Arne Döring
ce148e71ef disallow static in return type (#9686) [nobackport] 2019-08-06 01:26:53 +02:00
Andreas Rumpf
42e83ac24c fixes #11817 (#11889) 2019-08-05 16:48:26 +02:00
Andy Davidoff
d208d7a995 set[T].len is an alias for set[T].card (#11885) [feature] 2019-08-05 14:27:45 +02:00
Araq
61c66abbfe newruntime: make system.delete and friends work with owned ref (bugfix); reported on the forum 2019-08-05 00:14:30 +02:00
Araq
7024bb800c fixes #11844 2019-08-04 23:54:29 +02:00
John Paul Adrian Glaubitz
65d1140d11 Add build support for Linux/ia64 (#11880) [feature]
* compiler: Add ia64 as target architecture on Linux
* build.sh: Enable CPU detection for ia64
2019-08-04 23:16:30 +02:00
Arne Döring
b73d097d36 fixes #9829 (#11849) 2019-08-04 19:31:55 +02:00
Chris Heller
343ace8194 Skip db_postgres.setRow if getRow returns 0 rows (#11859)
Fixes nim-lang/Nim#11821
2019-08-04 19:28:24 +02:00
Leorize
51d998390c tgetaddrinfo: disable ICMP tests for Haiku
They're not supported by Haiku's getaddrinfo()
2019-08-04 12:15:17 +01:00
Leorize
df32c45757 tgetaddrinfo: use sizeof() instead of hardcoding
OS like Haiku have a bigger sockaddr_in struct for legacy(?) reasons.
Using sizeof() should account for the different struct sizes.
2019-08-04 12:15:17 +01:00
Oscar Nihlgård
bcfb540e57 Allow typeof(nil) as generic parameter (#11869) 2019-08-03 10:16:07 +02:00
Oscar Nihlgård
50e921bb94 VM exception fixes (#11868) 2019-08-02 22:59:04 +01:00
Jjp137
a906b3952b random: minor documentation updates (#11831)
Add docs for the sample procs that take in sets, and clean up a
few other minor things.
2019-08-02 02:42:18 -04:00
Oscar Nihlgård
829f719670 Fix VM conversion to var type [bugfix] (#11866) 2019-08-01 17:44:12 +02:00
Arne Döring
803406d07c fix #11854 (#11857) 2019-07-30 17:24:42 +02:00
Dominik Picheta
bb949a75db Fixes subtle SSL recvInto bug.
This resulted in a "value out of range: -1" exception inside `recvInto`
(on the `copyMem` line). Basically readIntoBuf was returning `-1`.
2019-07-27 19:06:56 +01:00
Andreas Rumpf
ceb1a1b688 IR: minor refactoring 2019-07-27 14:01:28 +02:00
Andreas Rumpf
f58d87cb43 IC: some progress 2019-07-27 14:01:28 +02:00
Andreas Rumpf
c9c8fa99cc destructors spec: be more precise about temporaries 2019-07-27 14:01:28 +02:00
Andreas Rumpf
b9c15371a3 nimgrep: introduce the --rex option 2019-07-27 14:01:28 +02:00
Andreas Rumpf
f7c99838e2 nimgrep: fixes the -w option 2019-07-27 14:01:28 +02:00
Andreas Rumpf
25e6c53bb5 makes the -d:nimIncremental compiler mode compile again 2019-07-27 14:01:28 +02:00
Arne Döring
1a77040278 fix #11812 (#11829)
* fixes #11812
* fixes #10899
* fixes #11367
2019-07-27 07:21:47 +02:00
Giovanni Petrantoni
2fdba334da Use proper types according to MSDN and fix clang build of windows dynlib (#11828) 2019-07-26 10:11:21 +02:00
Andrii Riabushenko
4c73139316 revert changes 2019-07-25 23:18:20 +01:00
Andrii Riabushenko
95856ab8d3 add test 2019-07-25 23:07:43 +01:00
Andrii Riabushenko
d7bc4e43a2 fixes #11826 2019-07-25 23:02:04 +01:00
Miran
3bb6d1916e fix #11772, JS random seed was too large (#11820) 2019-07-25 04:53:50 -04:00
narimiran
3ccda773d6 close #11166 by adding a test 2019-07-25 10:05:02 +02:00
narimiran
13190435a6 close #9891 by adding a test 2019-07-25 09:25:18 +02:00
genotrance
44aadd50cf Fix #10630 - fix broken separators in nim doc (#11814) 2019-07-24 14:45:05 +02:00
narimiran
5484352d26 fix asyncftpclient examples [ci skip] 2019-07-24 11:49:06 +02:00
Timothee Cour
8c93c692b9 run runnableExamples in the module scope (#11732) [feature] 2019-07-22 16:22:57 +02:00
narimiran
30f2cec671 fix failing JS tests 2019-07-22 11:41:20 +02:00
Benjamin Summerton
46f2271968 Add opacity to JS Style
I noticed this was missing.  It has cross browser support: https://developer.mozilla.org/en-US/docs/Web/CSS/opacity#Browser_compatibility
2019-07-21 23:15:36 +01:00
cooldome
d563efb719 fixes #11792 (#11793) 2019-07-21 16:53:22 +02:00
Araq
67a6effb7b fixes #11745 2019-07-19 22:38:35 +02:00
Araq
affe1be47c fixes #11790 [nobackport] 2019-07-19 22:24:56 +02:00
Araq
dc38b88f7e bugfix: it should be [UnusedImport] [nobackport] 2019-07-19 19:33:56 +02:00
Araq
1868cbc449 revert the bugfix for #11747 as it really was a new, poorly though-out feature 2019-07-19 19:32:13 +02:00
Araq
5a020d641d style improvements; fixes #11774 2019-07-19 17:25:04 +02:00
Araq
313cc337f2 fixes a 'nim check' regression 2019-07-19 17:09:11 +02:00
Araq
de69e1856f installer: ship nimpretty.exe on Windows 2019-07-19 16:48:27 +02:00
Andreas Rumpf
70e8551e37 async macro: general stability improvements [bugfix] (#11787) 2019-07-19 16:47:38 +02:00
Jörg Wollenschläger
903d06bab8 Fix the range of destroyed elements when shrinking a seq (#11785) 2019-07-19 16:46:47 +02:00
Andreas Rumpf
a5d6080a81 Merge pull request #11766 from nim-lang/araq-detect-unused-imports
[feature] detect unused imports
2019-07-19 01:06:45 +02:00
Andreas Rumpf
fbb0642e27 Merge branch 'devel' into araq-detect-unused-imports 2019-07-18 18:16:32 +02:00
Andreas Rumpf
9852cf804b warn about unused imports; fixes an 'export' regression [nobackport] 2019-07-18 18:16:25 +02:00
Araq
6d8913ee14 nimpretty: fixes #11616 2019-07-18 12:13:22 +02:00
Araq
7deb49e992 nimpretty: fixes #11699 2019-07-18 11:28:25 +02:00
Araq
5b7273b4f8 [refactoring] nimpretty 2019-07-18 11:00:29 +02:00
Andreas Rumpf
4becd5a2a8 Merge pull request #11771 from nim-lang/araq-remove-unused-imports
[refactoring] remove unused imports in the compiler and in some stdli…
2019-07-18 08:48:11 +02:00
Araq
07d465ca42 [refactoring] remove unused imports in the compiler and in some stdlib modules 2019-07-18 00:36:03 +02:00
Araq
4137a4dbf3 [feature] detect unused imports 2019-07-17 22:36:23 +02:00
narimiran
f50e4500c2 update changelogs [ci skip] 2019-07-17 21:20:28 +02:00
Andreas Rumpf
745669ac25 fixes #11758 [nobackport] 2019-07-17 20:06:10 +02:00
Kaushal Modi
d40872bf9b [bugfix] Make std/unicode compile with --styleCheck:error (#11763) 2019-07-17 19:48:15 +02:00
Kaushal Modi
404b224945 [bugfix] Make std/unittest compile with --styleCheck:error (#11762) 2019-07-17 19:47:50 +02:00
Andreas Rumpf
210988c532 [refactoring] don't use 'defer' 2019-07-17 16:36:40 +02:00
Andreas Rumpf
1acb9bae94 Merge pull request #11743 from GULPF/stdlib-monotimes [feature]
Use std/monotimes in the stdlib [feature]
2019-07-17 16:06:34 +02:00
Andreas Rumpf
e11494f1cf Merge pull request #11680 from timotheecour/pr_fix_sigmatch_errmsg
fixes #8305; fixes #7808; fixes #10285; fixes #11061 + other bugs with type mismatch error msgs
2019-07-17 16:01:44 +02:00
Andreas Rumpf
326860e84c Merge pull request #11751 from nim-lang/araq-fixes-11474
fixes #11747
2019-07-17 15:21:07 +02:00
Andreas Rumpf
15d2a92be0 fixes #11747 2019-07-17 15:19:25 +02:00
Andreas Rumpf
bae08d0961 Merge pull request #11753 from kaushalmodi/fix-compilation-warning-in-macros
[bugfix] Fix compilation warning in macros.nim
2019-07-17 15:17:45 +02:00
Andreas Rumpf
43940294c5 fixes a critical 'nim secret' regression 2019-07-17 15:10:02 +02:00
Kaushal Modi
44d80dd863 [bugfix] critbits styleCheck fix: consistent var naming (#11752) 2019-07-16 21:24:09 +02:00
Kaushal Modi
3f7142fcfd [bugfix] openssl styleCheck fix: consistent var naming (#11750) 2019-07-16 21:23:12 +02:00
Kaushal Modi
0b511b15ea styleCheck fix: type naming: s/outType/OutType/ (#11749) 2019-07-16 21:22:34 +02:00
Kaushal Modi
dcbb2d66da Fix compilation warning in macros.nim
Fixes:

> macros.nim(1423, 35) Warning: `typed` will change its meaning in future versions of
  Nim. `void` or no return type declaration at all has the same
  meaning as the current meaning of `typed` as return type declaration. [Deprecated]
2019-07-16 15:03:44 -04:00
Oscar Nihlgård
1f32498a47 Use std/monotimes in the stdlib 2019-07-16 11:05:42 +02:00
Andreas Rumpf
102b71f42e Merge pull request #11740 from nim-lang/araq-fixes-11723
fixes #11723
2019-07-16 09:08:15 +02:00
Tristano Ajmone
8550a8127c Fix Typos in Internal Docs (#11735) [ci skip] 2019-07-15 19:05:23 +02:00
Araq
76f9ddb6ab fixes #11723 2019-07-15 17:22:01 +02:00
Kartik Saranathan
ec9d0ee86d fix broken link (#11736) [ci skip] 2019-07-15 16:05:43 +02:00
Andreas Rumpf
8513f50a8d Add std/monotimes which implements monotonic timestamps (#11712)
* [feature] Added std/monotimes

* [other] Minor optimization in times
2019-07-15 13:47:30 +02:00
Araq
dd7dd1b6dc styleCheck fixes [bugfix] 2019-07-15 13:16:02 +02:00
Araq
ad67a46e5d styleCheck fixes [bugfix] 2019-07-15 12:03:21 +02:00
Araq
52cbd0c558 styleCheck fixes [bugfix] 2019-07-15 10:56:55 +02:00
Araq
edbe02b4e1 newruntime: progress to make 'async' work with --newruntime 2019-07-15 10:56:55 +02:00
Andreas Rumpf
df53c68a36 makes devel green again 2019-07-14 17:14:51 +02:00
Araq
58e0dad371 'nim check' stability improvements 2019-07-14 16:11:42 +02:00
Araq
e06046ab51 makes --styleCheck:error the default for the Nim compiler itself 2019-07-14 16:08:52 +02:00
Araq
fab70e4fe3 minor update for the genode target 2019-07-14 16:08:15 +02:00
Araq
44c12d9d20 make 'koch temp' work again 2019-07-14 16:07:30 +02:00
Araq
9db369063c [refactoring] moves transformation for 'spawn' into its own spawn.nim implementation 2019-07-14 12:13:19 +02:00
alaviss
a59fb5b352 os: confine osErrorMsg example to Linux (#11725)
POSIX does **not** define the exact number for each errors. This caused
a failure in docs building on Haiku.
2019-07-13 16:16:09 +02:00
Jacek Sieka
cf36e4a44a times: use posix constant instead of import (#11692)
* times: use posix constant instead of import

* simplify clock id usage
2019-07-13 08:39:20 +02:00
Andreas Rumpf
de1ede77fe fixes #11715 (#11721) 2019-07-13 07:55:56 +02:00
Araq
d55cc0888d better run also considers the command line; fixes #11719 [feature] 2019-07-12 21:53:46 +02:00
Araq
423e8cca91 newruntime: refchecks:on|off switch 2019-07-12 21:53:46 +02:00
Araq
416ba133ad made --newruntime ready for multi-threading 2019-07-12 21:53:46 +02:00
Araq
bb5ca0772e atomics.nim: minor improvements 2019-07-12 21:53:45 +02:00
Araq
f45a1b927a documented --newruntime switch 2019-07-12 21:53:45 +02:00
Araq
03ded27021 preparations to be able to use atomics in runtime_v2.nim 2019-07-12 21:53:45 +02:00
Andreas Rumpf
2895ad70c8 fixes tcompiletimerange [bugfix] (#11720) 2019-07-12 15:37:54 +02:00
Ico Doornekamp
38b836b49e Moved 'Case statement macros' documentation out of manual into manual_experimental (#11716) 2019-07-12 14:41:54 +02:00
Araq
7606efc0bf [bugfix] VM: finally do inheritance properly 2019-07-12 12:15:30 +02:00
Araq
6d125da93f koch/nim: completion of the 'better run' feature 2019-07-12 10:48:29 +02:00
Araq
13253f4154 document 'nim' defines prefix 2019-07-12 10:48:07 +02:00
Araq
5bf3734984 nimpretty: implement a --maxLineLen command line option 2019-07-12 10:23:21 +02:00
Oscar Nihlgård
974362c98f [other] Minor optimization in times 2019-07-12 10:15:12 +02:00
Oscar Nihlgård
fd24a8923e [feature] Added std/monotimes 2019-07-12 10:15:06 +02:00
Araq
eaf4b42ff9 JS codegen: supports toOpenArray [bugfix] 2019-07-12 10:11:59 +02:00
Araq
511b6ae27c koch temp bugfix 2019-07-12 10:11:34 +02:00
Miran
2f0a50fa51 nimpretty: fix #11700, no extra newlines (#11714) 2019-07-12 09:14:21 +02:00
Andreas Rumpf
3d88d06b32 better run [feature] (#11709)
* track the checksums of all involved Nim files for smarter 'nim c -r' recompiles
* don't recompile unless necessary for 'nim c -r' [feature]
* [feature] koch boot uses a two step process in order to free the RAM before the GCC/Clang invocations
* fixes a serious regression
2019-07-11 21:36:23 +02:00
Dominik Picheta
b8be1ccb85 Give NilAccessError a message (#11706) 2019-07-11 11:14:38 +02:00
Andreas Rumpf
ac458448d8 make async tests green again 2019-07-11 11:09:10 +02:00
Araq
cb3c3c306c minor style changes 2019-07-11 00:28:20 +02:00
Araq
38bdf1cd7f minor style changes 2019-07-10 23:55:56 +02:00
Araq
b2f9447896 make tests green again 2019-07-10 23:32:04 +02:00
Araq
87a2ced1ba there is only one style -- my style 2019-07-10 19:17:06 +02:00
Araq
73cc029fec fixes linter regressions 2019-07-10 18:59:27 +02:00
Araq
dc0bbba3fa make editdistance work with --styleCheck:error 2019-07-10 18:58:59 +02:00
Araq
78174857f8 fixes #10901 2019-07-10 16:10:20 +02:00
Araq
b03421d087 fixes #11683 2019-07-10 16:00:05 +02:00
Araq
bc7733827d make more parts of the stdlib compile with --styleCheck:error 2019-07-10 15:48:30 +02:00
Araq
6663dbbe57 fixes #11691 2019-07-10 15:28:35 +02:00
Huy
e5425b5f2f [feature] add unsafeColumnAt procs, that return unsafe cstring from InstantRow (#11647) 2019-07-10 14:56:09 +02:00
Araq
c94647aeca styleCheck: make the compiler and large parts of the stdlib compatible with --styleCheck:error 2019-07-10 12:42:41 +02:00
Ivan Bobev
96523cdd3e Make public additional types from sha1 module [feature] (#11694)
* Make public additional types from sha1 module

After making public newSha1State, update and finalize methods from the
sha1 module was forgotten to be made public Sha1Digest and Sha1State
types used by the new public methods.

* Update changelog.md with sha1 module changes
2019-07-10 10:20:08 +02:00
Araq
18182e4bfd linter: refactorings 2019-07-10 09:07:03 +02:00
Araq
ff4a9a226f style changes 2019-07-10 09:06:54 +02:00
Araq
bd689849f2 nim styleChecker: implemented all the missing features (bugfix) 2019-07-10 00:29:58 +02:00
Araq
c6c9e30379 minor system.nim style changes 2019-07-10 00:29:58 +02:00
Araq
7a39eb13a5 koch temp: use -d:leanCompiler if possible 2019-07-10 00:29:58 +02:00
Miran
2255d8795b [other] prettify collections (#11695) 2019-07-09 22:45:23 +02:00
Araq
55e8aefbea newruntime: async progress 2019-07-09 20:15:57 +02:00
Araq
73c570d1d9 control flow graph: don't ignore yield statements 2019-07-09 20:15:57 +02:00
Araq
ad58ed344a newruntime: map system.reset to =destroy 2019-07-09 20:15:57 +02:00
Arne Döring
eb059fa848 closes #11551 (#11693) 2019-07-09 19:38:38 +02:00
Araq
a85e20c125 newruntime: 'owned distinct' is a valid construct (required by async) 2019-07-09 15:23:46 +02:00
Araq
fa982b43f0 make tests green again 2019-07-09 13:29:16 +02:00
narimiran
96d49608c0 nimpretty: more comment indentation fixes 2019-07-09 13:15:35 +02:00
Araq
eefcea8892 nimpretty: more improvements 2019-07-09 11:38:01 +02:00
Araq
fc34193483 nimpretty: code cleanups 2019-07-09 11:38:01 +02:00
Araq
0193c8ad2e nimpretty: yet another improvement 2019-07-09 11:38:01 +02:00
Araq
7993d61d00 async: more 'owned' annotations 2019-07-09 11:38:00 +02:00
Araq
2c2f2de614 asyncmacro produces 'owned' types 2019-07-09 11:38:00 +02:00
Araq
f64179e7fe bugfix: allow type conversions between 'owned ref' types 2019-07-09 11:38:00 +02:00
Araq
7c62de0cb7 better error message for invalid types 2019-07-09 11:38:00 +02:00
Arne Döring
11dad688fe Offsetof fixes (#11690)
* first fixes

* more tests and fixes

* code normalization
2019-07-09 09:07:45 +02:00
Timothee Cour
063ae96a66 address comments 2019-07-08 15:24:20 -07:00
Timothee Cour
5ddea6a98f add tests for #8305 #7808 #10285 #11061 + other bugs 2019-07-08 15:24:20 -07:00
Timothee Cour
5fce81edfd make tests/concepts/t3330.nim disabled again: the order of candidates is machine dependent 2019-07-08 15:24:20 -07:00
Timothee Cour
6375df4c53 make tests/concepts/t3330.nim disabled again: the order of candidates is machine dependent 2019-07-08 15:24:20 -07:00
Timothee Cour
b80d70b0f3 fix tests 2019-07-08 15:24:20 -07:00
Timothee Cour
a6526695f0 fix #8305 #7808 #10285 #11061 + other bugs with type mismatch error msgs 2019-07-08 15:24:20 -07:00
Miran
b50ae6817a [other] test more packages (#11687) 2019-07-08 22:22:15 +02:00
Andreas Rumpf
124a584eb2 fixes #11530 2019-07-08 19:40:42 +02:00
Timothee Cour
655cb08461 [refactoring] nimbase.h: remove dead code which was confusing (#11682) 2019-07-08 10:36:02 +02:00
Jacek Sieka
9e7d885f35 dynlib: use posix module (#11623) 2019-07-08 09:14:35 +02:00
Miran
d0616ed115 nimpretty: don't introduce extra spaces after a colon or a comma (#11672) 2019-07-07 20:13:10 +02:00
Araq
085a21ebf4 fixes #11350 2019-07-07 17:17:14 +02:00
Andreas Rumpf
bab1f67971 fixes #11660 (#11677) 2019-07-07 15:25:25 +02:00
awr1
6a7f8e8ab5 [HCR] Added warning for using performCodeReload() in main module (#11667)
* [HCR] Added error for using performCodeReload() in main module

* [HCR] changed this to a warning, clarified usage

* [HCR] fixed typo
2019-07-07 09:18:33 +02:00
Andreas Rumpf
3258c1e2a3 fixes #11671 2019-07-07 00:29:43 +02:00
Andreas Rumpf
465815e894 improved the error message for #11494; closes #11494 2019-07-06 23:59:23 +02:00
Andreas Rumpf
6ce6bce12e fixes a finish.exe regression 2019-07-06 22:48:22 +02:00
Andreas Rumpf
d2684cdfd2 fixes #11447 2019-07-06 21:20:16 +02:00
Andreas Rumpf
cab0c3e544 fixes #3333 2019-07-06 20:38:10 +02:00
Andreas Rumpf
64e1408920 fixes #8316 (#11673) 2019-07-06 20:02:50 +02:00
Andreas Rumpf
2678fa679a fixes #7057 2019-07-06 15:24:14 +02:00
Andreas Rumpf
02b9af2f75 ABI fixes for OSX/BSD; fixes #6860 (#11666) 2019-07-06 13:00:29 +02:00
Juan Carlos
25cd8a5490 Documentation Diff, Typo (#11566)
* Documentation for Diff, add Examples and runnableExamples
2019-07-06 09:45:48 +02:00
Miran
34c09a98c7 nimpretty: improved detection of commas and semicolons (#11661)
* nimpretty: improved detection of commas and semicolons

* address the comments
2019-07-06 00:21:21 +02:00
Arne Döring
7d5d9f7703 introduce internal Int128 type, use it to fix case stmt checks (#11652)
* initial version of int128
* use int128 in case stmt
* fixes #11552
2019-07-05 22:45:32 +02:00
Miran
176eaf5c90 nimpretty: don't touch formatted multiline comments (#11663) 2019-07-05 21:47:01 +02:00
cooldome
d1f6c820dd Fixes #11662: render ops priority (#11664) 2019-07-05 21:25:36 +02:00
narimiran
2c0c0e772c nimpretty: nicer debugging [ci skip] 2019-07-05 10:08:52 +02:00
Miran
96a19ea1b4 nimpretty: relax line length rules when dealing with (inline) comments (#11657) 2019-07-05 09:32:56 +02:00
Timothee Cour
95f2f2396f fix #11651 exportc symbol not exported, leading to link error (#11658) 2019-07-05 07:53:21 +02:00
Andreas Rumpf
28c9c062a4 fixes #11610 (#11659) 2019-07-05 07:26:06 +02:00
Tomohiro
b64dd795b1 manual: document block expression (#11638) 2019-07-05 01:43:14 +02:00
Andreas Rumpf
5f515410af newruntime for async (#11650)
* fixes overloading resolution for passing owned(Future[string]) to Future[T]
* WIP: make --newruntime work with .async
* memtracker: make it compile again
* make Nimble compile again
2019-07-05 01:42:17 +02:00
Ivan Bobev
d914dca513 Make public some sha1 module procedures (#11655) [feature]
Make "newSha1State", "update" and "finalize" procedures from the sha1
module public in order to be possible to compute single sha1 hash of
multiple separate blocks of data.
2019-07-04 22:29:03 +02:00
Akito13
0a501932c2 Corrected example shown in documentation (#11654) [ci skip]
Used template within example was added to imports.
2019-07-04 15:59:29 +02:00
Graeme Cross
dad3c40f55 Fix the broken link in math.nim (#11653) [ci skip] 2019-07-04 13:24:19 +02:00
narimiran
4450fca6fd nimpretty: fix out of bounds error [ci skip] 2019-07-04 12:02:35 +02:00
Araq
a59f0adc50 nimpretty: nimpretty now understands splitting newlines 2019-07-04 11:32:15 +02:00
Araq
7d29f8b1a4 nimpretty: distinguish between the different kinds of newlines in Nim 2019-07-04 10:44:04 +02:00
Timothee Cour
64168d4aea fixes #8405: -d:useNimRtl now works even when {.rtl.} procs are used at compile time; CTFFI now works with {dynlib} (#11635) 2019-07-03 23:57:52 +02:00
Miran
0718d6c2cd [bugfix] fix wrong nimpretty unidents, refs #11616 (#11645) 2019-07-03 18:55:15 +02:00
Andreas Rumpf
045eeab6b4 fixes #11585 2019-07-03 15:38:24 +02:00
Timothee Cour
0ca71dd92c [bugfix] fix mach_absolute_time header; refs #11591 (#11593) 2019-07-03 14:59:07 +02:00
Miran
1e9316e23c [bugfix] fix #11484, acknowledge 'danger' flag (#11486) 2019-07-03 13:01:22 +02:00
Araq
c0db1705dc fixes #11510 2019-07-03 12:54:11 +02:00
Araq
476b4ff372 fixes #11636 2019-07-03 12:54:11 +02:00
Liam Sc
a157c2baef Added 'keys' iterator to JsonNode (#11597) [feature] 2019-07-03 08:06:22 +02:00
Arne Döring
20d0ef8afb [backport] fix #11320 (#11538)
* [backport] fix #11320
* fix test for 32 bit test
2019-07-03 08:00:40 +02:00
Hugo Locurcio
0a1cb631a2 Implement some custom formatting for input fields in the documentation (#11632)
* Implement some custom formatting for input fields in the documentation

Aside of resulting in more consistent appearance across browsers,
this also fixes input form rendering when using Firefox with a
dark system theme on Linux.

* change the expected html in the tests
2019-07-03 07:40:24 +02:00
Graeme Cross
ab6dec6e90 Documentation improvements to the times module (#11639)
* Typo and grammar fixes for the times module
* Minor typo fixes to the times module
2019-07-03 07:39:19 +02:00
Andreas Rumpf
71b7383f12 fixes #11479 (#11641) 2019-07-03 07:22:30 +02:00
Miran
c522a455df [bugfix] nimpretty indents multiline comments correctly (#11607) 2019-07-02 10:52:46 +02:00
Andreas Rumpf
cce8a739da fixes #11633 2019-07-01 23:53:41 +02:00
Andreas Rumpf
766960dc15 fixes #11515 (#11624)
* fixes #11515

* better fix for #11515; make tests green
2019-07-01 18:08:50 +02:00
Andreas Rumpf
9b949855c7 fixes #11618 (#11631) 2019-07-01 14:10:08 +02:00
alaviss
2c10b246ec assertions: fixes #11545 (#11605)
* assertions: properly fix #11545

* tests/assert: enable excessiveStackTrace

* tests/assert: add test case for #11545

* tfailedassert_stacktrace: disable excessiveStackTrace

* assertions: weird workaround for failing tests

This fixes megatest on *nix, but have no idea why
2019-07-01 13:19:07 +02:00
Araq
bd55c862a6 fixes #11617 2019-07-01 13:12:04 +02:00
Araq
c352892232 fixes #11628 2019-07-01 12:34:19 +02:00
Araq
413dff03a0 fixes #11614 2019-07-01 12:29:03 +02:00
Ico Doornekamp
a5686961bd Make repr use 'ptr' for ptr types instead of 'ref' (#11626) 2019-07-01 11:59:27 +02:00
Juan Carlos
d7a7662a7f Remove IO.js compat (long dead vanished project,superseed by NodeJS) (#11627) 2019-07-01 11:59:02 +02:00
Araq
dd39b11b13 [bugfix] make -d:nimSetUtf8CodePage switch work again 2019-07-01 10:35:52 +02:00
Andreas Rumpf
d37c4e44d3 added destructors.rst document 2019-07-01 08:51:47 +02:00
alaviss
e259f80fc7 msgs, ccgstmts: fixes #11572 (#11621)
* [refactor] msgs: toFilename now return just the filename

The C codegen uses just the file name for stacktrace when
excessiveStackTrace is off (see quotedName),
so there aren't any reason for other codegen to not do the same.

The file name is now cached in TFileInfo.shortName, which was introduced
for nimsuggest, and went unused after several refactoring of the
compiler.

A toProjPath() proc has been added for the previous behavior of
toFilename().

* ccgstmt: use quotedFilename() for raiseExceptionEx

This is the same proc used for stacktrace when --stacktrace:on

Fixes #11572

* msgs: handle case where file name is not available
2019-06-30 12:30:37 +02:00
Andreas Rumpf
7113c1e931 [other] additions to the manual 2019-06-29 23:41:25 +02:00
Araq
3606e035f5 fixes #11606 2019-06-28 21:13:03 +02:00
Araq
7ddb31262e fixes #11611 2019-06-28 21:04:49 +02:00
Ivan Bobev
5be5bf0222 Pass additional koch options to the nim compiler (#11615)
Add possibility when "koch tools" command is used, nim compiler options
to be passed. The current options are kept and the new user specified
options will be added to the end of the command line if present.

Example:
> koch --latest tools -d:danger --debugInfo --lineDir:on
bin\nim.exe c -o:bin\nimsuggest.exe -d:release -d:danger -d:danger
 --debugInfo --lineDir:on nimsuggest/nimsuggest.nim
...
bin\nim.exe c -o:bin\nimgrep.exe -d:release -d:danger --debugInfo
 --lineDir:on tools/nimgrep.nim
...
bin\nim.exe c -o:bin\vccexe.exe -d:danger --debugInfo --lineDir:on
 tools/vccexe/vccexe.nim
...
bin\nim.exe c -o:bin\nimpretty.exe -d:release -d:danger --debugInfo
 --lineDir:on nimpretty/nimpretty.nim
...
bin\nim.exe c -o:bin\nimfind.exe -d:release -d:danger --debugInfo
 --lineDir:on tools/nimfind.nim
...
bin\nim.exe c -o:bin\nimble.exe --noNimblePath --nilseqs:on -d:release
 -d:danger --debugInfo --lineDir:on dist\nimble\src\nimble.nim
2019-06-28 18:06:43 +02:00
Araq
284a8cb58a nimpretty: bugfix [bugfix] 2019-06-28 11:45:21 +02:00
Andreas Rumpf
d72edfb14b Merge pull request #11609 from zestyr/xmltree-typo
Fix typo in xmltree docs
2019-06-27 21:36:49 +02:00
Andreas Rumpf
765ff4b67b contributing.rst guide: Make the rules reflect the reality. 2019-06-27 21:28:53 +02:00
Andreas Rumpf
17bbce7c8a manual: typo 2019-06-27 21:25:07 +02:00
Andreas Rumpf
d9604d7d0b manual: document how accessors are resolved; fixes #11514 2019-06-27 21:25:07 +02:00
Zestyr
bab83c4d8b Fix typo in xmltree docs [ci skip] 2019-06-27 20:44:42 +02:00
Araq
f36a61e6d4 make tests green again 2019-06-27 17:10:11 +02:00
Andreas Rumpf
fb878330a9 fixes #11445 2019-06-27 14:46:38 +02:00
Andreas Rumpf
135fdde6a9 fixes #11523 2019-06-26 23:41:20 +02:00
Andreas Rumpf
19b142401c fixes #11525 2019-06-26 23:15:58 +02:00
Andreas Rumpf
48cbf1c496 Merge pull request #11598 from narimiran/fix-sharedtables
[bugfix] fix #11588, don't check if SharedTable is initialized
2019-06-26 23:11:34 +02:00
Andreas Rumpf
ce2777af5a fixes #11600 (#11602) 2019-06-26 23:10:20 +02:00
Miran
f65eaa51f1 [bugfix] fix #11532, nimpretty should ignore source code filters (#11603) 2019-06-26 23:09:57 +02:00
Andreas Rumpf
e083a1533b fixes #11098 2019-06-26 19:34:05 +02:00
narimiran
326e3ad09d [bugfix] fix #11588, don't check if SharedTable is initialized 2019-06-26 17:16:55 +02:00
Araq
b6fb47df77 fixes #11600 2019-06-26 15:55:27 +02:00
Miran
f288e1b11a [bugfix] fix #11469, new rules for a newline in nimpretty (#11512)
* [bugfix] fix #11469, new rules for a newline in nimpretty
* concatenate two lines if they have the same indentation level
2019-06-26 15:36:44 +02:00
Araq
0a81b038fd fixes #11577 2019-06-26 15:33:51 +02:00
alaviss
993b3909a8 [refactor] compiler/[msgs, reorder, semstmts]: use toMsgFilename where appropriate (#11595)
* compiler/msgs: toMsgFilename now operates on FileIndex
* compiler/reorder: use toMsgFilename for compiler messages
* compiler/semstmts: respect listFullPaths for recursive deps error
2019-06-26 14:38:19 +02:00
Toshiyuki-Tega
b7f8031e98 VCC discovery using vswhere (#6540) (#11559) 2019-06-26 10:52:22 +02:00
Juan Carlos
206f2478b8 Documentation highlite (#11596)
* Add Documentation with examples for highlite

* Add Documentation with examples for highlite
2019-06-26 10:28:11 +02:00
Andreas Rumpf
0f868b587b fixes #11563 (#11594) 2019-06-26 06:55:43 +02:00
alaviss
2f1a1b7106 compiler/[msgs, options]: confine --listFullPaths to compiler messages (#11583)
* compiler/[msgs, options]: make toFilename independent of listFullPaths

toFilename is used mainly in codegen, as such it should not follow
--listFullPaths

* compiler/msgs: use toMsgFilename for toFileLineCol

This proc is mainly used for compiler messages, so it should follow
--listFullPaths

* compiler/msgs: remove toFileLine

unused proc

* compiler/msgs: cleanup toMsgFilename

Also improved path choosing logic, /home should now be preferred over
../home on *nix
2019-06-26 02:40:10 +02:00
cooldome
0d50b0c8a7 increase dfa instruction limit (#11579) 2019-06-24 22:34:54 -07:00
Jasper Jenkins
91f0626dcb [bugfix] remove dangling ref (#11576) 2019-06-25 02:04:15 +02:00
Gérôme Fournier
181350f6c9 Fix out of bound access in cgi module (#11578)
When an HTTP request with a zero CONTENT_LENGTH is made,
attempting to access addr(result[0]) raise an exception as the 0 index
is out of bound
2019-06-25 02:03:44 +02:00
WhiteDuke
2a7cf71db3 Fix typo (#11573) 2019-06-25 00:24:51 +02:00
alaviss
403fd3ac43 assertions: make assert follow excessiveStackTrace (#11574) 2019-06-25 00:23:22 +02:00
alaviss
e9a23cee0a nim.cfg: disable excessiveStackTrace on release (#11575) 2019-06-25 00:22:30 +02:00
narimiran
436f570651 [documentation] fix #4630, document unsupported functions for JS 2019-06-24 12:52:54 +02:00
Arne Döring
e90d91f0e4 [refactoring] remove zeroExtend and friends from the compiler builtins. (#11531)
* remove zeroExtend and friends from the compiler builtins.
* fix jssys
2019-06-24 09:19:02 +02:00
Simon Krauter
800bc661b6 Spelling fixes in nimc.rst (#11569) 2019-06-23 15:15:55 -07:00
Juan Carlos
bb9b60604b [other] Documentation NimScript (#11548)
* Documentation of NimScript, update and expand, mention the benefits aside of its limitations, add examples, update the list of usable std lib modules
2019-06-23 20:08:21 +02:00
Giovanni Petrantoni
b81fd958d1 [feature] Add dynlib (required on windows/cpp) to nimCoroutines related gc_common procs (#11567) 2019-06-23 18:05:10 +02:00
Miran
3d50f7e2a1 [bugfix] fix OrderedTable iterators (#11562) 2019-06-22 22:28:45 -07:00
Andreas Rumpf
79c721d418 [bugfix] fixes #11524 2019-06-22 01:52:49 +02:00
Andreas Rumpf
0db3c670ac closes #11533 2019-06-21 20:45:00 +02:00
Andreas Rumpf
35df59b3ce [bugfix] fixes #11556 2019-06-21 20:38:18 +02:00
narimiran
12eebf48b6 [documentation] fix wrong link [ci skip] 2019-06-21 12:04:43 +02:00
Kaushal Modi
a4c613c110 [other] Improve the "tabs are not allowed" error message (#11554) 2019-06-20 22:16:06 +02:00
Miran
23e95dc629 [bugfix] fix delete in strutils and sequtils (#11535) 2019-06-20 21:04:37 +02:00
Miran
d6b0e46ee4 [bugfix] correct 'source' for documentation (#11540) 2019-06-20 21:03:48 +02:00
Miran
45bbf1ef5b [bugfix] fix OrderedTable default initialization (#11549) 2019-06-20 21:03:11 +02:00
Andreas Rumpf
55da84e141 [other] new experimental pragma .nodestroy for easier custom destructors 2019-06-20 19:41:03 +02:00
Andreas Rumpf
f310cf5250 [other] added system.dispose for owned refs 2019-06-20 19:40:18 +02:00
Andreas Rumpf
280193cc07 [bugfix] system.nim: make pop work with --newruntime 2019-06-20 19:39:42 +02:00
Andreas Rumpf
7e4748beee [bugfix] proper destruction for strings/seqs for --newruntime 2019-06-20 19:39:19 +02:00
Andreas Rumpf
bc9fb4885b [bugfix] system.nim: make pop work with --newruntime 2019-06-20 19:38:25 +02:00
Araq
678beb8ef9 [other] newruntime: add a simple closure iterator test 2019-06-20 11:31:21 +02:00
Araq
6adcc09877 [bugfix] newruntime: trivial closure iterator works 2019-06-20 11:31:20 +02:00
Araq
c83914b435 [refactoring] closureiters.nim: style change 2019-06-20 11:31:20 +02:00
Araq
50afafdb38 wip 2019-06-20 11:31:19 +02:00
Andreas Rumpf
af10788dcc WIP: closures for the newruntime [ci skip] 2019-06-20 11:30:42 +02:00
narimiran
16d81fa205 [bugfix] fix #11546, correct link for sequtils 2019-06-20 09:41:06 +02:00
narimiran
96bed814d2 [bugfix] fix #11543, add std/sums to theindex.html 2019-06-20 09:37:21 +02:00
Andreas Rumpf
0adb1c6223 newruntime: added yet another test 2019-06-20 08:38:29 +02:00
Andreas Rumpf
c65a5d754b [bugfix] owned closures (#11544) 2019-06-20 07:40:45 +02:00
Arne Döring
1a074fffa4 change newLit on Seq (#11542) 2019-06-19 20:14:54 +02:00
Araq
ab36ffbeb1 [bugfix] fixes #11517 2019-06-19 17:39:52 +02:00
Araq
ff89f7e33a libffi: style changes 2019-06-19 16:54:34 +02:00
narimiran
de88fdb86e Revert "makes travis OSX green again"
This reverts commit 79a23fe805.
2019-06-19 15:53:42 +02:00
Miran
ae5a4cea98 [other] update homebrew, fix travis fails on OSX (#11541) 2019-06-19 15:54:40 +02:00
narimiran
cf47c2c60c [other] documentation: deprecation comments are now auto-generated 2019-06-19 14:21:46 +02:00
alaviss
24ac13f653 [bugfix] gc_common: export foreign thread gc docs (#11536) 2019-06-19 12:41:22 +02:00
Araq
f67be92512 [feature] cleanup PR, refs #11424 2019-06-19 09:54:01 +02:00
Araq
296c48de5e fixes #11436 2019-06-19 09:48:55 +02:00
Araq
79a23fe805 makes travis OSX green again 2019-06-19 09:48:55 +02:00
Phạm Ngọc Quang Nam
7c637c2faf [bugfix] Fix smtp.nim unhandled exception (#11498) 2019-06-19 00:26:59 +02:00
Jasper Jenkins
8ee0f14ab6 literal array indices (#11424) 2019-06-18 14:16:33 +02:00
Araq
c99ce5051e add HCR document to the tools.rst list 2019-06-18 12:19:14 +02:00
Araq
38f05bb9a3 HCR: better documentation 2019-06-18 12:17:26 +02:00
Benjamin Summerton
a009cbdc2f Add cbrt() bindings for the JS Target (#11528)
`Math.cbrt()` exists:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cbrt

The binding was missing for the JavaScript backend.
2019-06-18 02:26:47 -04:00
yatsen1
c8268330be [feature] Add boehm gc finalizer (#11446) 2019-06-17 20:47:18 +02:00
Miran
ac3449b93b [bugfix] fix #11450, random.initRand crashes in JS backend (#11522) 2019-06-17 20:46:04 +02:00
Miran
6cad5c7861 [bugfix] fix #11482, fix nimsuggest range error (#11519)
The default starting parameters for `line` and `col` were switched.

See line 141: "line starts at 1, column at 0, dirtyfile is optional".
Also, in `TLineInfo` object, `line` is uint16, `col` is int16.
2019-06-17 20:41:41 +02:00
narimiran
b70fd0400e [other] introduce a separate changelog for backports, update
contributing guidelines
2019-06-17 12:15:47 +02:00
Juan Carlos
eb087b3546 [bugfix] Fixes #11434 , Update Tools Documentation (#11449) 2019-06-17 11:17:28 +02:00
Juan Carlos
aa7f23e1ee [bugfix] Fixes #11495 , Remove TinyC from help (#11508) 2019-06-17 11:03:18 +02:00
Phạm Ngọc Quang Nam
9f6187b46c Add starttls for smtp (#11500)
* Add starttls for smtp

* Update smtp.nim
2019-06-16 23:50:56 +01:00
Kaushal Modi
7182922622 [feature] Added os.delEnv; add delEnv support to nimscript too (#11466)
[feature] Fixes https://github.com/nim-lang/Nim/issues/11452.
2019-06-15 11:32:26 +02:00
Andreas Rumpf
eadea343ef [bugfix] fixes https://github.com/nim-lang/Nim/issues/11430
[bugfix] fixes https://github.com/nim-lang/Nim/issues/11430
2019-06-15 11:29:10 +02:00
Charles Blake
6dc6487311 Disambiguate idents now that all 3 rfind's are included in the RTL. 2019-06-15 03:46:21 -04:00
Andreas Rumpf
68cce40510 [bugfix] Add .47 as supported libssl version (#11503) 2019-06-14 23:03:00 +02:00
Kaushal Modi
d1ce86fdc6 [bugfix] Fix the link to "For Loop Macro" section (#11505) 2019-06-14 23:02:30 +02:00
SolitudeSF
e96afd6324 [bugfix] Add .47 as supported libssl version 2019-06-14 20:00:23 +03:00
Kaushal Modi
c656714623 [bugfix] Minor formatting fix in tut2 [ci skip] (#11501)
Monospace `untyped` like elsewhere in the tutorial.
2019-06-14 15:13:44 +02:00
Araq
57a83df745 [bugfix] nimpretty: better alignment; fixes #11467 2019-06-14 11:16:39 +02:00
Juan Carlos
80320c72d3 [bugfix] document the norewrite pragma (#11453)
* fixes #9454
* Peer review feedback, wording, move to experimental manual
2019-06-13 19:37:17 +02:00
Jasper Jenkins
bda9fd149c [refactoring] error instead of quit for basename (#11491) 2019-06-13 19:34:41 +02:00
Charles Blake
e11d582fa1 Merge branch 'devel' of https://github.com/nim-lang/Nim into devel 2019-06-13 10:21:11 -04:00
Charles Blake
e7188cdfa8 Add missing ,int to type signature in doc comment references. 2019-06-13 10:20:43 -04:00
Jasper Jenkins
06ef56ba72 [bugfix] fix quit errormsg in nimvm (#11490) 2019-06-13 15:30:30 +02:00
Simon Krauter
e2f99a2026 Update tut1: -d:release does not turn off *allruntime checks off anymore (#11492)
According to https://nim-lang.org/blog/2019/06/06/version-0200-released.html
"The -d:release switch now does not disable runtime checks anymore. "
2019-06-13 15:16:38 +02:00
Araq
165ea46284 [bugfix] nimpretty: fixes #11470 2019-06-13 10:58:27 +02:00
Araq
af39f26a3a [bugfix] nimpretty: fixes #11468 2019-06-13 10:42:37 +02:00
Araq
b70295c768 [other] nimsuggest: adhere to our style guide 2019-06-13 09:59:03 +02:00
alaviss
08fdffc717 [other] appveyor: use official dlls on nim-lang.org (#11473) 2019-06-12 17:09:36 +02:00
Dominik Picheta
73c44c6e9b [bugfix] Fixes async IO operations stalling even after socket is closed. (#11232) 2019-06-12 17:07:05 +02:00
Charles Blake
bde899d4f8 Attempt to close https://github.com/nim-lang/Nim/issues/11430 2019-06-12 07:44:56 -04:00
Jasper Jenkins
da035e9c83 [bugfix] fix nimpretty for absolute paths (#11480) 2019-06-12 11:59:25 +02:00
Araq
b056d32a79 [refactoring] liftdestructors.nim is callable from lambdalifting; refs #11217 2019-06-12 10:44:45 +02:00
Arne Döring
e4d0f4fee0 fix regression in semfold for old right shift (#11477) 2019-06-12 09:26:30 +02:00
Araq
c07973e313 [refactoring] liftdestructors is now a module of its own 2019-06-12 08:45:47 +02:00
Araq
549d8cc0c6 [other] make typeAllowed easier to debug by using structured programming 2019-06-12 08:45:47 +02:00
Andreas Rumpf
572b7c37a5 [other] preparations for --styleCheck:error for the Nim compiler (#11478) 2019-06-12 08:35:32 +02:00
Arne Döring
c7e1c665a1 [refactoring] refactor the compiler and stdlib to deprecation warnings (#11419) 2019-06-11 16:49:56 +02:00
Juan Carlos
3d13103443 [bugfix] Add .nimf to mimetypes (#11417) 2019-06-11 16:46:15 +02:00
Hitesh Jasani
a9aef65b2d [feature] Enable Oid usage in hashtables (#11472) 2019-06-11 15:06:46 +02:00
Miran
b3d2cd738a [other] better error message for IndexError for empty containers (#11476) 2019-06-11 14:34:21 +02:00
Andrii Riabushenko
7cfc7cfb26 fixes #11118 2019-04-30 21:46:45 +01:00
1312 changed files with 44013 additions and 129387 deletions

37
.builds/freebsd.yml Normal file
View File

@@ -0,0 +1,37 @@
# see https://man.sr.ht/builds.sr.ht/compatibility.md#freebsd
image: freebsd/latest
# packages:
# - databases/sqlite3
# - devel/boehm-gc-threaded
# - devel/pcre
# - devel/sdl20
# - devel/sfml
# - www/node
# - devel/gmake
# - devel/git
sources:
- https://github.com/nim-lang/Nim
environment:
CC: /usr/bin/clang
tasks:
- setup: |
# workaround https://github.com/timotheecour/Nim/issues/76
sudo pkg update -q -f
sudo pkg install -y -q databases/sqlite3 devel/boehm-gc-threaded devel/pcre \
devel/sdl20 devel/sfml www/node devel/gmake devel/git
cd Nim
git clone --depth 1 -q https://github.com/nim-lang/csources.git
gmake -C csources -j $(sysctl -n hw.ncpu)
bin/nim c --skipUserCfg --skipParentCfg koch
echo 'export PATH=$HOME/Nim/bin:$PATH' >> $HOME/.buildenv
- test: |
cd Nim
if ! ./koch runCI; then
nim c -r tools/ci_testresults.nim
exit 1
fi
triggers:
- action: email
condition: failure
to: Andreas Rumpf <rumpf_a@web.de>

2
.github/FUNDING.yml vendored
View File

@@ -1,7 +1,7 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
patreon: 'araq' # Replace with a single Patreon username
open_collective: 'nim' # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel

View File

@@ -1,45 +1,39 @@
---
name: Bug report
about: Have you found an unexpected behavior? Use this template.
title: Think about the title, twice
labels: ''
assignees: ''
---
<!-- Think about the title, twice. -->
<!-- Summarize the problem here, keep it short and simple. -->
Function `echo` outputs the wrong string.
### Example
<!-- Paste your example in the code-block below. -->
```nim
echo "Hello World!"
```
### Current Output
```
Hola mundo!
```
### Expected Output
<!-- What should be the correct output? -->
```
Hello World!
```
### Possible Solution
<!--- Have you found a possible solution? Post it here. -->
* In file xyz there is a call that might be the cause of it.
### Additional Information
<!--- For Example:
* Your Nim version (output of `nim -v`).
* Was it working in the previous Nim releases?
* A link to a related issue or discussion.
* A project reference where (and how) the issue causes problems.
-->
* It was working in version a.b.c
* Issue #abc is related, but different because of ...
* This issue is blocking my project xyz
```
$ nim -v
Nim Compiler Version 0.1.2

View File

@@ -1,6 +1,9 @@
---
name: Feature request
about: Do you want to suggest a new feature? Use this template.
title: ''
labels: ''
assignees: ''
---

122
.github/workflows/ci.yml.disabled vendored Normal file
View File

@@ -0,0 +1,122 @@
name: Continous Integration
on: [push, pull_request]
jobs:
build:
strategy:
matrix:
os: [ubuntu-18.04, macos-10.15, windows-2019]
cpu: [amd64, i386]
cpp: ['false', 'true']
pkg: ['false', 'true']
exclude:
- os: ubuntu-18.04
cpp: 'true'
- os: ubuntu-18.04
pkg: 'true'
- os: macos-10.15
cpu: i386
- os: macos-10.15
pkg: 'true'
- os: windows-2019
cpu: i386
- os: windows-2019
cpp: 'true'
name: '${{ matrix.os }} (${{ matrix.cpu }}, cpp: ${{ matrix.cpp }}, pkg: ${{ matrix.pkg }})'
runs-on: ${{ matrix.os }}
env:
NIM_COMPILE_TO_CPP: ${{ matrix.cpp }}
NIM_TEST_PACKAGES: ${{ matrix.pkg }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Install node.js 8.x'
uses: actions/setup-node@v1
with:
node-version: '8.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
- name: 'Install dependencies (Linux i386)'
if: runner.os == 'Linux' && matrix.cpu == 'i386'
run: |
sudo dpkg --add-architecture i386
sudo apt-fast update -qq
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 \
libffi-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
exec $(which gcc) -m32 "\$@"
EOF
cat << EOF > bin/g++
#!/bin/bash
exec $(which g++) -m32 "\$@"
EOF
chmod 755 bin/gcc
chmod 755 bin/g++
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install boehmgc make sfml
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Build csources'
shell: bash
run: |
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Run CI'
shell: bash
run: ./koch runCI
- name: 'Show failed tests'
if: failure()
shell: bash
run: nim c -r tools/ci_testresults.nim

133
.github/workflows/ci_docs.yml vendored Normal file
View File

@@ -0,0 +1,133 @@
name: Nim Docs CI
on:
push:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'doc/**.rst'
- 'doc/nimdoc.css'
- '.github/workflows/ci_docs.yml'
pull_request:
# Run only on changes on these files
paths:
- 'lib/**.nim'
- 'doc/**.rst'
- '.github/workflows/ci_docs.yml'
jobs:
build:
strategy:
fail-fast: false
matrix:
target: [linux, windows, osx]
include:
- target: linux
os: ubuntu-18.04
- target: windows
os: windows-2019
- target: osx
os: macos-10.15
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Install build dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install make
- name: 'Install build dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Get current csources version'
id: csources-version
shell: bash
run: |
sha=$(git ls-remote https://github.com/nim-lang/csources master | cut -f 1)
echo "::set-output name=sha::$sha"
- name: 'Get prebuilt csources from cache'
id: csources-cache
uses: actions/cache@v1
with:
path: bin
key: '${{ matrix.os }}-${{ steps.csources-version.outputs.sha }}'
- name: 'Checkout csources'
if: steps.csources-cache.outputs.cache-hit != 'true'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- name: 'Build 1-stage compiler from csources'
shell: bash
run: |
ext=
[[ '${{ runner.os }}' == 'Windows' ]] && ext=.exe
if [[ ! -x bin/nim-csources$ext ]]; then
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc
cp bin/nim{,-csources}$ext
else
echo 'Cache hit, using prebuilt csources'
cp bin/nim{-csources,}$ext
fi
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build the real compiler'
shell: bash
run: ./koch boot -d:release
- name: 'Build documentation'
shell: bash
run: ./koch doc --git.commit:devel
- name: 'Prepare documentation for deployment'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
shell: bash
run: cp -f doc/html/{overview,index}.html
- name: 'Publish documentation to Github Pages'
if: |
github.event_name == 'push' && github.ref == 'refs/heads/devel' &&
matrix.target == 'linux'
uses: crazy-max/ghaction-github-pages@v1
with:
build_dir: doc/html
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

91
.github/workflows/ci_ssl.yml vendored Normal file
View File

@@ -0,0 +1,91 @@
name: Nim SSL CI
on:
pull_request:
# Run only on changes on related files
paths:
- 'lib/pure/httpclient.nim'
- 'lib/pure/net.nim'
- 'lib/pure/ssl_certs.nim'
- 'lib/wrappers/openssl.nim'
- 'tests/stdlib/thttpclient_ssl*'
- 'tests/untestable/thttpclient_ssl*'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04, macos-10.15, windows-2019]
cpu: [amd64]
name: '${{ matrix.os }} (${{ matrix.cpu }})'
runs-on: ${{ matrix.os }}
steps:
- name: 'Checkout'
uses: actions/checkout@v2
- name: 'Checkout csources'
uses: actions/checkout@v2
with:
repository: nim-lang/csources
path: csources
- 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 -y libssl1.1
- name: 'Install dependencies (macOS)'
if: runner.os == 'macOS'
run: brew install make
- name: 'Install dependencies (Windows)'
if: runner.os == 'Windows'
shell: bash
run: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo "::add-path::${{ github.workspace }}/dist/mingw64/bin"
- name: 'Add build binaries to PATH'
shell: bash
run: echo "::add-path::${{ github.workspace }}/bin"
- name: 'Build 1-stage compiler from csources'
shell: bash
run: |
ncpu=
case '${{ runner.os }}' in
'Linux')
ncpu=$(nproc)
;;
'macOS')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu='${{ matrix.cpu }}'
- name: 'Build koch'
shell: bash
run: nim c koch
- name: 'Build the real compiler'
shell: bash
run: ./koch boot
- name: 'Run SSL nimDisableCertificateValidation integration tests'
shell: bash
run: nim c -d:nimDisableCertificateValidation -d:ssl -r -p:. tests/untestable/thttpclient_ssl_disabled.nim
- name: 'Run SSL certificate check integration tests'
# Not supported on Windows due to old openssl version
if: runner.os != 'Windows'
shell: bash
run: nim c -d:ssl -p:. --threads:on -r tests/untestable/thttpclient_ssl.nim

14
.gitignore vendored
View File

@@ -65,7 +65,7 @@ testament.db
/tests/**/*.json
/tests/**/*.js
/csources
dist/
/dist/
# Private directories and files (IDEs)
.*/
@@ -84,3 +84,15 @@ megatest.nim
/outputGotten.txt
/lib/pure/*.js
!/.builds/
!/.github
# ignore debug dirs generated by dsymutil on OSX
*.dSYM
nimdoc.out.css
# for `nim c -r nimdoc/tester` etc; this can be in multiple places
htmldocs

View File

@@ -4,45 +4,12 @@ language: c
dist: xenial
matrix:
fast_finish: true
include:
- os: linux
env:
- NIM_COMPILE_TO_CPP=false
- CPU=amd64
- os: linux
env:
- NIM_COMPILE_TO_CPP=false
- CPU=i386
addons:
apt:
packages:
- gcc-multilib
- g++-multilib
- libcurl4-openssl-dev:i386
- libgc-dev:i386
- libglib2.0-dev:i386
- libpulse-dev:i386
- libsdl1.2-dev:i386
- libsfml-dev:i386
- os: osx
env:
- NIM_COMPILE_TO_CPP=false
- CPU=amd64
- os: osx
env:
- NIM_COMPILE_TO_CPP=true
- CPU=amd64
# To allow failures for a failing configuration, use something like:
# allow_failures:
# - env: NIM_COMPILE_TO_CPP=true
# - os: osx
addons:
apt:
# update the list above if more deps are introduced
@@ -51,18 +18,8 @@ addons:
- libsdl1.2-dev
- libgc-dev
- libsfml-dev
homebrew:
packages:
- boehmgc
- make
- sfml
update: true
install:
- if [[ $CPU = i386 ]]; then echo -e "#!/bin/bash\n$(which gcc) -m32 \"\$@\"" > bin/gcc; fi
- if [[ $CPU = i386 ]]; then chmod 755 bin/gcc; fi
- if [[ $CPU = i386 ]]; then echo -e "#!/bin/bash\n$(which g++) -m32 \"\$@\"" > bin/g++; fi
- if [[ $CPU = i386 ]]; then chmod 755 bin/g++; fi
- libc6-dbg
- valgrind
before_script:
- git clone --depth 1 https://github.com/nim-lang/csources.git
@@ -73,11 +30,17 @@ script:
- echo "travis_fold:start:nim_c_koch"
- nim c koch
- echo "travis_fold:end:nim_c_koch"
- ./koch runCI
- echo "travis_fold:start:koch_boot"
- ./koch boot
- echo "travis_fold:end:koch_boot"
- echo "travis_fold:start:koch_doc"
- ./koch doc
- echo "travis_fold:end:koch_doc"
before_deploy:
# Make https://nim-lang.github.io/Nim work the same as https://nim-lang.github.io/Nim/overview.html
- cp -f ./doc/html/overview.html ./doc/html/index.html
deploy: # https://nim-lang.github.io/Nim
provider: pages
# local-dir *has* to be a relative path from the repo root.
@@ -87,6 +50,3 @@ deploy: # https://nim-lang.github.io/Nim
keep-history: false
on:
branch: devel
# Extract failed tests
after_failure: nim c -r tools/ci_testresults.nim

View File

@@ -4,8 +4,8 @@ environment:
DLLS_URL: https://nim-lang.org/download/dlls.zip
DLLS_ARCHIVE: dlls.zip
MINGW_DIR: mingw64
MINGW_URL: https://nim-lang.org/download/mingw64-6.3.0.7z
MINGW_ARCHIVE: mingw64-6.3.0.7z
MINGW_URL: https://nim-lang.org/download/mingw64.7z
MINGW_ARCHIVE: mingw64.7z
matrix:
- NIM_TEST_PACKAGES: false
@@ -15,10 +15,6 @@ cache:
- '%MINGW_ARCHIVE%'
- '%DLLS_ARCHIVE%'
matrix:
#allow_failures:
# - NIM_TEST_PACKAGES: true
fast_finish: true
install:
- ps: Install-Product node 8 # node 8 or later is required to test js async stuff
@@ -33,6 +29,8 @@ install:
- cd ..
build_script:
- openssl version
- openssl version -d
- bin\nim c koch
- koch runCI

164
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,164 @@
trigger:
branches:
include:
- '*'
pr:
branches:
include:
- '*'
jobs:
- job: packages
timeoutInMinutes: 90 # default `60` led to lots of cancelled jobs; use 0 for unlimited (may be undesirable)
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.15'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.15'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64:
vmImage: 'windows-2019'
CPU: amd64
Windows_amd64_pkg:
vmImage: 'windows-2019'
CPU: amd64
NIM_TEST_PACKAGES: true
pool:
vmImage: $(vmImage)
workspace:
clean: all
steps:
- bash: git config --global core.autocrlf false
displayName: 'Disable auto conversion to CRLF by git (Windows-only)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- checkout: self
- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install node.js 8.x'
- bash: |
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
displayName: 'Install dependencies (amd64 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'amd64'))
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# - llvm has to be downgraded to have 32bit version installed for sfml.
# - libgcc and libstdc++ have to be downgraded as an optimization to
# prevent the use of the toolchain ppa, which has a terrible download
# speed.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0 libgcc1 libstdc++6
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
Package: *
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
Pin-Priority: 100
EOF
sudo apt-fast update -qq
# `:i386` (e.g. in `libffi-dev:i386`) is needed otherwise you may get:
# `could not load: libffi.so` during dynamic loading.
DEBIAN_FRONTEND='noninteractive' \
sudo apt-fast install --no-install-recommends --allow-downgrades -yq \
g++-multilib gcc-multilib libcurl4-openssl-dev:i386 libgc-dev:i386 \
libsdl1.2-dev:i386 libsfml-dev:i386 libglib2.0-dev:i386 libffi-dev:i386
cat << EOF > bin/gcc
#!/bin/bash
exec $(which gcc) -m32 "\$@"
EOF
cat << EOF > bin/g++
#!/bin/bash
exec $(which g++) -m32 "\$@"
EOF
chmod 755 bin/gcc
chmod 755 bin/g++
displayName: 'Install dependencies (i386 Linux)'
condition: and(eq(variables['Agent.OS'], 'Linux'), eq(variables['CPU'], 'i386'))
- bash: brew install boehmgc make sfml
displayName: 'Install dependencies (OSX)'
condition: eq(variables['Agent.OS'], 'Darwin')
- bash: |
mkdir dist
curl -L https://nim-lang.org/download/mingw64.7z -o dist/mingw64.7z
curl -L https://nim-lang.org/download/dlls.zip -o dist/dlls.zip
7z x dist/mingw64.7z -odist
7z x dist/dlls.zip -obin
echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/dist/mingw64/bin'
displayName: 'Install dependencies (Windows)'
condition: eq(variables['Agent.OS'], 'Windows_NT')
- bash: echo '##vso[task.prependpath]$(System.DefaultWorkingDirectory)/bin'
displayName: 'Add build binaries to PATH'
- bash: |
echo 'PATH:' "$PATH"
echo '##[section]gcc version'
gcc -v
echo '##[section]nodejs version'
node -v
echo '##[section]make version'
make -v
displayName: 'System information'
- bash: |
ncpu=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
;;
'Darwin')
ncpu=$(sysctl -n hw.ncpu)
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build csources'
- bash: nim c koch
displayName: 'Build koch'
# set result to omit the "bash exited with error code '1'" message
- bash: |
./koch runCI || echo '##vso[task.complete result=Failed]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

View File

@@ -6,8 +6,16 @@ set -e
which nim > /dev/null || (echo "nim not in PATH"; exit 1)
which gdb > /dev/null || (echo "gdb not in PATH"; exit 1)
if [[ "$(uname -s)" == "Darwin" ]]; then
which greadlink > /dev/null || (echo "readlink not in PATH. Please install coreutils from homebrew."; exit 1)
READLINK=greadlink
else
which readlink > /dev/null || (echo "readlink not in PATH."; exit 1)
READLINK=readlink
fi
# Find out where the pretty printer Python module is
NIM_SYSROOT=$(dirname $(dirname $(readlink -e $(which nim))))
NIM_SYSROOT=$(dirname $(dirname $($READLINK -e $(which nim))))
GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
# Run GDB with the additional arguments that load the pretty printers
@@ -16,6 +24,4 @@ GDB_PYTHON_MODULE_PATH="$NIM_SYSROOT/tools/nim-gdb.py"
NIM_GDB="${NIM_GDB:-gdb}"
# exec replaces the new process of bash with gdb. It is always good to
# have fewer processes.
exec ${NIM_GDB} \
-eval-command "source $GDB_PYTHON_MODULE_PATH" \
"$@"
exec "${NIM_GDB}" -eval-command="source $GDB_PYTHON_MODULE_PATH" "$@"

1
bin/nim-gdb.bash Symbolic link
View File

@@ -0,0 +1 @@
nim-gdb

14
bin/nim-gdb.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
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 @NIM_GDB=gdb.exe
@echo source %@GDB_PYTHON_MODULE_PATH%> wingdbcommand.txt
%@NIM_GDB% --command="wingdbcommand.txt" %*
del wingdbcommand.txt /f /q
EXIT /B %ERRORLEVEL%
@echo on

17
build_all.bat Normal file
View File

@@ -0,0 +1,17 @@
@echo off
rem build development version of the compiler; can be rerun safely
if not exist csources (
git clone --depth 1 https://github.com/nim-lang/csources.git
)
if not exist bin\nim.exe (
cd csources
if PROCESSOR_ARCHITECTURE == AMD64 (
SET ARCH=64
)
CALL build.bat
cd ..
)
bin\nim.exe c --skipUserCfg --skipParentCfg koch
koch.exe boot -d:release --skipUserCfg --skipParentCfg
koch.exe tools --skipUserCfg --skipParentCfg

View File

@@ -1,23 +1,41 @@
#! /bin/sh
# build development version of the compiler; can be rerun safely
# build development version of the compiler; can be rerun safely.
# arguments can be passed, eg `--os freebsd`
set -u # error on undefined variables
set -e # exit on first error
echo_run(){
printf "\n$*\n"
echo "$*"
"$@"
}
[ -d csources ] || echo_run git clone --depth 1 https://github.com/nim-lang/csources.git
[ -d csources ] || echo_run git clone -q --depth 1 https://github.com/nim-lang/csources.git
nim_csources=bin/nim_csources
build_nim_csources_via_script(){
echo_run cd csources
echo_run sh build.sh "$@"
}
build_nim_csources(){
## avoid changing dir in case of failure
# avoid changing dir in case of failure
(
echo_run cd csources
echo_run sh build.sh $@
if [ $# -ne 0 ]; then
# some args were passed (eg: `--cpu i386`), need to call build.sh
build_nim_csources_via_script "$@"
else
# no args, use multiple Make jobs (5X faster on 16 cores: 10s instead of 50s)
makeX=make
unamestr=$(uname)
if [ "$unamestr" = 'FreeBSD' ]; then
makeX=gmake
fi
nCPU=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || 1)
which $makeX && echo_run $makeX -C csources -j $((nCPU + 2)) -l $nCPU || build_nim_csources_via_script
fi
)
# keep $nim_csources in case needed to investigate bootstrap issues
# without having to rebuild from csources
@@ -29,5 +47,6 @@ build_nim_csources(){
# Note: if fails, may need to `cd csources && git pull`
echo_run bin/nim c --skipUserCfg --skipParentCfg koch
echo_run ./koch boot -d:release
echo_run ./koch tools # Compile Nimble and other tools.
echo_run ./koch boot -d:release --skipUserCfg --skipParentCfg
echo_run ./koch tools --skipUserCfg --skipParentCfg # Compile Nimble and other tools.

View File

@@ -1,37 +1,15 @@
# v1.1 - XXXX-XX-XX
# v1.4.0 - yyyy-mm-dd
## Changes affecting backwards compatibility
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
- Enable Oid usage in hashtables. (#11472)
#
# Language additions
## Standard library additions and changes
## Language changes
### Tool changes
## Compiler changes
### Compiler changes
## Tool changes
- VM can now cast integer type arbitrarily. (#11459)
## Bugfixes

View File

@@ -1,31 +0,0 @@
# v0.20.4 - xxxx-xx-xx
## Changes affecting backwards compatibility
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
## Language additions
## Language changes
### Tool changes
### Compiler changes
## Bugfixes

View File

@@ -100,7 +100,7 @@
- We changed how array accesses "from backwards" like ``a[^1]`` or ``a[0..^1]`` are
implemented. These are now implemented purely in ``system.nim`` without compiler
support. There is a new "heterogenous" slice type ``system.HSlice`` that takes 2
support. There is a new "heterogeneous" slice type ``system.HSlice`` that takes 2
generic parameters which can be ``BackwardsIndex`` indices. ``BackwardsIndex`` is
produced by ``system.^``.
This means if you overload ``[]`` or ``[]=`` you need to ensure they also work
@@ -660,4 +660,4 @@ for i in a..b:
- Fixed "C++: SIGABRT instead of IndexError for out-of-bounds"
([#6512](https://github.com/nim-lang/Nim/issues/6512))
- Fixed "An uncaught exception in cpp mode doesn't show the exception name/msg"
([#6431](https://github.com/nim-lang/Nim/issues/6431))
([#6431](https://github.com/nim-lang/Nim/issues/6431))

View File

@@ -0,0 +1,138 @@
# v1.0 - 2019-09-23
## Changes affecting backwards compatibility
- The switch ``-d:nimBinaryStdFiles`` does not exist anymore. Instead
stdin/stdout/stderr are binary files again. This change only affects
Windows.
- On Windows console applications the code-page is set at program startup
to UTF-8. Use the new switch `-d:nimDontSetUtf8CodePage` to disable this
feature.
- The language definition and compiler are now stricter about ``gensym``'ed
symbols in hygienic templates. See the section in the
[manual](https://nim-lang.org/docs/manual.html#templates-hygiene-in-templates)
for further details. Use the compiler switch `--oldgensym:on` for a
transition period.
### Breaking changes in the standard library
- We removed `unicode.Rune16` without any deprecation period as the name
was wrong (see the [RFC](https://github.com/nim-lang/RFCs/issues/151) for details)
and we didn't find any usages of it in the wild. If you still need it, add this
piece of code to your project:
```nim
type
Rune16* = distinct int16
```
- `exportc` now uses C instead of C++ mangling with `nim cpp`, matching behavior
of `importc`, see #10578.
Use the new `exportcpp` to mangle as C++ when using `nim cpp`.
### Breaking changes in the compiler
- A bug allowing `int` to be implicitly converted to range types of smaller size
(e.g `range[0'i8..10'i8]`) has been fixed.
## Library additions
- `encodings.getCurrentEncoding` now distinguishes between the console's
encoding and the OS's encoding. This distinction is only meaningful on
Windows.
- Added `system.getOsFileHandle` which is usually more useful
than `system.getFileHandle`. This distinction is only meaningful on
Windows.
- Added a `json.parseJsonFragments` iterator that can be used to speedup
JSON processing substantially when there are JSON fragments separated
by whitespace.
## Library changes
- Added `os.delEnv` and `nimscript.delEnv`. (#11466)
- Enabled Oid usage in hashtables. (#11472)
- Added `unsafeColumnAt` procs, that return unsafe cstring from InstantRow. (#11647)
- Make public `Sha1Digest` and `Sha1State` types and `newSha1State`,
`update` and `finalize` procedures from `sha1` module. (#11694)
- Added the `std/monotimes` module which implements monotonic timestamps.
- Consistent error handling of two `exec` overloads. (#10967)
- Officially the following modules now have an unstable API:
- std/varints
- core/allocators
- core/hotcodereloading
- asyncstreams
- base64
- browsers
- collections/rtarrays
- collections/sharedlist
- collections/sharedtable
- concurrency/atomics
- concurrency/cpuload
- concurrency/threadpool
- coro
- endians
- httpcore
- parsesql
- pathnorm
- reservedmem
- typetraits
Every other stdlib module is API stable with respect to version 1.
## Language additions
- Inline iterators returning `lent T` types are now supported, similarly to
iterators returning `var T`:
```nim
iterator myitems[T](x: openarray[T]): lent T
iterator mypairs[T](x: openarray[T]): tuple[idx: int, val: lent T]
```
- Added an `importjs` pragma that can now be used instead of `importcpp`
and `importc` to import symbols from JavaScript. `importjs` for routines always
takes a "pattern" for maximum flexibility.
## Language changes
- `uint64` is now finally a regular ordinal type. This means `high(uint64)` compiles
and yields the correct value.
### Tool changes
- The Nim compiler now does not recompile the Nim project via ``nim c -r`` if
no dependent Nim file changed. This feature can be overridden by
the ``--forceBuild`` command line option.
- The Nim compiler now warns about unused module imports. You can use a
top level ``{.used.}`` pragma in the module that you want to be importable
without producing this warning.
- The "testament" testing tool's name was changed
from `tester` to `testament` and is generally available as a tool to run Nim
tests automatically.
### Compiler changes
- VM can now cast integer type arbitrarily. (#11459)
## Bugfixes

View File

@@ -0,0 +1,56 @@
# v1.0.2 - 2019-10-23
## Bugfixes
* fixes the --verbosity:2 regression
* Fixed "Fail to compile a file twice under Windows (v1.0 bug)." [#12242](https://github.com/nim-lang/Nim/issues/12242)
* fix nimpretty removing space before pragma
* JS: gensym is stricter for 'this'
* Fixed "VM Assertion Error with newruntime" [#12294](https://github.com/nim-lang/Nim/issues/12294)
* Fixed "Assertion error when running `nim check` on compiler/nim.nim" [#12281](https://github.com/nim-lang/Nim/issues/12281)
* Fixed "Compiler crash with empty array and generic instantiation with int as parameter" [#12264](https://github.com/nim-lang/Nim/issues/12264)
* Fixed "Regression in JS backend codegen "Error: request to generate code for .compileTime proc"" [#12240](https://github.com/nim-lang/Nim/issues/12240)
* Fix how `relativePath` handle case sensitiviy
* Fixed "SIGSEGV in compiler when using generic types and seqs" [#12336](https://github.com/nim-lang/Nim/issues/12336)
* Fixed "[1.0.0] weird interaction between `import os` and casting integer to char on macosx trigger bad codegen" [#12291](https://github.com/nim-lang/Nim/issues/12291)
* VM: no special casing for big endian machines
* Fixed "`internal error: environment misses` with a simple template inside one of Jester macros" [#12323](https://github.com/nim-lang/Nim/issues/12323)
* nimsuggest: fix tcp socket leak
* nimsuggest: fix tcp socket leak for epc backend
* Fixed "`writeFile` and `write(f, str)` skip null bytes on Windows" [#12315](https://github.com/nim-lang/Nim/issues/12315)
* Fixed "Crash in intsets symmetric_difference" [#12366](https://github.com/nim-lang/Nim/issues/12366)
* Fixed "[regression] VM crash when dealing with var param of a proc result" [#12244](https://github.com/nim-lang/Nim/issues/12244)
* fixes a koch regression that made 'koch boot --listcmd' not work anymore
* Fixed "[regression] inconsistent signed int `mod` operator between runtime, compiletime, and semfold" [#12332](https://github.com/nim-lang/Nim/issues/12332)
* Fixed "Boehm disables interior pointer checking" [#12286](https://github.com/nim-lang/Nim/issues/12286)
* Fixes semCustomPragma when nkSym
* Fixed yield in nkCheckedFieldExpr
* Fixed "`randomize()` from `random` not working on JS" [#12418](https://github.com/nim-lang/Nim/issues/12418)
* Fixed "Compiler crash with invalid object variant" [#12379](https://github.com/nim-lang/Nim/issues/12379)
* fix type's case in random.nim
* Fixed "Update docs with a better way to signal unimplemented methods" [#10804](https://github.com/nim-lang/Nim/issues/10804)
* Fixed "Nim language manual, push pragma is not explained well" [#10824](https://github.com/nim-lang/Nim/issues/10824)
* Fixed "[regression] Importing more than one module with same name from different packages produce bad codegen" [#12420](https://github.com/nim-lang/Nim/issues/12420)
* Namespace unittest enums to avoid name conflicts
* Fixed "VM checks unsigned integers for overflow." [#12310](https://github.com/nim-lang/Nim/issues/12310)
* Fixed "line directive is not generated for first line of function definition" [#12426](https://github.com/nim-lang/Nim/issues/12426)
## Documentation improvements
* threadpool: fix link in docs (#12258)
* Fix spellings (#12277)
* fix #12278, don't expose internal PCRE documentation
* Fixed "Documentation of quitprocs is wrong" [#12279(https://github.com/nim-lang/Nim/issues/12279)
* Fix typo in docs
* Fix reference to parseSpec proc in readme
* [doc/tut1] removed discard discussion in comments
* Documentation improvements around the db interface
* Easier build instructions for windows - just run `build_all.bat`.
* fix a few dead links and a missing sentence in documentation
* Macro docs additions
* Updated the code example in the os module to use better grammar.
* Mention "lambdas" and `=>` in the manual
* Better documentation on Garbage Collector

View File

@@ -0,0 +1,532 @@
# v1.2.0 - 2020-04-02
## Standard library additions and changes
- Added overloaded `strformat.fmt` macro that use specified characters as
delimiter instead of '{' and '}'.
- Added new procs in `tables.nim`: `OrderedTable.pop`, `CountTable.del`,
`CountTable.pop`, `Table.pop`.
- Added `strtabs.clear` overload that reuses the existing mode.
- Added `browsers.osOpen` const alias for the operating system specific *"open"* command.
- Added `sugar.dup` for turning in-place algorithms like `sort` and `shuffle`
into operations that work on a copy of the data and return the mutated copy,
like the existing `sorted` does.
- Added `sugar.collect` that does comprehension for seq/set/table collections.
- Added `sugar.capture` for capturing some local loop variables when creating a
closure. This is an enhanced version of `closureScope`.
- Added `typetraits.tupleLen` to get number of elements of a tuple/type tuple,
and `typetraits.get` to get the ith element of a type tuple.
- Added `typetraits.genericParams` to return a tuple of generic params from a
generic instantiation.
- `options` now treats `proc` like other pointer types, meaning `nil` proc variables
are converted to `None`.
- Added `os.normalizePathEnd` for additional path sanitization.
- Added `times.fromUnixFloat,toUnixFloat`, sub-second resolution versions of
`fromUnix`,`toUnixFloat`.
- Added `wrapnils` module for chains of field-access and indexing where the LHS
can be nil. This simplifies code by reducing need for if-else branches around
intermediate maybe nil values. E.g. `echo ?.n.typ.kind`.
- Added `minIndex`, `maxIndex` and `unzip` to the `sequtils` module.
- Added `os.isRelativeTo` to tell whether a path is relative to another.
- Added `resetOutputFormatters` to `unittest`.
- Added `expectIdent` to the `macros` module.
- Added `os.isValidFilename` that returns `true` if `filename` argument is valid
for cross-platform use.
- Added `times.isLeapDay`
- `base64` adds URL-Safe Base64, implements RFC-4648 Section-7.
- Added a new module, `std / compilesettings` for querying the compiler about
diverse configuration settings.
- Added `net.getPeerCertificates` and `asyncnet.getPeerCertificates` for
retrieving the verified certificate chain of the peer we are connected to
through an SSL-wrapped `Socket`/`AsyncSocket`.
- Added `browsers.openDefaultBrowser` without URL, implements IETF RFC-6694 Section-3.
- Added `jsconsole.trace`, `jsconsole.table`, `jsconsole.exception` for JavaScript target.
- Added `distinctBase` overload for values: `assert 12.MyInt.distinctBase == 12`
- Added new module `std/stackframes`, in particular `setFrameMsg`, which enables
custom runtime annotation of stackframes, see #13351 for examples.
Turn on/off via `--stackTraceMsgs:on/off`.
- Added `sequtils.countIt`, allowing for counting items using a predicate.
- Added a `with` macro for easy function chaining that's available everywhere,
there is no need to concern your APIs with returning the first argument
to enable "chaining", instead use the dedicated macro `with` that
was designed for it. For example:
```nim
type
Foo = object
col, pos: string
proc setColor(f: var Foo; r, g, b: int) = f.col = $(r, g, b)
proc setPosition(f: var Foo; x, y: float) = f.pos = $(x, y)
var f: Foo
with(f, setColor(2, 3, 4), setPosition(0.0, 1.0))
echo f
```
- `macros.newLit` now works for ref object types.
- `macro pragmas` can now be used in type sections.
- 5 new pragmas were added to Nim in order to make the upcoming tooling more
convenient to use. Nim compiler checks these pragmas for syntax but otherwise
ignores them. The pragmas are `requires`, `ensures`, `assume`, `assert`, `invariant`.
- `system.writeFile` has been overloaded to also support `openarray[byte]`.
- `asyncdispatch.drain` now properly takes into account `selector.hasPendingOperations`
and only returns once all pending async operations are guaranteed to have completed.
- `sequtils.zip` now returns a sequence of anonymous tuples i.e. those tuples
now do not have fields named "a" and "b".
- `distinctBase` has been moved from `sugar` to `typetraits` and now it is
implemented as compiler type trait instead of macro. `distinctBase` in sugar
module is now deprecated.
- `CountTable.mget` has been removed from `tables.nim`. It didn't work, and it
was an oversight to be included in v1.0.
- `tables.merge(CountTable, CountTable): CountTable` has been removed.
It didn't work well together with the existing inplace version of the same proc
(`tables.merge(var CountTable, CountTable)`).
It was an oversight to be included in v1.0.
- `asyncdispatch.drain` now consistently uses the passed timeout value for all
iterations of the event loop, and not just the first iteration.
This is more consistent with the other asyncdispatch APIs, and allows
`asyncdispatch.drain` to be more efficient.
- `base64.encode` and `base64.decode` were made faster by about 50%.
- `htmlgen` adds [MathML](https://wikipedia.org/wiki/MathML) support
(ISO 40314).
- `macros.eqIdent` is now invariant to export markers and backtick quotes.
- `htmlgen.html` allows `lang` in the `<html>` tag and common valid attributes.
- `macros.basename` and `basename=` got support for `PragmaExpr`,
so that an expression like `MyEnum {.pure.}` is handled correctly.
- `httpclient.maxredirects` changed from `int` to `Natural`, because negative values
serve no purpose whatsoever.
- `httpclient.newHttpClient` and `httpclient.newAsyncHttpClient` added `headers`
argument to set initial HTTP Headers, instead of a hardcoded empty `newHttpHeader()`.
- `parseutils.parseUntil` has now a different behaviour if the `until` parameter is
empty. This was required for intuitive behaviour of the strscans module
(see bug #13605).
- `strutils.formatFloat` with `precision = 0` has the same behavior in all
backends, and it is compatible with Python's behavior,
e.g. `formatFloat(3.14159, precision = 0)` is now `3`, not `3.`.
- `times.parse` now only uses input to compute its result, and not `now`:
`parse("2020", "YYYY", utc())` is now `2020-01-01T00:00:00Z` instead of
`2020-03-02T00:00:00Z` if run on 03-02; it also doesn't crash anymore when
used on 29th, 30th, 31st of each month.
- `httpcore.==(string, HttpCode)` is now deprecated due to lack of practical
usage. The `$` operator can be used to obtain the string form of `HttpCode`
for comparison if desired.
- `std/oswalkdir` was buggy, it's now deprecated and reuses `std/os` procs.
- `net.newContext` now performs SSL Certificate checking on Linux and OSX.
Define `nimDisableCertificateValidation` to disable it globally.
- `os.walkDir` and `os.walkDirRec` now have new flag, `checkDir` (default: false).
If it is set to true, it will throw if input dir is invalid instead of a noop
(which is the default behaviour, as it was before this change),
`os.walkDirRec` only throws if top-level dir is invalid, but ignores errors for
subdirs, otherwise it would be impossible to resume iteration.
- The `FD` variant of `selector.unregister` for `ioselector_epoll` and
`ioselector_select` now properly handle the `Event.User` select event type.
- `joinPath` path normalization when `/` is the first argument works correctly:
`assert "/" / "/a" == "/a"`. Fixed the edge case: `assert "" / "" == ""`.
- `xmltree` now adds indentation consistently to child nodes for any number
of children nodes.
- `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/"
as the dir component of `/root_sub_dir` instead of the empty string.
- The deprecated `lc` macro has been removed from `sugar`. It is now replaced with the
more powerful `collect` macro.
- `os.relativePath("foo", "foo")` is now `"."`, not `""`, as `""` means invalid
path and shouldn't be conflated with `"."`; use `-d:nimOldRelativePathBehavior`
to restore the old behavior.
- `os.joinPath(a, b)` now honors trailing slashes in `b` (or `a` if `b` = "").
- `base64.encode` no longer supports `lineLen` and `newLine`.
Use `base64.encodeMime` instead.
## Language changes
- An `align` pragma can now be used for variables and object fields, similar
to the `alignas` declaration modifier in C/C++.
- `=sink` type bound operator is now optional. Compiler can now use combination
of `=destroy` and `copyMem` to move objects efficiently.
- Unsigned integer operators have been fixed to allow promotion of the first operand.
- Conversions to unsigned integers are unchecked at runtime, imitating earlier Nim
versions. The documentation was improved to acknowledge this special case.
See https://github.com/nim-lang/RFCs/issues/175 for more details.
- New syntax for lvalue references: `var b {.byaddr.} = expr` enabled by
`import std/decls`.
- `var a {.foo.}: MyType = expr` now lowers to `foo(a, MyType, expr)` for
non-builtin pragmas, enabling things like lvalue references (see `decls.byaddr`).
## Compiler changes
- Generated JS code uses spaces, instead of mixed spaces and tabs.
- The Nim compiler now supports the ``--asm`` command option for easier
inspection of the produced assembler code.
- The Nim compiler now supports a new pragma called ``.localPassc`` to
pass specific compiler options to the C(++) backend for the C(++) file
that was produced from the current Nim module.
- The compiler now inferes "sink parameters". To disable this for a specific routine,
annotate it with `.nosinks`. To disable it for a section of code, use
`{.push sinkInference: off.}`...`{.pop.}`.
- The compiler now supports a new switch `--panics:on` that turns runtime
errors like `IndexError` or `OverflowError` into fatal errors that **cannot**
be caught via Nim's `try` statement. `--panics:on` can improve the
runtime efficiency and code size of your program significantly.
- The compiler now warns about inheriting directly from `system.Exception` as
this is **very bad** style. You should inherit from `ValueError`, `IOError`,
`OSError` or from a different specific exception type that inherits from
`CatchableError` and cannot be confused with a `Defect`.
- The error reporting for Nim's effect system has been improved.
- Implicit conversions for `const` behave correctly now, meaning that code like
`const SOMECONST = 0.int; procThatTakesInt32(SOMECONST)` will be illegal now.
Simply write `const SOMECONST = 0` instead.
- The `{.dynlib.}` pragma is now required for exporting symbols when making
shared objects on POSIX and macOS, which make it consistent with the behavior
on Windows.
- The compiler is now more strict about type conversions concerning proc
types: Type conversions cannot be used to hide `.raise` effects or side
effects, instead a `cast` must be used. With the flag `--useVersion:1.0` the
old behaviour is emulated.
- The Nim compiler now implements a faster way to detect overflows based
on GCC's `__builtin_sadd_overflow` family of functions. (Clang also
supports these). Some versions of GCC lack this feature and unfortunately
we cannot detect this case reliably. So if you get compilation errors like
"undefined reference to `__builtin_saddll_overflow`" compile your programs
with `-d:nimEmulateOverflowChecks`.
## Tool changes
- Nimpretty doesn't accept negative indentation argument anymore, because it was
breaking files.
## Bugfixes
- Fixed "`nimgrep --nocolor` is ignored on posix; should be instead: `--nimgrep --color=[auto]|true|false`"
([#7591](https://github.com/nim-lang/Nim/issues/7591))
- Fixed "Runtime index on const array (of converted obj) causes C-compiler error"
([#10514](https://github.com/nim-lang/Nim/issues/10514))
- Fixed "windows x86 with vcc compile error with "asmNoStackFrame""
([#12298](https://github.com/nim-lang/Nim/issues/12298))
- Fixed "[TODO] regression: Error: Locks requires --threads:on option"
([#12330](https://github.com/nim-lang/Nim/issues/12330))
- Fixed "Add --cc option to --help or --fullhelp output"
([#12010](https://github.com/nim-lang/Nim/issues/12010))
- Fixed "questionable `csize` definition in `system.nim`"
([#12187](https://github.com/nim-lang/Nim/issues/12187))
- Fixed "os.getAppFilename() returns incorrect results on OpenBSD"
([#12389](https://github.com/nim-lang/Nim/issues/12389))
- Fixed "HashSet[uint64] slow insertion depending on values"
([#11764](https://github.com/nim-lang/Nim/issues/11764))
- Fixed "Differences between compiling 'classic call syntax' vs 'method call syntax' ."
([#12453](https://github.com/nim-lang/Nim/issues/12453))
- Fixed "c -d:nodejs --> SIGSEGV: Illegal storage access"
([#12502](https://github.com/nim-lang/Nim/issues/12502))
- Fixed "Closure iterator crashes on --newruntime due to "dangling references""
([#12443](https://github.com/nim-lang/Nim/issues/12443))
- Fixed "No `=destroy` for elements of closure environments other than for latest devel --gc:destructors"
([#12577](https://github.com/nim-lang/Nim/issues/12577))
- Fixed "strutils:formatBiggestFloat() gives different results in JS mode"
([#8242](https://github.com/nim-lang/Nim/issues/8242))
- Fixed "Regression (devel): the new `csize_t` definition isn't consistently used, nor tested thoroughly..."
([#12597](https://github.com/nim-lang/Nim/issues/12597))
- Fixed "tables.take() is defined only for `Table` and missed for other table containers"
([#12519](https://github.com/nim-lang/Nim/issues/12519))
- Fixed "`pthread_key_t` errors on OpenBSD"
([#12135](https://github.com/nim-lang/Nim/issues/12135))
- Fixed "newruntime: simple seq pop at ct results in compile error"
([#12644](https://github.com/nim-lang/Nim/issues/12644))
- Fixed "[Windows] finish.exe C:\Users\<USERNAME>\.nimble\bin is not in your PATH environment variable."
([#12319](https://github.com/nim-lang/Nim/issues/12319))
- Fixed "Error with strformat + asyncdispatch + const"
([#12612](https://github.com/nim-lang/Nim/issues/12612))
- Fixed "MultipartData needs $"
([#11863](https://github.com/nim-lang/Nim/issues/11863))
- Fixed "Nim stdlib style issues with --styleCheck:error"
([#12687](https://github.com/nim-lang/Nim/issues/12687))
- Fixed "new $nimbleDir path substitution yields unexpected search paths"
([#12767](https://github.com/nim-lang/Nim/issues/12767))
- Fixed "Regression: inlined procs now get multiple rounds of destructor injection"
([#12766](https://github.com/nim-lang/Nim/issues/12766))
- Fixed "newruntime: compiler generates defective code"
([#12669](https://github.com/nim-lang/Nim/issues/12669))
- Fixed "broken windows modules path handling because of 'os.relativePath' breaking changes"
([#12734](https://github.com/nim-lang/Nim/issues/12734))
- Fixed "for loop tuple syntax not rendered correctly"
([#12740](https://github.com/nim-lang/Nim/issues/12740))
- Fixed "Crash when trying to use `type.name[0]`"
([#12804](https://github.com/nim-lang/Nim/issues/12804))
- Fixed "Enums should be considered Trivial types in Atomics"
([#12812](https://github.com/nim-lang/Nim/issues/12812))
- Fixed "Produce static/const initializations for variables when possible"
([#12216](https://github.com/nim-lang/Nim/issues/12216))
- Fixed "Assigning descriminator field leads to internal assert with --gc:destructors"
([#12821](https://github.com/nim-lang/Nim/issues/12821))
- Fixed "nimsuggest `use` command does not return all instances of symbol"
([#12832](https://github.com/nim-lang/Nim/issues/12832))
- Fixed "@[] is a problem for --gc:destructors"
([#12820](https://github.com/nim-lang/Nim/issues/12820))
- Fixed "Codegen ICE in allPathsAsgnResult"
([#12827](https://github.com/nim-lang/Nim/issues/12827))
- Fixed "seq[Object with ref and destructor type] doesn't work in old runtime"
([#12882](https://github.com/nim-lang/Nim/issues/12882))
- Fixed "Destructor not invoked because it is instantiated too late, old runtime"
([#12883](https://github.com/nim-lang/Nim/issues/12883))
- Fixed "The collect macro does not handle if/case correctly"
([#12874](https://github.com/nim-lang/Nim/issues/12874))
- Fixed "allow typed/untyped params in magic procs (even if not in stdlib)"
([#12911](https://github.com/nim-lang/Nim/issues/12911))
- Fixed "ARC/newruntime memory corruption"
([#12899](https://github.com/nim-lang/Nim/issues/12899))
- Fixed "tasyncclosestall.nim still flaky test: Address already in use"
([#12919](https://github.com/nim-lang/Nim/issues/12919))
- Fixed "newruntime and computed goto: variables inside the loop are in generated code uninitialised"
([#12785](https://github.com/nim-lang/Nim/issues/12785))
- Fixed "osx: dsymutil needs to be called for debug builds to keep debug info"
([#12735](https://github.com/nim-lang/Nim/issues/12735))
- Fixed "codegen ICE with ref objects, gc:destructors"
([#12826](https://github.com/nim-lang/Nim/issues/12826))
- Fixed "mutable iterator cannot yield named tuples"
([#12945](https://github.com/nim-lang/Nim/issues/12945))
- Fixed "parsecfg stores "\r\n" line breaks just as "\n""
([#12970](https://github.com/nim-lang/Nim/issues/12970))
- Fixed "db_postgres.getValue issues warning when no rows found"
([#12973](https://github.com/nim-lang/Nim/issues/12973))
- Fixed "ARC: Unpacking tuple with seq causes segfault"
([#12989](https://github.com/nim-lang/Nim/issues/12989))
- Fixed "ARC/newruntime: strutils.join on seq with only empty strings causes segfault"
([#12965](https://github.com/nim-lang/Nim/issues/12965))
- Fixed "regression (1.0.4): `{.push exportc.}` wrongly affects generic instantiations, causing codegen errors"
([#12985](https://github.com/nim-lang/Nim/issues/12985))
- Fixed "cdt, crash with --gc:arc, works fine with default gc"
([#12978](https://github.com/nim-lang/Nim/issues/12978))
- Fixed "ARC: No indexError thrown on out-of-bound seq access, SIGSEGV instead"
([#12961](https://github.com/nim-lang/Nim/issues/12961))
- Fixed "ARC/async: Returning in a try-block results in wrong codegen"
([#12956](https://github.com/nim-lang/Nim/issues/12956))
- Fixed "asm keyword is generating wrong output C code when --cc:tcc"
([#12988](https://github.com/nim-lang/Nim/issues/12988))
- Fixed "Destructor not invoked"
([#13026](https://github.com/nim-lang/Nim/issues/13026))
- Fixed "ARC/newruntime: Adding inherited var ref object to seq with base type causes segfault"
([#12964](https://github.com/nim-lang/Nim/issues/12964))
- Fixed "Style check error with JS compiler target"
([#13032](https://github.com/nim-lang/Nim/issues/13032))
- Fixed "regression(1.0.4): undeclared identifier: 'readLines'; plus another regression and bug"
([#13013](https://github.com/nim-lang/Nim/issues/13013))
- Fixed "regression(1.04) `invalid pragma: since` with nim js"
([#12996](https://github.com/nim-lang/Nim/issues/12996))
- Fixed "Sink to MemMove optimization in injectdestructors"
([#13002](https://github.com/nim-lang/Nim/issues/13002))
- Fixed "--gc:arc: `catch` doesn't work with exception subclassing"
([#13072](https://github.com/nim-lang/Nim/issues/13072))
- Fixed "nim c --gc:arc --exceptions:{setjmp,goto} incorrectly handles raise; `nim cpp --gc:arc` is ok"
([#13070](https://github.com/nim-lang/Nim/issues/13070))
- Fixed "typetraits feature request - get subtype of a generic type"
([#6454](https://github.com/nim-lang/Nim/issues/6454))
- Fixed "CountTable inconsistencies between keys() and len() after setting value to 0"
([#12813](https://github.com/nim-lang/Nim/issues/12813))
- Fixed "{.align.} pragma is not applied if there is a generic field"
([#13122](https://github.com/nim-lang/Nim/issues/13122))
- Fixed "ARC, finalizer, allow rebinding the same function multiple times"
([#13112](https://github.com/nim-lang/Nim/issues/13112))
- Fixed "`nim doc` treats `export localSymbol` incorrectly"
([#13100](https://github.com/nim-lang/Nim/issues/13100))
- Fixed "--gc:arc SIGSEGV (double free?)"
([#13119](https://github.com/nim-lang/Nim/issues/13119))
- Fixed "codegen bug with arc"
([#13105](https://github.com/nim-lang/Nim/issues/13105))
- Fixed "symbols not defined in the grammar"
([#10665](https://github.com/nim-lang/Nim/issues/10665))
- Fixed "[JS] Move is not defined"
([#9674](https://github.com/nim-lang/Nim/issues/9674))
- Fixed "[TODO] pathutils.`/` can return invalid AbsoluteFile"
([#13121](https://github.com/nim-lang/Nim/issues/13121))
- Fixed "regression(1.04) `nim doc main.nim` generates broken html (no css)"
([#12998](https://github.com/nim-lang/Nim/issues/12998))
- Fixed "Wrong supportsCopyMem on string in type section"
([#13095](https://github.com/nim-lang/Nim/issues/13095))
- Fixed "Arc, finalizer, out of memory"
([#13157](https://github.com/nim-lang/Nim/issues/13157))
- Fixed "`--genscript` messes up nimcache and future nim invocations"
([#13144](https://github.com/nim-lang/Nim/issues/13144))
- Fixed "--gc:arc with --exceptions:goto for "nim c" generate invalid c code"
([#13186](https://github.com/nim-lang/Nim/issues/13186))
- Fixed "[regression] duplicate member `_i1` codegen bug"
([#13195](https://github.com/nim-lang/Nim/issues/13195))
- Fixed "RTree investigations with valgrind for --gc:arc"
([#13110](https://github.com/nim-lang/Nim/issues/13110))
- Fixed "relativePath("foo", ".") returns wrong path"
([#13211](https://github.com/nim-lang/Nim/issues/13211))
- Fixed "asyncftpclient - problem with welcome.msg"
([#4684](https://github.com/nim-lang/Nim/issues/4684))
- Fixed "Unclear error message, lowest priority"
([#13256](https://github.com/nim-lang/Nim/issues/13256))
- Fixed "Channel messages are corrupted"
([#13219](https://github.com/nim-lang/Nim/issues/13219))
- Fixed "Codegen bug with exportc and case objects"
([#13281](https://github.com/nim-lang/Nim/issues/13281))
- Fixed "[bugfix] fix #11590: c compiler warnings silently ignored, giving undefined behavior"
([#11591](https://github.com/nim-lang/Nim/issues/11591))
- Fixed "[CI] tnetdial flaky test"
([#13132](https://github.com/nim-lang/Nim/issues/13132))
- Fixed "Cross-Compiling with -d:mingw fails to locate compiler under OSX"
([#10717](https://github.com/nim-lang/Nim/issues/10717))
- Fixed "`nim doc --project` broken with imports below main project file or duplicate names"
([#13150](https://github.com/nim-lang/Nim/issues/13150))
- Fixed "regression: isNamedTuple(MyGenericTuple[int]) is false, should be true"
([#13349](https://github.com/nim-lang/Nim/issues/13349))
- Fixed "--gc:arc codegen bug copying objects bound to C structs with missing C struct fields"
([#13269](https://github.com/nim-lang/Nim/issues/13269))
- Fixed "write requires conversion to string"
([#13182](https://github.com/nim-lang/Nim/issues/13182))
- Fixed "Some remarks to stdlib documentation"
([#13352](https://github.com/nim-lang/Nim/issues/13352))
- Fixed "a `check` in unittest generated by template doesn't show actual value"
([#6736](https://github.com/nim-lang/Nim/issues/6736))
- Fixed "Implicit return with case expression fails with 'var' return."
([#3339](https://github.com/nim-lang/Nim/issues/3339))
- Fixed "Segfault with closure on arc"
([#13314](https://github.com/nim-lang/Nim/issues/13314))
- Fixed "[Macro] Crash on malformed case statement with multiple else"
([#13255](https://github.com/nim-lang/Nim/issues/13255))
- Fixed "regression: `echo 'discard' | nim c -r -` generates a file '-' ; `-` should be treated specially"
([#13374](https://github.com/nim-lang/Nim/issues/13374))
- Fixed "on OSX, debugging (w gdb or lldb) a nim program crashes at the 1st call to `execCmdEx`"
([#9634](https://github.com/nim-lang/Nim/issues/9634))
- Fixed "Internal error in getTypeDescAux"
([#13378](https://github.com/nim-lang/Nim/issues/13378))
- Fixed "gc:arc mode breaks tuple let"
([#13368](https://github.com/nim-lang/Nim/issues/13368))
- Fixed "Nim compiler hangs for certain C/C++ compiler errors"
([#8648](https://github.com/nim-lang/Nim/issues/8648))
- Fixed "htmlgen does not support `data-*` attributes"
([#13444](https://github.com/nim-lang/Nim/issues/13444))
- Fixed "[gc:arc] setLen will cause string not to be null-terminated."
([#13457](https://github.com/nim-lang/Nim/issues/13457))
- Fixed "joinPath("", "") is "/" ; should be """
([#13455](https://github.com/nim-lang/Nim/issues/13455))
- Fixed "[CI] flaky test on windows: tests/osproc/texitcode.nim"
([#13449](https://github.com/nim-lang/Nim/issues/13449))
- Fixed "Casting to float32 on NimVM is broken"
([#13479](https://github.com/nim-lang/Nim/issues/13479))
- Fixed "`--hints:off` doesn't work (doesn't override ~/.config/nim.cfg)"
([#8312](https://github.com/nim-lang/Nim/issues/8312))
- Fixed "joinPath("", "") is "/" ; should be """
([#13455](https://github.com/nim-lang/Nim/issues/13455))
- Fixed "tables.values is broken"
([#13496](https://github.com/nim-lang/Nim/issues/13496))
- Fixed "global user config can override project specific config"
([#9405](https://github.com/nim-lang/Nim/issues/9405))
- Fixed "Non deterministic macros and id consistency problem"
([#12627](https://github.com/nim-lang/Nim/issues/12627))
- Fixed "try expression doesn't work with return on expect branch"
([#13490](https://github.com/nim-lang/Nim/issues/13490))
- Fixed "CI will break every 4 years on feb 28: times doesn't handle leap years properly"
([#13543](https://github.com/nim-lang/Nim/issues/13543))
- Fixed "[minor] `nimgrep --word` doesn't work with operators (eg misses `1 +% 2`)"
([#13528](https://github.com/nim-lang/Nim/issues/13528))
- Fixed "`as` is usable as infix operator but its existence and precedence are not documented"
([#13409](https://github.com/nim-lang/Nim/issues/13409))
- Fixed "JSON unmarshalling drops seq's items"
([#13531](https://github.com/nim-lang/Nim/issues/13531))
- Fixed "os.joinPath returns wrong path when head ends '\' or '/' and tail starts '..'."
([#13579](https://github.com/nim-lang/Nim/issues/13579))
- Fixed "Block-local types with the same name lead to bad codegen (sighashes regression)"
([#5170](https://github.com/nim-lang/Nim/issues/5170))
- Fixed "tuple codegen error"
([#12704](https://github.com/nim-lang/Nim/issues/12704))
- Fixed "newHttpHeaders does not accept repeated headers"
([#13573](https://github.com/nim-lang/Nim/issues/13573))
- Fixed "regression: --incremental:on fails on simplest example"
([#13319](https://github.com/nim-lang/Nim/issues/13319))
- Fixed "strscan can't get value of last element in format"
([#13605](https://github.com/nim-lang/Nim/issues/13605))
- Fixed "hashes_examples crashes with "Bus Error" (unaligned access) on sparc64"
([#12508](https://github.com/nim-lang/Nim/issues/12508))
- Fixed "gc:arc bug with re-used `seq[T]`"
([#13596](https://github.com/nim-lang/Nim/issues/13596))
- Fixed "`raise CatchableError` is broken with --gc:arc when throwing inside a proc"
([#13599](https://github.com/nim-lang/Nim/issues/13599))
- Fixed "cpp --gc:arc --exceptions:goto fails to raise with discard"
([#13436](https://github.com/nim-lang/Nim/issues/13436))
- Fixed "terminal doesn't compile with -d:useWinAnsi"
([#13607](https://github.com/nim-lang/Nim/issues/13607))
- Fixed "Parsing "sink ptr T" - region needs to be an object type"
([#12757](https://github.com/nim-lang/Nim/issues/12757))
- Fixed "gc:arc + threads:on + closures compilation error"
([#13519](https://github.com/nim-lang/Nim/issues/13519))
- Fixed "[ARC] segmentation fault"
([#13240](https://github.com/nim-lang/Nim/issues/13240))
- Fixed "times.toDateTime buggy on 29th, 30th and 31th of each month"
([#13558](https://github.com/nim-lang/Nim/issues/13558))
- Fixed "Deque misbehaves on VM"
([#13310](https://github.com/nim-lang/Nim/issues/13310))
- Fixed "Nimscript listFiles should throw exception when path is not found"
([#12676](https://github.com/nim-lang/Nim/issues/12676))
- Fixed "koch boot fails if even an empty config.nims is present in ~/.config/nims/ [devel regression]"
([#13633](https://github.com/nim-lang/Nim/issues/13633))
- Fixed "nim doc generates lots of false positive LockLevel warnings"
([#13218](https://github.com/nim-lang/Nim/issues/13218))
- Fixed "Arrays are passed by copy to iterators, causing crashes, unnecessary allocations and slowdowns"
([#12747](https://github.com/nim-lang/Nim/issues/12747))
- Fixed "Range types always uses signed integer as a base type"
([#13646](https://github.com/nim-lang/Nim/issues/13646))
- Fixed "Generate c code cannot compile with recent devel version"
([#13645](https://github.com/nim-lang/Nim/issues/13645))
- Fixed "[regression] VM: Error: cannot convert -1 to uint64"
([#13661](https://github.com/nim-lang/Nim/issues/13661))
- Fixed "Spurious raiseException(Exception) detected"
([#13654](https://github.com/nim-lang/Nim/issues/13654))
- Fixed "gc:arc memory leak"
([#13659](https://github.com/nim-lang/Nim/issues/13659))
- Fixed "Error: cannot convert -1 to uint (inside tuples)"
([#13671](https://github.com/nim-lang/Nim/issues/13671))
- Fixed "strformat issue with --gc:arc"
([#13622](https://github.com/nim-lang/Nim/issues/13622))
- Fixed "astToStr doesn't work inside generics"
([#13524](https://github.com/nim-lang/Nim/issues/13524))
- Fixed "oswalkdir.walkDirRec wont return folders"
([#11458](https://github.com/nim-lang/Nim/issues/11458))
- Fixed "`echo 'echo 1' | nim c -r -` silently gives wrong results (nimBetterRun not updated for stdin)"
([#13412](https://github.com/nim-lang/Nim/issues/13412))
- Fixed "gc:arc destroys the global variable accidentally."
([#13691](https://github.com/nim-lang/Nim/issues/13691))
- Fixed "[minor] sigmatch errors should be sorted, for reproducible errors"
([#13538](https://github.com/nim-lang/Nim/issues/13538))
- Fixed "Exception when converting csize to clong"
([#13698](https://github.com/nim-lang/Nim/issues/13698))
- Fixed "ARC: variables are no copied on the thread spawn causing crashes"
([#13708](https://github.com/nim-lang/Nim/issues/13708))
- Fixed "Illegal distinct seq causes compiler crash"
([#13720](https://github.com/nim-lang/Nim/issues/13720))
- Fixed "cyclic seq definition crashes the compiler"
([#13715](https://github.com/nim-lang/Nim/issues/13715))
- Fixed "Iterator with openArray parameter make the argument evaluated many times"
([#13417](https://github.com/nim-lang/Nim/issues/13417))
- Fixed "net/asyncnet: Unable to access peer's certificate chain"
([#13299](https://github.com/nim-lang/Nim/issues/13299))
- Fixed "Accidentally "SIGSEGV: Illegal storage access" error after arc optimizations (#13325)"
([#13709](https://github.com/nim-lang/Nim/issues/13709))
- Fixed "Base64 Regression"
([#13722](https://github.com/nim-lang/Nim/issues/13722))
- Fixed "A regression (?) with --gc:arc and repr"
([#13731](https://github.com/nim-lang/Nim/issues/13731))
- Fixed "Internal compiler error when using the new variable pragmas"
([#13737](https://github.com/nim-lang/Nim/issues/13737))
- Fixed "bool conversion produces vcc 2019 warning at cpp compilation stage"
([#13744](https://github.com/nim-lang/Nim/issues/13744))
- Fixed "Compiler "does not detect" a type recursion error in the wrong code, remaining frozen"
([#13763](https://github.com/nim-lang/Nim/issues/13763))
- Fixed "[minor] regression: `Foo[0.0] is Foo[-0.0]` is now false"
([#13730](https://github.com/nim-lang/Nim/issues/13730))
- Fixed "`nim doc` - only whitespace on first line causes segfault"
([#13631](https://github.com/nim-lang/Nim/issues/13631))
- Fixed "hashset regression"
([#13794](https://github.com/nim-lang/Nim/issues/13794))
- Fixed "`os.getApplFreebsd` could return incorrect paths in the case of a long path"
([#13806](https://github.com/nim-lang/Nim/issues/13806))
- Fixed "Destructors are not inherited"
([#13810](https://github.com/nim-lang/Nim/issues/13810))
- Fixed "io.readLines AssertionError on devel"
([#13829](https://github.com/nim-lang/Nim/issues/13829))
- Fixed "exceptions:goto accidentally reset the variable during exception handling"
([#13782](https://github.com/nim-lang/Nim/issues/13782))

View File

@@ -1,33 +1,20 @@
# vx.xx.x - yyyy-mm-dd
# v1.xx.x - yyyy-mm-dd
This is an example file.
The changes should go to changelog.md!
## Changes affecting backwards compatibility
## Standard library additions and changes
- Example item: `Foo` changed to `Bar`.
### Breaking changes in the standard library
### Breaking changes in the compiler
## Library additions
## Library changes
## Language additions
- Added `example.exampleProc`.
- Changed `example.foo` to take additional `bar` parameter.
## Language changes
### Tool changes
## Compiler changes
### Compiler changes
## Tool changes
## Bugfixes

View File

@@ -22,17 +22,17 @@ proc isPartOfAux(n: PNode, b: PType, marker: var IntSet): TAnalysisResult =
result = arNo
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = isPartOfAux(n.sons[i], b, marker)
for i in 0..<n.len:
result = isPartOfAux(n[i], b, marker)
if result == arYes: return
of nkRecCase:
assert(n.sons[0].kind == nkSym)
result = isPartOfAux(n.sons[0], b, marker)
assert(n[0].kind == nkSym)
result = isPartOfAux(n[0], b, marker)
if result == arYes: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = isPartOfAux(lastSon(n.sons[i]), b, marker)
result = isPartOfAux(lastSon(n[i]), b, marker)
if result == arYes: return
else: discard "isPartOfAux(record case branch)"
of nkSym:
@@ -46,14 +46,14 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
case a.kind
of tyObject:
if a.sons[0] != nil:
result = isPartOfAux(a.sons[0].skipTypes(skipPtrs), b, marker)
if a[0] != nil:
result = isPartOfAux(a[0].skipTypes(skipPtrs), b, marker)
if result == arNo: result = isPartOfAux(a.n, b, marker)
of tyGenericInst, tyDistinct, tyAlias, tySink:
result = isPartOfAux(lastSon(a), b, marker)
of tyArray, tySet, tyTuple:
for i in 0 ..< sonsLen(a):
result = isPartOfAux(a.sons[i], b, marker)
for i in 0..<a.len:
result = isPartOfAux(a[i], b, marker)
if result == arYes: return
else: discard
@@ -108,7 +108,7 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
result = arMaybe
of nkBracketExpr:
result = isPartOf(a[0], b[0])
if len(a) >= 2 and len(b) >= 2:
if a.len >= 2 and b.len >= 2:
# array accesses:
if result == arYes and isDeepConstExpr(a[1]) and isDeepConstExpr(b[1]):
# we know it's the same array and we have 2 constant indexes;
@@ -181,16 +181,19 @@ proc isPartOf*(a, b: PNode): TAnalysisResult =
else: discard
of nkObjConstr:
result = arNo
for i in 1 ..< b.len:
for i in 1..<b.len:
let res = isPartOf(a, b[i][1])
if res != arNo:
result = res
if res == arYes: break
of nkCallKinds:
result = arNo
for i in 1 ..< b.len:
for i in 1..<b.len:
let res = isPartOf(a, b[i])
if res != arNo:
result = res
if res == arYes: break
of nkBracket:
if b.len > 0:
result = isPartOf(a, b[0])
else: discard

View File

@@ -71,7 +71,7 @@ iterator parseTableCells*(s: string, delim = '\t'): Cell =
proc alignTable*(s: string, delim = '\t', fill = ' ', sep = " "): string =
## formats a `delim`-delimited `s` representing a table; each cell is aligned
## to a width that's computed for each column; consecutive columns are
## delimted by `sep`, and alignment space is filled using `fill`.
## delimited by `sep`, and alignment space is filled using `fill`.
## More customized formatting can be done by calling `parseTableCells` directly.
for cell in parseTableCells(s, delim):
result.add cell.text

File diff suppressed because it is too large Load Diff

View File

@@ -24,46 +24,55 @@ proc typeToYaml*(conf: ConfigRef; n: PType, indent: int = 0, maxRecDepth: int =
proc symToYaml*(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1): Rope
proc lineInfoToStr*(conf: ConfigRef; info: TLineInfo): Rope
when declared(echo):
# these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements:
proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.}
proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
template debug*(x: PSym|PType|PNode) {.deprecated.} =
when compiles(c.config):
debug(c.config, x)
elif compiles(c.graph.config):
debug(c.graph.config, x)
# these are for debugging only: They are not really deprecated, but I want
# the warning so that release versions do not contain debugging statements:
proc debug*(n: PSym; conf: ConfigRef = nil) {.exportc: "debugSym", deprecated.}
proc debug*(n: PType; conf: ConfigRef = nil) {.exportc: "debugType", deprecated.}
proc debug*(n: PNode; conf: ConfigRef = nil) {.exportc: "debugNode", deprecated.}
proc typekinds*(t: PType) {.deprecated.} =
var t = t
var s = ""
while t != nil and t.len > 0:
s.add $t.kind
s.add " "
t = t.lastSon
echo s
template debug*(x: PSym|PType|PNode) {.deprecated.} =
when compiles(c.config):
debug(c.config, x)
elif compiles(c.graph.config):
debug(c.graph.config, x)
else:
error()
template debug*(x: auto) {.deprecated.} =
echo x
template mdbg*: bool {.deprecated.} =
when compiles(c.graph):
c.module.fileIdx == c.graph.config.projectMainIdx
elif compiles(c.module):
c.module.fileIdx == c.config.projectMainIdx
elif compiles(c.c.module):
c.c.module.fileIdx == c.c.config.projectMainIdx
elif compiles(m.c.module):
m.c.module.fileIdx == m.c.config.projectMainIdx
elif compiles(cl.c.module):
cl.c.module.fileIdx == cl.c.config.projectMainIdx
elif compiles(p):
when compiles(p.lex):
p.lex.fileIdx == p.lex.config.projectMainIdx
else:
error()
template debug*(x: auto) {.deprecated.} =
echo x
template mdbg*: bool {.deprecated.} =
when compiles(c.graph):
c.module.fileIdx == c.graph.config.projectMainIdx
elif compiles(c.module):
c.module.fileIdx == c.config.projectMainIdx
elif compiles(c.c.module):
c.c.module.fileIdx == c.c.config.projectMainIdx
elif compiles(m.c.module):
m.c.module.fileIdx == m.c.config.projectMainIdx
elif compiles(cl.c.module):
cl.c.module.fileIdx == cl.c.config.projectMainIdx
elif compiles(p):
when compiles(p.lex):
p.lex.fileIdx == p.lex.config.projectMainIdx
else:
p.module.module.fileIdx == p.config.projectMainIdx
elif compiles(m.module.fileIdx):
m.module.fileIdx == m.config.projectMainIdx
elif compiles(L.fileIdx):
L.fileIdx == L.config.projectMainIdx
else:
error()
p.module.module.fileIdx == p.config.projectMainIdx
elif compiles(m.module.fileIdx):
m.module.fileIdx == m.config.projectMainIdx
elif compiles(L.fileIdx):
L.fileIdx == L.config.projectMainIdx
else:
error()
# --------------------------- ident tables ----------------------------------
proc idTableGet*(t: TIdTable, key: PIdObj): RootRef
@@ -77,7 +86,6 @@ proc idNodeTablePut*(t: var TIdNodeTable, key: PIdObj, val: PNode)
# ---------------------------------------------------------------------------
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
proc lookupInRecord*(n: PNode, field: PIdent): PSym
proc mustRehash*(length, counter: int): bool
proc nextTry*(h, maxHash: Hash): Hash {.inline.}
@@ -108,16 +116,16 @@ proc skipConvAndClosure*(n: PNode): PNode =
case result.kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64,
nkClosure:
result = result.sons[0]
result = result[0]
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = result.sons[1]
result = result[1]
else: break
proc sameValue*(a, b: PNode): bool =
result = false
case a.kind
of nkCharLit..nkUInt64Lit:
if b.kind in {nkCharLit..nkUInt64Lit}: result = a.intVal == b.intVal
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) == getInt(b)
of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit:
@@ -131,8 +139,8 @@ proc leValue*(a, b: PNode): bool =
# a <= b?
result = false
case a.kind
of nkCharLit..nkUInt32Lit:
if b.kind in {nkCharLit..nkUInt32Lit}: result = a.intVal <= b.intVal
of nkCharLit..nkUInt64Lit:
if b.kind in {nkCharLit..nkUInt64Lit}: result = getInt(a) <= getInt(b)
of nkFloatLit..nkFloat64Lit:
if b.kind in {nkFloatLit..nkFloat64Lit}: result = a.floatVal <= b.floatVal
of nkStrLit..nkTripleStrLit:
@@ -152,17 +160,17 @@ proc lookupInRecord(n: PNode, field: PIdent): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = lookupInRecord(n.sons[i], field)
for i in 0..<n.len:
result = lookupInRecord(n[i], field)
if result != nil: return
of nkRecCase:
if (n.sons[0].kind != nkSym): return nil
result = lookupInRecord(n.sons[0], field)
if (n[0].kind != nkSym): return nil
result = lookupInRecord(n[0], field)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), field)
result = lookupInRecord(lastSon(n[i]), field)
if result != nil: return
else: return nil
of nkSym:
@@ -174,14 +182,55 @@ proc getModule*(s: PSym): PSym =
assert((result.kind == skModule) or (result.owner != result))
while result != nil and result.kind != skModule: result = result.owner
proc getSymFromList(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start ..< sonsLen(list):
if list.sons[i].kind == nkSym:
result = list.sons[i].sym
proc fromSystem*(op: PSym): bool {.inline.} = sfSystemModule in getModule(op).flags
proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym =
for i in start..<list.len:
if list[i].kind == nkSym:
result = list[i].sym
if result.name.id == ident.id: return
else: return nil
result = nil
proc sameIgnoreBacktickGensymInfo(a, b: string): bool =
if a[0] != b[0]: return false
var alen = a.len - 1
while alen > 0 and a[alen] != '`': dec(alen)
if alen <= 0: alen = a.len
var i = 1
var j = 1
while true:
while i < alen and a[i] == '_': inc i
while j < b.len and b[j] == '_': inc j
var aa = if i < alen: toLowerAscii(a[i]) else: '\0'
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
if aa != bb: return false
# the characters are identical:
if i >= alen:
# both cursors at the end:
if j >= b.len: return true
# not yet at the end of 'b':
return false
elif j >= b.len:
return false
inc i
inc j
proc getNamedParamFromList*(list: PNode, ident: PIdent): PSym =
## Named parameters are special because a named parameter can be
## gensym'ed and then they have '\`<number>' suffix that we need to
## ignore, see compiler / evaltempl.nim, snippet:
##
##..code-block:: nim
##
## result.add newIdentNode(getIdent(c.ic, x.name.s & "\`gensym" & $x.id),
## if c.instLines: actual.info else: templ.info)
for i in 1..<list.len:
let it = list[i].sym
if it.name.id == ident.id or
sameIgnoreBacktickGensymInfo(it.name.s, ident.s): return it
proc hashNode(p: RootRef): Hash =
result = hash(cast[pointer](p))
@@ -206,15 +255,15 @@ proc makeYamlString*(s: string): Rope =
const MaxLineLength = 64
result = nil
var res = "\""
for i in 0 ..< s.len:
for i in 0..<s.len:
if (i + 1) mod MaxLineLength == 0:
add(res, '\"')
add(res, "\n")
add(result, rope(res))
res.add('\"')
res.add("\n")
result.add(rope(res))
res = "\"" # reset
add(res, toYamlChar(s[i]))
add(res, '\"')
add(result, rope(res))
res.add(toYamlChar(s[i]))
res.add('\"')
result.add(rope(res))
proc flagsToStr[T](flags: set[T]): Rope =
if flags == {}:
@@ -222,8 +271,8 @@ proc flagsToStr[T](flags: set[T]): Rope =
else:
result = nil
for x in items(flags):
if result != nil: add(result, ", ")
add(result, makeYamlString($x))
if result != nil: result.add(", ")
result.add(makeYamlString($x))
result = "[" & result & "]"
proc lineInfoToStr(conf: ConfigRef; info: TLineInfo): Rope =
@@ -250,25 +299,25 @@ proc symToYamlAux(conf: ConfigRef; n: PSym, marker: var IntSet, indent: int,
# indent + 2, maxRecDepth - 1),
let istr = rspaces(indent + 2)
result = rope("{")
addf(result, "$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
addf(result, "$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
addf(result, "$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
result.addf("$N$1\"name\": $2", [istr, makeYamlString(n.name.s)])
result.addf("$N$1\"typ\": $2", [istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth - 1)])
if conf != nil:
# if we don't pass the config, we probably don't care about the line info
addf(result, "$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
result.addf("$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
if card(n.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
addf(result, "$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
addf(result, "$N$1\"ast\": $2", [istr, ast])
addf(result, "$N$1\"options\": $2", [istr, flagsToStr(n.options)])
addf(result, "$N$1\"position\": $2", [istr, rope(n.position)])
addf(result, "$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
addf(result, "$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
result.addf("$N$1\"magic\": $2", [istr, makeYamlString($n.magic)])
result.addf("$N$1\"ast\": $2", [istr, ast])
result.addf("$N$1\"options\": $2", [istr, flagsToStr(n.options)])
result.addf("$N$1\"position\": $2", [istr, rope(n.position)])
result.addf("$N$1\"k\": $2", [istr, makeYamlString($n.loc.k)])
result.addf("$N$1\"storage\": $2", [istr, makeYamlString($n.loc.storage)])
if card(n.loc.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
addf(result, "$N$1\"r\": $2", [istr, n.loc.r])
addf(result, "$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
addf(result, "$N$1}", [rspaces(indent)])
result.addf("$N$1\"flags\": $2", [istr, makeYamlString($n.loc.flags)])
result.addf("$N$1\"r\": $2", [istr, n.loc.r])
result.addf("$N$1\"lode\": $2", [istr, treeToYamlAux(conf, n.loc.lode, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1}", [rspaces(indent)])
proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
maxRecDepth: int): Rope =
@@ -279,27 +328,27 @@ proc typeToYamlAux(conf: ConfigRef; n: PType, marker: var IntSet, indent: int,
sonsRope = "\"$1 @$2\"" % [rope($n.kind), rope(
strutils.toHex(cast[ByteAddress](n), sizeof(n) * 2))]
else:
if sonsLen(n) > 0:
if n.len > 0:
sonsRope = rope("[")
for i in 0 ..< sonsLen(n):
if i > 0: add(sonsRope, ",")
addf(sonsRope, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n.sons[i],
for i in 0..<n.len:
if i > 0: sonsRope.add(",")
sonsRope.addf("$N$1$2", [rspaces(indent + 4), typeToYamlAux(conf, n[i],
marker, indent + 4, maxRecDepth - 1)])
addf(sonsRope, "$N$1]", [rspaces(indent + 2)])
sonsRope.addf("$N$1]", [rspaces(indent + 2)])
else:
sonsRope = rope("null")
let istr = rspaces(indent + 2)
result = rope("{")
addf(result, "$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
addf(result, "$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
addf(result, "$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
result.addf("$N$1\"sym\": $2", [istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth - 1)])
result.addf("$N$1\"n\": $2", [istr, treeToYamlAux(conf, n.n, marker, indent + 2, maxRecDepth - 1)])
if card(n.flags) > 0:
addf(result, "$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
addf(result, "$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
addf(result, "$N$1\"size\": $2", [istr, rope(n.size)])
addf(result, "$N$1\"align\": $2", [istr, rope(n.align)])
addf(result, "$N$1\"sons\": $2", [istr, sonsRope])
result.addf("$N$1\"flags\": $2", [istr, flagsToStr(n.flags)])
result.addf("$N$1\"callconv\": $2", [istr, makeYamlString(CallingConvToStr[n.callConv])])
result.addf("$N$1\"size\": $2", [istr, rope(n.size)])
result.addf("$N$1\"align\": $2", [istr, rope(n.align)])
result.addf("$N$1\"sons\": $2", [istr, sonsRope])
proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
maxRecDepth: int): Rope =
@@ -310,34 +359,34 @@ proc treeToYamlAux(conf: ConfigRef; n: PNode, marker: var IntSet, indent: int,
result = "{$N$1\"kind\": $2" % [istr, makeYamlString($n.kind)]
if maxRecDepth != 0:
if conf != nil:
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
result.addf(",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
case n.kind
of nkCharLit..nkInt64Lit:
addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
result.addf(",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
addf(result, ",$N$1\"floatVal\": $2",
result.addf(",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
result.addf(",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
addf(result, ",$N$1\"sym\": $2",
result.addf(",$N$1\"sym\": $2",
[istr, symToYamlAux(conf, n.sym, marker, indent + 2, maxRecDepth)])
of nkIdent:
if n.ident != nil:
addf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
result.addf(",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)])
else:
addf(result, ",$N$1\"ident\": null", [istr])
result.addf(",$N$1\"ident\": null", [istr])
else:
if sonsLen(n) > 0:
addf(result, ",$N$1\"sons\": [", [istr])
for i in 0 ..< sonsLen(n):
if i > 0: add(result, ",")
addf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n.sons[i],
if n.len > 0:
result.addf(",$N$1\"sons\": [", [istr])
for i in 0..<n.len:
if i > 0: result.add(",")
result.addf("$N$1$2", [rspaces(indent + 4), treeToYamlAux(conf, n[i],
marker, indent + 4, maxRecDepth - 1)])
addf(result, "$N$1]", [istr])
addf(result, ",$N$1\"typ\": $2",
result.addf("$N$1]", [istr])
result.addf(",$N$1\"typ\": $2",
[istr, typeToYamlAux(conf, n.typ, marker, indent + 2, maxRecDepth)])
addf(result, "$N$1}", [rspaces(indent)])
result.addf("$N$1}", [rspaces(indent)])
proc treeToYaml(conf: ConfigRef; n: PNode, indent: int = 0, maxRecDepth: int = - 1): Rope =
var marker = initIntSet()
@@ -379,7 +428,7 @@ proc indentLess(this: var DebugPrinter) =
proc newlineAndIndent(this: var DebugPrinter) =
this.res.add "\n"
this.currentLine += 1
for i in 0 ..< this.indent:
for i in 0..<this.indent:
this.res.add ' '
proc openCurly(this: var DebugPrinter) =
@@ -515,12 +564,12 @@ proc value(this: var DebugPrinter; value: PType) =
this.key "n"
this.value value.n
if sonsLen(value) > 0:
if value.len > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
for i in 0..<value.len:
this.value value[i]
if i != value.len - 1:
this.comma
this.closeBracket
@@ -568,41 +617,41 @@ proc value(this: var DebugPrinter; value: PNode) =
if this.renderSymType and value.typ != nil:
this.key "typ"
this.value value.typ
if sonsLen(value) > 0:
if value.len > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
for i in 0..<value.len:
this.value value[i]
if i != value.len - 1:
this.comma
this.closeBracket
this.closeCurly
when declared(echo):
proc debug(n: PSym; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PType; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PSym; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PNode; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
#this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PType; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc debug(n: PNode; conf: ConfigRef) =
var this: DebugPrinter
this.visited = initTable[pointer, int]()
#this.renderSymType = true
this.useColor = not defined(windows)
this.value(n)
echo($this.res)
proc nextTry(h, maxHash: Hash): Hash =
result = ((5 * h) + 1) and maxHash
@@ -629,13 +678,13 @@ proc objectSetRawInsert(data: var TObjectSeq, obj: RootRef) =
proc objectSetEnlarge(t: var TObjectSet) =
var n: TObjectSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i] != nil: objectSetRawInsert(n, t.data[i])
swap(t.data, n)
proc objectSetIncl*(t: var TObjectSet, obj: RootRef) =
if mustRehash(len(t.data), t.counter): objectSetEnlarge(t)
if mustRehash(t.data.len, t.counter): objectSetEnlarge(t)
objectSetRawInsert(t.data, obj)
inc(t.counter)
@@ -648,7 +697,7 @@ proc objectSetContainsOrIncl*(t: var TObjectSet, obj: RootRef): bool =
if it == obj:
return true # found it
h = nextTry(h, high(t.data))
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
objectSetEnlarge(t)
objectSetRawInsert(t.data, obj)
else:
@@ -691,13 +740,13 @@ proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
proc strTableEnlarge(t: var TStrTable) =
var n: seq[PSym]
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i] != nil: strTableRawInsert(n, t.data[i])
swap(t.data, n)
proc strTableAdd*(t: var TStrTable, n: PSym) =
if mustRehash(len(t.data), t.counter): strTableEnlarge(t)
if mustRehash(t.data.len, t.counter): strTableEnlarge(t)
strTableRawInsert(t.data, n)
inc(t.counter)
@@ -724,7 +773,7 @@ proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
if not onConflictKeepOld:
t.data[replaceSlot] = n # overwrite it with newer definition!
return t.data[replaceSlot] # found it
elif mustRehash(len(t.data), t.counter):
elif mustRehash(t.data.len, t.counter):
strTableEnlarge(t)
strTableRawInsert(t.data, n)
else:
@@ -828,7 +877,7 @@ iterator items*(tab: TStrTable): PSym =
s = nextIter(it, tab)
proc hasEmptySlot(data: TIdPairSeq): bool =
for h in 0 .. high(data):
for h in 0..high(data):
if data[h].key == nil:
return true
result = false
@@ -881,9 +930,9 @@ proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) =
assert(t.data[index].key != nil)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
if mustRehash(t.data.len, t.counter):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i].key != nil:
idTableRawInsert(n, t.data[i].key, t.data[i].val)
assert(hasEmptySlot(n))
@@ -892,7 +941,7 @@ proc idTablePut(t: var TIdTable, key: PIdObj, val: RootRef) =
inc(t.counter)
iterator idTablePairs*(t: TIdTable): tuple[key: PIdObj, val: RootRef] =
for i in 0 .. high(t.data):
for i in 0..high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
proc idNodeTableRawGet(t: TIdNodeTable, key: PIdObj): int =
@@ -926,10 +975,10 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
assert(t.data[index].key != nil)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
var n: TIdNodePairSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(t.data):
if t.data[i].key != nil:
idNodeTableRawInsert(n, t.data[i].key, t.data[i].val)
swap(t.data, n)
@@ -937,13 +986,13 @@ proc idNodeTablePut(t: var TIdNodeTable, key: PIdObj, val: PNode) =
inc(t.counter)
iterator pairs*(t: TIdNodeTable): tuple[key: PIdObj, val: PNode] =
for i in 0 .. high(t.data):
for i in 0..high(t.data):
if not isNil(t.data[i].key): yield (t.data[i].key, t.data[i].val)
proc initIITable(x: var TIITable) =
x.counter = 0
newSeq(x.data, StartSize)
for i in 0 ..< StartSize: x.data[i].key = InvalidKey
for i in 0..<StartSize: x.data[i].key = InvalidKey
proc iiTableRawGet(t: TIITable, key: int): int =
var h: Hash
@@ -974,11 +1023,11 @@ proc iiTablePut(t: var TIITable, key, val: int) =
assert(t.data[index].key != InvalidKey)
t.data[index].val = val
else:
if mustRehash(len(t.data), t.counter):
if mustRehash(t.data.len, t.counter):
var n: TIIPairSeq
newSeq(n, len(t.data) * GrowthFactor)
for i in 0 .. high(n): n[i].key = InvalidKey
for i in 0 .. high(t.data):
newSeq(n, t.data.len * GrowthFactor)
for i in 0..high(n): n[i].key = InvalidKey
for i in 0..high(t.data):
if t.data[i].key != InvalidKey:
iiTableRawInsert(n, t.data[i].key, t.data[i].val)
swap(t.data, n)
@@ -992,3 +1041,10 @@ proc isAddrNode*(n: PNode): bool =
if n[0].kind == nkSym and n[0].sym.magic == mAddr: true
else: false
else: false
proc listSymbolNames*(symbols: openArray[PSym]): string =
for sym in symbols:
if result.len > 0:
result.add ", "
result.add sym.name.s

View File

@@ -52,25 +52,25 @@ proc bitSetInit(b: var TBitSet, length: int) =
newSeq(b, length)
proc bitSetUnion(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] or y[i]
for i in 0..high(x): x[i] = x[i] or y[i]
proc bitSetDiff(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] and not y[i]
for i in 0..high(x): x[i] = x[i] and not y[i]
proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] xor y[i]
for i in 0..high(x): x[i] = x[i] xor y[i]
proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
for i in 0 .. high(x): x[i] = x[i] and y[i]
for i in 0..high(x): x[i] = x[i] and y[i]
proc bitSetEquals(x, y: TBitSet): bool =
for i in 0 .. high(x):
for i in 0..high(x):
if x[i] != y[i]:
return false
result = true
proc bitSetContains(x, y: TBitSet): bool =
for i in 0 .. high(x):
for i in 0..high(x):
if (x[i] and not y[i]) != Zero:
return false
result = true

View File

@@ -37,34 +37,34 @@ template eq(a, b): bool = cmp(a, b) == 0
proc getOrDefault*[Key, Val](b: BTree[Key, Val], key: Key): Val =
var x = b.root
while x.isInternal:
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if j+1 == x.entries or less(key, x.keys[j+1]):
x = x.links[j]
break
assert(not x.isInternal)
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if eq(key, x.keys[j]): return x.vals[j]
proc contains*[Key, Val](b: BTree[Key, Val], key: Key): bool =
var x = b.root
while x.isInternal:
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if j+1 == x.entries or less(key, x.keys[j+1]):
x = x.links[j]
break
assert(not x.isInternal)
for j in 0 ..< x.entries:
for j in 0..<x.entries:
if eq(key, x.keys[j]): return true
return false
proc copyHalf[Key, Val](h, result: Node[Key, Val]) =
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
result.keys[j] = h.keys[Mhalf + j]
if h.isInternal:
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
result.links[j] = h.links[Mhalf + j]
else:
for j in 0 ..< Mhalf:
for j in 0..<Mhalf:
shallowCopy(result.vals[j], h.vals[Mhalf + j])
proc split[Key, Val](h: Node[Key, Val]): Node[Key, Val] =
@@ -191,7 +191,7 @@ when isMainModule:
st.add("www.yahoo.com", "216.109.118.65")
assert st.getOrDefault("www.cs.princeton.edu") == "abc"
assert st.getOrDefault("www.harvardsucks.com") == nil
assert st.getOrDefault("www.harvardsucks.com") == ""
assert st.getOrDefault("www.simpsons.com") == "209.052.165.60"
assert st.getOrDefault("www.apple.com") == "17.112.152.32"

View File

@@ -102,7 +102,7 @@ proc hashTree(c: var MD5Context, n: PNode) =
of nkStrLit..nkTripleStrLit:
c &= n.strVal
else:
for i in 0..<n.len: hashTree(c, n.sons[i])
for i in 0..<n.len: hashTree(c, n[i])
proc hashType(c: var MD5Context, t: PType) =
# modelled after 'typeToString'
@@ -120,44 +120,44 @@ proc hashType(c: var MD5Context, t: PType) =
case t.kind
of tyGenericBody, tyGenericInst, tyGenericInvocation:
for i in 0 ..< sonsLen(t)-ord(t.kind != tyGenericInvocation):
c.hashType t.sons[i]
for i in 0..<t.len-ord(t.kind != tyGenericInvocation):
c.hashType t[i]
of tyUserTypeClass:
internalAssert t.sym != nil and t.sym.owner != nil
c &= t.sym.owner.name.s
of tyUserTypeClassInst:
let body = t.base
c.hashSym body.sym
for i in 1 .. sonsLen(t) - 2:
c.hashType t.sons[i]
for i in 1..<t.len-1:
c.hashType t[i]
of tyFromExpr:
c.hashTree(t.n)
of tyArray:
c.hashTree(t.sons[0].n)
c.hashType(t.sons[1])
c.hashTree(t[0].n)
c.hashType(t[1])
of tyTuple:
if t.n != nil:
assert(sonsLen(t.n) == sonsLen(t))
for i in 0 ..< sonsLen(t.n):
assert(t.n.sons[i].kind == nkSym)
c &= t.n.sons[i].sym.name.s
assert(t.n.len == t.len)
for i in 0..<t.n.len:
assert(t.n[i].kind == nkSym)
c &= t.n[i].sym.name.s
c &= ":"
c.hashType(t.sons[i])
c.hashType(t[i])
c &= ","
else:
for i in 0 ..< sonsLen(t): c.hashType t.sons[i]
for i in 0..<t.len: c.hashType t[i]
of tyRange:
c.hashTree(t.n)
c.hashType(t.sons[0])
c.hashType(t[0])
of tyProc:
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
for i in 0..<t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t[i])
md5Update(c, cast[cstring](addr(t.callConv)), 1)
if tfNoSideEffect in t.flags: c &= ".noSideEffect"
if tfThread in t.flags: c &= ".thread"
else:
for i in 0..<t.len: c.hashType(t.sons[i])
for i in 0..<t.len: c.hashType(t[i])
if tfNotNil in t.flags: c &= "not nil"
proc canonConst(n: PNode): TUid =
@@ -238,35 +238,35 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
encodeVInt(n.sym.id, result)
pushSym(w, n.sym)
else:
for i in 0 ..< sonsLen(n):
encodeNode(w, n.info, n.sons[i], result)
add(result, ')')
for i in 0..<n.len:
encodeNode(w, n.info, n[i], result)
result.add(')')
proc encodeLoc(w: PRodWriter, loc: TLoc, result: var string) =
var oldLen = result.len
result.add('<')
if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
if loc.s != low(loc.s):
add(result, '*')
result.add('*')
encodeVInt(ord(loc.s), result)
if loc.flags != {}:
add(result, '$')
result.add('$')
encodeVInt(cast[int32](loc.flags), result)
if loc.t != nil:
add(result, '^')
result.add('^')
encodeVInt(cast[int32](loc.t.id), result)
pushType(w, loc.t)
if loc.r != nil:
add(result, '!')
result.add('!')
encodeStr($loc.r, result)
if loc.a != 0:
add(result, '?')
result.add('?')
encodeVInt(loc.a, result)
if oldLen + 1 == result.len:
# no data was necessary, so remove the '<' again:
setLen(result, oldLen)
else:
add(result, '>')
result.add('>')
proc encodeType(w: PRodWriter, t: PType, result: var string) =
if t == nil:
@@ -277,47 +277,47 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
if t.kind == tyForward: internalError("encodeType: tyForward")
# for the new rodfile viewer we use a preceding [ so that the data section
# can easily be disambiguated:
add(result, '[')
result.add('[')
encodeVInt(ord(t.kind), result)
add(result, '+')
result.add('+')
encodeVInt(t.id, result)
if t.n != nil:
encodeNode(w, unknownLineInfo(), t.n, result)
encodeNode(w, unknownLineInfo, t.n, result)
if t.flags != {}:
add(result, '$')
result.add('$')
encodeVInt(cast[int32](t.flags), result)
if t.callConv != low(t.callConv):
add(result, '?')
result.add('?')
encodeVInt(ord(t.callConv), result)
if t.owner != nil:
add(result, '*')
result.add('*')
encodeVInt(t.owner.id, result)
pushSym(w, t.owner)
if t.sym != nil:
add(result, '&')
result.add('&')
encodeVInt(t.sym.id, result)
pushSym(w, t.sym)
if t.size != - 1:
add(result, '/')
result.add('/')
encodeVBiggestInt(t.size, result)
if t.align != - 1:
add(result, '=')
result.add('=')
encodeVInt(t.align, result)
encodeLoc(w, t.loc, result)
for i in 0 ..< sonsLen(t):
if t.sons[i] == nil:
add(result, "^()")
for i in 0..<t.len:
if t[i] == nil:
result.add("^()")
else:
add(result, '^')
encodeVInt(t.sons[i].id, result)
pushType(w, t.sons[i])
result.add('^')
encodeVInt(t[i].id, result)
pushType(w, t[i])
proc encodeLib(w: PRodWriter, lib: PLib, info: TLineInfo, result: var string) =
add(result, '|')
result.add('|')
encodeVInt(ord(lib.kind), result)
add(result, '|')
result.add('|')
encodeStr($lib.name, result)
add(result, '|')
result.add('|')
encodeNode(w, info, lib.path, result)
proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
@@ -363,8 +363,8 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
encodeLoc(w, s.loc, result)
if s.annex != nil: encodeLib(w, s.annex, s.info, result)
if s.constraint != nil:
add(result, '#')
encodeNode(w, unknownLineInfo(), s.constraint, result)
result.add('#')
encodeNode(w, unknownLineInfo, s.constraint, result)
# lazy loading will soon reload the ast lazily, so the ast needs to be
# the last entry of a symbol:
if s.ast != nil:

View File

@@ -9,43 +9,67 @@
#
# included from cgen.nim
proc canRaiseDisp(p: BProc; n: PNode): bool =
# we assume things like sysFatal cannot raise themselves
if n.kind == nkSym and {sfNeverRaises, sfImportc, sfCompilerProc} * n.sym.flags != {}:
result = false
elif optPanics in p.config.globalOptions or
(n.kind == nkSym and sfSystemModule in getModule(n.sym).flags):
# we know we can be strict:
result = canRaise(n)
else:
# we have to be *very* conservative:
result = canRaiseConservative(n)
proc leftAppearsOnRightSide(le, ri: PNode): bool =
if le != nil:
for i in 1 ..< ri.len:
for i in 1..<ri.len:
let r = ri[i]
if isPartOf(le, r) != arNo: return true
proc hasNoInit(call: PNode): bool {.inline.} =
result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags
proc isHarmlessStore(p: BProc; canRaise: bool; d: TLoc): bool =
if d.k in {locTemp, locNone} or not canRaise:
result = true
elif d.k == locLocalVar and p.withinTryWithExcept == 0:
# we cannot observe a store to a local variable if the current proc
# has no error handler:
result = true
else:
result = false
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
callee, params: Rope) =
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
genLineDir(p, ri)
var pl = callee & ~"(" & params
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
var typ = skipTypes(ri[0].typ, abstractInst)
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if params != nil: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
# Great, we can use 'd':
if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
elif d.k notin {locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var:
discard "resetLoc(p, d)"
add(pl, addrLoc(p.config, d))
add(pl, ~");$n")
pl.add(addrLoc(p.config, d))
pl.add(~");$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
add(pl, ~");$n")
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
pl.add(~");$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
add(pl, ~")")
pl.add(~")")
if p.module.compileToCpp:
if lfSingleUse in d.flags:
# do not generate spurious temporaries for C++! For C we're better off
@@ -56,32 +80,55 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
excl d.flags, lfSingleUse
else:
if d.k == locNone and p.splitDecls == 0:
getTempCpp(p, typ.sons[0], d, pl)
getTempCpp(p, typ[0], d, pl)
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if d.k == locNone: getTemp(p, typ[0], d)
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if canRaise: raiseExit(p)
elif isHarmlessStore(p, canRaise, d):
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
var tmp: TLoc
getTemp(p, typ[0], tmp, needsInit=true)
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, tmp, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {})
else:
add(pl, ~");$n")
pl.add(~");$n")
line(p, cpsStmts, pl)
if canRaise: raiseExit(p)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc openArrayLoc(p: BProc, n: PNode): Rope =
var a: TLoc
let q = skipConv(n)
var q = skipConv(n)
var skipped = false
while q.kind == nkStmtListExpr and q.len > 0:
skipped = true
q = q.lastSon
if getMagic(q) == mSlice:
# magic: pass slice to openArray:
if skipped:
q = skipConv(n)
while q.kind == nkStmtListExpr and q.len > 0:
for i in 0..<q.len-1:
genStmts(p, q[i])
q = q.lastSon
var b, c: TLoc
initLocExpr(p, q[1], a)
initLocExpr(p, q[2], b)
@@ -90,21 +137,23 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
if optBoundsCheck in p.options:
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
let dest = getTypeDesc(p.module, n.typ[0])
case ty.kind
of tyArray:
let first = firstOrd(p.config, ty)
let first = toInt64(firstOrd(p.config, ty))
if first == 0:
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
result = "($4*)(($1)+($2)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
else:
result = "($1)+(($2)-($4)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first)]
of tyOpenArray, tyVarargs, tyUncheckedArray:
result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
result = "($5*)($1)+(($2)-($4)), ($3)-($2)+1" %
[rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first), dest]
of tyOpenArray, tyVarargs, tyUncheckedArray, tyCString:
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
of tyString, tySequence:
if skipTypes(n.typ, abstractInst).kind == tyVar and
not compileToCpp(p.module):
result = "(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
result = "($5*)(*$1)$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
result = "$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p)]
result = "($5*)$1$4+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dataField(p), dest]
else:
internalError(p.config, "openArrayLoc: " & typeToString(a.t))
else:
@@ -136,7 +185,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
var a: TLoc
initLocExpr(p, n.sons[0], a)
initLocExpr(p, n[0], a)
result = ropecg(p.module, "#nimToCStringConv($1)", [a.rdLoc])
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
@@ -144,17 +193,17 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
if n.kind == nkStringToCString:
result = genArgStringToCString(p, n)
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
var n = if n.kind != nkHiddenAddr: n else: n.sons[0]
var n = if n.kind != nkHiddenAddr: n else: n[0]
result = openArrayLoc(p, n)
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
initLocExpr(p, n, a)
result = addrLoc(p.config, a)
elif p.module.compileToCpp and param.typ.kind == tyVar and
n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n.sons[0], a)
initLocExprSingleUse(p, n[0], a)
# 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.sons[0]
let callee = call[0]
if callee.kind == nkSym and
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {}:
@@ -174,36 +223,35 @@ proc genArgNoParam(p: BProc, n: PNode): Rope =
result = rdLoc(a)
template genParamLoop(params) {.dirty.} =
if i < sonsLen(typ):
assert(typ.n.sons[i].kind == nkSym)
let paramType = typ.n.sons[i]
if i < typ.len:
assert(typ.n[i].kind == nkSym)
let paramType = typ.n[i]
if not paramType.typ.isCompileTimeOnly:
if params != nil: add(params, ~", ")
add(params, genArg(p, ri.sons[i], paramType.sym, ri))
if params != nil: params.add(~", ")
params.add(genArg(p, ri[i], paramType.sym, ri))
else:
if params != nil: add(params, ~", ")
add(params, genArgNoParam(p, ri.sons[i]))
if params != nil: params.add(~", ")
params.add(genArgNoParam(p, ri[i]))
proc addActualPrefixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and
proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
if sym.flags * {sfImportc, sfNonReloadable} == {} and sym.loc.k == locProc and
(sym.typ.callConv == ccInline or sym.owner.id == module.id):
res = res & "_actual".rope
proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
# this is a hotspot in the compiler
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var params: Rope
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInstOwned)
var typ = skipTypes(ri[0].typ, abstractInstOwned)
assert(typ.kind == tyProc)
assert(sonsLen(typ) == sonsLen(typ.n))
var length = sonsLen(ri)
for i in 1 ..< length:
assert(typ.len == typ.n.len)
for i in 1..<ri.len:
genParamLoop(params)
var callee = rdLoc(op)
if p.hcrOn and ri.sons[0].kind == nkSym:
callee.addActualPrefixForHCR(p.module.module, ri.sons[0].sym)
if p.hcrOn and ri[0].kind == nkSym:
callee.addActualSuffixForHCR(p.module.module, ri[0].sym)
fixupCall(p, le, ri, d, callee, params)
proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
@@ -217,14 +265,13 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
const PatProc = "$1.ClE_0? $1.ClP_0($3$1.ClE_0):(($4)($1.ClP_0))($2)"
const PatIter = "$1.ClP_0($3$1.ClE_0)" # we know the env exists
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var pl: Rope
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
for i in 1 ..< length:
assert(sonsLen(typ) == sonsLen(typ.n))
for i in 1..<ri.len:
assert(typ.len == typ.n.len)
genParamLoop(pl)
template genCallPattern {.dirty.} =
@@ -234,27 +281,29 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
lineF(p, cpsStmts, PatProc & ";$n", [rdLoc(op), pl, pl.addComma, rawProc])
let rawProc = getRawProcType(p, typ)
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
if sonsLen(ri) > 1: add(pl, ~", ")
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if ri.len > 1: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
# Great, we can use 'd':
if d.k == locNone:
getTemp(p, typ.sons[0], d, needsInit=true)
getTemp(p, typ[0], d, needsInit=true)
elif d.k notin {locTemp} and not hasNoInit(ri):
# reset before pass as 'result' var:
discard "resetLoc(p, d)"
add(pl, addrLoc(p.config, d))
pl.add(addrLoc(p.config, d))
genCallPattern()
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
genCallPattern()
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
elif isHarmlessStore(p, canRaise, d):
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
@@ -262,29 +311,43 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
else:
list.r = PatProc % [rdLoc(op), pl, pl.addComma, rawProc]
genAssignment(p, d, list, {}) # no need for deep copying
if canRaise: raiseExit(p)
else:
var tmp: TLoc
getTemp(p, typ[0], tmp)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
if tfIterator in typ.flags:
list.r = PatIter % [rdLoc(op), pl, pl.addComma, rawProc]
else:
list.r = PatProc % [rdLoc(op), pl, pl.addComma, rawProc]
genAssignment(p, tmp, list, {})
if canRaise: raiseExit(p)
genAssignment(p, d, tmp, {})
else:
genCallPattern()
if canRaise: raiseExit(p)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
if i < sonsLen(typ):
if i < typ.len:
# 'var T' is 'T&' in C++. This means we ignore the request of
# any nkHiddenAddr when it's a 'var T'.
let paramType = typ.n.sons[i]
let paramType = typ.n[i]
assert(paramType.kind == nkSym)
if paramType.typ.isCompileTimeOnly:
result = nil
elif typ.sons[i].kind == tyVar and ri.sons[i].kind == nkHiddenAddr:
result = genArgNoParam(p, ri.sons[i][0])
elif typ[i].kind == tyVar and ri[i].kind == nkHiddenAddr:
result = genArgNoParam(p, ri[i][0])
else:
result = genArgNoParam(p, ri.sons[i]) #, typ.n.sons[i].sym)
result = genArgNoParam(p, ri[i]) #, typ.n[i].sym)
else:
if tfVarargs notin typ.flags:
localError(p.config, ri.info, "wrong argument count")
result = nil
else:
result = genArgNoParam(p, ri.sons[i])
result = genArgNoParam(p, ri[i])
discard """
Dot call syntax in C++
@@ -328,16 +391,16 @@ proc skipAddrDeref(node: PNode): PNode =
var isAddr = false
case n.kind
of nkAddr, nkHiddenAddr:
n = n.sons[0]
n = n[0]
isAddr = true
of nkDerefExpr, nkHiddenDeref:
n = n.sons[0]
n = n[0]
else: return n
if n.kind == nkObjDownConv: n = n.sons[0]
if n.kind == nkObjDownConv: n = n[0]
if isAddr and n.kind in {nkDerefExpr, nkHiddenDeref}:
result = n.sons[0]
result = n[0]
elif n.kind in {nkAddr, nkHiddenAddr}:
result = n.sons[0]
result = n[0]
else:
result = node
@@ -345,13 +408,13 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
# for better or worse c2nim translates the 'this' argument to a 'var T'.
# However manual wrappers may also use 'ptr T'. In any case we support both
# for convenience.
internalAssert p.config, i < sonsLen(typ)
assert(typ.n.sons[i].kind == nkSym)
internalAssert p.config, i < typ.len
assert(typ.n[i].kind == nkSym)
# if the parameter is lying (tyVar) and thus we required an additional deref,
# skip the deref:
var ri = ri[i]
while ri.kind == nkObjDownConv: ri = ri[0]
let t = typ.sons[i].skipTypes({tyGenericInst, tyAlias, tySink})
let t = typ[i].skipTypes({tyGenericInst, tyAlias, tySink})
if t.kind == tyVar:
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
if x.typ.kind == tyPtr:
@@ -373,7 +436,7 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType): Rope =
else:
ri = skipAddrDeref(ri)
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
result = genArgNoParam(p, ri) #, typ.n.sons[i].sym)
result = genArgNoParam(p, ri) #, typ.n[i].sym)
result.add(".")
proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
@@ -382,22 +445,25 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
while i < pat.len:
case pat[i]
of '@':
if j < ri.len:
result.add genOtherArg(p, ri, j, typ)
for k in j+1 ..< ri.len:
result.add(~", ")
result.add genOtherArg(p, ri, k, typ)
var first = true
for k in j..<ri.len:
let arg = genOtherArg(p, ri, k, typ)
if arg.len > 0:
if not first:
result.add(~", ")
first = false
result.add arg
inc i
of '#':
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
let ri = ri[j]
if ri.kind in nkCallKinds:
let typ = skipTypes(ri.sons[0].typ, abstractInst)
if pat[i+1] == '+': result.add genArgNoParam(p, ri.sons[0])
let typ = skipTypes(ri[0].typ, abstractInst)
if pat[i+1] == '+': result.add genArgNoParam(p, ri[0])
result.add(~"(")
if 1 < ri.len:
result.add genOtherArg(p, ri, 1, typ)
for k in j+1 ..< ri.len:
for k in j+1..<ri.len:
result.add(~", ")
result.add genOtherArg(p, ri, k, typ)
result.add(~")")
@@ -408,7 +474,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
result.add genThisArg(p, ri, j, typ)
inc i
elif i+1 < pat.len and pat[i+1] == '[':
var arg = ri.sons[j].skipAddrDeref
var arg = ri[j].skipAddrDeref
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
result.add genArgNoParam(p, arg)
#result.add debugTree(arg, 0, 10)
@@ -428,24 +494,23 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType): Rope =
if pat[i] notin {'@', '#', '\''}: inc(i)
else: break
if i - 1 >= start:
add(result, substr(pat, start, i - 1))
result.add(substr(pat, start, i - 1))
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
assert(typ.len == typ.n.len)
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
let pat = ri[0].sym.loc.r.data
internalAssert p.config, pat.len > 0
if pat.contains({'#', '(', '@', '\''}):
var pl = genPatternCall(p, ri, pat, typ)
# simpler version of 'fixupCall' that works with the pl+params combination:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
if typ.sons[0] != nil:
var typ = skipTypes(ri[0].typ, abstractInst)
if typ[0] != nil:
if p.module.compileToCpp and lfSingleUse in d.flags:
# do not generate spurious temporaries for C++! For C we're better off
# with them to prevent undefined behaviour and because the codegen
@@ -454,115 +519,114 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
d.r = pl
excl d.flags, lfSingleUse
else:
if d.k == locNone: getTemp(p, typ.sons[0], d)
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, d.lode, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
add(pl, ~";$n")
pl.add(~";$n")
line(p, cpsStmts, pl)
else:
var pl: Rope = nil
#var param = typ.n.sons[1].sym
#var param = typ.n[1].sym
if 1 < ri.len:
add(pl, genThisArg(p, ri, 1, typ))
add(pl, op.r)
pl.add(genThisArg(p, ri, 1, typ))
pl.add(op.r)
var params: Rope
for i in 2 ..< length:
for i in 2..<ri.len:
if params != nil: params.add(~", ")
assert(sonsLen(typ) == sonsLen(typ.n))
add(params, genOtherArg(p, ri, i, typ))
assert(typ.len == typ.n.len)
params.add(genOtherArg(p, ri, i, typ))
fixupCall(p, le, ri, d, pl, params)
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
# generates a crappy ObjC call
var op: TLoc
initLocExpr(p, ri.sons[0], op)
initLocExpr(p, ri[0], op)
var pl = ~"["
# getUniqueType() is too expensive here:
var typ = skipTypes(ri.sons[0].typ, abstractInst)
var typ = skipTypes(ri[0].typ, abstractInst)
assert(typ.kind == tyProc)
var length = sonsLen(ri)
assert(sonsLen(typ) == sonsLen(typ.n))
assert(typ.len == typ.n.len)
# don't call '$' here for efficiency:
let pat = ri.sons[0].sym.loc.r.data
let pat = ri[0].sym.loc.r.data
internalAssert p.config, pat.len > 0
var start = 3
if ' ' in pat:
start = 1
add(pl, op.r)
if length > 1:
add(pl, ~": ")
add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
pl.add(op.r)
if ri.len > 1:
pl.add(~": ")
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
start = 2
else:
if length > 1:
add(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
add(pl, ~" ")
add(pl, op.r)
if length > 2:
add(pl, ~": ")
add(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
for i in start ..< length:
assert(sonsLen(typ) == sonsLen(typ.n))
if i >= sonsLen(typ):
if ri.len > 1:
pl.add(genArg(p, ri[1], typ.n[1].sym, ri))
pl.add(~" ")
pl.add(op.r)
if ri.len > 2:
pl.add(~": ")
pl.add(genArg(p, ri[2], typ.n[2].sym, ri))
for i in start..<ri.len:
assert(typ.len == typ.n.len)
if i >= typ.len:
internalError(p.config, ri.info, "varargs for objective C method?")
assert(typ.n.sons[i].kind == nkSym)
var param = typ.n.sons[i].sym
add(pl, ~" ")
add(pl, param.name.s)
add(pl, ~": ")
add(pl, genArg(p, ri.sons[i], param, ri))
if typ.sons[0] != nil:
if isInvalidReturnType(p.config, typ.sons[0]):
if sonsLen(ri) > 1: add(pl, ~" ")
assert(typ.n[i].kind == nkSym)
var param = typ.n[i].sym
pl.add(~" ")
pl.add(param.name.s)
pl.add(~": ")
pl.add(genArg(p, ri[i], param, ri))
if typ[0] != nil:
if isInvalidReturnType(p.config, typ[0]):
if ri.len > 1: pl.add(~" ")
# beware of 'result = p(result)'. We always allocate a temporary:
if d.k in {locTemp, locNone}:
# We already got a temp. Great, special case it:
if d.k == locNone: getTemp(p, typ.sons[0], d, needsInit=true)
add(pl, ~"Result: ")
add(pl, addrLoc(p.config, d))
add(pl, ~"];$n")
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
pl.add(~"Result: ")
pl.add(addrLoc(p.config, d))
pl.add(~"];$n")
line(p, cpsStmts, pl)
else:
var tmp: TLoc
getTemp(p, typ.sons[0], tmp, needsInit=true)
add(pl, addrLoc(p.config, tmp))
add(pl, ~"];$n")
getTemp(p, typ[0], tmp, needsInit=true)
pl.add(addrLoc(p.config, tmp))
pl.add(~"];$n")
line(p, cpsStmts, pl)
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
add(pl, ~"]")
if d.k == locNone: getTemp(p, typ.sons[0], d)
pl.add(~"]")
if d.k == locNone: getTemp(p, typ[0], d)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc
initLoc(list, locCall, ri, OnUnknown)
list.r = pl
genAssignment(p, d, list, {}) # no need for deep copying
else:
add(pl, ~"];$n")
pl.add(~"];$n")
line(p, cpsStmts, pl)
proc genCall(p: BProc, e: PNode, d: var TLoc) =
if e.sons[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
if e[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, nil, e, d)
elif e.sons[0].kind == nkSym and sfInfixCall in e.sons[0].sym.flags:
elif e[0].kind == nkSym and sfInfixCall in e[0].sym.flags:
genInfixCall(p, nil, e, d)
elif e.sons[0].kind == nkSym and sfNamedParamCall in e.sons[0].sym.flags:
elif e[0].kind == nkSym and sfNamedParamCall in e[0].sym.flags:
genNamedParamCall(p, e, d)
else:
genPrefixCall(p, nil, e, d)
postStmtActions(p)
proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
if ri.sons[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
if ri[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
genClosureCall(p, le, ri, d)
elif ri.sons[0].kind == nkSym and sfInfixCall in ri.sons[0].sym.flags:
elif ri[0].kind == nkSym and sfInfixCall in ri[0].sym.flags:
genInfixCall(p, le, ri, d)
elif ri.sons[0].kind == nkSym and sfNamedParamCall in ri.sons[0].sym.flags:
elif ri[0].kind == nkSym and sfNamedParamCall in ri[0].sym.flags:
genNamedParamCall(p, ri, d)
else:
genPrefixCall(p, le, ri, d)

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,8 @@
# distribution, for details about the copyright.
#
# included from cgen.nim
## This include file contains the logic to produce constant string
## and seq literals. The code here is responsible that
## ``const x = ["a", "b"]`` works without hidden runtime creation code.
@@ -19,7 +21,7 @@ template detectVersion(field, corename) =
if core == nil or core.kind != skConst:
m.g.field = 1
else:
m.g.field = int ast.getInt(core.ast)
m.g.field = toInt(ast.getInt(core.ast))
result = m.g.field
proc detectStrVersion(m: BModule): int =
@@ -33,8 +35,8 @@ proc detectSeqVersion(m: BModule): int =
proc genStringLiteralDataOnlyV1(m: BModule, s: string): Rope =
discard cgsym(m, "TGenericSeq")
result = getTempName(m)
addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), rope(len(s))])
m.s[cfsData].addf("STRING_LITERAL($1, $2, $3);$n",
[result, makeCString(s), rope(s.len)])
proc genStringLiteralV1(m: BModule; n: PNode): Rope =
if s.isNil:
@@ -51,29 +53,31 @@ proc genStringLiteralV1(m: BModule; n: PNode): Rope =
# ------ Version 2: destructor based strings and seqs -----------------------
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope) =
addf(m.s[cfsData], "static const struct {$n" &
" NI cap; void* allocator; NIM_CHAR data[$2+1];$n" &
"} $1 = { $2, NIM_NIL, $3 };$n",
[result, rope(len(s)), makeCString(s)])
proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bool) =
m.s[cfsData].addf("static $4 struct {$n" &
" NI cap; NIM_CHAR data[$2+1];$n" &
"} $1 = { $2 | NIM_STRLIT_FLAG, $3 };$n",
[result, rope(s.len), makeCString(s),
rope(if isConst: "const" else: "")])
proc genStringLiteralV2(m: BModule; n: PNode): Rope =
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
if id == m.labels:
let pureLit = getTempName(m)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
result = getTempName(m)
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(len(n.strVal)), pureLit])
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
else:
result = getTempName(m)
addf(m.s[cfsData], "static const NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(len(n.strVal)), m.tmpBase & rope(id)])
m.s[cfsData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
[result, rope(n.strVal.len), m.tmpBase & rope(id),
rope(if isConst: "const" else: "")])
proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool): Rope =
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
var pureLit: Rope
if id == m.labels:
@@ -81,19 +85,20 @@ proc genStringLiteralV2Const(m: BModule; n: PNode): Rope =
discard cgsym(m, "NimStrPayload")
discard cgsym(m, "NimStringV2")
# string literal not found in the cache:
genStringLiteralDataOnlyV2(m, n.strVal, pureLit)
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
else:
pureLit = m.tmpBase & rope(id)
result = "{$1, (NimStrPayload*)&$2}" % [rope(len(n.strVal)), pureLit]
result = "{$1, (NimStrPayload*)&$2}" % [rope(n.strVal.len), pureLit]
# ------ Version selector ---------------------------------------------------
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope =
proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
isConst: bool): Rope =
case detectStrVersion(m)
of 0, 1: result = genStringLiteralDataOnlyV1(m, s)
of 2:
result = getTempName(m)
genStringLiteralDataOnlyV2(m, s, result)
genStringLiteralDataOnlyV2(m, s, result, isConst)
else:
localError(m.config, info, "cannot determine how to produce code for string literal")
@@ -103,6 +108,6 @@ proc genNilStringLiteral(m: BModule; info: TLineInfo): Rope =
proc genStringLiteral(m: BModule; n: PNode): Rope =
case detectStrVersion(m)
of 0, 1: result = genStringLiteralV1(m, n)
of 2: result = genStringLiteralV2(m, n)
of 2: result = genStringLiteralV2(m, n, isConst = true)
else:
localError(m.config, n.info, "cannot determine how to produce code for string literal")

View File

@@ -28,8 +28,8 @@ const
cfsFieldInfo: "NIM_merge_FIELD_INFO",
cfsTypeInfo: "NIM_merge_TYPE_INFO",
cfsProcHeaders: "NIM_merge_PROC_HEADERS",
cfsVars: "NIM_merge_VARS",
cfsData: "NIM_merge_DATA",
cfsVars: "NIM_merge_VARS",
cfsProcs: "NIM_merge_PROCS",
cfsInitProc: "NIM_merge_INIT_PROC",
cfsDatInitProc: "NIM_merge_DATINIT_PROC",
@@ -50,9 +50,9 @@ const
proc genSectionStart*(fs: TCFileSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
result = nil
add(result, "\n/*\t")
add(result, CFileSectionNames[fs])
add(result, ":*/\n")
result.add("\n/*\t")
result.add(CFileSectionNames[fs])
result.add(":*/\n")
proc genSectionEnd*(fs: TCFileSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
@@ -61,9 +61,9 @@ proc genSectionEnd*(fs: TCFileSection; conf: ConfigRef): Rope =
proc genSectionStart*(ps: TCProcSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):
result = rope("")
add(result, "\n/*\t")
add(result, CProcSectionNames[ps])
add(result, ":*/\n")
result.add("\n/*\t")
result.add(CProcSectionNames[ps])
result.add(":*/\n")
proc genSectionEnd*(ps: TCProcSection; conf: ConfigRef): Rope =
if compilationCachePresent(conf):

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,11 @@ proc emulatedThreadVars(conf: ConfigRef): bool =
result = {optThreads, optTlsEmulation} <= conf.globalOptions
proc accessThreadLocalVar(p: BProc, s: PSym) =
if emulatedThreadVars(p.config) and not p.threadVarAccessed:
p.threadVarAccessed = true
if emulatedThreadVars(p.config) and threadVarAccessed notin p.flags:
p.flags.incl threadVarAccessed
incl p.module.flags, usesThreadVars
addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV_;$n", [])
add(p.procSec(cpsInit),
p.procSec(cpsLocals).addf("\tNimThreadVars* NimTV_;$n", [])
p.procSec(cpsInit).add(
ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n", []))
proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
@@ -30,23 +30,25 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) =
# allocator for it :-(
if not containsOrIncl(m.g.nimtvDeclared, s.id):
m.g.nimtvDeps.add(s.loc.t)
addf(m.g.nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
m.g.nimtv.addf("$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r])
else:
if isExtern: add(m.s[cfsVars], "extern ")
if optThreads in m.config.globalOptions: add(m.s[cfsVars], "NIM_THREADVAR ")
add(m.s[cfsVars], getTypeDesc(m, s.loc.t))
addf(m.s[cfsVars], " $1;$n", [s.loc.r])
if isExtern: m.s[cfsVars].add("extern ")
elif lfExportLib in s.loc.flags: m.s[cfsVars].add("N_LIB_EXPORT_VAR ")
else: m.s[cfsVars].add("N_LIB_PRIVATE ")
if optThreads in m.config.globalOptions: m.s[cfsVars].add("NIM_THREADVAR ")
m.s[cfsVars].add(getTypeDesc(m, s.loc.t))
m.s[cfsVars].addf(" $1;$n", [s.loc.r])
proc generateThreadLocalStorage(m: BModule) =
if m.g.nimtv != nil and (usesThreadVars in m.flags or sfMainModule in m.module.flags):
for t in items(m.g.nimtvDeps): discard getTypeDesc(m, t)
addf(m.s[cfsSeqTypes], "typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
m.s[cfsSeqTypes].addf("typedef struct {$1} NimThreadVars;$n", [m.g.nimtv])
proc generateThreadVarsSize(m: BModule) =
if m.g.nimtv != nil:
let externc = if m.config.cmd == cmdCompileToCpp or
sfCompileToCpp in m.module.flags: "extern \"C\" "
else: ""
addf(m.s[cfsProcs],
m.s[cfsProcs].addf(
"$#NI NimThreadVarsSize(){return (NI)sizeof(NimThreadVars);}$n",
[externc.rope])

View File

@@ -17,7 +17,7 @@ type
visitorFrmt: string
const
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
visitorFrmt = "#nimGCvisit((void*)$1, $2);$n"
proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType)
proc genCaseRange(p: BProc, branch: PNode)
@@ -28,18 +28,18 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
if n == nil: return
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
genTraverseProc(c, accessor, n.sons[i], typ)
for i in 0..<n.len:
genTraverseProc(c, accessor, n[i], typ)
of nkRecCase:
if (n.sons[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
if (n[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
var p = c.p
let disc = n.sons[0].sym
let disc = n[0].sym
if disc.loc.r == nil: fillObjectFields(c.p.module, typ)
if disc.loc.t == nil:
internalError(c.p.config, n.info, "genTraverseProc()")
lineF(p, cpsStmts, "switch ($1.$2) {$n", [accessor, disc.loc.r])
for i in 1 ..< sonsLen(n):
let branch = n.sons[i]
for i in 1..<n.len:
let branch = n[i]
assert branch.kind in {nkOfBranch, nkElse}
if branch.kind == nkOfBranch:
genCaseRange(c.p, branch)
@@ -73,38 +73,39 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
tySink, tyOwned:
genTraverseProc(c, accessor, lastSon(typ))
of tyArray:
let arraySize = lengthOrd(c.p.config, typ.sons[0])
let arraySize = lengthOrd(c.p.config, typ[0])
var i: TLoc
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
let oldCode = p.s(cpsStmts)
linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, arraySize])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.r]), typ.sons[1])
genTraverseProc(c, ropecg(c.p.module, "$1[$2]", [accessor, i.r]), typ[1])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
else:
lineF(p, cpsStmts, "}$n", [])
of tyObject:
for i in 0 ..< sonsLen(typ):
var x = typ.sons[i]
for i in 0..<typ.len:
var x = typ[i]
if x != nil: x = x.skipTypes(skipPtrs)
genTraverseProc(c, accessor.parentObj(c.p.module), x)
if typ.n != nil: genTraverseProc(c, accessor, typ.n, typ)
of tyTuple:
let typ = getUniqueType(typ)
for i in 0 ..< sonsLen(typ):
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ.sons[i])
for i in 0..<typ.len:
genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", [accessor, i]), typ[i])
of tyRef:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
of tySequence:
if tfHasAsgn notin typ.flags:
if optSeqDestructors notin c.p.module.config.globalOptions:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
elif containsGarbageCollectedRef(typ.lastSon):
# destructor based seqs are themselves not traced but their data is, if
# they contain a GC'ed type:
genTraverseProcSeq(c, accessor, typ)
lineCg(p, cpsStmts, "#nimGCvisitSeq((void*)$1, $2);$n", [accessor, c.visitorFrmt])
#genTraverseProcSeq(c, accessor, typ)
of tyString:
if tfHasAsgn notin typ.flags:
lineCg(p, cpsStmts, visitorFrmt, [accessor, c.visitorFrmt])
@@ -118,7 +119,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
var p = c.p
assert typ.kind == tySequence
var i: TLoc
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
let oldCode = p.s(cpsStmts)
var a: TLoc
a.r = accessor
@@ -126,7 +127,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
lineF(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
[i.r, lenExpr(c.p, a)])
let oldLen = p.s(cpsStmts).len
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ.sons[0])
genTraverseProc(c, "$1$3[$2]" % [accessor, i.r, dataField(c.p)], typ[0])
if p.s(cpsStmts).len == oldLen:
# do not emit dummy long loops for faster debug builds:
p.s(cpsStmts) = oldCode
@@ -154,11 +155,11 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
if typ.kind == tySequence:
genTraverseProcSeq(c, "a".rope, typ)
else:
if skipTypes(typ.sons[0], typedescInst+{tyOwned}).kind == tyArray:
if skipTypes(typ[0], typedescInst+{tyOwned}).kind == tyArray:
# C's arrays are broken beyond repair:
genTraverseProc(c, "a".rope, typ.sons[0])
genTraverseProc(c, "a".rope, typ[0])
else:
genTraverseProc(c, "(*a)".rope, typ.sons[0])
genTraverseProc(c, "(*a)".rope, typ[0])
let generatedProc = "$1 {$n$2$3$4}\n" %
[header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)]
@@ -167,8 +168,8 @@ proc genTraverseProc(m: BModule, origTyp: PType; sig: SigHash): Rope =
m.s[cfsProcs].add(generatedProc)
if hcrOn:
addf(m.s[cfsProcHeaders], "N_NIMCALL_PTR(void, $1)(void*, NI);\n", [result])
addf(m.s[cfsDynLibInit], "\t$1 = (N_NIMCALL_PTR(void, )(void*, NI)) hcrRegisterProc($3, \"$1\", (void*)$2);\n",
m.s[cfsProcHeaders].addf("N_NIMCALL_PTR(void, $1)(void*, NI);\n", [result])
m.s[cfsDynLibInit].addf("\t$1 = (N_NIMCALL_PTR(void, )(void*, NI)) hcrRegisterProc($3, \"$1\", (void*)$2);\n",
[result, markerName, getModuleDllPath(m)])
proc genTraverseProcForGlobal(m: BModule, s: PSym; info: TLineInfo): Rope =

File diff suppressed because it is too large Load Diff

View File

@@ -16,11 +16,11 @@ import
proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
case n.kind
of nkStmtList:
for i in 0 ..< n.len:
for i in 0..<n.len:
result = getPragmaStmt(n[i], w)
if result != nil: break
of nkPragma:
for i in 0 ..< n.len:
for i in 0..<n.len:
if whichPragma(n[i]) == w: return n[i]
else: discard
@@ -33,7 +33,7 @@ proc hashString*(conf: ConfigRef; s: string): BiggestInt =
# we have to use the same bitwidth
# as the target CPU
var b = 0'u64
for i in 0 ..< len(s):
for i in 0..<s.len:
b = b + uint(s[i])
b = b + (b shl 10)
b = b xor (b shr 6)
@@ -43,7 +43,7 @@ proc hashString*(conf: ConfigRef; s: string): BiggestInt =
result = cast[Hash](b)
else:
var a = 0'u32
for i in 0 ..< len(s):
for i in 0..<s.len:
a = a + uint32(s[i])
a = a + (a shl 10)
a = a xor (a shr 6)
@@ -70,18 +70,18 @@ proc mangle*(name: string): string =
template special(x) =
result.add x
requiresUnderscore = true
for i in start..(name.len-1):
for i in start..<name.len:
let c = name[i]
case c
of 'a'..'z', '0'..'9', 'A'..'Z':
add(result, c)
result.add(c)
of '_':
# we generate names like 'foo_9' for scope disambiguations and so
# disallow this here:
if i > 0 and i < name.len-1 and name[i+1] in Digits:
discard
else:
add(result, c)
result.add(c)
of '$': special "dollar"
of '%': special "percent"
of '&': special "amp"
@@ -102,7 +102,7 @@ proc mangle*(name: string): string =
of '@': special "at"
of '|': special "bar"
else:
add(result, "X" & toHex(ord(c), 2))
result.add("X" & toHex(ord(c), 2))
requiresUnderscore = true
if requiresUnderscore:
result.add "_"

File diff suppressed because it is too large Load Diff

View File

@@ -27,8 +27,8 @@ type
cfsFieldInfo, # section for field information
cfsTypeInfo, # section for type information
cfsProcHeaders, # section for C procs prototypes
cfsVars, # section for C variable declarations
cfsData, # section for C constant data
cfsVars, # section for C variable declarations
cfsProcs, # section for C procs that are not inline
cfsInitProc, # section for the C init proc
cfsDatInitProc, # section for the C datInit proc
@@ -58,22 +58,26 @@ type
id*: int # the ID of the label; positive means that it
label*: Rope # generated text for the label
# nil if label is not used
sections*: TCProcSections # the code beloging
sections*: TCProcSections # the code belonging
isLoop*: bool # whether block is a loop
nestedTryStmts*: int16 # how many try statements is it nested into
nestedExceptStmts*: int16 # how many except statements is it nested into
frameLen*: int16
TCProcFlag* = enum
beforeRetNeeded,
threadVarAccessed,
hasCurFramePointer,
noSafePoints,
nimErrorFlagAccessed,
nimErrorFlagDeclared
TCProc = object # represents C proc that is currently generated
prc*: PSym # the Nim proc that this C proc belongs to
beforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
threadVarAccessed*: bool # true if the proc already accessed some threadvar
hasCurFramePointer*: bool # true if _nimCurFrame var needed to recover after
# exception is generated
noSafePoints*: bool # the proc doesn't use safe points in exception handling
flags*: set[TCProcFlag]
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
currLineInfo*: TLineInfo # AST codegen will make this superfluous
nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]
nestedTryStmts*: seq[tuple[fin: PNode, inExcept: bool, label: Natural]]
# in how many nested try statements we are
# (the vars must be volatile then)
# bool is true when are in the except part of a try block
@@ -86,14 +90,12 @@ type
options*: TOptions # options that should be used for code
# generation; this is the same as prc.options
# unless prc == nil
maxFrameLen*: int # max length of frame descriptor
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
# requires 'T x = T()' to become 'T x; x = T()'
# (yes, C++ is weird like that)
gcFrameId*: Natural # for the GC stack marking
gcFrameType*: Rope # the struct {} we put the GC markers into
withinTryWithExcept*: int # required for goto based exception handling
sigConflicts*: CountTable[string]
TTypeSeq* = seq[PType]
@@ -117,8 +119,6 @@ type
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
forwardedProcs*: seq[PSym] # proc:s that did not yet have a body
generatedHeader*: BModule
breakPointId*: int
breakpoints*: Rope # later the breakpoints are inserted into the main proc
typeInfoMarker*: TypeCacheWithOwner
config*: ConfigRef
graph*: ModuleGraph
@@ -152,7 +152,7 @@ type
initProc*: BProc # code for init procedure
preInitProc*: BProc # code executed before the init proc
hcrCreateTypeInfosProc*: Rope # type info globals are in here when HCR=on
inHcrInitGuard*: bool # We are currently withing a HCR reloading guard.
inHcrInitGuard*: bool # We are currently within a HCR reloading guard.
typeStack*: TTypeSeq # used for type generation
dataCache*: TNodeTable
typeNodes*, nimTypes*: int # used for type info generation
@@ -174,7 +174,7 @@ proc includeHeader*(this: BModule; header: string) =
proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# section in the current block
result = p.blocks[p.blocks.len-1].sections[s]
result = p.blocks[^1].sections[s]
proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
# top level proc sections

View File

@@ -7,7 +7,7 @@
# distribution, for details about the copyright.
#
## This module implements code generation for multi methods.
## This module implements code generation for methods.
import
intsets, options, ast, msgs, idents, renderer, types, magicsys,
@@ -23,11 +23,11 @@ proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
result = n
elif diff < 0:
result = newNodeIT(nkObjUpConv, n.info, d)
addSon(result, n)
result.add n
if downcast: internalError(conf, n.info, "cgmeth.genConv: no upcast allowed")
elif diff > 0:
result = newNodeIT(nkObjDownConv, n.info, d)
addSon(result, n)
result.add n
if not downcast:
internalError(conf, n.info, "cgmeth.genConv: no downcast allowed")
else:
@@ -44,26 +44,26 @@ proc getDispatcher*(s: PSym): PSym =
proc methodCall*(n: PNode; conf: ConfigRef): PNode =
result = n
# replace ordinary method by dispatcher method:
let disp = getDispatcher(result.sons[0].sym)
let disp = getDispatcher(result[0].sym)
if disp != nil:
result.sons[0].sym = disp
result[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in 1 ..< sonsLen(result):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf)
for i in 1..<result.len:
result[i] = genConv(result[i], disp.typ[i], true, conf)
else:
localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
localError(conf, n.info, "'" & $result[0] & "' lacks a dispatcher")
type
MethodResult = enum No, Invalid, Yes
proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
if a.name.id != b.name.id: return
if sonsLen(a.typ) != sonsLen(b.typ):
if a.typ.len != b.typ.len:
return
for i in 1 ..< sonsLen(a.typ):
var aa = a.typ.sons[i]
var bb = b.typ.sons[i]
for i in 1..<a.typ.len:
var aa = a.typ[i]
var bb = b.typ[i]
while true:
aa = skipTypes(aa, {tyGenericInst, tyAlias})
bb = skipTypes(bb, {tyGenericInst, tyAlias})
@@ -72,7 +72,7 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
bb = bb.lastSon
else:
break
if sameType(a.typ.sons[i], b.typ.sons[i]):
if sameType(a.typ[i], b.typ[i]):
if aa.kind == tyObject and result != Invalid:
result = Yes
elif aa.kind == tyObject and bb.kind == tyObject and (i == 1 or multiMethods):
@@ -90,22 +90,22 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
return No
if result == Yes:
# check for return type:
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]):
if b.typ.sons[0] != nil and b.typ.sons[0].kind == tyUntyped:
if not sameTypeOrNil(a.typ[0], b.typ[0]):
if b.typ[0] != nil and b.typ[0].kind == tyUntyped:
# infer 'auto' from the base to make it consistent:
b.typ.sons[0] = a.typ.sons[0]
b.typ[0] = a.typ[0]
else:
return No
proc attachDispatcher(s: PSym, dispatcher: PNode) =
if dispatcherPos < s.ast.len:
# we've added a dispatcher already, so overwrite it
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
else:
setLen(s.ast.sons, dispatcherPos+1)
if s.ast[resultPos] == nil:
s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym): PSym =
var disp = copySym(s)
@@ -115,16 +115,16 @@ proc createDispatcher(s: PSym): PSym =
# we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
disp.ast = copyTree(s.ast)
disp.ast.sons[bodyPos] = newNodeI(nkEmpty, s.info)
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil
if s.typ.sons[0] != nil:
if disp.ast.sonsLen > resultPos:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
if s.typ[0] != nil:
if disp.ast.len > resultPos:
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym)
else:
# We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will
# be updated in fixupDispatcher().
disp.ast.addSon(newNodeI(nkEmpty, s.info))
disp.ast.add newNodeI(nkEmpty, s.info)
attachDispatcher(s, newSymNode(disp))
# attach to itself to prevent bugs:
attachDispatcher(disp, newSymNode(disp))
@@ -136,9 +136,9 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
# from later definitions, particularly the resultPos slot. Also,
# the lock level of the dispatcher needs to be updated/checked
# against that of the method.
if disp.ast.sonsLen > resultPos and meth.ast.sonsLen > resultPos and
disp.ast.sons[resultPos].kind == nkEmpty:
disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos])
if disp.ast.len > resultPos and meth.ast.len > resultPos and
disp.ast[resultPos].kind == nkEmpty:
disp.ast[resultPos] = copyTree(meth.ast[resultPos])
# The following code works only with lock levels, so we disable
# it when they're not available.
@@ -158,13 +158,12 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
disp.typ.lockLevel = meth.typ.lockLevel
proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
let L = len(g.methods)
var witness: PSym
for i in 0 ..< L:
for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s, multimethods = optMultiMethods in g.config.globalOptions)
of Yes:
add(g.methods[i].methods, s)
g.methods[i].methods.add(s)
attachDispatcher(s, disp.ast[dispatcherPos])
fixupDispatcher(s, disp, g.config)
#echo "fixup ", disp.name.s, " ", disp.id
@@ -178,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
of Invalid:
if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher:
add(g.methods, (methods: @[s], dispatcher: createDispatcher(s)))
g.methods.add((methods: @[s], dispatcher: createDispatcher(s)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
@@ -190,32 +189,32 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
proc relevantCol(methods: seq[PSym], col: int): bool =
# returns true iff the position is relevant
var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
var t = methods[0].typ[col].skipTypes(skipPtrs)
if t.kind == tyObject:
for i in 1 .. high(methods):
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
for i in 1..high(methods):
let t2 = skipTypes(methods[i].typ[col], skipPtrs)
if not sameType(t2, t):
return true
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
for col in 1 ..< sonsLen(a.typ):
for col in 1..<a.typ.len:
if contains(relevantCols, col):
var aa = skipTypes(a.typ.sons[col], skipPtrs)
var bb = skipTypes(b.typ.sons[col], skipPtrs)
var aa = skipTypes(a.typ[col], skipPtrs)
var bb = skipTypes(b.typ[col], skipPtrs)
var d = inheritanceDiff(aa, bb)
if (d != high(int)) and d != 0:
return d
proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
# we use shellsort here; fast and simple
var n = len(a)
var n = a.len
var h = 1
while true:
h = 3 * h + 1
if h > n: break
while true:
h = h div 3
for i in h ..< n:
for i in h..<n:
var v = a[i]
var j = i
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
@@ -228,71 +227,70 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
var base = methods[0].ast[dispatcherPos].sym
result = base
var paramLen = sonsLen(base.typ)
var paramLen = base.typ.len
var nilchecks = newNodeI(nkStmtList, base.info)
var disp = newNodeI(nkIfStmt, base.info)
var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
var iss = getSysMagic(g, unknownLineInfo(), "of", mOf)
let boolType = getSysType(g, unknownLineInfo(), tyBool)
for col in 1 ..< paramLen:
var ands = getSysMagic(g, unknownLineInfo, "and", mAnd)
var iss = getSysMagic(g, unknownLineInfo, "of", mOf)
let boolType = getSysType(g, unknownLineInfo, tyBool)
for col in 1..<paramLen:
if contains(relevantCols, col):
let param = base.typ.n.sons[col].sym
let param = base.typ.n[col].sym
if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
addSon(nilchecks, newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param)))
for meth in 0 .. high(methods):
nilchecks.add newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param))
for meth in 0..high(methods):
var curr = methods[meth] # generate condition:
var cond: PNode = nil
for col in 1 ..< paramLen:
for col in 1..<paramLen:
if contains(relevantCols, col):
var isn = newNodeIT(nkCall, base.info, boolType)
addSon(isn, newSymNode(iss))
let param = base.typ.n.sons[col].sym
addSon(isn, newSymNode(param))
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
isn.add newSymNode(iss)
let param = base.typ.n[col].sym
isn.add newSymNode(param)
isn.add newNodeIT(nkType, base.info, curr.typ[col])
if cond != nil:
var a = newNodeIT(nkCall, base.info, boolType)
addSon(a, newSymNode(ands))
addSon(a, cond)
addSon(a, isn)
a.add newSymNode(ands)
a.add cond
a.add isn
cond = a
else:
cond = isn
let retTyp = base.typ.sons[0]
let retTyp = base.typ[0]
let call = newNodeIT(nkCall, base.info, retTyp)
addSon(call, newSymNode(curr))
for col in 1 ..< paramLen:
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
curr.typ.sons[col], false, g.config))
call.add newSymNode(curr)
for col in 1..<paramLen:
call.add genConv(newSymNode(base.typ.n[col].sym),
curr.typ[col], false, g.config)
var ret: PNode
if retTyp != nil:
var a = newNodeI(nkFastAsgn, base.info)
addSon(a, newSymNode(base.ast.sons[resultPos].sym))
addSon(a, call)
a.add newSymNode(base.ast[resultPos].sym)
a.add call
ret = newNodeI(nkReturnStmt, base.info)
addSon(ret, a)
ret.add a
else:
ret = call
if cond != nil:
var a = newNodeI(nkElifBranch, base.info)
addSon(a, cond)
addSon(a, ret)
addSon(disp, a)
a.add cond
a.add ret
disp.add a
else:
disp = ret
nilchecks.add disp
nilchecks.flags.incl nfTransf # should not be further transformed
result.ast.sons[bodyPos] = nilchecks
result.ast[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList)
for bucket in 0 ..< len(g.methods):
for bucket in 0..<g.methods.len:
var relevantCols = initIntSet()
for col in 1 ..< sonsLen(g.methods[bucket].methods[0].typ):
for col in 1..<g.methods[bucket].methods[0].typ.len:
if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
if optMultiMethods notin g.config.globalOptions:
# if multi-methods are not enabled, we are interested only in the first field
break
sortBucket(g.methods[bucket].methods, relevantCols)
addSon(result,
newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols)))
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))

View File

@@ -90,9 +90,6 @@
# :unrollFinally = true
# goto nearestFinally (or -1 if not exists)
#
# Every finally block calls closureIterEndFinally() upon its successful
# completion.
#
# Example:
#
# try:
@@ -126,6 +123,7 @@
# if :curExc.isNil:
# return :tmpResult
# else:
# closureIterSetupExc(nil)
# raise
# state = -1 # Goto next state. In this case we just exit
# break :stateLoop
@@ -156,8 +154,8 @@ type
# is their finally. For finally it is parent finally. Otherwise -1
const
nkSkip = { nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt } + procDefs
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt} + procDefs
proc newStateAccess(ctx: var Ctx): PNode =
if ctx.stateVarSym.isNil:
@@ -174,7 +172,7 @@ proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
# Creates state assignment:
# :state = stateNo
ctx.newStateAssgn(newIntTypeNode(nkIntLit, stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
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), ctx.fn, ctx.fn.info)
@@ -239,7 +237,7 @@ proc toStmtList(n: PNode): PNode =
proc addGotoOut(n: PNode, gotoOut: PNode): PNode =
# Make sure `n` is a stmtlist, and ends with `gotoOut`
result = toStmtList(n)
if result.len == 0 or result.sons[^1].kind != nkGotoState:
if result.len == 0 or result[^1].kind != nkGotoState:
result.add(gotoOut)
proc newTempVar(ctx: var Ctx, typ: PType): PSym =
@@ -275,7 +273,7 @@ proc transformBreaksAndContinuesInWhile(ctx: var Ctx, n: PNode, before, after: P
if ctx.blockLevel == 0:
result = after
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformBreaksAndContinuesInWhile(n[i], before, after)
proc transformBreaksInBlock(ctx: var Ctx, n: PNode, label, after: PNode): PNode =
@@ -295,7 +293,7 @@ proc transformBreaksInBlock(ctx: var Ctx, n: PNode, label, after: PNode): PNode
if label.kind == nkSym and n[0].sym == label.sym:
result = after
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformBreaksInBlock(n[i], label, after)
proc newNullifyCurExc(ctx: var Ctx, info: TLineInfo): PNode =
@@ -320,7 +318,7 @@ proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
if c.len > 1:
var cond: PNode
for i in 0 .. c.len - 2:
for i in 0..<c.len - 1:
assert(c[i].kind == nkType)
let nextCond = newTree(nkCall,
newSymNode(g.getSysMagic(c.info, "of", mOf)),
@@ -359,7 +357,7 @@ proc addElseToExcept(ctx: var Ctx, n: PNode) =
block: # :unrollFinally = true
branchBody.add(newTree(nkAsgn,
ctx.newUnrollFinallyAccess(n.info),
newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool))))
newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool))))
block: # :curExc = getCurrentException()
branchBody.add(newTree(nkAsgn,
@@ -403,7 +401,7 @@ proc exprToStmtList(n: PNode): tuple[s, res: PNode] =
var n = n
while n.kind == nkStmtListExpr:
result.s.sons.add(n.sons)
result.s.sons.setLen(result.s.sons.len - 1) # delete last son
result.s.sons.setLen(result.s.len - 1) # delete last son
n = n[^1]
result.res = n
@@ -437,7 +435,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkYieldStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -451,7 +449,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkPar, nkObjConstr, nkTupleConstr, nkBracket:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -461,7 +459,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
if n.typ.isNil: internalError(ctx.g.config, "lowerStmtListExprs: constr typ.isNil")
result.typ = n.typ
for i in 0 ..< n.len:
for i in 0..<n.len:
case n[i].kind
of nkExprColonExpr:
if n[i][1].kind == nkStmtListExpr:
@@ -477,7 +475,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkIfStmt, nkIfExpr:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -543,7 +541,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkTryStmt, nkHiddenTryStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -556,7 +554,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
let tmp = ctx.newTempVar(n.typ)
n[0] = ctx.convertExprBodyToAsgn(n[0], tmp)
for i in 1 ..< n.len:
for i in 1..<n.len:
let branch = n[i]
case branch.kind
of nkExceptBranch:
@@ -573,7 +571,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkCaseStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -591,7 +589,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(st)
n[0] = ex
for i in 1 ..< n.len:
for i in 1..<n.len:
let branch = n[i]
case branch.kind
of nkOfBranch:
@@ -603,9 +601,9 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(n)
result.add(ctx.newEnvVarAccess(tmp))
of nkCallKinds:
of nkCallKinds, nkChckRange, nkChckRangeF, nkChckRange64:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -645,7 +643,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result.add(ifNode)
result.add(ctx.newEnvVarAccess(tmp))
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
if n[i].kind == nkStmtListExpr:
let (st, ex) = exprToStmtList(n[i])
result.add(st)
@@ -674,7 +672,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkDiscardStmt, nkReturnStmt, nkRaiseStmt:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -685,9 +683,10 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = ex
result.add(n)
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv:
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv, nkObjDownConv,
nkDerefExpr, nkHiddenDeref:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -701,7 +700,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
of nkAsgn, nkFastAsgn:
var ns = false
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], ns)
if ns:
@@ -759,7 +758,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
n[0] = newSymNode(ctx.g.getSysSym(n[0].info, "true"))
n[1] = newBody
of nkDotExpr:
of nkDotExpr, nkCheckedFieldExpr:
var ns = false
n[0] = ctx.lowerStmtListExprs(n[0], ns)
if ns:
@@ -779,14 +778,14 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
result = newNodeI(nkStmtListExpr, n.info)
result.typ = n.typ
let (st, ex) = exprToStmtList(n[1])
n.kind = nkBlockStmt
n.transitionSonsKind(nkBlockStmt)
n.typ = nil
n[1] = st
result.add(n)
result.add(ex)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.lowerStmtListExprs(n[i], needsSplit)
proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
@@ -809,10 +808,11 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
let retStmt = newTree(nkReturnStmt, asgn)
let branch = newTree(nkElifBranch, cmp, retStmt)
# The C++ backend requires `getCurrentException` here.
let raiseStmt = newTree(nkRaiseStmt, ctx.g.callCodegenProc("getCurrentException"))
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
nullifyExc.info = info
let raiseStmt = newTree(nkRaiseStmt, curExc)
raiseStmt.info = info
let elseBranch = newTree(nkElse, raiseStmt)
let elseBranch = newTree(nkElse, newTree(nkStmtList, nullifyExc, raiseStmt))
let ifBody = newTree(nkIfStmt, branch, elseBranch)
let elifBranch = newTree(nkElifBranch, ctx.newUnrollFinallyAccess(info), ifBody)
@@ -832,13 +832,14 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
block: # :unrollFinally = true
let asgn = newNodeI(nkAsgn, n.info)
asgn.add(ctx.newUnrollFinallyAccess(n.info))
asgn.add(newIntTypeNode(nkIntLit, 1, ctx.g.getSysType(n.info, tyBool)))
asgn.add(newIntTypeNode(1, ctx.g.getSysType(n.info, tyBool)))
result.add(asgn)
if n[0].kind != nkEmpty:
let asgnTmpResult = newNodeI(nkAsgn, n.info)
asgnTmpResult.add(ctx.newTmpResultAccess())
asgnTmpResult.add(n[0])
let x = if n[0].kind in {nkAsgn, nkFastAsgn}: n[0][1] else: n[0]
asgnTmpResult.add(x)
result.add(asgnTmpResult)
result.add(ctx.newNullifyCurExc(n.info))
@@ -849,7 +850,7 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
of nkSkip:
discard
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformReturnsInTry(n[i])
proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode =
@@ -859,14 +860,14 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
of nkStmtList, nkStmtListExpr:
result = addGotoOut(result, gotoOut)
for i in 0 ..< n.len:
for i in 0..<n.len:
if n[i].hasYields:
# Create a new split
let go = newNodeI(nkGotoState, n[i].info)
n[i] = ctx.transformClosureIteratorBody(n[i], go)
let s = newNodeI(nkStmtList, n[i + 1].info)
for j in i + 1 ..< n.len:
for j in i + 1..<n.len:
s.add(n[j])
n.sons.setLen(i + 1)
@@ -889,7 +890,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
result[^1] = ctx.transformClosureIteratorBody(result[^1], gotoOut)
of nkIfStmt, nkCaseStmt:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
if n[^1].kind != nkElse:
# We don't have an else branch, but every possible branch has to end with
@@ -1001,7 +1002,7 @@ proc transformClosureIteratorBody(ctx: var Ctx, n: PNode, gotoOut: PNode): PNode
internalError(ctx.g.config, "closure iter " & $n.kind)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformClosureIteratorBody(n[i], gotoOut)
proc stateFromGotoState(n: PNode): int =
@@ -1038,18 +1039,18 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(ctx.newStateAssgn(stateFromGotoState(n[1])))
var retStmt = newNodeI(nkReturnStmt, n.info)
if n[0].sons[0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n[0].sons[0].info)
var retVal = n[0].sons[0] #liftCapturedVars(n.sons[0], owner, d, c)
addSon(a, newSymNode(getClosureIterResult(ctx.g, ctx.fn)))
addSon(a, retVal)
if n[0][0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n[0][0].info)
var retVal = n[0][0] #liftCapturedVars(n[0], owner, d, c)
a.add newSymNode(getClosureIterResult(ctx.g, ctx.fn))
a.add retVal
retStmt.add(a)
else:
retStmt.add(ctx.g.emptyNode)
result.add(retStmt)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformStateAssignments(n[i])
of nkSkip:
@@ -1069,7 +1070,7 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(breakState)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.transformStateAssignments(n[i])
proc skipStmtList(ctx: Ctx; n: PNode): PNode =
@@ -1110,7 +1111,7 @@ proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode =
result = copyTree(n)
result[0].intVal = ctx.skipEmptyStates(result[0].intVal.int)
else:
for i in 0 ..< n.len:
for i in 0..<n.len:
n[i] = ctx.skipThroughEmptyStates(n[i])
proc newArrayType(g: ModuleGraph; n: int, t: PType, owner: PSym): PType =
@@ -1162,7 +1163,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
ctx.newStateAccess(),
newIntTypeNode(nkIntLit, 0, intTyp))
newIntTypeNode(0, intTyp))
cond.typ = boolTyp
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
@@ -1174,7 +1175,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
block:
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
newIntTypeNode(nkIntLit, 0, intTyp),
newIntTypeNode(0, intTyp),
ctx.newStateAccess())
cond.typ = boolTyp
@@ -1186,7 +1187,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
let cond = newTree(nkCall,
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
ctx.newStateAccess(),
newIntTypeNode(nkIntLit, 0, intTyp))
newIntTypeNode(0, intTyp))
cond.typ = boolTyp
let negateState = newTree(nkCall,
@@ -1287,9 +1288,9 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
ctx.fn = fn
if getEnvParam(fn).isNil:
# Lambda lifting was not done yet. Use temporary :state sym, which
# Lambda lifting was not done yet. Use temporary :state sym, which will
# be handled specially by lambda lifting. Local temp vars (if needed)
# should folllow the same logic.
# should follow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
@@ -1310,7 +1311,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# Optimize empty states away
ctx.deleteEmptyStates()
# Make new body by concating the list of states
# Make new body by concatenating the list of states
result = newNodeI(nkStmtList, n.info)
for s in ctx.states:
assert(s.len == 2)

View File

@@ -10,9 +10,11 @@
## Helpers for binaries that use compiler passes, eg: nim, nimsuggest, nimfix
import
options, idents, nimconf, scriptconfig, extccomp, commands, msgs,
options, idents, nimconf, extccomp, commands, msgs,
lineinfos, modulegraphs, condsyms, os, pathutils
from strutils import normalize
type
NimProg* = ref object
suggestMode*: bool
@@ -27,10 +29,7 @@ proc initDefinesProg*(self: NimProg, conf: ConfigRef, name: string) =
proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
self.processCmdLine(passCmd1, "", conf)
if self.supportsStdinFile and conf.projectName == "-":
conf.projectName = "stdinfile"
conf.projectFull = AbsoluteFile "stdinfile"
conf.projectPath = AbsoluteDir getCurrentDir()
conf.projectIsStdin = true
handleStdinInput(conf)
elif conf.projectName != "":
try:
conf.projectFull = canonicalizePath(conf, AbsoluteFile conf.projectName)
@@ -44,45 +43,31 @@ proc processCmdLineAndProjectPath*(self: NimProg, conf: ConfigRef) =
conf.projectPath = AbsoluteDir canonicalizePath(conf, AbsoluteFile getCurrentDir())
proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: ConfigRef): bool =
loadConfigs(DefaultConfig, cache, conf) # load all config files
if self.suggestMode:
conf.command = "nimsuggest"
loadConfigs(DefaultConfig, cache, conf) # load all config files
template runNimScriptIfExists(path: AbsoluteFile) =
let p = path # eval once
if fileExists(p):
runNimScript(cache, p, freshDefines = false, conf)
# Caution: make sure this stays in sync with `loadConfigs`
if optSkipSystemConfigFile notin conf.globalOptions:
runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
if optSkipUserConfigFile notin conf.globalOptions:
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(conf.projectPath.string, fromRoot = true, inclusive = false):
runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims)
if optSkipProjConfigFile notin conf.globalOptions:
runNimScriptIfExists(conf.projectPath / DefaultConfigNims)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
if not self.suggestMode:
runNimScriptIfExists(scriptFile)
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
if fileExists(scriptFile) and scriptFile == conf.projectFull:
return false
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard
if conf.command == "":
conf.command = "e"
return false
elif conf.command.normalize == "e":
return false
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars(conf)
# XXX This is hacky. We need to find a better way.
case conf.command
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
else:
discard
self.processCmdLine(passCmd2, "", conf)
if conf.command == "":
rawMessage(conf, errGenerated, "command missing")

View File

@@ -18,7 +18,8 @@ template bootSwitch(name, expr, userString) =
bootSwitch(usedRelease, defined(release), "-d:release")
bootSwitch(usedDanger, defined(danger), "-d:danger")
bootSwitch(usedGnuReadline, defined(useLinenoise), "-d:useLinenoise")
# `useLinenoise` deprecated in favor of `nimUseLinenoise`, kept for backward compatibility
bootSwitch(useLinenoise, defined(nimUseLinenoise) or defined(useLinenoise), "-d:nimUseLinenoise")
bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm")
bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep")
bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational")
@@ -31,6 +32,7 @@ import
pathutils, strtabs
from incremental import nimIncremental
from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
# but some have deps to imported modules. Yay.
bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
@@ -101,7 +103,7 @@ proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) =
msgWriteln(conf, "git hash: " & gitHash, {msgStdout})
msgWriteln(conf, "active boot switches:" & usedRelease & usedDanger &
usedTinyC & usedGnuReadline & usedNativeStacktrace &
usedTinyC & useLinenoise & usedNativeStacktrace &
usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC,
{msgStdout})
msgQuit(0)
@@ -110,7 +112,7 @@ proc writeCommandLineUsage*(conf: ConfigRef) =
msgWriteln(conf, getCommandLineDesc(conf), {msgStdout})
proc addPrefix(switch: string): string =
if len(switch) <= 1: result = "-" & switch
if switch.len <= 1: result = "-" & switch
else: result = "--" & switch
const
@@ -127,14 +129,14 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC
info: TLineInfo) =
cmd = ""
var i = 0
if i < len(switch) and switch[i] == '-': inc(i)
if i < len(switch) and switch[i] == '-': inc(i)
while i < len(switch):
if i < switch.len and switch[i] == '-': inc(i)
if i < switch.len and switch[i] == '-': inc(i)
while i < switch.len:
case switch[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': add(cmd, switch[i])
of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': cmd.add(switch[i])
else: break
inc(i)
if i >= len(switch): arg = ""
if i >= switch.len: arg = ""
# cmd:arg => (cmd,arg)
elif switch[i] in {':', '='}: arg = substr(switch, i + 1)
# cmd[sub]:rest => (cmd,[sub]:rest)
@@ -178,17 +180,17 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
var i = 0
var n = hintMin
var isBracket = false
if i < len(arg) and arg[i] == '[':
if i < arg.len and arg[i] == '[':
isBracket = true
inc(i)
while i < len(arg) and (arg[i] notin {':', '=', ']'}):
add(id, arg[i])
while i < arg.len and (arg[i] notin {':', '=', ']'}):
id.add(arg[i])
inc(i)
if isBracket:
if i < len(arg) and arg[i] == ']': inc(i)
if i < arg.len and arg[i] == ']': inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if i < len(arg) and (arg[i] in {':', '='}): inc(i)
if i < arg.len and (arg[i] in {':', '='}): inc(i)
else: invalidCmdLineOption(conf, pass, orig, info)
if state == wHint:
let x = findStr(lineinfos.HintsToStr, id)
@@ -198,17 +200,21 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
let x = findStr(lineinfos.WarningsToStr, id)
if x >= 0: n = TNoteKind(x + ord(warnMin))
else: localError(conf, info, "unknown warning: " & id)
case substr(arg, i).normalize
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
incl(conf.enableNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
incl(conf.disableNotes, n)
excl(conf.foreignPackageNotes, n)
else: localError(conf, info, errOnOrOffExpectedButXFound % arg)
let val = substr(arg, i).normalize
if val notin ["on", "off"]:
localError(conf, info, errOnOrOffExpectedButXFound % arg)
elif n notin conf.cmdlineNotes or pass == passCmd1:
if pass == passCmd1: incl(conf.cmdlineNotes, n)
incl(conf.modifiedyNotes, n)
case val
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename)
@@ -219,19 +225,22 @@ const
errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
case switch.normalize
of "gc":
case arg.normalize
of "boehm": result = conf.selectedGC == gcBoehm
of "refc": result = conf.selectedGC == gcRefc
of "v2": result = false
of "boehm": result = conf.selectedGC == gcBoehm
of "refc": result = conf.selectedGC == gcRefc
of "v2": result = false
of "markandsweep": result = conf.selectedGC == gcMarkAndSweep
of "generational": result = false
of "destructors": result = conf.selectedGC == gcDestructors
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "destructors", "arc": result = conf.selectedGC == gcArc
of "orc": result = conf.selectedGC == gcOrc
of "hooks": result = conf.selectedGC == gcHooks
of "go": result = conf.selectedGC == gcGo
of "none": result = conf.selectedGC == gcNone
of "stack", "regions": result = conf.selectedGC == gcRegions
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
of "opt":
@@ -243,15 +252,22 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo
of "verbosity": result = $conf.verbosity == arg
of "app":
case arg.normalize
of "gui": result = contains(conf.globalOptions, optGenGuiApp)
of "console": result = not contains(conf.globalOptions, optGenGuiApp)
of "lib": result = contains(conf.globalOptions, optGenDynLib) and
of "gui": result = contains(conf.globalOptions, optGenGuiApp)
of "console": result = not contains(conf.globalOptions, optGenGuiApp)
of "lib": result = contains(conf.globalOptions, optGenDynLib) and
not contains(conf.globalOptions, optGenGuiApp)
of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and
not contains(conf.globalOptions, optGenGuiApp)
else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg)
of "dynliboverride":
result = isDynlibOverride(conf, arg)
of "exceptions":
case arg.normalize
of "cpp": result = conf.exc == excCpp
of "setjmp": result = conf.exc == excSetjmp
of "quirky": result = conf.exc == excQuirky
of "goto": result = conf.exc == excGoto
else: localError(conf, info, errInvalidExceptionSystem % arg)
else: invalidCmdLineOption(conf, passCmd1, switch, info)
proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool =
@@ -265,8 +281,9 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "hints": result = contains(conf.options, optHints)
of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis)
of "stacktrace": result = contains(conf.options, optStackTrace)
of "stacktracemsgs": result = contains(conf.options, optStackTraceMsgs)
of "linetrace": result = contains(conf.options, optLineTrace)
of "debugger": result = contains(conf.options, optEndb)
of "debugger": result = contains(conf.globalOptions, optCDebug)
of "profiler": result = contains(conf.options, optProfiler)
of "memtracker": result = contains(conf.options, optMemTracker)
of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions
@@ -281,6 +298,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "boundchecks": result = contains(conf.options, optBoundsCheck)
of "refchecks": result = contains(conf.options, optRefCheck)
of "overflowchecks": result = contains(conf.options, optOverflowCheck)
of "staticboundchecks": result = contains(conf.options, optStaticBoundsCheck)
of "stylechecks": result = contains(conf.options, optStyleCheck)
of "linedir": result = contains(conf.options, optLineDir)
of "assertions", "a": result = contains(conf.options, optAssert)
@@ -359,6 +377,14 @@ proc dynlibOverride(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, in
expectArg(conf, switch, arg, pass, info)
options.inclDynlibOverride(conf, arg)
proc handleStdinInput*(conf: ConfigRef) =
conf.projectName = "stdinfile"
conf.projectFull = conf.projectName.AbsoluteFile
conf.projectPath = AbsoluteDir getCurrentDir()
conf.projectIsStdin = true
if conf.outDir.isEmpty:
conf.outDir = getNimcacheDir(conf)
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf: ConfigRef) =
var
@@ -366,8 +392,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
case switch.normalize
of "path", "p":
expectArg(conf, switch, arg, pass, info)
addPath(conf, if pass == passPP: processCfgPath(conf, arg, info)
else: processPath(conf, arg, info), info)
for path in nimbleSubs(conf, arg):
addPath(conf, if pass == passPP: processCfgPath(conf, path, info)
else: processPath(conf, path, info), info)
of "nimblepath", "babelpath":
# keep the old name for compat
if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions:
@@ -380,6 +407,9 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "nonimblepath", "nobabelpath":
expectNoArg(conf, switch, arg, pass, info)
disableNimblePath(conf)
of "clearnimblepath":
expectNoArg(conf, switch, arg, pass, info)
clearNimblePath(conf)
of "excludepath":
expectArg(conf, switch, arg, pass, info)
let path = processPath(conf, arg, info)
@@ -387,26 +417,32 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.lazyPaths.keepItIf(it != path)
of "nimcache":
expectArg(conf, switch, arg, pass, info)
conf.nimcacheDir = processPath(conf, arg, info, true)
conf.nimcacheDir = processPath(conf, arg, info, notRelativeToProj=true)
of "out", "o":
expectArg(conf, switch, arg, pass, info)
let f = splitFile(arg.expandTilde)
let f = splitFile(processPath(conf, arg, info, notRelativeToProj=true).string)
conf.outFile = RelativeFile f.name & f.ext
conf.outDir = toAbsoluteDir f.dir
of "outdir":
expectArg(conf, switch, arg, pass, info)
conf.outDir = toAbsoluteDir arg.expandTilde
conf.outDir = processPath(conf, arg, info, notRelativeToProj=true)
of "docseesrcurl":
expectArg(conf, switch, arg, pass, info)
conf.docSeeSrcUrl = arg
of "docroot":
conf.docRoot = if arg.len == 0: "@default" else: arg
of "mainmodule", "m":
discard "allow for backwards compatibility, but don't do anything"
of "define", "d":
expectArg(conf, switch, arg, pass, info)
if {':', '='} in arg:
splitSwitch(conf, arg, key, val, pass, info)
if cmpIgnoreStyle(key, "nimQuirky") == 0:
conf.exc = excQuirky
defineSymbol(conf.symbols, key, val)
else:
if cmpIgnoreStyle(arg, "nimQuirky") == 0:
conf.exc = excQuirky
defineSymbol(conf.symbols, arg)
of "undef", "u":
expectArg(conf, switch, arg, pass, info)
@@ -437,30 +473,57 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optWholeProject}, arg, pass, info)
of "gc":
expectArg(conf, switch, arg, pass, info)
case arg.normalize
of "boehm":
conf.selectedGC = gcBoehm
defineSymbol(conf.symbols, "boehmgc")
of "refc":
conf.selectedGC = gcRefc
of "v2":
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
of "markandsweep":
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors":
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")
of "go":
conf.selectedGC = gcGo
defineSymbol(conf.symbols, "gogc")
of "none":
conf.selectedGC = gcNone
defineSymbol(conf.symbols, "nogc")
of "stack", "regions":
conf.selectedGC= gcRegions
defineSymbol(conf.symbols, "gcregions")
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
if pass in {passCmd2, passPP}:
case arg.normalize
of "boehm":
conf.selectedGC = gcBoehm
defineSymbol(conf.symbols, "boehmgc")
of "refc":
conf.selectedGC = gcRefc
of "v2":
message(conf, info, warnDeprecated, "--gc:v2 is deprecated; using default gc")
of "markandsweep":
conf.selectedGC = gcMarkAndSweep
defineSymbol(conf.symbols, "gcmarkandsweep")
of "destructors", "arc":
conf.selectedGC = gcArc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcarc")
incl conf.globalOptions, optSeqDestructors
incl conf.globalOptions, optTinyRtti
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimV2")
of "orc":
conf.selectedGC = gcOrc
if conf.cmd != cmdCompileToCpp:
conf.exc = excGoto
defineSymbol(conf.symbols, "gcdestructors")
defineSymbol(conf.symbols, "gcorc")
incl conf.globalOptions, optSeqDestructors
incl conf.globalOptions, optTinyRtti
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimV2")
of "hooks":
conf.selectedGC = gcHooks
defineSymbol(conf.symbols, "gchooks")
incl conf.globalOptions, optSeqDestructors
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
of "go":
conf.selectedGC = gcGo
defineSymbol(conf.symbols, "gogc")
of "none":
conf.selectedGC = gcNone
defineSymbol(conf.symbols, "nogc")
of "stack", "regions":
conf.selectedGC = gcRegions
defineSymbol(conf.symbols, "gcregions")
else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg)
of "warnings", "w":
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
@@ -469,28 +532,23 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)
of "stacktrace": processOnOffSwitch(conf, {optStackTrace}, arg, pass, info)
of "stacktracemsgs": processOnOffSwitch(conf, {optStackTraceMsgs}, arg, pass, info)
of "excessivestacktrace": processOnOffSwitchG(conf, {optExcessiveStackTrace}, arg, pass, info)
of "linetrace": processOnOffSwitch(conf, {optLineTrace}, arg, pass, info)
of "debugger":
case arg.normalize
of "on", "endb":
conf.options.incl optEndb
defineSymbol(conf.symbols, "endb")
of "off":
conf.options.excl optEndb
undefSymbol(conf.symbols, "endb")
of "native", "gdb":
incl(conf.globalOptions, optCDebug)
conf.options = conf.options + {optLineDir} - {optEndb}
of "on", "native", "gdb":
conf.globalOptions.incl optCDebug
conf.options.incl optLineDir
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
undefSymbol(conf.symbols, "endb")
of "off":
conf.globalOptions.excl optCDebug
else:
localError(conf, info, "expected endb|gdb but found " & arg)
localError(conf, info, "expected native|gdb|on|off but found " & arg)
of "g": # alias for --debugger:native
incl(conf.globalOptions, optCDebug)
conf.options = conf.options + {optLineDir} - {optEndb}
conf.globalOptions.incl optCDebug
conf.options.incl optLineDir
#defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
undefSymbol(conf.symbols, "endb")
of "profiler":
processOnOffSwitch(conf, {optProfiler}, arg, pass, info)
if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler")
@@ -513,7 +571,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
undefSymbol(conf.symbols, "useNimRtl")
of "oldnewlines":
case arg.normalize
of "","on":
of "", "on":
conf.oldNewlines = true
defineSymbol(conf.symbols, "nimOldNewlines")
of "off":
@@ -536,13 +594,14 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "boundchecks": processOnOffSwitch(conf, {optBoundsCheck}, arg, pass, info)
of "refchecks": processOnOffSwitch(conf, {optRefCheck}, arg, pass, info)
of "overflowchecks": processOnOffSwitch(conf, {optOverflowCheck}, arg, pass, info)
of "staticboundchecks": processOnOffSwitch(conf, {optStaticBoundsCheck}, arg, pass, info)
of "stylechecks": processOnOffSwitch(conf, {optStyleCheck}, arg, pass, info)
of "linedir": processOnOffSwitch(conf, {optLineDir}, arg, pass, info)
of "assertions", "a": processOnOffSwitch(conf, {optAssert}, arg, pass, info)
of "deadcodeelim": discard # deprecated, dead code elim always on
of "threads":
processOnOffSwitchG(conf, {optThreads}, arg, pass, info)
#if optThreads in conf.globalOptions: incl(conf.notes, warnGcUnsafe)
#if optThreads in conf.globalOptions: conf.setNote(warnGcUnsafe)
of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info)
of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info)
of "implicitstatic":
@@ -615,28 +674,31 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
conf.implicitIncludes.add findModule(conf, arg, toFullPath(conf, info)).string
of "listcmd":
processOnOffSwitchG(conf, {optListCmd}, arg, pass, info)
of "asm":
processOnOffSwitchG(conf, {optProduceAsm}, arg, pass, info)
of "genmapping":
processOnOffSwitchG(conf, {optGenMapping}, arg, pass, info)
of "os":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd1, passPP}:
let theOS = platform.nameToOS(arg)
if theOS == osNone:
let osList = platform.listOSnames().join(", ")
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
elif theOS != conf.target.hostOS:
setTarget(conf.target, theOS, conf.target.targetCPU)
let theOS = platform.nameToOS(arg)
if theOS == osNone:
let osList = platform.listOSnames().join(", ")
localError(conf, info, "unknown OS: '$1'. Available options are: $2" % [arg, $osList])
else:
setTarget(conf.target, theOS, conf.target.targetCPU)
of "cpu":
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd1, passPP}:
let cpu = platform.nameToCPU(arg)
if cpu == cpuNone:
let cpuList = platform.listCPUnames().join(", ")
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
elif cpu != conf.target.hostCPU:
setTarget(conf.target, conf.target.targetOS, cpu)
let cpu = platform.nameToCPU(arg)
if cpu == cpuNone:
let cpuList = platform.listCPUnames().join(", ")
localError(conf, info, "unknown CPU: '$1'. Available options are: $2" % [ arg, cpuList])
else:
setTarget(conf.target, conf.target.targetOS, cpu)
of "run", "r":
processOnOffSwitchG(conf, {optRun}, arg, pass, info)
of "maxloopiterationsvm":
expectArg(conf, switch, arg, pass, info)
conf.maxLoopIterationsVM = parseInt(arg)
of "errormax":
expectArg(conf, switch, arg, pass, info)
# Note: `nim check` (etc) can overwrite this.
@@ -651,9 +713,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if verbosity notin {0..3}:
localError(conf, info, "invalid verbosity level: '$1'" % arg)
conf.verbosity = verbosity
conf.notes = NotesVerbosity[conf.verbosity]
incl(conf.notes, conf.enableNotes)
excl(conf.notes, conf.disableNotes)
var verb = NotesVerbosity[conf.verbosity]
## We override the default `verb` by explicitly modified (set/unset) notes.
conf.notes = (conf.modifiedyNotes * conf.notes + verb) -
(conf.modifiedyNotes * verb - conf.notes)
conf.mainPackageNotes = conf.notes
of "parallelbuild":
expectArg(conf, switch, arg, pass, info)
@@ -752,8 +815,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
localError(conf, info, "unknown obsolete feature")
of "nocppexceptions":
expectNoArg(conf, switch, arg, pass, info)
incl(conf.globalOptions, optNoCppExceptions)
conf.exc = low(ExceptionSystem)
defineSymbol(conf.symbols, "noCppExceptions")
of "exceptions":
case arg.normalize
of "cpp": conf.exc = excCpp
of "setjmp": conf.exc = excSetjmp
of "quirky": conf.exc = excQuirky
of "goto": conf.exc = excGoto
else: localError(conf, info, errInvalidExceptionSystem % arg)
of "cppdefine":
expectArg(conf, switch, arg, pass, info)
if conf != nil:
@@ -763,14 +833,22 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if pass in {passCmd2, passPP}:
doAssert(conf != nil)
incl(conf.features, destructor)
incl(conf.globalOptions, optNimV2)
incl(conf.globalOptions, optTinyRtti)
incl(conf.globalOptions, optOwnedRefs)
incl(conf.globalOptions, optSeqDestructors)
defineSymbol(conf.symbols, "nimV2")
conf.selectedGC = gcDestructors
defineSymbol(conf.symbols, "gcdestructors")
conf.selectedGC = gcHooks
defineSymbol(conf.symbols, "gchooks")
defineSymbol(conf.symbols, "nimSeqsV2")
defineSymbol(conf.symbols, "nimOwnedEnabled")
of "seqsv2":
processOnOffSwitchG(conf, {optSeqDestructors}, arg, pass, info)
if pass in {passCmd2, passPP}:
defineSymbol(conf.symbols, "nimSeqsV2")
of "stylecheck":
case arg.normalize
of "off": conf.globalOptions = conf.globalOptions - {optStyleHint, optStyleError}
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint}
of "hint": conf.globalOptions = conf.globalOptions + {optStyleHint} - {optStyleError}
of "error": conf.globalOptions = conf.globalOptions + {optStyleError}
else: localError(conf, info, errOffHintsError % arg)
of "showallmismatches":
@@ -788,13 +866,41 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "expandmacro":
expectArg(conf, switch, arg, pass, info)
conf.macrosToExpand[arg] = "T"
of "":
conf.projectName = "-"
of "oldgensym":
processOnOffSwitchG(conf, {optNimV019}, arg, pass, info)
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
of "1.0":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "0")
# always be compatible with 1.0.100:
defineSymbol(conf.symbols, "NimPatch", "100")
# old behaviors go here:
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
conf.globalOptions.incl optNimV1Emulation
else:
localError(conf, info, "unknown Nim version; currently supported values are: {1.0}")
of "benchmarkvm":
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
of "sinkinference":
processOnOffSwitch(conf, {optSinkInference}, arg, pass, info)
of "panics":
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
if optPanics in conf.globalOptions:
defineSymbol(conf.symbols, "nimPanics")
of "sourcemap":
conf.globalOptions.incl optSourcemap
conf.options.incl optLineDir
# processOnOffSwitchG(conf, {optSourcemap, opt}, arg, pass, info)
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
handleStdinInput(conf)
else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
else: invalidCmdLineOption(conf, pass, switch, info)
template gCmdLineInfo*(): untyped = newLineInfo(config, AbsoluteFile"command line", 1, 1)
template gCmdLineInfo*(): untyped = newLineInfo(commandLineIdx, 1, 1)
proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) =
var cmd, arg: string

View File

@@ -48,13 +48,11 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimalias")
defineSymbol("nimlocks")
defineSymbol("nimnode")
defineSymbol("nimnomagic64")
defineSymbol("nimvarargstyped")
defineSymbol("nimtypedescfixed")
defineSymbol("nimKnowsNimvm")
defineSymbol("nimArrIdx")
defineSymbol("nimHasalignOf")
defineSymbol("nimNewShiftOps")
defineSymbol("nimDistros")
defineSymbol("nimHasCppDefine")
defineSymbol("nimGenericInOutFlags")
@@ -87,6 +85,7 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasDefault")
defineSymbol("nimMacrosSizealignof")
defineSymbol("nimNoZeroExtendMagic")
defineSymbol("nimMacrosGetNodeId")
for f in low(Feature)..high(Feature):
defineSymbol("nimHas" & $f)
@@ -97,3 +96,23 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimFixedOwned")
defineSymbol("nimHasStyleChecks")
defineSymbol("nimToOpenArrayCString")
defineSymbol("nimHasUsed")
defineSymbol("nimFixedForwardGeneric")
defineSymbol("nimnomagic64")
defineSymbol("nimNewShiftOps")
defineSymbol("nimHasCursor")
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("nimHasSinkInference")
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")

View File

@@ -1,6 +0,0 @@
## Use the module 'lineinfos' instead!
{.deprecated.}
import lineinfos
export lineinfos

View File

@@ -1,72 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2019 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
lineinfos, parampatterns
##[
This module implements "cursor" detection. A cursor is a local variable
that is used for navigation in a datastructure, it does not "own" the
data it aliases but it might update the underlying datastructure.
Two primary examples for cursors that I have in mind and that are critical
for optimization:
1. Local string variable introduced by ``for x in a``::
var i = 0
while i < a.len:
let cursor = a[i]
use cursor
inc i
2. Local ``ref`` variable for navigation::
var cursor = listHead
while cursor != nil:
use cursor
cursor = cursor.next
Cursors are very interesting for the optimizer because they can be copyMem'ed
and don't need a destructor.
More formally, a cursor is a variable that is set on all paths to
a *location* or a proc call that produced a ``lent/var`` type. All statements
that come after these assignments MUST not mutate what the cursor aliases.
Mutations *through* the cursor are allowed if the cursor has ref semantics.
Look at this complex real world example taken from the compiler itself:
.. code-block:: Nim
proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope =
var t = typ
while true:
if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}:
return t.sym.loc.r
if t.kind in irrelevantForBackend:
t = t.lastSon
else:
break
let typ = if typ.kind in {tyAlias, tySink, tyOwned}: typ.lastSon else: typ
if typ.loc.r == nil:
typ.loc.r = typ.typeName & $sig
result = typ.loc.r
if result == nil: internalError(m.config, "getTypeName: " & $typ.kind)
Here `t` is a cursor but without a control flow based analysis we are unlikely
to detect it.
]##
# Araq: I owe you an implementation. For now use the .cursor pragma. :-/

View File

@@ -25,7 +25,7 @@ type
dotGraph: Rope
proc addDependencyAux(b: Backend; importing, imported: string) =
addf(b.dotGraph, "$1 -> \"$2\";$n", [rope(importing), rope(imported)])
b.dotGraph.addf("$1 -> \"$2\";$n", [rope(importing), rope(imported)])
# s1 -> s2_4[label="[0-9]"];
proc addDotDependency(c: PPassContext, n: PNode): PNode =
@@ -34,14 +34,14 @@ proc addDotDependency(c: PPassContext, n: PNode): PNode =
let b = Backend(g.graph.backend)
case n.kind
of nkImportStmt:
for i in 0 ..< sonsLen(n):
var imported = getModuleName(g.config, n.sons[i])
for i in 0..<n.len:
var imported = getModuleName(g.config, n[i])
addDependencyAux(b, g.module.name.s, imported)
of nkFromStmt, nkImportExceptStmt:
var imported = getModuleName(g.config, n.sons[0])
var imported = getModuleName(g.config, n[0])
addDependencyAux(b, g.module.name.s, imported)
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
for i in 0 ..< sonsLen(n): discard addDotDependency(c, n.sons[i])
for i in 0..<n.len: discard addDotDependency(c, n[i])
else:
discard

View File

@@ -37,13 +37,10 @@ type
InstrKind* = enum
goto, fork, join, def, use
Instr* = object
n*: PNode
n*: PNode # contains the def/use location.
case kind*: InstrKind
of def, use: sym*: PSym # 'sym' can also be 'nil' and
# then 'n' contains the def/use location.
# This is used so that we can track object
# and tuple field accesses precisely.
of goto, fork, join: dest*: int
else: discard
ControlFlowGraph* = seq[Instr]
@@ -94,8 +91,7 @@ proc echoCfg*(c: ControlFlowGraph; start=0; last = -1) {.deprecated.} =
## echos the ControlFlowGraph for debugging purposes.
var buf = ""
codeListing(c, buf, start, last)
when declared(echo):
echo buf
echo buf
proc forkI(c: var Con; n: PNode): TPosition =
result = TPosition(c.code.len)
@@ -331,20 +327,20 @@ when true:
L4:
join F1
]#
if isTrue(n.sons[0]):
if isTrue(n[0]):
# 'while true' is an idiom in Nim and so we produce
# better code for it:
for i in 0..2:
withBlock(nil):
c.gen(n.sons[1])
c.gen(n[1])
else:
let oldForksLen = c.forks.len
var endings: array[3, TPosition]
for i in 0..2:
withBlock(nil):
c.gen(n.sons[0])
c.gen(n[0])
endings[i] = c.forkI(n)
c.gen(n.sons[1])
c.gen(n[1])
for i in countdown(endings.high, 0):
let endPos = endings[i]
c.patch(endPos)
@@ -363,20 +359,20 @@ else:
let oldForksLen = c.forks.len
let lab1 = c.genLabel
withBlock(nil):
if isTrue(n.sons[0]):
c.gen(n.sons[1])
if isTrue(n[0]):
c.gen(n[1])
c.jmpBack(n, lab1)
else:
c.gen(n.sons[0])
c.gen(n[0])
let lab2 = c.forkI(n)
c.gen(n.sons[1])
c.gen(n[1])
c.jmpBack(n, lab1)
c.patch(lab2)
setLen(c.forks, oldForksLen)
proc genBlock(c: var Con; n: PNode) =
withBlock(n.sons[0].sym):
c.gen(n.sons[1])
withBlock(n[0].sym):
c.gen(n[1])
proc genJoins(c: var Con; n: PNode) =
for i in countdown(c.forks.high, 0): joinI(c, c.forks[i], n)
@@ -384,10 +380,10 @@ proc genJoins(c: var Con; n: PNode) =
proc genBreak(c: var Con; n: PNode) =
genJoins(c, n)
let lab1 = c.gotoI(n)
if n.sons[0].kind == nkSym:
#echo cast[int](n.sons[0].sym)
if n[0].kind == nkSym:
#echo cast[int](n[0].sym)
for i in countdown(c.blocks.len-1, 0):
if c.blocks[i].label == n.sons[0].sym:
if c.blocks[i].label == n[0].sym:
c.blocks[i].fixups.add lab1
return
#globalError(n.info, "VM problem: cannot find 'break' target")
@@ -441,13 +437,13 @@ proc genIf(c: var Con, n: PNode) =
]#
let oldLen = c.forks.len
var endings: seq[TPosition] = @[]
for i in 0 ..< len(n):
var it = n.sons[i]
c.gen(it.sons[0])
for i in 0..<n.len:
var it = n[i]
c.gen(it[0])
if it.len == 2:
let elsePos = forkI(c, it[1])
c.gen(it.sons[1])
endings.add(c.gotoI(it.sons[1]))
c.gen(it[1])
endings.add(c.gotoI(it[1]))
c.patch(elsePos)
for i in countdown(endings.high, 0):
let endPos = endings[i]
@@ -461,9 +457,9 @@ proc genAndOr(c: var Con; n: PNode) =
# asgn dest, b
# lab1:
# join F1
c.gen(n.sons[1])
c.gen(n[1])
forkT(n):
c.gen(n.sons[2])
c.gen(n[2])
proc genCase(c: var Con; n: PNode) =
# if (!expr1) goto lab1;
@@ -476,16 +472,16 @@ proc genCase(c: var Con; n: PNode) =
# lab2:
# elsePart
# Lend:
let isExhaustive = skipTypes(n.sons[0].typ,
let isExhaustive = skipTypes(n[0].typ,
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString}
var endings: seq[TPosition] = @[]
let oldLen = c.forks.len
c.gen(n.sons[0])
for i in 1 ..< n.len:
let it = n.sons[i]
c.gen(n[0])
for i in 1..<n.len:
let it = n[i]
if it.len == 1:
c.gen(it.sons[0])
c.gen(it[0])
elif i == n.len-1 and isExhaustive:
# treat the last branch as 'else' if this is an exhaustive case statement.
c.gen(it.lastSon)
@@ -507,23 +503,22 @@ proc genTry(c: var Con; n: PNode) =
let oldFixups = c.tryStmtFixups.len
#let elsePos = c.forkI(n)
c.gen(n.sons[0])
c.gen(n[0])
dec c.inTryStmt
for i in oldFixups..c.tryStmtFixups.high:
let f = c.tryStmtFixups[i]
c.patch(f)
# we also need to produce join instructions
# for the 'fork' that might preceed the goto instruction
# for the 'fork' that might precede the goto instruction
if f.int-1 >= 0 and c.code[f.int-1].kind == fork:
c.joinI(TPosition(f.int-1), n)
setLen(c.tryStmtFixups, oldFixups)
#c.patch(elsePos)
for i in 1 ..< n.len:
let it = n.sons[i]
for i in 1..<n.len:
let it = n[i]
if it.kind != nkFinally:
var blen = len(it)
let endExcept = c.forkI(it)
c.gen(it.lastSon)
endings.add(c.gotoI(it))
@@ -538,7 +533,7 @@ proc genTry(c: var Con; n: PNode) =
let fin = lastSon(n)
if fin.kind == nkFinally:
c.gen(fin.sons[0])
c.gen(fin[0])
doAssert(c.forks.len == oldLen)
template genNoReturn(c: var Con; n: PNode) =
@@ -547,7 +542,7 @@ template genNoReturn(c: var Con; n: PNode) =
proc genRaise(c: var Con; n: PNode) =
genJoins(c, n)
gen(c, n.sons[0])
gen(c, n[0])
if c.inTryStmt > 0:
c.tryStmtFixups.add c.gotoI(n)
else:
@@ -555,12 +550,12 @@ proc genRaise(c: var Con; n: PNode) =
proc genImplicitReturn(c: var Con) =
if c.owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter} and resultPos < c.owner.ast.len:
gen(c, c.owner.ast.sons[resultPos])
gen(c, c.owner.ast[resultPos])
proc genReturn(c: var Con; n: PNode) =
genJoins(c, n)
if n.sons[0].kind != nkEmpty:
gen(c, n.sons[0])
if n[0].kind != nkEmpty:
gen(c, n[0])
else:
genImplicitReturn(c)
genNoReturn(c, n)
@@ -573,16 +568,6 @@ const
nkObjDownConv, nkObjUpConv}
PathKinds1 = {nkHiddenStdConv, nkHiddenSubConv}
proc getRoot(n: PNode): PNode =
result = n
while true:
case result.kind
of PathKinds0:
result = result[0]
of PathKinds1:
result = result[1]
else: break
proc skipConvDfa*(n: PNode): PNode =
result = n
while true:
@@ -594,11 +579,23 @@ proc skipConvDfa*(n: PNode): PNode =
else: break
proc genUse(c: var Con; orig: PNode) =
let n = dfa.getRoot(orig)
var n = orig
while true:
case n.kind
of PathKinds0 - {nkBracketExpr}:
n = n[0]
of nkBracketExpr:
gen(c, n[1])
n = n[0]
of PathKinds1:
n = n[1]
else: break
if n.kind in nkCallKinds:
gen(c, n)
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: orig, kind: use, sym: if orig != n: nil else: n.sym)
c.code.add Instr(n: orig, kind: use)
proc aliases(obj, field: PNode): bool =
proc aliases*(obj, field: PNode): bool =
var n = field
var obj = obj
while obj.kind in {nkHiddenSubConv, nkHiddenStdConv, nkObjDownConv, nkObjUpConv}:
@@ -606,66 +603,45 @@ proc aliases(obj, field: PNode): bool =
while true:
if sameTrees(obj, n): return true
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenDeref, nkDerefExpr:
of PathKinds0, PathKinds1:
n = n[0]
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
else:
break
return false
proc useInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == use
if ins.sym != nil and loc.kind == nkSym:
result = ins.sym == loc.sym
else:
result = ins.n == loc or sameTrees(ins.n, loc)
if not result:
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc) or aliases(loc, ins.n)
result = sameTrees(ins.n, loc) or
ins.n.aliases(loc) or loc.aliases(ins.n)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
proc defInstrTargets*(ins: Instr; loc: PNode): bool =
assert ins.kind == def
if ins.sym != nil and loc.kind == nkSym:
result = ins.sym == loc.sym
else:
result = ins.n == loc or sameTrees(ins.n, loc)
if not result:
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
# use x.f; question: does it affect the full 'x'? No.
# use x; question does it affect 'x.f'? Yes.
result = aliases(ins.n, loc)
result = sameTrees(ins.n, loc) or ins.n.aliases(loc)
# We can come here if loc is 'x.f' and ins.n is 'x' or the other way round.
# def x.f; question: does it affect the full 'x'? No.
# def x; question: does it affect the 'x.f'? Yes.
proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
var n = orig
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv:
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
n = n[0]
of nkBracketExpr:
# in a[i] the 'i' must be known
if n.len > 1 and n[1].kind in {nkCharLit..nkUInt64Lit}:
n = n[0]
else:
return false
of nkHiddenDeref, nkDerefExpr:
# We "own" sinkparam[].loc but not ourVar[].location as it is a nasty
# pointer indirection.
n = n[0]
return n.kind == nkSym and n.sym.owner == owner and (isSinkParam(n.sym) or
n.sym.typ.skipTypes(abstractInst-{tyOwned}).kind in {tyOwned})
of nkBracketExpr:
let x = n[0]
if x.typ != nil and x.typ.skipTypes(abstractInst).kind == tyTuple:
n = x
else:
break
else:
break
# XXX Allow closure deref operations here if we know
@@ -685,18 +661,29 @@ proc isAnalysableFieldAccess*(orig: PNode; owner: PSym): bool =
# lower level C++ optimizer to specialize this code.
proc genDef(c: var Con; n: PNode) =
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: n, kind: def, sym: n.sym)
elif isAnalysableFieldAccess(n, c.owner):
c.code.add Instr(n: n, kind: def, sym: nil)
var m = n
# XXX do something about this duplicated logic here.
while true:
case m.kind
of nkDotExpr, nkCheckedFieldExpr, nkHiddenSubConv, nkHiddenStdConv,
nkObjDownConv, nkObjUpConv, nkHiddenAddr, nkAddr:
m = m[0]
of nkBracketExpr:
gen(c, m[1])
m = m[0]
of nkHiddenDeref, nkDerefExpr:
m = m[0]
else:
break
proc canRaise(fn: PNode): bool =
const magicsThatCanRaise = {
mNone, mSlurp, mStaticExec, mParseExprToAst, mParseStmtToAst}
if fn.kind == nkSym and fn.sym.magic notin magicsThatCanRaise:
result = false
if n.kind == nkSym and n.sym.kind in InterestingSyms:
c.code.add Instr(n: n, kind: def)
elif isAnalysableFieldAccess(n, c.owner):
c.code.add Instr(n: n, kind: def)
else:
result = true
# bug #13314: An assignment to t5.w = -5 is a usage of 't5'
# we still need to gather the use information:
gen(c, n)
proc genCall(c: var Con; n: PNode) =
gen(c, n[0])
@@ -706,13 +693,13 @@ proc genCall(c: var Con; n: PNode) =
for i in 1..<n.len:
gen(c, n[i])
when false:
if t != nil and i < t.len and t.sons[i].kind == tyVar:
if t != nil and i < t.len and t[i].kind == tyVar:
# This is wrong! Pass by var is a 'might def', not a 'must def'
# like the other defs we emit. This is not good enough for a move
# optimizer.
genDef(c, n[i])
# every call can potentially raise:
if c.inTryStmt > 0 and canRaise(n[0]):
if c.inTryStmt > 0 and canRaiseConservative(n[0]):
# we generate the instruction sequence:
# fork lab1
# goto exceptionHandler (except or finally)
@@ -739,23 +726,23 @@ proc genVarSection(c: var Con; n: PNode) =
discard
elif a.kind == nkVarTuple:
gen(c, a.lastSon)
for i in 0 .. a.len-3: genDef(c, a[i])
for i in 0..<a.len-2: genDef(c, a[i])
else:
gen(c, a.lastSon)
if a.lastSon.kind != nkEmpty:
genDef(c, a.sons[0])
genDef(c, a[0])
proc gen(c: var Con; n: PNode) =
case n.kind
of nkSym: genUse(c, n)
of nkCallKinds:
if n.sons[0].kind == nkSym:
let s = n.sons[0].sym
if n[0].kind == nkSym:
let s = n[0].sym
if s.magic != mNone:
genMagic(c, n, s.magic)
else:
genCall(c, n)
if sfNoReturn in n.sons[0].sym.flags:
if sfNoReturn in n[0].sym.flags:
genNoReturn(c, n)
else:
genCall(c, n)
@@ -771,7 +758,7 @@ proc gen(c: var Con; n: PNode) =
of nkIfStmt, nkIfExpr: genIf(c, n)
of nkWhenStmt:
# This is "when nimvm" node. Chose the first branch.
gen(c, n.sons[0].sons[1])
gen(c, n[0][1])
of nkCaseStmt: genCase(c, n)
of nkWhileStmt: genWhile(c, n)
of nkBlockExpr, nkBlockStmt: genBlock(c, n)
@@ -783,10 +770,10 @@ proc gen(c: var Con; n: PNode) =
nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr, nkYieldStmt:
for x in n: gen(c, x)
of nkPragmaBlock: gen(c, n.lastSon)
of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n.sons[0])
of nkDiscardStmt, nkObjDownConv, nkObjUpConv: gen(c, n[0])
of nkConv, nkExprColonExpr, nkExprEqExpr, nkCast, nkHiddenSubConv, nkHiddenStdConv:
gen(c, n.sons[1])
of nkStringToCString, nkCStringToString: gen(c, n.sons[0])
gen(c, n[1])
of nkStringToCString, nkCStringToString: gen(c, n[0])
of nkVarSection, nkLetSection: genVarSection(c, n)
of nkDefer:
doAssert false, "dfa construction pass requires the elimination of 'defer'"

View File

@@ -21,11 +21,13 @@ import
const
exportSection = skField
htmldocsDir = RelativeDir"htmldocs"
type
TSections = array[TSymKind, Rope]
TDocumentor = object of rstgen.RstGenerator
modDesc: Rope # module description
module: PSym
modDeprecationMsg: Rope
toc, section: TSections
indexValFilename: string
@@ -42,20 +44,65 @@ type
destFile*: AbsoluteFile
thisDir*: AbsoluteDir
examples: string
wroteCss*: bool
PDoc* = ref TDocumentor ## Alias to type less.
proc nativeToUnix(path: string): string =
doAssert not path.isAbsolute # absolute files need more care for the drive
when DirSep == '\\':
result = replace(path, '\\', '/')
else: result = path
proc docOutDir(conf: ConfigRef, subdir: RelativeDir = RelativeDir""): AbsoluteDir =
if not conf.outDir.isEmpty: conf.outDir else: conf.projectPath / subdir
proc presentationPath*(conf: ConfigRef, file: AbsoluteFile, isTitle = false): RelativeFile =
## returns a relative file that will be appended to outDir
let file2 = $file
template bail() =
result = relativeTo(file, conf.projectPath)
proc nimbleDir(): AbsoluteDir =
getNimbleFile(conf, file2).parentDir.AbsoluteDir
case conf.docRoot:
of "@default": # using `@` instead of `$` to avoid shell quoting complications
result = getRelativePathFromConfigPath(conf, file)
let dir = nimbleDir()
if not dir.isEmpty:
let result2 = relativeTo(file, dir)
if not result2.isEmpty and (result.isEmpty or result2.string.len < result.string.len):
result = result2
if result.isEmpty: bail()
of "@pkg":
let dir = nimbleDir()
if dir.isEmpty: bail()
else: result = relativeTo(file, dir)
of "@path":
result = getRelativePathFromConfigPath(conf, file)
if result.isEmpty: bail()
elif conf.docRoot.len > 0:
doAssert conf.docRoot.isAbsolute, conf.docRoot # or globalError
doAssert conf.docRoot.existsDir, conf.docRoot
result = relativeTo(file, conf.docRoot.AbsoluteDir)
else:
bail()
if isTitle:
result = result.string.nativeToUnix.RelativeFile
else:
result = result.string.replace("..", "@@").RelativeFile ## refs #13223
doAssert not result.isEmpty
proc whichType(d: PDoc; n: PNode): PSym =
if n.kind == nkSym:
if d.types.strTableContains(n.sym):
result = n.sym
else:
for i in 0..<safeLen(n):
for i in 0..<n.safeLen:
let x = whichType(d, n[i])
if x != nil: return x
proc attachToType(d: PDoc; p: PSym): PSym =
let params = p.ast.sons[paramsPos]
let params = p.ast[paramsPos]
template check(i) =
result = whichType(d, params[i])
if result != nil: return result
@@ -68,7 +115,7 @@ proc attachToType(d: PDoc; p: PSym): PSym =
template declareClosures =
proc compilerMsgHandler(filename: string, line, col: int,
msgKind: rst.MsgKind, arg: string) {.procvar, gcsafe.} =
msgKind: rst.MsgKind, arg: string) {.gcsafe.} =
# translate msg kind:
var k: TMsgKind
case msgKind
@@ -85,7 +132,7 @@ template declareClosures =
{.gcsafe.}:
globalError(conf, newLineInfo(conf, AbsoluteFile filename, line, col), k, arg)
proc docgenFindFile(s: string): string {.procvar, gcsafe.} =
proc docgenFindFile(s: string): string {.gcsafe.} =
result = options.findFile(conf, s).string
if result.len == 0:
result = getCurrentDir() / s
@@ -102,12 +149,11 @@ proc parseRst(text, filename: string,
proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
ext: string, dir: RelativeDir; guessTarget: bool): AbsoluteFile =
if optWholeProject in conf.globalOptions:
let d = if conf.outDir.isEmpty: conf.projectPath / dir else: conf.outDir
let d = conf.docOutDir(dir)
createDir(d)
result = d / changeFileExt(filename, ext)
elif guessTarget:
let d = if not conf.outDir.isEmpty: conf.outDir
else: conf.projectPath
let d = conf.docOutDir
createDir(d)
result = d / changeFileExt(filename, ext)
elif not conf.outFile.isEmpty:
@@ -115,9 +161,10 @@ proc getOutFile2(conf: ConfigRef; filename: RelativeFile,
else:
result = getOutFile(conf, filename, ext)
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt): PDoc =
proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef, outExt: string = HtmlExt, module: PSym = nil): PDoc =
declareClosures()
new(result)
result.module = module
result.conf = conf
result.cache = cache
initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex),
@@ -146,10 +193,10 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
initStrTable result.types
result.onTestSnippet =
proc (gen: var RstGenerator; filename, cmd: string; status: int; content: string) =
inc(gen.id)
var d = TDocumentor(gen)
var outp: AbsoluteFile
if filename.len == 0:
inc(d.id)
let nameOnly = splitFile(d.filename).name
outp = getNimcacheDir(conf) / RelativeDir(nameOnly) /
RelativeFile(nameOnly & "_snippet_" & $d.id & ".nim")
@@ -171,16 +218,16 @@ proc newDocumentor*(filename: AbsoluteFile; cache: IdentCache; conf: ConfigRef,
if execShellCmd(c2) != status:
rawMessage(conf, errGenerated, "executing of external program failed: " & c2)
result.emitted = initIntSet()
result.destFile = getOutFile2(conf, relativeTo(filename, conf.projectPath),
outExt, RelativeDir"htmldocs", false)
result.destFile = getOutFile2(conf, presentationPath(conf, filename),
outExt, htmldocsDir, false)
result.thisDir = result.destFile.splitFile.dir
template dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) =
if conf.cmd != cmdRst2tex: addf(dest, xml, args)
else: addf(dest, tex, args)
if conf.cmd != cmdRst2tex: dest.addf(xml, args)
else: dest.addf(tex, args)
proc getVarIdx(varnames: openArray[string], id: string): int =
for i in 0 .. high(varnames):
for i in 0..high(varnames):
if cmpIgnoreStyle(varnames[i], id) == 0:
return i
result = -1
@@ -189,44 +236,43 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
varnames: openArray[string],
varvalues: openArray[Rope]): Rope =
var i = 0
var L = len(frmt)
result = nil
var num = 0
while i < L:
while i < frmt.len:
if frmt[i] == '$':
inc(i) # skip '$'
case frmt[i]
of '#':
add(result, varvalues[num])
result.add(varvalues[num])
inc(num)
inc(i)
of '$':
add(result, "$")
result.add("$")
inc(i)
of '0'..'9':
var j = 0
while true:
j = (j * 10) + ord(frmt[i]) - ord('0')
inc(i)
if (i > L + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
if (i > frmt.len + 0 - 1) or not (frmt[i] in {'0'..'9'}): break
if j > high(varvalues) + 1:
rawMessage(conf, errGenerated, "Invalid format string; too many $s: " & frmt)
num = j
add(result, varvalues[j - 1])
result.add(varvalues[j - 1])
of 'A'..'Z', 'a'..'z', '\x80'..'\xFF':
var id = ""
while true:
add(id, frmt[i])
id.add(frmt[i])
inc(i)
if not (frmt[i] in {'A'..'Z', '_', 'a'..'z', '\x80'..'\xFF'}): break
var idx = getVarIdx(varnames, id)
if idx >= 0: add(result, varvalues[idx])
if idx >= 0: result.add(varvalues[idx])
else: rawMessage(conf, errGenerated, "unknown substition variable: " & id)
of '{':
var id = ""
inc(i)
while i < frmt.len and frmt[i] != '}':
add(id, frmt[i])
id.add(frmt[i])
inc(i)
if i >= frmt.len:
rawMessage(conf, errGenerated, "expected closing '}'")
@@ -234,15 +280,15 @@ proc ropeFormatNamedVars(conf: ConfigRef; frmt: FormatStr,
inc(i) # skip }
# search for the variable:
let idx = getVarIdx(varnames, id)
if idx >= 0: add(result, varvalues[idx])
if idx >= 0: result.add(varvalues[idx])
else: rawMessage(conf, errGenerated, "unknown substition variable: " & id)
else:
add(result, "$")
result.add("$")
var start = i
while i < L:
while i < frmt.len:
if frmt[i] != '$': inc(i)
else: break
if i - 1 >= start: add(result, substr(frmt, start, i - 1))
if i - 1 >= start: result.add(substr(frmt, start, i - 1))
proc genComment(d: PDoc, n: PNode): string =
result = ""
@@ -259,8 +305,8 @@ proc genRecCommentAux(d: PDoc, n: PNode): Rope =
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef,
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn, nkHiddenStdConv}:
# notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
for i in 0 ..< len(n):
result = genRecCommentAux(d, n.sons[i])
for i in 0..<n.len:
result = genRecCommentAux(d, n[i])
if result != nil: return
else:
when defined(nimNoNilSeqs): n.comment = ""
@@ -287,19 +333,18 @@ proc getPlainDocstring(n: PNode): string =
if startsWith(n.comment, "##"):
result = n.comment
if result.len < 1:
for i in 0 ..< safeLen(n):
result = getPlainDocstring(n.sons[i])
for i in 0..<n.safeLen:
result = getPlainDocstring(n[i])
if result.len > 0: return
proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
result = module.kind == skModule and module.owner != nil and
module.owner.id == conf.mainPackageId
result = module.kind == skModule and module.getnimblePkgId == conf.mainPackageId
proc externalDep(d: PDoc; module: PSym): string =
if optWholeProject in d.conf.globalOptions:
if optWholeProject in d.conf.globalOptions or d.conf.docRoot.len > 0:
let full = AbsoluteFile toFullPath(d.conf, FileIndex module.position)
let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath), HtmlExt,
RelativeDir"htmldocs", sfMainModule notin module.flags)
let tmp = getOutFile2(d.conf, presentationPath(d.conf, full), HtmlExt,
htmldocsDir, sfMainModule notin module.flags)
result = relativeTo(tmp, d.thisDir, '/').string
else:
result = extractFilename toFullPath(d.conf, FileIndex module.position)
@@ -358,7 +403,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
dispA(d.conf, result, "<span class=\"Identifier\">$1</span>",
"\\spanIdentifier{$1}", [rope(esc(d.target, literal))])
of tkSpaces, tkInvalid:
add(result, literal)
result.add(literal)
of tkCurlyDotLe:
dispA(d.conf, result, "<span>" & # This span is required for the JS to work properly
"""<span class="Other">{</span><span class="Other pragmadots">...</span><span class="Other">}</span>
@@ -406,6 +451,7 @@ proc runAllExamples(d: PDoc) =
elif isDefined(d.conf, "objc"): "objc"
else: "c"
if os.execShellCmd(os.getAppFilename() & " " & backend &
" --warning[UnusedImport]:off" &
" --path:" & quoteShell(d.conf.projectPath) &
" --nimcache:" & quoteShell(outputDir) &
" -r " & quoteShell(outp)) != 0:
@@ -415,12 +461,6 @@ proc runAllExamples(d: PDoc) =
rawMessage(d.conf, hintSuccess, ["runnableExamples: " & outp.string])
removeFile(outp.changeFileExt(ExeExt))
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
proc prepareExamples(d: PDoc; n: PNode) =
var docComment = newTree(nkCommentStmt)
@@ -430,12 +470,20 @@ proc prepareExamples(d: PDoc; n: PNode) =
docComment,
newTree(nkImportStmt, newStrNode(nkStrLit, d.filename)))
runnableExamples.info = n.info
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
for a in n.lastSon: runnableExamples.add a
testExample(d, runnableExamples)
when false:
proc extractImports(n: PNode; result: PNode) =
if n.kind in {nkImportStmt, nkImportExceptStmt, nkFromStmt}:
result.add copyTree(n)
n.kind = nkEmpty
return
for i in 0..<n.safeLen: extractImports(n[i], result)
let imports = newTree(nkStmtList)
var savedLastSon = copyTree n.lastSon
extractImports(savedLastSon, imports)
for imp in imports: runnableExamples.add imp
runnableExamples.add newTree(nkBlockStmt, newNode(nkEmpty), copyTree savedLastSon)
proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
if n.info.fileIndex != orig.info.fileIndex: return
@@ -462,7 +510,7 @@ proc getAllRunnableExamplesRec(d: PDoc; n, orig: PNode; dest: var Rope) =
nodeToHighlightedHtml(d, b, dest, {}, nil)
dest.add(d.config.getOrDefault"doc.listing_end" % id)
else: discard
for i in 0 ..< n.safeLen:
for i in 0..<n.safeLen:
getAllRunnableExamplesRec(d, n[i], orig, dest)
proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
@@ -471,8 +519,8 @@ proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) =
proc isVisible(d: PDoc; n: PNode): bool =
result = false
if n.kind == nkPostfix:
if n.len == 2 and n.sons[0].kind == nkIdent:
var v = n.sons[0].ident
if n.len == 2 and n[0].kind == nkIdent:
var v = n[0].ident
result = v.id == ord(wStar) or v.id == ord(wMinus)
elif n.kind == nkSym:
# we cannot generate code for forwarded symbols here as we have no
@@ -485,12 +533,12 @@ proc isVisible(d: PDoc; n: PNode): bool =
if result and containsOrIncl(d.emitted, n.sym.id):
result = false
elif n.kind == nkPragmaExpr:
result = isVisible(d, n.sons[0])
result = isVisible(d, n[0])
proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
case n.kind
of nkPostfix: result = getName(d, n.sons[1], splitAfter)
of nkPragmaExpr: result = getName(d, n.sons[0], splitAfter)
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 nkAccQuoted:
@@ -504,8 +552,8 @@ proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
case n.kind
of nkPostfix: result = getNameIdent(cache, n.sons[1])
of nkPragmaExpr: result = getNameIdent(cache, n.sons[0])
of nkPostfix: result = getNameIdent(cache, n[1])
of nkPragmaExpr: result = getNameIdent(cache, n[0])
of nkSym: result = n.sym.name
of nkIdent: result = n.ident
of nkAccQuoted:
@@ -519,13 +567,13 @@ proc getNameIdent(cache: IdentCache; n: PNode): PIdent =
proc getRstName(n: PNode): PRstNode =
case n.kind
of nkPostfix: result = getRstName(n.sons[1])
of nkPragmaExpr: result = getRstName(n.sons[0])
of nkPostfix: result = getRstName(n[1])
of nkPragmaExpr: result = getRstName(n[0])
of nkSym: result = newRstNode(rnLeaf, n.sym.renderDefinitionName)
of nkIdent: result = newRstNode(rnLeaf, n.ident.s)
of nkAccQuoted:
result = getRstName(n.sons[0])
for i in 1 ..< n.len: result.text.add(getRstName(n[i]).text)
result = getRstName(n[0])
for i in 1..<n.len: result.text.add(getRstName(n[i]).text)
of nkOpenSymChoice, nkClosedSymChoice:
result = getRstName(n[0])
else:
@@ -570,7 +618,7 @@ proc complexName(k: TSymKind, n: PNode, baseName: string): string =
of skTemplate: result.add(".t")
of skConverter: result.add(".c")
else: discard
if len(n) > paramsPos and n[paramsPos].kind == nkFormalParams:
if n.len > paramsPos and n[paramsPos].kind == nkFormalParams:
let params = renderParamTypes(n[paramsPos])
if params.len > 0:
result.add(defaultParamSeparator)
@@ -589,7 +637,7 @@ proc docstringSummary(rstText: string): string =
##
## Most docstrings will contain a one liner summary, so stripping at the
## first newline is usually fine. If after that the content is still too big,
## it is stripped at the first comma, colon or dot, usual english sentence
## it is stripped at the first comma, colon or dot, usual English sentence
## separators.
##
## No guarantees are made on the size of the output, but it should be small.
@@ -628,8 +676,12 @@ proc genDeprecationMsg(d: PDoc, n: PNode): Rope =
else:
doAssert false
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
if not isVisible(d, nameNode): return
type DocFlags = enum
kDefault
kForceExport
proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags) =
if (docFlags != kForceExport) and not isVisible(d, nameNode): return
let
name = getName(d, nameNode)
nameRope = name.rope
@@ -650,8 +702,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
plainName.add(literal)
var pragmaNode: PNode = nil
if n.isCallable and n.sons[pragmasPos].kind != nkEmpty:
pragmaNode = findPragma(n.sons[pragmasPos], wDeprecated)
if n.isCallable and n[pragmasPos].kind != nkEmpty:
pragmaNode = findPragma(n[pragmasPos], wDeprecated)
inc(d.id)
let
@@ -677,7 +729,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
let cwd = canonicalizePath(d.conf, getCurrentDir())
var path = toFullPath(d.conf, n.info)
if path.startsWith(cwd):
path = path[cwd.len+1 .. ^1].replace('\\', '/')
path = path[cwd.len+1..^1].replace('\\', '/')
let gitUrl = getConfigVar(d.conf, "git.url")
if gitUrl.len > 0:
let defaultBranch =
@@ -689,7 +741,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
["path", "line", "url", "commit", "devel"], [rope path.string,
rope($n.info.line), rope gitUrl, rope commit, rope develBranch])])
add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
d.section[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "seeSrc", "deprecationMsg"],
[nameRope, result, comm, itemIDRope, plainNameRope, plainSymbolRope,
@@ -712,7 +764,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
setIndexTerm(d[], external, symbolOrId, plain, nameNode.sym.name.s & '.' & plain,
xmltree.escape(getPlainDocstring(e).docstringSummary))
add(d.toc[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
d.toc[k].add(ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item.toc"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",
"itemSymOrID", "itemSymEnc", "itemSymOrIDEnc", "attype"],
[rope(getName(d, nameNode, d.splitAfter)), result, comm,
@@ -744,6 +796,35 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
result["description"] = %comm
if r.buf.len > 0:
result["code"] = %r.buf
if k in routineKinds:
result["signature"] = newJObject()
if n[paramsPos][0].kind != nkEmpty:
result["signature"]["return"] = %($n[paramsPos][0])
if n[paramsPos].len > 1:
result["signature"]["arguments"] = newJArray()
for paramIdx in 1 ..< n[paramsPos].len:
for identIdx in 0 ..< n[paramsPos][paramIdx].len - 2:
let
paramName = $n[paramsPos][paramIdx][identIdx]
paramType = $n[paramsPos][paramIdx][^2]
if n[paramsPos][paramIdx][^1].kind != nkEmpty:
let paramDefault = $n[paramsPos][paramIdx][^1]
result["signature"]["arguments"].add %{"name": %paramName, "type": %paramType, "default": %paramDefault}
else:
result["signature"]["arguments"].add %{"name": %paramName, "type": %paramType}
if n[pragmasPos].kind != nkEmpty:
result["signature"]["pragmas"] = newJArray()
for pragma in n[pragmasPos]:
result["signature"]["pragmas"].add %($pragma)
if n[genericParamsPos].kind != nkEmpty:
result["signature"]["genericParams"] = newJArray()
for genericParam in n[genericParamsPos]:
var param = %{"name": %($genericParam)}
if genericParam.sym.typ.sons.len > 0:
param["types"] = newJArray()
for kind in genericParam.sym.typ.sons:
param["types"].add %($kind)
result["signature"]["genericParams"].add param
proc checkForFalse(n: PNode): bool =
result = n.kind == nkIdent and cmpIgnoreStyle(n.ident.s, "false") == 0
@@ -758,11 +839,11 @@ proc traceDeps(d: PDoc, it: PNode) =
a.add dir
a.add sep # dummy entry, replaced in the loop
for x in it[2]:
a.sons[2] = x
a[2] = x
traceDeps(d, a)
elif it.kind == nkSym and belongsToPackage(d.conf, it.sym):
let external = externalDep(d, it.sym)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
@@ -772,7 +853,7 @@ proc exportSym(d: PDoc; s: PSym) =
const k = exportSection
if s.kind == skModule and belongsToPackage(d.conf, s):
let external = externalDep(d, s)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
dispA(d.conf, d.section[k],
"<a class=\"reference external\" href=\"$2\">$1</a>",
"$1", [rope esc(d.target, changeFileExt(external, "")),
@@ -781,7 +862,7 @@ proc exportSym(d: PDoc; s: PSym) =
let module = originatingModule(s)
if belongsToPackage(d.conf, module):
let external = externalDep(d, module)
if d.section[k] != nil: add(d.section[k], ", ")
if d.section[k] != nil: d.section[k].add(", ")
# XXX proper anchor generation here
dispA(d.conf, d.section[k],
"<a href=\"$2#$1\"><span class=\"Identifier\">$1</span></a>",
@@ -789,37 +870,37 @@ proc exportSym(d: PDoc; s: PSym) =
rope changeFileExt(external, "html")])
proc documentNewEffect(cache: IdentCache; n: PNode): PNode =
let s = n.sons[namePos].sym
let s = n[namePos].sym
if tfReturnsNew in s.typ.flags:
result = newIdentNode(getIdent(cache, "new"), n.info)
proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, idx: int): PNode =
let spec = effectSpec(x, effectType)
if isNil(spec):
let s = n.sons[namePos].sym
let s = n[namePos].sym
let actual = s.typ.n.sons[0]
let actual = s.typ.n[0]
if actual.len != effectListLen: return
let real = actual.sons[idx]
let real = actual[idx]
# warning: hack ahead:
var effects = newNodeI(nkBracket, n.info, real.len)
for i in 0 ..< real.len:
for i in 0..<real.len:
var t = typeToString(real[i].typ)
if t.startsWith("ref "): t = substr(t, 4)
effects.sons[i] = newIdentNode(getIdent(cache, t), n.info)
effects[i] = newIdentNode(getIdent(cache, t), n.info)
# set the type so that the following analysis doesn't screw up:
effects.sons[i].typ = real[i].typ
effects[i].typ = real[i].typ
result = newNode(nkExprColonExpr, n.info, @[
newIdentNode(getIdent(cache, specialWords[effectType]), n.info), effects])
proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName: string): PNode =
let s = n.sons[namePos].sym
let s = n[namePos].sym
let params = s.typ.n
var effects = newNodeI(nkBracket, n.info)
for i in 1 ..< params.len:
for i in 1..<params.len:
if params[i].kind == nkSym and flag in params[i].sym.flags:
effects.add params[i]
@@ -828,8 +909,8 @@ proc documentWriteEffect(cache: IdentCache; n: PNode; flag: TSymFlag; pragmaName
newIdentNode(getIdent(cache, pragmaName), n.info), effects])
proc documentRaises*(cache: IdentCache; n: PNode) =
if n.sons[namePos].kind != nkSym: return
let pragmas = n.sons[pragmasPos]
if n[namePos].kind != nkSym: return
let pragmas = n[pragmasPos]
let p1 = documentEffect(cache, n, pragmas, wRaises, exceptionEffects)
let p2 = documentEffect(cache, n, pragmas, wTags, tagEffects)
let p3 = documentWriteEffect(cache, n, sfWrittenTo, "writes")
@@ -838,59 +919,65 @@ proc documentRaises*(cache: IdentCache; n: PNode) =
if p1 != nil or p2 != nil or p3 != nil or p4 != nil or p5 != nil:
if pragmas.kind == nkEmpty:
n.sons[pragmasPos] = newNodeI(nkPragma, n.info)
if p1 != nil: n.sons[pragmasPos].add p1
if p2 != nil: n.sons[pragmasPos].add p2
if p3 != nil: n.sons[pragmasPos].add p3
if p4 != nil: n.sons[pragmasPos].add p4
if p5 != nil: n.sons[pragmasPos].add p5
n[pragmasPos] = newNodeI(nkPragma, n.info)
if p1 != nil: n[pragmasPos].add p1
if p2 != nil: n[pragmasPos].add p2
if p3 != nil: n[pragmasPos].add p3
if p4 != nil: n[pragmasPos].add p4
if p5 != nil: n[pragmasPos].add p5
proc generateDoc*(d: PDoc, n, orig: PNode) =
proc generateDoc*(d: PDoc, n, orig: PNode, docFlags: DocFlags = kDefault) =
template genItemAux(skind) =
genItem(d, n, n[namePos], skind, docFlags)
case n.kind
of nkPragma:
let pragmaNode = findPragma(n, wDeprecated)
add(d.modDeprecationMsg, genDeprecationMsg(d, pragmaNode))
of nkCommentStmt: add(d.modDesc, genComment(d, n))
d.modDeprecationMsg.add(genDeprecationMsg(d, pragmaNode))
of nkCommentStmt: d.modDesc.add(genComment(d, n))
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skProc)
genItemAux(skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skFunc)
genItemAux(skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skMethod)
genItemAux(skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skIterator)
of nkMacroDef: genItem(d, n, n.sons[namePos], skMacro)
of nkTemplateDef: genItem(d, n, n.sons[namePos], skTemplate)
genItemAux(skIterator)
of nkMacroDef: genItemAux(skMacro)
of nkTemplateDef: genItemAux(skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
genItem(d, n, n.sons[namePos], skConverter)
genItemAux(skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
genItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
genItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)), docFlags)
of nkStmtList:
for i in 0 ..< sonsLen(n): generateDoc(d, n.sons[i], orig)
for i in 0..<n.len: generateDoc(d, n[i], orig)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateDoc(d, lastSon(n.sons[0]), orig)
if not checkForFalse(n[0][0]):
generateDoc(d, lastSon(n[0]), orig)
of nkImportStmt:
for it in n: traceDeps(d, it)
of nkExportStmt:
for it in n:
if it.kind == nkSym: exportSym(d, it.sym)
if it.kind == nkSym:
if d.module != nil and d.module == it.sym.owner:
generateDoc(d, it.sym.ast, orig, kForceExport)
else:
exportSym(d, it.sym)
of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n[0])
of nkCallKinds:
var comm: Rope = nil
getAllRunnableExamples(d, n, comm)
if comm != nil: add(d.modDesc, comm)
if comm != nil: d.modDesc.add(comm)
else: discard
proc add(d: PDoc; j: JsonNode) =
@@ -902,39 +989,39 @@ proc generateJson*(d: PDoc, n: PNode, includeComments: bool = true) =
if includeComments:
d.add %*{"comment": genComment(d, n)}
else:
add(d.modDesc, genComment(d, n))
d.modDesc.add(genComment(d, n))
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skProc)
d.add genJsonItem(d, n, n[namePos], skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skFunc)
d.add genJsonItem(d, n, n[namePos], skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skMethod)
d.add genJsonItem(d, n, n[namePos], skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skIterator)
d.add genJsonItem(d, n, n[namePos], skIterator)
of nkMacroDef:
d.add genJsonItem(d, n, n.sons[namePos], skMacro)
d.add genJsonItem(d, n, n[namePos], skMacro)
of nkTemplateDef:
d.add genJsonItem(d, n, n.sons[namePos], skTemplate)
d.add genJsonItem(d, n, n[namePos], skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
d.add genJsonItem(d, n, n.sons[namePos], skConverter)
d.add genJsonItem(d, n, n[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
d.add genJsonItem(d, n.sons[i], n.sons[i].sons[0],
d.add genJsonItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
generateJson(d, n.sons[i], includeComments)
for i in 0..<n.len:
generateJson(d, n[i], includeComments)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateJson(d, lastSon(n.sons[0]), includeComments)
if not checkForFalse(n[0][0]):
generateJson(d, lastSon(n[0]), includeComments)
else: discard
proc genTagsItem(d: PDoc, n, nameNode: PNode, k: TSymKind): string =
@@ -948,36 +1035,36 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
r.add stripped
of nkProcDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skProc)
r.add genTagsItem(d, n, n[namePos], skProc)
of nkFuncDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skFunc)
r.add genTagsItem(d, n, n[namePos], skFunc)
of nkMethodDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skMethod)
r.add genTagsItem(d, n, n[namePos], skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skIterator)
r.add genTagsItem(d, n, n[namePos], skIterator)
of nkMacroDef:
r.add genTagsItem(d, n, n.sons[namePos], skMacro)
r.add genTagsItem(d, n, n[namePos], skMacro)
of nkTemplateDef:
r.add genTagsItem(d, n, n.sons[namePos], skTemplate)
r.add genTagsItem(d, n, n[namePos], skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(d.cache, n)
r.add genTagsItem(d, n, n.sons[namePos], skConverter)
r.add genTagsItem(d, n, n[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in 0 ..< sonsLen(n):
if n.sons[i].kind != nkCommentStmt:
for i in 0..<n.len:
if n[i].kind != nkCommentStmt:
# order is always 'type var let const':
r.add genTagsItem(d, n.sons[i], n.sons[i].sons[0],
r.add genTagsItem(d, n[i], n[i][0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
for i in 0 ..< sonsLen(n):
generateTags(d, n.sons[i], r)
for i in 0..<n.len:
generateTags(d, n[i], r)
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]):
generateTags(d, lastSon(n.sons[0]), r)
if not checkForFalse(n[0][0]):
generateTags(d, lastSon(n[0]), r)
else: discard
proc genSection(d: PDoc, kind: TSymKind) =
@@ -994,6 +1081,12 @@ proc genSection(d: PDoc, kind: TSymKind) =
"sectionid", "sectionTitle", "sectionTitleID", "content"], [
ord(kind).rope, title, rope(ord(kind) + 50), d.toc[kind]])
const nimdocOutCss = "nimdoc.out.css"
# `out` to make it easier to use with gitignore in user's repos
proc cssHref(outDir: AbsoluteDir, destFile: AbsoluteFile): Rope =
rope($relativeTo(outDir / nimdocOutCss.RelativeFile, destFile.splitFile().dir, '/'))
proc genOutFile(d: PDoc): Rope =
var
code, content: Rope
@@ -1002,21 +1095,22 @@ proc genOutFile(d: PDoc): Rope =
var tmp = ""
renderTocEntries(d[], j, 1, tmp)
var toc = tmp.rope
for i in low(TSymKind) .. high(TSymKind):
for i in low(TSymKind)..high(TSymKind):
genSection(d, i)
add(toc, d.toc[i])
toc.add(d.toc[i])
if toc != nil:
toc = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.toc"), ["content"], [toc])
for i in low(TSymKind) .. high(TSymKind): add(code, d.section[i])
for i in low(TSymKind)..high(TSymKind): code.add(d.section[i])
# 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.filename).relativeTo(d.conf.projectPath, '/').changeFileExt(HtmlExt).string
let external = presentationPath(d.conf, AbsoluteFile d.filename).changeFileExt(HtmlExt).string.nativeToUnix
setIndexTerm(d[], external, "", title)
else:
# Modules get an automatic title for the HTML, but no entry in the index.
title = extractFilename(changeFileExt(d.filename, ""))
# better than `extractFilename(changeFileExt(d.filename, ""))` as it disambiguates dups
title = $presentationPath(d.conf, AbsoluteFile d.filename, isTitle = true).changeFileExt("")
let bodyname = if d.hasToc and not d.isPureRst: "doc.body_toc_group"
elif d.hasToc: "doc.body_toc"
@@ -1027,25 +1121,27 @@ proc genOutFile(d: PDoc): Rope =
rope(getClockStr()), code, d.modDeprecationMsg])
if optCompileOnly notin d.conf.globalOptions:
# XXX what is this hack doing here? 'optCompileOnly' means raw output!?
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics", "deprecationMsg"],
[title.rope, toc, d.modDesc, rope(getDateStr()),
rope(getClockStr()), content, d.meta[metaAuthor].rope,
d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
[cssHref(d.conf.outDir, d.destFile), title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()),
content, d.meta[metaAuthor].rope, d.meta[metaVersion].rope, d.analytics.rope, d.modDeprecationMsg])
else:
code = content
result = code
proc generateIndex*(d: PDoc) =
if optGenIndex in d.conf.globalOptions:
let dir = if not d.conf.outDir.isEmpty: d.conf.outDir
else: d.conf.projectPath / RelativeDir"htmldocs"
let dir = d.conf.docOutDir(htmldocsDir)
createDir(dir)
let dest = dir / changeFileExt(relativeTo(AbsoluteFile d.filename,
d.conf.projectPath), IndexExt)
let dest = dir / changeFileExt(presentationPath(d.conf, AbsoluteFile d.filename), IndexExt)
writeIndexFile(d[], dest.string)
proc updateOutfile(d: PDoc, outfile: AbsoluteFile) =
if d.module == nil or sfMainModule in d.module.flags: # nil for eg for commandRst2Html
if d.conf.outDir.isEmpty: d.conf.outDir = d.conf.docOutDir
if d.conf.outFile.isEmpty: d.conf.outFile = outfile.relativeTo(d.conf.outDir)
proc writeOutput*(d: PDoc, useWarning = false) =
runAllExamples(d)
var content = genOutFile(d)
@@ -1053,11 +1149,18 @@ proc writeOutput*(d: PDoc, useWarning = false) =
writeRope(stdout, content)
else:
template outfile: untyped = d.destFile
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, "htmldocs")
createDir(outfile.splitFile.dir)
#let outfile = getOutFile2(d.conf, shortenDir(d.conf, filename), outExt, htmldocsDir)
let dir = outfile.splitFile.dir
createDir(dir)
updateOutfile(d, outfile)
if not writeRope(content, outfile):
rawMessage(d.conf, if useWarning: warnCannotOpenFile else: errCannotOpenFile,
outfile.string)
elif not d.wroteCss:
let cssSource = $d.conf.getPrefixDir() / "doc" / "nimdoc.css"
let cssDest = $dir / nimdocOutCss
copyFile(cssSource, cssDest)
d.wroteCss = true
proc writeOutputJson*(d: PDoc, useWarning = false) =
runAllExamples(d)
@@ -1075,6 +1178,7 @@ proc writeOutputJson*(d: PDoc, useWarning = false) =
if open(f, d.destFile.string, fmWrite):
write(f, $content)
close(f)
updateOutfile(d, d.destFile)
else:
localError(d.conf, newLineInfo(d.conf, AbsoluteFile d.filename, -1, -1),
warnUser, "unable to open file \"" & d.destFile.string &
@@ -1160,12 +1264,17 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
proc commandBuildIndex*(cache: IdentCache, conf: ConfigRef) =
var content = mergeIndexes(conf.projectFull.string).rope
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), ["title",
"tableofcontents", "moduledesc", "date", "time",
var outFile = RelativeFile"theindex"
if conf.outFile != RelativeFile"":
outFile = conf.outFile
let filename = getOutFile(conf, outFile, HtmlExt)
let code = ropeFormatNamedVars(conf, getConfigVar(conf, "doc.file"), [
"nimdoccss", "title", "tableofcontents", "moduledesc", "date", "time",
"content", "author", "version", "analytics"],
["Index".rope, nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
[cssHref(conf.outDir, filename), rope"Index", nil, nil, rope(getDateStr()),
rope(getClockStr()), content, nil, nil, nil])
# no analytics because context is not available
let filename = getOutFile(conf, RelativeFile"theindex", HtmlExt)
if not writeRope(code, filename):
rawMessage(conf, errCannotOpenFile, filename.string)

View File

@@ -11,7 +11,7 @@
# semantic checking.
import
options, ast, msgs, idents, passes, docgen, lineinfos, pathutils
options, ast, msgs, passes, docgen, lineinfos, pathutils
from modulegraphs import ModuleGraph, PPassContext
@@ -22,8 +22,8 @@ type
config: ConfigRef
PGen = ref TGen
template shouldProcess(g): bool =
(g.module.owner.id == g.doc.conf.mainPackageId and optWholeProject in g.doc.conf.globalOptions) or
proc shouldProcess(g: PGen): bool =
(optWholeProject in g.doc.conf.globalOptions and g.module.getnimblePkgId == g.doc.conf.mainPackageId) or
sfMainModule in g.module.flags or g.config.projectMainIdx == g.module.info.fileIndex
template closeImpl(body: untyped) {.dirty.} =
@@ -62,7 +62,7 @@ template myOpenImpl(ext: untyped) {.dirty.} =
g.module = module
g.config = graph.config
var d = newDocumentor(AbsoluteFile toFullPath(graph.config, FileIndex module.position),
graph.cache, graph.config, ext)
graph.cache, graph.config, ext, module)
d.hasToc = true
g.doc = d
result = g

View File

@@ -13,7 +13,7 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
result.typ = newType(tyProc, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
addSon(result.typ.n, newNodeI(nkEffectList, info))
result.typ.n.add newNodeI(nkEffectList, info)
result.typ.addParam dest
@@ -22,7 +22,7 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
caseStmt.add(newSymNode dest)
# copy the branches over, but replace the fields with the for loop body:
for i in 0 ..< t.n.len:
for i in 0..<t.n.len:
assert(t.n[i].kind == nkSym)
var field = t.n[i].sym
let val = if field.ast == nil: field.name.s else: field.ast.strVal
@@ -33,28 +33,35 @@ proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
body.add(caseStmt)
var n = newNodeI(nkProcDef, info, bodyPos+2)
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
n.sons[namePos] = newSymNode(result)
n.sons[paramsPos] = result.typ.n
n.sons[bodyPos] = body
n.sons[resultPos] = newSymNode(res)
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = body
n[resultPos] = newSymNode(res)
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfNeverRaises
proc searchObjCase(obj: PNode; field: PSym): PNode =
proc searchObjCaseImpl(obj: PNode; field: PSym): PNode =
case obj.kind
of nkSym:
result = nil
of nkElse, nkOfBranch:
result = searchObjCase(obj.lastSon, field)
result = searchObjCaseImpl(obj.lastSon, field)
else:
if obj.kind == nkRecCase and obj[0].kind == nkSym and obj[0].sym == field:
result = obj
else:
for x in obj:
result = searchObjCase(x, field)
result = searchObjCaseImpl(x, field)
if result != nil: break
proc searchObjCase(t: PType; field: PSym): PNode =
result = searchObjCaseImpl(t.n, field)
if result == nil and t.len > 0:
result = searchObjCase(t[0].skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field)
doAssert result != nil
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), t.owner, info)
@@ -67,7 +74,7 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
result.typ = newType(tyProc, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
addSon(result.typ.n, newNodeI(nkEffectList, info))
result.typ.n.add newNodeI(nkEffectList, info)
result.typ.addParam dest
@@ -75,12 +82,11 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
var caseStmt = newNodeI(nkCaseStmt, info)
caseStmt.add(newSymNode dest)
let subObj = searchObjCase(t.n, field)
doAssert subObj != nil
for i in 1 ..< subObj.len:
let subObj = searchObjCase(t, field)
for i in 1..<subObj.len:
let ofBranch = subObj[i]
var newBranch = newNodeI(ofBranch.kind, ofBranch.info)
for j in 0..ofBranch.len-2:
for j in 0..<ofBranch.len-1:
newBranch.add ofBranch[j]
newBranch.add newTree(nkStmtList, newTree(nkFastAsgn, newSymNode(res), newIntNode(nkInt8Lit, i)))
@@ -89,10 +95,11 @@ proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGra
body.add(caseStmt)
var n = newNodeI(nkProcDef, info, bodyPos+2)
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
n.sons[namePos] = newSymNode(result)
n.sons[paramsPos] = result.typ.n
n.sons[bodyPos] = body
n.sons[resultPos] = newSymNode(res)
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = body
n[resultPos] = newSymNode(res)
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfNeverRaises

View File

@@ -9,13 +9,16 @@
## This file implements the FFI part of the evaluator for Nim code.
import ast, astalgo, ropes, types, options, tables, dynlib, msgs, os, lineinfos
import ast, types, options, tables, dynlib, msgs, lineinfos
from os import getAppFilename
import pkg/libffi
when defined(windows):
const libcDll = "msvcrt.dll"
elif defined(linux):
const libcDll = "libc.so(.6|.5|)"
elif defined(bsd):
const libcDll = "/lib/libc.so.7"
elif defined(osx):
const libcDll = "/usr/lib/libSystem.dylib"
else:
@@ -27,7 +30,7 @@ var
gDllCache = initTable[string, LibHandle]()
when defined(windows):
var gExeHandle = loadLib(os.getAppFilename())
var gExeHandle = loadLib(getAppFilename())
else:
var gExeHandle = loadLib()
@@ -46,38 +49,35 @@ proc getDll(conf: ConfigRef, cache: var TDllCache; dll: string; info: TLineInfo)
const
nkPtrLit = nkIntLit # hopefully we can get rid of this hack soon
var myerrno {.importc: "errno", header: "<errno.h>".}: cint ## error variable
proc importcSymbol*(conf: ConfigRef, sym: PSym): PNode =
let name = $sym.loc.r
let name = sym.cname # $sym.loc.r would point to internal name
# the AST does not support untyped pointers directly, so we use an nkIntLit
# that contains the address instead:
result = newNodeIT(nkPtrLit, sym.info, sym.typ)
case name
of "stdin": result.intVal = cast[ByteAddress](system.stdin)
of "stdout": result.intVal = cast[ByteAddress](system.stdout)
of "stderr": result.intVal = cast[ByteAddress](system.stderr)
of "vmErrnoWrapper": result.intVal = cast[ByteAddress](myerrno)
else:
when true:
var libPathMsg = ""
let lib = sym.annex
if lib != nil and lib.path.kind notin {nkStrLit..nkTripleStrLit}:
globalError(conf, sym.info, "dynlib needs to be a string lit")
var theAddr: pointer
if (lib.isNil or lib.kind == libHeader) and not gExehandle.isNil:
if (lib.isNil or lib.kind == libHeader) and not gExeHandle.isNil:
libPathMsg = "current exe: " & getAppFilename() & " nor libc: " & libcDll
# first try this exe itself:
theAddr = gExehandle.symAddr(name)
theAddr = gExeHandle.symAddr(name)
# then try libc:
if theAddr.isNil:
let dllhandle = getDll(conf, gDllCache, libcDll, sym.info)
theAddr = dllhandle.symAddr(name)
elif not lib.isNil:
let dll = if lib.kind == libHeader: libcDll else: lib.path.strVal
libPathMsg = dll
let dllhandle = getDll(conf, gDllCache, dll, sym.info)
theAddr = dllhandle.symAddr(name)
if theAddr.isNil: globalError(conf, sym.info, "cannot import: " & sym.name.s)
if theAddr.isNil: globalError(conf, sym.info,
"cannot import symbol: " & name & " from " & libPathMsg)
result.intVal = cast[ByteAddress](theAddr)
proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.TType =
proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.Type =
if t == nil: return addr libffi.type_void
case t.kind
@@ -94,7 +94,7 @@ proc mapType(conf: ConfigRef, t: ast.PType): ptr libffi.TType =
tyTyped, tyTypeDesc, tyProc, tyArray, tyStatic, tyNil:
result = addr libffi.type_pointer
of tyDistinct, tyAlias, tySink:
result = mapType(conf, t.sons[0])
result = mapType(conf, t[0])
else:
result = nil
# too risky:
@@ -120,16 +120,16 @@ proc packSize(conf: ConfigRef, v: PNode, typ: PType): int =
if v.kind in {nkNilLit, nkPtrLit}:
result = sizeof(pointer)
else:
result = sizeof(pointer) + packSize(conf, v.sons[0], typ.lastSon)
result = sizeof(pointer) + packSize(conf, v[0], typ.lastSon)
of tyDistinct, tyGenericInst, tyAlias, tySink:
result = packSize(conf, v, typ.sons[0])
result = packSize(conf, v, typ[0])
of tyArray:
# consider: ptr array[0..1000_000, int] which is common for interfacing;
# we use the real length here instead
if v.kind in {nkNilLit, nkPtrLit}:
result = sizeof(pointer)
elif v.len != 0:
result = v.len * packSize(conf, v.sons[0], typ.sons[1])
result = v.len * packSize(conf, v[0], typ[1])
else:
result = getSize(conf, typ).int
@@ -138,16 +138,16 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer)
proc getField(conf: ConfigRef, n: PNode; position: int): PSym =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = getField(conf, n.sons[i], position)
for i in 0..<n.len:
result = getField(conf, n[i], position)
if result != nil: return
of nkRecCase:
result = getField(conf, n.sons[0], position)
result = getField(conf, n[0], position)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = getField(conf, lastSon(n.sons[i]), position)
result = getField(conf, lastSon(n[i]), position)
if result != nil: return
else: internalError(conf, n.info, "getField(record case branch)")
of nkSym:
@@ -158,12 +158,12 @@ proc packObject(conf: ConfigRef, x: PNode, typ: PType, res: pointer) =
internalAssert conf, x.kind in {nkObjConstr, nkPar, nkTupleConstr}
# compute the field's offsets:
discard getSize(conf, typ)
for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
var it = x.sons[i]
for i in ord(x.kind == nkObjConstr)..<x.len:
var it = x[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
let field = it.sons[0].sym
pack(conf, it.sons[1], field.typ, res +! field.offset)
internalAssert conf, it[0].kind == nkSym
let field = it[0].sym
pack(conf, it[1], field.typ, res +! field.offset)
elif typ.n != nil:
let field = getField(conf, typ.n, i)
pack(conf, it, field.typ, res +! field.offset)
@@ -224,19 +224,19 @@ proc pack(conf: ConfigRef, v: PNode, typ: PType, res: pointer) =
packRecCheck = 0
globalError(conf, v.info, "cannot map value to FFI " & typeToString(v.typ))
inc packRecCheck
pack(conf, v.sons[0], typ.lastSon, res +! sizeof(pointer))
pack(conf, v[0], typ.lastSon, res +! sizeof(pointer))
dec packRecCheck
awr(pointer, res +! sizeof(pointer))
of tyArray:
let baseSize = getSize(conf, typ.sons[1])
for i in 0 ..< v.len:
pack(conf, v.sons[i], typ.sons[1], res +! i * baseSize)
let baseSize = getSize(conf, typ[1])
for i in 0..<v.len:
pack(conf, v[i], typ[1], res +! i * baseSize)
of tyObject, tyTuple:
packObject(conf, v, typ, res)
of tyNil:
discard
of tyDistinct, tyGenericInst, tyAlias, tySink:
pack(conf, v, typ.sons[0], res)
pack(conf, v, typ[0], res)
else:
globalError(conf, v.info, "cannot map value to FFI " & typeToString(v.typ))
@@ -245,14 +245,14 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode
proc unpackObjectAdd(conf: ConfigRef, x: pointer, n, result: PNode) =
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
unpackObjectAdd(conf, x, n.sons[i], result)
for i in 0..<n.len:
unpackObjectAdd(conf, x, n[i], result)
of nkRecCase:
globalError(conf, result.info, "case objects cannot be unpacked")
of nkSym:
var pair = newNodeI(nkExprColonExpr, result.info, 2)
pair.sons[0] = n
pair.sons[1] = unpack(conf, x +! n.sym.offset, n.sym.typ, nil)
pair[0] = n
pair[1] = unpack(conf, x +! n.sym.offset, n.sym.typ, nil)
#echo "offset: ", n.sym.name.s, " ", n.sym.offset
result.add pair
else: discard
@@ -275,28 +275,28 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
globalError(conf, n.info, "cannot map value from FFI")
if typ.n.isNil:
globalError(conf, n.info, "cannot unpack unnamed tuple")
for i in ord(n.kind == nkObjConstr) ..< sonsLen(n):
var it = n.sons[i]
for i in ord(n.kind == nkObjConstr)..<n.len:
var it = n[i]
if it.kind == nkExprColonExpr:
internalAssert conf, it.sons[0].kind == nkSym
let field = it.sons[0].sym
it.sons[1] = unpack(conf, x +! field.offset, field.typ, it.sons[1])
internalAssert conf, it[0].kind == nkSym
let field = it[0].sym
it[1] = unpack(conf, x +! field.offset, field.typ, it[1])
else:
let field = getField(conf, typ.n, i)
n.sons[i] = unpack(conf, x +! field.offset, field.typ, it)
n[i] = unpack(conf, x +! field.offset, field.typ, it)
proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
if n.isNil:
result = newNode(nkBracket)
result.typ = typ
newSeq(result.sons, lengthOrd(conf, typ).int)
newSeq(result.sons, lengthOrd(conf, typ).toInt)
else:
result = n
if result.kind != nkBracket:
globalError(conf, n.info, "cannot map value from FFI")
let baseSize = getSize(conf, typ.sons[1])
for i in 0 ..< result.len:
result.sons[i] = unpack(conf, x +! i * baseSize, typ.sons[1], result.sons[i])
let baseSize = getSize(conf, typ[1])
for i in 0..<result.len:
result[i] = unpack(conf, x +! i * baseSize, typ[1], result[i])
proc canonNodeKind(k: TNodeKind): TNodeKind =
case k
@@ -327,7 +327,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
else:
reset n[]
result = n
result.kind = nkNilLit
result[] = TNode(kind: nkNilLit)
result.typ = typ
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
@@ -376,7 +376,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
awi(nkPtrLit, cast[ByteAddress](p))
elif n != nil and n.len == 1:
internalAssert(conf, n.kind == nkRefTy)
n.sons[0] = unpack(conf, p, typ.lastSon, n.sons[0])
n[0] = unpack(conf, p, typ.lastSon, n[0])
result = n
else:
globalError(conf, n.info, "cannot map value from FFI " & typeToString(typ))
@@ -419,41 +419,41 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
dealloc a
proc callForeignFunction*(conf: ConfigRef, call: PNode): PNode =
internalAssert conf, call.sons[0].kind == nkPtrLit
internalAssert conf, call[0].kind == nkPtrLit
var cif: TCif
var sig: TParamList
var sig: ParamList
# use the arguments' types for varargs support:
for i in 1..call.len-1:
sig[i-1] = mapType(conf, call.sons[i].typ)
for i in 1..<call.len:
sig[i-1] = mapType(conf, call[i].typ)
if sig[i-1].isNil:
globalError(conf, call.info, "cannot map FFI type")
let typ = call.sons[0].typ
let typ = call[0].typ
if prep_cif(cif, mapCallConv(conf, typ.callConv, call.info), cuint(call.len-1),
mapType(conf, typ.sons[0]), sig) != OK:
mapType(conf, typ[0]), sig) != OK:
globalError(conf, call.info, "error in FFI call")
var args: TArgList
let fn = cast[pointer](call.sons[0].intVal)
for i in 1 .. call.len-1:
var t = call.sons[i].typ
args[i-1] = alloc0(packSize(conf, call.sons[i], t))
pack(conf, call.sons[i], t, args[i-1])
let retVal = if isEmptyType(typ.sons[0]): pointer(nil)
else: alloc(getSize(conf, typ.sons[0]).int)
var args: ArgList
let fn = cast[pointer](call[0].intVal)
for i in 1..<call.len:
var t = call[i].typ
args[i-1] = alloc0(packSize(conf, call[i], t))
pack(conf, call[i], t, args[i-1])
let retVal = if isEmptyType(typ[0]): pointer(nil)
else: alloc(getSize(conf, typ[0]).int)
libffi.call(cif, fn, retVal, args)
if retVal.isNil:
result = newNode(nkEmpty)
else:
result = unpack(conf, retVal, typ.sons[0], nil)
result = unpack(conf, retVal, typ[0], nil)
result.info = call.info
if retVal != nil: dealloc retVal
for i in 1 .. call.len-1:
call.sons[i] = unpack(conf, args[i-1], typ.sons[i], call[i])
for i in 1..<call.len:
call[i] = unpack(conf, args[i-1], typ[i], call[i])
dealloc args[i-1]
proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
@@ -462,39 +462,39 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
internalAssert conf, fn.kind == nkPtrLit
var cif: TCif
var sig: TParamList
var sig: ParamList
for i in 0..len-1:
var aTyp = args[i+start].typ
if aTyp.isNil:
internalAssert conf, i+1 < fntyp.len
aTyp = fntyp.sons[i+1]
aTyp = fntyp[i+1]
args[i+start].typ = aTyp
sig[i] = mapType(conf, aTyp)
if sig[i].isNil: globalError(conf, info, "cannot map FFI type")
if prep_cif(cif, mapCallConv(conf, fntyp.callConv, info), cuint(len),
mapType(conf, fntyp.sons[0]), sig) != OK:
mapType(conf, fntyp[0]), sig) != OK:
globalError(conf, info, "error in FFI call")
var cargs: TArgList
var cargs: ArgList
let fn = cast[pointer](fn.intVal)
for i in 0 .. len-1:
for i in 0..len-1:
let t = args[i+start].typ
cargs[i] = alloc0(packSize(conf, args[i+start], t))
pack(conf, args[i+start], t, cargs[i])
let retVal = if isEmptyType(fntyp.sons[0]): pointer(nil)
else: alloc(getSize(conf, fntyp.sons[0]).int)
let retVal = if isEmptyType(fntyp[0]): pointer(nil)
else: alloc(getSize(conf, fntyp[0]).int)
libffi.call(cif, fn, retVal, cargs)
if retVal.isNil:
result = newNode(nkEmpty)
else:
result = unpack(conf, retVal, fntyp.sons[0], nil)
result = unpack(conf, retVal, fntyp[0], nil)
result.info = info
if retVal != nil: dealloc retVal
for i in 0 .. len-1:
for i in 0..len-1:
let t = args[i+start].typ
args[i+start] = unpack(conf, cargs[i], t, args[i+start])
dealloc cargs[i]

View File

@@ -10,7 +10,7 @@
## Template evaluation engine. Now hygienic.
import
strutils, options, ast, astalgo, msgs, renderer, lineinfos
strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents
type
TemplCtx = object
@@ -20,6 +20,7 @@ type
mapping: TIdTable # every gensym'ed symbol needs to be mapped to some
# new symbol
config: ConfigRef
ic: IdentCache
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a)
@@ -37,11 +38,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
of nkSym:
var s = templ.sym
if (s.owner == nil and s.kind == skParam) or s.owner == c.owner:
if s.kind == skParam and sfGenSym notin s.flags:
handleParam actual.sons[s.position]
if s.kind == skParam and {sfGenSym, sfTemplateParam} * s.flags == {sfTemplateParam}:
handleParam actual[s.position]
elif (s.owner != nil) and (s.kind == skGenericParam or
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
handleParam actual.sons[s.owner.typ.len + s.position - 1]
handleParam actual[s.owner.typ.len + s.position - 1]
else:
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
var x = PSym(idTableGet(c.mapping, s))
@@ -52,7 +53,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
#if x.kind == skParam and x.owner.kind == skModule:
# internalAssert c.config, false
idTablePut(c.mapping, s, x)
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions:
result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id),
if c.instLines: actual.info else: templ.info)
else:
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
else:
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
@@ -63,8 +68,8 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
# "declarative" context (bug #9235).
if c.isDeclarative:
var res = copyNode(c, templ, actual)
for i in 0 ..< sonsLen(templ):
evalTemplateAux(templ.sons[i], actual, c, res)
for i in 0..<templ.len:
evalTemplateAux(templ[i], actual, c, res)
result.add res
else:
result.add newNodeI(nkEmpty, templ.info)
@@ -77,8 +82,8 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
c.isDeclarative = true
isDeclarative = true
var res = copyNode(c, templ, actual)
for i in 0 ..< sonsLen(templ):
evalTemplateAux(templ.sons[i], actual, c, res)
for i in 0..<templ.len:
evalTemplateAux(templ[i], actual, c, res)
result.add res
if isDeclarative: c.isDeclarative = false
@@ -117,22 +122,22 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
n.renderTree)
result = newNodeI(nkArgList, n.info)
for i in 1 .. givenRegularParams:
result.addSon n[i]
for i in 1..givenRegularParams:
result.add n[i]
# handle parameters with default values, which were
# not supplied by the user
for i in givenRegularParams+1 .. expectedRegularParams:
let default = s.typ.n.sons[i].sym.ast
for i in givenRegularParams+1..expectedRegularParams:
let default = s.typ.n[i].sym.ast
if default.isNil or default.kind == nkEmpty:
localError(conf, n.info, errWrongNumberOfArguments)
addSon(result, newNodeI(nkEmpty, n.info))
result.add newNodeI(nkEmpty, n.info)
else:
addSon(result, default.copyTree)
result.add default.copyTree
# add any generic paramaters
for i in 1 .. genericParams:
result.addSon n.sons[givenRegularParams + i]
# add any generic parameters
for i in 1..genericParams:
result.add n[givenRegularParams + i]
# to prevent endless recursion in template instantiation
const evalTemplateLimit* = 1000
@@ -150,7 +155,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
if x.kind in nkCallKinds:
for i in 1..<x.len:
if x[i].kind in nkCallKinds:
x.sons[i].info = info
x[i].info = info
else:
result = newNodeI(nkStmtListExpr, info)
var d = newNodeI(nkComesFrom, info)
@@ -160,7 +165,9 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
result.typ = res.typ
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef; fromHlo=false): PNode =
conf: ConfigRef;
ic: IdentCache;
fromHlo=false): PNode =
inc(conf.evalTemplateCounter)
if conf.evalTemplateCounter > evalTemplateLimit:
globalError(conf, n.info, errTemplateInstantiationTooNested)
@@ -172,6 +179,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.owner = tmpl
ctx.genSymOwner = genSymOwner
ctx.config = conf
ctx.ic = ic
initIdTable(ctx.mapping)
let body = tmpl.getBody
@@ -179,7 +187,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
if isAtom(body):
result = newNodeI(nkPar, body.info)
evalTemplateAux(body, args, ctx, result)
if result.len == 1: result = result.sons[0]
if result.len == 1: result = result[0]
else:
localError(conf, result.info, "illformed AST: " &
renderTree(result, {renderNoComments}))
@@ -188,8 +196,8 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.instLines = sfCallsite in tmpl.flags
if ctx.instLines:
result.info = n.info
for i in 0 ..< safeLen(body):
evalTemplateAux(body.sons[i], args, ctx, result)
for i in 0..<body.safeLen:
evalTemplateAux(body[i], args, ctx, result)
result.flags.incl nfFromTemplate
result = wrapInComesFrom(n.info, tmpl, result)
#if ctx.debugActive:

View File

@@ -14,7 +14,7 @@
import
ropes, os, strutils, osproc, platform, condsyms, options, msgs,
lineinfos, std / sha1, streams, pathutils, sequtils, times
lineinfos, std / sha1, streams, pathutils, sequtils, times, strtabs
type
TInfoCCProp* = enum # properties of the C compiler:
@@ -48,6 +48,8 @@ type
# used on some platforms
asmStmtFrmt: string, # format of ASM statement
structStmtFmt: string, # Format for struct statement
produceAsm: string, # Format how to produce assembler listings
cppXsupport: string, # what to do to enable C++X support
props: TInfoCCProps] # properties of the C compiler
@@ -58,13 +60,16 @@ type
template compiler(name, settings: untyped): untyped =
proc name: TInfoCC {.compileTime.} = settings
const
gnuAsmListing = "-Wa,-acdl=$asmfile -g -fverbose-asm -masm=intel"
# GNU C and C++ Compiler
compiler gcc:
result = (
name: "gcc",
objExt: "o",
optSpeed: " -O3 ",
optSize: " -Os ",
optSpeed: " -O3 -fno-ident",
optSize: " -Os -fno-ident",
compilerExe: "gcc",
cppCompiler: "g++",
compileTmpl: "-c $options $include -o $objfile $file",
@@ -80,6 +85,8 @@ compiler gcc:
pic: "-fPIC",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++14 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
@@ -105,6 +112,8 @@ compiler nintendoSwitchGCC:
pic: "-fPIE",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $3 $2 ", # struct|union [packed] $name
produceAsm: gnuAsmListing,
cppXsupport: "-std=gnu++14 -funsigned-char",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard, hasGnuAsm,
hasAttribute})
@@ -138,12 +147,12 @@ compiler vcc:
optSize: " /O1 /G7 ",
compilerExe: "cl",
cppCompiler: "cl",
compileTmpl: "/c$vccplatform$options $include /Fo$objfile $file",
compileTmpl: "/c$vccplatform $options $include /Fo$objfile $file",
buildGui: " /link /SUBSYSTEM:WINDOWS ",
buildDll: " /LD",
buildLib: "lib /OUT:$libfile $objfiles",
linkerExe: "cl",
linkTmpl: "$options $builddll$vccplatform /Fe$exefile $objfiles $buildgui",
linkTmpl: "$builddll$vccplatform /Fe$exefile $objfiles $buildgui $options",
includeCmd: " /I",
linkDirCmd: " /LIBPATH:",
linkLibCmd: " $1.lib",
@@ -151,6 +160,8 @@ compiler vcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
produceAsm: "/Fa$asmfile",
cppXsupport: "",
props: {hasCpp, hasAssume, hasDeclspec})
compiler clangcl:
@@ -196,6 +207,8 @@ compiler lcc:
pic: "",
asmStmtFrmt: "_asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Borland C Compiler
@@ -220,6 +233,8 @@ compiler bcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasSwitchRange, hasComputedGoto, hasCpp, hasGcGuard,
hasAttribute})
@@ -245,6 +260,8 @@ compiler dmc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$3$n$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Watcom C Compiler
@@ -269,6 +286,8 @@ compiler wcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {hasCpp})
# Tiny C Compiler
@@ -291,9 +310,11 @@ compiler tcc:
linkLibCmd: "", # XXX: not supported yet
debug: " -g ",
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
asmStmtFrmt: "asm($1);$n",
structStmtFmt: "$1 $2",
props: {hasSwitchRange, hasComputedGoto})
produceAsm: gnuAsmListing,
cppXsupport: "",
props: {hasSwitchRange, hasComputedGoto, hasGnuAsm})
# Pelles C Compiler
compiler pcc:
@@ -318,6 +339,8 @@ compiler pcc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
# Your C Compiler
@@ -342,6 +365,8 @@ compiler ucc:
pic: "",
asmStmtFrmt: "__asm{$n$1$n}$n",
structStmtFmt: "$1 $2",
produceAsm: "",
cppXsupport: "",
props: {})
const
@@ -370,13 +395,15 @@ proc libNameTmpl(conf: ConfigRef): string {.inline.} =
proc nameToCC*(name: string): TSystemCC =
## Returns the kind of compiler referred to by `name`, or ccNone
## if the name doesn't refer to any known compiler.
for i in succ(ccNone) .. high(TSystemCC):
for i in succ(ccNone)..high(TSystemCC):
if cmpIgnoreStyle(name, CC[i].name) == 0:
return i
result = ccNone
proc listCCnames(): seq[string] =
for i in succ(ccNone) .. high(TSystemCC):
proc listCCnames(): string =
result = ""
for i in succ(ccNone)..high(TSystemCC):
if i > succ(ccNone): result.add ", "
result.add CC[i].name
proc isVSCompatible*(conf: ConfigRef): bool =
@@ -404,7 +431,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
CC[c].name & fullSuffix
result = getConfigVar(conf, fullCCname)
if result.len == 0:
# not overriden for this cross compilation setting?
# not overridden for this cross compilation setting?
result = getConfigVar(conf, CC[c].name & fullSuffix)
else:
result = getConfigVar(conf, CC[c].name & fullSuffix)
@@ -412,17 +439,16 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string =
proc setCC*(conf: ConfigRef; ccname: string; info: TLineInfo) =
conf.cCompiler = nameToCC(ccname)
if conf.cCompiler == ccNone:
let ccList = listCCnames().join(", ")
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, ccList])
localError(conf, info, "unknown C compiler: '$1'. Available options are: $2" % [ccname, listCCnames()])
conf.compileOptions = getConfigVar(conf, conf.cCompiler, ".options.always")
conf.linkOptions = ""
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
for i in low(CC) .. high(CC): undefSymbol(conf.symbols, CC[i].name)
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
proc addOpt(dest: var string, src: string) =
if len(dest) == 0 or dest[len(dest)-1] != ' ': add(dest, " ")
add(dest, src)
if dest.len == 0 or dest[^1] != ' ': dest.add(" ")
dest.add(src)
proc addLinkOption*(conf: ConfigRef; option: string) =
addOpt(conf.linkOptions, option)
@@ -439,11 +465,11 @@ proc addCompileOptionCmd*(conf: ConfigRef; option: string) =
proc initVars*(conf: ConfigRef) =
# we need to define the symbol here, because ``CC`` may have never been set!
for i in low(CC) .. high(CC): undefSymbol(conf.symbols, CC[i].name)
for i in low(CC)..high(CC): undefSymbol(conf.symbols, CC[i].name)
defineSymbol(conf.symbols, CC[conf.cCompiler].name)
addCompileOption(conf, getConfigVar(conf, conf.cCompiler, ".options.always"))
#addLinkOption(getConfigVar(cCompiler, ".options.linker"))
if len(conf.cCompilerPath) == 0:
if conf.cCompilerPath.len == 0:
conf.cCompilerPath = getConfigVar(conf, conf.cCompiler, ".path")
proc completeCfilePath*(conf: ConfigRef; cfile: AbsoluteFile,
@@ -457,6 +483,13 @@ proc toObjFile*(conf: ConfigRef; filename: AbsoluteFile): AbsoluteFile =
proc addFileToCompile*(conf: ConfigRef; cf: Cfile) =
conf.toCompile.add(cf)
proc addLocalCompileOption*(conf: ConfigRef; option: string; nimfile: AbsoluteFile) =
let key = completeCfilePath(conf, withPackageName(conf, nimfile)).string
var value = conf.cfileSpecificOptions.getOrDefault(key)
if strutils.find(value, option, 0) < 0:
addOpt(value, option)
conf.cfileSpecificOptions[key] = value
proc resetCompilationLists*(conf: ConfigRef) =
conf.toCompile.setLen 0
## XXX: we must associate these with their originating module
@@ -469,7 +502,7 @@ proc addExternalFileToLink*(conf: ConfigRef; filename: AbsoluteFile) =
conf.externalToLink.insert(filename.string, 0)
proc execWithEcho(conf: ConfigRef; cmd: string, msg = hintExecuting): int =
rawMessage(conf, msg, cmd)
rawMessage(conf, msg, if msg == hintLinking and not(optListCmd in conf.globalOptions or conf.verbosity > 1): "" else: cmd)
result = execCmd(cmd)
proc execExternalProgram*(conf: ConfigRef; cmd: string, msg = hintExecuting) =
@@ -481,10 +514,7 @@ proc generateScript(conf: ConfigRef; script: Rope) =
let (_, name, _) = splitFile(conf.outFile.string)
let filename = getNimcacheDir(conf) / RelativeFile(addFileExt("compile_" & name,
platform.OS[conf.target.targetOS].scriptExt))
if writeRope(script, filename):
copyFile(conf.libpath / RelativeFile"nimbase.h",
getNimcacheDir(conf) / RelativeFile"nimbase.h")
else:
if not writeRope(script, filename):
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)
proc getOptSpeed(conf: ConfigRef; c: TSystemCC): string =
@@ -509,8 +539,10 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} =
# `optGenMapping` is included here for niminst.
result = conf.globalOptions * {optGenScript, optGenMapping} != {}
proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
proc cFileSpecificOptions(conf: ConfigRef; nimname, fullNimFile: string): string =
result = conf.compileOptions
addOpt(result, conf.cfileSpecificOptions.getOrDefault(fullNimFile))
for option in conf.compileOptionsCmd:
if strutils.find(result, option, 0) < 0:
addOpt(result, option)
@@ -531,20 +563,19 @@ proc cFileSpecificOptions(conf: ConfigRef; nimname: string): string =
if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key))
proc getCompileOptions(conf: ConfigRef): string =
result = cFileSpecificOptions(conf, "__dummy__")
result = cFileSpecificOptions(conf, "__dummy__", "__dummy__")
proc vccplatform(conf: ConfigRef): string =
# VCC specific but preferable over the config hacks people
# had to do before, see #11306
case conf.target.targetCPU
of cpuI386:
result = " --platform:x86"
of cpuArm:
result = " --platform:arm"
of cpuAmd64:
result = " --platform:amd64"
else:
result = ""
if conf.cCompiler == ccVcc:
let exe = getConfigVar(conf, conf.cCompiler, ".exe")
if "vccexe.exe" == extractFilename(exe):
result = case conf.target.targetCPU
of cpuI386: " --platform:x86"
of cpuArm: " --platform:arm"
of cpuAmd64: " --platform:amd64"
else: ""
proc getLinkOptions(conf: ConfigRef): string =
result = conf.linkOptions & " " & conf.linkOptionsCmd & " "
@@ -557,8 +588,11 @@ proc needsExeExt(conf: ConfigRef): bool {.inline.} =
result = (optGenScript in conf.globalOptions and conf.target.targetOS == osWindows) or
(conf.target.hostOS == osWindows)
proc useCpp(conf: ConfigRef; cfile: AbsoluteFile): bool =
conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c")
proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: AbsoluteFile): string =
result = if conf.cmd == cmdCompileToCpp and not cfile.string.endsWith(".c"):
result = if useCpp(conf, cfile):
CC[compiler].cppCompiler
else:
CC[compiler].compilerExe
@@ -572,28 +606,32 @@ proc getLinkerExe(conf: ConfigRef; compiler: TSystemCC): string =
elif optMixedMode in conf.globalOptions and conf.cmd != cmdCompileToCpp: CC[compiler].cppCompiler
else: getCompilerExe(conf, compiler, AbsoluteFile"")
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): string =
var c = conf.cCompiler
var options = cFileSpecificOptions(conf, cfile.nimname)
proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
isMainFile = false; produceOutput = false): string =
let c = conf.cCompiler
# We produce files like module.nim.cpp, so the absolute Nim filename is not
# cfile.name but `cfile.cname.changeFileExt("")`:
var options = cFileSpecificOptions(conf, cfile.nimname, cfile.cname.changeFileExt("").string)
var exe = getConfigVar(conf, c, ".exe")
if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname)
if needsExeExt(conf): exe = addFileExt(exe, "exe")
if (optGenDynLib in conf.globalOptions or (conf.hcrOn and not isMainFile)) and
ospNeedsPIC in platform.OS[conf.target.targetOS].props:
add(options, ' ' & CC[c].pic)
options.add(' ' & CC[c].pic)
var includeCmd, compilePattern: string
if useCpp(conf, cfile.cname):
options.add(' ' & CC[c].cppXsupport)
var compilePattern: string
# compute include paths:
var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
if not noAbsolutePaths(conf):
# compute include paths:
includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
for includeDir in items(conf.cIncludes):
includeCmd.add(join([CC[c].includeCmd, includeDir.quoteShell]))
compilePattern = joinPath(conf.cCompilerPath, exe)
else:
includeCmd = ""
compilePattern = getCompilerExe(conf, c, cfile.cname)
includeCmd.add(join([CC[c].includeCmd, quoteShell(conf.projectPath.string)]))
@@ -603,7 +641,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
var objfile =
if cfile.obj.isEmpty:
if not cfile.flags.contains(CfileFlag.External) or noAbsolutePaths(conf):
if CfileFlag.External notin cfile.flags or noAbsolutePaths(conf):
toObjFile(conf, cf).string
else:
completeCfilePath(conf, toObjFile(conf, cf)).string
@@ -614,19 +652,30 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile, isMainFile = false): str
# D files are required by nintendo switch libs for
# compilation. They are basically a list of all includes.
let dfile = objfile.changeFileExt(".d").quoteShell()
let dfile = objfile.changeFileExt(".d").quoteShell
objfile = quoteShell(objfile)
let cfsh = quoteShell(cf)
result = quoteShell(compilePattern % [
"dfile", dfile,
"file", cfsh, "objfile", objfile, "options", options,
"file", cfsh, "objfile", quoteShell(objfile), "options", options,
"include", includeCmd, "nim", getPrefixDir(conf).string,
"lib", conf.libpath.string])
add(result, ' ')
addf(result, CC[c].compileTmpl, [
if optProduceAsm in conf.globalOptions:
if CC[conf.cCompiler].produceAsm.len > 0:
let asmfile = objfile.changeFileExt(".asm").quoteShell
addOpt(result, CC[conf.cCompiler].produceAsm % ["asmfile", asmfile])
if produceOutput:
rawMessage(conf, hintUserRaw, "Produced assembler here: " & asmfile)
else:
if produceOutput:
rawMessage(conf, hintUserRaw, "Couldn't produce assembler listing " &
"for the selected C compiler: " & CC[conf.cCompiler].name)
result.add(' ')
result.addf(CC[c].compileTmpl, [
"dfile", dfile,
"file", cfsh, "objfile", objfile,
"file", cfsh, "objfile", quoteShell(objfile),
"options", options, "include", includeCmd,
"nim", quoteShell(getPrefixDir(conf)),
"lib", quoteShell(conf.libpath),
@@ -641,7 +690,7 @@ proc footprint(conf: ConfigRef; cfile: Cfile): SecureHash =
getCompileCFileCmd(conf, cfile))
proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool =
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
if conf.cmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM, cmdNone}:
return false
var hashFile = toGeneratedFile(conf, conf.withPackageName(cfile.cname), "sha1")
@@ -662,6 +711,10 @@ proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) =
if optForceFullMake notin conf.globalOptions and fileExists(c.obj) and
not externalFileChanged(conf, c):
c.flags.incl CfileFlag.Cached
else:
# make sure Nim keeps recompiling the external file on reruns
# if compilation is not successful
discard tryRemoveFile(c.obj.string)
conf.toCompile.add(c)
proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
@@ -670,22 +723,6 @@ proc addExternalFileToCompile*(conf: ConfigRef; filename: AbsoluteFile) =
flags: {CfileFlag.External})
addExternalFileToCompile(conf, c)
proc compileCFiles(conf: ConfigRef; list: CfileList, script: var Rope, cmds: var TStringSeq,
prettyCmds: var TStringSeq) =
var currIdx = 0
for it in list:
# call the C compiler for the .c file:
if it.flags.contains(CfileFlag.Cached): continue
var compileCmd = getCompileCFileCmd(conf, it, currIdx == list.len - 1)
inc currIdx
if optCompileOnly notin conf.globalOptions:
add(cmds, compileCmd)
let (_, name, _) = splitFile(it.cname)
add(prettyCmds, if hintCC in conf.notes: "CC: " & demanglePackageName(name) else: "")
if optGenScript in conf.globalOptions:
add(script, compileCmd)
add(script, "\n")
proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
objfiles: string, isDllBuild: bool): string =
if optGenStaticLib in conf.globalOptions:
@@ -700,7 +737,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")
if len(linkerExe) == 0: linkerExe = getLinkerExe(conf, conf.cCompiler)
if linkerExe.len == 0: linkerExe = getLinkerExe(conf, conf.cCompiler)
# bug #6452: We must not use ``quoteShell`` here for ``linkerExe``
if needsExeExt(conf): linkerExe = addFileExt(linkerExe, "exe")
if noAbsolutePaths(conf): result = linkerExe
@@ -730,7 +767,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
"buildgui", buildgui, "options", linkOptions, "objfiles", objfiles,
"exefile", exefile, "nim", getPrefixDir(conf).string, "lib", conf.libpath.string])
result.add ' '
addf(result, linkTmpl, ["builddll", builddll,
result.addf(linkTmpl, ["builddll", builddll,
"mapfile", mapfile,
"buildgui", buildgui, "options", linkOptions,
"objfiles", objfiles, "exefile", exefile,
@@ -757,7 +794,7 @@ proc getLinkCmd(conf: ConfigRef; output: AbsoluteFile,
# way of being able to debug and rebuild the program at the same time. This
# is accomplished using the /PDB:<filename> flag (there also exists the
# /PDBALTPATH:<filename> flag). The only downside is that the .pdb files are
# atleast 300kb big (when linking statically to the runtime - or else 5mb+)
# at least 300kb big (when linking statically to the runtime - or else 5mb+)
# and will quickly accumulate. There is a hacky solution: we could try to
# delete all .pdb files with a pattern and swallow exceptions.
#
@@ -795,20 +832,27 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body
proc execLinkCmd(conf: ConfigRef; linkCmd: string) =
tryExceptOSErrorMessage(conf, "invocation of external linker program failed."):
execExternalProgram(conf, linkCmd,
if optListCmd in conf.globalOptions or conf.verbosity > 1: hintExecuting else: hintLinking)
execExternalProgram(conf, linkCmd, hintLinking)
proc maybeRunDsymutil(conf: ConfigRef; exe: AbsoluteFile) =
when defined(osx):
if optCDebug notin conf.globalOptions: return
# if needed, add an option to skip or override location
let cmd = "dsymutil " & $(exe).quoteShell
conf.extraCmds.add cmd
tryExceptOSErrorMessage(conf, "invocation of dsymutil failed."):
execExternalProgram(conf, cmd, hintExecuting)
proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: int)) =
let runCb = proc (idx: int, p: Process) =
let exitCode = p.peekExitCode
if exitCode != 0:
rawMessage(conf, errGenerated, "execution of an external compiler program '" &
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" &
p.outputStream.readAll.strip)
cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n")
if conf.numberOfProcessors == 0: conf.numberOfProcessors = countProcessors()
var res = 0
if conf.numberOfProcessors <= 1:
for i in 0 .. high(cmds):
for i in 0..high(cmds):
tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
res = execWithEcho(conf, cmds[i])
if res != 0:
@@ -816,15 +860,8 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
cmds[i])
else:
tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."):
if optListCmd in conf.globalOptions or conf.verbosity > 1:
res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath},
conf.numberOfProcessors, afterRunEvent=runCb)
elif conf.verbosity == 1:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath, poParentStreams},
conf.numberOfProcessors, prettyCb, afterRunEvent=runCb)
else:
res = execProcesses(cmds, {poStdErrToStdOut, poUsePath},
conf.numberOfProcessors, afterRunEvent=runCb)
if res != 0:
if conf.numberOfProcessors <= 1:
rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
@@ -866,6 +903,13 @@ proc hcrLinkTargetName(conf: ConfigRef, objFile: string, isMain = false): Absolu
else: platform.OS[conf.target.targetOS].dllFrmt % basename
result = conf.getNimcacheDir / RelativeFile(targetName)
proc displayProgressCC(conf: ConfigRef, path, compileCmd: string): string =
if conf.hasHint(hintCC):
if optListCmd in conf.globalOptions or conf.verbosity > 1:
result = MsgKindToStr[hintCC] % (demanglePackageName(path.splitFile.name) & ": " & compileCmd)
else:
result = MsgKindToStr[hintCC] % demanglePackageName(path.splitFile.name)
proc callCCompiler*(conf: ConfigRef) =
var
linkCmd: string
@@ -874,13 +918,22 @@ proc callCCompiler*(conf: ConfigRef) =
# generated
#var c = cCompiler
var script: Rope = nil
var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[]
var cmds: TStringSeq
var prettyCmds: TStringSeq
let prettyCb = proc (idx: int) =
when declared(echo):
let cmd = prettyCmds[idx]
if cmd != "": echo cmd
compileCFiles(conf, conf.toCompile, script, cmds, prettyCmds)
if prettyCmds[idx].len > 0: echo prettyCmds[idx]
for idx, it in conf.toCompile:
# call the C compiler for the .c file:
if CfileFlag.Cached in it.flags: continue
let compileCmd = getCompileCFileCmd(conf, it, idx == conf.toCompile.len - 1, produceOutput=true)
if optCompileOnly notin conf.globalOptions:
cmds.add(compileCmd)
prettyCmds.add displayProgressCC(conf, $it.cname, compileCmd)
if optGenScript in conf.globalOptions:
script.add(compileCmd)
script.add("\n")
if optCompileOnly notin conf.globalOptions:
execCmdsInParallel(conf, cmds, prettyCb)
if optNoLinking notin conf.globalOptions:
@@ -888,8 +941,8 @@ proc callCCompiler*(conf: ConfigRef) =
var objfiles = ""
for it in conf.externalToLink:
let objFile = if noAbsolutePaths(conf): it.extractFilename else: it
add(objfiles, ' ')
add(objfiles, quoteShell(
objfiles.add(' ')
objfiles.add(quoteShell(
addFileExt(objFile, CC[conf.cCompiler].objExt)))
if conf.hcrOn: # lets assume that optCompileOnly isn't on
@@ -899,14 +952,14 @@ proc callCCompiler*(conf: ConfigRef) =
# don't relink each of the many binaries (one for each source file) if the nim code is
# cached because that would take too much time for small changes - the only downside to
# this is that if an external-to-link file changes the final target wouldn't be relinked
if x.flags.contains(CfileFlag.Cached): continue
if CfileFlag.Cached in x.flags: continue
# we pass each object file as if it is the project file - a .dll will be created for each such
# object file in the nimcache directory, and only in the case of the main project file will
# there be probably an executable (if the project is such) which will be copied out of the nimcache
let objFile = conf.getObjFilePath(x)
let buildDll = idx != mainFileIdx
let linkTarget = conf.hcrLinkTargetName(objFile, not buildDll)
add(cmds, getLinkCmd(conf, linkTarget, objfiles & " " & quoteShell(objFile), buildDll))
cmds.add(getLinkCmd(conf, linkTarget, objfiles & " " & quoteShell(objFile), buildDll))
# try to remove all .pdb files for the current binary so they don't accumulate endlessly in the nimcache
# for more info check the comment inside of getLinkCmd() where the /PDB:<filename> MSVC flag is used
if isVSCompatible(conf):
@@ -917,7 +970,7 @@ proc callCCompiler*(conf: ConfigRef) =
prettyCmds = map(prettyCmds, proc (curr: string): string = return curr.replace("CC", "Link"))
execCmdsInParallel(conf, cmds, prettyCb)
# only if not cached - copy the resulting main file from the nimcache folder to its originally intended destination
if not conf.toCompile[mainFileIdx].flags.contains(CfileFlag.Cached):
if CfileFlag.Cached notin conf.toCompile[mainFileIdx].flags:
let mainObjFile = getObjFilePath(conf, conf.toCompile[mainFileIdx])
var src = conf.hcrLinkTargetName(mainObjFile, true)
var dst = conf.prepareToWriteOutput
@@ -925,8 +978,8 @@ proc callCCompiler*(conf: ConfigRef) =
else:
for x in conf.toCompile:
let objFile = if noAbsolutePaths(conf): x.obj.extractFilename else: x.obj.string
add(objfiles, ' ')
add(objfiles, quoteShell(objFile))
objfiles.add(' ')
objfiles.add(quoteShell(objFile))
let mainOutput = if optGenScript notin conf.globalOptions: conf.prepareToWriteOutput
else: AbsoluteFile(conf.projectName)
linkCmd = getLinkCmd(conf, mainOutput, objfiles)
@@ -939,15 +992,18 @@ proc callCCompiler*(conf: ConfigRef) =
linkViaResponseFile(conf, linkCmd)
else:
execLinkCmd(conf, linkCmd)
maybeRunDsymutil(conf, mainOutput)
else:
linkCmd = ""
if optGenScript in conf.globalOptions:
add(script, linkCmd)
add(script, "\n")
script.add(linkCmd)
script.add("\n")
generateScript(conf, script)
#from json import escapeJson
import json
import json, std / sha1
template hashNimExe(): string = $secureHashFile(os.getAppFilename())
proc writeJsonBuildInstructions*(conf: ConfigRef) =
template lit(x: untyped) = f.write x
@@ -960,17 +1016,16 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
f.write escapeJson(x)
proc cfiles(conf: ConfigRef; f: File; buf: var string; clist: CfileList, isExternal: bool) =
var pastStart = false
for it in clist:
var comma = false
for i, it in clist:
if CfileFlag.Cached in it.flags: continue
let compileCmd = getCompileCFileCmd(conf, it)
if pastStart: lit "],\L"
if comma: lit ",\L" else: comma = true
lit "["
str it.cname.string
lit ", "
str compileCmd
pastStart = true
lit "]\L"
lit "]"
proc linkfiles(conf: ConfigRef; f: File; buf, objfiles: var string; clist: CfileList;
llist: seq[string]) =
@@ -979,21 +1034,35 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
let objfile = if noAbsolutePaths(conf): it.extractFilename
else: it
let objstr = addFileExt(objfile, CC[conf.cCompiler].objExt)
add(objfiles, ' ')
add(objfiles, objstr)
objfiles.add(' ')
objfiles.add(objstr)
if pastStart: lit ",\L"
str objstr
pastStart = true
for it in clist:
let objstr = quoteShell(it.obj)
add(objfiles, ' ')
add(objfiles, objstr)
objfiles.add(' ')
objfiles.add(objstr)
if pastStart: lit ",\L"
str objstr
pastStart = true
lit "\L"
proc depfiles(conf: ConfigRef; f: File) =
var i = 0
for it in conf.m.fileInfos:
let path = it.fullPath.string
if isAbsolute(path): # TODO: else?
if i > 0: lit "],\L"
lit "["
str path
lit ", "
str $secureHashFile(path)
inc i
lit "]\L"
var buf = newStringOfCap(50)
let jsonFile = conf.getNimcacheDir / RelativeFile(conf.projectName & ".json")
@@ -1009,57 +1078,116 @@ proc writeJsonBuildInstructions*(conf: ConfigRef) =
lit "],\L\"linkcmd\": "
str getLinkCmd(conf, conf.absOutFile, objfiles)
lit ",\L\"extraCmds\": "
lit $(%* conf.extraCmds)
lit ",\L\"stdinInput\": "
lit $(%* conf.projectIsStdin)
if optRun in conf.globalOptions or isDefined(conf, "nimBetterRun"):
lit ",\L\"cmdline\": "
str conf.commandLine
lit ",\L\"depfiles\":[\L"
depfiles(conf, f)
lit "],\L\"nimexe\": \L"
str hashNimExe()
lit "\L"
lit "\L}\L"
close(f)
proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile): bool =
let jsonFile = toGeneratedFile(conf, projectfile, "json")
if not fileExists(jsonFile): return true
if not fileExists(conf.absOutFile): return true
result = false
try:
let data = json.parseFile(jsonFile.string)
if not data.hasKey("depfiles") or not data.hasKey("cmdline"):
return true
let oldCmdLine = data["cmdline"].getStr
if conf.commandLine != oldCmdLine:
return true
if hashNimExe() != data["nimexe"].getStr:
return true
if not data.hasKey("stdinInput"): return true
let stdinInput = data["stdinInput"].getBool
if conf.projectIsStdin or stdinInput:
# could optimize by returning false if stdin input was the same,
# but I'm not sure how to get full stding input
return true
let depfilesPairs = data["depfiles"]
doAssert depfilesPairs.kind == JArray
for p in depfilesPairs:
doAssert p.kind == JArray
# >= 2 for forwards compatibility with potential later .json files:
doAssert p.len >= 2
let depFilename = p[0].getStr
let oldHashValue = p[1].getStr
let newHashValue = $secureHashFile(depFilename)
if oldHashValue != newHashValue:
return true
except IOError, OSError, ValueError:
echo "Warning: JSON processing failed: ", getCurrentExceptionMsg()
result = true
proc runJsonBuildInstructions*(conf: ConfigRef; projectfile: AbsoluteFile) =
let jsonFile = toGeneratedFile(conf, projectfile, "json")
try:
let data = json.parseFile(jsonFile.string)
let toCompile = data["compile"]
doAssert toCompile.kind == JArray
var cmds: TStringSeq = @[]
var prettyCmds: TStringSeq = @[]
var cmds: TStringSeq
var prettyCmds: TStringSeq
let prettyCb = proc (idx: int) =
if prettyCmds[idx].len > 0: echo prettyCmds[idx]
for c in toCompile:
doAssert c.kind == JArray
doAssert c.len >= 2
add(cmds, c[1].getStr)
let (_, name, _) = splitFile(c[0].getStr)
add(prettyCmds, "CC: " & name)
cmds.add(c[1].getStr)
prettyCmds.add displayProgressCC(conf, c[0].getStr, c[1].getStr)
let prettyCb = proc (idx: int) =
when declared(echo):
echo prettyCmds[idx]
execCmdsInParallel(conf, cmds, prettyCb)
let linkCmd = data["linkcmd"]
doAssert linkCmd.kind == JString
execLinkCmd(conf, linkCmd.getStr)
if data.hasKey("extraCmds"):
let extraCmds = data["extraCmds"]
doAssert extraCmds.kind == JArray
for cmd in extraCmds:
doAssert cmd.kind == JString, $cmd.kind
let cmd2 = cmd.getStr
execExternalProgram(conf, cmd2, hintExecuting)
except:
when declared(echo):
echo getCurrentException().getStackTrace()
quit "error evaluating JSON file: " & jsonFile.string
let e = getCurrentException()
quit "\ncaught exception:\n" & e.msg & "\nstacktrace:\n" & e.getStackTrace() &
"error evaluating JSON file: " & jsonFile.string
proc genMappingFiles(conf: ConfigRef; list: CfileList): Rope =
for it in list:
addf(result, "--file:r\"$1\"$N", [rope(it.cname.string)])
result.addf("--file:r\"$1\"$N", [rope(it.cname.string)])
proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) =
if optGenMapping notin conf.globalOptions: return
var code = rope("[C_Files]\n")
add(code, genMappingFiles(conf, conf.toCompile))
add(code, "\n[C_Compiler]\nFlags=")
add(code, strutils.escape(getCompileOptions(conf)))
code.add(genMappingFiles(conf, conf.toCompile))
code.add("\n[C_Compiler]\nFlags=")
code.add(strutils.escape(getCompileOptions(conf)))
add(code, "\n[Linker]\nFlags=")
add(code, strutils.escape(getLinkOptions(conf) & " " &
code.add("\n[Linker]\nFlags=")
code.add(strutils.escape(getLinkOptions(conf) & " " &
getConfigVar(conf, conf.cCompiler, ".options.linker")))
add(code, "\n[Environment]\nlibpath=")
add(code, strutils.escape(conf.libpath.string))
code.add("\n[Environment]\nlibpath=")
code.add(strutils.escape(conf.libpath.string))
addf(code, "\n[Symbols]$n$1", [symbolMapping])
code.addf("\n[Symbols]$n$1", [symbolMapping])
let filename = conf.projectPath / RelativeFile"mapping.txt"
if not writeRope(code, filename):
rawMessage(conf, errGenerated, "could not write to file: " & filename.string)

View File

@@ -22,7 +22,7 @@ type
info: TLineInfo
indent, emitPar: int
x: string # the current input line
outp: PLLStream # the ouput will be parsed by pnimsyn
outp: PLLStream # the output will be parsed by pnimsyn
subsChar, nimDirective: char
emit, conc, toStr: string
curly, bracket, par: int
@@ -75,7 +75,7 @@ proc parseLine(p: var TTmplParser) =
let d = j
var keyw = ""
while j < len and p.x[j] in PatternChars:
add(keyw, p.x[j])
keyw.add(p.x[j])
inc(j)
scanPar(p, j)

View File

@@ -20,13 +20,13 @@ proc invalidPragma(conf: ConfigRef; n: PNode) =
proc getArg(conf: ConfigRef; n: PNode, name: string, pos: int): PNode =
result = nil
if n.kind in {nkEmpty..nkNilLit}: return
for i in 1 ..< sonsLen(n):
if n.sons[i].kind == nkExprEqExpr:
if n.sons[i].sons[0].kind != nkIdent: invalidPragma(conf, n)
if cmpIgnoreStyle(n.sons[i].sons[0].ident.s, name) == 0:
return n.sons[i].sons[1]
for i in 1..<n.len:
if n[i].kind == nkExprEqExpr:
if n[i][0].kind != nkIdent: invalidPragma(conf, n)
if cmpIgnoreStyle(n[i][0].ident.s, name) == 0:
return n[i][1]
elif i == pos:
return n.sons[i]
return n[i]
proc charArg*(conf: ConfigRef; n: PNode, name: string, pos: int, default: char): char =
var x = getArg(conf, n, name, pos)
@@ -55,7 +55,7 @@ proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, cal
var line = newStringOfCap(80)
while llStreamReadLine(stdin, line):
var stripped = strip(line, leading, trailing)
if len(pattern) == 0 or startsWith(stripped, pattern):
if pattern.len == 0 or startsWith(stripped, pattern):
llStreamWriteln(result, stripped)
else:
llStreamWriteln(result, line)
@@ -63,7 +63,7 @@ proc filterStrip*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, cal
proc filterReplace*(conf: ConfigRef; stdin: PLLStream, filename: AbsoluteFile, call: PNode): PLLStream =
var sub = strArg(conf, call, "sub", 1, "")
if len(sub) == 0: invalidPragma(conf, call)
if sub.len == 0: invalidPragma(conf, call)
var by = strArg(conf, call, "by", 2, "")
result = llStreamOpen("")
var line = newStringOfCap(80)

View File

@@ -13,8 +13,8 @@ import ast, astalgo
const
someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
mEqUntracedRef, mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
mLeI, mLeF64, mLeU, mLeEnum,
mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtEnum,
mLtCh, mLtB, mLtPtr}
proc isCounter(s: PSym): bool {.inline.} =
@@ -45,13 +45,13 @@ proc counterInTree(n, loop: PNode; counter: PSym): bool =
for it in n:
if counterInTree(it.lastSon): return true
else:
for i in 0 ..< safeLen(n):
for i in 0..<n.safeLen:
if counterInTree(n[i], loop, counter): return true
proc copyExcept(n: PNode, x, dest: PNode) =
if x == n: return
if n.kind in {nkStmtList, nkStmtListExpr}:
for i in 0 ..< n.len: copyExcept(n[i], x, dest)
for i in 0..<n.len: copyExcept(n[i], x, dest)
else:
dest.add n

View File

@@ -40,6 +40,7 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
readSuccessful = true
# only cache successful runs:
if result[1] == 0:
@@ -54,5 +55,6 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (str
p.inputStream.write(input)
p.inputStream.close()
result = p.readOutput
p.close()
except IOError, OSError:
result = ("", -1)

View File

@@ -10,22 +10,21 @@
## This module implements the 'implies' relation for guards.
import ast, astalgo, msgs, magicsys, nimsets, trees, types, renderer, idents,
saturate, modulegraphs, options, lineinfos
saturate, modulegraphs, options, lineinfos, int128
const
someEq = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc,
mEqUntracedRef, mEqStr, mEqSet, mEqCString}
mEqStr, mEqSet, mEqCString}
# set excluded here as the semantics are vastly different:
someLe = {mLeI, mLeF64, mLeU, mLeU64, mLeEnum,
someLe = {mLeI, mLeF64, mLeU, mLeEnum,
mLeCh, mLeB, mLePtr, mLeStr}
someLt = {mLtI, mLtF64, mLtU, mLtU64, mLtEnum,
someLt = {mLtI, mLtF64, mLtU, mLtEnum,
mLtCh, mLtB, mLtPtr, mLtStr}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq,
mXLenStr, mXLenSeq}
someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq}
someIn = {mInRange, mInSet}
someIn = {mInSet}
someHigh = {mHigh}
# we don't list unsigned here because wrap around semantics suck for
@@ -35,8 +34,8 @@ const
someMul = {mMulI, mMulF64}
someDiv = {mDivI, mDivF64}
someMod = {mModI}
someMax = {mMaxI, mMaxF64}
someMin = {mMinI, mMinF64}
someMax = {mMaxI}
someMin = {mMinI}
someBinaryOp = someAdd+someSub+someMul+someMax+someMin
proc isValue(n: PNode): bool = n.kind in {nkCharLit..nkNilLit}
@@ -65,16 +64,16 @@ proc isLetLocation(m: PNode, isApprox: bool): bool =
while true:
case n.kind
of nkDotExpr, nkCheckedFieldExpr, nkObjUpConv, nkObjDownConv:
n = n.sons[0]
n = n[0]
of nkDerefExpr, nkHiddenDeref:
n = n.sons[0]
n = n[0]
inc derefs
of nkBracketExpr:
if isConstExpr(n.sons[1]) or isLet(n.sons[1]) or isConstExpr(n.sons[1].skipConv):
n = n.sons[0]
if isConstExpr(n[1]) or isLet(n[1]) or isConstExpr(n[1].skipConv):
n = n[0]
else: return
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
n = n.sons[1]
n = n[1]
else:
break
result = n.isLet and derefs <= ord(isApprox)
@@ -105,34 +104,34 @@ proc initOperators*(g: ModuleGraph): Operators =
proc swapArgs(fact: PNode, newOp: PSym): PNode =
result = newNodeI(nkCall, fact.info, 3)
result.sons[0] = newSymNode(newOp)
result.sons[1] = fact.sons[2]
result.sons[2] = fact.sons[1]
result[0] = newSymNode(newOp)
result[1] = fact[2]
result[2] = fact[1]
proc neg(n: PNode; o: Operators): PNode =
if n == nil: return nil
case n.getMagic
of mNot:
result = n.sons[1]
result = n[1]
of someLt:
# not (a < b) == a >= b == b <= a
result = swapArgs(n, o.opLe)
of someLe:
result = swapArgs(n, o.opLt)
of mInSet:
if n.sons[1].kind != nkCurly: return nil
let t = n.sons[2].typ.skipTypes(abstractInst)
if n[1].kind != nkCurly: return nil
let t = n[2].typ.skipTypes(abstractInst)
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = n.sons[0]
result.sons[2] = n.sons[2]
result[0] = n[0]
result[2] = n[2]
if t.kind == tyEnum:
var s = newNodeIT(nkCurly, n.info, n.sons[1].typ)
var s = newNodeIT(nkCurly, n.info, n[1].typ)
for e in t.n:
let eAsNode = newIntNode(nkIntLit, e.sym.position)
if not inSet(n.sons[1], eAsNode): s.add eAsNode
result.sons[1] = s
if not inSet(n[1], eAsNode): s.add eAsNode
result[1] = s
#elif t.kind notin {tyString, tySequence} and lengthOrd(t) < 1000:
# result.sons[1] = complement(n.sons[1])
# result[1] = complement(n[1])
else:
# not ({2, 3, 4}.contains(x)) x != 2 and x != 3 and x != 4
# XXX todo
@@ -140,13 +139,13 @@ proc neg(n: PNode; o: Operators): PNode =
of mOr:
# not (a or b) --> not a and not b
let
a = n.sons[1].neg(o)
b = n.sons[2].neg(o)
a = n[1].neg(o)
b = n[2].neg(o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
elif a != nil:
result = a
elif b != nil:
@@ -154,19 +153,19 @@ proc neg(n: PNode; o: Operators): PNode =
else:
# leave not (a == 4) as it is
result = newNodeI(nkCall, n.info, 2)
result.sons[0] = newSymNode(o.opNot)
result.sons[1] = n
result[0] = newSymNode(o.opNot)
result[1] = n
proc buildCall(op: PSym; a: PNode): PNode =
result = newNodeI(nkCall, a.info, 2)
result.sons[0] = newSymNode(op)
result.sons[1] = a
result[0] = newSymNode(op)
result[1] = a
proc buildCall(op: PSym; a, b: PNode): PNode =
result = newNodeI(nkInfix, a.info, 3)
result.sons[0] = newSymNode(op)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(op)
result[1] = a
result[2] = b
proc `|+|`(a, b: PNode): PNode =
result = copyNode(a)
@@ -250,35 +249,35 @@ proc pred(n: PNode): PNode =
else:
result = n
proc buildLe*(o: Operators; a, b: PNode): PNode =
result = o.opLe.buildCall(a, b)
proc canon*(n: PNode; o: Operators): PNode =
# XXX for now only the new code in 'semparallel' uses this
if n.safeLen >= 1:
result = shallowCopy(n)
for i in 0 ..< n.len:
result.sons[i] = canon(n.sons[i], o)
for i in 0..<n.len:
result[i] = canon(n[i], o)
elif n.kind == nkSym and n.sym.kind == skLet and
n.sym.astdef.getMagic in (someEq + someAdd + someMul + someMin +
someMax + someHigh + {mUnaryLt} + someSub + someLen + someDiv):
someMax + someHigh + someSub + someLen + someDiv):
result = n.sym.astdef.copyTree
else:
result = n
case result.getMagic
of someEq, someAdd, someMul, someMin, someMax:
# these are symmetric; put value as last:
if result.sons[1].isValue and not result.sons[2].isValue:
result = swapArgs(result, result.sons[0].sym)
if result[1].isValue and not result[2].isValue:
result = swapArgs(result, result[0].sym)
# (4 + foo) + 2 --> (foo + 4) + 2
of someHigh:
# high == len+(-1)
result = o.opAdd.buildCall(o.opLen.buildCall(result[1]), minusOne())
of mUnaryLt:
result = buildCall(o.opAdd, result[1], minusOne())
of someSub:
# x - 4 --> x + (-4)
result = negate(result[1], result[2], result, o)
of someLen:
result.sons[0] = o.opLen.newSymNode
of someLt:
result[0] = o.opLen.newSymNode
of someLt - {mLtF64}:
# x < y same as x <= y-1:
let y = n[2].canon(o)
let p = pred(y)
@@ -318,16 +317,16 @@ proc canon*(n: PNode; o: Operators): PNode =
if plus != nil and not isLetLocation(x, true):
result = buildCall(result[0].sym, plus, y[1])
else: discard
elif x.isValue and y.getMagic in someAdd and y[2].isValue:
elif x.isValue and y.getMagic in someAdd and y[2].kind == x.kind:
# 0 <= a.len + 3
# -3 <= a.len
result.sons[1] = x |-| y[2]
result.sons[2] = y[1]
elif x.isValue and y.getMagic in someSub and y[2].isValue:
result[1] = x |-| y[2]
result[2] = y[1]
elif x.isValue and y.getMagic in someSub and y[2].kind == x.kind:
# 0 <= a.len - 3
# 3 <= a.len
result.sons[1] = x |+| y[2]
result.sons[2] = y[1]
result[1] = x |+| y[2]
result[2] = y[1]
else: discard
proc buildAdd*(a: PNode; b: BiggestInt; o: Operators): PNode =
@@ -336,41 +335,43 @@ proc buildAdd*(a: PNode; b: BiggestInt; o: Operators): PNode =
proc usefulFact(n: PNode; o: Operators): PNode =
case n.getMagic
of someEq:
if skipConv(n.sons[2]).kind == nkNilLit and (
isLetLocation(n.sons[1], false) or isVar(n.sons[1])):
result = o.opIsNil.buildCall(n.sons[1])
if skipConv(n[2]).kind == nkNilLit and (
isLetLocation(n[1], false) or isVar(n[1])):
result = o.opIsNil.buildCall(n[1])
else:
if isLetLocation(n.sons[1], true) or isLetLocation(n.sons[2], true):
if isLetLocation(n[1], true) or isLetLocation(n[2], true):
# XXX algebraic simplifications! 'i-1 < a.len' --> 'i < a.len+1'
result = n
elif n[1].getMagic in someLen or n[2].getMagic in someLen:
result = n
of someLe+someLt:
if isLetLocation(n.sons[1], true) or isLetLocation(n.sons[2], true):
if isLetLocation(n[1], true) or isLetLocation(n[2], true):
# XXX algebraic simplifications! 'i-1 < a.len' --> 'i < a.len+1'
result = n
elif n[1].getMagic in someLen or n[2].getMagic in someLen:
# XXX Rethink this whole idea of 'usefulFact' for semparallel
result = n
of mIsNil:
if isLetLocation(n.sons[1], false) or isVar(n.sons[1]):
if isLetLocation(n[1], false) or isVar(n[1]):
result = n
of someIn:
if isLetLocation(n.sons[1], true):
if isLetLocation(n[1], true):
result = n
of mAnd:
let
a = usefulFact(n.sons[1], o)
b = usefulFact(n.sons[2], o)
a = usefulFact(n[1], o)
b = usefulFact(n[2], o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
elif a != nil:
result = a
elif b != nil:
result = b
of mNot:
let a = usefulFact(n.sons[1], o)
let a = usefulFact(n[1], o)
if a != nil:
result = a.neg(o)
of mOr:
@@ -381,13 +382,13 @@ proc usefulFact(n: PNode; o: Operators): PNode =
# (x == 3) or (y == 2) ---> not ( not (x==3) and not (y == 2))
# not (x != 3 and y != 2)
let
a = usefulFact(n.sons[1], o).neg(o)
b = usefulFact(n.sons[2], o).neg(o)
a = usefulFact(n[1], o).neg(o)
b = usefulFact(n[2], o).neg(o)
if a != nil and b != nil:
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opAnd)
result.sons[1] = a
result.sons[2] = b
result[0] = newSymNode(o.opAnd)
result[1] = a
result[2] = b
result = result.neg(o)
elif n.kind == nkSym and n.sym.kind == skLet:
# consider:
@@ -404,10 +405,20 @@ type
TModel* = object
s*: seq[PNode] # the "knowledge base"
o*: Operators
beSmart*: bool
proc addFact*(m: var TModel, nn: PNode) =
let n = usefulFact(nn, m.o)
if n != nil: m.s.add n
if n != nil:
if not m.beSmart:
m.s.add n
else:
let c = canon(n, m.o)
if c.getMagic == mAnd:
addFact(m, c[1])
addFact(m, c[2])
else:
m.s.add c
proc addFactNeg*(m: var TModel, n: PNode) =
let n = n.neg(m.o)
@@ -436,22 +447,22 @@ proc sameTree*(a, b: PNode): bool =
if not result and a.sym.magic != mNone:
result = a.sym.magic == b.sym.magic or sameOpr(a.sym, b.sym)
of nkIdent: result = a.ident.id == b.ident.id
of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
of nkCharLit..nkUInt64Lit: result = a.intVal == b.intVal
of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
of nkType: result = a.typ == b.typ
of nkEmpty, nkNilLit: result = true
else:
if sonsLen(a) == sonsLen(b):
for i in 0 ..< sonsLen(a):
if not sameTree(a.sons[i], b.sons[i]): return
if a.len == b.len:
for i in 0..<a.len:
if not sameTree(a[i], b[i]): return
result = true
proc hasSubTree(n, x: PNode): bool =
if n.sameTree(x): result = true
else:
for i in 0..safeLen(n)-1:
if hasSubTree(n.sons[i], x): return true
for i in 0..n.safeLen-1:
if hasSubTree(n[i], x): return true
proc invalidateFacts*(m: var TModel, n: PNode) =
# We are able to guard local vars (as opposed to 'let' variables)!
@@ -479,21 +490,21 @@ proc valuesUnequal(a, b: PNode): bool =
result = not sameValue(a, b)
proc impliesEq(fact, eq: PNode): TImplication =
let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1)
let (loc, val) = if isLocation(eq[1]): (1, 2) else: (2, 1)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], eq.sons[loc]):
if sameTree(fact[1], eq[loc]):
# this is not correct; consider: a == b; a == 1 --> unknown!
if sameTree(fact.sons[2], eq.sons[val]): result = impYes
elif valuesUnequal(fact.sons[2], eq.sons[val]): result = impNo
elif sameTree(fact.sons[2], eq.sons[loc]):
if sameTree(fact.sons[1], eq.sons[val]): result = impYes
elif valuesUnequal(fact.sons[1], eq.sons[val]): result = impNo
if sameTree(fact[2], eq[val]): result = impYes
elif valuesUnequal(fact[2], eq[val]): result = impNo
elif sameTree(fact[2], eq[loc]):
if sameTree(fact[1], eq[val]): result = impYes
elif valuesUnequal(fact[1], eq[val]): result = impNo
of mInSet:
# remember: mInSet is 'contains' so the set comes first!
if sameTree(fact.sons[2], eq.sons[loc]) and isValue(eq.sons[val]):
if inSet(fact.sons[1], eq.sons[val]): result = impYes
if sameTree(fact[2], eq[loc]) and isValue(eq[val]):
if inSet(fact[1], eq[val]): result = impYes
else: result = impNo
of mNot, mOr, mAnd: assert(false, "impliesEq")
else: discard
@@ -522,7 +533,7 @@ proc geImpliesIn(x, c, aSet: PNode): TImplication =
var value = newIntNode(c.kind, c.intVal)
let max = lastOrd(nil, x.typ)
# don't iterate too often:
if max - value.intVal < 1000:
if max - getInt(value) < toInt128(1000):
var i, pos, neg: int
while value.intVal <= max:
if inSet(aSet, value): inc pos
@@ -536,28 +547,28 @@ proc compareSets(a, b: PNode): TImplication =
elif intersectSets(nil, a, b).len == 0: result = impNo
proc impliesIn(fact, loc, aSet: PNode): TImplication =
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], loc):
if inSet(aSet, fact.sons[2]): result = impYes
if sameTree(fact[1], loc):
if inSet(aSet, fact[2]): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], loc):
if inSet(aSet, fact.sons[1]): result = impYes
elif sameTree(fact[2], loc):
if inSet(aSet, fact[1]): result = impYes
else: result = impNo
of mInSet:
if sameTree(fact.sons[2], loc):
result = compareSets(fact.sons[1], aSet)
if sameTree(fact[2], loc):
result = compareSets(fact[1], aSet)
of someLe:
if sameTree(fact.sons[1], loc):
result = leImpliesIn(fact.sons[1], fact.sons[2], aSet)
elif sameTree(fact.sons[2], loc):
result = geImpliesIn(fact.sons[2], fact.sons[1], aSet)
if sameTree(fact[1], loc):
result = leImpliesIn(fact[1], fact[2], aSet)
elif sameTree(fact[2], loc):
result = geImpliesIn(fact[2], fact[1], aSet)
of someLt:
if sameTree(fact.sons[1], loc):
result = leImpliesIn(fact.sons[1], fact.sons[2].pred, aSet)
elif sameTree(fact.sons[2], loc):
if sameTree(fact[1], loc):
result = leImpliesIn(fact[1], fact[2].pred, aSet)
elif sameTree(fact[2], loc):
# 4 < x --> 3 <= x
result = geImpliesIn(fact.sons[2], fact.sons[1].pred, aSet)
result = geImpliesIn(fact[2], fact[1].pred, aSet)
of mNot, mOr, mAnd: assert(false, "impliesIn")
else: discard
@@ -567,90 +578,93 @@ proc valueIsNil(n: PNode): TImplication =
else: impUnknown
proc impliesIsNil(fact, eq: PNode): TImplication =
case fact.sons[0].sym.magic
case fact[0].sym.magic
of mIsNil:
if sameTree(fact.sons[1], eq.sons[1]):
if sameTree(fact[1], eq[1]):
result = impYes
of someEq:
if sameTree(fact.sons[1], eq.sons[1]):
result = valueIsNil(fact.sons[2].skipConv)
elif sameTree(fact.sons[2], eq.sons[1]):
result = valueIsNil(fact.sons[1].skipConv)
if sameTree(fact[1], eq[1]):
result = valueIsNil(fact[2].skipConv)
elif sameTree(fact[2], eq[1]):
result = valueIsNil(fact[1].skipConv)
of mNot, mOr, mAnd: assert(false, "impliesIsNil")
else: discard
proc impliesGe(fact, x, c: PNode): TImplication =
assert isLocation(x)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x = 4; question x >= 56? --> true iff 4 >= 56
if leValue(c, fact.sons[2]): result = impYes
if leValue(c, fact[2]): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], x):
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impYes
elif sameTree(fact[2], x):
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impYes
else: result = impNo
of someLt:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x < 4; question N <= x? --> false iff N <= 4
if leValue(fact.sons[2], c): result = impNo
if leValue(fact[2], c): result = impNo
# fact: x < 4; question 2 <= x? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 < x; question: N-1 < x ? --> true iff N-1 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c.pred, fact.sons[1]): result = impYes
if isValue(fact[1]) and isValue(c):
if leValue(c.pred, fact[1]): result = impYes
of someLe:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x <= 4; question x >= 56? --> false iff 4 <= 56
if leValue(fact.sons[2], c): result = impNo
if leValue(fact[2], c): result = impNo
# fact: x <= 4; question x >= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 <= x; question: x >= 2 ? --> true iff 2 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impYes
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impYes
of mNot, mOr, mAnd: assert(false, "impliesGe")
else: discard
proc impliesLe(fact, x, c: PNode): TImplication =
if not isLocation(x):
if c.isValue:
if leValue(x, x): return impYes
else: return impNo
return impliesGe(fact, c, x)
case fact.sons[0].sym.magic
case fact[0].sym.magic
of someEq:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x = 4; question x <= 56? --> true iff 4 <= 56
if leValue(fact.sons[2], c): result = impYes
if leValue(fact[2], c): result = impYes
else: result = impNo
elif sameTree(fact.sons[2], x):
if isValue(fact.sons[1]) and isValue(c):
if leValue(fact.sons[1], c): result = impYes
elif sameTree(fact[2], x):
if isValue(fact[1]) and isValue(c):
if leValue(fact[1], c): result = impYes
else: result = impNo
of someLt:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x < 4; question x <= N? --> true iff N-1 <= 4
if leValue(fact.sons[2], c.pred): result = impYes
if leValue(fact[2], c.pred): result = impYes
# fact: x < 4; question x <= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 < x; question: x <= 1 ? --> false iff 1 <= 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1]): result = impNo
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1]): result = impNo
of someLe:
if sameTree(fact.sons[1], x):
if isValue(fact.sons[2]) and isValue(c):
if sameTree(fact[1], x):
if isValue(fact[2]) and isValue(c):
# fact: x <= 4; question x <= 56? --> true iff 4 <= 56
if leValue(fact.sons[2], c): result = impYes
if leValue(fact[2], c): result = impYes
# fact: x <= 4; question x <= 2? --> we don't know
elif sameTree(fact.sons[2], x):
elif sameTree(fact[2], x):
# fact: 3 <= x; question: x <= 2 ? --> false iff 2 < 3
if isValue(fact.sons[1]) and isValue(c):
if leValue(c, fact.sons[1].pred): result = impNo
if isValue(fact[1]) and isValue(c):
if leValue(c, fact[1].pred): result = impNo
of mNot, mOr, mAnd: assert(false, "impliesLe")
else: discard
@@ -686,32 +700,32 @@ proc factImplies(fact, prop: PNode): TImplication =
# (not a) -> b compute as not (a -> b) ???
# == not a or not b == not (a and b)
let arg = fact.sons[1]
let arg = fact[1]
case arg.getMagic
of mIsNil, mEqRef:
return ~factImplies(arg, prop)
of mAnd:
# not (a and b) means not a or not b:
# a or b --> both need to imply 'prop'
let a = factImplies(arg.sons[1], prop)
let b = factImplies(arg.sons[2], prop)
let a = factImplies(arg[1], prop)
let b = factImplies(arg[2], prop)
if a == b: return ~a
return impUnknown
else:
return impUnknown
of mAnd:
result = factImplies(fact.sons[1], prop)
result = factImplies(fact[1], prop)
if result != impUnknown: return result
return factImplies(fact.sons[2], prop)
return factImplies(fact[2], prop)
else: discard
case prop.sons[0].sym.magic
of mNot: result = ~fact.factImplies(prop.sons[1])
case prop[0].sym.magic
of mNot: result = ~fact.factImplies(prop[1])
of mIsNil: result = impliesIsNil(fact, prop)
of someEq: result = impliesEq(fact, prop)
of someLe: result = impliesLe(fact, prop.sons[1], prop.sons[2])
of someLt: result = impliesLt(fact, prop.sons[1], prop.sons[2])
of mInSet: result = impliesIn(fact, prop.sons[2], prop.sons[1])
of someLe: result = impliesLe(fact, prop[1], prop[2])
of someLt: result = impliesLt(fact, prop[1], prop[2])
of mInSet: result = impliesIn(fact, prop[2], prop[1])
else: result = impUnknown
proc doesImply*(facts: TModel, prop: PNode): TImplication =
@@ -802,7 +816,7 @@ proc ple(m: TModel; a, b: PNode): TImplication =
if lastOrd(nil, a.typ) <= b.intVal: return impYes
# 3 <= x iff low(x) <= 3
if a.isValue and b.typ != nil and b.typ.isOrdinalType:
if firstOrd(nil, b.typ) <= a.intVal: return impYes
if a.intVal <= firstOrd(nil, b.typ): return impYes
# x <= x
if sameTree(a, b): return impYes
@@ -813,7 +827,11 @@ proc ple(m: TModel; a, b: PNode): TImplication =
# x <= y+c if 0 <= c and x <= y
# x <= y+(-c) if c <= 0 and y >= x
if b.getMagic in someAdd and zero() <=? b[2] and a <=? b[1]: return impYes
if b.getMagic in someAdd:
if zero() <=? b[2] and a <=? b[1]: return impYes
# x <= y-c if x+c <= y
if b[2] <=? zero() and (canon(m.o.opSub.buildCall(a, b[2]), m.o) <=? b[1]):
return impYes
# x+c <= y if c <= 0 and x <= y
if a.getMagic in someAdd and a[2] <=? zero() and a[1] <=? b: return impYes
@@ -881,8 +899,8 @@ proc replaceSubTree(n, x, by: PNode): PNode =
result = by
elif hasSubTree(n, x):
result = shallowCopy(n)
for i in 0 .. safeLen(n)-1:
result.sons[i] = replaceSubTree(n.sons[i], x, by)
for i in 0..n.safeLen-1:
result[i] = replaceSubTree(n[i], x, by)
else:
result = n
@@ -902,10 +920,13 @@ proc pleViaModelRec(m: var TModel; a, b: PNode): TImplication =
# --> true if (len-100) <= (len-1)
let x = fact[1]
let y = fact[2]
if sameTree(x, a) and y.getMagic in someAdd and b.getMagic in someAdd and
sameTree(y[1], b[1]):
if ple(m, b[2], y[2]) == impYes:
return impYes
# x <= y.
# Question: x <= b? True iff y <= b.
if sameTree(x, a):
if ple(m, y, b) == impYes: return impYes
if y.getMagic in someAdd and b.getMagic in someAdd and sameTree(y[1], b[1]):
if ple(m, b[2], y[2]) == impYes:
return impYes
# x <= y implies a <= b if a <= x and y <= b
if ple(m, a, x) == impYes:
@@ -964,6 +985,10 @@ proc proveLe*(m: TModel; a, b: PNode): TImplication =
proc addFactLe*(m: var TModel; a, b: PNode) =
m.s.add canon(m.o.opLe.buildCall(a, b), m.o)
proc addFactLt*(m: var TModel; a, b: PNode) =
let bb = m.o.opAdd.buildCall(b, minusOne())
addFactLe(m, a, bb)
proc settype(n: PNode): PType =
result = newType(tySet, n.typ.owner)
addSonSkipIntLit(result, n.typ)
@@ -971,37 +996,37 @@ proc settype(n: PNode): PType =
proc buildOf(it, loc: PNode; o: Operators): PNode =
var s = newNodeI(nkCurly, it.info, it.len-1)
s.typ = settype(loc)
for i in 0..it.len-2: s.sons[i] = it.sons[i]
for i in 0..<it.len-1: s[i] = it[i]
result = newNodeI(nkCall, it.info, 3)
result.sons[0] = newSymNode(o.opContains)
result.sons[1] = s
result.sons[2] = loc
result[0] = newSymNode(o.opContains)
result[1] = s
result[2] = loc
proc buildElse(n: PNode; o: Operators): PNode =
var s = newNodeIT(nkCurly, n.info, settype(n.sons[0]))
for i in 1..n.len-2:
let branch = n.sons[i]
var s = newNodeIT(nkCurly, n.info, settype(n[0]))
for i in 1..<n.len-1:
let branch = n[i]
assert branch.kind != nkElse
if branch.kind == nkOfBranch:
for j in 0..branch.len-2:
s.add(branch.sons[j])
for j in 0..<branch.len-1:
s.add(branch[j])
result = newNodeI(nkCall, n.info, 3)
result.sons[0] = newSymNode(o.opContains)
result.sons[1] = s
result.sons[2] = n.sons[0]
result[0] = newSymNode(o.opContains)
result[1] = s
result[2] = n[0]
proc addDiscriminantFact*(m: var TModel, n: PNode) =
var fact = newNodeI(nkCall, n.info, 3)
fact.sons[0] = newSymNode(m.o.opEq)
fact.sons[1] = n.sons[0]
fact.sons[2] = n.sons[1]
fact[0] = newSymNode(m.o.opEq)
fact[1] = n[0]
fact[2] = n[1]
m.s.add fact
proc addAsgnFact*(m: var TModel, key, value: PNode) =
var fact = newNodeI(nkCall, key.info, 3)
fact.sons[0] = newSymNode(m.o.opEq)
fact.sons[1] = key
fact.sons[2] = value
fact[0] = newSymNode(m.o.opEq)
fact[1] = key
fact[2] = value
m.s.add fact
proc sameSubexprs*(m: TModel; a, b: PNode): bool =
@@ -1015,34 +1040,34 @@ proc sameSubexprs*(m: TModel; a, b: PNode): bool =
# However, nil checking requires exactly the same mechanism! But for now
# we simply use sameTree and live with the unsoundness of the analysis.
var check = newNodeI(nkCall, a.info, 3)
check.sons[0] = newSymNode(m.o.opEq)
check.sons[1] = a
check.sons[2] = b
check[0] = newSymNode(m.o.opEq)
check[1] = a
check[2] = b
result = m.doesImply(check) == impYes
proc addCaseBranchFacts*(m: var TModel, n: PNode, i: int) =
let branch = n.sons[i]
let branch = n[i]
if branch.kind == nkOfBranch:
m.s.add buildOf(branch, n.sons[0], m.o)
m.s.add buildOf(branch, n[0], m.o)
else:
m.s.add n.buildElse(m.o).neg(m.o)
proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
if check.sons[1].kind == nkCurly:
if check[1].kind == nkCurly:
result = copyTree(check)
if access.kind == nkDotExpr:
var a = copyTree(access)
a.sons[1] = check.sons[2]
result.sons[2] = a
a[1] = check[2]
result[2] = a
# 'access.kind != nkDotExpr' can happen for object constructors
# which we don't check yet
else:
# it is some 'not'
assert check.getMagic == mNot
result = buildProperFieldCheck(access, check.sons[1], o).neg(o)
result = buildProperFieldCheck(access, check[1], o).neg(o)
proc checkFieldAccess*(m: TModel, n: PNode; conf: ConfigRef) =
for i in 1..n.len-1:
let check = buildProperFieldCheck(n.sons[0], n.sons[i], m.o)
for i in 1..<n.len:
let check = buildProperFieldCheck(n[0], n[i], m.o)
if check != nil and m.doesImply(check) != impYes:
message(conf, n.info, warnProveField, renderTree(n.sons[0])); break
message(conf, n.info, warnProveField, renderTree(n[0])); break

View File

@@ -12,14 +12,14 @@
proc hlo(c: PContext, n: PNode): PNode
proc evalPattern(c: PContext, n, orig: PNode): PNode =
internalAssert c.config, n.kind == nkCall and n.sons[0].kind == nkSym
internalAssert c.config, n.kind == nkCall and n[0].kind == nkSym
# we need to ensure that the resulting AST is semchecked. However, it's
# aweful to semcheck before macro invocation, so we don't and treat
# awful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context.
var rule: string
if optHints in c.config.options and hintPattern in c.config.notes:
if c.config.hasHint(hintPattern):
rule = renderTree(n, {renderNoComments})
let s = n.sons[0].sym
let s = n[0].sym
case s.kind
of skMacro:
result = semMacroExpr(c, n, orig, s)
@@ -27,7 +27,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
result = semTemplateExpr(c, n, s, {efFromHlo})
else:
result = semDirectOp(c, n, {})
if optHints in c.config.options and hintPattern in c.config.notes:
if c.config.hasHint(hintPattern):
message(c.config, orig.info, hintPattern, rule & " --> '" &
renderTree(result, {renderNoComments}) & "'")
@@ -50,7 +50,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
c.patterns[i] = nil
if x.kind == nkStmtList:
assert x.len == 3
x.sons[1] = evalPattern(c, x.sons[1], result)
x[1] = evalPattern(c, x[1], result)
result = flattenStmts(x)
else:
result = evalPattern(c, x, result)
@@ -68,17 +68,17 @@ proc hlo(c: PContext, n: PNode): PNode =
result = n
else:
if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
n.sons[0].kind == nkSym and
{sfGlobal, sfPure} * n.sons[0].sym.flags == {sfGlobal, sfPure}:
n[0].kind == nkSym and
{sfGlobal, sfPure} * n[0].sym.flags == {sfGlobal, sfPure}:
# do not optimize 'var g {.global} = re(...)' again!
return n
result = applyPatterns(c, n)
if result == n:
# no optimization applied, try subtrees:
for i in 0 ..< safeLen(result):
let a = result.sons[i]
for i in 0..<result.safeLen:
let a = result[i]
let h = hlo(c, a)
if h != a: result.sons[i] = h
if h != a: result[i] = h
else:
# perform type checking, so that the replacement still fits:
if isEmptyType(n.typ) and isEmptyType(result.typ):

View File

@@ -87,7 +87,7 @@ proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIden
new(result)
result.h = h
result.s = newString(length)
for i in 0 ..< length: result.s[i] = identifier[i]
for i in 0..<length: result.s[i] = identifier[i]
result.next = ic.buckets[idx]
ic.buckets[idx] = result
if id == 0:
@@ -97,11 +97,11 @@ proc getIdent*(ic: IdentCache; identifier: cstring, length: int, h: Hash): PIden
result.id = id
proc getIdent*(ic: IdentCache; identifier: string): PIdent =
result = getIdent(ic, cstring(identifier), len(identifier),
result = getIdent(ic, cstring(identifier), identifier.len,
hashIgnoreStyle(identifier))
proc getIdent*(ic: IdentCache; identifier: string, h: Hash): PIdent =
result = getIdent(ic, cstring(identifier), len(identifier), h)
result = getIdent(ic, cstring(identifier), identifier.len, h)
proc newIdentCache*(): IdentCache =
result = IdentCache()
@@ -110,7 +110,7 @@ proc newIdentCache*(): IdentCache =
result.idDelegator = result.getIdent":delegator"
result.emptyIdent = result.getIdent("")
# initialize the keywords:
for s in succ(low(specialWords)) .. high(specialWords):
for s in succ(low(specialWords))..high(specialWords):
result.getIdent(specialWords[s], hashIgnoreStyle(specialWords[s])).id = ord(s)
proc whichKeyword*(id: PIdent): TSpecialWord =

View File

@@ -11,12 +11,12 @@
import
intsets, ast, astalgo, msgs, options, idents, lookups,
semdata, modulepaths, sigmatch, lineinfos
semdata, modulepaths, sigmatch, lineinfos, sets
proc readExceptSet*(c: PContext, n: PNode): IntSet =
assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
result = initIntSet()
for i in 1 ..< n.len:
for i in 1..<n.len:
let ident = lookups.considerQuotedIdent(c, n[i])
result.incl(ident.id)
@@ -27,11 +27,11 @@ proc importPureEnumField*(c: PContext; s: PSym) =
if checkB == nil:
strTableAdd(c.pureEnumFields, s)
else:
# mark as ambigous:
# mark as ambiguous:
incl(c.ambiguousSymbols, checkB.id)
incl(c.ambiguousSymbols, s.id)
proc rawImportSymbol(c: PContext, s: PSym) =
proc rawImportSymbol(c: PContext, s, origin: PSym) =
# This does not handle stubs, because otherwise loading on demand would be
# pointless in practice. So importing stubs is fine here!
# check if we have already a symbol of the same name:
@@ -47,8 +47,8 @@ proc rawImportSymbol(c: PContext, s: PSym) =
if s.kind == skType:
var etyp = s.typ
if etyp.kind in {tyBool, tyEnum}:
for j in 0 ..< sonsLen(etyp.n):
var e = etyp.n.sons[j].sym
for j in 0..<etyp.n.len:
var e = etyp.n[j].sym
if e.kind != skEnumField:
internalError(c.config, s.info, "rawImportSymbol")
# BUGFIX: because of aliases for enums the symbol may already
@@ -63,13 +63,14 @@ proc rawImportSymbol(c: PContext, s: PSym) =
check = nextIdentIter(it, c.importTable.symbols)
if e != nil:
if sfPure notin s.flags:
rawImportSymbol(c, e)
rawImportSymbol(c, e, origin)
else:
importPureEnumField(c, e)
else:
# rodgen assures that converters and patterns are no stubs
if s.kind == skConverter: addConverter(c, s)
if hasPattern(s): addPattern(c, s)
if s.owner != origin:
c.exportIndirections.incl((origin.id, s.id))
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerQuotedIdent(c, n)
@@ -88,10 +89,10 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
while e != nil:
if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3")
if s.kind in ExportableSymKinds:
rawImportSymbol(c, e)
rawImportSymbol(c, e, fromMod)
e = nextIdentIter(it, fromMod.tab)
else:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
suggestSym(c.config, n.info, s, c.graph.usageSym, false)
proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
@@ -103,14 +104,14 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) =
if s.kind notin ExportableSymKinds:
internalError(c.config, s.info, "importAllSymbols: " & $s.kind & " " & s.name.s)
if exceptSet.isNil or s.name.id notin exceptSet:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
s = nextIter(i, fromMod.tab)
proc importAllSymbols*(c: PContext, fromMod: PSym) =
var exceptSet: IntSet
importAllSymbolsExcept(c, fromMod, exceptSet)
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym) =
if n.isNil: return
case n.kind
of nkExportStmt:
@@ -120,21 +121,22 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) =
if s.kind == skModule:
importAllSymbolsExcept(c, s, exceptSet)
elif exceptSet.isNil or s.name.id notin exceptSet:
rawImportSymbol(c, s)
rawImportSymbol(c, s, fromMod)
of nkExportExceptStmt:
localError(c.config, n.info, "'export except' not implemented")
else:
for i in 0..safeLen(n)-1:
importForwarded(c, n.sons[i], exceptSet)
for i in 0..n.safeLen-1:
importForwarded(c, n[i], exceptSet, fromMod)
proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
result = realModule
c.unusedImports.add((realModule, n.info))
if n.kind != nkImportAs: discard
elif n.len != 2 or n.sons[1].kind != nkIdent:
elif n.len != 2 or n[1].kind != nkIdent:
localError(c.config, n.info, "module alias must be an identifier")
elif n.sons[1].ident.id != realModule.name.id:
elif n[1].ident.id != realModule.name.id:
# some misguided guy will write 'import abc.foo as foo' ...
result = createModuleAlias(realModule, n.sons[1].ident, realModule.info,
result = createModuleAlias(realModule, n[1].ident, realModule.info,
c.config.options)
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
@@ -146,12 +148,16 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
#echo "adding ", toFullPath(f), " at ", L+1
if recursion >= 0:
var err = ""
for i in recursion ..< L:
for i in recursion..<L:
if i > recursion: err.add "\n"
err.add toFullPath(c.config, c.graph.importStack[i]) & " imports " &
toFullPath(c.config, c.graph.importStack[i+1])
c.recursiveDep = err
discard pushOptionEntry(c)
result = importModuleAs(c, n, c.graph.importModuleCallback(c.graph, c.module, f))
popOptionEntry(c)
#echo "set back to ", L
c.graph.importStack.setLen(L)
# we cannot perform this check reliably because of
@@ -172,8 +178,8 @@ proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
proc transformImportAs(c: PContext; n: PNode): PNode =
if n.kind == nkInfix and considerQuotedIdent(c, n[0]).s == "as":
result = newNodeI(nkImportAs, n.info)
result.add n.sons[1]
result.add n.sons[2]
result.add n[1]
result.add n[2]
else:
result = n
@@ -185,12 +191,12 @@ proc impMod(c: PContext; it: PNode; importStmtResult: PNode) =
# ``addDecl`` needs to be done before ``importAllSymbols``!
addDecl(c, m, it.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, emptySet)
#importForwarded(c, m.ast, emptySet)
#importForwarded(c, m.ast, emptySet, m)
proc evalImport*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
for i in 0 ..< sonsLen(n):
let it = n.sons[i]
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]
@@ -200,13 +206,13 @@ proc evalImport*(c: PContext, n: PNode): PNode =
imp.add sep # dummy entry, replaced in the loop
for x in it[2]:
# transform `a/b/[c as d]` to `/a/b/c as d`
if x.kind == nkInfix and x.sons[0].ident.s == "as":
if x.kind == nkInfix and x[0].ident.s == "as":
let impAs = copyTree(x)
imp.sons[2] = x.sons[1]
impAs.sons[1] = imp
imp[2] = x[1]
impAs[1] = imp
impMod(c, imp, result)
else:
imp.sons[2] = x
imp[2] = x
impMod(c, imp, result)
else:
impMod(c, it, result)
@@ -214,22 +220,22 @@ proc evalImport*(c: PContext, n: PNode): PNode =
proc evalFrom*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
n[0] = transformImportAs(c, n[0])
var m = myImportModule(c, n[0], result)
if m != nil:
n.sons[0] = newSymNode(m)
n[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
for i in 1 ..< sonsLen(n):
if n.sons[i].kind != nkNilLit:
importSymbol(c, n.sons[i], m)
for i in 1..<n.len:
if n[i].kind != nkNilLit:
importSymbol(c, n[i], m)
proc evalImportExcept*(c: PContext, n: PNode): PNode =
result = newNodeI(nkImportStmt, n.info)
checkMinSonsLen(n, 2, c.config)
n.sons[0] = transformImportAs(c, n.sons[0])
var m = myImportModule(c, n.sons[0], result)
n[0] = transformImportAs(c, n[0])
var m = myImportModule(c, n[0], result)
if m != nil:
n.sons[0] = newSymNode(m)
n[0] = newSymNode(m)
addDecl(c, m, n.info) # add symbol to symbol table of module
importAllSymbolsExcept(c, m, readExceptSet(c, n))
#importForwarded(c, m.ast, exceptSet)
#importForwarded(c, m.ast, exceptSet, m)

View File

@@ -10,7 +10,7 @@
## Basic type definitions the module graph needs in order to support
## incremental compilations.
const nimIncremental* = true # defined(nimIncremental)
const nimIncremental* = defined(nimIncremental)
import options, lineinfos

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,10 @@ Name: "Nim"
Version: "$version"
Platforms: """
windows: i386;amd64
linux: i386;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
linux: i386;hppa;ia64;alpha;amd64;powerpc64;arm;sparc;sparc64;m68k;mips;mipsel;mips64;mips64el;powerpc;powerpc64el;arm64;riscv64
macosx: i386;amd64;powerpc64
solaris: i386;amd64;sparc;sparc64
freebsd: i386;amd64
freebsd: i386;amd64;powerpc64;arm;arm64
netbsd: i386;amd64
openbsd: i386;amd64
dragonfly: i386;amd64
@@ -65,6 +65,7 @@ Files: "compiler"
Files: "doc"
Files: "doc/html"
Files: "tools"
Files: "tools/nim-gdb.py"
Files: "nimpretty"
Files: "testament"
Files: "nimsuggest"
@@ -87,6 +88,7 @@ Files: "bin/nimble.exe"
Files: "bin/vccexe.exe"
Files: "bin/nimgrab.exe"
Files: "bin/nimpretty.exe"
Files: "bin/testament.exe"
Files: "koch.exe"
Files: "finish.exe"
@@ -137,4 +139,4 @@ licenses: "bin/nim,MIT;lib/*,MIT;"
[nimble]
pkgName: "compiler"
pkgFiles: "compiler/*;doc/basicopt.txt;doc/advopt.txt"
pkgFiles: "compiler/*;doc/basicopt.txt;doc/advopt.txt;doc/nimdoc.css"

View File

@@ -1,4 +1,9 @@
## This module is for compiler internal use only. For reliable error
## messages and range checks, the compiler needs a data type that can
## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
## type is for that purpose.
from math import trunc
type
Int128* = object
@@ -11,46 +16,40 @@ template sdata(arg: Int128, idx: int): int32 =
# encoding least significant int first (like LittleEndian)
type
InvalidArgument = object of Exception
template require(cond: bool) =
if unlikely(not cond):
raise newException(InvalidArgument, "")
const
Zero* = Int128(udata: [0'u32,0,0,0])
One* = Int128(udata: [1'u32,0,0,0])
Ten* = Int128(udata: [10'u32,0,0,0])
Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
template low*(t: typedesc[Int128]): Int128 = Min
template high*(t: typedesc[Int128]): Int128 = Max
proc `$`*(a: Int128): string
proc toInt128*[T: SomeInteger](arg: T): Int128 =
when T is SomeUnsignedInt:
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)
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:
when 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
@@ -74,13 +73,96 @@ proc toInt64*(arg: Int128): int64 =
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt64Checked*(arg: Int128; onError: int64): int64 =
if isNegative(arg):
if arg.sdata(3) != -1 or arg.sdata(2) != -1:
return onError
else:
if arg.sdata(3) != 0 or arg.sdata(2) != 0:
return onError
return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc toInt32*(arg: Int128): int32 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
arg.sdata(0)
proc toInt16*(arg: Int128): int16 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int16(arg.sdata(0))
proc toInt8*(arg: Int128): int8 =
if isNegative(arg):
assert(arg.sdata(3) == -1, "out of range")
assert(arg.sdata(2) == -1, "out of range")
assert(arg.sdata(1) == -1, "out of range")
else:
assert(arg.sdata(3) == 0, "out of range")
assert(arg.sdata(2) == 0, "out of range")
assert(arg.sdata(1) == 0, "out of range")
int8(arg.sdata(0))
proc toInt*(arg: Int128): int =
when sizeof(int) == 4:
cast[int](toInt32(arg))
else:
cast[int](toInt64(arg))
proc toUInt64*(arg: Int128): uint64 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
bitconcat(arg.udata[1], arg.udata[0])
proc toUInt32*(arg: Int128): uint32 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
arg.udata[0]
proc toUInt16*(arg: Int128): uint16 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint16(arg.udata[0])
proc toUInt8*(arg: Int128): uint8 =
assert(arg.udata[3] == 0)
assert(arg.udata[2] == 0)
assert(arg.udata[1] == 0)
uint8(arg.udata[0])
proc toUInt*(arg: Int128): uint =
when sizeof(int) == 4:
cast[uint](toInt32(arg))
else:
cast[uint](toInt64(arg))
proc castToInt64*(arg: Int128): int64 =
## Conversion to int64 without range check.
cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
proc castToUInt64*(arg: Int128): uint64 =
## Conversion to uint64 without range check.
cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
proc addToHex(result: var string; arg: uint32) =
for i in 0 ..< 8:
for i in 0..<8:
let idx = (arg shr ((7-i) * 4)) and 0xf
result.add "0123456789abcdef"[idx]
@@ -168,14 +250,14 @@ proc `shr`*(a: Int128, b: int): Int128 =
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = a.sdata(3) shr (b and 31)
result.udata[1] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr (b and 31))
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr (b and 31))
result.udata[1] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
result.udata[0] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr (b and 31))
elif b < 96:
if isNegative(a):
result.sdata(3) = -1
result.sdata(2) = -1
result.sdata(1) = a.sdata(3) shr (b and 31)
result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr (b and 31))
result.udata[0] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
else: # b < 128
if isNegative(a):
result.sdata(3) = -1
@@ -206,7 +288,6 @@ proc `shl`*(a: Int128, b: int): Int128 =
result.udata[2] = 0
result.udata[3] = a.udata[0] shl (b and 31)
proc `+`*(a,b: Int128): Int128 =
let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
result.udata[0] = cast[uint32](tmp0)
@@ -254,7 +335,6 @@ proc `*`(a: Int128, b: uint32): Int128 =
result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
proc `*`*(a: Int128, b: int32): Int128 =
let isNegative = isNegative(a) xor isNegative(b)
result = a * cast[uint32](abs(b))
if b < 0:
result = -result
@@ -275,8 +355,6 @@ proc low64(a: Int128): uint64 =
bitconcat(a.udata[1], a.udata[0])
proc `*`*(lhs,rhs: Int128): Int128 =
let isNegative = isNegative(lhs) xor isNegative(rhs)
let
a = cast[uint64](lhs.udata[0])
b = cast[uint64](lhs.udata[1])
@@ -298,10 +376,6 @@ proc `*`*(lhs,rhs: Int128): Int128 =
result = result + toInt128(a32 * b00) shl 32
result = result + toInt128(a00 * b32) shl 32
if isNegative != isNegative(result):
echo result
assert(false, "overflow")
proc `*=`*(a: var Int128, b: Int128) =
a = a * b
@@ -319,18 +393,25 @@ proc fastLog2*(a: Int128): int =
proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
assert(divisor != Zero)
let isNegative = isNegative(dividend) xor isNegative(divisor)
let isNegativeA = isNegative(dividend)
let isNegativeB = isNegative(divisor)
var dividend = abs(dividend)
let divisor = abs(divisor)
if divisor > dividend:
result.quotient = Zero
result.remainder = dividend
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
return
if divisor == dividend:
result.quotient = One
if isNegativeA xor isNegativeB:
result.quotient = NegOne
else:
result.quotient = One
result.remainder = Zero
return
@@ -343,7 +424,7 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
# Uses shift-subtract algorithm to divide dividend by denominator. The
# remainder will be left in dividend.
for i in 0 .. shift:
for i in 0..shift:
quotient = quotient shl 1
if dividend >= denominator:
dividend = dividend - denominator
@@ -351,8 +432,14 @@ proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
denominator = denominator shr 1
result.quotient = quotient
result.remainder = dividend
if isNegativeA xor isNegativeB:
result.quotient = -quotient
else:
result.quotient = quotient
if isNegativeA:
result.remainder = -dividend
else:
result.remainder = dividend
proc `div`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
@@ -362,28 +449,32 @@ proc `mod`*(a,b: Int128): Int128 =
let (a,b) = divMod(a,b)
return b
proc `$`*(a: Int128): string =
if a == Zero:
result = "0"
elif a == low(Int128):
result = "-170141183460469231731687303715884105728"
proc addInt128*(result: var string; value: Int128) =
let initialSize = result.len
if value == Zero:
result.add "0"
elif value == low(Int128):
result.add "-170141183460469231731687303715884105728"
else:
let isNegative = isNegative(a)
var a = abs(a)
while a > Zero:
let (quot, rem) = divMod(a, Ten)
let isNegative = isNegative(value)
var value = abs(value)
while value > Zero:
let (quot, rem) = divMod(value, Ten)
result.add "0123456789"[rem.toInt64]
a = quot
value = quot
if isNegative:
result.add '-'
var i = 0
var i = initialSize
var j = high(result)
while i < j:
swap(result[i], result[j])
i += 1
j -= 1
proc `$`*(a: Int128): string =
result.addInt128(a)
proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
assert(pos < arg.len)
assert(arg[pos] in {'-','0'..'9'})
@@ -395,7 +486,7 @@ proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
pos += 1
result = Zero
while pos < arg.len and arg[pos] in '0' .. '9':
while pos < arg.len and arg[pos] in '0'..'9':
result = result * Ten
result.inc(uint32(arg[pos]) - uint32('0'))
pos += 1
@@ -435,6 +526,75 @@ proc `+`*(a: BiggestInt, b: Int128): Int128 =
proc `+`*(a: Int128, b: BiggestInt): Int128 =
a + toInt128(b)
proc toFloat64*(arg: Int128): float64 =
let isNegative = isNegative(arg)
let arg = abs(arg)
let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
result = a + 18446744073709551616'f64 * b # a + 2^64 * b
if isNegative:
result = -result
proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
proc toInt128*(arg: float64): Int128 =
let isNegative = arg < 0
let v0 = ldexp(abs(arg), -100)
let w0 = uint64(trunc(v0))
let v1 = ldexp(v0 - float64(w0), 50)
let w1 = uint64(trunc(v1))
let v2 = ldexp(v1 - float64(w1), 50)
let w2 = uint64(trunc(v2))
let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
if isNegative:
return -res
else:
return res
proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = arg.udata[1]
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0]
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xffff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
result.udata[0] = arg.udata[0] and 0xff
result.udata[1] = 0
result.udata[2] = 0
result.udata[3] = 0
proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
case numbytes
of 1:
return maskUInt8(arg)
of 2:
return maskUInt16(arg)
of 4:
return maskUInt32(arg)
of 8:
return maskUInt64(arg)
else:
assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
when isMainModule:
let (a,b) = divMod(Ten,Ten)
@@ -486,8 +646,8 @@ when isMainModule:
d[37] = parseDecimalInt128("10000000000000000000000000000000000000")
d[38] = parseDecimalInt128("100000000000000000000000000000000000000")
for i in 0 ..< d.len:
for j in 0 ..< d.len:
for i in 0..<d.len:
for j in 0..<d.len:
doAssert(cmp(d[i], d[j]) == cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == d[i+j]
@@ -504,8 +664,8 @@ when isMainModule:
for it in d.mitems:
it = -it
for i in 0 ..< d.len:
for j in 0 ..< d.len:
for i in 0..<d.len:
for j in 0..<d.len:
doAssert(cmp(d[i], d[j]) == -cmp(i,j))
if i + j < d.len:
doAssert d[i] * d[j] == -d[i+j]
@@ -514,3 +674,108 @@ when isMainModule:
doAssert $high(Int128) == "170141183460469231731687303715884105727"
doAssert $low(Int128) == "-170141183460469231731687303715884105728"
var ma = 100'i64
var mb = 13
doAssert toInt128(ma) * toInt128(0) == toInt128(0)
doAssert toInt128(-ma) * toInt128(0) == toInt128(0)
# sign correctness
doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))
doAssert divMod(toInt128( mb),toInt128( mb)) == (toInt128( mb div mb), toInt128( mb mod mb))
doAssert divMod(toInt128(-mb),toInt128( mb)) == (toInt128(-mb div mb), toInt128(-mb mod mb))
doAssert divMod(toInt128( mb),toInt128(-mb)) == (toInt128( mb div -mb), toInt128( mb mod -mb))
doAssert divMod(toInt128(-mb),toInt128(-mb)) == (toInt128(-mb div -mb), toInt128(-mb mod -mb))
doAssert divMod(toInt128( mb),toInt128( ma)) == (toInt128( mb div ma), toInt128( mb mod ma))
doAssert divMod(toInt128(-mb),toInt128( ma)) == (toInt128(-mb div ma), toInt128(-mb mod ma))
doAssert divMod(toInt128( mb),toInt128(-ma)) == (toInt128( mb div -ma), toInt128( mb mod -ma))
doAssert divMod(toInt128(-mb),toInt128(-ma)) == (toInt128(-mb div -ma), toInt128(-mb mod -ma))
let e = parseDecimalInt128("70997106675279150998592376708984375")
let strArray = [
# toHex(e shr 0), toHex(e shr 1), toHex(e shr 2), toHex(e shr 3)
"000dac6d782d266a37300c32591eee37", "0006d636bc1693351b9806192c8f771b", "00036b1b5e0b499a8dcc030c9647bb8d", "0001b58daf05a4cd46e601864b23ddc6",
"0000dac6d782d266a37300c32591eee3", "00006d636bc1693351b9806192c8f771", "000036b1b5e0b499a8dcc030c9647bb8", "00001b58daf05a4cd46e601864b23ddc",
"00000dac6d782d266a37300c32591eee", "000006d636bc1693351b9806192c8f77", "0000036b1b5e0b499a8dcc030c9647bb", "000001b58daf05a4cd46e601864b23dd",
"000000dac6d782d266a37300c32591ee", "0000006d636bc1693351b9806192c8f7", "00000036b1b5e0b499a8dcc030c9647b", "0000001b58daf05a4cd46e601864b23d",
"0000000dac6d782d266a37300c32591e", "00000006d636bc1693351b9806192c8f", "000000036b1b5e0b499a8dcc030c9647", "00000001b58daf05a4cd46e601864b23",
"00000000dac6d782d266a37300c32591", "000000006d636bc1693351b9806192c8", "0000000036b1b5e0b499a8dcc030c964", "000000001b58daf05a4cd46e601864b2",
"000000000dac6d782d266a37300c3259", "0000000006d636bc1693351b9806192c", "00000000036b1b5e0b499a8dcc030c96", "0000000001b58daf05a4cd46e601864b",
"0000000000dac6d782d266a37300c325", "00000000006d636bc1693351b9806192", "000000000036b1b5e0b499a8dcc030c9", "00000000001b58daf05a4cd46e601864",
"00000000000dac6d782d266a37300c32", "000000000006d636bc1693351b980619", "0000000000036b1b5e0b499a8dcc030c", "000000000001b58daf05a4cd46e60186",
"000000000000dac6d782d266a37300c3", "0000000000006d636bc1693351b98061", "00000000000036b1b5e0b499a8dcc030", "0000000000001b58daf05a4cd46e6018",
"0000000000000dac6d782d266a37300c", "00000000000006d636bc1693351b9806", "000000000000036b1b5e0b499a8dcc03", "00000000000001b58daf05a4cd46e601",
"00000000000000dac6d782d266a37300", "000000000000006d636bc1693351b980", "0000000000000036b1b5e0b499a8dcc0", "000000000000001b58daf05a4cd46e60",
"000000000000000dac6d782d266a3730", "0000000000000006d636bc1693351b98", "00000000000000036b1b5e0b499a8dcc", "0000000000000001b58daf05a4cd46e6",
"0000000000000000dac6d782d266a373", "00000000000000006d636bc1693351b9", "000000000000000036b1b5e0b499a8dc", "00000000000000001b58daf05a4cd46e",
"00000000000000000dac6d782d266a37", "000000000000000006d636bc1693351b", "0000000000000000036b1b5e0b499a8d", "000000000000000001b58daf05a4cd46",
"000000000000000000dac6d782d266a3", "0000000000000000006d636bc1693351", "00000000000000000036b1b5e0b499a8", "0000000000000000001b58daf05a4cd4",
"0000000000000000000dac6d782d266a", "00000000000000000006d636bc169335", "000000000000000000036b1b5e0b499a", "00000000000000000001b58daf05a4cd",
"00000000000000000000dac6d782d266", "000000000000000000006d636bc16933", "0000000000000000000036b1b5e0b499", "000000000000000000001b58daf05a4c",
"000000000000000000000dac6d782d26", "0000000000000000000006d636bc1693", "00000000000000000000036b1b5e0b49", "0000000000000000000001b58daf05a4",
"0000000000000000000000dac6d782d2", "00000000000000000000006d636bc169", "000000000000000000000036b1b5e0b4", "00000000000000000000001b58daf05a",
"00000000000000000000000dac6d782d", "000000000000000000000006d636bc16", "0000000000000000000000036b1b5e0b", "000000000000000000000001b58daf05",
"000000000000000000000000dac6d782", "0000000000000000000000006d636bc1", "00000000000000000000000036b1b5e0", "0000000000000000000000001b58daf0",
"0000000000000000000000000dac6d78", "00000000000000000000000006d636bc", "000000000000000000000000036b1b5e", "00000000000000000000000001b58daf",
"00000000000000000000000000dac6d7", "000000000000000000000000006d636b", "0000000000000000000000000036b1b5", "000000000000000000000000001b58da",
"000000000000000000000000000dac6d", "0000000000000000000000000006d636", "00000000000000000000000000036b1b", "0000000000000000000000000001b58d",
"0000000000000000000000000000dac6", "00000000000000000000000000006d63", "000000000000000000000000000036b1", "00000000000000000000000000001b58",
"00000000000000000000000000000dac", "000000000000000000000000000006d6", "0000000000000000000000000000036b", "000000000000000000000000000001b5",
"000000000000000000000000000000da", "0000000000000000000000000000006d", "00000000000000000000000000000036", "0000000000000000000000000000001b",
"0000000000000000000000000000000d", "00000000000000000000000000000006", "00000000000000000000000000000003", "00000000000000000000000000000001",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
"00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
]
for i in 0 ..< 128:
let str1 = toHex(e shr i)
let str2 = strArray[i]
doAssert str1 == str2
let strArray2 = [
"000dac6d782d266a37300c32591eee37", "001b58daf05a4cd46e601864b23ddc6e", "0036b1b5e0b499a8dcc030c9647bb8dc", "006d636bc1693351b9806192c8f771b8",
"00dac6d782d266a37300c32591eee370", "01b58daf05a4cd46e601864b23ddc6e0", "036b1b5e0b499a8dcc030c9647bb8dc0", "06d636bc1693351b9806192c8f771b80",
"0dac6d782d266a37300c32591eee3700", "1b58daf05a4cd46e601864b23ddc6e00", "36b1b5e0b499a8dcc030c9647bb8dc00", "6d636bc1693351b9806192c8f771b800",
"dac6d782d266a37300c32591eee37000", "b58daf05a4cd46e601864b23ddc6e000", "6b1b5e0b499a8dcc030c9647bb8dc000", "d636bc1693351b9806192c8f771b8000",
"ac6d782d266a37300c32591eee370000", "58daf05a4cd46e601864b23ddc6e0000", "b1b5e0b499a8dcc030c9647bb8dc0000", "636bc1693351b9806192c8f771b80000",
"c6d782d266a37300c32591eee3700000", "8daf05a4cd46e601864b23ddc6e00000", "1b5e0b499a8dcc030c9647bb8dc00000", "36bc1693351b9806192c8f771b800000",
"6d782d266a37300c32591eee37000000", "daf05a4cd46e601864b23ddc6e000000", "b5e0b499a8dcc030c9647bb8dc000000", "6bc1693351b9806192c8f771b8000000",
"d782d266a37300c32591eee370000000", "af05a4cd46e601864b23ddc6e0000000", "5e0b499a8dcc030c9647bb8dc0000000", "bc1693351b9806192c8f771b80000000",
"782d266a37300c32591eee3700000000", "f05a4cd46e601864b23ddc6e00000000", "e0b499a8dcc030c9647bb8dc00000000", "c1693351b9806192c8f771b800000000",
"82d266a37300c32591eee37000000000", "05a4cd46e601864b23ddc6e000000000", "0b499a8dcc030c9647bb8dc000000000", "1693351b9806192c8f771b8000000000",
"2d266a37300c32591eee370000000000", "5a4cd46e601864b23ddc6e0000000000", "b499a8dcc030c9647bb8dc0000000000", "693351b9806192c8f771b80000000000",
"d266a37300c32591eee3700000000000", "a4cd46e601864b23ddc6e00000000000", "499a8dcc030c9647bb8dc00000000000", "93351b9806192c8f771b800000000000",
"266a37300c32591eee37000000000000", "4cd46e601864b23ddc6e000000000000", "99a8dcc030c9647bb8dc000000000000", "3351b9806192c8f771b8000000000000",
"66a37300c32591eee370000000000000", "cd46e601864b23ddc6e0000000000000", "9a8dcc030c9647bb8dc0000000000000", "351b9806192c8f771b80000000000000",
"6a37300c32591eee3700000000000000", "d46e601864b23ddc6e00000000000000", "a8dcc030c9647bb8dc00000000000000", "51b9806192c8f771b800000000000000",
"a37300c32591eee37000000000000000", "46e601864b23ddc6e000000000000000", "8dcc030c9647bb8dc000000000000000", "1b9806192c8f771b8000000000000000",
"37300c32591eee370000000000000000", "6e601864b23ddc6e0000000000000000", "dcc030c9647bb8dc0000000000000000", "b9806192c8f771b80000000000000000",
"7300c32591eee3700000000000000000", "e601864b23ddc6e00000000000000000", "cc030c9647bb8dc00000000000000000", "9806192c8f771b800000000000000000",
"300c32591eee37000000000000000000", "601864b23ddc6e000000000000000000", "c030c9647bb8dc000000000000000000", "806192c8f771b8000000000000000000",
"00c32591eee370000000000000000000", "01864b23ddc6e0000000000000000000", "030c9647bb8dc0000000000000000000", "06192c8f771b80000000000000000000",
"0c32591eee3700000000000000000000", "1864b23ddc6e00000000000000000000", "30c9647bb8dc00000000000000000000", "6192c8f771b800000000000000000000",
"c32591eee37000000000000000000000", "864b23ddc6e000000000000000000000", "0c9647bb8dc000000000000000000000", "192c8f771b8000000000000000000000",
"32591eee370000000000000000000000", "64b23ddc6e0000000000000000000000", "c9647bb8dc0000000000000000000000", "92c8f771b80000000000000000000000",
"2591eee3700000000000000000000000", "4b23ddc6e00000000000000000000000", "9647bb8dc00000000000000000000000", "2c8f771b800000000000000000000000",
"591eee37000000000000000000000000", "b23ddc6e000000000000000000000000", "647bb8dc000000000000000000000000", "c8f771b8000000000000000000000000",
"91eee370000000000000000000000000", "23ddc6e0000000000000000000000000", "47bb8dc0000000000000000000000000", "8f771b80000000000000000000000000",
"1eee3700000000000000000000000000", "3ddc6e00000000000000000000000000", "7bb8dc00000000000000000000000000", "f771b800000000000000000000000000",
"eee37000000000000000000000000000", "ddc6e000000000000000000000000000", "bb8dc000000000000000000000000000", "771b8000000000000000000000000000",
"ee370000000000000000000000000000", "dc6e0000000000000000000000000000", "b8dc0000000000000000000000000000", "71b80000000000000000000000000000",
"e3700000000000000000000000000000", "c6e00000000000000000000000000000", "8dc00000000000000000000000000000", "1b800000000000000000000000000000",
"37000000000000000000000000000000", "6e000000000000000000000000000000", "dc000000000000000000000000000000", "b8000000000000000000000000000000",
"70000000000000000000000000000000", "e0000000000000000000000000000000", "c0000000000000000000000000000000", "80000000000000000000000000000000",
]
for i in 0 ..< 128:
let str1 = toHex(e shl i)
let str2 = strArray2[i]
doAssert str1 == str2

File diff suppressed because it is too large Load Diff

View File

@@ -7,28 +7,30 @@
# distribution, for details about the copyright.
#
# included from jsgen.nim
## Type info generation for the JS backend.
proc rope(arg: Int128): Rope = rope($arg)
proc genTypeInfo(p: PProc, typ: PType): Rope
proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
var
s, u: Rope
length: int
field: PSym
b: PNode
result = nil
case n.kind
of nkRecList:
length = sonsLen(n)
if length == 1:
result = genObjectFields(p, typ, n.sons[0])
if n.len == 1:
result = genObjectFields(p, typ, n[0])
else:
s = nil
for i in 0 ..< length:
if i > 0: add(s, ", \L")
add(s, genObjectFields(p, typ, n.sons[i]))
for i in 0..<n.len:
if i > 0: s.add(", \L")
s.add(genObjectFields(p, typ, n[i]))
result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}") % [rope(length), s]
"typ: null, name: null, sons: [$2]}") % [rope(n.len), s]
of nkSym:
field = n.sym
s = genTypeInfo(p, field.typ)
@@ -37,29 +39,28 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
[mangleName(p.module, field), s,
makeJSString(field.name.s)]
of nkRecCase:
length = sonsLen(n)
if (n.sons[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
field = n.sons[0].sym
if (n[0].kind != nkSym): internalError(p.config, n.info, "genObjectFields")
field = n[0].sym
s = genTypeInfo(p, field.typ)
for i in 1 ..< length:
b = n.sons[i] # branch
for i in 1..<n.len:
b = n[i] # branch
u = nil
case b.kind
of nkOfBranch:
if sonsLen(b) < 2:
if b.len < 2:
internalError(p.config, b.info, "genObjectFields; nkOfBranch broken")
for j in 0 .. sonsLen(b) - 2:
if u != nil: add(u, ", ")
if b.sons[j].kind == nkRange:
addf(u, "[$1, $2]", [rope(getOrdValue(b.sons[j].sons[0])),
rope(getOrdValue(b.sons[j].sons[1]))])
for j in 0..<b.len - 1:
if u != nil: u.add(", ")
if b[j].kind == nkRange:
u.addf("[$1, $2]", [rope(getOrdValue(b[j][0])),
rope(getOrdValue(b[j][1]))])
else:
add(u, rope(getOrdValue(b.sons[j])))
u.add(rope(getOrdValue(b[j])))
of nkElse:
u = rope(lengthOrd(p.config, field.typ))
else: internalError(p.config, n.info, "genObjectFields(nkRecCase)")
if result != nil: add(result, ", \L")
addf(result, "[setConstr($1), $2]",
if result != nil: result.add(", \L")
result.addf("[setConstr($1), $2]",
[u, genObjectFields(p, typ, lastSon(b))])
result = ("{kind: 3, offset: \"$1\", len: $3, " &
"typ: $2, name: $4, sons: [$5]}") % [
@@ -68,27 +69,27 @@ proc genObjectFields(p: PProc, typ: PType, n: PNode): Rope =
else: internalError(p.config, n.info, "genObjectFields")
proc objHasTypeField(t: PType): bool {.inline.} =
tfInheritable in t.flags or t.sons[0] != nil
tfInheritable in t.flags or t[0] != nil
proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
let kind = if objHasTypeField(typ): tyObject else: tyTuple
var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "var NNI$1 = $2;$n",
p.g.typeInfo.addf("var NNI$1 = $2;$n",
[rope(typ.id), genObjectFields(p, typ, typ.n)])
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ.sons[0] != nil):
addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0].skipTypes(skipPtrs))])
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
if (typ.kind == tyObject) and (typ[0] != nil):
p.g.typeInfo.addf("$1.base = $2;$n",
[name, genTypeInfo(p, typ[0].skipTypes(skipPtrs))])
proc genTupleFields(p: PProc, typ: PType): Rope =
var s: Rope = nil
for i in 0 ..< typ.len:
if i > 0: add(s, ", \L")
for i in 0..<typ.len:
if i > 0: s.add(", \L")
s.addf("{kind: 1, offset: \"Field$1\", len: 0, " &
"typ: $2, name: \"Field$1\", sons: null}",
[i.rope, genTypeInfo(p, typ.sons[i])])
[i.rope, genTypeInfo(p, typ[i])])
result = ("{kind: 2, len: $1, offset: 0, " &
"typ: null, name: null, sons: [$2]}") % [rope(typ.len), s]
@@ -96,30 +97,29 @@ proc genTupleInfo(p: PProc, typ: PType, name: Rope) =
var s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "var NNI$1 = $2;$n",
p.g.typeInfo.addf("var NNI$1 = $2;$n",
[rope(typ.id), genTupleFields(p, typ)])
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
proc genEnumInfo(p: PProc, typ: PType, name: Rope) =
let length = sonsLen(typ.n)
var s: Rope = nil
for i in 0 ..< length:
if (typ.n.sons[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
let field = typ.n.sons[i].sym
if i > 0: add(s, ", \L")
for i in 0..<typ.n.len:
if (typ.n[i].kind != nkSym): internalError(p.config, typ.n.info, "genEnumInfo")
let field = typ.n[i].sym
if i > 0: s.add(", \L")
let extName = if field.ast == nil: field.name.s else: field.ast.strVal
addf(s, "\"$1\": {kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
s.addf("\"$1\": {kind: 1, offset: $1, typ: $2, name: $3, len: 0, sons: null}",
[rope(field.position), name, makeJSString(extName)])
var n = ("var NNI$1 = {kind: 2, offset: 0, typ: null, " &
"name: null, len: $2, sons: {$3}};$n") % [rope(typ.id), rope(length), s]
"name: null, len: $2, sons: {$3}};$n") % [rope(typ.id), rope(typ.n.len), s]
s = ("var $1 = {size: 0, kind: $2, base: null, node: null, " &
"finalizer: null};$n") % [name, rope(ord(typ.kind))]
prepend(p.g.typeInfo, s)
add(p.g.typeInfo, n)
addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
if typ.sons[0] != nil:
addf(p.g.typeInfo, "$1.base = $2;$n",
[name, genTypeInfo(p, typ.sons[0])])
p.g.typeInfo.add(n)
p.g.typeInfo.addf("$1.node = NNI$2;$n", [name, rope(typ.id)])
if typ[0] != nil:
p.g.typeInfo.addf("$1.base = $2;$n",
[name, genTypeInfo(p, typ[0])])
proc genTypeInfo(p: PProc, typ: PType): Rope =
let t = typ.skipTypes({tyGenericInst, tyDistinct, tyAlias, tySink, tyOwned})
@@ -127,7 +127,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
if containsOrIncl(p.g.typeInfoGenerated, t.id): return
case t.kind
of tyDistinct:
result = genTypeInfo(p, t.sons[0])
result = genTypeInfo(p, t[0])
of tyPointer, tyProc, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64:
var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
@@ -138,15 +138,15 @@ 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)
addf(p.g.typeInfo, "$1.base = $2;$n",
p.g.typeInfo.addf("$1.base = $2;$n",
[result, genTypeInfo(p, t.lastSon)])
of tyArray:
var s =
"var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n" %
[result, rope(ord(t.kind))]
prepend(p.g.typeInfo, s)
addf(p.g.typeInfo, "$1.base = $2;$n",
[result, genTypeInfo(p, t.sons[1])])
p.g.typeInfo.addf("$1.base = $2;$n",
[result, genTypeInfo(p, t[1])])
of tyEnum: genEnumInfo(p, t, result)
of tyObject: genObjectInfo(p, t, result)
of tyTuple: genTupleInfo(p, t, result)

View File

@@ -128,8 +128,8 @@ proc newCall(a: PSym, b: PNode): PNode =
proc createClosureIterStateType*(g: ModuleGraph; iter: PSym): PType =
var n = newNodeI(nkRange, iter.info)
addSon(n, newIntNode(nkIntLit, -1))
addSon(n, newIntNode(nkIntLit, 0))
n.add newIntNode(nkIntLit, -1)
n.add newIntNode(nkIntLit, 0)
result = newType(tyRange, iter)
result.n = n
var intType = nilOrSysInt(g)
@@ -148,27 +148,27 @@ proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
proc getClosureIterResult*(g: ModuleGraph; iter: PSym): PSym =
if resultPos < iter.ast.len:
result = iter.ast.sons[resultPos].sym
result = iter.ast[resultPos].sym
else:
# XXX a bit hacky:
result = newSym(skResult, getIdent(g.cache, ":result"), iter, iter.info, {})
result.typ = iter.typ.sons[0]
result.typ = iter.typ[0]
incl(result.flags, sfUsed)
iter.ast.add newSymNode(result)
proc addHiddenParam(routine: PSym, param: PSym) =
assert param.kind == skParam
var params = routine.ast.sons[paramsPos]
var params = routine.ast[paramsPos]
# -1 is correct here as param.position is 0 based but we have at position 0
# some nkEffect node:
param.position = routine.typ.n.len-1
addSon(params, newSymNode(param))
params.add newSymNode(param)
#incl(routine.typ.flags, tfCapturesEnv)
assert sfFromGeneric in param.flags
#echo "produced environment: ", param.id, " for ", routine.id
proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
let params = routine.ast.sons[paramsPos]
let params = routine.ast[paramsPos]
let hidden = lastSon(params)
if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
result = hidden.sym
@@ -179,7 +179,7 @@ proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
result = routine
proc getEnvParam*(routine: PSym): PSym =
let params = routine.ast.sons[paramsPos]
let params = routine.ast[paramsPos]
let hidden = lastSon(params)
if hidden.kind == nkSym and hidden.sym.name.s == paramName:
result = hidden.sym
@@ -206,8 +206,8 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
# which is however the only case when we generate an assignment in the first
# place.
result = newNodeI(nkAsgn, info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode =
result = newNodeIT(nkClosure, info, prc.typ)
@@ -218,6 +218,10 @@ proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode
if env.skipConv.kind == nkClosure:
localError(g.config, info, "internal error: taking closure of closure")
result.add(env)
#if isClosureIterator(result.typ):
createTypeBoundOps(g, nil, result.typ, info)
if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions:
prc.flags.incl sfInjectDestructors
proc interestingIterVar(s: PSym): bool {.inline.} =
# XXX optimization: Only lift the variable if it lives across
@@ -233,6 +237,12 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
result = conf.cmd == cmdCompileToJS and not isCompileTime
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) =
createTypeBoundOps(g, nil, refType.lastSon, info)
createTypeBoundOps(g, nil, refType, info)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors
proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
if liftingHarmful(g.config, owner): return n
@@ -245,7 +255,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var env: PNode
if owner.isIterator:
let it = getHiddenParam(g, owner)
addUniqueField(it.typ.sons[0], hp, g.cache)
addUniqueField(it.typ.skipTypes({tyOwned})[0], hp, g.cache)
env = indirectAccess(newSymNode(it), hp, hp.info)
else:
let e = newSym(skLet, iter.name, owner, n.info)
@@ -257,13 +267,12 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result.add(v)
# add 'new' statement:
result.add newCall(getSysSym(g, n.info, "internalNew"), env)
if optNimV2 in g.config.globalOptions:
createTypeBoundOps(g, nil, env.typ, n.info)
createTypeBoundOpsLL(g, env.typ, n.info, owner)
result.add makeClosure(g, iter, env, n.info)
proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
let envParam = getHiddenParam(g, owner)
let obj = envParam.typ.skipTypes({tyOwned, tyRef})
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
addField(obj, s, g.cache)
var access = newSymNode(envParam)
@@ -293,7 +302,7 @@ type
DetectionPass = object
processed, capturedVars: IntSet
ownerToType: Table[int, PType]
somethingToDo, noDestructors: bool
somethingToDo: bool
graph: ModuleGraph
proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass =
@@ -323,7 +332,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
c.ownerToType[owner.id] = result
proc asOwnedRef(c: DetectionPass; t: PType): PType =
if optNimV2 in c.graph.config.globalOptions:
if optOwnedRefs in c.graph.config.globalOptions:
assert t.kind == tyRef
result = newType(tyOwned, t.owner)
result.flags.incl tfHasOwned
@@ -335,16 +344,17 @@ proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
info: TLineInfo): PType =
var r = c.getEnvTypeForOwner(owner, info)
result = newType(tyPtr, owner)
rawAddSon(result, r.skipTypes({tyOwned, tyRef}))
rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr}))
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let refObj = c.getEnvTypeForOwner(dest, info) # getHiddenParam(dest).typ
let obj = refObj.skipTypes({tyOwned, tyRef})
let obj = refObj.skipTypes({tyOwned, tyRef, tyPtr})
# The assumption here is that gcDestructors means we cannot deal
# with cycles properly, so it's better to produce a weak ref (=ptr) here.
# This seems to be generally correct but since it's a bit risky it's only
# enabled for gcDestructors.
let fieldType = if false: # c.graph.config.selectedGC == gcDestructors:
# This seems to be generally correct but since it's a bit risky it's disabled
# for now.
# XXX This is wrong for the 'hamming' test, so remove this logic again.
let fieldType = if isDefined(c.graph.config, "nimCycleBreaker"):
c.getEnvTypeForOwnerUp(dep, info) #getHiddenParam(dep).typ
else:
c.getEnvTypeForOwner(dep, info)
@@ -354,11 +364,18 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
let upIdent = getIdent(c.graph.cache, upName)
let upField = lookupInRecord(obj.n, upIdent)
if upField != nil:
if upField.typ.skipTypes({tyOwned, tyRef}) != fieldType.skipTypes({tyOwned, tyRef}):
if upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) != fieldType.skipTypes({tyOwned, tyRef, tyPtr}):
localError(c.graph.config, dep.info, "internal error: up references do not agree")
when false:
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, obj.owner, obj.owner.info)
result.typ = fieldType
when false:
if c.graph.config.selectedGC == gcDestructors:
result.flags.incl sfCursor
rawAddField(obj, result)
discard """
@@ -415,8 +432,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if innerProc:
if s.isIterator: c.somethingToDo = true
if not c.processed.containsOrIncl(s.id):
let body = transformBody(c.graph, s, cache = true,
noDestructors = c.noDestructors)
let body = transformBody(c.graph, s, cache = true)
detectCapturedVars(body, s, c)
let ow = s.skipGenericOwner
if ow == owner:
@@ -425,8 +441,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
addClosureParam(c, owner, n.info)
if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef})
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
if s.name.id == getIdent(c.graph.cache, ":state").id:
obj.n[0].sym.id = -s.id
@@ -451,8 +467,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
#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})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef})
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
addField(obj, s, c.graph.cache)
# create required upFields:
var w = owner.skipGenericOwner
@@ -477,7 +493,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
w = up
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt:
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
discard
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil:
@@ -507,7 +523,7 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
if not envParam.isNil:
var access = newSymNode(envParam)
while true:
let obj = access.typ.sons[0]
let obj = access.typ[0]
assert obj.kind == tyObject
let field = getFieldFromObj(obj, s)
if field != nil:
@@ -526,7 +542,7 @@ proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNo
when false:
if owner.kind == skIterator and owner.typ.callConv == ccClosure:
let it = getHiddenParam(owner)
addUniqueField(it.typ.sons[0], v)
addUniqueField(it.typ[0], v)
result = indirectAccess(newSymNode(it), v, v.info)
else:
result = newSymNode(v)
@@ -542,7 +558,7 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
localError d.graph.config, owner.info, "internal error: could not determine closure type"
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info)
c.envVars[owner.id] = result
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info)
v.flags = {sfShadowed, sfGeneratedOp}
v.typ = envVarType
@@ -552,7 +568,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
let p = getHiddenParam(g, owner)
result = p.newSymNode
if owner.isIterator:
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef}).n, getIdent(g.cache, upName))
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName))
if upField == nil:
localError(g.config, owner.info, "could not find up reference for closure iter")
else:
@@ -572,20 +588,20 @@ proc rawClosureCreation(owner: PSym;
var v = newNodeI(nkVarSection, env.info)
addVar(v, env)
result.add(v)
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
addVar(v, unowned)
# add 'new' statement:
result.add(newCall(getSysSym(d.graph, env.info, "internalNew"), env))
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let env2 = copyTree(env)
env2.typ = unowned.typ
result.add newAsgnStmt(unowned, env2, env.info)
createTypeBoundOps(d.graph, nil, unowned.typ, env.info)
createTypeBoundOpsLL(d.graph, unowned.typ, env.info, owner)
# add assignment statements for captured parameters:
for i in 1..<owner.typ.n.len:
@@ -594,11 +610,14 @@ proc rawClosureCreation(owner: PSym;
let fieldAccess = indirectAccess(env, local, env.info)
# add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info))
createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info)
if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
owner.flags.incl sfInjectDestructors
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
if upField != nil:
let up = getUpViaParam(d.graph, owner)
if up != nil and upField.typ.skipTypes({tyOwned, tyRef}) == up.typ.skipTypes({tyOwned, tyRef}):
if up != nil and upField.typ.skipTypes({tyOwned, tyRef, tyPtr}) == up.typ.skipTypes({tyOwned, tyRef, tyPtr}):
result.add(newAsgnStmt(rawIndirectAccess(env, upField, env.info),
up, env.info))
#elif oldenv != nil and oldenv.typ == upField.typ:
@@ -608,16 +627,16 @@ proc rawClosureCreation(owner: PSym;
localError(d.graph.config, env.info, "internal error: cannot create up reference")
# we are not in the sem'check phase anymore! so pass 'nil' for the PContext
# and hope for the best:
if optNimV2 in d.graph.config.globalOptions:
createTypeBoundOps(d.graph, nil, env.typ, owner.info)
createTypeBoundOpsLL(d.graph, env.typ, owner.info, owner)
proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
info: TLineInfo; res: PNode) =
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil
let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
res.add newAsgnStmt(unowned, nilLit, info)
createTypeBoundOpsLL(d.graph, unowned.typ, info, owner)
proc closureCreationForIter(iter: PNode;
d: DetectionPass; c: var LiftingPass): PNode =
@@ -629,7 +648,7 @@ proc closureCreationForIter(iter: PNode;
var vnode: PNode
if owner.isIterator:
let it = getHiddenParam(d.graph, owner)
addUniqueField(it.typ.skipTypes({tyOwned, tyRef}), v, d.graph.cache)
addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache)
vnode = indirectAccess(newSymNode(it), v, v.info)
else:
vnode = v.newSymNode
@@ -637,13 +656,12 @@ proc closureCreationForIter(iter: PNode;
addVar(vs, vnode)
result.add(vs)
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
if optNimV2 in d.graph.config.globalOptions:
createTypeBoundOps(d.graph, nil, vnode.typ, iter.info)
createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, owner)
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef}).n, getIdent(d.graph.cache, upName))
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
if upField != nil:
let u = setupEnvVar(owner, d, c, iter.info)
if u.typ.skipTypes({tyOwned, tyRef}) == upField.typ.skipTypes({tyOwned, tyRef}):
if u.typ.skipTypes({tyOwned, tyRef, tyPtr}) == upField.typ.skipTypes({tyOwned, tyRef, tyPtr}):
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
u, iter.info))
else:
@@ -653,9 +671,9 @@ proc closureCreationForIter(iter: PNode;
proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode =
var access = setupEnvVar(owner, d, c, n.info)
if optNimV2 in d.graph.config.globalOptions:
if optOwnedRefs in d.graph.config.globalOptions:
access = c.unownedEnvVars[owner.id]
let obj = access.typ.skipTypes({tyOwned, tyRef})
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let field = getFieldFromObj(obj, n.sym)
if field != nil:
result = rawIndirectAccess(access, field, n.info)
@@ -664,7 +682,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
result = n
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef}).n.sons[0].sym
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode
@@ -689,7 +707,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
while true:
if access.typ == wanted:
return makeClosure(d.graph, s, access, n.info)
let obj = access.typ.skipTypes({tyOwned, tyRef})
let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName))
if upField == nil:
localError(d.graph.config, n.info, "internal error: no environment found")
@@ -708,7 +726,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# echo renderTree(s.getBody, {renderIds})
let oldInContainer = c.inContainer
c.inContainer = 0
var body = transformBody(d.graph, s)
var body = transformBody(d.graph, s, cache = false)
body = liftCapturedVars(body, s, d, c)
if c.envVars.getOrDefault(s.id).isNil:
s.transformedBody = body
@@ -733,13 +751,13 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
discard
of nkClosure:
if n[1].kind == nkNilLit:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
let x = n.sons[0].skipConv
n[0] = liftCapturedVars(n[0], owner, d, c)
let x = n[0].skipConv
if x.kind == nkClosure:
#localError(n.info, "internal error: closure to closure created")
# now we know better, so patch it:
n.sons[0] = x.sons[0]
n.sons[1] = x.sons[1]
n[0] = x[0]
n[1] = x[1]
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil and n[namePos].kind == nkSym:
let oldInContainer = c.inContainer
@@ -750,27 +768,29 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c.inContainer = oldInContainer
of nkHiddenStdConv:
if n.len == 2:
n.sons[1] = liftCapturedVars(n[1], owner, d, c)
n[1] = liftCapturedVars(n[1], owner, d, c)
if n[1].kind == nkClosure: result = n[1]
of nkReturnStmt:
if n[0].kind in {nkAsgn, nkFastAsgn}:
# we have a `result = result` expression produced by the closure
# transform, let's not touch the LHS in order to make the lifting pass
# correct when `result` is lifted
n[0].sons[1] = liftCapturedVars(n[0].sons[1], owner, d, c)
n[0][1] = liftCapturedVars(n[0][1], owner, d, c)
else:
n.sons[0] = liftCapturedVars(n[0], owner, d, c)
n[0] = liftCapturedVars(n[0], owner, d, c)
of nkTypeOfExpr:
result = n
else:
if owner.isIterator:
if nfLL in n.flags:
# special case 'when nimVm' due to bug #3636:
n.sons[1] = liftCapturedVars(n[1], owner, d, c)
n[1] = liftCapturedVars(n[1], owner, d, c)
return
let inContainer = n.kind in {nkObjConstr, nkBracket}
if inContainer: inc c.inContainer
for i in 0..<n.len:
n.sons[i] = liftCapturedVars(n[i], owner, d, c)
n[i] = liftCapturedVars(n[i], owner, d, c)
if inContainer: dec c.inContainer
# ------------------ old stuff -------------------------------------------
@@ -817,16 +837,15 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
# pretend 'fn' is a closure iterator for the analysis:
let oldKind = fn.kind
let oldCC = fn.typ.callConv
fn.kind = skIterator
fn.transitionRoutineSymKind(skIterator)
fn.typ.callConv = ccClosure
d.ownerToType[fn.id] = ptrType
detectCapturedVars(body, fn, d)
result = liftCapturedVars(body, fn, d, c)
fn.kind = oldKind
fn.transitionRoutineSymKind(oldKind)
fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
noDestructors: bool): PNode =
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ...
@@ -842,7 +861,6 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
tooEarly = true
else:
var d = initDetectionPass(g, fn)
d.noDestructors = noDestructors
detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn, body.info)
@@ -896,11 +914,10 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
...
"""
if liftingHarmful(g.config, owner): return body
var L = body.len
if not (body.kind == nkForStmt and body[L-2].kind in nkCallKinds):
if not (body.kind == nkForStmt and body[^2].kind in nkCallKinds):
localError(g.config, body.info, "ignored invalid for loop")
return body
var call = body[L-2]
var call = body[^2]
result = newNodeI(nkStmtList, body.info)
@@ -921,40 +938,39 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
result.add(v)
# add 'new' statement:
result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
if optNimV2 in g.config.globalOptions:
createTypeBoundOps(g, nil, env.typ, body.info)
createTypeBoundOpsLL(g, env.typ, body.info, owner)
elif op.kind == nkStmtListExpr:
let closure = op.lastSon
if closure.kind == nkClosure:
call.sons[0] = closure
for i in 0 .. op.len-2:
call[0] = closure
for i in 0..<op.len-1:
result.add op[i]
var loopBody = newNodeI(nkStmtList, body.info, 3)
var whileLoop = newNodeI(nkWhileStmt, body.info, 2)
whileLoop.sons[0] = newIntTypeNode(nkIntLit, 1, getSysType(g, body.info, tyBool))
whileLoop.sons[1] = loopBody
whileLoop[0] = newIntTypeNode(1, getSysType(g, body.info, tyBool))
whileLoop[1] = loopBody
result.add whileLoop
# setup loopBody:
# gather vars in a tuple:
var v2 = newNodeI(nkLetSection, body.info)
var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info)
for i in 0 .. L-3:
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.kind = skLet
addSon(vpart, body[i])
body[i].sym.transitionToLet()
vpart.add body[i]
addSon(vpart, newNodeI(nkEmpty, body.info)) # no explicit type
vpart.add newNodeI(nkEmpty, body.info) # no explicit type
if not env.isNil:
call.sons[0] = makeClosure(g, call.sons[0].sym, env.newSymNode, body.info)
addSon(vpart, call)
addSon(v2, vpart)
call[0] = makeClosure(g, call[0].sym, env.newSymNode, body.info)
vpart.add call
v2.add vpart
loopBody.sons[0] = v2
loopBody[0] = v2
var bs = newNodeI(nkBreakState, body.info)
bs.addSon(call.sons[0])
bs.add call[0]
let ibs = newNodeI(nkIfStmt, body.info)
let elifBranch = newNodeI(nkElifBranch, body.info)
@@ -966,5 +982,5 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
elifBranch.add(br)
ibs.add(elifBranch)
loopBody.sons[1] = ibs
loopBody.sons[2] = body[L-1]
loopBody[1] = ibs
loopBody[2] = body[^1]

View File

@@ -9,10 +9,7 @@
## Layouter for nimpretty.
import idents, lexer, lineinfos, llstream, options, msgs, strutils,
pathutils
from os import changeFileExt
from sequtils import delete
import idents, lexer, lineinfos, llstream, options, msgs, strutils, pathutils
const
MinLineLen = 15
@@ -24,7 +21,7 @@ type
SemicolonKind = enum
detectSemicolonKind, useSemicolon, dontTouch
LayoutToken = enum
LayoutToken* = enum
ltSpaces,
ltCrucialNewline, ## a semantically crucial newline (indentation!)
ltSplittingNewline, ## newline used for splitting up long
@@ -44,8 +41,8 @@ type
col, lastLineNumber, lineSpan, indentLevel, indWidth*, inSection: int
keepIndents*: int
doIndentMore*: int
kinds: seq[LayoutToken]
tokens: seq[string]
kinds*: seq[LayoutToken]
tokens*: seq[string]
indentStack: seq[int]
fixedUntil: int # marks where we must not go in the content
altSplitPos: array[SplitKind, int] # alternative split positions
@@ -149,7 +146,7 @@ proc optionalIsGood(em: var Emitter; pos, currentLen: int): bool =
proc lenOfNextTokens(em: Emitter; pos: int): int =
result = 0
for i in 1 ..< em.tokens.len-pos:
for i in 1..<em.tokens.len-pos:
if em.kinds[pos+i] in {ltCrucialNewline, ltSplittingNewline, ltOptionalNewline}: break
inc result, em.tokens[pos+i].len
@@ -163,13 +160,11 @@ proc guidingInd(em: Emitter; pos: int): int =
inc i
result = -1
proc closeEmitter*(em: var Emitter) =
proc renderTokens*(em: var Emitter): string =
## Render Emitter tokens to a string of code
template defaultCase() =
content.add em.tokens[i]
inc lineLen, em.tokens[i].len
let outFile = em.config.absOutFile
var content = newStringOfCap(16_000)
var maxLhs = 0
var lineLen = 0
@@ -246,6 +241,11 @@ proc closeEmitter*(em: var Emitter) =
defaultCase()
inc i
return content
proc writeOut*(em: Emitter, content: string) =
## Write to disk
let outFile = em.config.absOutFile
if fileExists(outFile) and readFile(outFile.string) == content:
discard "do nothing, see #9499"
return
@@ -256,6 +256,11 @@ proc closeEmitter*(em: var Emitter) =
f.llStreamWrite content
llStreamClose(f)
proc closeEmitter*(em: var Emitter) =
## Renders emitter tokens and write to a file
let content = renderTokens(em)
em.writeOut(content)
proc wr(em: var Emitter; x: string; lt: LayoutToken) =
em.tokens.add x
em.kinds.add lt
@@ -314,11 +319,11 @@ proc removeSpaces(em: var Emitter) =
const
openPars = {tkParLe, tkParDotLe,
tkBracketLe, tkBracketLeColon, tkCurlyDotLe,
tkCurlyLe}
tkBracketLe, tkBracketDotLe, tkBracketLeColon,
tkCurlyDotLe, tkCurlyLe}
closedPars = {tkParRi, tkParDotRi,
tkBracketRi, tkCurlyDotRi,
tkCurlyRi, tkBracketDotRi}
tkBracketRi, tkBracketDotRi,
tkCurlyDotRi, tkCurlyRi}
splitters = openPars + {tkComma, tkSemiColon} # do not add 'tkColon' here!
oprSet = {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs,
@@ -444,6 +449,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
em.indentLevel = tok.indent
elif (em.lastTok in (splitters + oprSet) and
tok.tokType notin (closedPars - {tkBracketDotRi})):
if tok.tokType in openPars and tok.indent > em.indentStack[^1]:
while em.indentStack[^1] < tok.indent:
em.indentStack.add(em.indentStack[^1] + em.indWidth)
# aka: we are in an expression context:
let alignment = max(tok.indent - em.indentStack[^1], 0)
em.indentLevel = alignment + em.indentStack.high * em.indWidth
@@ -499,7 +507,8 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
rememberSplit(splitComma)
wrSpace em
of openPars:
if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker:
if tok.strongSpaceA > 0 and not em.endsInWhite and
(not em.wasExportMarker or tok.tokType == tkCurlyDotLe):
wrSpace em
wr(em, TokTypeToStr[tok.tokType], ltSomeParLe)
rememberSplit(splitParLe)
@@ -561,7 +570,7 @@ proc endsWith(em: Emitter; k: varargs[string]): bool =
return true
proc rfind(em: Emitter, t: string): int =
for i in 1 .. 5:
for i in 1..5:
if em.tokens[^i] == t:
return i

View File

@@ -134,7 +134,7 @@ type
TErrorHandler* = proc (conf: ConfigRef; info: TLineInfo; msg: TMsgKind; arg: string)
TLexer* = object of TBaseLexer
fileIdx*: FileIndex
indentAhead*: int # if > 0 an indendation has already been read
indentAhead*: int # if > 0 an indentation has already been read
# this is needed because scanning comments
# needs so much look-ahead
currLineIndent*: int
@@ -304,11 +304,11 @@ template tokenEndPrevious(tok, pos) =
tok.offsetB = L.offsetBase + pos
template eatChar(L: var TLexer, t: var TToken, replacementChar: char) =
add(t.literal, replacementChar)
t.literal.add(replacementChar)
inc(L.bufpos)
template eatChar(L: var TLexer, t: var TToken) =
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
proc getNumber(L: var TLexer, result: var TToken) =
@@ -317,7 +317,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
result = 0
while true:
if L.buf[pos] in chars:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
inc(result)
else:
@@ -328,14 +328,14 @@ proc getNumber(L: var TLexer, result: var TToken) =
"only single underscores may occur in a token and token may not " &
"end with an underscore: e.g. '1__1' and '1_' are invalid")
break
add(tok.literal, '_')
tok.literal.add('_')
inc(pos)
L.bufpos = pos
proc matchChars(L: var TLexer, tok: var TToken, chars: set[char]) =
var pos = L.bufpos # use registers for pos, buf
while L.buf[pos] in chars:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
L.bufpos = pos
@@ -351,12 +351,12 @@ proc getNumber(L: var TLexer, result: var TToken) =
# We must verify +/- specifically so that we're not past the literal
if L.buf[L.bufpos] in {'+', '-'} and
L.buf[L.bufpos - 1] in {'e', 'E'}:
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
matchChars(L, t, literalishChars)
if L.buf[L.bufpos] in {'\'', 'f', 'F', 'd', 'D', 'i', 'I', 'u', 'U'}:
inc(L.bufpos)
add(t.literal, L.buf[L.bufpos])
t.literal.add(L.buf[L.bufpos])
matchChars(L, t, {'0'..'9'})
L.bufpos = msgPos
lexMessage(L, msgKind, msg % t.literal)
@@ -565,7 +565,7 @@ proc getNumber(L: var TLexer, result: var TToken) =
case result.tokType
of floatTypes:
result.fNumber = parseFloat(result.literal)
of tkUInt64Lit:
of tkUInt64Lit, tkUIntLit:
var iNumber: uint64
var len: int
try:
@@ -687,51 +687,51 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
if L.config.oldNewlines:
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\n not allowed in character literal")
add(tok.literal, L.config.target.tnl)
tok.literal.add(L.config.target.tnl)
else:
add(tok.literal, '\L')
tok.literal.add('\L')
inc(L.bufpos)
of 'p', 'P':
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\p not allowed in character literal")
add(tok.literal, L.config.target.tnl)
tok.literal.add(L.config.target.tnl)
inc(L.bufpos)
of 'r', 'R', 'c', 'C':
add(tok.literal, CR)
tok.literal.add(CR)
inc(L.bufpos)
of 'l', 'L':
add(tok.literal, LF)
tok.literal.add(LF)
inc(L.bufpos)
of 'f', 'F':
add(tok.literal, FF)
tok.literal.add(FF)
inc(L.bufpos)
of 'e', 'E':
add(tok.literal, ESC)
tok.literal.add(ESC)
inc(L.bufpos)
of 'a', 'A':
add(tok.literal, BEL)
tok.literal.add(BEL)
inc(L.bufpos)
of 'b', 'B':
add(tok.literal, BACKSPACE)
tok.literal.add(BACKSPACE)
inc(L.bufpos)
of 'v', 'V':
add(tok.literal, VT)
tok.literal.add(VT)
inc(L.bufpos)
of 't', 'T':
add(tok.literal, '\t')
tok.literal.add('\t')
inc(L.bufpos)
of '\'', '\"':
add(tok.literal, L.buf[L.bufpos])
tok.literal.add(L.buf[L.bufpos])
inc(L.bufpos)
of '\\':
add(tok.literal, '\\')
tok.literal.add('\\')
inc(L.bufpos)
of 'x', 'X':
inc(L.bufpos)
var xi = 0
handleHexChar(L, xi, 1)
handleHexChar(L, xi, 2)
add(tok.literal, chr(xi))
tok.literal.add(chr(xi))
of 'u', 'U':
if tok.tokType == tkCharLit:
lexMessage(L, errGenerated, "\\u not allowed in character literal")
@@ -761,14 +761,14 @@ proc getEscapedChar(L: var TLexer, tok: var TToken) =
lexMessage(L, warnOctalEscape)
var xi = 0
handleDecChars(L, xi)
if (xi <= 255): add(tok.literal, chr(xi))
if (xi <= 255): tok.literal.add(chr(xi))
else: lexMessage(L, errGenerated, "invalid character constant")
else: lexMessage(L, errGenerated, "invalid character constant")
proc newString(s: cstring, len: int): string =
## XXX, how come there is no support for this?
result = newString(len)
for i in 0 ..< len:
for i in 0..<len:
result[i] = s[i]
proc handleCRLF(L: var TLexer, pos: int): int =
@@ -815,12 +815,12 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
tokenEndIgnore(tok, pos+2)
L.bufpos = pos + 3 # skip the three """
break
add(tok.literal, '\"')
tok.literal.add('\"')
inc(pos)
of CR, LF:
tokenEndIgnore(tok, pos)
pos = handleCRLF(L, pos)
add(tok.literal, "\n")
tok.literal.add("\n")
of nimlexbase.EndOfFile:
tokenEndIgnore(tok, pos)
var line2 = L.lineNumber
@@ -830,7 +830,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
L.bufpos = pos
break
else:
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
else:
# ordinary string literal
@@ -841,7 +841,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
if c == '\"':
if mode != normal and L.buf[pos+1] == '\"':
inc(pos, 2)
add(tok.literal, '"')
tok.literal.add('"')
else:
tokenEndIgnore(tok, pos)
inc(pos) # skip '"'
@@ -855,7 +855,7 @@ proc getString(L: var TLexer, tok: var TToken, mode: StringMode) =
getEscapedChar(L, tok)
pos = L.bufpos
else:
add(tok.literal, c)
tok.literal.add(c)
inc(pos)
L.bufpos = pos
@@ -864,7 +864,9 @@ proc getCharacter(L: var TLexer, tok: var TToken) =
inc(L.bufpos) # skip '
var c = L.buf[L.bufpos]
case c
of '\0'..pred(' '), '\'': lexMessage(L, errGenerated, "invalid character literal")
of '\0'..pred(' '), '\'':
lexMessage(L, errGenerated, "invalid character literal")
tok.literal = $c
of '\\': getEscapedChar(L, tok)
else:
tok.literal = $c
@@ -945,15 +947,14 @@ proc getPrecedence*(tok: TToken, strongSpaces: bool): int =
case tok.tokType
of tkOpr:
let L = tok.ident.s.len
let relevantChar = tok.ident.s[0]
# arrow like?
if L > 1 and tok.ident.s[L-1] == '>' and
tok.ident.s[L-2] in {'-', '~', '='}: return considerStrongSpaces(1)
if tok.ident.s.len > 1 and tok.ident.s[^1] == '>' and
tok.ident.s[^2] in {'-', '~', '='}: return considerStrongSpaces(1)
template considerAsgn(value: untyped) =
result = if tok.ident.s[L-1] == '=': 1 else: value
result = if tok.ident.s[^1] == '=': 1 else: value
case relevantChar
of '$', '^': considerAsgn(10)
@@ -1079,7 +1080,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
var lastBackslash = -1
while L.buf[pos] notin {CR, LF, nimlexbase.EndOfFile}:
if L.buf[pos] == '\\': lastBackslash = pos+1
add(tok.literal, L.buf[pos])
tok.literal.add(L.buf[pos])
inc(pos)
tokenEndIgnore(tok, pos)
pos = handleCRLF(L, pos)
@@ -1349,7 +1350,7 @@ proc getPrecedence*(ident: PIdent): int =
initToken(tok)
tok.ident = ident
tok.tokType =
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol) .. ord(tokKeywordHigh) - ord(tkSymbol):
if tok.ident.id in ord(tokKeywordLow) - ord(tkSymbol)..ord(tokKeywordHigh) - ord(tkSymbol):
TTokType(tok.ident.id + ord(tkSymbol))
else: tkOpr
getPrecedence(tok, false)

View File

@@ -16,6 +16,8 @@
import modulegraphs, lineinfos, idents, ast, renderer, semdata,
sighashes, lowerings, options, types, msgs, magicsys, tables
from trees import isCaseObj
type
TLiftCtx = object
g: ModuleGraph
@@ -34,38 +36,73 @@ proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineIn
proc at(a, i: PNode, elemType: PType): PNode =
result = newNodeI(nkBracketExpr, a.info, 2)
result.sons[0] = a
result.sons[1] = i
result[0] = a
result[1] = i
result.typ = elemType
proc fillBodyTup(c: var TLiftCtx; t: PType; body, x, y: PNode) =
for i in 0 ..< t.len:
for i in 0..<t.len:
let lit = lowerings.newIntLit(c.g, x.info, i)
fillBody(c, t.sons[i], body, x.at(lit, t.sons[i]), y.at(lit, t.sons[i]))
let b = if c.kind == attachedTrace: y else: y.at(lit, t[i])
fillBody(c, t[i], body, x.at(lit, t[i]), b)
proc dotField(x: PNode, f: PSym): PNode =
result = newNodeI(nkDotExpr, x.info, 2)
result.sons[0] = x
result.sons[1] = newSymNode(f, x.info)
if x.typ.skipTypes(abstractInst).kind == tyVar:
result[0] = x.newDeref
else:
result[0] = x
result[1] = newSymNode(f, x.info)
result.typ = f.typ
proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
proc newAsgnStmt(le, ri: PNode): PNode =
result = newNodeI(nkAsgn, le.info, 2)
result[0] = le
result[1] = ri
proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
body.add newAsgnStmt(x, y)
proc genAddr(g: ModuleGraph; x: PNode): PNode =
if x.kind == nkHiddenDeref:
checkSonsLen(x, 1, g.config)
result = x[0]
else:
result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ))
result.add x
proc destructorCall(g: ModuleGraph; op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ[0])
result.add(newSymNode(op))
result.add genAddr(g, x)
proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode; enforceDefaultOp: bool) =
case n.kind
of nkSym:
let f = n.sym
fillBody(c, f.typ, body, x.dotField(f), y.dotField(f))
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
enforceDefaultOp:
defaultOp(c, f.typ, body, x.dotField(f), b)
else:
fillBody(c, f.typ, body, x.dotField(f), b)
of nkNilLit: discard
of nkRecCase:
if c.kind in {attachedSink, attachedAsgn, attachedDeepCopy}:
## the value needs to be destroyed before we assign the selector
## or the value is lost
# XXX This is only correct for 'attachedSink'!
var localEnforceDefaultOp = enforceDefaultOp
if c.kind == attachedSink:
# the value needs to be destroyed before we assign the selector
# or the value is lost
let prevKind = c.kind
c.kind = attachedDestructor
fillBodyObj(c, n, body, x, y)
fillBodyObj(c, n, body, x, y, enforceDefaultOp = false)
c.kind = prevKind
localEnforceDefaultOp = true
# copy the selector:
fillBodyObj(c, n[0], body, x, y)
fillBodyObj(c, n[0], body, x, y, enforceDefaultOp = false)
# we need to generate a case statement:
var caseStmt = newNodeI(nkCaseStmt, c.info)
# XXX generate 'if' that checks same branches
@@ -74,64 +111,102 @@ proc fillBodyObj(c: var TLiftCtx; n, body, x, y: PNode) =
caseStmt.add(access)
var emptyBranches = 0
# copy the branches over, but replace the fields with the for loop body:
for i in 1 ..< n.len:
for i in 1..<n.len:
var branch = copyTree(n[i])
let L = branch.len
branch.sons[L-1] = newNodeI(nkStmtList, c.info)
branch[^1] = newNodeI(nkStmtList, c.info)
fillBodyObj(c, n[i].lastSon, branch.sons[L-1], x, y)
if branch.sons[L-1].len == 0: inc emptyBranches
fillBodyObj(c, n[i].lastSon, branch[^1], x, y,
enforceDefaultOp = localEnforceDefaultOp)
if branch[^1].len == 0: inc emptyBranches
caseStmt.add(branch)
if emptyBranches != n.len-1:
body.add(caseStmt)
of nkRecList:
for t in items(n): fillBodyObj(c, t, body, x, y)
for t in items(n): fillBodyObj(c, t, body, x, y, enforceDefaultOp)
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)
fillBodyObj(c, t.n, body, x, y, enforceDefaultOp = false)
proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
if t.len > 0 and t.sons[0] != nil:
fillBodyObjT(c, skipTypes(t.sons[0], abstractPtrs), body, x, y)
fillBodyObj(c, t.n, body, x, y)
var hasCase = isCaseObj(t.n)
var obj = t
while obj.len > 0 and obj[0] != nil:
obj = skipTypes(obj[0], abstractPtrs)
hasCase = hasCase or isCaseObj(obj.n)
proc genAddr(g: ModuleGraph; x: PNode): PNode =
if x.kind == nkHiddenDeref:
checkSonsLen(x, 1, g.config)
result = x.sons[0]
if hasCase and c.kind in {attachedAsgn, attachedDeepCopy}:
# assignment for case objects is complex, we do:
# =destroy(dest)
# wasMoved(dest)
# for every field:
# `=` dest.field, src.field
# ^ this is what we used to do, but for 'result = result.sons[0]' it
# destroys 'result' too early.
# So this is what we really need to do:
# let blob {.cursor.} = dest # remembers the old dest.kind
# wasMoved(dest)
# dest.kind = src.kind
# for every field (dependent on dest.kind):
# `=` dest.field, src.field
# =destroy(blob)
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
temp.typ = x.typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info)
let blob = newSymNode(temp)
v.addVar(blob, x)
body.add v
#body.add newAsgnStmt(blob, x)
var wasMovedCall = newNodeI(nkCall, c.info)
wasMovedCall.add(newSymNode(createMagic(c.g, "wasMoved", mWasMoved)))
wasMovedCall.add x # mWasMoved does not take the address
body.add wasMovedCall
fillBodyObjTImpl(c, t, body, x, y)
when false:
# does not work yet due to phase-ordering problems:
assert t.destructor != nil
body.add destructorCall(c.g, t.destructor, blob)
let prevKind = c.kind
c.kind = attachedDestructor
fillBodyObjTImpl(c, t, body, blob, y)
c.kind = prevKind
else:
result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ))
addSon(result, x)
fillBodyObjTImpl(c, t, body, x, y)
proc newAsgnCall(g: ModuleGraph; op: PSym; x, y: PNode): PNode =
proc newHookCall(g: ModuleGraph; op: PSym; x, y: PNode): PNode =
#if sfError in op.flags:
# localError(c.config, x.info, "usage of '$1' is a user-defined error" % op.name.s)
result = newNodeI(nkCall, x.info)
result.add newSymNode(op)
result.add genAddr(g, x)
result.add y
proc newAsgnStmt(le, ri: PNode): PNode =
result = newNodeI(nkAsgn, le.info, 2)
result.sons[0] = le
result.sons[1] = ri
if op.typ.sons[1].kind == tyVar:
result.add genAddr(g, x)
else:
result.add x
if y != nil:
result.add y
proc newOpCall(op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ.sons[0])
result = newNodeIT(nkCall, x.info, op.typ[0])
result.add(newSymNode(op))
result.add x
proc destructorCall(g: ModuleGraph; op: PSym; x: PNode): PNode =
result = newNodeIT(nkCall, x.info, op.typ.sons[0])
result.add(newSymNode(op))
result.add genAddr(g, x)
proc newDeepCopyCall(op: PSym; x, y: PNode): PNode =
result = newAsgnStmt(x, newOpCall(op, y))
proc useNoGc(c: TLiftCtx; t: PType): bool {.inline.} =
result = optNimV2 in c.g.config.globalOptions and
result = optSeqDestructors in c.g.config.globalOptions and
({tfHasGCedMem, tfHasOwned} * t.flags != {} or t.isGCedMem)
proc requiresDestructor(c: TLiftCtx; t: PType): bool {.inline.} =
result = optSeqDestructors in c.g.config.globalOptions and
containsGarbageCollectedRef(t)
proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
if c.c != nil and typeInst != nil:
result = c.c.instTypeBoundOp(c.c, op, typeInst, c.info, attachedAsgn, 1)
@@ -142,7 +217,7 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym =
proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
field: var PSym): bool =
if optNimV2 in c.g.config.globalOptions:
if optSeqDestructors in c.g.config.globalOptions:
let op = field
if field != nil and sfOverriden in field.flags:
if sfError in op.flags:
@@ -150,7 +225,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
#else:
# markUsed(c.g.config, c.info, op, c.g.usageSym)
onUse(c.info, op)
body.add newAsgnCall(c.g, op, x, y)
body.add newHookCall(c.g, op, x, y)
result = true
elif tfHasAsgn in t.flags:
var op: PSym
@@ -179,12 +254,20 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
#debug(t)
#return false
assert op.ast[genericParamsPos].kind == nkEmpty
body.add newAsgnCall(c.g, op, x, y)
body.add newHookCall(c.g, op, x, y)
result = true
proc addDestructorCall(c: var TLiftCtx; t: PType; body, x: PNode) =
proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
let t = orig.skipTypes(abstractInst)
var op = t.destructor
if op == nil and useNoGc(c, t):
if op != nil and sfOverriden in op.flags:
if op.ast[genericParamsPos].kind != nkEmpty:
# patch generic destructor:
op = instantiateGeneric(c, op, t, t.typeInst)
t.attachedOps[attachedDestructor] = op
if op == nil and (useNoGc(c, t) or requiresDestructor(c, t)):
op = produceSym(c.g, c.c, t, attachedDestructor, c.info)
doAssert op != nil
doAssert op == t.destructor
@@ -213,10 +296,10 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
body.add destructorCall(c.g, op, x)
result = true
#result = addDestructorCall(c, t, body, x)
of attachedAsgn:
result = considerAsgnOrSink(c, t, body, x, y, t.assignment)
of attachedSink:
result = considerAsgnOrSink(c, t, body, x, y, t.asink)
of attachedAsgn, attachedSink, attachedTrace:
result = considerAsgnOrSink(c, t, body, x, y, t.attachedOps[c.kind])
of attachedDispose:
result = considerAsgnOrSink(c, t, body, x, nil, t.attachedOps[c.kind])
of attachedDeepCopy:
let op = t.attachedOps[attachedDeepCopy]
if op != nil:
@@ -225,17 +308,6 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
body.add newDeepCopyCall(op, x, y)
result = true
proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind != attachedDestructor:
body.add newAsgnStmt(x, y)
proc addVar(father, v, value: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart.sons[0] = v
vpart.sons[1] = newNodeI(nkEmpty, v.info)
vpart.sons[2] = value
addSon(father, vpart)
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info)
temp.typ = getSysType(c.g, body.info, tyInt)
@@ -256,8 +328,8 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
let cmp = genBuiltin(c.g, mLtI, "<", i)
cmp.add genLen(c.g, dest)
cmp.typ = getSysType(c.g, c.info, tyBool)
result.sons[0] = cmp
result.sons[1] = newNodeI(nkStmtList, c.info)
result[0] = cmp
result[1] = newNodeI(nkStmtList, c.info)
proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action))
@@ -288,12 +360,12 @@ proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let i = declareCounter(c, body, firstOrd(c.g.config, t))
let i = declareCounter(c, body, toInt64(firstOrd(c.g.config, t)))
let whileLoop = genWhileLoop(c, i, x)
let elemType = t.lastSon
fillBody(c, elemType, whileLoop.sons[1], x.at(i, elemType),
y.at(i, elemType))
addIncStmt(c, whileLoop.sons[1], i)
let b = if c.kind == attachedTrace: y else: y.at(i, elemType)
fillBody(c, elemType, whileLoop[1], x.at(i, elemType), b)
addIncStmt(c, whileLoop[1], i)
body.add whileLoop
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
@@ -316,13 +388,26 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# destroy all elements:
forallElements(c, t, body, x, y)
body.add genBuiltin(c.g, mDestroy, "destroy", x)
of attachedTrace:
# follow all elements:
forallElements(c, t, body, x, y)
of attachedDispose:
body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
createTypeBoundOps(c.g, c.c, t, body.info)
# 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})
let canon = c.g.canonTypes.getOrDefault(h)
if canon != nil: t = canon
case c.kind
of attachedAsgn, attachedDeepCopy:
doAssert t.assignment != nil
body.add newAsgnCall(c.g, t.assignment, x, y)
body.add newHookCall(c.g, t.assignment, x, y)
of attachedSink:
# we always inline the move for better performance:
let moveCall = genBuiltin(c.g, mMove, "move", x)
@@ -333,10 +418,14 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# alternatively we could do this:
when false:
doAssert t.asink != nil
body.add newAsgnCall(c.g, t.asink, x, y)
body.add newHookCall(c.g, t.asink, x, y)
of attachedDestructor:
doAssert t.destructor != nil
body.add destructorCall(c.g, t.destructor, x)
of attachedTrace:
body.add newHookCall(c.g, t.attachedOps[c.kind], x, y)
of attachedDispose:
body.add newHookCall(c.g, t.attachedOps[c.kind], x, nil)
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
@@ -348,8 +437,108 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
doAssert t.destructor != nil
moveCall.add destructorCall(c.g, t.destructor, x)
body.add moveCall
of attachedDestructor:
of attachedDestructor, attachedDispose:
body.add genBuiltin(c.g, mDestroy, "destroy", x)
of attachedTrace:
discard "strings are atomic and have no inner elements that are to trace"
proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon
if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
else:
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, x)
let isCyclic = c.g.config.selectedGC == gcOrc and types.canFormAcycle(t)
var cond: PNode
if isCyclic:
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer)
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, x, typInfo)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, x)
else:
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
cond.typ = getSysType(c.g, x.info, tyBool)
case c.kind
of attachedSink:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedAsgn:
body.add genIf(c, y, callCodegenProc(c.g,
if isCyclic: "nimIncRefCyclic" else: "nimIncRef", c.info, y))
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
actions.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfo, "getTypeInfo", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer)
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y)
else:
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y)
of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector.
when false:
let cond = copyTree(x)
cond.typ = getSysType(c.g, x.info, tyBool)
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x)
body.add genIf(c, cond, actions)
proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
## Closures are really like refs except they always use a virtual destructor
## and we need to do the refcounting only on the ref field which we call 'xenv':
let xenv = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xenv.typ = getSysType(c.g, c.info, tyPointer)
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xenv)
let decRefProc =
if c.g.config.selectedGC == gcOrc: "nimDecRefIsLastCyclicDyn"
else: "nimDecRefIsLast"
let cond = callCodegenProc(c.g, decRefProc, c.info, xenv)
cond.typ = getSysType(c.g, x.info, tyBool)
case c.kind
of attachedSink:
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedAsgn:
let yenv = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
yenv.typ = getSysType(c.g, c.info, tyPointer)
let incRefProc =
if c.g.config.selectedGC == gcOrc: "nimIncRefCyclic"
else: "nimIncRef"
body.add genIf(c, yenv, callCodegenProc(c.g, incRefProc, c.info, yenv))
body.add genIf(c, cond, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
actions.add newAsgnStmt(xenv, newNodeIT(nkNilLit, body.info, xenv.typ))
body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv), y)
of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector.
when false:
let cond = copyTree(xenv)
cond.typ = getSysType(c.g, xenv.info, tyBool)
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, xenv)
body.add genIf(c, cond, actions)
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind
@@ -359,18 +548,22 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
body.add newAsgnStmt(x, y)
of attachedAsgn:
body.add genIf(c, y, callCodegenProc(c.g, "nimIncWeakRef", c.info, y))
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 attachedDestructor:
# it's better to prepend the destruction of weak refs in order to
# prevent wrong "dangling refs exist" problems:
let des = genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDecWeakRef", c.info, x)
actions.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
let des = genIf(c, x, actions)
if body.len == 0:
body.add des
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var actions = newNodeI(nkStmtList, c.info)
@@ -391,20 +584,22 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, x, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
actions.add newAsgnStmt(x, newNodeIT(nkNilLit, body.info, t))
body.add genIf(c, x, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if c.kind == attachedDeepCopy:
# a big problem is that we don't know the enviroment's type here, so we
# a big problem is that we don't know the environment's type here, so we
# have to go through some indirection; we delegate this to the codegen:
let call = newNodeI(nkCall, c.info, 2)
call.typ = t
call.sons[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
call.sons[1] = y
call[0] = newSymNode(createMagic(c.g, "deepCopy", mDeepCopy))
call[1] = y
body.add newAsgnStmt(x, call)
elif optNimV2 in c.g.config.globalOptions and
optRefCheck in c.g.config.options:
elif (optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options) or c.g.config.selectedGC in {gcArc, gcOrc}:
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.g, c.info, tyPointer)
case c.kind
@@ -416,22 +611,25 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedAsgn:
let yy = genBuiltin(c.g, mAccessEnv, "accessEnv", y)
yy.typ = getSysType(c.g, c.info, tyPointer)
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncWeakRef", c.info, yy))
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 attachedDestructor:
let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
var actions = newNodeI(nkStmtList, c.info)
actions.add callCodegenProc(c.g, "nimDecWeakRef", c.info, xx)
actions.add newAsgnStmt(xx, newNodeIT(nkNilLit, body.info, xx.typ))
let des = genIf(c, xx, actions)
if body.len == 0:
body.add des
else:
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xx = genBuiltin(c.g, mAccessEnv, "accessEnv", x)
xx.typ = getSysType(c.g, c.info, tyPointer)
var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
case c.kind
@@ -439,29 +637,36 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, xx, actions)
body.add newAsgnStmt(x, y)
of attachedDestructor:
actions.add newAsgnStmt(xx, newNodeIT(nkNilLit, body.info, xx.typ))
body.add genIf(c, xx, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace, attachedDispose: discard
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case t.kind
of tyNone, tyEmpty, tyVoid: discard
of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCString,
tyPtr, tyOpt, tyUncheckedArray:
tyPtr, tyOpt, tyUncheckedArray, tyVar, tyLent:
defaultOp(c, t, body, x, y)
of tyRef:
if optNimV2 in c.g.config.globalOptions and
optRefCheck in c.g.config.options:
if c.g.config.selectedGC in {gcArc, gcOrc}:
atomicRefOp(c, t, body, x, y)
elif (optOwnedRefs in c.g.config.globalOptions and
optRefCheck in c.g.config.options):
weakrefOp(c, t, body, x, y)
else:
defaultOp(c, t, body, x, y)
of tyProc:
if t.callConv == ccClosure:
closureOp(c, t, body, x, y)
if c.g.config.selectedGC in {gcArc, gcOrc}:
atomicClosureOp(c, t, body, x, y)
else:
closureOp(c, t, body, x, y)
else:
defaultOp(c, t, body, x, y)
of tyOwned:
let base = t.skipTypes(abstractInstOwned)
if optNimV2 in c.g.config.globalOptions:
if optOwnedRefs in c.g.config.globalOptions:
case base.kind
of tyRef:
ownedRefOp(c, base, body, x, y)
@@ -480,12 +685,12 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of tySequence:
if useNoGc(c, t):
useSeqOrStrOp(c, t, body, x, y)
elif c.g.config.selectedGC == gcDestructors:
elif optSeqDestructors in c.g.config.globalOptions:
# note that tfHasAsgn is propagated so we need the check on
# 'selectedGC' here to determine if we have the new runtime.
discard considerUserDefinedOp(c, t, body, x, y)
elif tfHasAsgn in t.flags:
if c.kind != attachedDestructor:
if c.kind in {attachedAsgn, attachedSink, attachedDeepCopy}:
body.add newSeqCall(c.g, x, y)
forallElements(c, t, body, x, y)
else:
@@ -499,28 +704,33 @@ 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):
fillBodyObjT(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)
else:
fillBodyObjT(c, t, body, x, y)
of tyDistinct:
if not considerUserDefinedOp(c, t, body, x, y):
fillBody(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
fillBody(c, t[0], body, x, y)
of tyTuple:
fillBodyTup(c, t, body, x, y)
of tyVarargs, tyOpenArray:
localError(c.g.config, c.info, "cannot copy openArray")
if c.kind == attachedDestructor and (tfHasAsgn in t.flags or useNoGc(c, t)):
forallElements(c, t, body, x, y)
else:
discard "cannot copy openArray"
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
tyTypeDesc, tyGenericInvocation, tyForward:
#internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t))
discard
of tyVar, tyLent:
if c.kind != attachedDestructor:
fillBody(c, lastSon(t), body, x, y)
of tyOrdinal, tyRange, tyInferred,
tyGenericInst, tyStatic, tyAlias, tySink:
fillBody(c, lastSon(t), body, x, y)
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo): PSym =
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
kind: TTypeAttachedOp; info: TLineInfo): PSym =
assert typ.kind == tyDistinct
let baseType = typ[0]
if baseType.attachedOps[kind] == nil:
@@ -546,36 +756,53 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
a.asgnForType = typ
let dest = newSym(skParam, getIdent(g.cache, "dest"), result, info)
let src = newSym(skParam, getIdent(g.cache, "src"), result, info)
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"), result, info)
var d: PNode
#if kind notin {attachedTrace, attachedDispose}:
dest.typ = makeVarType(typ.owner, typ)
src.typ = typ
d = newDeref(newSymNode(dest))
#else:
# dest.typ = typ
# d = newSymNode(dest)
if kind == attachedTrace:
src.typ = getSysType(g, info, tyPointer)
else:
src.typ = typ
result.typ = newProcType(info, typ.owner)
result.typ.addParam dest
if kind != attachedDestructor:
if kind notin {attachedDestructor, attachedDispose}:
result.typ.addParam src
# register this operation already:
typ.attachedOps[kind] = result
var tk: TTypeKind
if optNimV2 in g.config.globalOptions:
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
if kind == attachedSink and typ.attachedOps[attachedDestructor] != nil and
sfOverriden in typ.attachedOps[attachedDestructor].flags:
## compiler can use a combination of `=destroy` and memCopy for sink op
dest.flags.incl sfCursor
body.add newOpCall(typ.attachedOps[attachedDestructor], d[0])
body.add newAsgnStmt(d, newSymNode(src))
else:
tk = tyNone # no special casing for strings and seqs
case tk
of tySequence:
fillSeqOp(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
of tyString:
fillStrOp(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
else:
fillBody(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
var tk: TTypeKind
if g.config.selectedGC in {gcArc, gcOrc, gcHooks}:
tk = skipTypes(typ, {tyOrdinal, tyRange, tyInferred, tyGenericInst, tyStatic, tyAlias, tySink}).kind
else:
tk = tyNone # no special casing for strings and seqs
case tk
of tySequence:
fillSeqOp(a, typ, body, d, newSymNode(src))
of tyString:
fillStrOp(a, typ, body, d, newSymNode(src))
else:
fillBody(a, typ, body, d, newSymNode(src))
var n = newNodeI(nkProcDef, info, bodyPos+1)
for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
n.sons[namePos] = newSymNode(result)
n.sons[paramsPos] = result.typ.n
n.sons[bodyPos] = body
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
n[namePos] = newSymNode(result)
n[paramsPos] = result.typ.n
n[bodyPos] = body
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfGeneratedOp
@@ -595,7 +822,7 @@ proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) =
internalError(g.config, info, "resolved destructor is generic")
if t.destructor.magic == mDestroy:
internalError(g.config, info, "patching mDestroy with mDestroy?")
n.sons[0] = newSymNode(t.destructor)
n[0] = newSymNode(t.destructor)
for x in n: patchBody(g, c, x, info)
template inst(field, t) =
@@ -613,24 +840,29 @@ template inst(field, t) =
else:
localError(g.config, info, "unresolved generic parameter")
proc isTrival(s: PSym): bool {.inline.} = s == nil or s.ast[bodyPos].len == 0
proc isTrival(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0)
proc isEmptyContainer(g: ModuleGraph, t: PType): bool =
(t.kind == tyArray and lengthOrd(g.config, t[0]) == 0) or
(t.kind == tySequence and t[0].kind == tyError)
proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) =
## In the semantic pass this is called in strategic places
## to ensure we lift assignment, destructors and moves properly.
## The later 'injectdestructors' pass depends on it.
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.skipTypes({tyAlias}).flags != {}: return
if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.flags != {}: return
incl orig.flags, tfCheckedForDestructor
let h = sighashes.hashType(orig, {CoType, CoConsiderOwned, CoDistinct})
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
if isEmptyContainer(skipped): return
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
var canon = g.canonTypes.getOrDefault(h)
var overwrite = false
if canon == nil:
let typ = orig.skipTypes({tyGenericInst, tyAlias})
g.canonTypes[h] = typ
canon = typ
elif canon != orig:
overwrite = true
g.canonTypes[h] = skipped
canon = skipped
# multiple cases are to distinguish here:
# 1. we don't know yet if 'typ' has a nontrival destructor.
@@ -639,15 +871,18 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
# 4. We have a custom destructor.
# 5. We have a (custom) generic destructor.
# we do not generate '=trace' nor '=dispose' procs if we
# have the cycle detection disabled, saves code size.
let lastAttached = if g.config.selectedGC == gcOrc: attachedDispose
else: attachedSink
# we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..attachedSink:
for k in attachedDestructor..lastAttached:
if canon.attachedOps[k] == nil:
discard produceSym(g, c, canon, k, info)
else:
inst(canon.attachedOps[k], canon)
if overwrite:
for k in attachedDestructor..attachedSink:
if canon != orig:
orig.attachedOps[k] = canon.attachedOps[k]
if not isTrival(orig.destructor):

View File

@@ -30,10 +30,10 @@ proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode =
let field = addUniqueField(c.objType, s, c.cache)
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = c.objType
add(deref, newSymNode(c.partialParam, info))
deref.add(newSymNode(c.partialParam, info))
result = newNodeI(nkDotExpr, info)
add(result, deref)
add(result, newSymNode(field))
result.add(deref)
result.add(newSymNode(field))
result.typ = field.typ
proc liftLocals(n: PNode; i: int; c: var Ctx) =
@@ -44,12 +44,12 @@ proc liftLocals(n: PNode; i: int; c: var Ctx) =
n[i] = lookupOrAdd(c, it.sym, it.info)
of procDefs, nkTypeSection: discard
else:
for i in 0 ..< it.safeLen:
for i in 0..<it.safeLen:
liftLocals(it, i, c)
proc lookupParam(params, dest: PNode): PSym =
if dest.kind != nkIdent: return nil
for i in 1 ..< params.len:
for i in 1..<params.len:
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
return params[i].sym

View File

@@ -13,7 +13,7 @@
import ropes, tables, pathutils
const
explanationsBaseUrl* = "https://nim-lang.org/docs/manual"
explanationsBaseUrl* = "https://nim-lang.org/docs"
type
TMsgKind* = enum
@@ -23,6 +23,7 @@ type
errGeneralParseError,
errNewSectionExpected,
errInvalidDirectiveX,
errProveInit,
errGenerated,
errUser,
warnCannotOpenFile,
@@ -33,12 +34,18 @@ type
warnFieldXNotSupported, warnCommentXIgnored,
warnTypelessParam,
warnUseBase, warnWriteToForeignHeap, warnUnsafeCode,
warnUnusedImportX,
warnInheritFromException,
warnEachIdentIsTuple,
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUnsafeSetLen,
warnUnsafeDefault,
warnProveInit, warnProveField, warnProveIndex,
warnStaticIndexCheck, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnCaseTransition, warnUser,
warnInconsistentSpacing, warnCaseTransition, warnCycleCreated, warnUser,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintLineTooLong, hintXDeclaredButNotUsed,
hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
hintConditionAlwaysTrue, hintConditionAlwaysFalse, hintName, hintPattern,
@@ -59,6 +66,7 @@ const
errGeneralParseError: "general parse error",
errNewSectionExpected: "new section expected",
errInvalidDirectiveX: "invalid directive: '$1'",
errProveInit: "Cannot prove that '$1' is initialized.",
errGenerated: "$1",
errUser: "$1",
warnCannotOpenFile: "cannot open '$1'",
@@ -78,10 +86,16 @@ const
warnUseBase: "use {.base.} for base methods; baseless methods are deprecated",
warnWriteToForeignHeap: "write to foreign heap",
warnUnsafeCode: "unsafe code: '$1'",
warnUnusedImportX: "imported and not used: '$1'",
warnInheritFromException: "inherit from a more precise exception type like ValueError, IOError or OSError",
warnEachIdentIsTuple: "each identifier is a tuple",
warnUnsafeSetLen: "setLen can potentially expand the sequence, " &
"but the element type '$1' doesn't have a valid default value",
warnUnsafeDefault: "The '$1' type doesn't have a valid default value",
warnProveInit: "Cannot prove that '$1' is initialized. This will become a compile time error in the future.",
warnProveField: "cannot prove that field '$1' is accessible",
warnProveIndex: "cannot prove index '$1' is valid",
warnStaticIndexCheck: "$1",
warnGcUnsafe: "not GC-safe: '$1'",
warnGcUnsafe2: "$1",
warnUninit: "'$1' might not have been initialized",
@@ -91,10 +105,12 @@ const
warnResultShadowed: "Special variable 'result' is shadowed.",
warnInconsistentSpacing: "Number of spaces around '$#' is not consistent",
warnCaseTransition: "Potential object case transition, instantiate new object instead",
warnCycleCreated: "$1",
warnUser: "$1",
hintSuccess: "operation successful: $#",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintCC: "CC: \'$1\'", # unused
# keep in sync with `testament.isSuccess`
hintSuccessX: "$loc LOC; $sec sec; $mem; $build build; proj: $project; out: $output",
hintCC: "CC: $1",
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
@@ -111,7 +127,7 @@ const
hintName: "$1",
hintPattern: "$1",
hintExecuting: "$1",
hintLinking: "",
hintLinking: "$1",
hintDependency: "$1",
hintSource: "$1",
hintPerformance: "$1",
@@ -133,14 +149,18 @@ const
"LanguageXNotSupported", "FieldXNotSupported",
"CommentXIgnored",
"TypelessParam", "UseBase", "WriteToForeignHeap",
"UnsafeCode", "EachIdentIsTuple",
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
"UnsafeCode", "UnusedImport", "InheritFromException",
"EachIdentIsTuple",
"UnsafeSetLen", "UnsafeDefault",
"ProveInit", "ProveField", "ProveIndex",
"IndexCheck", "GcUnsafe", "GcUnsafe2", "Uninit",
"GcMem", "Destructor", "LockLevel", "ResultShadowed",
"Spacing", "CaseTransition", "User"]
"Spacing", "CaseTransition", "CycleCreated", "User"]
HintsToStr* = [
"Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"XDeclaredButNotUsed",
"ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "CondFalse", "Name", "Pattern", "Exec", "Link", "Dependency",
"Source", "Performance", "StackTrace", "GCStats", "GlobalVar", "ExpandMacro",
@@ -221,7 +241,7 @@ type
TErrorOutputs* = set[TErrorOutput]
ERecoverableError* = object of ValueError
ESuggestDone* = object of Exception
ESuggestDone* = object of ValueError
proc `==`*(a, b: FileIndex): bool {.borrow.}
@@ -230,18 +250,16 @@ proc raiseRecoverableError*(msg: string) {.noinline.} =
const
InvalidFileIdx* = FileIndex(-1)
proc unknownLineInfo*(): TLineInfo =
result.line = uint16(0)
result.col = int16(-1)
result.fileIndex = InvalidFileIdx
unknownLineInfo* = TLineInfo(line: 0, col: -1, fileIndex: InvalidFileIdx)
type
Severity* {.pure.} = enum ## VS Code only supports these three
Hint, Warning, Error
const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
const
trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions
# are produced within comments and string literals
commandLineIdx* = FileIndex(-3)
type
MsgConfig* = object ## does not need to be stored in the incremental cache
@@ -259,7 +277,7 @@ type
proc initMsgConfig*(): MsgConfig =
result.msgContext = @[]
result.lastError = unknownLineInfo()
result.lastError = unknownLineInfo
result.filenameToIndexTbl = initTable[string, FileIndex]()
result.fileInfos = @[]
result.errorOutputs = {eStdOut, eStdErr}

View File

@@ -37,7 +37,7 @@ proc beautifyName(s: string, k: TSymKind): string =
# Types should start with a capital unless builtins like 'int' etc.:
if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
"char", "byte", "bool", "openArray", "seq", "array", "void",
"pointer", "float", "csize", "cdouble", "cchar", "cschar",
"pointer", "float", "csize", "csize_t", "cdouble", "cchar", "cschar",
"cshort", "cu", "nil", "typedesc", "auto", "any",
"range", "openarray", "varargs", "set", "cfloat", "ref", "ptr",
"untyped", "typed", "static", "sink", "lent", "type", "owned"]:
@@ -72,10 +72,9 @@ proc beautifyName(s: string, k: TSymKind): string =
proc differ*(line: string, a, b: int, x: string): string =
proc substrEq(s: string, pos, last: int, substr: string): bool =
var i = 0
var length = substr.len
while i < length and pos+i <= last and s[pos+i] == substr[i]:
while i < substr.len and pos+i <= last and s[pos+i] == substr[i]:
inc i
return i == length
return i == substr.len
let last = min(b, line.len)

View File

@@ -12,9 +12,11 @@
import
pathutils
# support '-d:useGnuReadline' for backwards compatibility:
when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
import rdstdin
# support `useGnuReadline`, `useLinenoise` for backwards compatibility
const hasRstdin = (defined(nimUseLinenoise) or defined(useLinenoise) or defined(useGnuReadline)) and
not defined(windows)
when hasRstdin: import rdstdin
type
TLLRepl* = proc (s: PLLStream, buf: pointer, bufLen: int): int
@@ -109,12 +111,12 @@ proc llReadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
var line = newStringOfCap(120)
var triples = 0
while readLineFromStdin(if s.s.len == 0: ">>> " else: "... ", line):
add(s.s, line)
add(s.s, "\n")
s.s.add(line)
s.s.add("\n")
inc triples, countTriples(line)
if not continueLine(line, (triples and 1) == 1): break
inc(s.lineOffset)
result = min(bufLen, len(s.s) - s.rd)
result = min(bufLen, s.s.len - s.rd)
if result > 0:
copyMem(buf, addr(s.s[s.rd]), result)
inc(s.rd, result)
@@ -124,7 +126,7 @@ proc llStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int =
of llsNone:
result = 0
of llsString:
result = min(bufLen, len(s.s) - s.rd)
result = min(bufLen, s.s.len - s.rd)
if result > 0:
copyMem(buf, addr(s.s[0 + s.rd]), result)
inc(s.rd, result)
@@ -139,7 +141,7 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool =
of llsNone:
result = true
of llsString:
while s.rd < len(s.s):
while s.rd < s.s.len:
case s.s[s.rd]
of '\x0D':
inc(s.rd)
@@ -149,9 +151,9 @@ proc llStreamReadLine*(s: PLLStream, line: var string): bool =
inc(s.rd)
break
else:
add(line, s.s[s.rd])
line.add(s.s[s.rd])
inc(s.rd)
result = line.len > 0 or s.rd < len(s.s)
result = line.len > 0 or s.rd < s.s.len
of llsFile:
result = readLine(s.f, line)
of llsStdIn:
@@ -162,8 +164,8 @@ proc llStreamWrite*(s: PLLStream, data: string) =
of llsNone, llsStdIn:
discard
of llsString:
add(s.s, data)
inc(s.wr, len(data))
s.s.add(data)
inc(s.wr, data.len)
of llsFile:
write(s.f, data)
@@ -177,7 +179,7 @@ proc llStreamWrite*(s: PLLStream, data: char) =
of llsNone, llsStdIn:
discard
of llsString:
add(s.s, data)
s.s.add(data)
inc(s.wr)
of llsFile:
c = data
@@ -189,7 +191,7 @@ proc llStreamWrite*(s: PLLStream, buf: pointer, buflen: int) =
discard
of llsString:
if buflen > 0:
setLen(s.s, len(s.s) + buflen)
setLen(s.s, s.s.len + buflen)
copyMem(addr(s.s[0 + s.wr]), buf, buflen)
inc(s.wr, buflen)
of llsFile:
@@ -204,7 +206,7 @@ proc llStreamReadAll*(s: PLLStream): string =
of llsString:
if s.rd == 0: result = s.s
else: result = substr(s.s, s.rd)
s.rd = len(s.s)
s.rd = s.s.len
of llsFile:
result = newString(bufSize)
var bytes = readBuffer(s.f, addr(result[0]), bufSize)

View File

@@ -36,11 +36,11 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
of nkAccQuoted:
case n.len
of 0: handleError(n, origin)
of 1: result = considerQuotedIdent(c, n.sons[0], origin)
of 1: result = considerQuotedIdent(c, n[0], origin)
else:
var id = ""
for i in 0..<n.len:
let x = n.sons[i]
let x = n[i]
case x.kind
of nkIdent: id.add(x.ident.s)
of nkSym: id.add(x.sym.name.s)
@@ -49,7 +49,7 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
result = getIdent(c.cache, id)
of nkOpenSymChoice, nkClosedSymChoice:
if n[0].kind == nkSym:
result = n.sons[0].sym.name
result = n[0].sym.name
else:
handleError(n, origin)
else:
@@ -100,16 +100,15 @@ proc searchInScopes*(c: PContext, s: PIdent): PSym =
if result != nil: return
result = nil
when declared(echo):
proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
var i = 0
for scope in walkScopes(c.currentScope):
echo "scope ", i
for h in 0 .. high(scope.symbols.data):
if scope.symbols.data[h] != nil:
echo scope.symbols.data[h].name.s
if i == limit: break
inc i
proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
var i = 0
for scope in walkScopes(c.currentScope):
echo "scope ", i
for h in 0..high(scope.symbols.data):
if scope.symbols.data[h] != nil:
echo scope.symbols.data[h].name.s
if i == limit: break
inc i
proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
for scope in walkScopes(c.currentScope):
@@ -124,7 +123,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
## creates an error symbol to avoid cascading errors (for IDE support)
var m = n
# ensure that 'considerQuotedIdent' can't fail:
if m.kind == nkDotExpr: m = m.sons[1]
if m.kind == nkDotExpr: m = m[1]
let ident = if m.kind in {nkIdent, nkSym, nkAccQuoted}:
considerQuotedIdent(c, m)
else:
@@ -233,7 +232,7 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addInterfaceDeclAux(c, sym)
when defined(nimfix):
# when we cannot find the identifier, retry with a changed identifer:
# when we cannot find the identifier, retry with a changed identifier:
proc altSpelling(x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(toLowerAscii(x.s[0]) & x.s.substr(1))
@@ -326,29 +325,29 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
errorUseQualifier(c, n.info, n.sym)
of nkDotExpr:
result = nil
var m = qualifiedLookUp(c, n.sons[0], (flags*{checkUndeclared})+{checkModule})
var m = qualifiedLookUp(c, n[0], (flags*{checkUndeclared})+{checkModule})
if m != nil and m.kind == skModule:
var ident: PIdent = nil
if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n.sons[1])
if n[1].kind == nkIdent:
ident = n[1].ident
elif n[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n[1])
if ident != nil:
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n, c.config)
else:
result = strTableGet(m.tab, ident).skipAlias(n, c.config)
if result == nil and checkUndeclared in flags:
fixSpelling(n.sons[1], ident, searchInScopes)
errorUndeclaredIdentifier(c, n.sons[1].info, ident.s)
result = errorSym(c, n.sons[1])
elif n.sons[1].kind == nkSym:
result = n.sons[1].sym
fixSpelling(n[1], ident, searchInScopes)
errorUndeclaredIdentifier(c, n[1].info, ident.s)
result = errorSym(c, n[1])
elif n[1].kind == nkSym:
result = n[1].sym
elif checkUndeclared in flags and
n.sons[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n.sons[1].info, "identifier expected, but got: " &
renderTree(n.sons[1]))
result = errorSym(c, n.sons[1])
n[1].kind notin {nkOpenSymChoice, nkClosedSymChoice}:
localError(c.config, n[1].info, "identifier expected, but got: " &
renderTree(n[1]))
result = errorSym(c, n[1])
else:
result = nil
when false:
@@ -372,13 +371,13 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimDone
of nkDotExpr:
o.mode = oimOtherModule
o.m = qualifiedLookUp(c, n.sons[0], {checkUndeclared, checkModule})
o.m = qualifiedLookUp(c, n[0], {checkUndeclared, checkModule})
if o.m != nil and o.m.kind == skModule:
var ident: PIdent = nil
if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n.sons[1], n)
if n[1].kind == nkIdent:
ident = n[1].ident
elif n[1].kind == nkAccQuoted:
ident = considerQuotedIdent(c, n[1], n)
if ident != nil:
if o.m == c.module:
# a module may access its private members:
@@ -388,12 +387,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
else:
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n, c.config)
else:
noidentError(c.config, n.sons[1], n)
result = errorSym(c, n.sons[1])
noidentError(c.config, n[1], n)
result = errorSym(c, n[1])
of nkClosedSymChoice, nkOpenSymChoice:
o.mode = oimSymChoice
if n[0].kind == nkSym:
result = n.sons[0].sym
result = n[0].sym
else:
o.mode = oimDone
return nil
@@ -430,8 +429,8 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimOtherModule:
result = nextIdentIter(o.it, o.m.tab).skipAlias(n, c.config)
of oimSymChoice:
if o.symChoiceIndex < sonsLen(n):
result = n.sons[o.symChoiceIndex].sym
if o.symChoiceIndex < n.len:
result = n[o.symChoiceIndex].sym
incl(o.inSymChoice, result.id)
inc o.symChoiceIndex
elif n.kind == nkOpenSymChoice:
@@ -439,19 +438,19 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoiceLocalLookup
o.scope = c.currentScope
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
while result == nil:
o.scope = o.scope.parent
if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
of oimSymChoiceLocalLookup:
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n, c.config)
while result == nil:
o.scope = o.scope.parent
if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
n[0].sym.name, o.inSymChoice).skipAlias(n, c.config)
when false:
if result != nil and result.kind == skStub: loadStub(result)

View File

@@ -16,41 +16,48 @@ import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,
lineinfos
proc newDeref*(n: PNode): PNode {.inline.} =
result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
addSon(result, n)
result = newNodeIT(nkHiddenDeref, n.info, n.typ[0])
result.add n
proc newTupleAccess*(g: ModuleGraph; tup: PNode, i: int): PNode =
if tup.kind == nkHiddenAddr:
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}))
result.addSon(newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar}).sons[i]))
addSon(result[0], tup[0])
result = newNodeIT(nkHiddenAddr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent}))
result.add newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(abstractInst+{tyPtr, tyVar, tyLent})[i])
result[0].add tup[0]
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
lit.intVal = i
addSon(result[0], lit)
result[0].add lit
else:
result = newNodeIT(nkBracketExpr, tup.info, tup.typ.skipTypes(
abstractInst).sons[i])
addSon(result, copyTree(tup))
abstractInst)[i])
result.add copyTree(tup)
var lit = newNodeIT(nkIntLit, tup.info, getSysType(g, tup.info, tyInt))
lit.intVal = i
addSon(result, lit)
result.add lit
proc addVar*(father, v: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart.sons[0] = v
vpart.sons[1] = newNodeI(nkEmpty, v.info)
vpart.sons[2] = vpart[1]
addSon(father, vpart)
vpart[0] = v
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = vpart[1]
father.add vpart
proc addVar*(father, v, value: PNode) =
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart[0] = v
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = value
father.add vpart
proc newAsgnStmt*(le, ri: PNode): PNode =
result = newNodeI(nkAsgn, le.info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc newFastAsgnStmt*(le, ri: PNode): PNode =
result = newNodeI(nkFastAsgn, le.info, 2)
result.sons[0] = le
result.sons[1] = ri
result[0] = le
result[1] = ri
proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
assert n.kind == nkVarTuple
@@ -63,13 +70,13 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var v = newNodeI(nkVarSection, value.info)
let tempAsNode = newSymNode(temp)
v.addVar(tempAsNode)
v.addVar(tempAsNode, value)
result.add(v)
result.add newAsgnStmt(tempAsNode, value)
for i in 0 .. n.len-3:
if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
result.add newAsgnStmt(n.sons[i], newTupleAccess(g, tempAsNode, i))
for i in 0..<n.len-2:
let val = newTupleAccess(g, tempAsNode, i)
if n[i].kind == nkSym: v.addVar(n[i], val)
else: result.add newAsgnStmt(n[i], val)
proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used
@@ -89,10 +96,10 @@ proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
result = newNodeI(nkBracketExpr, tup.info)
addSon(result, copyTree(tup))
result.add copyTree(tup)
var lit = newNodeI(nkIntLit, tup.info)
lit.intVal = i
addSon(result, lit)
result.add lit
proc newTryFinally*(body, final: PNode): PNode =
result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final))
@@ -106,31 +113,31 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = newNodeI(nkEmpty, value.info)
vpart.sons[2] = value
addSon(v, vpart)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, value.info)
vpart[2] = value
v.add vpart
result.add(v)
let lhs = n.sons[0]
for i in 0 .. lhs.len-1:
result.add newAsgnStmt(lhs.sons[i], newTupleAccessRaw(tempAsNode, i))
let lhs = n[0]
for i in 0..<lhs.len:
result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i))
proc lowerSwap*(g: ModuleGraph; n: PNode; 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), owner, n.info, owner.options)
temp.typ = n.sons[1].typ
temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, n.info)
let tempAsNode = newSymNode(temp)
var vpart = newNodeI(nkIdentDefs, v.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = newNodeI(nkEmpty, v.info)
vpart.sons[2] = n[1]
addSon(v, vpart)
vpart[0] = tempAsNode
vpart[1] = newNodeI(nkEmpty, v.info)
vpart[2] = n[1]
v.add vpart
result.add(v)
result.add newFastAsgnStmt(n[1], n[2])
@@ -150,46 +157,53 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
s.typ = result
result.sym = s
template fieldCheck {.dirty.} =
when false:
if tfCheckedForDestructor in obj.flags:
echo "missed field ", field.name.s
writeStackTrace()
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
field.position = obj.n.len
obj.n.add newSymNode(field)
propagateToOwner(obj, field.typ)
fieldCheck()
proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode =
# returns a[].field as a node
assert field.kind == skField
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
addSon(deref, a)
deref.typ = a.typ.skipTypes(abstractInst)[0]
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc rawDirectAccess*(obj, field: PSym): PNode =
# returns a.field as a node
assert field.kind == skField
result = newNodeI(nkDotExpr, field.info)
addSon(result, newSymNode obj)
addSon(result, newSymNode field)
result.add newSymNode(obj)
result.add newSymNode(field)
result.typ = field.typ
proc lookupInRecord(n: PNode, id: int): PSym =
result = nil
case n.kind
of nkRecList:
for i in 0 ..< sonsLen(n):
result = lookupInRecord(n.sons[i], id)
for i in 0..<n.len:
result = lookupInRecord(n[i], id)
if result != nil: return
of nkRecCase:
if n.sons[0].kind != nkSym: return
result = lookupInRecord(n.sons[0], id)
if n[0].kind != nkSym: return
result = lookupInRecord(n[0], id)
if result != nil: return
for i in 1 ..< sonsLen(n):
case n.sons[i].kind
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = lookupInRecord(lastSon(n.sons[i]), id)
result = lookupInRecord(lastSon(n[i]), id)
if result != nil: return
else: discard
of nkSym:
@@ -206,8 +220,10 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
field.position = obj.n.len
field.flags = s.flags * {sfCursor}
obj.n.add newSymNode(field)
fieldCheck()
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.id)
@@ -219,45 +235,45 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
field.position = obj.n.len
obj.n.add newSymNode(field)
result = field
proc newDotExpr*(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info)
let field = lookupInRecord(obj.typ.n, b.id)
assert field != nil, b.name.s
addSon(result, newSymNode(obj))
addSon(result, newSymNode(field))
result.add newSymNode(obj)
result.add newSymNode(field)
result.typ = field.typ
proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode =
# returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
deref.typ = a.typ.skipTypes(abstractInst)[0]
var t = deref.typ.skipTypes(abstractInst)
var field: PSym
while true:
assert t.kind == tyObject
field = lookupInRecord(t.n, b)
if field != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
#if field == nil:
# echo "FIELD ", b
# debug deref.typ
assert field != nil
addSon(deref, a)
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode =
# returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
deref.typ = a.typ.skipTypes(abstractInst)[0]
var t = deref.typ.skipTypes(abstractInst)
var field: PSym
let bb = getIdent(cache, b)
@@ -265,17 +281,17 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): P
assert t.kind == tyObject
field = getSymFromList(t.n, bb)
if field != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
#if field == nil:
# echo "FIELD ", b
# debug deref.typ
assert field != nil
addSon(deref, a)
deref.add a
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.add deref
result.add newSymNode(field)
result.typ = field.typ
proc getFieldFromObj*(t: PType; v: PSym): PSym =
@@ -285,7 +301,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
assert t.kind == tyObject
result = lookupInRecord(t.n, v.id)
if result != nil: break
t = t.sons[0]
t = t[0]
if t == nil: break
t = t.skipTypes(skipPtrs)
@@ -296,19 +312,19 @@ proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
result = indirectAccess(newSymNode(a), b, info)
proc genAddrOf*(n: PNode): PNode =
proc genAddrOf*(n: PNode, typeKind = tyPtr): PNode =
result = newNodeI(nkAddr, n.info, 1)
result.sons[0] = n
result.typ = newType(tyPtr, n.typ.owner)
result[0] = n
result.typ = newType(typeKind, n.typ.owner)
result.typ.rawAddSon(n.typ)
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
result = newNodeIT(k, n.info,
n.typ.skipTypes(abstractInst).sons[0])
n.typ.skipTypes(abstractInst)[0])
result.add n
proc callCodegenProc*(g: ModuleGraph; name: string;
info: TLineInfo = unknownLineInfo();
info: TLineInfo = unknownLineInfo;
arg1, arg2, arg3, optionalArgs: PNode = nil): PNode =
result = newNodeI(nkCall, info)
let sym = magicsys.getCompilerProc(g, name)
@@ -320,9 +336,9 @@ proc callCodegenProc*(g: ModuleGraph; name: string;
if arg2 != nil: result.add arg2
if arg3 != nil: result.add arg3
if optionalArgs != nil:
for i in 1..optionalArgs.len-3:
for i in 1..<optionalArgs.len-2:
result.add optionalArgs[i]
result.typ = sym.typ.sons[0]
result.typ = sym.typ[0]
proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
result = nkIntLit.newIntNode(value)
@@ -330,21 +346,21 @@ proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
if skipTypes(n.typ, abstractVar).kind == tyArray:
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)))
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
else:
result = newNodeI(nkCall, n.info, 2)
result.typ = getSysType(g, n.info, tyInt)
result.sons[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
result.sons[1] = n
result[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
result[1] = n
proc genLen*(g: ModuleGraph; n: PNode): PNode =
if skipTypes(n.typ, abstractVar).kind == tyArray:
result = newIntLit(g, n.info, lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1)
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
else:
result = newNodeI(nkCall, n.info, 2)
result.typ = getSysType(g, n.info, tyInt)
result.sons[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
result.sons[1] = n
result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
result[1] = n
proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym =
result = newSym(skLet, name, owner, varSection.info, owner.options)
@@ -352,8 +368,8 @@ proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym =
result.typ = expr.typ
var varDef = newNodeI(nkIdentDefs, varSection.info, 3)
varDef.sons[0] = newSymNode(result)
varDef.sons[1] = newNodeI(nkEmpty, varSection.info)
varDef.sons[2] = expr
varDef[0] = newSymNode(result)
varDef[1] = newNodeI(nkEmpty, varSection.info)
varDef[2] = expr
varSection.add varDef

View File

@@ -40,7 +40,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy
while r != nil:
if r.magic == m:
# prefer the tyInt variant:
if r.typ.sons[0] != nil and r.typ.sons[0].kind == tyInt: return r
if r.typ[0] != nil and r.typ[0].kind == tyInt: return r
result = r
r = nextIdentIter(ti, g.systemModule.tab)
if result != nil: return result
@@ -68,7 +68,7 @@ proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType =
of tyUInt64: result = sysTypeFromName("uint64")
of tyFloat: result = sysTypeFromName("float")
of tyFloat32: result = sysTypeFromName("float32")
of tyFloat64: return sysTypeFromName("float64")
of tyFloat64: result = sysTypeFromName("float64")
of tyFloat128: result = sysTypeFromName("float128")
of tyBool: result = sysTypeFromName("bool")
of tyChar: result = sysTypeFromName("char")
@@ -79,7 +79,9 @@ proc getSysType*(g: ModuleGraph; info: TLineInfo; kind: TTypeKind): PType =
else: internalError(g.config, "request for typekind: " & $kind)
g.sysTypes[kind] = result
if result.kind != kind:
internalError(g.config, "wanted: " & $kind & " got: " & $result.kind)
if kind == tyFloat64 and result.kind == tyFloat: discard # because of aliasing
else:
internalError(g.config, "wanted: " & $kind & " got: " & $result.kind)
if result == nil: internalError(g.config, "type not found: " & $kind)
proc resetSysTypes*(g: ModuleGraph) =
@@ -123,7 +125,7 @@ proc addSonSkipIntLit*(father, son: PType) =
when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[]
let s = son.skipIntLit
add(father.sons, s)
father.sons.add(s)
propagateToOwner(father, s)
proc setIntLitType*(g: ModuleGraph; result: PNode) =

View File

@@ -18,7 +18,7 @@ import
sem, idents, passes, extccomp,
cgen, json, nversion,
platform, nimconf, passaux, depends, vm, idgen,
parser, modules,
modules,
modulegraphs, tables, rod, lineinfos, pathutils
when not defined(leanCompiler):
@@ -82,6 +82,13 @@ proc commandCompileToC(graph: ModuleGraph) =
semanticPasses(graph)
registerPass(graph, cgenPass)
if {optRun, optForceFullMake} * conf.globalOptions == {optRun} or isDefined(conf, "nimBetterRun"):
let proj = changeFileExt(conf.projectFull, "")
if not changeDetectedViaJsonBuildInstructions(conf, proj):
# nothing changed
graph.config.notes = graph.config.mainPackageNotes
return
compileProject(graph)
if graph.config.errorCounter > 0:
return # issue #9933
@@ -101,6 +108,7 @@ proc commandJsonScript(graph: ModuleGraph) =
when not defined(leanCompiler):
proc commandCompileToJS(graph: ModuleGraph) =
let conf = graph.config
conf.exc = excCpp
if conf.outDir.isEmpty:
conf.outDir = conf.projectPath
@@ -143,14 +151,6 @@ const evalPasses = [verbosePass, semPass, evalPass]
proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym) =
carryPasses(graph, nodes, module, evalPasses)
proc commandEval(graph: ModuleGraph; exp: string) =
if graph.systemModule == nil:
interactivePasses(graph)
compileSystemModule(graph)
let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
evalNim(graph, echoExp.parseString(graph.cache, graph.config),
makeStdinModule(graph))
proc commandScan(cache: IdentCache, config: ConfigRef) =
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
var stream = llStreamOpen(f, fmRead)
@@ -185,10 +185,12 @@ proc mainCommand*(graph: ModuleGraph) =
of "c", "cc", "compile", "compiletoc":
# compile means compileToC currently
conf.cmd = cmdCompileToC
if conf.exc == excNone: conf.exc = excSetjmp
defineSymbol(graph.config.symbols, "c")
commandCompileToC(graph)
of "cpp", "compiletocpp":
conf.cmd = cmdCompileToCpp
if conf.exc == excNone: conf.exc = excCpp
defineSymbol(graph.config.symbols, "cpp")
commandCompileToC(graph)
of "objc", "compiletooc":
@@ -198,7 +200,7 @@ proc mainCommand*(graph: ModuleGraph) =
of "run":
conf.cmd = cmdRun
when hasTinyCBackend:
extccomp.setCC("tcc")
extccomp.setCC(conf, "tcc", unknownLineInfo)
commandCompileToC(graph)
else:
rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc")
@@ -223,6 +225,12 @@ proc mainCommand*(graph: ModuleGraph) =
loadConfigs(DocConfig, cache, conf)
commandDoc(cache, conf)
of "doc2", "doc":
conf.setNoteDefaults(warnLockLevel, false) # issue #13218
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # issue #13218
# because currently generates lots of false positives due to conflation
# of labels links in doc comments, eg for random.rand:
# ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
# ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
@@ -231,6 +239,7 @@ proc mainCommand*(graph: ModuleGraph) =
defineSymbol(conf.symbols, "nimdoc")
commandDoc2(graph, false)
of "rst2html":
conf.setNoteDefaults(warnRedefinitionOfLabel, false) # similar to issue #13218
when defined(leanCompiler):
quit "compiler wasn't built with documentation generator"
else:
@@ -291,7 +300,9 @@ proc mainCommand*(graph: ModuleGraph) =
for s in definedSymbolNames(conf.symbols): definedSymbols.elems.add(%s)
var libpaths = newJArray()
var lazyPaths = newJArray()
for dir in conf.searchPaths: libpaths.elems.add(%dir.string)
for dir in conf.lazyPaths: lazyPaths.elems.add(%dir.string)
var hints = newJObject() # consider factoring with `listHints`
for a in hintMin..hintMax:
@@ -304,9 +315,12 @@ proc mainCommand*(graph: ModuleGraph) =
var dumpdata = %[
(key: "version", val: %VersionAsString),
(key: "prefixdir", val: %conf.getPrefixDir().string),
(key: "libpath", val: %conf.libpath.string),
(key: "project_path", val: %conf.projectFull.string),
(key: "defined_symbols", val: definedSymbols),
(key: "lib_paths", val: %libpaths),
(key: "lazyPaths", val: %lazyPaths),
(key: "outdir", val: %conf.outDir.string),
(key: "out", val: %conf.outFile.string),
(key: "nimcache", val: %getNimcacheDir(conf).string),
@@ -338,8 +352,11 @@ proc mainCommand*(graph: ModuleGraph) =
conf.cmd = cmdInteractive
commandInteractive(graph)
of "e":
incl conf.globalOptions, optWasNimscript
commandEval(graph, mainCommandArg(conf))
if not fileExists(conf.projectFull):
rawMessage(conf, errGenerated, "NimScript file does not exist: " & conf.projectFull.string)
elif not conf.projectFull.string.endsWith(".nims"):
rawMessage(conf, errGenerated, "not a NimScript file: " & conf.projectFull.string)
# main NimScript logic handled in cmdlinehelper.nim.
of "nop", "help":
# prevent the "success" message:
conf.cmd = cmdDump
@@ -351,16 +368,25 @@ proc mainCommand*(graph: ModuleGraph) =
if conf.errorCounter == 0 and
conf.cmd notin {cmdInterpret, cmdRun, cmdDump}:
when declared(system.getMaxMem):
let usedMem = formatSize(getMaxMem()) & " peakmem"
else:
let usedMem = formatSize(getTotalMem())
rawMessage(conf, hintSuccessX, [$conf.linesCompiled,
formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3),
usedMem,
if isDefined(conf, "danger"): "Dangerous Release Build"
elif isDefined(conf, "release"): "Release Build"
else: "Debug Build"])
let mem =
when declared(system.getMaxMem): formatSize(getMaxMem()) & " peakmem"
else: formatSize(getTotalMem()) & " totmem"
let loc = $conf.linesCompiled
let build = if isDefined(conf, "danger"): "Dangerous Release"
elif isDefined(conf, "release"): "Release"
else: "Debug"
let sec = formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3)
let project = if optListFullPaths in conf.globalOptions: $conf.projectFull else: $conf.projectName
var output = $conf.absOutFile
if optListFullPaths notin conf.globalOptions: output = output.AbsoluteFile.extractFilename
rawMessage(conf, hintSuccessX, [
"loc", loc,
"sec", sec,
"mem", mem,
"build", build,
"project", project,
"output", output,
])
when PrintRopeCacheStats:
echo "rope cache stats: "

View File

@@ -64,7 +64,7 @@ type
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.}
recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.}
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
cacheTables*: Table[string, BTree[string, PNode]]
passes*: seq[TPass]
@@ -72,6 +72,10 @@ type
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
globalDestructors*: seq[PNode]
proofEngine*: proc (graph: ModuleGraph; assumptions: seq[PNode]; toProve: PNode): (bool, string) {.nimcall.}
requirementsCheck*: proc (graph: ModuleGraph; assumptions: seq[PNode];
call, requirement: PNode): (bool, string) {.nimcall.}
compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.}
TPassContext* = object of RootObj # the pass's context
PPassContext* = ref TPassContext
@@ -98,7 +102,7 @@ const
proc toBase64a(s: cstring, len: int): string =
## encodes `s` into base64 representation.
result = newStringOfCap(((len + 2) div 3) * 4)
result.add '_'
result.add "__"
var i = 0
while i < len - 2:
let a = ord(s[i])
@@ -163,8 +167,9 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
result = g.doStopCompile != nil and g.doStopCompile()
proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo(), {})
result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo, {})
result.magic = m
result.flags = {sfNeverRaises}
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph()
@@ -215,7 +220,7 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
if g.suggestMode:
g.deps.incl m.position.dependsOn(dep.int)
# we compute the transitive closure later when quering the graph lazily.
# we compute the transitive closure later when querying the graph lazily.
# this improves efficiency quite a lot:
#invalidTransitiveClosure = true

View File

@@ -139,7 +139,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
result.add modname
of nkPrefix:
when false:
if n.sons[0].kind == nkIdent and n.sons[0].ident.s == "$":
if n[0].kind == nkIdent and n[0].ident.s == "$":
result = lookupPackage(n[1], nil)
else:
discard
@@ -149,7 +149,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths is deprecated")
result = renderTree(n, {renderNoComments}).replace(".", "/")
of nkImportAs:
result = getModuleName(conf, n.sons[0])
result = getModuleName(conf, n[0])
else:
localError(conf, n.info, "invalid module name: '$1'" % n.renderTree)
result = ""

View File

@@ -39,7 +39,8 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
# but starting with version 0.20 we now produce a fake Nimble package instead
# to resolve the conflicts:
let pck3 = fakePackageName(graph.config, filename)
packSym = newSym(skPackage, getIdent(graph.cache, pck3), nil, result.info)
# this makes the new `packSym`'s owner be the original `packSym`
packSym = newSym(skPackage, getIdent(graph.cache, pck3), packSym, result.info)
initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym)
@@ -50,22 +51,19 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
setLen(graph.modules, int(fileIdx) + 1)
graph.modules[result.position] = result
incl(result.flags, sfUsed)
initStrTable(result.tab)
strTableAdd(result.tab, result) # a module knows itself
strTableAdd(packSym.tab, result)
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.
new(result)
result.id = -1 # for better error checking
result.kind = skModule
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
result.name = getIdent(graph.cache, splitFile(filename).name)
result = PSym(kind: skModule, id: -1, # for better error checking
name: getIdent(graph.cache, splitFile(filename).name),
info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s):
rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
result.info = newLineInfo(fileIdx, 1, 1)
partialInitModule(result, graph, fileIdx, filename)
proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): PSym =
@@ -94,7 +92,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
graph.markClientsDirty(fileIdx)
proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym {.procvar.} =
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, {})
@@ -109,7 +107,7 @@ proc importModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PSym {.proc
if s.owner.id == graph.config.mainPackageId or isDefined(graph.config, "booting"): graph.config.mainPackageNotes
else: graph.config.foreignPackageNotes
proc includeModule*(graph: ModuleGraph; s: PSym, fileIdx: FileIndex): PNode {.procvar.} =
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)

View File

@@ -26,13 +26,13 @@ proc makeCString*(s: string): Rope =
const MaxLineLength = 64
result = nil
var res = newStringOfCap(int(s.len.toFloat * 1.1) + 1)
add(res, "\"")
for i in 0 ..< len(s):
res.add("\"")
for i in 0..<s.len:
if (i + 1) mod MaxLineLength == 0:
add(res, "\"\L\"")
res.add("\"\L\"")
toCChar(s[i], res)
add(res, '\"')
add(result, rope(res))
res.add('\"')
result.add(rope(res))
proc newFileInfo(fullPath: AbsoluteFile, projPath: RelativeFile): TFileInfo =
@@ -81,6 +81,7 @@ proc fileInfoIdx*(conf: ConfigRef; filename: AbsoluteFile; isKnownFile: var bool
pseudoPath = true
if conf.m.filenameToIndexTbl.hasKey(canon.string):
isKnownFile = true
result = conf.m.filenameToIndexTbl[canon.string]
else:
isKnownFile = false
@@ -152,27 +153,32 @@ proc pushInfoContext*(conf: ConfigRef; info: TLineInfo; detail: string = "") =
conf.m.msgContext.add((info, detail))
proc popInfoContext*(conf: ConfigRef) =
setLen(conf.m.msgContext, len(conf.m.msgContext) - 1)
setLen(conf.m.msgContext, conf.m.msgContext.len - 1)
proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
let L = conf.m.msgContext.len
let i = if index < 0: L + index else: index
if i >=% L: result = unknownLineInfo()
let i = if index < 0: conf.m.msgContext.len + index else: index
if i >=% conf.m.msgContext.len: result = unknownLineInfo
else: result = conf.m.msgContext[i].info
const
commandLineDesc = "command line"
template toFilename*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil:
"???"
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
else:
conf.m.fileInfos[fileIdx.int32].shortName
proc toProjPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: "???"
if fileIdx.int32 < 0 or conf == nil:
(if fileIdx == commandLineIdx: commandLineDesc else: "???")
else: conf.m.fileInfos[fileIdx.int32].projPath.string
proc toFullPath*(conf: ConfigRef; fileIdx: FileIndex): string =
if fileIdx.int32 < 0 or conf == nil: result = "???"
else: result = conf.m.fileInfos[fileIdx.int32].fullPath.string
if fileIdx.int32 < 0 or conf == nil:
result = (if fileIdx == commandLineIdx: commandLineDesc else: "???")
else:
result = conf.m.fileInfos[fileIdx.int32].fullPath.string
proc setDirtyFile*(conf: ConfigRef; fileIdx: FileIndex; filename: AbsoluteFile) =
assert fileIdx.int32 >= 0
@@ -189,7 +195,7 @@ proc getHash*(conf: ConfigRef; fileIdx: FileIndex): string =
proc toFullPathConsiderDirty*(conf: ConfigRef; fileIdx: FileIndex): AbsoluteFile =
if fileIdx.int32 < 0:
result = AbsoluteFile"???"
result = AbsoluteFile(if fileIdx == commandLineIdx: commandLineDesc else: "???")
elif not conf.m.fileInfos[fileIdx.int32].dirtyFile.isEmpty:
result = conf.m.fileInfos[fileIdx.int32].dirtyFile
else:
@@ -327,14 +333,14 @@ proc getMessageStr(msg: TMsgKind, arg: string): string =
type
TErrorHandling = enum doNothing, doAbort, doRaise
proc log*(s: string) {.procvar.} =
proc log*(s: string) =
var f: File
if open(f, getHomeDir() / "nimsuggest.log", fmAppend):
f.writeLine(s)
close(f)
proc quit(conf: ConfigRef; msg: TMsgKind) {.gcsafe.} =
if defined(debug) or msg == errInternal or hintStackTrace in conf.notes:
if defined(debug) or msg == errInternal or conf.hasHint(hintStackTrace):
{.gcsafe.}:
if stackTraceAvailable() and isNil(conf.writelnHook):
writeStackTrace()
@@ -368,7 +374,7 @@ proc writeContext(conf: ConfigRef; lastinfo: TLineInfo) =
const instantiationFrom = "template/generic instantiation from here"
const instantiationOfFrom = "template/generic instantiation of `$1` from here"
var info = lastinfo
for i in 0 ..< len(conf.m.msgContext):
for i in 0..<conf.m.msgContext.len:
let context = conf.m.msgContext[i]
if context.info != lastinfo and context.info != info:
if conf.structuredErrorHook != nil:
@@ -399,22 +405,20 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
case msg
of errMin..errMax:
sev = Severity.Error
writeContext(conf, unknownLineInfo())
writeContext(conf, unknownLineInfo)
title = ErrorTitle
color = ErrorColor
of warnMin..warnMax:
sev = Severity.Warning
if optWarns notin conf.options: return
if msg notin conf.notes: return
writeContext(conf, unknownLineInfo())
if not conf.hasWarn(msg): return
writeContext(conf, unknownLineInfo)
title = WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
if optHints notin conf.options: return
if msg notin conf.notes: return
if not conf.hasHint(msg): return
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
@@ -422,7 +426,7 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
let s = msgKindToString(msg) % args
if conf.structuredErrorHook != nil:
conf.structuredErrorHook(conf, unknownLineInfo(),
conf.structuredErrorHook(conf, unknownLineInfo,
s & (if kind.len > 0: KindFormat % kind else: ""), sev)
if not ignoreMsgBecauseOfIdeTools(conf, msg):
@@ -494,7 +498,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
conf.m.lastError = info
of warnMin..warnMax:
sev = Severity.Warning
ignoreMsg = optWarns notin conf.options or msg notin conf.notes
ignoreMsg = not conf.hasWarn(msg)
if not ignoreMsg: writeContext(conf, info)
title = WarningTitle
color = WarningColor
@@ -502,7 +506,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
inc(conf.warnCounter)
of hintMin..hintMax:
sev = Severity.Hint
ignoreMsg = optHints notin conf.options or msg notin conf.notes
ignoreMsg = not conf.hasHint(msg)
title = HintTitle
color = HintColor
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
@@ -520,7 +524,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
KindColor, `%`(KindFormat, kind))
else:
styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s)
if hintSource in conf.notes:
if conf.hasHint(hintSource):
conf.writeSurroundingSrc(info)
handleError(conf, msg, eh, s)
@@ -555,7 +559,7 @@ proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
proc internalError*(conf: ConfigRef; errMsg: string) =
if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
writeContext(conf, unknownLineInfo())
writeContext(conf, unknownLineInfo)
rawMessage(conf, errInternal, errMsg)
template assertNotNil*(conf: ConfigRef; e): untyped =

View File

@@ -17,6 +17,8 @@ type
enabled: bool
f: File
buf: string
filename: AbsoluteFile
syms: seq[PSym]
proc doWrite(f: var NdiFile; s: PSym; conf: ConfigRef) =
f.buf.setLen 0
@@ -28,13 +30,20 @@ proc doWrite(f: var NdiFile; s: PSym; conf: ConfigRef) =
f.f.writeLine("\t", toFullPath(conf, s.info), "\t", f.buf)
template writeMangledName*(f: NdiFile; s: PSym; conf: ConfigRef) =
if f.enabled: doWrite(f, s, conf)
if f.enabled: f.syms.add s
proc open*(f: var NdiFile; filename: AbsoluteFile; conf: ConfigRef) =
f.enabled = not filename.isEmpty
if f.enabled:
f.f = open(filename.string, fmWrite, 8000)
f.filename = filename
f.buf = newStringOfCap(20)
proc close*(f: var NdiFile) =
if f.enabled: close(f.f)
proc close*(f: var NdiFile, conf: ConfigRef) =
if f.enabled:
f.f = open(f.filename.string, fmWrite, 8000)
doAssert f.f != nil, f.filename.string
for s in f.syms:
doWrite(f, s, conf)
close(f.f)
f.syms.reset
f.filename.reset

View File

@@ -7,12 +7,13 @@ define:nimcore
#define:nimIncremental
#import:"$projectpath/testability"
#define:staticSqlite
@if windows:
cincludes: "$lib/wrappers/libffi/common"
@end
define:useStdoutAsStdmsg
define:nimOldCaseObjects
@if nimHasStyleChecks:
styleCheck:error
@@ -20,7 +21,3 @@ define:nimOldCaseObjects
#define:useNodeIds
#gc:markAndSweep
@if nimHasWarningCaseTransition:
warning[CaseTransition]:off
@end

View File

@@ -40,20 +40,40 @@ proc prependCurDir(f: AbsoluteFile): AbsoluteFile =
else:
result = f
proc addCmdPrefix*(result: var string, kind: CmdLineKind) =
# consider moving this to std/parseopt
case kind
of cmdLongOption: result.add "--"
of cmdShortOption: result.add "-"
of cmdArgument, cmdEnd: discard
proc processCmdLine(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
config.commandLine.setLen 0
# bugfix: otherwise, config.commandLine ends up duplicated
while true:
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongOption, cmdShortOption:
config.commandLine.add " "
config.commandLine.addCmdPrefix p.kind
config.commandLine.add p.key.quoteShell # quoteShell to be future proof
if p.val.len > 0:
config.commandLine.add ':'
config.commandLine.add p.val.quoteShell
if p.key == " ":
p.key = "-"
if processArgument(pass, p, argsCount, config): break
else:
processSwitch(pass, p, config)
of cmdArgument:
config.commandLine.add " "
config.commandLine.add p.key.quoteShell
if processArgument(pass, p, argsCount, config): break
if pass == passCmd2:
if {optRun, optWasNimscript} * config.globalOptions == {} and
@@ -73,12 +93,12 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) =
self.processCmdLineAndProjectPath(conf)
if not self.loadConfigsAndRunMainCommand(cache, conf): return
if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics())
if conf.hasHint(hintGCStats): echo(GC_getStatistics())
#echo(GC_getStatistics())
if conf.errorCounter != 0: return
when hasTinyCBackend:
if conf.cmd == cmdRun:
tccgen.run(conf.arguments)
tccgen.run(conf, conf.arguments)
if optRun in conf.globalOptions:
var ex = quoteShell conf.absOutFile
if conf.cmd == cmdCompileToJS:

View File

@@ -48,7 +48,7 @@ proc `<`*(ver: Version, ver2: Version): bool =
# Handling for normal versions such as "0.1.0" or "1.0".
var sVer = string(ver).split('.')
var sVer2 = string(ver2).split('.')
for i in 0..max(sVer.len, sVer2.len)-1:
for i in 0..<max(sVer.len, sVer2.len):
var sVerI = 0
if i < sVer.len:
discard parseInt(sVer[i], sVerI)
@@ -69,9 +69,10 @@ proc getPathVersion*(p: string): tuple[name, version: string] =
result.version = ""
const specialSeparator = "-#"
var sepIdx = p.find(specialSeparator)
let last = p.rfind(p.lastPathPart) # the index where the last path part begins
var sepIdx = p.find(specialSeparator, start = last)
if sepIdx == -1:
sepIdx = p.rfind('-')
sepIdx = p.rfind('-', start = last)
if sepIdx == -1:
result.name = p
@@ -82,7 +83,7 @@ proc getPathVersion*(p: string): tuple[name, version: string] =
result.name = p
return
result.name = p[0 .. sepIdx - 1]
result.name = p[0..sepIdx - 1]
result.version = p.substr(sepIdx + 1)
proc addPackage(conf: ConfigRef; packages: StringTableRef, p: string; info: TLineInfo) =
@@ -129,6 +130,10 @@ proc addPathRec(conf: ConfigRef; dir: string, info: TLineInfo) =
proc nimblePath*(conf: ConfigRef; path: AbsoluteDir, info: TLineInfo) =
addPathRec(conf, path.string, info)
addNimblePath(conf, path.string, info)
let i = conf.nimblePaths.find(path)
if i != -1:
conf.nimblePaths.delete(i)
conf.nimblePaths.insert(path, 0)
when isMainModule:
proc v(s: string): Version = s.newVersion
@@ -142,16 +147,16 @@ when isMainModule:
let conf = newConfigRef()
var rr = newStringTable()
addPackage conf, rr, "irc-#a111", unknownLineInfo()
addPackage conf, rr, "irc-#head", unknownLineInfo()
addPackage conf, rr, "irc-0.1.0", unknownLineInfo()
#addPackage conf, rr, "irc", unknownLineInfo()
#addPackage conf, rr, "another", unknownLineInfo()
addPackage conf, rr, "another-0.1", unknownLineInfo()
addPackage conf, rr, "irc-#a111", unknownLineInfo
addPackage conf, rr, "irc-#head", unknownLineInfo
addPackage conf, rr, "irc-0.1.0", unknownLineInfo
#addPackage conf, rr, "irc", unknownLineInfo
#addPackage conf, rr, "another", unknownLineInfo
addPackage conf, rr, "another-0.1", unknownLineInfo
addPackage conf, rr, "ab-0.1.3", unknownLineInfo()
addPackage conf, rr, "ab-0.1", unknownLineInfo()
addPackage conf, rr, "justone-1.0", unknownLineInfo()
addPackage conf, rr, "ab-0.1.3", unknownLineInfo
addPackage conf, rr, "ab-0.1", unknownLineInfo
addPackage conf, rr, "justone-1.0", unknownLineInfo
doAssert toSeq(rr.chosen) ==
@["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]

View File

@@ -11,7 +11,7 @@
import
llstream, commands, os, strutils, msgs, lexer,
options, idents, wordrecg, strtabs, lineinfos, pathutils
options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig
# ---------------- configuration file parser -----------------------------
# we use Nim's scanner here to save space and work
@@ -114,7 +114,7 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack
ppGetTok(L, tok) # skip @
case whichKeyword(tok.ident)
of wIf:
setLen(condStack, len(condStack) + 1)
setLen(condStack, condStack.len + 1)
let res = evalppIf(L, tok, config)
condStack[high(condStack)] = res
if not res: jumpToDirective(L, tok, jdElseEndif, config, condStack)
@@ -160,40 +160,47 @@ proc checkSymbol(L: TLexer, tok: TToken) =
proc parseAssignment(L: var TLexer, tok: var TToken;
config: ConfigRef; condStack: var seq[bool]) =
if tok.ident.s == "-" or tok.ident.s == "--":
confTok(L, tok, config, condStack) # skip unnecessary prefix
if tok.ident != nil:
if tok.ident.s == "-" or tok.ident.s == "--":
confTok(L, tok, config, condStack) # skip unnecessary prefix
var info = getLineInfo(L, tok) # save for later in case of an error
checkSymbol(L, tok)
var s = $tok
confTok(L, tok, config, condStack) # skip symbol
var val = ""
while tok.tokType == tkDot:
add(s, '.')
s.add('.')
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(s, $tok)
s.add($tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketLe:
# BUGFIX: val, not s!
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, '[')
add(val, $tok)
val.add('[')
val.add($tok)
confTok(L, tok, config, condStack)
if tok.tokType == tkBracketRi: confTok(L, tok, config, condStack)
else: lexMessage(L, errGenerated, "expected closing ']'")
add(val, ']')
val.add(']')
let percent = tok.ident != nil and tok.ident.s == "%="
if tok.tokType in {tkColon, tkEquals} or percent:
if len(val) > 0: add(val, ':')
if val.len > 0: val.add(':')
confTok(L, tok, config, condStack) # skip ':' or '=' or '%'
checkSymbol(L, tok)
add(val, $tok)
val.add($tok)
confTok(L, tok, config, condStack) # skip symbol
if tok.tokType in {tkColon, tkEquals}:
val.add($tok) # add the :
confTok(L, tok, config, condStack) # skip symbol
checkSymbol(L, tok)
val.add($tok) # add the token after it
confTok(L, tok, config, condStack) # skip symbol
while tok.ident != nil and tok.ident.s == "&":
confTok(L, tok, config, condStack)
checkSymbol(L, tok)
add(val, $tok)
val.add($tok)
confTok(L, tok, config, condStack)
if percent:
processSwitch(s, strtabs.`%`(val, config.configVars,
@@ -201,7 +208,7 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
else:
processSwitch(s, val, passPP, info, config)
proc readConfigFile(filename: AbsoluteFile; cache: IdentCache;
proc readConfigFile*(filename: AbsoluteFile; cache: IdentCache;
config: ConfigRef): bool =
var
L: TLexer
@@ -215,7 +222,7 @@ proc readConfigFile(filename: AbsoluteFile; cache: IdentCache;
var condStack: seq[bool] = @[]
confTok(L, tok, config, condStack) # read in the first token
while tok.tokType != tkEof: parseAssignment(L, tok, config, condStack)
if len(condStack) > 0: lexMessage(L, errGenerated, "expected @end")
if condStack.len > 0: lexMessage(L, errGenerated, "expected @end")
closeLexer(L)
return true
@@ -239,19 +246,34 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
template readConfigFile(path) =
let configPath = path
if readConfigFile(configPath, cache, conf):
add(configFiles, configPath)
configFiles.add(configPath)
template runNimScriptIfExists(path: AbsoluteFile) =
let p = path # eval once
if fileExists(p):
configFiles.add(p)
runNimScript(cache, p, freshDefines = false, conf)
if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg))
if cfg == DefaultConfig:
runNimScriptIfExists(getSystemConfigPath(conf, DefaultConfigNims))
if optSkipUserConfigFile notin conf.globalOptions:
readConfigFile(getUserConfigPath(cfg))
if cfg == DefaultConfig:
runNimScriptIfExists(getUserConfigPath(DefaultConfigNims))
let pd = if not conf.projectPath.isEmpty: conf.projectPath else: AbsoluteDir(getCurrentDir())
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(pd.string, fromRoot=true, inclusive=false):
readConfigFile(AbsoluteDir(dir) / cfg)
if cfg == DefaultConfig:
runNimScriptIfExists(AbsoluteDir(dir) / DefaultConfigNims)
if optSkipProjConfigFile notin conf.globalOptions:
readConfigFile(pd / cfg)
@@ -262,6 +284,20 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
projectConfig = changeFileExt(conf.projectFull, "nim.cfg")
readConfigFile(projectConfig)
if cfg == DefaultConfig:
runNimScriptIfExists(pd / DefaultConfigNims)
for filename in configFiles:
# delayed to here so that `hintConf` is honored
rawMessage(conf, hintConf, filename.string)
block:
let scriptFile = conf.projectFull.changeFileExt("nims")
if conf.command != "nimsuggest":
runNimScriptIfExists(scriptFile)
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile)
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard

View File

@@ -46,7 +46,7 @@ proc selectUniqueSymbol*(i: Interpreter; name: string;
s = nextIdentIter(it, i.mainModule.tab)
proc selectRoutine*(i: Interpreter; name: string): PSym =
## Selects a declared rountine (proc/func/etc) from the main module.
## Selects a declared routine (proc/func/etc) from the main module.
## The routine needs to have the export marker ``*``. The only matching
## routine is returned and ``nil`` if it is overloaded.
result = selectUniqueSymbol(i, name, {skTemplate, skMacro, skFunc,

View File

@@ -98,7 +98,7 @@ proc handleCmdLine(config: ConfigRef) =
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig, config) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
# command line can overwrite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "", config)
mainCommand()

View File

@@ -157,7 +157,7 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
result = ""
var i = L.lineStart
while not (L.buf[i] in {CR, LF, EndOfFile}):
add(result, L.buf[i])
result.add(L.buf[i])
inc(i)
result.add("\n")
if marker:

View File

@@ -17,13 +17,13 @@ proc inSet*(s: PNode, elem: PNode): bool =
if s.kind != nkCurly:
#internalError(s.info, "inSet")
return false
for i in 0 ..< sonsLen(s):
if s.sons[i].kind == nkRange:
if leValue(s.sons[i].sons[0], elem) and
leValue(elem, s.sons[i].sons[1]):
for i in 0..<s.len:
if s[i].kind == nkRange:
if leValue(s[i][0], elem) and
leValue(elem, s[i][1]):
return true
else:
if sameValue(s.sons[i], elem):
if sameValue(s[i], elem):
return true
result = false
@@ -31,13 +31,13 @@ proc overlap*(a, b: PNode): bool =
if a.kind == nkRange:
if b.kind == nkRange:
# X..Y and C..D overlap iff (X <= D and C <= Y)
result = leValue(a.sons[0], b.sons[1]) and
leValue(b.sons[0], a.sons[1])
result = leValue(a[0], b[1]) and
leValue(b[0], a[1])
else:
result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
result = leValue(a[0], b) and leValue(b, a[1])
else:
if b.kind == nkRange:
result = leValue(b.sons[0], a) and leValue(a, b.sons[1])
result = leValue(b[0], a) and leValue(a, b[1])
else:
result = sameValue(a, b)
@@ -47,61 +47,61 @@ proc someInSet*(s: PNode, a, b: PNode): bool =
if s.kind != nkCurly:
#internalError(s.info, "SomeInSet")
return false
for i in 0 ..< sonsLen(s):
if s.sons[i].kind == nkRange:
if leValue(s.sons[i].sons[0], b) and leValue(b, s.sons[i].sons[1]) or
leValue(s.sons[i].sons[0], a) and leValue(a, s.sons[i].sons[1]):
for i in 0..<s.len:
if s[i].kind == nkRange:
if leValue(s[i][0], b) and leValue(b, s[i][1]) or
leValue(s[i][0], a) and leValue(a, s[i][1]):
return true
else:
# a <= elem <= b
if leValue(a, s.sons[i]) and leValue(s.sons[i], b):
if leValue(a, s[i]) and leValue(s[i], b):
return true
result = false
proc toBitSet*(conf: ConfigRef; s: PNode, b: var TBitSet) =
var first, j: BiggestInt
first = firstOrd(conf, s.typ.sons[0])
var first, j: Int128
first = firstOrd(conf, s.typ[0])
bitSetInit(b, int(getSize(conf, s.typ)))
for i in 0 ..< sonsLen(s):
if s.sons[i].kind == nkRange:
j = getOrdValue(s.sons[i].sons[0], first)
while j <= getOrdValue(s.sons[i].sons[1], first):
bitSetIncl(b, j - first)
for i in 0..<s.len:
if s[i].kind == nkRange:
j = getOrdValue(s[i][0], first)
while j <= getOrdValue(s[i][1], first):
bitSetIncl(b, toInt64(j - first))
inc(j)
else:
bitSetIncl(b, getOrdValue(s.sons[i], first) - first)
bitSetIncl(b, toInt64(getOrdValue(s[i]) - first))
proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): PNode =
var
a, b, e, first: BiggestInt # a, b are interval borders
elemType: PType
n: PNode
elemType = settype.sons[0]
first = firstOrd(conf, elemType)
elemType = settype[0]
first = firstOrd(conf, elemType).toInt64
result = newNodeI(nkCurly, info)
result.typ = settype
result.info = info
e = 0
while e < len(s) * ElemSize:
while e < s.len * ElemSize:
if bitSetIn(s, e):
a = e
b = e
while true:
inc(b)
if (b >= len(s) * ElemSize) or not bitSetIn(s, b): break
if (b >= s.len * ElemSize) or not bitSetIn(s, b): break
dec(b)
let aa = newIntTypeNode(nkIntLit, a + first, elemType)
let aa = newIntTypeNode(a + first, elemType)
aa.info = info
if a == b:
addSon(result, aa)
result.add aa
else:
n = newNodeI(nkRange, info)
n.typ = elemType
addSon(n, aa)
let bb = newIntTypeNode(nkIntLit, b + first, elemType)
n.add aa
let bb = newIntTypeNode(b + first, elemType)
bb.info = info
addSon(n, bb)
addSon(result, n)
n.add bb
result.add n
e = b
inc(e)
@@ -132,7 +132,7 @@ proc equalSets*(conf: ConfigRef; a, b: PNode): bool =
proc complement*(conf: ConfigRef; a: PNode): PNode =
var x: TBitSet
toBitSet(conf, a, x)
for i in 0 .. high(x): x[i] = not x[i]
for i in 0..high(x): x[i] = not x[i]
result = toTreeSet(conf, x, a.typ, a.info)
proc deduplicate*(conf: ConfigRef; a: PNode): PNode =
@@ -149,8 +149,8 @@ proc setHasRange*(s: PNode): bool =
assert s.kind == nkCurly
if s.kind != nkCurly:
return false
for i in 0 ..< sonsLen(s):
if s.sons[i].kind == nkRange:
for i in 0..<s.len:
if s[i].kind == nkRange:
return true
result = false

View File

@@ -15,6 +15,6 @@ const
VersionAsString* = system.NimVersion
RodFileVersion* = "1223" # modify this if the rod-format changes!
NimCompilerApiVersion* = 3 ## Check for the existance of this before accessing it
NimCompilerApiVersion* = 3 ## Check for the existence of this before accessing it
## as older versions of the compiler API do not
## declare this.

View File

@@ -19,18 +19,19 @@ const
useEffectSystem* = true
useWriteTracking* = false
hasFFI* = defined(nimHasLibFFI)
copyrightYear* = "2019"
copyrightYear* = "2020"
type # please make sure we have under 32 options
# (improves code efficiency a lot!)
TOption* = enum # **keep binary compatible**
optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
optOverflowCheck, optNilCheck, optRefCheck,
optNaNCheck, optInfCheck, optStyleCheck,
optNaNCheck, optInfCheck, optStaticBoundsCheck, optStyleCheck,
optAssert, optLineDir, optWarns, optHints,
optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
optOptimizeSpeed, optOptimizeSize,
optStackTrace, # stack tracing support
optStackTraceMsgs, # enable custom runtime msgs via `setFrameMsg`
optLineTrace, # line tracing support (includes stack tracing)
optEndb, # embedded debugger
optByRef, # use pass by ref for objects
# (for interfacing with C)
optProfiler, # profiler turned on
@@ -40,7 +41,9 @@ type # please make sure we have under 32 options
optMemTracker,
optLaxStrings,
optNilSeqs,
optOldAst
optOldAst,
optSinkInference # 'sink T' inference
TOptions* = set[TOption]
TGlobalOption* = enum # **keep binary compatible**
@@ -72,7 +75,6 @@ type # please make sure we have under 32 options
# also: generate header file
optIdeDebug # idetools: debug mode
optIdeTerse # idetools: use terse descriptions
optNoCppExceptions # use C exception handling even with CPP
optExcessiveStackTrace # fully qualified module filenames
optShowAllMismatches # show all overloading resolution candidates
optWholeProject # for 'doc2': output any dependency
@@ -82,8 +84,18 @@ type # please make sure we have under 32 options
optNoNimblePath
optHotCodeReloading
optDynlibOverrideAll
optNimV2
optSeqDestructors # active if the implementation uses the new
# string/seq implementation based on destructors
optTinyRtti # active if we use the new "tiny RTTI"
# implementation
optOwnedRefs # active if the Nim compiler knows about 'owned'.
optMultiMethods
optNimV019
optBenchmarkVM # Enables cpuTime() in the VM
optProduceAsm # produce assembler code
optPanics # turn panics (sysFatal) into a process termination
optNimV1Emulation # emulate Nim v1.0
optSourcemap
TGlobalOptions* = set[TGlobalOption]
@@ -110,14 +122,15 @@ type
cmdJsonScript # compile a .json build file
TStringSeq* = seq[string]
TGCMode* = enum # the selected GC
gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcDestructors,
gcUnselected, gcNone, gcBoehm, gcRegions, gcMarkAndSweep, gcArc, gcOrc,
gcHooks,
gcRefc, gcV2, gcGo
# gcRefc and the GCs that follow it use a write barrier,
# as far as usesWriteBarrier() is concerned
IdeCmd* = enum
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
ideHighlight, ideOutline, ideKnown, ideMsg
ideHighlight, ideOutline, ideKnown, ideMsg, ideProject
Feature* = enum ## experimental features; DO NOT RENAME THESE!
implicitDeref,
@@ -138,8 +151,12 @@ type
LegacyFeature* = enum
allowSemcheckedAstModification,
## Allows to modify a NimNode where the type has already been
## flaged with nfSem. If you actually do this, it will cause
## flagged with nfSem. If you actually do this, it will cause
## bugs.
checkUnsignedConversions
## Historically and especially in version 1.0.0 of the language
## conversions to unsigned numbers were checked. In 1.0.4 they
## are not anymore.
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf
@@ -148,6 +165,13 @@ type
ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccLcc, ccBcc, ccDmc, ccWcc, ccVcc,
ccTcc, ccPcc, ccUcc, ccIcl, ccIcc, ccClangCl
ExceptionSystem* = enum
excNone, # no exception system selected yet
excSetjmp, # setjmp based exception handling
excCpp, # use C++'s native exception handling
excGoto, # exception handling based on goto (should become the new default for C)
excQuirky # quirky exception handling
CfileFlag* {.pure.} = enum
Cached, ## no need to recompile this time
External ## file was introduced via .compile pragma
@@ -183,7 +207,7 @@ type
## the incremental compilation mechanisms
## (+) means "part of the dependency"
target*: Target # (+)
linesCompiled*: int # all lines that have been compiled
linesCompiled*: int # all lines that have been compiled
options*: TOptions # (+)
globalOptions*: TGlobalOptions # (+)
macrosToExpand*: StringTableRef
@@ -193,6 +217,7 @@ type
exitcode*: int8
cmd*: TCommands # the command
selectedGC*: TGCMode # the selected GC (+)
exc*: ExceptionSystem
verbosity*: int # how verbose the compiler is
numberOfProcessors*: int # number of processors
evalExpr*: string # expression for idetools --eval
@@ -208,27 +233,29 @@ type
ideCmd*: IdeCmd
oldNewlines*: bool
cCompiler*: TSystemCC
enableNotes*: TNoteKinds
disableNotes*: TNoteKinds
modifiedyNotes*: TNoteKinds # notes that have been set/unset from either cmdline/configs
cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline
foreignPackageNotes*: TNoteKinds
notes*: TNoteKinds
notes*: TNoteKinds # notes after resolving all logic(defaults, verbosity)/cmdline/configs
mainPackageNotes*: TNoteKinds
mainPackageId*: int
errorCounter*: int
hintCounter*: int
warnCounter*: int
errorMax*: int
maxLoopIterationsVM*: int ## VM: max iterations of all loops
configVars*: StringTableRef
symbols*: StringTableRef ## We need to use a StringTableRef here as defined
## symbols are always guaranteed to be style
## insensitive. Otherwise hell would break lose.
packageCache*: StringTableRef
nimblePaths*: seq[AbsoluteDir]
searchPaths*: seq[AbsoluteDir]
lazyPaths*: seq[AbsoluteDir]
outFile*: RelativeFile
outDir*: AbsoluteDir
prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
dllOverrides, moduleOverrides*: StringTableRef
dllOverrides, moduleOverrides*, cfileSpecificOptions*: StringTableRef
projectName*: string # holds a name like 'nim'
projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
projectFull*: AbsoluteFile # projectPath/projectName
@@ -236,11 +263,14 @@ type
projectMainIdx*: FileIndex # the canonical path id of the main module
command*: string # the main command (e.g. cc, check, scan, etc)
commandArgs*: seq[string] # any arguments after the main command
commandLine*: string
extraCmds*: seq[string] # for writeJsonBuildInstructions
keepComments*: bool # whether the parser needs to keep comments
implicitImports*: seq[string] # modules that are to be implicitly imported
implicitIncludes*: seq[string] # modules that are to be implicitly included
docSeeSrcUrl*: string # if empty, no seeSrc will be generated. \
# The string uses the formatting variables `path` and `line`.
docRoot*: string ## see nim --fullhelp for --docRoot
# the used compiler
cIncludes*: seq[AbsoluteDir] # directories to search for included files
@@ -264,6 +294,24 @@ type
severity: Severity) {.closure, gcsafe.}
cppCustomNamespace*: string
proc setNoteDefaults*(conf: ConfigRef, note: TNoteKind, enabled = true) =
template fun(op) =
conf.notes.op note
conf.mainPackageNotes.op note
conf.foreignPackageNotes.op note
if enabled: fun(incl) else: fun(excl)
proc setNote*(conf: ConfigRef, note: TNoteKind, enabled = true) =
# see also `prepareConfigNotes` which sets notes
if note notin conf.cmdlineNotes:
if enabled: incl(conf.notes, note) else: excl(conf.notes, note)
proc hasHint*(conf: ConfigRef, note: TNoteKind): bool =
optHints in conf.options and note in conf.notes
proc hasWarn*(conf: ConfigRef, note: TNoteKind): bool =
optWarns in conf.options and note in conf.notes
proc hcrOn*(conf: ConfigRef): bool = return optHotCodeReloading in conf.globalOptions
template depConfigFields*(fn) {.dirty.} =
@@ -277,12 +325,12 @@ const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, par
const
ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
optStyleCheck, optRefCheck}
optStyleCheck}
DefaultOptions* = {optObjCheck, optFieldCheck, optRangeCheck,
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
optHints, optStackTrace, optLineTrace,
optTrMacros, optNilCheck, optStyleCheck}
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
optTrMacros, optNilCheck, optStyleCheck, optSinkInference}
DefaultGlobalOptions* = {optThreadAnalysis,
optExcessiveStackTrace, optListFullPaths}
@@ -335,6 +383,7 @@ proc newConfigRef*(): ConfigRef =
libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
dllOverrides: newStringTable(modeCaseInsensitive),
moduleOverrides: newStringTable(modeStyleInsensitive),
cfileSpecificOptions: newStringTable(modeCaseSensitive),
projectName: "", # holds a name like 'nim'
projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
projectFull: AbsoluteFile"", # projectPath/projectName
@@ -342,6 +391,7 @@ proc newConfigRef*(): ConfigRef =
projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
command: "", # the main command (e.g. cc, check, scan, etc)
commandArgs: @[], # any arguments after the main command
commandLine: "",
keepComments: true, # whether the parser needs to keep comments
implicitImports: @[], # modules that are to be implicitly imported
implicitIncludes: @[], # modules that are to be implicitly included
@@ -358,7 +408,8 @@ proc newConfigRef*(): ConfigRef =
ccompilerpath: "",
toCompile: @[],
arguments: "",
suggestMaxResults: 10_000
suggestMaxResults: 10_000,
maxLoopIterationsVM: 10_000_000,
)
setTargetFromSystem(result.target)
# enable colors by default on terminals
@@ -395,7 +446,7 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
result = conf.target.targetOS in {osLinux, osMorphos, osSkyos, osIrix, osPalmos,
osQnx, osAtari, osAix,
osHaiku, osVxWorks, osSolaris, osNetbsd,
osFreebsd, osOpenbsd, osDragonfly, osMacosx,
osFreebsd, osOpenbsd, osDragonfly, osMacosx, osIos,
osAndroid, osNintendoSwitch}
of "linux":
result = conf.target.targetOS in {osLinux, osAndroid}
@@ -405,8 +456,10 @@ proc isDefined*(conf: ConfigRef; symbol: string): bool =
result = platform.OS[conf.target.targetOS].props.contains(ospLacksThreadVars)
of "msdos": result = conf.target.targetOS == osDos
of "mswindows", "win32": result = conf.target.targetOS == osWindows
of "macintosh": result = conf.target.targetOS in {osMacos, osMacosx}
of "osx": result = conf.target.targetOS == osMacosx
of "macintosh":
result = conf.target.targetOS in {osMacos, osMacosx, osIos}
of "osx", "macosx":
result = conf.target.targetOS in {osMacosx, osIos}
of "sunos": result = conf.target.targetOS == osSolaris
of "nintendoswitch":
result = conf.target.targetOS == osNintendoSwitch
@@ -469,18 +522,27 @@ proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): Absolute
conf.outDir / changeFileExt(filename, ext)
proc absOutFile*(conf: ConfigRef): AbsoluteFile =
conf.outDir / conf.outFile
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
proc prepareToWriteOutput*(conf: ConfigRef): AbsoluteFile =
## Create the output directory and returns a full path to the output file
createDir conf.outDir
return conf.outDir / conf.outFile
result = conf.outDir / conf.outFile
when defined(posix):
if dirExists(result.string):
result.string.add ".out"
proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
## Gets the prefix dir, usually the parent directory where the binary resides.
##
## This is overridden by some tools (namely nimsuggest) via the ``conf.prefixDir``
## field.
## This should resolve to root of nim sources, whether running nim from a local
## 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
@@ -516,21 +578,26 @@ proc shortenDir*(conf: ConfigRef; dir: string): string {.
## returns the interesting part of a dir
var prefix = conf.projectPath.string & DirSep
if startsWith(dir, prefix):
return substr(dir, len(prefix))
return substr(dir, prefix.len)
prefix = getPrefixDir(conf).string & DirSep
if startsWith(dir, prefix):
return substr(dir, len(prefix))
return substr(dir, prefix.len)
result = dir
proc removeTrailingDirSep*(path: string): string =
if (len(path) > 0) and (path[len(path) - 1] == DirSep):
result = substr(path, 0, len(path) - 2)
if (path.len > 0) and (path[^1] == DirSep):
result = substr(path, 0, path.len - 2)
else:
result = path
proc disableNimblePath*(conf: ConfigRef) =
incl conf.globalOptions, optNoNimblePath
conf.lazyPaths.setLen(0)
conf.nimblePaths.setLen(0)
proc clearNimblePath*(conf: ConfigRef) =
conf.lazyPaths.setLen(0)
conf.nimblePaths.setLen(0)
include packagehandling
@@ -560,9 +627,16 @@ proc pathSubs*(conf: ConfigRef; p, config: string): string =
"projectname", conf.projectName,
"projectpath", conf.projectPath.string,
"projectdir", conf.projectPath.string,
"nimcache", getNimcacheDir(conf).string])
if "~/" in result:
result = result.replace("~/", home & '/')
"nimcache", getNimcacheDir(conf).string]).expandTilde
iterator nimbleSubs*(conf: ConfigRef; p: string): string =
let pl = p.toLowerAscii
if "$nimblepath" in pl or "$nimbledir" in pl:
for i in countdown(conf.nimblePaths.len-1, 0):
let nimblePath = removeTrailingDirSep(conf.nimblePaths[i].string)
yield p % ["nimblepath", nimblePath, "nimbledir", nimblePath]
else:
yield p
proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
ext: string): AbsoluteFile =
@@ -610,7 +684,25 @@ template patchModule(conf: ConfigRef) {.dirty.} =
let ov = conf.moduleOverrides[key]
if ov.len > 0: result = AbsoluteFile(ov)
proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile {.procvar.} =
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 ".."
proc getRelativePathFromConfigPath*(conf: ConfigRef; f: AbsoluteFile): RelativeFile =
let f = $f
template search(paths) =
for it in paths:
let it = $it
if f.isRelativeTo(it):
return relativePath(f, it).RelativeFile
search(conf.searchPaths)
search(conf.lazyPaths)
proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile =
if f.isAbsolute:
result = if f.existsFile: AbsoluteFile(f) else: AbsoluteFile""
else:
@@ -653,21 +745,40 @@ proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFi
proc findProjectNimFile*(conf: ConfigRef; pkg: string): string =
const extensions = [".nims", ".cfg", ".nimcfg", ".nimble"]
var candidates: seq[string] = @[]
var dir = pkg
var
candidates: seq[string] = @[]
dir = pkg
prev = dir
nimblepkg = ""
let pkgname = pkg.lastPathPart()
while true:
for k, f in os.walkDir(dir, relative=true):
for k, f in os.walkDir(dir, relative = true):
if k == pcFile and f != "config.nims":
let (_, name, ext) = splitFile(f)
if ext in extensions:
let x = changeFileExt(dir / name, ".nim")
if fileExists(x):
candidates.add x
if ext == ".nimble":
if nimblepkg.len == 0:
nimblepkg = name
# Since nimble packages can have their source in a subfolder,
# check the last folder we were in for a possible match.
if dir != prev:
let x = prev / x.extractFilename()
if fileExists(x):
candidates.add x
else:
# If we found more than one nimble file, chances are that we
# missed the real project file, or this is an invalid nimble
# package. Either way, bailing is the better choice.
return ""
let pkgname = if nimblepkg.len > 0: nimblepkg else: pkgname
for c in candidates:
# nim-foo foo or foo nfoo
if (pkg in c) or (c in pkg): return c
if candidates.len >= 1:
if pkgname in c.extractFilename(): return c
if candidates.len > 0:
return candidates[0]
prev = dir
dir = parentDir(dir)
if dir == "": break
return ""
@@ -700,6 +811,7 @@ proc parseIdeCmd*(s: string): IdeCmd =
of "outline": ideOutline
of "known": ideKnown
of "msg": ideMsg
of "project": ideProject
else: ideNone
proc `$`*(c: IdeCmd): string =
@@ -716,3 +828,14 @@ proc `$`*(c: IdeCmd): string =
of ideOutline: "outline"
of ideKnown: "known"
of ideMsg: "msg"
of ideProject: "project"
proc floatInt64Align*(conf: ConfigRef): int16 =
## Returns either 4 or 8 depending on reasons.
if conf != nil and conf.target.targetCPU == cpuI386:
#on Linux/BSD i386, double are aligned to 4bytes (except with -malign-double)
if conf.target.targetOS != osWindows:
# on i386 for all known POSIX systems, 64bits ints are aligned
# to 4bytes (except with -malign-double)
return 4
return 8

View File

@@ -15,10 +15,8 @@ iterator myParentDirs(p: string): string =
if current.len == 0: break
yield current
proc resetPackageCache*(conf: ConfigRef) =
conf.packageCache = newPackageCache()
proc getPackageName*(conf: ConfigRef; path: string): string =
proc getNimbleFile*(conf: ConfigRef; path: string): string =
## returns absolute path to nimble file, eg: /pathto/cligen.nimble
var parents = 0
block packageSearch:
for d in myParentDirs(path):
@@ -27,7 +25,7 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
return conf.packageCache[d]
inc parents
for file in walkFiles(d / "*.nimble"):
result = file.splitFile.name
result = file
break packageSearch
# we also store if we didn't find anything:
when not defined(nimNoNilSeqs):
@@ -38,23 +36,26 @@ proc getPackageName*(conf: ConfigRef; path: string): string =
dec parents
if parents <= 0: break
proc getPackageName*(conf: ConfigRef; path: string): string =
## returns nimble package name, eg: `cligen`
let path = getNimbleFile(conf, path)
result = path.splitFile.name
proc fakePackageName*(conf: ConfigRef; path: AbsoluteFile): string =
# foo/../bar becomes foo7_7bar
result = relativeTo(path, conf.projectPath, '/').string.multiReplace(
{"/": "7", "..": "_", "7": "77", "_": "__", ":": "8", "8": "88"})
# Convert `path` so that 2 modules with same name
# in different directory get different name and they can be
# placed in a directory.
# foo-#head/../bar becomes @foo-@hhead@s..@sbar
result = "@m" & relativeTo(path, conf.projectPath).string.multiReplace({$os.DirSep: "@s", $os.AltSep: "@s", "#": "@h", "@": "@@", ":": "@c"})
proc demanglePackageName*(path: string): string =
result = path.multiReplace(
{"88": "8", "8": ":", "77": "7", "__": "_", "_7": "../", "7": "/"})
result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
proc withPackageName*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
let x = getPackageName(conf, path.string)
if x.len == 0:
result = path
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
let (p, file, ext) = path.splitFile
if x == "stdlib":
# Hot code reloading now relies on 'stdlib_system' names etc.
result = p / RelativeFile((x & '_' & file) & ext)
else:
result = p / RelativeFile(fakePackageName(conf, path))
result = p / RelativeFile(fakePackageName(conf, path))

View File

@@ -46,7 +46,7 @@ proc patternError(n: PNode; conf: ConfigRef) =
localError(conf, n.info, "illformed AST: " & renderTree(n, {renderNoComments}))
proc add(code: var TPatternCode, op: TOpcode) {.inline.} =
add(code, chr(ord(op)))
code.add chr(ord(op))
proc whichAlias*(p: PSym): TAliasRequest =
if p.constraint != nil:
@@ -57,29 +57,29 @@ proc whichAlias*(p: PSym): TAliasRequest =
proc compileConstraints(p: PNode, result: var TPatternCode; conf: ConfigRef) =
case p.kind
of nkCallKinds:
if p.sons[0].kind != nkIdent:
patternError(p.sons[0], conf)
if p[0].kind != nkIdent:
patternError(p[0], conf)
return
let op = p.sons[0].ident
let op = p[0].ident
if p.len == 3:
if op.s == "|" or op.id == ord(wOr):
compileConstraints(p.sons[1], result, conf)
compileConstraints(p.sons[2], result, conf)
compileConstraints(p[1], result, conf)
compileConstraints(p[2], result, conf)
result.add(ppOr)
elif op.s == "&" or op.id == ord(wAnd):
compileConstraints(p.sons[1], result, conf)
compileConstraints(p.sons[2], result, conf)
compileConstraints(p[1], result, conf)
compileConstraints(p[2], result, conf)
result.add(ppAnd)
else:
patternError(p, conf)
elif p.len == 2 and (op.s == "~" or op.id == ord(wNot)):
compileConstraints(p.sons[1], result, conf)
compileConstraints(p[1], result, conf)
result.add(ppNot)
else:
patternError(p, conf)
of nkAccQuoted, nkPar:
if p.len == 1:
compileConstraints(p.sons[0], result, conf)
compileConstraints(p[0], result, conf)
else:
patternError(p, conf)
of nkIdent:
@@ -138,7 +138,7 @@ proc checkForSideEffects*(n: PNode): TSideEffectAnalysis =
case n.kind
of nkCallKinds:
# only calls can produce side effects:
let op = n.sons[0]
let op = n[0]
if op.kind == nkSym and isRoutine(op.sym):
let s = op.sym
if sfSideEffect in s.flags:
@@ -152,8 +152,8 @@ proc checkForSideEffects*(n: PNode): TSideEffectAnalysis =
# indirect call: assume side effect:
return seSideEffect
# we need to check n[0] too: (FwithSideEffectButReturnsProcWithout)(args)
for i in 0 ..< n.len:
let ret = checkForSideEffects(n.sons[i])
for i in 0..<n.len:
let ret = checkForSideEffects(n[i])
if ret == seSideEffect: return ret
elif ret == seUnknown and result == seNoSideEffect:
result = seUnknown
@@ -163,8 +163,8 @@ proc checkForSideEffects*(n: PNode): TSideEffectAnalysis =
else:
# assume no side effect:
result = seNoSideEffect
for i in 0 ..< n.len:
let ret = checkForSideEffects(n.sons[i])
for i in 0..<n.len:
let ret = checkForSideEffects(n[i])
if ret == seSideEffect: return ret
elif ret == seUnknown and result == seNoSideEffect:
result = seUnknown
@@ -218,45 +218,47 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
of nkSym:
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
else: {skVar, skResult, skTemp}
if n.sym.kind in kinds:
if n.sym.kind == skParam and n.sym.typ.kind in {tyVar, tySink}:
result = arLValue
elif isUnsafeAddr and n.sym.kind == skParam:
result = arLValue
elif n.sym.kind in kinds:
if owner != nil and owner == n.sym.owner and
sfGlobal notin n.sym.flags:
result = arLocalLValue
else:
result = arLValue
elif n.sym.kind == skParam and n.sym.typ.kind == tyVar:
result = arLValue
elif n.sym.kind == skType:
let t = n.sym.typ.skipTypes({tyTypeDesc})
if t.kind == tyVar: result = arStrange
of nkDotExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue
else:
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
result = isAssignable(owner, n[0], isUnsafeAddr)
if result != arNone and n[1].kind == nkSym and
sfDiscriminant in n[1].sym.flags:
result = arDiscriminant
of nkBracketExpr:
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tyPtr, tyRef}:
let t = skipTypes(n[0].typ, abstractInst-{tyTypeDesc})
if t.kind in {tyVar, tySink, tyPtr, tyRef}:
result = arLValue
elif isUnsafeAddr and t.kind == tyLent:
result = arLValue
else:
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
result = isAssignable(owner, n[0], isUnsafeAddr)
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
# Object and tuple conversions are still addressable, so we skip them
# XXX why is 'tyOpenArray' allowed here?
if skipTypes(n.typ, abstractPtrs-{tyTypeDesc}).kind in
{tyOpenArray, tyTuple, tyObject}:
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
elif compareTypes(n.typ, n.sons[1].typ, dcEqIgnoreDistinct):
result = isAssignable(owner, n[1], isUnsafeAddr)
elif compareTypes(n.typ, n[1].typ, dcEqIgnoreDistinct):
# types that are equal modulo distinction preserve l-value:
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
result = isAssignable(owner, n[1], isUnsafeAddr)
of nkHiddenDeref:
if isUnsafeAddr and n[0].typ.kind == tyLent: result = arLValue
elif n[0].typ.kind == tyLent: result = arDiscriminant
@@ -264,11 +266,11 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
of nkDerefExpr, nkHiddenAddr:
result = arLValue
of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
result = isAssignable(owner, n[0], isUnsafeAddr)
of nkCallKinds:
# builtin slice keeps lvalue-ness:
if getMagic(n) in {mArrGet, mSlice}:
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
result = isAssignable(owner, n[1], isUnsafeAddr)
elif n.typ != nil and n.typ.kind == tyVar:
result = arLValue
elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent:

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More