Compare commits

..

43 Commits

Author SHA1 Message Date
ringabout
5c4a5421b5 Merge branch 'devel' into pr_refc_copy 2023-04-13 18:17:42 +08:00
ringabout
16f42084d3 fixes #20900; Calling template through from generic function across module fails to build (#21649)
* fixes #20900; Calling template through from generic function across module fails to build

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

fixes #19225

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

* fix CI

* convert to compile option

* fix lie

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

* please don't tell me other packages do this

* fix CI + test typeclass callconv pragma

* better logic in parser

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

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

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

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

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

* Fixup: this should still be a func

* Run test case on js target

* Adapt testcase to contributor guide and best practices

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

* Add example code to lib/system.nim

* Fix compile error

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

Fixes #21593

* Properly cast intVal as unsigned

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

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

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

fixes #20687, fixes #21435

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

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

* set temp symbol AST

* hopeful fix some issues, add test for #19364

* always use temp for consts

* document, fix small issue

* fix manual indentation

* actually fix manual

* use helper proc

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

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

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

This reverts commit 3936071772.
2023-03-28 14:29:12 +08:00
heterodoxic
7d83dfd0d1 fixes #21505 (overload resolution of explicit constructors for imported C++ types) (#21511)
hacky attempt to reconcile default explicit constructors with enforcement of brace initialization, instead of memsetting imported objects to 0
2023-03-27 17:20:20 +02:00
Amjad Ben Hedhili
3936071772 Add cursor to lists iterator variables (#21527)
* followup #21507
2023-03-27 17:10:51 +02:00
119 changed files with 1669 additions and 877 deletions

View File

@@ -23,11 +23,11 @@ jobs:
vmImage: 'ubuntu-20.04'
CPU: amd64
# regularly breaks, refs bug #17325
Linux_i386:
# on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
vmImage: 'ubuntu-18.04'
CPU: i386
# Linux_i386:
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
# vmImage: 'ubuntu-18.04'
# CPU: i386
OSX_amd64:
vmImage: 'macOS-11'
CPU: amd64

View File

@@ -10,7 +10,6 @@
[//]: # "Additions:"
- Added `parseutils.parseSize` - inverse to `strutils.formatSize` - to parse human readable sizes.
[//]: # "Deprecations:"

View File

@@ -135,30 +135,90 @@
- The experimental strictFuncs feature now disallows a store to the heap via a `ref` or `ptr` indirection.
- Underscores (`_`) as routine parameters are now ignored and cannot be used in the routine body.
The following code now does not compile:
- The underscore identifier (`_`) is now generally not added to scope when
used as the name of a definition. While this was already the case for
variables, it is now also the case for routine parameters, generic
parameters, routine declarations, type declarations, etc. This means that the following code now does not compile:
```nim
proc foo(_: int): int = _ + 1
echo foo(1)
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
echo foo[int]()
proc _() = echo "_"
_()
type _ = int
let x: _ = 3
```
Instead, the following code now compiles:
Whereas the following code now compiles:
```nim
proc foo(_, _: int): int = 123
echo foo(1, 2)
```
- Underscores (`_`) as generic parameters are not supported and cannot be used.
Generics that use `_` as parameters will no longer compile requires you to replace `_` with something else:
```nim
proc foo[_](t: typedesc[_]): string = "BAR" # Can not compile
proc foo[T](t: typedesc[T]): string = "BAR" # Can compile
proc foo[_, _](): int = 123
echo foo[int, bool]()
proc foo[T, U](_: typedesc[T], _: typedesc[U]): (T, U) = (default(T), default(U))
echo foo(int, bool)
proc _() = echo "one"
proc _() = echo "two"
type _ = int
type _ = float
```
- - Added the `--legacy:verboseTypeMismatch` switch to get legacy type mismatch error messages.
- The JavaScript backend now uses [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
for 64-bit integer types (`int64` and `uint64`) by default. As this affects
JS code generation, code using these types to interface with the JS backend
may need to be updated. Note that `int` and `uint` are not affected.
For compatibility with [platforms that do not support BigInt](https://caniuse.com/bigint)
and in the case of potential bugs with the new implementation, the
old behavior is currently still supported with the command line option
`--jsbigint64:off`.
- The `proc` and `iterator` type classes now respectively only match
procs and iterators. Previously both type classes matched any of
procs or iterators.
```nim
proc prc(): int =
123
iterator iter(): int =
yield 123
proc takesProc[T: proc](x: T) = discard
proc takesIter[T: iterator](x: T) = discard
# always compiled:
takesProc(prc)
takesIter(iter)
# no longer compiles:
takesProc(iter)
takesIter(prc)
```
- The `proc` and `iterator` type classes now accept a calling convention pragma
(i.e. `proc {.closure.}`) that must be shared by matching proc or iterator
types. Previously pragmas were parsed but discarded if no parameter list
was given.
This is represented in the AST by an `nnkProcTy`/`nnkIteratorTy` node with
an `nnkEmpty` node in the place of the `nnkFormalParams` node, and the pragma
node in the same place as in a concrete `proc` or `iterator` type node. This
state of the AST may be unexpected to existing code, both due to the
replacement of the `nnkFormalParams` node as well as having child nodes
unlike other type class AST.
## Standard library additions and changes
[//]: # "Changes:"
@@ -231,6 +291,7 @@
- Added `openArray[char]` overloads for `std/parseutils` allowing more code reuse.
- Added `openArray[char]` overloads for `std/unicode` allowing more code reuse.
- Added `safe` parameter to `base64.encodeMime`.
- Added `parseutils.parseSize` - inverse to `strutils.formatSize` - to parse human readable sizes.
[//]: # "Deprecations:"
- Deprecated `selfExe` for Nimscript.
@@ -343,6 +404,26 @@
- `=wasMoved` can be overridden by users.
- Tuple unpacking for variables is now treated as syntax sugar that directly
expands into multiple assignments. Along with this, tuple unpacking for
variables can now be nested.
```nim
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
let (x, (_, y), _, z) = returnsNestedTuple()
# roughly becomes
let
tmpTup1 = returnsNestedTuple()
x = tmpTup1[0]
tmpTup2 = tmpTup1[1]
y = tmpTup2[1]
z = tmpTup1[3]
```
As a result `nnkVarTuple` nodes in variable sections will no longer be
reflected in `typed` AST.
## Compiler changes
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
@@ -364,4 +445,4 @@
## Tool changes
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs`).
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs`). Use `nimble develop --global` to create an old style link file in the special links directory documented at https://github.com/nim-lang/nimble#nimble-develop.

View File

@@ -1947,7 +1947,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
initLoc(call, locCall, e, OnHeap)
if not p.module.compileToCpp:
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)"
call.r = ropecg(p.module, setLenPattern, [
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
@@ -2339,7 +2339,7 @@ proc genWasMoved(p: BProc; n: PNode) =
if p.withinBlockLeaveActions > 0 and notYetAlive(n1):
discard
else:
initLocExpr(p, n1, a)
initLocExpr(p, n1, a, {lfEnforceDeref})
resetLoc(p, a)
#linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])

View File

@@ -200,6 +200,9 @@ proc isImportedCppType(t: PType): bool =
result = (t.sym != nil and sfInfixCall in t.sym.flags) or
(x.sym != nil and sfInfixCall in x.sym.flags)
proc isOrHasImportedCppType(typ: PType): bool =
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKind): Rope
proc isObjLackingTypeField(typ: PType): bool {.inline.} =
@@ -553,7 +556,10 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
else:
# don't use fieldType here because we need the
# tyGenericInst for C++ template support
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
if fieldType.isOrHasImportedCppType():
result.addf("$1$3 $2{};$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
else:
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
else: internalError(m.config, n.info, "genRecordFieldsAux()")
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =

View File

@@ -61,12 +61,12 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
var ms = getModule(s)
result = m.g.modules[ms.position]
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}) =
result.k = k
result.storage = s
result.lode = lode
result.r = ""
result.flags = {}
result.flags = flags
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) {.inline.} =
# fills the loc if it is not already initialized
@@ -487,9 +487,6 @@ proc resetLoc(p: BProc, loc: var TLoc) =
# on the bytes following the m_type field?
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
proc isOrHasImportedCppType(typ: PType): bool =
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
let typ = loc.t
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
@@ -644,7 +641,23 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
if sfVolatile in s.flags: decl.add(" volatile")
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
if value != "":
decl.addf(" $1 = $2;$n", [s.loc.r, value])
if p.module.compileToCpp and value.startsWith "{{}":
# TODO: taking this branch, re"\{\{\}(,\s\{\})*\}" might be emitted, resulting in
# either warnings (GCC 12.2+) or errors (Clang 15, MSVC 19.3+) of C++11+ compilers **when
# explicit constructors are around** due to overload resolution rules in place [^0][^1][^2]
# *Workaround* here: have C++'s static initialization mechanism do the default init work,
# for us lacking a deeper knowledge of an imported object's constructors' ex-/implicitness
# (so far) *and yet* trying to achieve default initialization.
# Still, generating {}s in genConstObjConstr() just to omit them here is faaaar from ideal;
# need to figure out a better way, possibly by keeping around more data about the
# imported objects' contructors?
#
# [^0]: https://en.cppreference.com/w/cpp/language/aggregate_initialization
# [^1]: https://cplusplus.github.io/CWG/issues/1518.html
# [^2]: https://eel.is/c++draft/over.match.ctor
decl.addf(" $1;$n", [s.loc.r])
else:
decl.addf(" $1 = $2;$n", [s.loc.r, value])
else:
decl.addf(" $1;$n", [s.loc.r])
else:
@@ -685,8 +698,8 @@ proc genLiteral(p: BProc, n: PNode; result: var Rope)
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
proc raiseExit(p: BProc)
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
initLoc(result, locNone, e, OnUnknown)
proc initLocExpr(p: BProc, e: PNode, result: var TLoc, flags: TLocFlags = {}) =
initLoc(result, locNone, e, OnUnknown, flags)
expr(p, e, result)
proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
@@ -1086,7 +1099,7 @@ proc genProcBody(p: BProc; procBody: PNode) =
proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
sfNoReturn in s.flags and m.config.exc != excGoto
proc genProcAux(m: BModule, prc: PSym) =
proc genProcAux*(m: BModule, prc: PSym) =
var p = newProc(prc, m)
var header = newRopeAppender()
genProcHeader(m, prc, header)
@@ -2094,7 +2107,7 @@ proc updateCachedModule(m: BModule) =
cf.flags = {CfileFlag.Cached}
addFileToCompile(m.config, cf)
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode): PNode =
## Also called from IC.
if sfMainModule in m.module.flags:
# phase ordering problem here: We need to announce this
@@ -2140,8 +2153,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
if m.g.forwardedProcs.len == 0:
incl m.flags, objHasKidsValid
let disp = generateMethodDispatchers(graph)
for x in disp: genProcAux(m, x.sym)
result = generateMethodDispatchers(graph, m.idgen)
let mm = m
m.g.modulesClosed.add mm

View File

@@ -213,7 +213,7 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
a[j] = v
if h == 1: break
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet; idgen: IdGenerator): PSym =
var base = methods[0].ast[dispatcherPos].sym
result = base
var paramLen = base.typ.len
@@ -272,7 +272,7 @@ proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PS
nilchecks.flags.incl nfTransf # should not be further transformed
result.ast[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
proc generateMethodDispatchers*(g: ModuleGraph, idgen: IdGenerator): PNode =
result = newNode(nkStmtList)
for bucket in 0..<g.methods.len:
var relevantCols = initIntSet()
@@ -282,4 +282,4 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode =
# if multi-methods are not enabled, we are interested only in the first field
break
sortBucket(g.methods[bucket].methods, relevantCols)
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols, idgen))

View File

@@ -336,6 +336,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
of "nilseqs", "nilchecks", "taintmode": warningOptionNoop(switch)
of "panics": result = contains(conf.globalOptions, optPanics)
of "jsbigint64": result = contains(conf.globalOptions, optJsBigInt64)
else: invalidCmdLineOption(conf, passCmd1, switch, info)
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
@@ -1065,29 +1066,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "expandarc":
expectArg(conf, switch, arg, pass, info)
conf.arcToExpand[arg] = "T"
of "useversion":
expectArg(conf, switch, arg, pass, info)
case arg
of "1.0":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "0")
# old behaviors go here:
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
undefSymbol(conf.symbols, "nimDoesntTrackDefects")
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
conf.globalOptions.incl optNimV1Emulation
of "1.2":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "2")
conf.globalOptions.incl optNimV12Emulation
of "1.6":
defineSymbol(conf.symbols, "NimMajor", "1")
defineSymbol(conf.symbols, "NimMinor", "6")
conf.globalOptions.incl optNimV16Emulation
else:
localError(conf, info, "unknown Nim version; currently supported values are: `1.0`, `1.2`")
# always be compatible with 1.x.100:
defineSymbol(conf.symbols, "NimPatch", "100")
of "benchmarkvm":
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
of "profilevm":
@@ -1101,6 +1079,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
if optPanics in conf.globalOptions:
defineSymbol(conf.symbols, "nimPanics")
of "jsbigint64":
processOnOffSwitchG(conf, {optJsBigInt64}, arg, pass, info)
of "sourcemap": # xxx document in --fullhelp
conf.globalOptions.incl optSourcemap
conf.options.incl optLineDir

View File

@@ -154,3 +154,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasGenericDefine")
defineSymbol("nimHasDefineAliases")
defineSymbol("nimHasWarnBareExcept")
defineSymbol("nimHasWarnCopyHookForRefc")

View File

@@ -112,13 +112,16 @@ type
proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst)
proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str)
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
proc addRstFileIndex(d: PDoc, fileIndex: lineinfos.FileIndex): rstast.FileIndex =
let invalid = rstast.FileIndex(-1)
result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid)
result = d.nimToRstFid.getOrDefault(fileIndex, default = invalid)
if result == invalid:
let fname = toFullPath(d.conf, info)
let fname = toFullPath(d.conf, fileIndex)
result = addFilename(d.sharedState, fname)
d.nimToRstFid[info.fileIndex] = result
d.nimToRstFid[fileIndex] = result
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
addRstFileIndex(d, info.fileIndex)
proc cmpDecimalsIgnoreCase(a, b: string): int =
## For sorting with correct handling of cases like 'uint8' and 'uint16'.
@@ -1060,7 +1063,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags, nonEx
fileIndex: addRstFileIndex(d, nameNode.info))
addAnchorNim(d.sharedState, external = false, refn = symbolOrId,
tooltip = detailedName, langSym = rstLangSymbol,
priority = symbolPriority(k), info = lineinfo)
priority = symbolPriority(k), info = lineinfo,
module = addRstFileIndex(d, FileIndex d.module.position))
let renderFlags =
if nonExports: {renderNoBody, renderNoComments, renderDocComments, renderSyms,
@@ -1451,7 +1455,8 @@ proc finishGenerateDoc*(d: var PDoc) =
isGroup: true),
priority = symbolPriority(k),
# select index `0` just to have any meaningful warning:
info = overloadChoices[0].info)
info = overloadChoices[0].info,
module = addRstFileIndex(d, FileIndex d.module.position))
if optGenIndexOnly in d.conf.globalOptions:
return

View File

@@ -50,7 +50,10 @@ proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var Alive
let n = unpackTree(g, m.module.position, m.fromDisk.topLevel, p)
cgen.genTopLevelStmt(bmod, n)
finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
let disps = finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
if disps != nil:
for disp in disps:
genProcAux(bmod, disp.sym)
m.fromDisk.backendFlags = cgen.whichInitProcs(bmod)
proc replayTypeInfo(g: ModuleGraph; m: var LoadedModule; origin: FileIndex) =

View File

@@ -249,7 +249,17 @@ proc canBeMoved(c: Con; t: PType): bool {.inline.} =
proc isNoInit(dest: PNode): bool {.inline.} =
result = dest.kind == nkSym and sfNoInit in dest.sym.flags
proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
proc deepAliases(dest, ri: PNode): bool =
case ri.kind
of nkCallKinds, nkStmtListExpr, nkBracket, nkTupleConstr, nkObjConstr,
nkCast, nkConv, nkObjUpConv, nkObjDownConv:
for r in ri:
if deepAliases(dest, r): return true
return false
else:
return aliases(dest, ri) != no
proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
isNoInit(dest):
@@ -263,7 +273,14 @@ proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNod
else:
# the default is to use combination of `=destroy(dest)` and
# and copyMem(dest, source). This is efficient.
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
if deepAliases(dest, ri):
# consider: x = x + y, it is wrong to destroy the destination first!
# tmp to support self assignments
let tmp = c.getTemp(s, dest.typ, dest.info)
result = newTree(nkStmtList, newTree(nkFastAsgn, tmp, dest), newTree(nkFastAsgn, dest, ri),
c.genDestroy(tmp))
else:
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
proc isCriticalLink(dest: PNode): bool {.inline.} =
#[
@@ -454,7 +471,7 @@ proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
# This was already done in the sink parameter handling logic.
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
let tmp = c.getTemp(s, arg.typ, arg.info)
result.add c.genSink(tmp, arg, {IsDecl})
result.add c.genSink(s, tmp, arg, {IsDecl})
result.add tmp
s.final.add c.genDestroy(tmp)
else:
@@ -1004,7 +1021,7 @@ proc sameLocation*(a, b: PNode): bool =
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b)
else: false
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
proc genFieldAccessSideEffects(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
# with side effects
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), nextSymId c.idgen, c.owner, ri[1].info)
temp.typ = ri[1].typ
@@ -1021,7 +1038,7 @@ proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCop
newAccess.add ri[0]
newAccess.add tempAsNode
var snk = c.genSink(dest, newAccess, flags)
var snk = c.genSink(s, dest, newAccess, flags)
result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess))
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopyFlag] = {}): PNode =
@@ -1039,21 +1056,21 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
else:
case ri.kind
of nkCallKinds:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkBracketExpr:
if isUnpackedTuple(ri[0]):
# unpacking of tuple: take over the elements
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s):
if aliases(dest, ri) == no:
# Rule 3: `=sink`(x, z); wasMoved(z)
if isAtom(ri[1]):
var snk = c.genSink(dest, ri, flags)
var snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
result = genFieldAccessSideEffects(c, dest, ri, flags)
result = genFieldAccessSideEffects(c, s, dest, ri, flags)
else:
result = c.genSink(dest, destructiveMoveVar(ri, c, s), flags)
result = c.genSink(s, dest, destructiveMoveVar(ri, c, s), flags)
else:
result = c.genCopy(dest, ri, flags)
result.add p(ri, c, s, consumed)
@@ -1065,25 +1082,25 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
else:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
result = c.genSink(dest, p(ri, c, s, consumed), flags)
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
of nkSym:
if isSinkParam(ri.sym) and isLastRead(ri, c, s):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
result = c.genCopy(dest, ri, flags)
result.add p(ri, c, s, consumed)
c.finishCopy(result, dest, isFromSink = false)
of nkHiddenSubConv, nkHiddenStdConv, nkConv, nkObjDownConv, nkObjUpConv, nkCast:
result = c.genSink(dest, p(ri, c, s, sinkArg), flags)
result = c.genSink(s, dest, p(ri, c, s, sinkArg), flags)
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
# We know the result will be a stmt so we use that fact to optimize
@@ -1094,7 +1111,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s) and
canBeMoved(c, dest.typ):
# Rule 3: `=sink`(x, z); wasMoved(z)
let snk = c.genSink(dest, ri, flags)
let snk = c.genSink(s, dest, ri, flags)
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
else:
result = c.genCopy(dest, ri, flags)

View File

@@ -571,12 +571,20 @@ proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
let size = n[1].typ.skipTypes(abstractRange).size
when reassign:
let (a, tmp) = maybeMakeTempAssignable(p, n[1], x)
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
if size == 8 and optJsBigInt64 in p.config.globalOptions:
r.res = "$1 = BigInt.asUintN(64, ($4 $2 $3))" % [a, rope op, y.rdLoc, tmp]
else:
let trimmer = unsignedTrimmer(size)
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
else:
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
if size == 8 and optJsBigInt64 in p.config.globalOptions:
r.res = "BigInt.asUintN(64, ($1 $2 $3))" % [x.rdLoc, rope op, y.rdLoc]
else:
let trimmer = unsignedTrimmer(size)
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
r.kind = resExpr
template ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
@@ -618,11 +626,45 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
if i == 0: applyFormat(frmtA) else: applyFormat(frmtB)
case op
of mAddI: applyFormat("addInt($1, $2)", "($1 + $2)")
of mSubI: applyFormat("subInt($1, $2)", "($1 - $2)")
of mMulI: applyFormat("mulInt($1, $2)", "($1 * $2)")
of mDivI: applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
of mModI: applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
of mAddI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "addInt64")
applyFormat("addInt64($1, $2)")
else:
applyFormat("addInt($1, $2)")
else:
applyFormat("($1 + $2)")
of mSubI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "subInt64")
applyFormat("subInt64($1, $2)")
else:
applyFormat("subInt($1, $2)")
else:
applyFormat("($1 - $2)")
of mMulI:
if i == 0:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "mulInt64")
applyFormat("mulInt64($1, $2)")
else:
applyFormat("mulInt($1, $2)")
else:
applyFormat("($1 * $2)")
of mDivI:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "divInt64")
applyFormat("divInt64($1, $2)", "$1 / $2")
else:
applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
of mModI:
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
useMagic(p, "modInt64")
applyFormat("modInt64($1, $2)", "$1 % $2")
else:
applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
of mSucc: applyFormat("addInt($1, $2)", "($1 + $2)")
of mPred: applyFormat("subInt($1, $2)", "($1 - $2)")
of mAddF64: applyFormat("($1 + $2)", "($1 + $2)")
@@ -631,15 +673,27 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
of mShrI: applyFormat("", "")
of mShlI:
if n[1].typ.size <= 4:
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.size == 8:
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asIntN(64, $1 << BigInt($2))")
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asUintN(64, $1 << BigInt($2))")
else:
applyFormat("($1 * Math.pow(2, $2))")
else:
applyFormat("($1 << $2)", "($1 << $2)")
else:
applyFormat("($1 * Math.pow(2, $2))", "($1 * Math.pow(2, $2))")
of mAshrI:
if n[1].typ.size <= 4:
applyFormat("($1 >> $2)", "($1 >> $2)")
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.size == 8:
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asIntN(64, $1 >> BigInt($2))")
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
applyFormat("BigInt.asUintN(64, $1 >> BigInt($2))")
else:
applyFormat("Math.floor($1 / Math.pow(2, $2))")
else:
applyFormat("Math.floor($1 / Math.pow(2, $2))", "Math.floor($1 / Math.pow(2, $2))")
applyFormat("($1 >> $2)", "($1 >> $2)")
of mBitandI: applyFormat("($1 & $2)", "($1 & $2)")
of mBitorI: applyFormat("($1 | $2)", "($1 | $2)")
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
@@ -697,7 +751,9 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mMulU: binaryUintExpr(p, n, r, "*")
of mDivU:
binaryUintExpr(p, n, r, "/")
if n[1].typ.skipTypes(abstractRange).size == 8:
if optJsBigInt64 notin p.config.globalOptions and
n[1].typ.skipTypes(abstractRange).size == 8:
# bigint / already truncates
r.res = "Math.trunc($1)" % [r.res]
of mDivI:
arithAux(p, n, r, op)
@@ -707,7 +763,13 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
var x, y: TCompRes
gen(p, n[1], x)
gen(p, n[2], y)
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
let typ = n[1].typ.skipTypes(abstractVarRange)
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
r.res = "BigInt.asIntN(64, BigInt.asUintN(64, $1) >> BigInt($2))" % [x.rdLoc, y.rdLoc]
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
r.res = "($1 >> BigInt($2))" % [x.rdLoc, y.rdLoc]
else:
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr, mStrToStr, mEnumToStr:
arithAux(p, n, r, op)
of mEqRef:
@@ -1764,15 +1826,25 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
createRecordVarAux(p, t.n, excludedFieldIDs, output)
t = t[0]
proc arrayTypeForElemType(typ: PType): string =
proc arrayTypeForElemType(conf: ConfigRef; typ: PType): string =
let typ = typ.skipTypes(abstractRange)
case typ.kind
of tyInt, tyInt32: "Int32Array"
of tyInt16: "Int16Array"
of tyInt8: "Int8Array"
of tyInt64:
if optJsBigInt64 in conf.globalOptions:
"BigInt64Array"
else:
""
of tyUInt, tyUInt32: "Uint32Array"
of tyUInt16: "Uint16Array"
of tyUInt8, tyChar, tyBool: "Uint8Array"
of tyUInt64:
if optJsBigInt64 in conf.globalOptions:
"BigUint64Array"
else:
""
of tyFloat32: "Float32Array"
of tyFloat64, tyFloat: "Float64Array"
of tyEnum:
@@ -1786,11 +1858,18 @@ proc arrayTypeForElemType(typ: PType): string =
proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
var t = skipTypes(typ, abstractInst)
case t.kind
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar:
of tyInt8..tyInt32, tyUInt8..tyUInt32, tyEnum, tyChar:
result = putToSeq("0", indirect)
of tyInt, tyUInt:
if $t.sym.loc.r == "bigint":
result = putToSeq("0n", indirect)
else:
result = putToSeq("0", indirect)
of tyInt64, tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
result = putToSeq("0n", indirect)
else:
result = putToSeq("0", indirect)
of tyFloat..tyFloat128:
result = putToSeq("0.0", indirect)
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
@@ -1804,7 +1883,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
of tyArray:
let length = toInt(lengthOrd(p.config, t))
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
let jsTyp = arrayTypeForElemType(p.config, e)
if jsTyp.len > 0:
result = "new $1($2)" % [rope(jsTyp), rope(length)]
elif length > 32:
@@ -1979,7 +2058,11 @@ proc genNewSeq(p: PProc, n: PNode) =
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
case skipTypes(n[1].typ, abstractVar + abstractRange).kind
of tyEnum, tyInt..tyUInt64, tyChar: gen(p, n[1], r)
of tyEnum, tyInt..tyInt32, tyUInt..tyUInt32, tyChar: gen(p, n[1], r)
of tyInt64, tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
unaryExpr(p, n, r, "", "Number($1)")
else: gen(p, n[1], r)
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1 : 0)")
else: internalError(p.config, n.info, "genOrd")
@@ -2202,14 +2285,34 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
r.res = "($1).length - 1" % [x.rdLoc]
r.kind = resExpr
of mInc:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
let typ = n[1].typ.skipTypes(abstractVarRange)
case typ.kind
of tyUInt..tyUInt32:
binaryUintExpr(p, n, r, "+", true)
of tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 + BigInt($2))", true)
else: binaryUintExpr(p, n, r, "+", true)
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if optOverflowCheck notin p.options:
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 + BigInt($2))", true)
else: binaryExpr(p, n, r, "addInt64", "$1 = addInt64($3, BigInt($2))", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($3, $2)", true)
of ast.mDec:
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
let typ = n[1].typ.skipTypes(abstractVarRange)
case typ.kind
of tyUInt..tyUInt32:
binaryUintExpr(p, n, r, "-", true)
of tyUInt64:
if optJsBigInt64 in p.config.globalOptions:
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 - BigInt($2))", true)
else: binaryUintExpr(p, n, r, "+", true)
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if optOverflowCheck notin p.options:
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 - BigInt($2))", true)
else: binaryExpr(p, n, r, "subInt64", "$1 = subInt64($3, BigInt($2))", true)
else:
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)", true)
@@ -2303,7 +2406,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
## Nim sequence maps to JS array.
var t = skipTypes(n.typ, abstractInst)
let e = elemType(t)
let jsTyp = arrayTypeForElemType(e)
let jsTyp = arrayTypeForElemType(p.config, e)
if skipTypes(n.typ, abstractVarRange).kind != tySequence and jsTyp.len > 0:
# generate typed array
# for example Nim generates `new Uint8Array([1, 2, 3])` for `[byte(1), 2, 3]`
@@ -2384,7 +2487,27 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
r.res = "(!!($1))" % [r.res]
r.kind = resExpr
elif toInt:
r.res = "(($1) | 0)" % [r.res]
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
else:
r.res = "(($1) | 0)" % [r.res]
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyUInt64:
r.res = "BigInt.asIntN(64, $1)" % [r.res]
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyInt64:
r.res = "BigInt.asUintN(64, $1)" % [r.res]
elif toUint or dest.kind in tyFloat..tyFloat64:
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
else:
# TODO: What types must we handle here?
discard
@@ -2395,7 +2518,11 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
var a, b: TCompRes
gen(p, n[0], r)
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
let src = skipTypes(n[0].typ, abstractVarRange)
let dest = skipTypes(n.typ, abstractVarRange)
if src.kind in {tyInt64, tyUInt64} and dest.kind notin {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
checkUnsignedConversions notin p.config.legacyFeatures):
discard "XXX maybe emit masking instructions here"
else:
@@ -2587,6 +2714,8 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
if toUint and (fromInt or fromUint):
let trimmer = unsignedTrimmer(dest.size)
r.res = "($1 $2)" % [r.res, trimmer]
elif toUint and src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number(BigInt.asUintN($1, $2))" % [$(dest.size * 8), r.res]
elif toInt:
if fromInt:
return
@@ -2602,6 +2731,25 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
of 4: "0xfffffffe"
else: ""
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
elif src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number(BigInt.asIntN($1, $2))" % [$(dest.size * 8), r.res]
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyUInt64:
r.res = "BigInt.asIntN(64, $1)" % [r.res]
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
if fromInt or fromUint:
r.res = "BigInt($1)" % [r.res]
elif src.kind in {tyFloat..tyFloat64}:
r.res = "BigInt(Math.trunc($1))" % [r.res]
elif src.kind == tyInt64:
r.res = "BigInt.asUintN(64, $1)" % [r.res]
elif dest.kind in tyFloat..tyFloat64:
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
r.res = "Number($1)" % [r.res]
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
r.address = r.res
r.res = "null"
@@ -2620,8 +2768,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkSym:
genSym(p, n, r)
of nkCharLit..nkUInt64Lit:
if n.typ.kind == tyBool:
case n.typ.skipTypes(abstractVarRange).kind
of tyBool:
r.res = if n.intVal == 0: rope"false" else: rope"true"
of tyUInt64:
r.res = rope($cast[BiggestUInt](n.intVal))
if optJsBigInt64 in p.config.globalOptions:
r.res.add('n')
of tyInt64:
r.res = rope(n.intVal)
if optJsBigInt64 in p.config.globalOptions:
r.res.add('n')
else:
r.res = rope(n.intVal)
r.kind = resExpr
@@ -2855,7 +3012,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
var p = newInitProc(globals, m)
attachProc(p, prc)
var disp = generateMethodDispatchers(graph)
var disp = generateMethodDispatchers(graph, m.idgen)
for i in 0..<disp.len:
let prc = disp[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id):

View File

@@ -88,6 +88,8 @@ type
warnUnnamedBreak = "UnnamedBreak",
warnStmtListLambda = "StmtListLambda",
warnBareExcept = "BareExcept",
warnCopyHookForRefc = "CopyHookForRefc",
warnImplicitDefaultValue = "ImplicitDefaultValue",
warnUser = "User",
# hints
hintSuccess = "Success", hintSuccessX = "SuccessX",
@@ -189,6 +191,8 @@ const
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
warnBareExcept: "$1",
warnCopyHookForRefc: "Overriding `=copy` hook is not reliable for refc",
warnImplicitDefaultValue: "$1",
warnUser: "$1",
hintSuccess: "operation successful: $#",
# keep in sync with `testament.isSuccess`

View File

@@ -396,11 +396,12 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) =
if fn.kind notin OverloadableSyms:
internalError(c.config, fn.info, "addOverloadableSymAt")
return
let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(c, fn.info, fn.name.s, check.info)
else:
scope.addSym(fn)
if fn.name.s != "_":
let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(c, fn.info, fn.name.s, check.info)
else:
scope.addSym(fn)
proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
## adds an overloadable symbol on the scope and the interface if appropriate
@@ -546,12 +547,16 @@ proc errorUseQualifier*(c: PContext; info:TLineInfo; choices: PNode) =
errorUseQualifier(c, info, candidates, prefix)
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extra = "") =
var err = "undeclared identifier: '" & name & "'" & extra
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency:\n"
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = ""
var err: string
if name == "_":
err = "the special identifier '_' is ignored in declarations and cannot be used"
else:
err = "undeclared identifier: '" & name & "'" & extra
if c.recursiveDep.len > 0:
err.add "\nThis might be caused by a recursive module dependency:\n"
err.add c.recursiveDep
# prevent excessive errors for 'nim check'
c.recursiveDep = ""
localError(c.config, info, errGenerated, err)
proc errorUndeclaredIdentifierHint*(c: PContext; n: PNode, ident: PIdent): PSym =

View File

@@ -46,3 +46,7 @@ define:useStdoutAsStdmsg
@if nimHasWarnBareExcept:
warningAserror[BareExcept]:on
@end
@if nimHasWarnCopyHookForRefc:
warningAserror[CopyHookForRefc]:on
@end

View File

@@ -102,13 +102,11 @@ type # please make sure we have under 32 options
optBenchmarkVM # Enables cpuTime() in the VM
optProduceAsm # produce assembler code
optPanics # turn panics (sysFatal) into a process termination
optNimV1Emulation # emulate Nim v1.0
optNimV12Emulation # emulate Nim v1.2
optNimV16Emulation # emulate Nim v1.6
optSourcemap
optProfileVM # enable VM profiler
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
optShowNonExportedFields # for documentation: show fields that are not exported
optJsBigInt64 # use bigints for 64-bit integers in JS
TGlobalOptions* = set[TGlobalOption]
@@ -479,7 +477,8 @@ const
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
optTrMacros, optStyleCheck, optCursorInference}
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace}
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
optJsBigInt64}
proc getSrcTimestamp(): DateTime =
try:

View File

@@ -1197,14 +1197,18 @@ proc parseProcExpr(p: var Parser; isExpr: bool; kind: TNodeKind): PNode =
let pragmas = optPragmas(p)
if p.tok.tokType == tkEquals and isExpr:
getTok(p)
skipComment(p, result)
result = newProcNode(kind, info, body = parseStmt(p),
result = newProcNode(kind, info, body = p.emptyNode,
params = params, name = p.emptyNode, pattern = p.emptyNode,
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
skipComment(p, result)
result[bodyPos] = parseStmt(p)
else:
result = newNodeI(if kind == nkIteratorDef: nkIteratorTy else: nkProcTy, info)
if hasSignature:
result.add(params)
if hasSignature or pragmas.kind != nkEmpty:
if hasSignature:
result.add(params)
else: # pragmas but no param list, implies typeclass with pragmas
result.add(p.emptyNode)
if kind == nkFuncDef:
parMessage(p, "func keyword is not allowed in type descriptions, use proc with {.noSideEffect.} pragma instead")
result.add(pragmas)
@@ -2277,13 +2281,19 @@ proc parseTypeDef(p: var Parser): PNode =
setEndInfo()
proc parseVarTuple(p: var Parser): PNode =
#| varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
#| varTupleLhs = '(' optInd (identWithPragma / varTupleLhs) ^+ comma optPar ')'
#| varTuple = varTupleLhs '=' optInd expr
result = newNodeP(nkVarTuple, p)
getTok(p) # skip '('
optInd(p, result)
# progress guaranteed
while p.tok.tokType in {tkSymbol, tkAccent}:
var a = identWithPragma(p, allowDot=true)
while p.tok.tokType in {tkSymbol, tkAccent, tkParLe}:
var a: PNode
if p.tok.tokType == tkParLe:
a = parseVarTuple(p)
a.add(p.emptyNode)
else:
a = identWithPragma(p, allowDot=true)
result.add(a)
if p.tok.tokType != tkComma: break
getTok(p)

View File

@@ -1,6 +1,7 @@
import sem, cgen, modulegraphs, ast, llstream, parser, msgs,
lineinfos, reorder, options, semdata, cgendata, modules, pathutils,
packages, syntaxes, depends, vm, pragmas, idents, lookups
packages, syntaxes, depends, vm, pragmas, idents, lookups, wordrecg,
liftdestructors
import pipelineutils
@@ -176,7 +177,16 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
case graph.pipelinePass
of CgenPass:
if bModule != nil:
finalCodegenActions(graph, BModule(bModule), finalNode)
let disps = finalCodegenActions(graph, BModule(bModule), finalNode)
if disps != nil:
let ctx = preparePContext(graph, module, idgen)
for disp in disps:
let retTyp = disp.sym.typ[0]
if retTyp != nil:
# todo properly semcheck the code of dispatcher?
createTypeBoundOps(graph, ctx, retTyp, disp.info, idgen)
genProcAux(BModule(bModule), disp.sym)
discard closePContext(graph, ctx, nil)
of JSgenPass:
when not defined(leanCompiler):
discard finalJSCodeGen(graph, bModule, finalNode)

View File

@@ -132,7 +132,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
# just in case, should be impossible though
if syms.len == 0:
break
if nextSymIndex > high(syms):
# we have reached the end
break
@@ -293,7 +293,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
const
errTypeMismatch = "type mismatch: got <"
errButExpected = "but expected one of:"
errExpectedPosition = "Expected one of (first mismatch at position [#]):"
errExpectedPosition = "Expected one of (first mismatch at [position]):"
errUndeclaredField = "undeclared field: '$1'"
errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
errBadRoutine = "attempting to call routine: '$1'$2"

View File

@@ -469,6 +469,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
res = t.kind == tyProc and
t.callConv == ccClosure
of "iterator":
# holdover from when `is iterator` didn't work
let t = skipTypes(t1, abstractRange)
res = t.kind == tyProc and
t.callConv == ccClosure and
@@ -1352,6 +1353,12 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
markUsed(c, n.info, s)
onUse(n.info, s)
result = newSymNode(s, n.info)
of skModule:
# make sure type is None and not nil for discard checking
if efWantStmt in flags: s.typ = newTypeS(tyNone, c)
markUsed(c, n.info, s)
onUse(n.info, s)
result = newSymNode(s, n.info)
else:
let info = getCallLineInfo(n)
#if efInCall notin flags:
@@ -1824,7 +1831,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
result.add(n[1])
return semExprNoType(c, result)
of nkPar, nkTupleConstr:
if a.len >= 2:
if a.len >= 2 or a.kind == nkTupleConstr:
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we
# prefer to do these rewritings in transf.nim:
@@ -3078,7 +3085,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
result = semConv(c, n, expectedType)
elif ambig and n.len == 1:
errorUseQualifier(c, n.info, s)
elif n.len == 1 or (n.kind == nkCall and useObjConstr(c, n, flags, expectedType)):
elif n.len == 1:
result = semObjConstr(c, n, flags, expectedType)
elif s.magic == mNone: result = semDirectOp(c, n, flags, expectedType)
else: result = semMagic(c, n, s, flags, expectedType)

View File

@@ -506,12 +506,12 @@ proc semGenericStmt(c: PContext, n: PNode,
result[i] = semGenericStmt(c, n[i], flags, ctx)
if result[0].kind == nkSym:
let fmoduleId = getModule(result[0].sym).id
var isVisible = false
var isVisable = false
for module in c.friendModules:
if module.id == fmoduleId:
isVisible = true
isVisable = true
break
if isVisible:
if isVisable:
for i in 1..<result.len:
if result[i].kind == nkExprColonExpr:
result[i][1].flags.incl nfSkipFieldChecking

View File

@@ -86,6 +86,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
var initValue = semExprFlagDispatched(c, assignment[1], flags, field.typ)
if initValue != nil:
initValue = fitNodeConsiderViewType(c, field.typ, initValue, assignment.info)
initValue.flags.incl nfSkipFieldChecking
assignment[0] = newSymNode(field)
assignment[1] = initValue
assignment.flags.incl nfSem
@@ -412,113 +413,15 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
else:
assert false, "Must not enter here."
type
ObjConstrError = enum
none
discriminatorError = "The discriminator can only be initialized with unnamed fields known at the compile time"
mixingError = "When mixing named fields and unnamed fields, every field needs to be initialized in order"
lackingError = "The object construction is given more fields than required"
proc filterObjConstr(c: PContext; field: PNode, n: PNode, iterField: var int, flags: TExprFlags, write: bool): ObjConstrError =
result = none
if iterField >= n.len:
return mixingError
case field.kind
of nkRecCase:
# handle defaults if the ast of the field is known
var discriminatorVal =
case n[iterField].kind
of nkExprColonExpr:
semExprFlagDispatched(c, n[iterField][1], flags + {efPreferStatic})
else:
semExprFlagDispatched(c, n[iterField], flags + {efPreferStatic})
let ret = filterObjConstr(c, field[0], n, iterField, flags, write)
if ret != none:
return ret
if discriminatorVal == nil or discriminatorVal.kind != nkIntLit:
return discriminatorError
let matchedBranch = field.pickCaseBranch discriminatorVal
if matchedBranch != nil:
result = filterObjConstr(c, matchedBranch.lastSon, n, iterField, flags, write)
else:
result = none
of nkSym:
if n[iterField].kind == nkExprColonExpr and field.sym.name.id == considerQuotedIdent(c, n[iterField][0]).id:
inc iterField
elif not fieldVisible(c, field.sym):
discard
elif n[iterField].kind != nkExprColonExpr:
if write:
n[iterField] = newTree(nkExprColonExpr, field, n[iterField])
inc iterField
else:
result = mixingError
of nkRecList:
for f in field:
let ret = filterObjConstr(c, f, n, iterField, flags, write)
if ret != none:
result = ret
break
else:
assert false
proc expandObjConstr(c: PContext, n: PNode, t: PType, flags: TExprFlags): PNode =
result = n
var hasValue = false
for i in 1..<n.len:
if n[i].kind != nkExprColonExpr:
hasValue = true
break
if hasValue:
var iterField = 1
let ret = filterObjConstr(c, t.n, result, iterField, flags, write = true)
if ret != none:
localError(c.config, result.info, $ret)
else:
if iterField > result.len:
localError(c.config, result.info, $mixingError)
elif iterField < result.len:
localError(c.config, result.info, $lackingError)
proc useObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): bool =
var n = copyTree(n)
var t = semTypeNode(c, n[0], nil)
if t == nil:
return false
if t.skipTypes({tyGenericInst,
tyAlias, tySink, tyOwned, tyRef}).kind != tyObject and
expectedType != nil and expectedType.skipTypes({tyGenericInst,
tyAlias, tySink, tyOwned, tyRef}).kind == tyObject:
t = expectedType
t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
if t.kind == tyRef:
t = skipTypes(t[0], {tyGenericInst, tyAlias, tySink, tyOwned})
if t.kind != tyObject:
return false
for i in 1..<n.len:
if n[i].kind == nkExprColonExpr:
return true
var iterField = 1
result = filterObjConstr(c, t.n, n, iterField, flags, write = false) == none
if iterField != n.len:
return false
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
var t = semTypeNode(c, n[0], nil)
result = newNodeIT(nkObjConstr, n.info, t)
for i in 0..<n.len:
result.add n[i]
if t == nil:
return localErrorNode(c, result, "object constructor needs an object type")
if t.skipTypes({tyGenericInst,
tyAlias, tySink, tyOwned, tyRef}).kind != tyObject and
expectedType != nil and expectedType.skipTypes({tyGenericInst,
@@ -541,10 +444,6 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
"'; the object's generic parameters cannot be inferred and must be explicitly given"
)
let expanded = expandObjConstr(c, n, t, flags)
for i in 0..<expanded.len:
result.add expanded[i]
# Check if the object is fully initialized by recursively testing each
# field (if this is a case object, initialized fields in two different
# branches will be reported as an error):

View File

@@ -396,7 +396,7 @@ proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) =
if sameType(a.graph.excType(aa[i]), a.graph.excType(e)): return
if e.typ != nil:
if optNimV1Emulation in a.config.globalOptions or not isDefectException(e.typ):
if not isDefectException(e.typ):
throws(a.exc, e, comesFrom)
proc addTag(a: PEffects, e, comesFrom: PNode) =

View File

@@ -161,18 +161,19 @@ proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
if result.typ.kind == tyNone:
localError(c.config, result.info, "expression has no type: " &
renderTree(result, {renderNoComments}))
var n = result
while n.kind in skipForDiscardable:
if n.kind == nkTryStmt: n = n[0]
else: n = n.lastSon
var s = "expression '" & $n & "' is of type '" &
result.typ.typeToString & "' and has to be used (or discarded)"
if result.info.line != n.info.line or
result.info.fileIndex != n.info.fileIndex:
s.add "; start of expression here: " & c.config$result.info
if result.typ.kind == tyProc:
s.add "; for a function call use ()"
localError(c.config, n.info, s)
else:
var n = result
while n.kind in skipForDiscardable:
if n.kind == nkTryStmt: n = n[0]
else: n = n.lastSon
var s = "expression '" & $n & "' is of type '" &
result.typ.typeToString & "' and has to be used (or discarded)"
if result.info.line != n.info.line or
result.info.fileIndex != n.info.fileIndex:
s.add "; start of expression here: " & c.config$result.info
if result.typ.kind == tyProc:
s.add "; for a function call use ()"
localError(c.config, n.info, s)
proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
result = n
@@ -583,6 +584,57 @@ proc globalVarInitCheck(c: PContext, n: PNode) =
if n.isLocalVarSym or n.kind in nkCallKinds and usesLocalVar(n):
localError(c.config, n.info, errCannotAssignToGlobal)
proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSymKind, origResult: var PNode): PNode =
## expand tuple unpacking assignments into new var/let/const section
if typ.kind != tyTuple:
localError(c.config, a.info, errXExpected, "tuple")
elif a.len-2 != typ.len:
localError(c.config, a.info, errWrongNumberOfVariables)
var
tmpTuple: PSym
lastDef: PNode
let defkind = if symkind == skConst: nkConstDef else: nkIdentDefs
# temporary not needed if not const and RHS is tuple literal
# const breaks with seqs without temporary
let useTemp = def.kind notin {nkPar, nkTupleConstr} or symkind == skConst
if useTemp:
# use same symkind for compatibility with original section
tmpTuple = newSym(symkind, getIdent(c.cache, "tmpTuple"), nextSymId c.idgen, getCurrOwner(c), n.info)
tmpTuple.typ = typ
tmpTuple.flags.incl(sfGenSym)
lastDef = newNodeI(defkind, a.info)
newSons(lastDef, 3)
lastDef[0] = newSymNode(tmpTuple)
# NOTE: at the moment this is always ast.emptyNode, see parser.nim
lastDef[1] = a[^2]
lastDef[2] = def
tmpTuple.ast = lastDef
addToVarSection(c, origResult, n, lastDef)
result = newNodeI(n.kind, a.info)
for j in 0..<a.len-2:
let name = a[j]
if useTemp and name.kind == nkIdent and name.ident.s == "_":
# skip _ assignments if we are using a temp as they are already evaluated
continue
if name.kind == nkVarTuple:
# nested tuple
lastDef = newNodeI(nkVarTuple, name.info)
newSons(lastDef, name.len)
for k in 0..<name.len-2:
lastDef[k] = name[k]
else:
lastDef = newNodeI(defkind, name.info)
newSons(lastDef, 3)
lastDef[0] = name
lastDef[^2] = c.graph.emptyNode
if useTemp:
lastDef[^1] = newTreeIT(nkBracketExpr, name.info, typ[j], newSymNode(tmpTuple), newIntNode(nkIntLit, j))
else:
var val = def[j]
if val.kind == nkExprColonExpr: val = val[1]
lastDef[^1] = val
result.add(lastDef)
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode
result = copyNode(n)
@@ -649,43 +701,37 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
if a.kind == nkVarTuple:
if tup.kind != tyTuple:
localError(c.config, a.info, errXExpected, "tuple")
elif a.len-2 != tup.len:
localError(c.config, a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info)
newSons(b, a.len)
# keep type desc for doc generator
# NOTE: at the moment this is always ast.emptyNode, see parser.nim
b[^2] = a[^2]
b[^1] = def
addToVarSection(c, result, n, b)
elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
a.kind == nkIdentDefs and a.len > 3:
message(c.config, a.info, warnEachIdentIsTuple)
# generate new section from tuple unpacking and embed it into this one
let assignments = makeVarTupleSection(c, n, a, def, tup, symkind, result)
let resSection = semVarOrLet(c, assignments, symkind)
for resDef in resSection:
addToVarSection(c, result, n, resDef)
else:
if tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
a.len > 3:
# var a, b = (1, 2)
message(c.config, a.info, warnEachIdentIsTuple)
for j in 0..<a.len-2:
if a[j].kind == nkDotExpr:
fillPartialObject(c, a[j],
if a.kind != nkVarTuple: typ else: tup[j])
addToVarSection(c, result, n, a)
continue
var v = semIdentDef(c, a[j], symkind, false)
styleCheckDef(c, v)
onDef(a[j].info, v)
if sfGenSym notin v.flags:
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
else:
if v.owner == nil: v.owner = c.p.owner
when oKeepVariableNames:
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
for j in 0..<a.len-2:
if a[j].kind == nkDotExpr:
fillPartialObject(c, a[j], typ)
addToVarSection(c, result, n, a)
continue
var v = semIdentDef(c, a[j], symkind, false)
styleCheckDef(c, v)
onDef(a[j].info, v)
if sfGenSym notin v.flags:
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
else:
let shadowed = findShadowedVar(c, v)
if shadowed != nil:
shadowed.flags.incl(sfShadowed)
if shadowed.kind == skResult and sfGenSym notin v.flags:
message(c.config, a.info, warnResultShadowed)
if a.kind != nkVarTuple:
if v.owner == nil: v.owner = c.p.owner
when oKeepVariableNames:
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
else:
let shadowed = findShadowedVar(c, v)
if shadowed != nil:
shadowed.flags.incl(sfShadowed)
if shadowed.kind == skResult and sfGenSym notin v.flags:
message(c.config, a.info, warnResultShadowed)
if def.kind != nkEmpty:
if sfThread in v.flags: localError(c.config, def.info, errThreadvarCannotInit)
setVarType(c, v, typ)
@@ -708,35 +754,26 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
b.add copyTree(def)
addToVarSection(c, result, n, b)
v.ast = b
else:
if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
# bug #7663, for 'nim check' this can be a non-tuple:
if tup.kind == tyTuple: setVarType(c, v, tup[j])
else: v.typ = tup
b[j] = newSymNode(v)
if def.kind == nkEmpty:
let actualType = v.typ.skipTypes({tyGenericInst, tyAlias,
tyUserTypeClassInst})
if actualType.kind in {tyObject, tyDistinct} and
actualType.requiresInit:
defaultConstructionError(c, v.typ, v.info)
else:
checkNilable(c, v)
# allow let to not be initialised if imported from C:
if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
localError(c.config, a.info, errLetNeedsInit)
if sfCompileTime in v.flags:
if a.kind != nkVarTuple:
if def.kind == nkEmpty:
let actualType = v.typ.skipTypes({tyGenericInst, tyAlias,
tyUserTypeClassInst})
if actualType.kind in {tyObject, tyDistinct} and
actualType.requiresInit:
defaultConstructionError(c, v.typ, v.info)
else:
checkNilable(c, v)
# allow let to not be initialised if imported from C:
if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
localError(c.config, a.info, errLetNeedsInit)
if sfCompileTime in v.flags:
var x = newNodeI(result.kind, v.info)
x.add result[i]
vm.setupCompileTimeVar(c.module, c.idgen, c.graph, x)
else:
localError(c.config, a.info, "cannot destructure to compile time variable")
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
message(c.config, v.info, hintGlobalVar)
if {sfGlobal, sfPure} <= v.flags:
globalVarInitCheck(c, def)
suggestSym(c.graph, v.info, v, c.graph.usageSym)
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
message(c.config, v.info, hintGlobalVar)
if {sfGlobal, sfPure} <= v.flags:
globalVarInitCheck(c, def)
suggestSym(c.graph, v.info, v, c.graph.usageSym)
proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n)
@@ -789,23 +826,19 @@ proc semConst(c: PContext, n: PNode): PNode =
typeAllowedCheck(c, a.info, typ, skConst, typFlags)
if a.kind == nkVarTuple:
if typ.kind != tyTuple:
localError(c.config, a.info, errXExpected, "tuple")
elif a.len-2 != typ.len:
localError(c.config, a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info)
newSons(b, a.len)
b[^2] = a[^2]
b[^1] = def
# generate new section from tuple unpacking and embed it into this one
let assignments = makeVarTupleSection(c, n, a, def, typ, skConst, result)
let resSection = semConst(c, assignments)
for resDef in resSection:
addToVarSection(c, result, n, resDef)
else:
for j in 0..<a.len-2:
var v = semIdentDef(c, a[j], skConst)
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
styleCheckDef(c, v)
onDef(a[j].info, v)
for j in 0..<a.len-2:
var v = semIdentDef(c, a[j], skConst)
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
elif v.owner == nil: v.owner = getCurrOwner(c)
styleCheckDef(c, v)
onDef(a[j].info, v)
if a.kind != nkVarTuple:
setVarType(c, v, typ)
when false:
v.ast = def # no need to copy
@@ -822,12 +855,7 @@ proc semConst(c: PContext, n: PNode): PNode =
b.add a[1]
b.add copyTree(def)
v.ast = b
else:
setVarType(c, v, typ[j])
v.ast = if def[j].kind != nkExprColonExpr: def[j]
else: def[j][1]
b[j] = newSymNode(v)
addToVarSection(c, result, n, b)
addToVarSection(c, result, n, b)
dec c.inStaticContext
include semfields
@@ -1034,7 +1062,8 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
result = n
n[^2] = semExprNoDeref(c, n[^2], {efWantIterator})
var call = n[^2]
if call.kind == nkStmtListExpr and isTrivalStmtExpr(call):
if call.kind == nkStmtListExpr and (isTrivalStmtExpr(call) or (call.lastSon.kind in nkCallKinds and call.lastSon[0].sym.kind == skIterator)):
call = call.lastSon
n[^2] = call
let isCallExpr = call.kind in nkCallKinds
@@ -1857,6 +1886,8 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
incl(s.flags, sfOverriden)
if name == "=":
message(c.config, n.info, warnDeprecated, "Overriding `=` hook is deprecated; Override `=copy` hook instead")
elif c.config.selectedGC == gcRefc and name == "=copy":
message(c.config, n.info, warnCopyHookForRefc)
let t = s.typ
if t.len == 3 and t[0] == nil and t[1].kind == tyVar:
var obj = t[1][0]
@@ -2275,7 +2306,6 @@ proc semMethod(c: PContext, n: PNode): PNode =
proc semConverterDef(c: PContext, n: PNode): PNode =
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "converter")
checkSonsLen(n, bodyPos + 1, c.config)
result = semProcAux(c, n, skConverter, converterPragmas)
# macros can transform converters to nothing:
if namePos >= result.safeLen: return result
@@ -2290,7 +2320,6 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
addConverterDef(c, LazySym(sym: s))
proc semMacroDef(c: PContext, n: PNode): PNode =
checkSonsLen(n, bodyPos + 1, c.config)
result = semProcAux(c, n, skMacro, macroPragmas)
# macros can transform macros to nothing:
if namePos >= result.safeLen: return result

View File

@@ -130,8 +130,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
e.typ = result
e.position = int(counter)
let symNode = newSymNode(e)
if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil and
c.config.cmd notin cmdDocLike: # A hack to produce documentation for enum fields.
if identToReplace != nil and c.config.cmd notin cmdDocLike:
# A hack to produce documentation for enum fields.
identToReplace[] = symNode
if e.position == 0: hasNull = true
if result.sym != nil and sfExported in result.sym.flags:
@@ -803,8 +803,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
else: illFormedAst(n, c.config)
if c.inGenericContext > 0:
# use a new check intset here for each branch:
var newCheck: IntSet
assign(newCheck, check)
var newCheck: IntSet = check
var newPos = pos
var newf = newNodeI(nkRecList, n.info)
semRecordNodeAux(c, it[idx], newCheck, newPos, newf, rectype, hasCaseFields)
@@ -1311,6 +1310,16 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if hasDefault:
def = a[^1]
if a.len > 3:
var msg = ""
for j in 0 ..< a.len - 2:
if msg.len != 0: msg.add(", ")
msg.add($a[j])
msg.add(" all have default value '")
msg.add(def.renderTree)
msg.add("', this may be unintentional, " &
"either use ';' (semicolon) or explicitly write each default value")
message(c.config, a.info, warnImplicitDefaultValue, msg)
block determineType:
var defTyp = typ
if genericParams != nil and genericParams.len > 0:
@@ -1359,6 +1368,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
for j in 0..<a.len-2:
var arg = newSymG(skParam, if a[j].kind == nkPragmaExpr: a[j][0] else: a[j], c)
if arg.name.s == "_":
arg.flags.incl(sfGenSym)
elif containsOrIncl(check, arg.name.id):
localError(c.config, a[j].info, "attempt to redefine: '" & arg.name.s & "'")
if a[j].kind == nkPragmaExpr:
pragma(c, arg, a[j][1], paramPragmas)
if not hasType and not hasDefault and kind notin {skTemplate, skMacro}:
@@ -1367,8 +1380,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
else:
localError(c.config, a.info, "parameter '$1' requires a type" % arg.name.s)
typ = errorType(c)
var nameForLift = arg.name.s
if sfGenSym in arg.flags:
nameForLift.add("`gensym" & $arg.id)
let lifted = liftParamType(c, kind, genericParams, typ,
arg.name.s, arg.info)
nameForLift, arg.info)
let finalType = if lifted != nil: lifted else: typ.skipIntLit(c.idgen)
arg.typ = finalType
arg.position = counter
@@ -1376,17 +1392,12 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
inc(counter)
if def != nil and def.kind != nkEmpty:
arg.ast = copyTree(def)
if arg.name.s == "_":
arg.flags.incl(sfGenSym)
elif containsOrIncl(check, arg.name.id):
localError(c.config, a[j].info, "attempt to redefine: '" & arg.name.s & "'")
result.n.add newSymNode(arg)
rawAddSon(result, finalType)
addParamOrResult(c, arg, kind)
styleCheckDef(c, a[j].info, arg)
onDef(a[j].info, arg)
if {optNimV1Emulation, optNimV12Emulation} * c.config.globalOptions == {}:
a[j] = newSymNode(arg)
a[j] = newSymNode(arg)
var r: PType
if n[0].kind != nkEmpty:
@@ -1748,7 +1759,7 @@ proc semProcTypeWithScope(c: PContext, n: PNode,
if n[1].kind != nkEmpty and n[1].len > 0:
pragma(c, s, n[1], procTypePragmas)
when useEffectSystem: setEffectsForProcType(c.graph, result, n[1])
elif c.optionStack.len > 0 and optNimV1Emulation notin c.config.globalOptions:
elif c.optionStack.len > 0:
# we construct a fake 'nkProcDef' for the 'mergePragmas' inside 'implicitPragmas'...
s.ast = newTree(nkProcDef, newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info),
newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info))
@@ -2043,25 +2054,27 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkOutTy: result = semVarOutType(c, n, prev, {tfIsOutParam})
of nkDistinctTy: result = semDistinct(c, n, prev)
of nkStaticTy: result = semStaticType(c, n[0], prev)
of nkIteratorTy:
if n.len == 0:
of nkProcTy, nkIteratorTy:
if n.len == 0 or n[0].kind == nkEmpty:
# 0 length or empty param list with possible pragmas imply typeclass
result = newTypeS(tyBuiltInTypeClass, c)
let child = newTypeS(tyProc, c)
child.flags.incl tfIterator
var symKind: TSymKind
if n.kind == nkIteratorTy:
child.flags.incl tfIterator
if n.len > 0 and n[1].kind != nkEmpty and n[1].len > 0:
# typeclass with pragma
let symKind = if n.kind == nkIteratorTy: skIterator else: skProc
# dummy symbol for `pragma`:
var s = newSymS(symKind, newIdentNode(getIdent(c.cache, "dummy"), n.info), c)
s.typ = child
# for now only call convention pragmas supported in proc typeclass
pragma(c, s, n[1], {FirstCallConv..LastCallConv})
result.addSonSkipIntLit(child, c.idgen)
else:
result = semProcTypeWithScope(c, n, prev, skIterator)
if result.kind == tyProc:
result.flags.incl(tfIterator)
if n.lastSon.kind == nkPragma and hasPragma(n.lastSon, wInline):
result.callConv = ccInline
else:
result.callConv = ccClosure
of nkProcTy:
if n.len == 0:
result = newConstraint(c, tyProc)
else:
result = semProcTypeWithScope(c, n, prev, skProc)
if n.kind == nkIteratorTy and result.kind == tyProc:
result.flags.incl(tfIterator)
of nkEnumTy: result = semEnum(c, n, prev)
of nkType: result = n.typ
of nkStmtListType: result = semStmtListType(c, n, prev)

View File

@@ -204,7 +204,7 @@ proc hasValuelessStatics(n: PNode): bool =
proc doThing(_: MyThing)
]#
if n.safeLen == 0:
n.typ.kind == tyStatic
n.typ == nil or n.typ.kind == tyStatic
else:
for x in n:
if hasValuelessStatics(x):

View File

@@ -9,11 +9,10 @@
## Computes hash values for routine (proc, method etc) signatures.
import ast, tables, ropes, md5, modulegraphs, options, msgs, packages, pathutils
import ast, tables, ropes, md5, modulegraphs, options, msgs, pathutils
from hashes import Hash
import types
import std/os
when defined(nimPreviewSlimSystem):
import std/assertions

View File

@@ -624,6 +624,9 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
if f.len != a.len: return
result = isEqual # start with maximum; also correct for no
# params at all
if f.flags * {tfIterator} != a.flags * {tfIterator}:
return isNone
template checkParam(f, a) =
result = minRel(result, procParamTypeRel(c, f, a))
@@ -1295,7 +1298,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyNil: result = isNone
else: discard
of tyOrdinal:
if isOrdinalType(a, allowEnumWithHoles = optNimV1Emulation in c.c.config.globalOptions):
if isOrdinalType(a):
var x = if a.kind == tyOrdinal: a[0] else: a
if f[0].kind == tyNone:
result = isGeneric
@@ -1636,13 +1639,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyBuiltInTypeClass:
considerPreviousT:
let targetKind = f[0].kind
let target = f[0]
let targetKind = target.kind
let effectiveArgType = a.skipTypes({tyRange, tyGenericInst,
tyBuiltInTypeClass, tyAlias, tySink, tyOwned})
let typeClassMatches = targetKind == effectiveArgType.kind and
not effectiveArgType.isEmptyContainer
if typeClassMatches or
(targetKind in {tyProc, tyPointer} and effectiveArgType.kind == tyNil):
if targetKind == effectiveArgType.kind:
if effectiveArgType.isEmptyContainer:
return isNone
if targetKind == tyProc:
if target.flags * {tfIterator} != effectiveArgType.flags * {tfIterator}:
return isNone
if tfExplicitCallConv in target.flags and
target.callConv != effectiveArgType.callConv:
return isNone
put(c, f, a)
return isGeneric
else:

View File

@@ -1686,7 +1686,7 @@ proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool =
of tyTuple:
var cycleDetectorCopy: IntSet
for i in 0..<t.len:
assign(cycleDetectorCopy, cycleDetector)
cycleDetectorCopy = cycleDetector
if isTupleRecursive(t[i], cycleDetectorCopy):
return true
of tyAlias, tyRef, tyPtr, tyGenericInst, tyVar, tyLent, tySink,

View File

@@ -64,9 +64,8 @@ proc renderType(n: PNode, toNormalize: bool): string =
result = "ptr"
of nkProcTy:
assert n.len != 1
if n.len > 1:
if n.len > 1 and n[0].kind == nkFormalParams:
let params = n[0]
assert params.kind == nkFormalParams
assert params.len > 0
result = "proc("
for i in 1..<params.len: result.add(renderType(params[i], toNormalize) & ',')

View File

@@ -38,7 +38,6 @@ when defined(nimPreviewSlimSystem):
else:
from std/formatfloat import addFloatRoundtrip, addFloatSprintf
from std/strutils import formatBiggestFloat, FloatFormatMode
# There are some useful procs in vmconv.
import vmconv, vmmarshal

View File

@@ -169,9 +169,10 @@ Advanced options:
enable experimental language feature
--legacy:$2
enable obsolete/legacy language feature
--useVersion:1.0|1.2|1.6 emulate Nim version X of the Nim compiler, for testing
--benchmarkVM:on|off turn benchmarking of VM code with cpuTime() on|off
--profileVM:on|off turn compile time VM profiler on|off
--sinkInference:on|off turn sink parameter inference on|off (default: off)
--panics:on|off turn panics into process terminations (default: off)
--deepcopy:on|off enable 'system.deepCopy' for ``--mm:arc|orc``
--jsbigint64:on|off toggle the use of [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
for 64-bit integers on the JavaScript backend (default: on)

View File

@@ -1348,7 +1348,7 @@ Generic parameters are treated in the type, not the ``proc`` itself.
Concrete syntax:
```nim
type MyProc[T] = proc(x: T)
type MyProc[T] = proc(x: T) {.nimcall.}
```
AST:
@@ -1363,7 +1363,8 @@ AST:
nnkProcTy( # behaves like a procedure declaration from here on
nnkFormalParams(
# ...
)
),
nnkPragma(nnkIdent("nimcall"))
)
)
```
@@ -1371,6 +1372,37 @@ AST:
The same syntax applies to ``iterator`` (with ``nnkIteratorTy``), but
*does not* apply to ``converter`` or ``template``.
Type class versions of these nodes generally share the same node kind but
without any child nodes. The ``tuple`` type class is represented by
``nnkTupleClassTy``, while a ``proc`` or ``iterator`` type class with pragmas
has an ``nnkEmpty`` node in place of the ``nnkFormalParams`` node of a
concrete ``proc`` or ``iterator`` type node.
```nim
type TypeClass = proc {.nimcall.} | ref | tuple
```
AST:
```nim
nnkTypeDef(
nnkIdent("TypeClass"),
nnkEmpty(),
nnkInfix(
nnkIdent("|"),
nnkProcTy(
nnkEmpty(),
nnkPragma(nnkIdent("nimcall"))
),
nnkInfix(
nnkIdent("|"),
nnkRefTy(),
nnkTupleClassTy()
)
)
)
```
Mixin statement
---------------

View File

@@ -187,7 +187,8 @@ conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
&IND{>} stmt
typeDef = identVisDot genericParamList? pragma '=' optInd typeDefValue
indAndComment?
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
varTupleLhs = '(' optInd (identWithPragma / varTupleLhs) ^+ comma optPar ')'
varTuple = varTupleLhs '=' optInd expr
colonBody = colcom stmt postExprBlocks?
variable = (varTuple / identColonEquals) colonBody? indAndComment
constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment

View File

@@ -47,17 +47,17 @@ Core
Provides a series of low-level methods for bit manipulation.
* [compilesettings](compilesettings.html)
This module allows querying the compiler about diverse configuration settings.
Querying the compiler about diverse configuration settings from code.
* [cpuinfo](cpuinfo.html)
This module implements procs to determine the number of CPUs / cores.
Procs to determine the number of CPUs / cores.
* [effecttraits](effecttraits.html)
This module provides access to the inferred .raises effects
Access to the inferred .raises effects
for Nim's macro system.
* [endians](endians.html)
This module contains helpers that deal with different byte orders.
Helpers that deal with different byte orders.
* [locks](locks.html)
Locks and condition variables for Nim.
@@ -75,10 +75,10 @@ Core
Provides (unsafe) access to Nim's run-time type information.
* [typetraits](typetraits.html)
This module defines compile-time reflection procs for working with types.
Compile-time reflection procs for working with types.
* [volatile](volatile.html)
This module contains code for generating volatile loads and stores,
Code for generating volatile loads and stores,
which are useful in embedded and systems programming.
@@ -86,24 +86,24 @@ Algorithms
----------
* [algorithm](algorithm.html)
This module implements some common generic algorithms like sort or binary search.
Some common generic algorithms like sort or binary search.
* [enumutils](enumutils.html)
This module adds functionality for the built-in `enum` type.
Additional functionality for the built-in `enum` type.
* [sequtils](sequtils.html)
This module implements operations for the built-in `seq` type
Operations for the built-in `seq` type
which were inspired by functional programming languages.
* [setutils](setutils.html)
This module adds functionality for the built-in `set` type.
Additional functionality for the built-in `set` type.
Collections
-----------
* [critbits](critbits.html)
This module implements a *crit bit tree* which is an efficient
A *crit bit tree* which is an efficient
container for a sorted set of strings, or a sorted mapping of strings.
* [deques](deques.html)
@@ -127,7 +127,7 @@ Collections
Efficient implementation of a set of ordinals as a sparse bit set.
* [ropes](ropes.html)
This module contains support for a *rope* data type.
A *rope* data type.
Ropes can represent very long strings efficiently;
in particular, concatenation is done in O(1) instead of O(n).
@@ -150,7 +150,7 @@ String handling
Utilities for `cstring` handling.
* [editdistance](editdistance.html)
This module contains an algorithm to compute the edit distance between two
An algorithm to compute the edit distance between two
Unicode strings.
* [encodings](encodings.html)
@@ -158,35 +158,37 @@ String handling
the `iconv` library, on Windows the Windows API.
* [formatfloat](formatfloat.html)
This module implements formatting floats as strings.
Formatting floats as strings.
* [objectdollar](objectdollar.html)
This module implements a generic `$` operator to convert objects to strings.
A generic `$` operator to convert objects to strings.
* [punycode](punycode.html)
Implements a representation of Unicode with the limited ASCII character subset.
* [strbasics](strbasics.html)
This module provides some high performance string operations.
Some high performance string operations.
* [strformat](strformat.html)
Macro based standard string interpolation/formatting. Inspired by
Python's f-strings.
Python's f-strings.\
**Note:** if you need templating, consider using Nim
[Source Code Filters (SCF)](filters.html).
* [strmisc](strmisc.html)
This module contains uncommon string handling operations that do not
fit with the commonly used operations in strutils.
Uncommon string handling operations that do not
fit with the commonly used operations in [strutils](strutils.html).
* [strscans](strscans.html)
This module contains a `scanf` macro for convenient parsing of mini languages.
A `scanf` macro for convenient parsing of mini languages.
* [strutils](strutils.html)
This module contains common string handling operations like changing
Common string handling operations like changing
case of a string, splitting a string into substrings, searching for
substrings, replacing substrings.
* [unicode](unicode.html)
This module provides support to handle the Unicode UTF-8 encoding.
Support for handling the Unicode UTF-8 encoding.
* [unidecode](unidecode.html)
It provides a single proc that does Unicode to ASCII transliterations.
@@ -196,7 +198,7 @@ String handling
Nim support for C/C++'s wide strings.
* [wordwrap](wordwrap.html)
This module contains an algorithm to wordwrap a Unicode string.
An algorithm for word-wrapping Unicode strings.
Time handling
@@ -213,17 +215,16 @@ Generic Operating System Services
---------------------------------
* [appdirs](appdirs.html)
This module implements helpers for determining special directories used by apps.
Helpers for determining special directories used by apps.
* [cmdline](cmdline.html)
This module contains system facilities for reading command
line parameters.
System facilities for reading command line parameters.
* [dirs](dirs.html)
This module implements directory handling.
Directory handling.
* [distros](distros.html)
This module implements the basics for OS distribution ("distro") detection
Basics for OS distribution ("distro") detection
and the OS's native package manager.
Its primary purpose is to produce output for Nimble packages,
but it also contains the widely used **Distribution** enum
@@ -231,19 +232,19 @@ Generic Operating System Services
See [packaging](packaging.html) for hints on distributing Nim using OS packages.
* [dynlib](dynlib.html)
This module implements the ability to access symbols from shared libraries.
Accessing symbols from shared libraries.
* [envvars](envvars.html)
This module implements environment variable handling.
Environment variable handling.
* [exitprocs](exitprocs.html)
This module allows adding hooks to program exit.
Adding hooks to program exit.
* [files](files.html)
This module implements file handling.
File handling.
* [memfiles](memfiles.html)
This module provides support for memory-mapped files (Posix's `mmap`)
Support for memory-mapped files (Posix's `mmap`)
on the different operating systems.
* [os](os.html)
@@ -252,52 +253,50 @@ Generic Operating System Services
commands, etc.
* [oserrors](oserrors.html)
This module implements OS error reporting.
OS error reporting.
* [osproc](osproc.html)
Module for process communication beyond `os.execShellCmd`.
* [paths](paths.html)
This module implements path handling.
Path handling.
* [reservedmem](reservedmem.html)
This module provides utilities for reserving portions of the
Utilities for reserving portions of the
address space of a program without consuming physical memory.
* [streams](streams.html)
This module provides a stream interface and two implementations thereof:
A stream interface and two implementations thereof:
the `FileStream` and the `StringStream` which implement the stream
interface for Nim file objects (`File`) and strings. Other modules
may provide other implementations for this standard stream interface.
* [symlinks](symlinks.html)
This module implements symlink handling.
Symlink handling.
* [syncio](syncio.html)
This module implements various synchronized I/O operations.
Various synchronized I/O operations.
* [terminal](terminal.html)
This module contains a few procedures to control the *terminal*
(also called *console*). The implementation simply uses ANSI escape
sequences and does not depend on any other module.
A module to control the terminal output (also called *console*).
* [tempfiles](tempfiles.html)
This module provides some utils to generate temporary path names and
create temporary files and directories.
Some utilities for generating temporary path names and
creating temporary files and directories.
Math libraries
--------------
* [complex](complex.html)
This module implements complex numbers and relevant mathematical operations.
Complex numbers and relevant mathematical operations.
* [fenv](fenv.html)
Floating-point environment. Handling of floating-point rounding and
exceptions (overflow, zero-divide, etc.).
* [lenientops](lenientops.html)
Provides binary operators for mixed integer/float expressions for convenience.
Binary operators for mixed integer/float expressions for convenience.
* [math](math.html)
Mathematical operations like cosine, square root.
@@ -306,7 +305,7 @@ Math libraries
Fast and tiny random number generator.
* [rationals](rationals.html)
This module implements rational numbers and relevant mathematical operations.
Rational numbers and relevant mathematical operations.
* [stats](stats.html)
Statistical analysis.
@@ -322,75 +321,69 @@ Internet Protocols and Support
Exports `asyncmacro` and `asyncfutures` for native backends, and `asyncjs` on the JS backend.
* [asyncdispatch](asyncdispatch.html)
This module implements an asynchronous dispatcher for IO operations.
An asynchronous dispatcher for IO operations.
* [asyncfile](asyncfile.html)
This module implements asynchronous file reading and writing using
`asyncdispatch`.
An asynchronous file reading and writing using `asyncdispatch`.
* [asyncftpclient](asyncftpclient.html)
This module implements an asynchronous FTP client using the `asyncnet`
module.
An asynchronous FTP client using the `asyncnet` module.
* [asynchttpserver](asynchttpserver.html)
This module implements an asynchronous HTTP server using the `asyncnet`
module.
An asynchronous HTTP server using the `asyncnet` module.
* [asyncmacro](asyncmacro.html)
Implements the `async` and `multisync` macros for `asyncdispatch`.
`async` and `multisync` macros for `asyncdispatch`.
* [asyncnet](asyncnet.html)
This module implements asynchronous sockets based on the `asyncdispatch`
module.
Asynchronous sockets based on the `asyncdispatch` module.
* [asyncstreams](asyncstreams.html)
This module provides `FutureStream` - a future that acts as a queue.
`FutureStream` - a future that acts as a queue.
* [cgi](cgi.html)
This module implements helpers for CGI applications.
Helpers for CGI applications.
* [cookies](cookies.html)
This module contains helper procs for parsing and generating cookies.
Helper procs for parsing and generating cookies.
* [httpclient](httpclient.html)
This module implements a simple HTTP client which supports both synchronous
A simple HTTP client with support for both synchronous
and asynchronous retrieval of web pages.
* [mimetypes](mimetypes.html)
This module implements a mimetypes database.
A mimetypes database.
* [nativesockets](nativesockets.html)
This module implements a low-level sockets API.
A low-level sockets API.
* [net](net.html)
This module implements a high-level sockets API. It replaces the
`sockets` module.
A high-level sockets API.
* [selectors](selectors.html)
This module implements a selector API with backends specific to each OS.
Currently, epoll on Linux and select on other operating systems.
A selector API with backends specific to each OS.
Supported OS primitives: `epoll`, `kqueue`, `poll`, and `select` on Windows.
* [smtp](smtp.html)
This module implements a simple SMTP client.
A simple SMTP client with support for both synchronous and asynchronous operation.
* [socketstreams](socketstreams.html)
This module provides an implementation of the streams interface for sockets.
An implementation of the streams interface for sockets.
* [uri](uri.html)
This module provides functions for working with URIs.
Functions for working with URIs and URLs.
Threading
---------
* [isolation](isolation.html)
This module implements the `Isolated[T]` type for
The `Isolated[T]` type for
safe construction of isolated subgraphs that can be
passed efficiently to different channels and threads.
* [tasks](tasks.html)
This module provides basic primitives for creating parallel programs.
Basic primitives for creating parallel programs.
* [threadpool](threadpool.html)
Implements Nim's [spawn](manual_experimental.html#parallel-amp-spawn).
@@ -403,13 +396,13 @@ Parsers
-------
* [htmlparser](htmlparser.html)
This module parses an HTML document and creates its XML tree representation.
HTML document parser that creates a XML tree representation.
* [json](json.html)
High-performance JSON parser.
* [lexbase](lexbase.html)
This is a low-level module that implements an extremely efficient buffering
A low-level module that implements an extremely efficient buffering
scheme for lexers and parsers. This is used by the diverse parsing modules.
* [parsecfg](parsecfg.html)
@@ -423,7 +416,7 @@ Parsers
The `parsecsv` module implements a simple high-performance CSV parser.
* [parsejson](parsejson.html)
This module implements a JSON parser. It is used and exported by the [json](json.html) module, but can also be used in its own right.
A JSON parser. It is used and exported by the [json](json.html) module, but can also be used in its own right.
* [parseopt](parseopt.html)
The `parseopt` module implements a command line option parser.
@@ -432,7 +425,7 @@ Parsers
The `parsesql` module implements a simple high-performance SQL parser.
* [parseutils](parseutils.html)
This module contains helpers for parsing tokens, numbers, identifiers, etc.
Helpers for parsing tokens, numbers, identifiers, etc.
* [parsexml](parsexml.html)
The `parsexml` module implements a simple high performance XML/HTML parser.
@@ -441,7 +434,7 @@ Parsers
web can be parsed with it.
* [pegs](pegs.html)
This module contains procedures and operators for handling PEGs.
Procedures and operators for handling PEGs.
Docutils
@@ -453,14 +446,14 @@ Docutils
The interface supports one language nested in another.
* [packages/docutils/rst](rst.html)
This module implements a reStructuredText parser. A large subset
A reStructuredText parser. A large subset
is implemented. Some features of the markdown wiki syntax are also supported.
* [packages/docutils/rstast](rstast.html)
This module implements an AST for the reStructuredText parser.
An AST for the reStructuredText parser.
* [packages/docutils/rstgen](rstgen.html)
This module implements a generator of HTML/Latex from reStructuredText.
A generator of HTML/Latex from reStructuredText.
XML Processing
@@ -471,17 +464,17 @@ XML Processing
contains a macro for XML/HTML code generation.
* [xmlparser](xmlparser.html)
This module parses an XML document and creates its XML tree representation.
XML document parser that creates a XML tree representation.
Generators
----------
* [genasts](genasts.html)
This module implements AST generation using captured variables for macros.
AST generation using captured variables for macros.
* [htmlgen](htmlgen.html)
This module implements a simple XML and HTML code
A simple XML and HTML code
generator. Each commonly used HTML tag has a corresponding macro
that generates a string with its HTML representation.
@@ -490,14 +483,13 @@ Hashing
-------
* [base64](base64.html)
This module implements a Base64 encoder and decoder.
A Base64 encoder and decoder.
* [hashes](hashes.html)
This module implements efficient computations of hash values for diverse
Nim types.
Efficient computations of hash values for diverse Nim types.
* [md5](md5.html)
This module implements the MD5 checksum algorithm.
The MD5 checksum algorithm.
* [oids](oids.html)
An OID is a global ID that consists of a timestamp,
@@ -505,14 +497,14 @@ Hashing
produce a globally distributed unique ID.
* [sha1](sha1.html)
This module implements the SHA-1 checksum algorithm.
The SHA-1 checksum algorithm.
Serialization
-------------
* [jsonutils](jsonutils.html)
This module implements a hookable (de)serialization for arbitrary types
Hookable (de)serialization for arbitrary types
using JSON.
* [marshal](marshal.html)
@@ -524,35 +516,35 @@ Miscellaneous
-------------
* [assertions](assertions.html)
This module implements assertion handling.
Assertion handling.
* [browsers](browsers.html)
This module implements procs for opening URLs with the user's default
Procs for opening URLs with the user's default
browser.
* [colors](colors.html)
This module implements color handling for Nim.
Color handling.
* [coro](coro.html)
This module implements experimental coroutines in Nim.
Experimental coroutines in Nim.
* [decls](decls.html)
This module implements syntax sugar for some declarations.
Syntax sugar for some declarations.
* [enumerate](enumerate.html)
This module implements `enumerate` syntactic sugar based on Nim's macro system.
`enumerate` syntactic sugar based on Nim's macro system.
* [importutils](importutils.html)
Utilities related to import and symbol resolution.
* [logging](logging.html)
This module implements a simple logger.
A simple logger.
* [segfaults](segfaults.html)
Turns access violations or segfaults into a `NilAccessDefect` exception.
* [sugar](sugar.html)
This module implements nice syntactic sugar based on Nim's macro system.
Nice syntactic sugar based on Nim's macro system.
* [unittest](unittest.html)
Implements a Unit testing DSL.
@@ -561,10 +553,10 @@ Miscellaneous
Decode variable-length integers that are compatible with SQLite.
* [with](with.html)
This module implements the `with` macro for easy function chaining.
The `with` macro for easy function chaining.
* [wrapnils](wrapnils.html)
This module allows evaluating expressions safely against nil dereferences.
Allows evaluating expressions safely against nil dereferences.
Modules for the JavaScript backend
@@ -603,12 +595,12 @@ Regular expressions
-------------------
* [re](re.html)
This module contains procedures and operators for handling regular
Procedures and operators for handling regular
expressions. The current implementation uses PCRE.
* [nre](nre.html)
This module contains many help functions for handling regular expressions.
Many help functions for handling regular expressions.
The current implementation uses PCRE.
Database support
@@ -635,7 +627,7 @@ Generic Operating System Services
---------------------------------
* [rdstdin](rdstdin.html)
This module contains code for reading from stdin.
Code for reading user input from stdin.
Wrappers
@@ -649,7 +641,7 @@ Windows-specific
----------------
* [winlean](winlean.html)
Contains a wrapper for a small subset of the Win32 API.
Wrapper for a small subset of the Win32 API.
* [registry](registry.html)
Windows registry support.
@@ -658,7 +650,7 @@ UNIX specific
-------------
* [posix](posix.html)
Contains a wrapper for the POSIX standard.
Wrapper for the POSIX standard.
* [posix_utils](posix_utils.html)
Contains helpers for the POSIX standard or specialized for Linux and BSDs.
@@ -674,13 +666,13 @@ Database support
----------------
* [mysql](mysql.html)
Contains a wrapper for the mySQL API.
Wrapper for the mySQL API.
* [odbcsql](odbcsql.html)
interface to the ODBC driver.
* [postgres](postgres.html)
Contains a wrapper for the PostgreSQL API.
Wrapper for the PostgreSQL API.
* [sqlite3](sqlite3.html)
Contains a wrapper for the SQLite 3 API.
Wrapper for the SQLite 3 API.
Network Programming and Internet Protocols

View File

@@ -1828,23 +1828,6 @@ an `object` type or a `ref object` type:
Note that, unlike tuples, objects require the field names along with their values.
For a `ref object` type `system.new` is invoked implicitly.
The field names can be omitted if all the values are given in order. It can be mixed with field names along with values.
```nim
var a1 = Student("Anton", 5)
var a2 = PStudent("Anton", age: 5)
```
Note that, objects with only one field must use field names along with values. Otherwise, they will be recognized as type conversions.
```nim
type
Teacher = object
name: string
# var t = Teacher("lisa") # Error: type mismatch: got 'string' for '"lisa"'
# but expected 'Teacher = object'
var t = Teacher(name: "lisa")
```
Object variants
---------------
@@ -3093,12 +3076,25 @@ when they are declared. The only exception to this is if the `{.importc.}`
pragma (or any of the other `importX` pragmas) is applied, in this case the
value is expected to come from native code, typically a C/C++ `const`.
Special identifier `_` (underscore)
-----------------------------------
The identifier `_` has a special meaning in declarations.
Any definition with the name `_` will not be added to scope, meaning the
definition is evaluated, but cannot be used. As a result the name `_` can be
indefinitely redefined.
```nim
let _ = 123
echo _ # error
let _ = 456 # compiles
```
Tuple unpacking
---------------
In a `var` or `let` statement tuple unpacking can be performed. The special
identifier `_` can be used to ignore some parts of the tuple:
In a `var`, `let` or `const` statement tuple unpacking can be performed.
The special identifier `_` can be used to ignore some parts of the tuple:
```nim
proc returnsTuple(): (int, int, int) = (4, 2, 3)
@@ -3106,6 +3102,35 @@ identifier `_` can be used to ignore some parts of the tuple:
let (x, _, z) = returnsTuple()
```
This is treated as syntax sugar for roughly the following:
```nim
let
tmpTuple = returnsTuple()
x = tmpTuple[0]
z = tmpTuple[2]
```
For `var` or `let` statements, if the value expression is a tuple literal,
each expression is directly expanded into an assignment without the use of
a temporary variable.
```nim
let (x, y, z) = (1, 2, 3)
# becomes
let
x = 1
y = 2
z = 3
```
Tuple unpacking can also be nested:
```nim
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
let (x, (_, y), _, z) = returnsNestedTuple()
```
Const section
@@ -3791,15 +3816,6 @@ every time the function is called.
proc foo(a: int, b: int = 47): int
```
Just as the comma propagates the types from right to left until the
first parameter or until a semicolon is hit, it also propagates the
default value starting from the parameter declared with it.
```nim
# Both a and b are optional with 47 as their default values.
proc foo(a, b: int = 47): int
```
Parameters can be declared mutable and so allow the proc to modify those
arguments, by using the type modifier `var`.
@@ -5451,9 +5467,9 @@ type class matches
================== ===================================================
`object` any object type
`tuple` any tuple type
`enum` any enumeration
`proc` any proc type
`iterator` any iterator type
`ref` any `ref` type
`ptr` any `ptr` type
`var` any `var` type
@@ -5513,6 +5529,17 @@ as `type constraints`:idx: of the generic type parameter:
onlyIntOrString("xy", 50) # invalid as 'T' cannot be both at the same time
```
`proc` and `iterator` type classes also accept a calling convention pragma
to restrict the calling convention of the matching `proc` or `iterator` type.
```nim
proc onlyClosure[T: proc {.closure.}](x: T) = discard
onlyClosure(proc() = echo "hello") # valid
proc foo() {.nimcall.} = discard
onlyClosure(foo) # type mismatch
```
Implicit generics
-----------------

View File

@@ -229,6 +229,14 @@ proc buildTools(args: string = "") =
nimCompileFold("Compile atlas", "tools/atlas/atlas.nim", options = "-d:release " & args,
outputName = "atlas")
proc testTools(args: string = "") =
nimCompileFold("Compile nimgrep", "tools/nimgrep.nim",
options = "-d:release " & args)
when defined(windows): buildVccTool(args)
bundleNimpretty(args)
nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release " & args)
nimCompileFold("Compile atlas", "tools/atlas/atlas.nim", options = "-d:release " & args,
outputName = "atlas")
proc nsis(latest: bool; args: string) =
bundleNimbleExe(latest, args)
@@ -546,7 +554,7 @@ proc runCI(cmd: string) =
nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release")
execFold("Test selected Nimble packages", "testament $# pcat nimble-packages" % batchParam)
else:
buildTools()
testTools()
for a in "zip opengl sdl1 jester@#head".split:
let buildDeps = "build"/"deps" # xxx factor pending https://github.com/timotheecour/Nim/issues/616

View File

@@ -947,6 +947,8 @@ proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indent
discard # same as nil node in this representation
of nnkCharLit .. nnkInt64Lit:
res.add(" " & $n.intVal)
of nnkUIntLit .. nnkUInt64Lit:
res.add(" " & $cast[uint64](n.intVal))
of nnkFloatLit .. nnkFloat64Lit:
res.add(" " & $n.floatVal)
of nnkStrLit .. nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:

View File

@@ -13,7 +13,7 @@
## specific requirements and solely targets JavaScript, you should be using
## the relevant functions in the `math`, `json`, and `times` stdlib
## modules instead.
import std/private/since
import std/private/[since, jsutils]
when not defined(js):
{.error: "This module only works on the JavaScript platform".}
@@ -74,9 +74,16 @@ proc parse*(d: DateLib, s: cstring): int {.importcpp.}
proc newDate*(): DateTime {.
importcpp: "new Date()".}
proc newDate*(date: int|int64|string): DateTime {.
proc newDate*(date: int|string): DateTime {.
importcpp: "new Date(#)".}
whenJsNoBigInt64:
proc newDate*(date: int64): DateTime {.
importcpp: "new Date(#)".}
do:
proc newDate*(date: int64): DateTime {.
importcpp: "new Date(Number(#))".}
proc newDate*(year, month, day, hours, minutes,
seconds, milliseconds: int): DateTime {.
importcpp: "new Date(#,#,#,#,#,#,#)".}

View File

@@ -350,7 +350,7 @@ type
footnoteAnchor = "footnote anchor",
headlineAnchor = "implicitly-generated headline anchor"
AnchorSubst = object
info: TLineInfo # where the anchor was defined
info: TLineInfo # the file where the anchor was defined
priority: int
case kind: range[arInternalRst .. arNim]
of arInternalRst:
@@ -360,6 +360,7 @@ type
anchorTypeExt: RstAnchorKind
refnameExt: string
of arNim:
module: FileIndex # anchor's module (generally not the same as file)
tooltip: string # displayed tooltip for Nim-generated anchors
langSym: LangSymbol
refname: string # A reference name that will be inserted directly
@@ -520,6 +521,9 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string =
proc getFilename(s: PRstSharedState, subst: AnchorSubst): string =
getFilename(s.filenames, subst.info.fileIndex)
proc getModule(s: PRstSharedState, subst: AnchorSubst): string =
result = getFilename(s.filenames, subst.module)
proc currFilename(s: PRstSharedState): string =
getFilename(s.filenames, s.currFileIdx)
@@ -830,7 +834,7 @@ proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string,
proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string,
langSym: LangSymbol, priority: int,
info: TLineInfo) =
info: TLineInfo, module: FileIndex) =
## Adds an anchor `refn`, which follows
## the rule `arNim` (i.e. a symbol in ``*.nim`` file)
s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add(
@@ -859,7 +863,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
for subst in substitutions:
if subst.kind == arNim:
if match(subst.langSym, langSym):
let key: GroupKey = (subst.langSym.symKind, getFilename(s, subst))
let key: GroupKey = (subst.langSym.symKind, getModule(s, subst))
found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst
for key, sList in found:
if sList.len == 1:
@@ -880,7 +884,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
break
doAssert(foundGroup,
"docgen has not generated the group for $1 (file $2)" % [
langSym.name, getFilename(s, sList[0]) ])
langSym.name, getModule(s, sList[0]) ])
proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo):
seq[AnchorSubst] =
@@ -2443,7 +2447,9 @@ proc parseParagraph(p: var RstParser, result: PRstNode) =
result.addIfNotNil(parseLineBlock(p))
of rnMarkdownBlockQuote:
result.addIfNotNil(parseMarkdownBlockQuote(p))
else: break
else:
dec p.idx # allow subsequent block to be parsed as another section
break
else:
break
of tkPunct:
@@ -3552,7 +3558,7 @@ proc loadIdxFile(s: var PRstSharedState, origFilename: string) =
langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword)
addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc,
langSym = langSym, priority = -4, # lowest
info=info)
info = info, module = info.fileIndex)
doAssert s.idxImports[origFilename].title != ""
proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) =

View File

@@ -63,6 +63,12 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T =
type BitsRange*[T] = range[0..sizeof(T)*8-1]
## A range with all bit positions for type `T`.
template typeMasked[T: SomeInteger](x: T): T =
when defined(js):
x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8)))
else:
x
func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
## Returns an extracted (and shifted) slice of bits from `v`.
runnableExamples:
@@ -73,7 +79,7 @@ func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1,
let
upmost = sizeof(T) * 8 - 1
uv = v.castToUnsigned
(uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
## Mutates `v` into an extracted (and shifted) slice of bits from `v`.
@@ -85,7 +91,7 @@ proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1,
let
upmost = sizeof(T) * 8 - 1
uv = v.castToUnsigned
v = (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
v = ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
## Creates a bitmask based on a slice of bits.
@@ -96,7 +102,7 @@ func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
let
upmost = sizeof(T) * 8 - 1
bitmask = bitnot(0.T).castToUnsigned
(bitmask shl (upmost - slice.b + slice.a) shr (upmost - slice.b)).T
((bitmask shl (upmost - slice.b + slice.a)).typeMasked shr (upmost - slice.b)).T
proc masked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
## Returns `v`, with only the `1` bits from `mask` matching those of

View File

@@ -501,7 +501,7 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
h = h !& ord(c)
result = !$h
proc hash*[T: tuple | object | proc](x: T): Hash =
proc hash*[T: tuple | object | proc | iterator {.closure.}](x: T): Hash =
## Efficient `hash` overload.
runnableExamples:
# for `tuple|object`, `hash` must be defined for each component of `x`.

View File

@@ -1110,7 +1110,7 @@ proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
dst = jsonNode.copy
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
when T is uint|uint64 or (not defined(js) and int.sizeof == 4):
when T is uint|uint64 or int.sizeof == 4:
verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
case jsonNode.kind
of JString:

View File

@@ -72,7 +72,7 @@ runnableExamples:
## in the standard library
import algorithm, math
import std/private/since
import std/private/[since, jsutils]
when defined(nimPreviewSlimSystem):
import std/[assertions]
@@ -231,11 +231,14 @@ proc rand[T: uint | uint64](r: var Rand; max: T): T =
let max = uint64(max)
when T.high.uint64 == uint64.high:
if max == uint64.high: return T(next(r))
var iters = 0
while true:
let x = next(r)
# avoid `mod` bias
if x <= randMax - (randMax mod max):
if x <= randMax - (randMax mod max) or iters > 20:
return T(x mod (max + 1))
else:
inc iters
proc rand*(r: var Rand; max: Natural): int {.benign.} =
## Returns a random integer in the range `0..max` using the given state.
@@ -337,9 +340,9 @@ proc rand*[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T =
when T is SomeFloat:
result = rand(r, x.b - x.a) + x.a
else: # Integers and Enum types
when defined(js):
whenJsNoBigInt64:
result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a))
else:
do:
result = cast[T](rand(r, cast[uint64](x.b) - cast[uint64](x.a)) + cast[uint64](x.a))
proc rand*[T: Ordinal or SomeFloat](x: HSlice[T, T]): T =
@@ -378,14 +381,14 @@ proc rand*[T: Ordinal](r: var Rand; t: typedesc[T]): T {.since: (1, 7, 1).} =
when T is range or T is enum:
result = rand(r, low(T)..high(T))
elif T is bool:
when defined(js):
whenJsNoBigInt64:
result = (r.next or 0) < 0
else:
do:
result = cast[int64](r.next) < 0
else:
when defined(js):
whenJsNoBigInt64:
result = cast[T](r.next shr (sizeof(uint)*8 - sizeof(T)*8))
else:
do:
result = cast[T](r.next shr (sizeof(uint64)*8 - sizeof(T)*8))
proc rand*[T: Ordinal](t: typedesc[T]): T =

View File

@@ -79,7 +79,7 @@ from unicode import toLower, toUpper
export toLower, toUpper
include "system/inclrtl"
import std/private/since
import std/private/[since, jsutils]
from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl,
startsWithImpl, endsWithImpl
@@ -944,9 +944,9 @@ func toHex*[T: SomeInteger](x: T, len: Positive): string =
doAssert b.toHex(4) == "1001"
doAssert toHex(62, 3) == "03E"
doAssert toHex(-8, 6) == "FFFFF8"
when defined(js):
whenJsNoBigInt64:
toHexImpl(cast[BiggestUInt](x), len, x < 0)
else:
do:
when T is SomeSignedInt:
toHexImpl(cast[BiggestUInt](BiggestInt(x)), len, x < 0)
else:
@@ -957,9 +957,9 @@ func toHex*[T: SomeInteger](x: T): string =
runnableExamples:
doAssert toHex(1984'i64) == "00000000000007C0"
doAssert toHex(1984'i16) == "07C0"
when defined(js):
whenJsNoBigInt64:
toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
else:
do:
when T is SomeSignedInt:
toHexImpl(cast[BiggestUInt](BiggestInt(x)), 2*sizeof(T), x < 0)
else:

View File

@@ -291,25 +291,57 @@ else:
## Returns some reasonable terminal width from either standard file
## descriptors, controlling terminal, environment variables or tradition.
var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors
# POSIX environment variable takes precendence.
# _COLUMNS_: This variable shall represent a decimal integer >0 used
# to indicate the user's preferred width in column positions for
# the terminal screen or window. If this variable is unset or null,
# the implementation determines the number of columns, appropriate
# for the terminal or window, in an unspecified manner.
# When COLUMNS is set, any terminal-width information implied by TERM
# is overridden. Users and conforming applications should not set COLUMNS
# unless they wish to override the system selection and produce output
# unrelated to the terminal characteristics.
# See POSIX Base Definitions Section 8.1 Environment Variable Definition
var w: int
var s = getEnv("COLUMNS") # Try standard env var
if len(s) > 0 and parseInt(s, w) > 0 and w > 0:
return w
w = terminalWidthIoctl([0, 1, 2]) # Try standard file descriptors
if w > 0: return w
var cterm = newString(L_ctermid) #Try controlling tty
var cterm = newString(L_ctermid) # Try controlling tty
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
if fd != -1:
w = terminalWidthIoctl([int(fd)])
discard close(fd)
if w > 0: return w
var s = getEnv("COLUMNS") #Try standard env var
if len(s) > 0 and parseInt(s, w) > 0 and w > 0:
return w
return 80 #Finally default to venerable value
return 80 # Finally default to venerable value
proc terminalHeight*(): int =
## Returns some reasonable terminal height from either standard file
## descriptors, controlling terminal, environment variables or tradition.
## Zero is returned if the height could not be determined.
var h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
# POSIX environment variable takes precendence.
# _LINES_: This variable shall represent a decimal integer >0 used
# to indicate the user's preferred number of lines on a page or
# the vertical screen or window size in lines. A line in this case
# is a vertical measure large enough to hold the tallest character
# in the character set being displayed. If this variable is unset or null,
# the implementation determines the number of lines, appropriate
# for the terminal or window (size, terminal baud rate, and so on),
# in an unspecified manner.
# When LINES is set, any terminal-height information implied by TERM
# is overridden. Users and conforming applications should not set LINES
# unless they wish to override the system selection and produce output
# unrelated to the terminal characteristics.
# See POSIX Base Definitions Section 8.1 Environment Variable Definition
var h: int
var s = getEnv("LINES") # Try standard env var
if len(s) > 0 and parseInt(s, h) > 0 and h > 0:
return h
h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
if h > 0: return h
var cterm = newString(L_ctermid) # Try controlling tty
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
@@ -317,9 +349,6 @@ else:
h = terminalHeightIoctl([int(fd)])
discard close(fd)
if h > 0: return h
var s = getEnv("LINES") # Try standard env var
if len(s) > 0 and parseInt(s, h) > 0 and h > 0:
return h
return 0 # Could not determine height
proc terminalSize*(): tuple[w, h: int] =

View File

@@ -537,7 +537,7 @@ proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay
assertValidDate monthday, month, year
# 1970-01-01 is a Thursday, we adjust to the previous Monday
let days = toEpochDay(monthday, month, year) - 3
let weeks = floorDiv(days, 7)
let weeks = floorDiv(days, 7'i64)
let wd = days - weeks * 7
# The value of d is 0 for a Sunday, 1 for a Monday, 2 for a Tuesday, etc.
# so we must correct for the WeekDay type.

View File

@@ -10,6 +10,8 @@
## This module allows adding hooks to program exit.
import locks
when defined(js) and not defined(nodejs):
import std/assertions
type
FunKind = enum kClosure, kNoconv # extend as needed

View File

@@ -64,10 +64,10 @@ func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs:
runnableExamples:
doAssert (big("3") + big("2") ** big("66")).wrapToUint(66) == big("3")
func toNumber*(this: JsBigInt): BiggestInt {.importjs: "Number(#)".} =
func toNumber*(this: JsBigInt): int {.importjs: "Number(#)".} =
## Does not do any bounds check and may or may not return an inexact representation.
runnableExamples:
doAssert toNumber(big"2147483647") == 2147483647.BiggestInt
doAssert toNumber(big"2147483647") == 2147483647.int
func `+`*(x, y: JsBigInt): JsBigInt {.importjs: "(# $1 #)".} =
runnableExamples:

View File

@@ -78,19 +78,24 @@ macro getDiscriminants(a: typedesc): seq[string] =
let sym = a[1]
let t = sym.getTypeImpl
let t2 = t[2]
doAssert t2.kind == nnkRecList
result = newTree(nnkBracket)
for ti in t2:
if ti.kind == nnkRecCase:
let key = ti[0][0]
let typ = ti[0][1]
result.add newLit key.strVal
if result.len > 0:
case t2.kind
of nnkEmpty: # allow empty objects
result = quote do:
@`result`
seq[string].default
of nnkRecList:
result = newTree(nnkBracket)
for ti in t2:
if ti.kind == nnkRecCase:
let key = ti[0][0]
result.add newLit key.strVal
if result.len > 0:
result = quote do:
@`result`
else:
result = quote do:
seq[string].default
else:
result = quote do:
seq[string].default
doAssert false, "unexpected kind: " & $t2.kind
macro initCaseObject(T: typedesc, fun: untyped): untyped =
## does the minimum to construct a valid case object, only initializing

View File

@@ -79,5 +79,18 @@ when defined(js):
assert not "123".toJs.isSafeInteger
assert 123.isSafeInteger
assert 123.toJs.isSafeInteger
assert 9007199254740991.toJs.isSafeInteger
assert not 9007199254740992.toJs.isSafeInteger
when false:
assert 9007199254740991.toJs.isSafeInteger
assert not 9007199254740992.toJs.isSafeInteger
template whenJsNoBigInt64*(no64, yes64): untyped =
when defined(js):
when compiles(compileOption("jsbigint64")):
when compileOption("jsbigint64"):
yes64
else:
no64
else:
no64
else:
no64

View File

@@ -1,5 +1,5 @@
##[
`since` is used to emulate older versions of nim stdlib with `--useVersion`,
`since` is used to emulate older versions of nim stdlib,
see `tuse_version.nim`.
If a symbol `foo` is added in version `(1,3,5)`, use `{.since: (1.3.5).}`, not

View File

@@ -62,11 +62,11 @@ proc typeof*(x: untyped; mode = typeOfIter): typedesc {.
doAssert type(myFoo()) is string
doAssert typeof(myFoo()) is string
doAssert typeof(myFoo(), typeOfIter) is string
doAssert typeof(myFoo3) is "iterator"
doAssert typeof(myFoo3) is iterator
doAssert typeof(myFoo(), typeOfProc) is float
doAssert typeof(0.0, typeOfProc) is float
doAssert typeof(myFoo3, typeOfProc) is "iterator"
doAssert typeof(myFoo3, typeOfProc) is iterator
doAssert not compiles(typeof(myFoo2(), typeOfProc))
# this would give: Error: attempting to call routine: 'myFoo2'
# since `typeOfProc` expects a typed expression and `myFoo2()` can
@@ -1108,6 +1108,11 @@ when defined(nimscript) or not defined(nimSeqsV2):
## containers should also call their adding proc `add` for consistency.
## Generic code becomes much easier to write if the Nim naming scheme is
## respected.
## ```
## var s: seq[string] = @["test2","test2"]
## s.add("test")
## assert s == @["test2", "test2", "test"]
## ```
when false: # defined(gcDestructors):
proc add*[T](x: var seq[T], y: sink openArray[T]) {.noSideEffect.} =
@@ -1142,13 +1147,17 @@ else:
## containers should also call their adding proc `add` for consistency.
## Generic code becomes much easier to write if the Nim naming scheme is
## respected.
## ```
## var s: seq[string] = @["test2","test2"]
## s.add("test") # s <- @[test2, test2, test]
## ```
##
## See also:
## * `& proc <#&,seq[T],seq[T]>`_
runnableExamples:
var a = @["a1", "a2"]
a.add(["b1", "b2"])
assert a == @["a1", "a2", "b1", "b2"]
var c = @["c0", "c1", "c2", "c3"]
a.add(c.toOpenArray(1, 2))
assert a == @["a1", "a2", "b1", "b2", "c1", "c2"]
{.noSideEffect.}:
let xl = x.len
setLen(x, xl + y.len)
@@ -2179,39 +2188,30 @@ when notJSnotNims:
include "system/profiler"
{.pop.}
proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} =
proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
## Retrieves the raw proc pointer of the closure `x`. This is
## useful for interfacing closures with C/C++, hash compuations, etc.
when T is "closure":
#[
The conversion from function pointer to `void*` is a tricky topic, but this
should work at least for c++ >= c++11, e.g. for `dlsym` support.
refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
]#
{.emit: """
`result` = (void*)`x`.ClP_0;
""".}
else:
{.error: "Only closure function and iterator are allowed!".}
#[
The conversion from function pointer to `void*` is a tricky topic, but this
should work at least for c++ >= c++11, e.g. for `dlsym` support.
refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
]#
{.emit: """
`result` = (void*)`x`.ClP_0;
""".}
proc rawEnv*[T: proc](x: T): pointer {.noSideEffect, inline.} =
proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`.
when T is "closure":
{.emit: """
`result` = `x`.ClE_0;
""".}
else:
{.error: "Only closure function and iterator are allowed!".}
{.emit: """
`result` = `x`.ClE_0;
""".}
proc finished*[T: proc](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
## It can be used to determine if a first class iterator has finished.
when T is "iterator":
{.emit: """
`result` = ((NI*) `x`.ClE_0)[1] < 0;
""".}
else:
{.error: "Only closure iterator is allowed!".}
{.emit: """
`result` = ((NI*) `x`.ClE_0)[1] < 0;
""".}
from std/private/digitsutils import addInt
export addInt

View File

@@ -275,10 +275,12 @@ proc genericReset(dest: pointer, mt: PNimType) =
proc selectBranch(discVal, L: int,
a: ptr array[0x7fff, ptr TNimNode]): ptr TNimNode =
result = a[L] # a[L] contains the ``else`` part (but may be nil)
if discVal <% L:
let x = a[discVal]
if x != nil: result = x
result = a[discVal]
if result == nil:
result = a[L]
else:
result = a[L] # a[L] contains the ``else`` part (but may be nil)
proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
a: ptr array[0x7fff, ptr TNimNode],

View File

@@ -10,7 +10,7 @@ const
## is the minor number of Nim's version.
## Odd for devel, even for releases.
NimPatch* {.intdefine.}: int = 1
NimPatch* {.intdefine.}: int = 3
## is the patch number of Nim's version.
## Odd for devel, even for releases.

View File

@@ -12,16 +12,10 @@ type
## compiler supports. Currently this is `float64`, but it is
## platform-dependent in general.
when defined(js):
type BiggestUInt* = uint32
BiggestUInt* = uint64
## is an alias for the biggest unsigned integer type the Nim compiler
## supports. Currently this is `uint32` for JS and `uint64` for other
## targets.
else:
type BiggestUInt* = uint64
## is an alias for the biggest unsigned integer type the Nim compiler
## supports. Currently this is `uint32` for JS and `uint64` for other
## targets.
## supports. Currently this is `uint64`, but it is platform-dependent
## in general.
when defined(windows):
type

View File

@@ -448,7 +448,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
else:
pushCurrentException(e)
{.emit: "throw `e`;".}
elif defined(nimQuirky) or gotoBasedExceptions:
elif quirkyExceptions or gotoBasedExceptions:
pushCurrentException(e)
when gotoBasedExceptions:
inc nimInErrorMode
@@ -560,7 +560,7 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
not defined(js) and not defined(nimscript) and
hostOS != "standalone" and hostOS != "any" and not defined(noCppExceptions) and
not defined(nimQuirky):
not quirkyExceptions:
type
StdException {.importcpp: "std::exception", header: "<exception>".} = object

View File

@@ -9,7 +9,9 @@
{.push profiler: off.}
const gotoBasedExceptions = compileOption("exceptions", "goto")
const
gotoBasedExceptions = compileOption("exceptions", "goto")
quirkyExceptions = compileOption("exceptions", "quirky")
when hostOS == "standalone":
include "$projectpath/panicoverride"
@@ -21,7 +23,7 @@ when hostOS == "standalone":
rawoutput(message)
panic(arg)
elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript):
elif (quirkyExceptions or defined(nimPanics)) and not defined(nimscript):
import ansi_c
func name(t: typedesc): string {.magic: "TypeTrait".}

View File

@@ -451,44 +451,44 @@ proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
return Math.trunc(`a` % `b`);
"""
proc checkOverflowInt64(a: int) {.asmNoStackFrame, compilerproc.} =
proc checkOverflowInt64(a: int64) {.asmNoStackFrame, compilerproc.} =
asm """
if (`a` > 9223372036854775807 || `a` < -9223372036854775808) `raiseOverflow`();
if (`a` > 9223372036854775807n || `a` < -9223372036854775808n) `raiseOverflow`();
"""
proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
proc addInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
asm """
var result = `a` + `b`;
`checkOverflowInt64`(result);
return result;
"""
proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
proc subInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
asm """
var result = `a` - `b`;
`checkOverflowInt64`(result);
return result;
"""
proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
proc mulInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
asm """
var result = `a` * `b`;
`checkOverflowInt64`(result);
return result;
"""
proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
proc divInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
asm """
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.trunc(`a` / `b`);
if (`b` == 0n) `raiseDivByZero`();
if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
return `a` / `b`;
"""
proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
proc modInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
asm """
if (`b` == 0) `raiseDivByZero`();
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
return Math.trunc(`a` % `b`);
if (`b` == 0n) `raiseDivByZero`();
if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
return `a` % `b`;
"""
proc negInt(a: int): int {.compilerproc.} =

View File

@@ -12,6 +12,8 @@ when defined(nimPreviewSlimSystem):
import std/formatfloat
proc reprInt(x: int64): string {.compilerproc.} = $x
proc reprInt(x: uint64): string {.compilerproc.} = $x
proc reprInt(x: int): string {.compilerproc.} = $x
proc reprFloat(x: float): string {.compilerproc.} = $x
proc reprPointer(p: pointer): string {.compilerproc.} =
@@ -192,8 +194,12 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
return
dec(cl.recDepth)
case typ.kind
of tyInt..tyInt64, tyUInt..tyUInt64:
of tyInt..tyInt32, tyUInt..tyUInt32:
add(result, reprInt(cast[int](p)))
of tyInt64:
add(result, reprInt(cast[int64](p)))
of tyUInt64:
add(result, reprInt(cast[uint64](p)))
of tyChar:
add(result, reprChar(cast[char](p)))
of tyBool:

View File

@@ -106,6 +106,7 @@
<li><a class="reference" href="#fn2" title="fn2()">fn2()</a></li>
<li><a class="reference" href="#fn2%2Cint" title="fn2(x: int)">fn2(x: int)</a></li>
<li><a class="reference" href="#fn2%2Cint%2Cfloat" title="fn2(x: int; y: float)">fn2(x: int; y: float)</a></li>
<li><a class="reference" href="#fn2%2Cint%2Cfloat%2Cfloat" title="fn2(x: int; y: float; z: float)">fn2(x: int; y: float; z: float)</a></li>
</ul>
<ul class="simple nested-toc-section">fn3
@@ -215,7 +216,7 @@
<ol class="simple"><li>Other case value</li>
<li>Second case.</li>
</ol>
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
@@ -229,7 +230,7 @@
<p>Group ref. with capital letters works: <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fN11</a> or <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fn11</a> </p>
Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">[]</a> is the same as <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`(G[T])</a> because there are no overloads. The full form: <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`*[T](x: G[T]): T</a>Ref. <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">[]=</a> aka <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`(G[T], int, T)</a>.Ref. <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">$</a> aka <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc $</a> or <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc `$`</a>.Ref. <a class="reference internal nimdoc" title="proc `$`[T](a: ref SomeType): string" href="#$,ref.SomeType">$(a: ref SomeType)</a>.Ref. <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">foo_bar</a> aka <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">iterator foo_bar_</a>.Ref. <a class="reference internal nimdoc" title="proc fn[T; U, V: SomeFloat]()" href="#fn">fn[T; U,V: SomeFloat]()</a>.Ref. <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">'big</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">func `'big`</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">`'big`(string)</a>.
<h1><a class="toc-backref" id="pandoc-markdown" href="#pandoc-markdown">Pandoc Markdown</a></h1><p>Now repeat all the auto links of above in Pandoc Markdown Syntax.</p>
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
@@ -392,6 +393,14 @@ Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href=
</dd>
</div>
<div id="fn2,int,float,float">
<dt><pre><span class="Keyword">proc</span> <a href="#fn2%2Cint%2Cfloat%2Cfloat"><span class="Identifier">fn2</span></a><span class="Other">(</span><span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">;</span> <span class="Identifier">y</span><span class="Other">:</span> <span class="Identifier">float</span><span class="Other">;</span> <span class="Identifier">z</span><span class="Other">:</span> <span class="Identifier">float</span><span class="Other">)</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
<dd>
</dd>
</div>

View File

@@ -1,5 +1,6 @@
nimTitle utils subdir/subdir_b/utils.html module subdir/subdir_b/utils 0
nim funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U proc funWithGenerics[T, U: SomeFloat](a: T; b: U) 1
nim fn2 subdir/subdir_b/utils.html#fn2,int,float,float proc fn2(x: int; y: float; z: float) 5
nim enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA 45
nim enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB 45
nim enumValueC subdir/subdir_b/utils.html#enumValueC SomeType.enumValueC 45
@@ -34,7 +35,7 @@ nim fn subdir/subdir_b/utils.html#fn proc fn[T; U, V: SomeFloat]() 160
nim `'big` subdir/subdir_b/utils.html#'big,string proc `'big`(a: string): SomeType 164
nimgrp $ subdir/subdir_b/utils.html#$-procs-all proc 148
nimgrp fn11 subdir/subdir_b/utils.html#fN11-procs-all proc 85
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 57
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 5
nimgrp f subdir/subdir_b/utils.html#f-procs-all proc 130
heading This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header 0
heading Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header 0

View File

@@ -175,6 +175,8 @@
data-doc-search-tag="utils: proc fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: proc fn2(x: int)</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: proc fn2(x: int; y: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat">utils: proc fn2(x: int; y: float)</a></li>
<li><a class="reference external"
data-doc-search-tag="utils: proc fn2(x: int; y: float; z: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat%2Cfloat">utils: proc fn2(x: int; y: float; z: float)</a></li>
</ul></dd>
<dt><a name="fn3" href="#fn3"><span>fn3:</span></a></dt><dd><ul class="simple">
<li><a class="reference external"

View File

@@ -1 +1,6 @@
proc funWithGenerics*[T, U: SomeFloat](a: T, b: U) = discard
# We check that presence of overloaded `fn2` here does not break
# referencing in the "parent" file (the one that includes this one)
proc fn2*(x: int, y: float, z: float) =
discard

View File

@@ -135,7 +135,7 @@ pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
pkg "pylib"
pkg "rbtree"
pkg "react", "nimble example"
pkg "regex", "nim c src/regex", url = "https://github.com/nim-lang/nim-regex"
pkg "regex", "nim c src/regex"
pkg "result", "nim c -r result.nim"
pkg "RollingHash", "nim c -r tests/test_cyclichash.nim"
pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim"

View File

@@ -222,7 +222,10 @@ proc extractErrorMsg(s: string; i: int; line: var int; col: var int; spec: var T
while result < s.len-1:
if s[result] == '\n':
msg.add '\n'
if result > 0 and s[result - 1] == '\r':
msg[^1] = '\n'
else:
msg.add '\n'
inc result
inc line
col = 1

30
tests/arc/t19364.nim Normal file
View File

@@ -0,0 +1,30 @@
discard """
cmd: '''nim c --gc:arc --expandArc:fooLeaks $file'''
nimout: '''
--expandArc: fooLeaks
var
tmpTuple_cursor
a_cursor
b_cursor
c_cursor
tmpTuple_cursor = refTuple
a_cursor = tmpTuple_cursor[0]
b_cursor = tmpTuple_cursor[1]
c_cursor = tmpTuple_cursor[2]
-- end of expandArc ------------------------
'''
"""
func fooLeaks(refTuple: tuple[a,
b,
c: seq[float]]): float =
let (a, b, c) = refTuple
let refset = (a: newSeq[float](25_000_000),
b: newSeq[float](25_000_000),
c: newSeq[float](25_000_000))
var res = newSeq[float](1_000_000)
for i in 0 .. res.high:
res[i] = fooLeaks(refset)

View File

@@ -0,0 +1,41 @@
discard """
matrix: "--mm:orc"
"""
# bug #20993
type
Dual[int] = object # must be generic (even if fully specified)
p: int
proc D(p: int): Dual[int] = Dual[int](p: p)
proc `+`(x: Dual[int], y: Dual[int]): Dual[int] = D(x.p + y.p)
type
Tensor[T] = object
buf: seq[T]
proc newTensor*[T](s: int): Tensor[T] = Tensor[T](buf: newSeq[T](s))
proc `[]`*[T](t: Tensor[T], idx: int): T = t.buf[idx]
proc `[]=`*[T](t: var Tensor[T], idx: int, val: T) = t.buf[idx] = val
proc `+.`[T](t1, t2: Tensor[T]): Tensor[T] =
let n = t1.buf.len
result = newTensor[T](n)
for i in 0 ..< n:
result[i] = t1[i] + t2[i]
proc toTensor*[T](a: sink seq[T]): Tensor[T] =
## This breaks it: Using `T` instead makes it work
type U = typeof(a[0])
var t: Tensor[U] # Tensor[T] works
t.buf = a
result = t
proc loss() =
var B = toTensor(@[D(123)])
let a = toTensor(@[D(-10)])
B = B +. a
doAssert B[0].p == 113, "I want to be 113, but I am " & $B[0].p
loss()

View File

@@ -597,3 +597,20 @@ block: # bug #19857
let res = v.toF()
foo()
import std/options
# bug #21592
type Event* = object
code*: string
type App* = ref object of RootObj
id*: string
method process*(self: App): Option[Event] {.base.} =
raise Exception.new_exception("not impl")
# bug #21617
type Test2 = ref object of RootObj
method bug(t: Test2): seq[float] {.base.} = discard

View File

@@ -0,0 +1,39 @@
discard """
action: "compile"
targets: "cpp"
cmd: "nim cpp $file"
"""
# see #21505: ensure compilation of imported C++ objects with explicit constructors while retaining default initialization through codegen changes due to #21279
{.emit:"""/*TYPESECTION*/
struct ExplObj
{
explicit ExplObj(int bar = 0) {}
};
struct BareObj
{
BareObj() {}
};
""".}
type
ExplObj {.importcpp.} = object
BareObj {.importcpp.} = object
type
Composer = object
explObj: ExplObj
bareObj: BareObj
proc foo =
var composer1 {.used.}: Composer
let composer2 {.used.} = Composer()
var composer1 {.used.}: Composer
let composer2 {.used.} = Composer()
foo()

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "When mixing named fields and unnamed fields, every field needs to be initialized in order"
errormsg: "incorrect object construction syntax"
file: "t5965_1.nim"
line: 10
"""

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "The object construction is given more fields than required"
errormsg: "incorrect object construction syntax"
file: "t5965_2.nim"
line: 10
"""

View File

@@ -3,7 +3,7 @@ discard """
exitcode: "1"
output: '''
t14444.nim(13) t14444
fatal.nim(51) sysFatal
fatal.nim(53) sysFatal
Error: unhandled exception: index out of bounds, the container is empty [IndexDefect]
'''
"""

View File

@@ -7,7 +7,7 @@ Expression: int(inNanoseconds(t2 - t1)) / 100.5
[1] int(inNanoseconds(t2 - t1)): int
[2] 100.5: float64
Expected one of (first mismatch at position [#]):
Expected one of (first mismatch at [position]):
[1] proc `/`(x, y: float): float
[1] proc `/`(x, y: float32): float32
[2] proc `/`(x, y: int): float
@@ -20,4 +20,4 @@ from times import inNanoseconds
let t1 = getMonotime()
let result = 1 + 2
let t2 = getMonotime()
echo "Elapsed: ", (t2 - t1).inNanoseconds.int / 100.5
echo "Elapsed: ", (t2 - t1).inNanoseconds.int / 100.5

View File

@@ -2,24 +2,10 @@ type
Noice* = object
hidden: int
Ciao* = object
hidden1: int
hidden2: int
Gull* = ref object
hidden1: int
field*: int
hidden2: int
field2*: int
template jjj*(): Noice =
var x = 7
template jjj*: Noice =
Noice(hidden: 15)
template said*(): Ciao =
var x = 7
Ciao(hidden1: 15 + x, 1)
type Opt* = object
o: int
proc foo*: Gull =
result = Gull(1, 2, 3, 4)
template none*(O: type Opt): Opt = Opt(o: 0)

View File

@@ -3,19 +3,11 @@ import m3770
doAssert $jjj() == "(hidden: 15)" # works
doAssert $said() == "(hidden1: 22, hidden2: 1)"
proc someGeneric(_: type) =
doAssert $jjj() == "(hidden: 15)" # fails: "Error: the field 'hidden' is not accessible."
when false: # todo somehow make it work?
doAssert $said() == "(hidden1: 22, hidden2: 1)"
someGeneric(int)
doAssert $(foo()[]) == "(hidden1: 1, field: 2, hidden2: 3, field2: 4)"
proc bar() =
var s = Gull(13, 14)
doAssert $(s[]) == "(hidden1: 0, field: 13, hidden2: 0, field2: 14)"
bar()
# bug #20900
proc c(y: int | int, w: Opt = Opt.none) = discard
c(0)

View File

@@ -0,0 +1,54 @@
discard """
output: '''30
60
90
150
180
210
240
60
180
240
[60, 180, 240]
[60, 180]'''
"""
import std/enumerate
template map[T; Y](i: iterable[T], fn: proc(x: T): Y): untyped =
iterator internal(): Y {.gensym.} =
for it in i:
yield fn(it)
internal()
template filter[T](i: iterable[T], fn: proc(x: T): bool): untyped =
iterator internal(): T {.gensym.} =
for it in i:
if fn(it):
yield it
internal()
template group[T](i: iterable[T], amount: static int): untyped =
iterator internal(): array[amount, T] {.gensym.} =
var val: array[amount, T]
for ind, it in enumerate i:
val[ind mod amount] = it
if ind mod amount == amount - 1:
yield val
internal()
var a = [10, 20, 30, 50, 60, 70, 80]
proc mapFn(x: int): int = x * 3
proc filterFn(x: int): bool = x mod 20 == 0
for x in a.items.map(mapFn):
echo x
for y in a.items.map(mapFn).filter(filterFn):
echo y
for y in a.items.map(mapFn).filter(filterFn).group(3):
echo y
for y in a.items.map(mapFn).filter(filterFn).group(2):
echo y

View File

@@ -1,3 +1,7 @@
discard """
matrix: "--jsbigint64:off; --jsbigint64:on"
"""
import std/private/jsutils
proc main()=
@@ -5,9 +9,10 @@ proc main()=
doAssert fn(array[2, int8].default) == "Int8Array"
doAssert fn(array[2, uint8].default) == "Uint8Array"
doAssert fn(array[2, byte].default) == "Uint8Array"
# doAssert fn(array[2, char].default) == "Uint8Array" # xxx fails; bug?
doAssert fn(array[2, uint64].default) == "Array"
# pending https://github.com/nim-lang/RFCs/issues/187 maybe use `BigUint64Array`
doAssert fn(array[2, char].default) == "Uint8Array"
whenJsNoBigInt64: discard
do:
doAssert fn(array[2, uint64].default) == "BigUint64Array"
doAssert fn([1'u8]) == "Uint8Array"
doAssert fn([1'u16]) == "Uint16Array"
doAssert fn([byte(1)]) == "Uint8Array"

View File

@@ -5,6 +5,7 @@ discard """
# Test numeric literals and handling of minus symbol
import std/[macros, strutils]
import std/private/jsutils
import mlexerutils
@@ -60,7 +61,8 @@ template main =
doAssert -2147483648'i32 == int32.low
when int.sizeof > 4:
doAssert -9223372036854775808 == int.low
when not defined(js):
whenJsNoBigInt64: discard
do:
doAssert -9223372036854775808 == int64.low
block: # check when a minus (-) is an unary op

22
tests/macros/t15691.nim Normal file
View File

@@ -0,0 +1,22 @@
discard """
action: compile
"""
import std/macros
macro simplifiedExpandMacros(body: typed): untyped =
result = body
simplifiedExpandMacros:
proc testProc() = discard
simplifiedExpandMacros:
template testTemplate(): untyped = discard
# Error: illformed AST: macro testMacro(): untyped =
simplifiedExpandMacros:
macro testMacro(): untyped = discard
# Error: illformed AST: converter testConverter(x: int): float =
simplifiedExpandMacros:
converter testConverter(x: int): float = discard

13
tests/macros/t21593.nim Normal file
View File

@@ -0,0 +1,13 @@
discard """
nimout: '''
StmtList
UIntLit 18446744073709551615
IntLit -1'''
"""
import macros
dumpTree:
0xFFFFFFFF_FFFFFFFF'u
0xFFFFFFFF_FFFFFFFF

View File

@@ -8,7 +8,9 @@ for i, d in pairs(data):
discard
for i, (x, y) in pairs(data):
discard
var (a, b) = (1, 2)
var
a = 1
b = 2
var data = @[(1, "one"), (2, "two")]
for (i, d) in pairs(data):

View File

@@ -1,8 +1,5 @@
discard """
action: reject
nimout: '''
t11634.nim(20, 7) Error: cannot destructure to compile time variable
'''
"""
type Foo = ref object

View File

@@ -1,4 +1,5 @@
discard """
matrix: "; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
output: '''
0 0
0 0
@@ -6,6 +7,8 @@ Success'''
"""
# Test the different integer operations
import std/private/jsutils
var testNumber = 0
template test(opr, a, b, c: untyped): untyped =
@@ -23,28 +26,37 @@ template test(opr, a, b, c: untyped): untyped =
test(`+`, 12'i8, -13'i16, -1'i16)
test(`shl`, 0b11, 0b100, 0b110000)
whenJsNoBigInt64: discard
do:
test(`shl`, 0b11'i64, 0b100'i64, 0b110000'i64)
when not defined(js):
# mixed type shr needlessly complicates codegen with bigint
# and thus is not yet supported in JS for 64 bit ints
test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
when not defined(js):
whenJsNoBigInt64: discard
do:
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64)
test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16)
test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8)
when not defined(js):
whenJsNoBigInt64: discard
do:
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32)
when not defined(js):
whenJsNoBigInt64: discard
do:
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
when not defined(js):
whenJsNoBigInt64: discard
do:
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)

View File

@@ -0,0 +1,15 @@
discard """
cmd: "nim check $file"
"""
# bug #19225
import std/sequtils
sequtils #[tt.Error
^ expression has no type: sequtils]#
proc foo() =
block: #[tt.Error
^ expression has no type: block:
sequtils]#
sequtils
foo()

View File

@@ -1,3 +1,15 @@
discard """
cmd: "nim check $file"
errormsg: ""
nimout: '''
t17437.nim(20, 16) Error: undeclared identifier: 'x'
t17437.nim(20, 16) Error: expression 'x' has no type (or is ambiguous)
t17437.nim(20, 19) Error: incorrect object construction syntax
t17437.nim(20, 19) Error: incorrect object construction syntax
t17437.nim(20, 12) Error: expression '' has no type (or is ambiguous)
'''
"""
# bug #17437 invalid object construction should result in error
type
@@ -5,8 +17,6 @@ type
x, y: int
proc m =
var x = 12
var y = 1
var v = V(x: x, y)
m()

15
tests/objects/t20972.nim Normal file
View File

@@ -0,0 +1,15 @@
discard """
matrix: "--mm:refc -d:release; --mm:orc -d:release"
"""
{.passC: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -Wall -Wextra -pedantic -flto".}
{.passL: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -flto".}
# bug #20972
type ForkedEpochInfo = object
case kind: bool
of true, false: discard
var info = ForkedEpochInfo(kind: true)
doAssert info.kind
info.kind = false
doAssert not info.kind

3
tests/parser/t19430.nim Normal file
View File

@@ -0,0 +1,3 @@
let x = proc() = ## abc
let y = 3 #[tt.Error
^ invalid indentation]#

View File

@@ -27,3 +27,51 @@ proc main() =
main()
main2()
block: # nested unpacking
block: # simple let
let (a, (b, c), d) = (1, (2, 3), 4)
doAssert (a, b, c, d) == (1, 2, 3, 4)
let foo = (a, (b, c), d)
let (a2, (b2, c2), d2) = foo
doAssert (a, b, c, d) == (a2, b2, c2, d2)
block: # var and assignment
var (x, (y, z), t) = ('a', (true, @[123]), "abc")
doAssert (x, y, z, t) == ('a', true, @[123], "abc")
(x, (y, z), t) = ('b', (false, @[456]), "def")
doAssert (x, y, z, t) == ('b', false, @[456], "def")
block: # very nested
let (_, (_, (_, (_, (_, a))))) = (1, (2, (3, (4, (5, 6)))))
doAssert a == 6
block: # const
const (a, (b, c), d) = (1, (2, 3), 4)
doAssert (a, b, c, d) == (1, 2, 3, 4)
const foo = (a, (b, c), d)
const (a2, (b2, c2), d2) = foo
doAssert (a, b, c, d) == (a2, b2, c2, d2)
block: # evaluation semantics preserved between literal and not literal
var s: seq[string]
block: # literal
let (a, (b, c), d) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
doAssert (a, b, c, d) == (1, 2, 3, 4)
doAssert s == @["a", "b", "c", "d"]
block: # underscore
s = @[]
let (a, (_, c), _) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
doAssert (a, c) == (1, 3)
doAssert s == @["a", "b", "c", "d"]
block: # temp
s = @[]
let foo = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
let (a, (b, c), d) = foo
doAssert (a, b, c, d) == (1, 2, 3, 4)
doAssert s == @["a", "b", "c", "d"]
block: # unary assignment unpacking
var a: int
(a,) = (1,)
doAssert a == 1

View File

@@ -1,14 +1,9 @@
# bug #15949
# bug #15949 and RFC #480
discard """
errormsg: "parameter 'a' requires a type"
nimout: '''
t15949.nim(20, 14) Error: parameter 'a' requires a type'''
"""
proc procWarn(a, b = 1): (int, int) = (a, b) #[tt.Warning
^ a, b all have default value '1', this may be unintentional, either use ';' (semicolon) or explicitly write each default value [ImplicitDefaultValue]]#
# line 10
proc procGood(a, b = 1): (int, int) = (a, b)
proc procGood(a = 1, b = 1): (int, int) = (a, b)
doAssert procGood() == (1, 1)
doAssert procGood(b = 3) == (1, 3)
@@ -17,4 +12,5 @@ doAssert procGood(a = 5, b = 6) == (5, 6)
# The type (and default value propagation breaks in the below example
# as semicolon is used instead of comma.
proc procBad(a; b = 1): (int, int) = (a, b)
proc procBad(a; b = 1): (int, int) = (a, b) #[tt.Error
^ parameter 'a' requires a type]#

View File

@@ -79,6 +79,19 @@ proc test() =
proc foo(_: int) =
let a = _
doAssert not compiles(main())
block: # generic params
doAssert not (compiles do:
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
doAssert foo[int]() == 0)
block:
proc foo[_, _](): int = 123
doAssert foo[int, bool]() == 123
block:
proc foo[T; U](_: typedesc[T]; _: typedesc[U]): (T, U) = (default(T), default(U))
doAssert foo(int, bool) == (0, false)
proc closureTest() =
var x = 0

View File

@@ -1,39 +0,0 @@
type
Standard* = object
name: string
id*: int
owner*: string
Color1* = enum
Red, Blue, Green
Case1* = object
name*: string
id*: int
color*: Color1
owner: string
## inplace object construction works
doAssert Standard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
proc initStandard*(name: string, id: int, owner: string): Standard =
Standard(name, id, owner)
## It works in the procs
doAssert initStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
static: doAssert initStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
template toStandard*(name: string, id: int, owner: string): Standard =
Standard(name, id, owner)
## It works in the procs
doAssert toStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
static: doAssert toStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
proc initColorRed*(name: string = "red", id: int = 1314, owner: string): Case1 =
result = Case1(name, id, Red, owner)
doAssert Case1("red", 1314, color: Red, owner: "unknown") == Case1("red", 1314, color: Red, "unknown")
doAssert Case1("red", 1314, Red, owner: "unknown") == Case1("red", 1314, Red, "unknown")
doAssert initColorRed(owner = "unknown") == Case1("red", id: 1314, Red, "unknown")

View File

@@ -1,90 +0,0 @@
import mobjectconstr_unnamed
type
Vector = object
a: int = 999
b, c: int
block: # positional construction
## It specifies all the unnamed fields
var x = Vector(1, 2, 3)
doAssert x.b == 2
block:
## unnamed fields can be mixed with named fields
block:
var x = Vector(a: 1, 2, 3)
doAssert x.c == 3
block:
var x = Vector(1, b: 2, 3)
doAssert x.c == 3
block:
var x = Vector(1, 2, c: 3)
doAssert x.c == 3
block:
## Object variants support unnamed fields for tags, which should be known at the compile time.
type
Color = enum
Red, Blue, Yellow
Factor = object
id: int
case flag: Color
of Red:
num: int
of Blue, Yellow:
done: bool
name: string
block:
var x = Factor(1, Red, 2, "1314")
doAssert x.num == 2
block:
var x = Factor(1, Blue, true, "1314")
doAssert x.done == true
block:
var x = Factor(1, Yellow, false, "1314")
doAssert x.done == false
type
Ciao = object
id: int
case flag: bool = false
of true:
num: int
of false:
done: bool
name: string
block:
var x = Ciao(12, false, false, "123")
doAssert x.done == false
block:
var x = Ciao(12, flag: true, 1, "123")
doAssert x.num == 1
## It works in the third module
block:
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
proc foo() =
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
foo()
template bar() =
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
bar()

View File

@@ -391,3 +391,23 @@ var sorted = newSeq[int](1000)
for i in 0..<sorted.len: sorted[i] = i*2
doAssert isSorted2(sorted, compare)
doAssert isSorted2(sorted, proc (a, b: int): bool {.inline.} = a < b)
block: # Ensure static descriminated objects compile
type
ObjKind = enum
KindA, KindB, KindC
MyObject[kind: static[ObjKind]] = object of RootObj
myNumber: int
when kind != KindA:
driverType: int
otherField: int
elif kind == KindC:
driverType: uint
otherField: int
var instance: MyObject[KindA]
discard instance
discard MyObject[KindC]()

28
tests/stdlib/t21564.nim Normal file
View File

@@ -0,0 +1,28 @@
discard """
targets: "c js"
"""
import bitops
import std/assertions
proc main() =
block: # bug #21564
# tesk `bitops.bitsliced` patch
doAssert(0x17.bitsliced(4..7) == 0x01)
doAssert(0x17.bitsliced(0..3) == 0x07)
block:
# test in-place `bitops.bitslice`
var t = 0x12F4
t.bitslice(4..7)
doAssert(t == 0xF)
block:
# test `bitops.toMask` patch via bitops.masked
doAssert(0x12FFFF34.masked(8..23) == 0x00FFFF00)
main()
static:
main()

View File

@@ -1,5 +1,5 @@
discard """
targets: "c cpp js"
matrix: "; --backend:cpp; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off"
"""
import std/hashes

View File

@@ -57,8 +57,9 @@ proc asyncTest() {.async.} =
doAssert(resp.code == Http404)
doAssert(resp.status == $Http404)
resp = await client.request("https://google.com/")
doAssert(resp.code.is2xx or resp.code.is3xx)
when false: # occasionally does not give success code
resp = await client.request("https://google.com/")
doAssert(resp.code.is2xx or resp.code.is3xx)
# getContent
try:
@@ -118,8 +119,9 @@ proc syncTest() =
doAssert(resp.code == Http404)
doAssert(resp.status == $Http404)
resp = client.request("https://google.com/")
doAssert(resp.code.is2xx or resp.code.is3xx)
when false: # occasionally does not give success code
resp = client.request("https://google.com/")
doAssert(resp.code.is2xx or resp.code.is3xx)
# getContent
try:

View File

@@ -1,6 +1,5 @@
discard """
matrix: "--mm:refc"
targets: "c cpp js"
matrix: "--mm:refc; --backend:cpp --mm:refc; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
"""
@@ -9,6 +8,7 @@ Note: Macro tests are in tests/stdlib/tjsonmacro.nim
]#
import std/[json,parsejson,strutils]
import std/private/jsutils
from std/math import isNaN
when not defined(js):
import std/streams
@@ -314,7 +314,8 @@ block: # bug #17383
else:
testRoundtrip(int.high): "9223372036854775807"
testRoundtrip(uint.high): "18446744073709551615"
when not defined(js):
whenJsNoBigInt64: discard
do:
testRoundtrip(int64.high): "9223372036854775807"
testRoundtrip(uint64.high): "18446744073709551615"

View File

@@ -436,11 +436,7 @@ proc testJson() =
block:
let s = """{"a": 1, "b": 2}"""
let t = parseJson(s).to(Table[string, int])
when not defined(js):
# For some reason on the JS backend `{"b": 2, "a": 0}` is
# sometimes the value of `t`. This needs investigation. I can't
# reproduce it right now in an isolated test.
doAssert t["a"] == 1
doAssert t["a"] == 1
doAssert t["b"] == 2
block:

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