Compare commits

...

34 Commits

Author SHA1 Message Date
ringabout
ce295d7243 fixes broken CI; bump macOS version to macos-11 (#20098)
* bump macOS image on Azure CI to macos-11
* fix CI error

(cherry picked from commit 8ef509b85b)
2022-07-28 07:47:52 +02:00
narimiran
c6e0983b47 fix typo 2022-07-20 11:20:33 +02:00
narimiran
c5cd23a776 fix important_packages 2022-07-20 11:19:41 +02:00
Tanguy
30ba13d22a Fix nested finally handling in closureiters [backport] (#19933)
* Fix nested finally handling in closureiters

* Fix CI

* review comment

* third time the charm

* Update compiler/closureiters.nim

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>

Co-authored-by: Dominik Picheta <dominikpicheta@googlemail.com>
(cherry picked from commit fb5fbf1e08)
2022-07-18 17:27:29 +02:00
narimiran
315f4ecff1 disable testing of 'fragments' package 2022-01-17 11:25:51 +01:00
flywind
49379e85ec mangle names in nimbase.h using cppDefine (#19395) [backport]
mangle names in nimbase.h
fix comments

(cherry picked from commit 4f6b59de96)
2022-01-17 11:18:03 +01:00
flywind
6ab3c1b365 nrvo shouldn't touch bycopy object[backport:1.2] (#19385)
fix nim-lang#19342

(cherry picked from commit 9b9ae8a487)
2022-01-17 07:40:43 +01:00
Ștefan Talpalaru
0dae9115c8 Nim-1.4: style fix (#19317)
this allows "--styleCheck:usages --styleCheck:error"
2022-01-05 01:31:09 +08:00
flywind
32882fa024 disable packages which doesn't support 1.4 (#19320)
ref https://github.com/nim-lang/Nim/pull/19317
2022-01-04 11:11:07 +01:00
Andreas Rumpf
dc1e948f15 Revert "Update uri.nim (#19148) [backport:1.0]" (#19280)
This reverts commit a3ef5df680.

(cherry picked from commit 81d32cf7e5)
2021-12-31 05:14:52 +01:00
Miran
65db3013a8 [backport:1.0] json: limit recursion depth (#19252)
* json: limit recursion depth

* do not run this check for JS backend

(cherry picked from commit c17baaefbc)
2021-12-14 18:21:19 +01:00
flywind
7f0e662032 oids: switch from PRNG to random module (#16203)
* switch from PRNG to random module
* fix the regression
* comments + tests
* runnableExamples
* make oids better

(cherry picked from commit 89a21e4ec7)
2021-12-13 15:03:56 +01:00
Dominik Picheta
547973c3e9 Update uri.nim (#19148) [backport:1.0]
(cherry picked from commit a3ef5df680)
2021-12-11 09:25:34 +01:00
Ștefan Talpalaru
4d5c5893ae nimc.rst: fix table markup (#19239)
(cherry picked from commit 1a92edeb89)
2021-12-11 05:48:23 +01:00
Ștefan Talpalaru
8c356fd971 nimRawSetjmp: support Windows (#19197)
* nimRawSetjmp: support Windows

Using `_setjmp()` directly is required to avoid some rare (but very
annoying) exception-related stack corruption leading to segfaults on
Windows, with Mingw-w64 and SEH.
More details: https://github.com/status-im/nimbus-eth2/issues/3121

Also add "nimBuiltinSetjmp" - mostly for benchmarking.

* fix for Apple's Clang++

(cherry picked from commit 69aabdab80)
2021-12-11 05:48:19 +01:00
Andreas Rumpf
17522d6ae1 fixes a possible 'javascript:' protocol exploit [backport:1.0] (#19134)
* fixes a possible 'javascript:' protocol exploit [backport:1.0]

* add tests

* Update tests/stdlib/trstgen.nim

* add the same logic for hyperlinks

* move the logic into a proc

Co-authored-by: narimiran <narimiran@disroot.org>
(cherry picked from commit 9338aa2497)
2021-12-10 11:56:52 +01:00
Tanguy
f8047c3e3c fix #19193 (#19195) [backport:1.2]
(cherry picked from commit cd592ed85b)
2021-12-10 11:50:13 +01:00
Etan Kissling
cfb6ebc07a allow HSlice bounded by constants of distinct types (#19219) [backport:1.2]
When creating heterogenous slices of distinct types, the compiler does
not initialize the internal type's `size` before accessing it.
This then leads to this crash message:
```
compiler/int128.nim(594, 11) `false` masking only implemented for 1, 2, 4 and 8 bytes [AssertionError]
```
This patch initializes the `size` properly, fixing the problem.

(cherry picked from commit 0213c7313b)
2021-12-10 11:49:39 +01:00
narimiran
8f20400466 we must use Ubuntu 18.04 2021-12-07 20:34:33 +01:00
Andreas Rumpf
6d3b706f6e misc bugfixes [backport:1.2] (#19203)
(cherry picked from commit 23c117a950)
2021-12-06 12:48:37 +01:00
Andreas Rumpf
0df0510722 fixes #14470 [backport:1.2] (#19115)
(cherry picked from commit 15157d06c3)
2021-12-06 12:41:49 +01:00
Andreas Rumpf
68df3c9afd fixes a 'mixin' statement handling regression [backport:1.2] (#18968)
(cherry picked from commit 8eef557157)
2021-12-06 12:41:33 +01:00
Etan Kissling
a8aaf5a27d allow converting static vars to openArray (#19048)
When assigning constant output to a seq, and then passing that static
seq to other functions that take `openArray`, the compiler may end up
producing errors, as it does not know how to convert `static[seq[T]]`
to `openArray[T]`. By ignoring the `static` wrapper on the type for
the purpose of determining data memory location and length, this gets
resolved cleanly. Unfortunately, it is relatively tricky to come up
with a minimal example, as there are followup problems from the failing
conversion, e.g., this may lead to `internal error: inconsistent
environment type`, instead of the relevant `openArrayLoc` error message.

(cherry picked from commit 490c4226a5)
2021-10-27 11:04:04 +02:00
flywind
80c8107c56 [tools] use the right parameter [backport:1.0] (#18957)
(cherry picked from commit b2873f0f63)
2021-10-06 13:41:18 +02:00
Andreas Rumpf
5bed375b52 fixes #16325 [backport:1.4] (#18784)
(cherry picked from commit a7cae2bda2)
2021-09-02 20:25:46 +02:00
Dankr4d
1228c5b3fc fixes #14511 [backport:1.4] (#18732)
* fixes #14511 [backport:1.4]

Signed-off-by: Dankr4d <dude569@freenet.de>

* Replaced fix with code from alaviss, for better readability, with small
changes.

Signed-off-by: Dankr4d <dude569@freenet.de>

* - Specified output in test.

Signed-off-by: Dankr4d <dude569@freenet.de>

* Replaced case in nnkRecCase with a simpler version, which just adds the
last son.

Signed-off-by: Dankr4d <dude569@freenet.de>

* Update tests/macros/t14511.nim

* Update tests/macros/t14511.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit c70e4040bd)
2021-09-02 20:25:39 +02:00
narimiran
0a8e9318d3 fix broken test 2021-08-24 07:28:19 +02:00
narimiran
22650a61e7 bump NimVersion to 1.4.9 2021-08-24 07:21:56 +02:00
flywind
8b80039cac fix #18702(fix parseutils.parseFloat) (#18703) [backport:1.0]
* fix #18702
* Apply suggestions from code review

(cherry picked from commit 901c5ded52)
2021-08-24 07:10:48 +02:00
Andreas Rumpf
b18c6fd09b fixes #18643 [backport:1.0] (#18678)
(cherry picked from commit 018465a234)
2021-08-24 07:10:26 +02:00
Andreas Rumpf
88340aab6d fixes #18411 (#18432) [backport:1.4]
(cherry picked from commit 1bed777314)
2021-08-24 07:09:10 +02:00
flywind
8a3e64f00e fixes #17768 [backport:1.4] (#18317)
* fixes #17768 [backport:1.4]

* tiny

(cherry picked from commit 2deb7011f5)
2021-08-24 07:09:00 +02:00
Timothee Cour
6c5585fc0b link stable and devel docs in nim docs (#18272) [backport:1.2]
(cherry picked from commit d3b27eb63e)
2021-08-24 07:08:47 +02:00
Yuriy Glukhov
ca1b7feb0f Fixes #17849 (#18055) [backport:1.2]
* Fixes #17849
* Update compiler/closureiters.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit a6bd6c7ed8)
2021-08-24 07:08:34 +02:00
44 changed files with 645 additions and 138 deletions

View File

@@ -42,7 +42,7 @@ jobs:
- target: windows
os: windows-2019
- target: osx
os: macos-10.15
os: macos-11
name: ${{ matrix.target }}
runs-on: ${{ matrix.os }}

View File

@@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04, macos-10.15]
os: [ubuntu-20.04, macos-11]
cpu: [amd64]
pkg: [1, 2]
name: '${{ matrix.os }} (pkg: ${{ matrix.pkg }})'

View File

@@ -15,16 +15,16 @@ jobs:
strategy:
matrix:
Linux_amd64:
vmImage: 'ubuntu-16.04'
vmImage: 'ubuntu-18.04'
CPU: amd64
Linux_i386:
vmImage: 'ubuntu-16.04'
vmImage: 'ubuntu-18.04'
CPU: i386
OSX_amd64:
vmImage: 'macOS-10.15'
vmImage: 'macOS-11'
CPU: amd64
OSX_amd64_cpp:
vmImage: 'macOS-10.15'
vmImage: 'macOS-11'
CPU: amd64
NIM_COMPILE_TO_CPP: true
Windows_amd64_batch0_3:

View File

@@ -214,7 +214,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
else:
var a: TLoc
initLocExpr(p, if n.kind == nkHiddenStdConv: n[1] else: n, a)
case skipTypes(a.t, abstractVar).kind
case skipTypes(a.t, abstractVar+{tyStatic}).kind
of tyOpenArray, tyVarargs:
if reifiedOpenArray(n):
if a.t.kind in {tyVar, tyLent}:

View File

@@ -916,7 +916,7 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
if optBoundsCheck in p.options and ty.kind != tyUncheckedArray:
if not isConstExpr(y):
# semantic pass has already checked for const index expressions
if firstOrd(p.config, ty) == 0:
if firstOrd(p.config, ty) == 0 and lastOrd(p.config, ty) >= 0:
if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)){ #raiseIndexError2($1, $2); $3}$n",
[rdCharLoc(b), intLiteral(lastOrd(p.config, ty)), raiseInstr(p)])

View File

@@ -1349,8 +1349,19 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
elif isDefined(p.config, "nimSigSetjmp"):
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", [safePoint])
elif isDefined(p.config, "nimBuiltinSetjmp"):
linefmt(p, cpsStmts, "$1.status = __builtin_setjmp($1.context);$n", [safePoint])
elif isDefined(p.config, "nimRawSetjmp"):
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
if isDefined(p.config, "mswindows"):
# The Windows `_setjmp()` takes two arguments, with the second being an
# undocumented buffer used by the SEH mechanism for stack unwinding.
# Mingw-w64 has been trying to get it right for years, but it's still
# prone to stack corruption during unwinding, so we disable that by setting
# it to NULL.
# More details: https://github.com/status-im/nimbus-eth2/issues/3121
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context, 0);$n", [safePoint])
else:
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
lineCg(p, cpsStmts, "if ($1.status == 0) {$n", [safePoint])

View File

@@ -223,7 +223,8 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
# such a poor programming language.
# We exclude records with refs too. This enhances efficiency and
# is necessary for proper code generation of assignments.
if rettype == nil: result = true
if rettype == nil or (tfByCopy notin rettype.flags and getSize(conf, rettype) > conf.target.floatSize*3):
result = true
else:
case mapType(conf, rettype, skResult)
of ctArray:

View File

@@ -439,8 +439,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
elif not isComplexValueType(typ):
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
if containsGarbageCollectedRef(loc.t):
var nilLoc: TLoc
initLoc(nilLoc, locTemp, loc.lode, OnStack)
nilLoc.r = rope("NIM_NIL")
genRefAssign(p, loc, nilLoc)
else:
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
else:
if not isTemp or containsGarbageCollectedRef(loc.t):
# don't use nimZeroMem for temporary values for performance if we can

View File

@@ -121,7 +121,10 @@
# yield 2
# if :unrollFinally: # This node is created by `newEndFinallyNode`
# if :curExc.isNil:
# return :tmpResult
# if nearestFinally == 0:
# return :tmpResult
# else:
# :state = nearestFinally # bubble up
# else:
# closureIterSetupExc(nil)
# raise
@@ -604,6 +607,12 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
internalError(ctx.g.config, "lowerStmtListExpr(nkCaseStmt): " & $branch.kind)
result.add(n)
result.add(ctx.newEnvVarAccess(tmp))
elif n[0].kind == nkStmtListExpr:
result = newNodeI(nkStmtList, n.info)
let (st, ex) = exprToStmtList(n[0])
result.add(st)
n[0] = ex
result.add(n)
of nkCallKinds, nkChckRange, nkChckRangeF, nkChckRange64:
var ns = false
@@ -794,7 +803,10 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
# Generate the following code:
# if :unrollFinally:
# if :curExc.isNil:
# return :tmpResult
# if nearestFinally == 0:
# return :tmpResult
# else:
# :state = nearestFinally # bubble up
# else:
# raise
let curExc = ctx.newCurExcAccess()
@@ -803,11 +815,17 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
let cmp = newTree(nkCall, newSymNode(ctx.g.getSysMagic(info, "==", mEqRef), info), curExc, nilnode)
cmp.typ = ctx.g.getSysType(info, tyBool)
let asgn = newTree(nkFastAsgn,
newSymNode(getClosureIterResult(ctx.g, ctx.fn), info),
ctx.newTmpResultAccess())
let retStmt =
if ctx.nearestFinally == 0:
# last finally, we can return
let asgn = newTree(nkFastAsgn,
newSymNode(getClosureIterResult(ctx.g, ctx.fn), info),
ctx.newTmpResultAccess())
newTree(nkReturnStmt, asgn)
else:
# bubble up to next finally
newTree(nkGotoState, ctx.g.newIntLit(info, ctx.nearestFinally))
let retStmt = newTree(nkReturnStmt, asgn)
let branch = newTree(nkElifBranch, cmp, retStmt)
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
@@ -851,6 +869,13 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
of nkSkip:
discard
of nkTryStmt:
if n.hasYields:
# the inner try will handle these transformations
discard
else:
for i in 0..<n.len:
n[i] = ctx.transformReturnsInTry(n[i])
else:
for i in 0..<n.len:
n[i] = ctx.transformReturnsInTry(n[i])

View File

@@ -164,7 +164,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, g)
of mBitnotI:
if n.typ.isUnsigned:
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g)
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(getSize(g.config, n.typ))), n, g)
else:
result = newIntNodeT(bitnot(getInt(a)), n, g)
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
@@ -276,23 +276,23 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
of mAddU:
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
let val = maskBytes(getInt(a) + getInt(b), int(getSize(g.config, n.typ)))
result = newIntNodeT(val, n, g)
of mSubU:
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
let val = maskBytes(getInt(a) - getInt(b), int(getSize(g.config, n.typ)))
result = newIntNodeT(val, n, g)
# echo "subU: ", val, " n: ", n, " result: ", val
of mMulU:
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
let val = maskBytes(getInt(a) * getInt(b), int(getSize(g.config, n.typ)))
result = newIntNodeT(val, n, g)
of mModU:
let argA = maskBytes(getInt(a), int(a.typ.size))
let argB = maskBytes(getInt(b), int(a.typ.size))
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
if argB != Zero:
result = newIntNodeT(argA mod argB, n, g)
of mDivU:
let argA = maskBytes(getInt(a), int(a.typ.size))
let argB = maskBytes(getInt(b), int(a.typ.size))
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
if argB != Zero:
result = newIntNodeT(argA div argB, n, g)
of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, g)

View File

@@ -358,12 +358,17 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
while objType.kind != tyObject:
objType = objType.lastSon
assert objType != nil
var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
let initResult = semConstructTypeAux(c, constrCtx, {})
assert constrCtx.missingFields.len > 0
localError(c.config, info,
"The $1 type doesn't have a default value. The following fields must be initialized: $2.",
[typeToString(t), listSymbolNames(constrCtx.missingFields)])
if objType.kind == tyObject:
var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
let initResult = semConstructTypeAux(c, constrCtx, {})
if constrCtx.missingFields.len > 0:
localError(c.config, info,
"The $1 type doesn't have a default value. The following fields must be initialized: $2." % [typeToString(t), listSymbolNames(constrCtx.missingFields)])
elif objType.kind == tyDistinct:
localError(c.config, info,
"The $1 distinct type doesn't have a default value." % typeToString(t))
else:
assert false, "Must not enter here."
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
var t = semTypeNode(c, n[0], nil)

View File

@@ -110,9 +110,14 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
result = copyNode(n)
var count = 0
for i in 0..<n.len:
toMixin.incl(considerQuotedIdent(c, n[i]).id)
result.add symChoice(c, n[i], nil, scForceOpen)
let x = symChoice(c, n[i], nil, scForceOpen)
inc count, x.len
result.add x
if count == 0:
result = newNodeI(nkEmpty, n.info)
proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
case n.kind

View File

@@ -614,8 +614,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
# if f is metatype.
result = typeRel(c, f, a)
# v--- is this correct?
if result <= isIntConv or inconsistentVarTypes(f, a):
if result <= isSubrange or inconsistentVarTypes(f, a):
result = isNone
#if result == isEqual:

View File

@@ -3,3 +3,9 @@
when defined(nimHasCppDefine):
cppDefine "errno"
cppDefine "unix"
# mangle the macro names in nimbase.h
cppDefine "NAN_INFINITY"
cppDefine "INF"
cppDefine "NAN"

View File

@@ -122,21 +122,12 @@ doc.body_toc_group = """
</div>
<div id="global-links">
<ul class="simple-boot">
<li>
<a href="manual.html">Manual</a>
</li>
<li>
<a href="lib.html">Standard library</a>
</li>
<li>
<a href="$theindexhref">Index</a>
</li>
<li>
<a href="compiler/$theindexhref">Compiler docs</a>
</li>
<li>
<a href="https://nim-lang.github.io/fusion/theindex.html">Fusion docs</a>
</li>
<li><a href="manual.html">Manual</a></li>
<li><a href="lib.html">Standard library</a></li>
<li> <a href="$theindexhref">Index</a></li>
<li><a href="compiler/$theindexhref">Compiler docs</a></li>
<li><a href="https://nim-lang.github.io/fusion/theindex.html">Fusion docs</a></li>
<li><a href="https://nim-lang.github.io/Nim/">devel</a>, <a href="https://nim-lang.org/documentation.html">stable</a></li>
</ul>
</div>
<div id="searchInputDiv">

View File

@@ -47,7 +47,7 @@ The commands to compile to either C, C++ or Objective-C are:
The most significant difference between these commands is that if you look
into the ``nimcache`` directory you will find ``.c``, ``.cpp`` or ``.m``
files, other than that all of them will produce a native binary for your
project. This allows you to take the generated code and place it directly
project. This allows you to take the generated code and place it directly
into a project using any of these languages. Here are some typical command-
line invocations::
@@ -110,8 +110,8 @@ Nim code calling the backend
Nim code can interface with the backend through the `Foreign function
interface <manual.html#foreign-function-interface>`_ mainly through the
`importc pragma <manual.html#foreign-function-interface-importc-pragma>`_.
The ``importc`` pragma is the *generic* way of making backend symbols available
in Nim and is available in all the target backends (JavaScript too). The C++
The `importc` pragma is the *generic* way of making backend symbols available
in Nim and is available in all the target backends (JavaScript too). The C++
or Objective-C backends have their respective `ImportCpp
<manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
`ImportObjC <manual.html#implementation-specific-pragmas-importobjc-pragma>`_
@@ -232,11 +232,6 @@ Also, C code requires you to specify a forward declaration for functions or
the compiler will assume certain types for the return value and parameters
which will likely make your program crash at runtime.
The Nim compiler can generate a C interface header through the ``--header``
command-line switch. The generated header will contain all the exported
symbols and the ``NimMain`` proc which you need to call before any other
Nim code.
Nim invocation example from C
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -255,9 +250,10 @@ Create a ``maths.c`` file with the following content:
.. code-block:: c
#include "fib.h"
#include <stdio.h>
extern int fib(int a);
int main(void)
{
NimMain();
@@ -270,13 +266,14 @@ Now you can run the following Unix like commands to first generate C sources
from the Nim code, then link them into a static binary along your main C
program::
$ nim c --noMain --noLinking --header:fib.h fib.nim
$ gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
.. code:: cmd
nim c --noMain --noLinking fib.nim
gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
The first command runs the Nim compiler with three special options to avoid
generating a ``main()`` function in the generated files, avoid linking the
object files into a final binary, and explicitly generate a header file for C
integration. All the generated files are placed into the ``nimcache``
generating a `main()`:c: function in the generated files and to avoid linking the
object files into a final binary. All the generated files are placed into the ``nimcache``
directory. That's why the next command compiles the ``maths.c`` source plus
all the ``.c`` files from ``nimcache``. In addition to this path, you also
have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
@@ -284,12 +281,12 @@ have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
Instead of depending on the generation of the individual ``.c`` files you can
also ask the Nim compiler to generate a statically linked library::
$ nim c --app:staticLib --noMain --header fib.nim
$ gcc -o m -Inimcache -Ipath/to/nim/lib libfib.nim.a maths.c
nim c --app:staticLib --noMain fib.nim
gcc -o m -Inimcache -Ipath/to/nim/lib libfib.nim.a maths.c
The Nim compiler will handle linking the source files generated in the
``nimcache`` directory into the ``libfib.nim.a`` static library, which you can
then link into your C program. Note that these commands are generic and will
then link into your C program. Note that these commands are generic and will
vary for each system. For instance, on Linux systems you will likely need to
use ``-ldl`` too to link in required dlopen functionality.

View File

@@ -149,6 +149,22 @@ ignored too. ``--define:FOO`` and ``--define:foo`` are identical.
Compile-time symbols starting with the ``nim`` prefix are reserved for the
implementation and should not be used elsewhere.
========================== ============================================
Name Description
========================== ============================================
nimStdSetjmp Use the standard `setjmp()/longjmp()` library
functions for setjmp-based exceptions. This is
the default on most platforms.
nimSigSetjmp Use `sigsetjmp()/siglongjmp()` for setjmp-based exceptions.
nimRawSetjmp Use `_setjmp()/_longjmp()` on POSIX and `_setjmp()/longjmp()`
on Windows, for setjmp-based exceptions. It's the default on
BSDs and BSD-like platforms, where it's significantly faster
than the standard functions.
nimBuiltinSetjmp Use `__builtin_setjmp()/__builtin_longjmp()` for setjmp-based
exceptions. This will not work if an exception is being thrown
and caught inside the same procedure. Useful for benchmarking.
========================== ============================================
Configuration files
-------------------

View File

@@ -1526,18 +1526,17 @@ proc customPragmaNode(n: NimNode): NimNode =
for i in 0..<identDefsStack.len: identDefsStack[i] = obj[2][i]
while identDefsStack.len > 0:
var identDefs = identDefsStack.pop()
if identDefs.kind == nnkRecCase:
identDefsStack.add(identDefs[0])
for i in 1..<identDefs.len:
let varNode = identDefs[i]
# if it is and empty branch, skip
if varNode[0].kind == nnkNilLit: continue
if varNode[1].kind == nnkIdentDefs:
identDefsStack.add(varNode[1])
else: # nnkRecList
for j in 0 ..< varNode[1].len:
identDefsStack.add(varNode[1][j])
case identDefs.kind
of nnkRecList:
for child in identDefs.children:
identDefsStack.add(child)
of nnkRecCase:
# Add condition definition
identDefsStack.add(identDefs[0])
# Add branches
for i in 1 ..< identDefs.len:
identDefsStack.add(identDefs[i].last)
else:
for i in 0 .. identDefs.len - 3:
let varNode = identDefs[i]

View File

@@ -26,7 +26,7 @@
## **Note:** Import ``packages/docutils/rstgen`` to use this module
import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
algorithm, parseutils
algorithm, parseutils, strscans
import ../../std/private/since
@@ -786,6 +786,16 @@ proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
rstnodeToRefname(n), tmp, $chr(n.level - 1 + ord('A'))])
proc safeProtocol(linkStr: var string) =
var protocol = ""
if scanf(linkStr, "$w:", protocol):
# if it has a protocol at all, ensure that it's not 'javascript:' or worse:
if cmpIgnoreCase(protocol, "http") == 0 or cmpIgnoreCase(protocol, "https") == 0 or
cmpIgnoreCase(protocol, "ftp") == 0:
discard "it's fine"
else:
linkStr = ""
proc renderTocEntry(d: PDoc, e: TocEntry, result: var string) =
dispA(d.target, result,
"<li><a class=\"reference\" id=\"$1_toc\" href=\"#$1\">$2</a></li>\n",
@@ -850,6 +860,8 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
# support for `:target:` links for images:
var target = esc(d.target, getFieldValue(n, "target").strip())
safeProtocol(target)
if target.len > 0:
# `htmlOut` needs to be of the following format for link to work for images:
# <a class="reference external" href="target"><img src=\"$1\"$2/></a>

View File

@@ -195,6 +195,8 @@ type
of JArray:
elems*: seq[JsonNode]
const DepthLimit = 1000
proc newJString*(s: string): JsonNode =
## Creates a new `JString JsonNode`.
result = JsonNode(kind: JString, str: s)
@@ -806,7 +808,7 @@ iterator mpairs*(node: var JsonNode): tuple[key: string, val: var JsonNode] =
for key, val in mpairs(node.fields):
yield (key, val)
proc parseJson(p: var JsonParser; rawIntegers, rawFloats: bool): JsonNode =
proc parseJson(p: var JsonParser; rawIntegers, rawFloats: bool, depth = 0): JsonNode =
## Parses JSON from a JSON Parser `p`.
case p.tok
of tkString:
@@ -842,6 +844,8 @@ proc parseJson(p: var JsonParser; rawIntegers, rawFloats: bool): JsonNode =
result = newJNull()
discard getTok(p)
of tkCurlyLe:
if depth > DepthLimit:
raiseParseErr(p, "}")
result = newJObject()
discard getTok(p)
while p.tok != tkCurlyRi:
@@ -850,16 +854,18 @@ proc parseJson(p: var JsonParser; rawIntegers, rawFloats: bool): JsonNode =
var key = p.a
discard getTok(p)
eat(p, tkColon)
var val = parseJson(p, rawIntegers, rawFloats)
var val = parseJson(p, rawIntegers, rawFloats, depth+1)
result[key] = val
if p.tok != tkComma: break
discard getTok(p)
eat(p, tkCurlyRi)
of tkBracketLe:
if depth > DepthLimit:
raiseParseErr(p, "]")
result = newJArray()
discard getTok(p)
while p.tok != tkBracketRi:
result.add(parseJson(p, rawIntegers, rawFloats))
result.add(parseJson(p, rawIntegers, rawFloats, depth+1))
if p.tok != tkComma: break
discard getTok(p)
eat(p, tkBracketRi)

View File

@@ -207,9 +207,9 @@ proc getProtoByName*(name: string): int {.since: (1, 3, 5).} =
let protoent = winlean.getprotobyname(name.cstring)
else:
let protoent = posix.getprotobyname(name.cstring)
if protoent == nil:
raise newException(OsError, "protocol not found")
raise newException(OSError, "protocol not found")
result = protoent.p_proto.int

View File

@@ -12,24 +12,24 @@
## produce a globally distributed unique ID. This implementation was extracted
## from the Mongodb interface and it thus binary compatible with a Mongo OID.
##
## This implementation calls ``math.randomize()`` for the first call of
## This implementation calls `initRand()` for the first call of
## ``genOid``.
import hashes, times, endians
import hashes, times, endians, random
type
Oid* = object ## an OID
Oid* = object ## An OID.
time: int32 ##
fuzz: int32 ##
count: int32 ##
proc `==`*(oid1: Oid, oid2: Oid): bool =
## Compare two Mongo Object IDs for equality
## Compares two Mongo Object IDs for equality.
return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and
(oid1.count == oid2.count)
proc hash*(oid: Oid): Hash =
## Generate hash of Oid for use in hashtables
## Generates hash of Oid for use in hashtables.
var h: Hash = 0
h = h !& hash(oid.time)
h = h !& hash(oid.fuzz)
@@ -44,7 +44,7 @@ proc hexbyte*(hex: char): int =
else: discard
proc parseOid*(str: cstring): Oid =
## parses an OID.
## Parses an OID.
var bytes = cast[cstring](addr(result.time))
var i = 0
while i < 12:
@@ -52,6 +52,7 @@ proc parseOid*(str: cstring): Oid =
inc(i)
proc oidToString*(oid: Oid, str: cstring) =
## Converts an oid to `str` which must have space allocated for 25 elements.
const hex = "0123456789abcdef"
# work around a compiler bug:
var str = str
@@ -66,35 +67,33 @@ proc oidToString*(oid: Oid, str: cstring) =
str[24] = '\0'
proc `$`*(oid: Oid): string =
## Converts an oid to string.
result = newString(24)
oidToString(oid, result)
proc rand(): cint {.importc: "rand", header: "<stdlib.h>", nodecl.}
proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>", nodecl.}
var t = getTime().toUnix.int32
srand(t)
var
incr: int = rand()
fuzz: int32 = rand()
t = getTime().toUnix.int32
seed = initRand(t)
incr: int = seed.rand(int.high)
let fuzz = cast[int32](seed.rand(high(int)))
proc genOid*(): Oid =
## generates a new OID.
## Generates a new OID.
runnableExamples:
doAssert ($genOid()).len == 24
if false: doAssert $genOid() == "5fc7f546ddbbc84800006aaf"
t = getTime().toUnix.int32
var i = int32(atomicInc(incr))
var i = cast[int32](atomicInc(incr))
bigEndian32(addr result.time, addr(t))
result.fuzz = fuzz
bigEndian32(addr result.count, addr(i))
proc generatedTime*(oid: Oid): Time =
## returns the generated timestamp of the OID.
## Returns the generated timestamp of the OID.
var tmp: int32
var dummy = oid.time
bigEndian32(addr(tmp), addr(dummy))
result = fromUnix(tmp)
when not defined(testing) and isMainModule:
let xo = genOid()
echo xo.generatedTime

View File

@@ -333,7 +333,7 @@ proc runeReverseOffset*(s: string, rev: Positive): (int, int) =
## from the end (starting with 1) and the total
## number of runes in the string.
##
## Returns a negative value for offset if there are to few runes in
## Returns a negative value for offset if there are too few runes in
## the string to satisfy the request.
##
## **Beware:** This can lead to unoptimized code and slow execution!
@@ -346,16 +346,14 @@ proc runeReverseOffset*(s: string, rev: Positive): (int, int) =
a = rev.int
o = 0
x = 0
let times = 2*rev.int-s.runeLen # transformed from rev.int - a < s.runeLen - rev.int
while o < s.len:
let r = runeLenAt(s, o)
o += r
if a < 0:
if a > times:
x += r
dec a
if a > 0:
return (-a, rev.int-a)
return (x, -a+rev.int)
result = if a > 0: (-a, rev.int-a) else: (x, -a+rev.int)
proc runeAtPos*(s: string, pos: int): Rune =
## Returns the rune at position ``pos``.

View File

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

View File

@@ -33,7 +33,10 @@ proc c_abort*() {.
importc: "abort", header: "<stdlib.h>", noSideEffect, noreturn.}
when defined(linux) and defined(amd64):
when defined(nimBuiltinSetjmp):
type
C_JmpBuf* = array[5, pointer]
elif defined(linux) and defined(amd64):
type
C_JmpBuf* {.importc: "jmp_buf", header: "<setjmp.h>", bycopy.} = object
abi: array[200 div sizeof(clong), clong]
@@ -89,18 +92,47 @@ when defined(macosx):
elif defined(haiku):
const SIGBUS* = cint(30)
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
# "nimRawSetjmp" is defined by default for certain platforms, so we need the
# "nimStdSetjmp" escape hatch with it.
when defined(nimSigSetjmp):
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "siglongjmp".}
template c_setjmp*(jmpb: C_JmpBuf): cint =
proc c_setjmp*(jmpb: C_JmpBuf): cint =
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
header: "<setjmp.h>", importc: "sigsetjmp".}
c_sigsetjmp(jmpb, 0)
elif defined(nimBuiltinSetjmp):
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) =
# Apple's Clang++ has trouble converting array names to pointers, so we need
# to be very explicit here.
proc c_builtin_longjmp(jmpb: ptr pointer, retval: cint) {.
importc: "__builtin_longjmp", nodecl.}
# The second parameter needs to be 1 and sometimes the C/C++ compiler checks it.
c_builtin_longjmp(unsafeAddr jmpb[0], 1)
proc c_setjmp*(jmpb: C_JmpBuf): cint =
proc c_builtin_setjmp(jmpb: ptr pointer): cint {.
importc: "__builtin_setjmp", nodecl.}
c_builtin_setjmp(unsafeAddr jmpb[0])
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "_longjmp".}
proc c_setjmp*(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "_setjmp".}
when defined(windows):
# No `_longjmp()` on Windows.
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "longjmp".}
# The Windows `_setjmp()` takes two arguments, with the second being an
# undocumented buffer used by the SEH mechanism for stack unwinding.
# Mingw-w64 has been trying to get it right for years, but it's still
# prone to stack corruption during unwinding, so we disable that by setting
# it to NULL.
# More details: https://github.com/status-im/nimbus-eth2/issues/3121
proc c_setjmp*(jmpb: C_JmpBuf): cint =
proc c_setjmp_win(jmpb: C_JmpBuf, ctx: pointer): cint {.
header: "<setjmp.h>", importc: "_setjmp".}
c_setjmp_win(jmpb, nil)
else:
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "_longjmp".}
proc c_setjmp*(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "_setjmp".}
else:
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "longjmp".}

View File

@@ -440,9 +440,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
pushCurrentException(e)
{.emit: "throw e;".}
elif defined(nimQuirky) or gotoBasedExceptions:
# XXX This check should likely also be done in the setjmp case below.
if e != currException:
pushCurrentException(e)
pushCurrentException(e)
when gotoBasedExceptions:
inc nimInErrorMode
else:

View File

@@ -240,15 +240,16 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
var ti = 0
let maxlen = t.high - "e+000".len # reserve enough space for exponent
result = i - start
let endPos = i
result = endPos - start
i = start
# re-parse without error checking, any error should be handled by the code above.
if i < s.len and s[i] == '.': i.inc
while i < s.len and s[i] in {'0'..'9','+','-'}:
if i < endPos and s[i] == '.': i.inc
while i < endPos and s[i] in {'0'..'9','+','-'}:
if ti < maxlen:
t[ti] = s[i]; inc(ti)
inc(i)
while i < s.len and s[i] in {'.', '_'}: # skip underscore and decimal point
while i < endPos and s[i] in {'.', '_'}: # skip underscore and decimal point
inc(i)
# insert exponent

View File

@@ -36,9 +36,9 @@ pkg1 "dashing", "nim c tests/functional.nim"
pkg1 "delaunay"
pkg1 "docopt"
pkg1 "easygl", "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl"
pkg1 "elvis"
# pkg1 "elvis"
# pkg1 "fidget"
pkg1 "fragments", "nim c -r fragments/dsl.nim"
# pkg1 "fragments", "nim c -r fragments/dsl.nim"
pkg1 "gara"
pkg1 "ggplotnim", "nim c -d:noCairo -r tests/tests.nim"
# pkg1 "gittyup", "nimble test", "https://github.com/disruptek/gittyup"
@@ -85,12 +85,12 @@ pkg2 "nimquery"
pkg2 "nimsl"
pkg2 "nimsvg"
pkg2 "nimterop", "nimble minitest"
pkg2 "nimwc", "nim c nimwc.nim"
# pkg2 "nimwc", "nim c nimwc.nim"
# pkg2 "nimx", "nim c --threads:on test/main.nim"
# pkg2 "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
pkg2 "norm", "nim c -r tests/sqlite/trows.nim"
pkg2 "npeg", "nimble testarc"
pkg2 "numericalnim", "nim c -r tests/test_integrate.nim"
pkg2 "numericalnim", "nimble nimCI"
pkg2 "optionsutils"
pkg2 "ormin", "nim c -o:orminn ormin.nim"
pkg2 "parsetoml"
@@ -98,7 +98,7 @@ pkg2 "patty"
pkg2 "plotly", "nim c examples/all.nim"
pkg2 "pnm"
pkg2 "polypbren"
pkg2 "prologue", "nimble tcompile"
# pkg2 "prologue", "nimble tcompile"
pkg2 "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
pkg2 "pylib"
pkg2 "rbtree"
@@ -114,7 +114,7 @@ pkg2 "snip", "nimble test", "https://github.com/genotrance/snip"
pkg2 "strslice"
pkg2 "strunicode", "nim c -r src/strunicode.nim"
pkg2 "synthesis"
pkg2 "telebot", "nim c -o:tbot -r src/telebot.nim"
# pkg2 "telebot", "nim c -o:tbot -r src/telebot.nim"
pkg2 "tempdir"
pkg2 "templates"
pkg2 "tensordsl", "nim c -r tests/tests.nim", "https://krux02@bitbucket.org/krux02/tensordslnim.git"

View File

@@ -590,3 +590,14 @@ block t12466:
a[0'u16 + i] = i
for i in 0'u16 ..< 8'u16:
a[0'u16 + i] = i
block t18643:
# https://github.com/nim-lang/Nim/issues/18643
let a: array[0, int] = []
var caught = false
let b = 9999999
try:
echo a[b]
except IndexDefect:
caught = true
doAssert caught, "IndexDefect not caught!"

16
tests/ccgbugs/tmangle.nim Normal file
View File

@@ -0,0 +1,16 @@
block:
proc hello() =
let NAN_INFINITY = 12
doAssert NAN_INFINITY == 12
let INF = "2.0"
doAssert INF == "2.0"
let NAN = 2.3
doAssert NAN == 2.3
hello()
block:
proc hello(NAN: float) =
doAssert NAN == 2.0
hello(2.0)

View File

@@ -1,4 +1,6 @@
discard """
disabled: "windows" # no sigsetjmp() there
matrix: "-d:nimStdSetjmp; -d:nimSigSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
output: '''
BEFORE
FINALLY
@@ -16,7 +18,7 @@ FINALLY
echo ""
proc no_expcetion =
proc no_exception =
try:
echo "BEFORE"
@@ -27,7 +29,7 @@ proc no_expcetion =
finally:
echo "FINALLY"
try: no_expcetion()
try: no_exception()
except: echo "RECOVER"
echo ""

View File

@@ -0,0 +1,130 @@
discard """
disabled: "posix" # already covered by texceptions.nim
matrix: "-d:nimStdSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
output: '''
BEFORE
FINALLY
BEFORE
EXCEPT
FINALLY
RECOVER
BEFORE
EXCEPT: IOError: hi
FINALLY
'''
"""
echo ""
proc no_exception =
try:
echo "BEFORE"
except:
echo "EXCEPT"
raise
finally:
echo "FINALLY"
try: no_exception()
except: echo "RECOVER"
echo ""
proc reraise_in_except =
try:
echo "BEFORE"
raise newException(IOError, "")
except IOError:
echo "EXCEPT"
raise
finally:
echo "FINALLY"
try: reraise_in_except()
except: echo "RECOVER"
echo ""
proc return_in_except =
try:
echo "BEFORE"
raise newException(IOError, "hi")
except:
echo "EXCEPT: ", getCurrentException().name, ": ", getCurrentExceptionMsg()
return
finally:
echo "FINALLY"
try: return_in_except()
except: echo "RECOVER"
block: #10417
proc moo() {.noreturn.} = discard
let bar =
try:
1
except:
moo()
doAssert(bar == 1)
# Make sure the VM handles the exceptions correctly
block:
proc fun1(): seq[int] =
try:
try:
raise newException(ValueError, "xx")
except:
doAssert("xx" == getCurrentExceptionMsg())
raise newException(KeyError, "yy")
except:
doAssert("yy" == getCurrentExceptionMsg())
result.add(1212)
try:
try:
raise newException(AssertionDefect, "a")
finally:
result.add(42)
except AssertionDefect:
result.add(99)
finally:
result.add(10)
result.add(4)
result.add(0)
try:
result.add(1)
except KeyError:
result.add(-1)
except ValueError:
result.add(-1)
except IndexDefect:
result.add(2)
except:
result.add(3)
try:
try:
result.add(1)
return
except:
result.add(-1)
finally:
result.add(2)
except KeyError:
doAssert(false)
finally:
result.add(3)
let x1 = fun1()
const x2 = fun1()
doAssert(x1 == x2)

View File

@@ -29,6 +29,14 @@ end
9018
@[1, 2]
@[1, 2, 3]
nested finally
outer finally
nested finally
outer finally
nested finally
outer finally
nested finally
outer finally
'''
"""
@@ -251,3 +259,71 @@ block:
for x in ff(@[1, 2], @[1, 2, 3]):
echo x
block:
# bug #19911 (return in nested try)
# try yield -> try
iterator p1: int {.closure.} =
try:
yield 0
try:
return
finally:
echo "nested finally"
echo "shouldn't run"
finally:
echo "outer finally"
echo "shouldn't run"
for _ in p1():
discard
# try -> try yield
iterator p2: int {.closure.} =
try:
try:
yield 0
return
finally:
echo "nested finally"
echo "shouldn't run"
finally:
echo "outer finally"
echo "shouldn't run"
for _ in p2():
discard
# try yield -> try yield
iterator p3: int {.closure.} =
try:
yield 0
try:
yield 0
return
finally:
echo "nested finally"
echo "shouldn't run"
finally:
echo "outer finally"
echo "shouldn't run"
for _ in p3():
discard
# try -> try
iterator p4: int {.closure.} =
try:
try:
return
finally:
echo "nested finally"
echo "shouldn't run"
finally:
echo "outer finally"
echo "shouldn't run"
for _ in p4():
discard

View File

@@ -483,5 +483,19 @@ block: # nnkChckRange
test(it, 1, 2, 3)
echo "ok"
block: #17849 - yield in case subject
template yieldInCase: int =
yield 2
3
iterator it(): int {.closure.} =
yield 1
case yieldInCase()
of 1: checkpoint(11)
of 3: checkpoint(13)
else: checkpoint(14)
yield 5
test(it, 1, 2, 13, 5)
echo "ok"

54
tests/macros/t14511.nim Normal file
View File

@@ -0,0 +1,54 @@
discard """
output: "true\n(y: XInt, a: 5)\n(y: XString, b: \"abc\")"
"""
import macros
block TEST_1:
# https://github.com/nim-lang/Nim/issues/14511
template myPragma() {.pragma.}
type
XType = enum
XInt,
XString,
XUnused
X = object
case y {.myPragma.}: XType
of XInt, XUnused:
a: int
else: # <-- Else case caused the "Error: index 1 not in 0 .. 0" error
b: string
var x: X = X(y: XInt, a: 5)
echo x.y.hasCustomPragma(myPragma)
echo x
echo X(y: XString, b: "abc")
block TEST_2:
template myDevice(val: string) {.pragma.}
template myKey(val: string) {.pragma.}
template myMouse(val: string) {.pragma.}
type
Device {.pure.} = enum Keyboard, Mouse
Key = enum Key1, Key2
Mouse = enum Mouse1, Mouse2
type
Obj = object of RootObj
case device {.myDevice: "MyDevicePragmaStr".}: Device
of Device.Keyboard:
key {.myKey: "MyKeyPragmaStr".}: Key
else: # <-- Else case caused the "Error: index 1 not in 0 .. 0" error
mouse {.myMouse: "MyMousePragmaStr".}: Mouse
var obj: Obj
assert obj.device.hasCustomPragma(myDevice) == true
assert obj.key.hasCustomPragma(myKey) == true
assert obj.mouse.hasCustomPragma(myMouse) == true
assert obj.device.getCustomPragmaVal(myDevice) == "MyDevicePragmaStr"
assert obj.key.getCustomPragmaVal(myKey) == "MyKeyPragmaStr"
assert obj.mouse.getCustomPragmaVal(myMouse) == "MyMousePragmaStr"

12
tests/objects/m19342.c Normal file
View File

@@ -0,0 +1,12 @@
struct Node
{
int data[25];
};
struct Node hello(int name) {
struct Node x = {999, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,
1, 2, 3, 4, 5};
return x;
}

18
tests/objects/t19342.nim Normal file
View File

@@ -0,0 +1,18 @@
discard """
targets: "c cpp"
"""
{.compile: "m19342.c".}
# bug #19342
type
Node* {.bycopy.} = object
data: array[25, cint]
proc myproc(name: cint): Node {.importc: "hello", cdecl.}
proc parse =
let node = myproc(10)
doAssert node.data[0] == 999
parse()

View File

@@ -0,0 +1,20 @@
discard """
errormsg: "got <B, proc (b: B){.closure, gcsafe, locks: 0.}>"
line: 20
"""
type
A = ref object of RootObj
B = ref object of A
P = proc (a: A)
# bug #16325
proc doThings(a: A, p: P) =
p(a)
var x = proc (b: B) {.closure.} =
echo "B"
doThings(B(), x)

View File

@@ -0,0 +1,2 @@
type Foo = distinct uint64
const slice = 0 ..< 42.Foo

View File

@@ -255,3 +255,35 @@ block: # bug #17383
when not defined(js):
testRoundtrip(int64.high): "9223372036854775807"
testRoundtrip(uint64.high): "18446744073709551615"
block:
let a = """
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
"""
when not defined(js):
try:
discard parseJson(a)
except JsonParsingError:
doAssert getCurrentExceptionMsg().contains("] expected")

6
tests/stdlib/toids.nim Normal file
View File

@@ -0,0 +1,6 @@
import std/oids
block: # genOid
let x = genOid()
doAssert ($x).len == 24

View File

@@ -1,5 +1,5 @@
import parseutils
import sequtils
import std/[parseutils, sequtils]
let input = "$test{} $this is ${an{ example}} "
let expected = @[(ikVar, "test"), (ikStr, "{} "), (ikVar, "this"),

View File

@@ -1,4 +1,4 @@
import unicode
import std/unicode
proc asRune(s: static[string]): Rune =
@@ -213,3 +213,10 @@ block differentSizes:
doAssert swapCase("ⱥbCd") == "ȺBcD"
doAssert swapCase("XyꟆaB") == "xYᶎAb"
doAssert swapCase("aᵹcᲈd") == "AꝽCꙊD"
block: # bug #17768
let s1 = "abcdef"
let s2 = "abcdéf"
doAssert s1.runeSubstr(0, -1) == "abcde"
doAssert s2.runeSubstr(0, -1) == "abcdé"

View File

@@ -41,7 +41,7 @@ proc downloadMingw(): DownloadResult =
let curl = findExe"curl"
var cmd: string
if curl.len > 0:
cmd = quoteShell(curl) & " --out " & "dist" / mingw & " " & url
cmd = quoteShell(curl) & " --output " & "dist" / mingw & " " & url
elif fileExists"bin/nimgrab.exe":
cmd = r"bin\nimgrab.exe " & url & " dist" / mingw
if cmd.len > 0: