mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
34 Commits
v1.4.8
...
version-1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce295d7243 | ||
|
|
c6e0983b47 | ||
|
|
c5cd23a776 | ||
|
|
30ba13d22a | ||
|
|
315f4ecff1 | ||
|
|
49379e85ec | ||
|
|
6ab3c1b365 | ||
|
|
0dae9115c8 | ||
|
|
32882fa024 | ||
|
|
dc1e948f15 | ||
|
|
65db3013a8 | ||
|
|
7f0e662032 | ||
|
|
547973c3e9 | ||
|
|
4d5c5893ae | ||
|
|
8c356fd971 | ||
|
|
17522d6ae1 | ||
|
|
f8047c3e3c | ||
|
|
cfb6ebc07a | ||
|
|
8f20400466 | ||
|
|
6d3b706f6e | ||
|
|
0df0510722 | ||
|
|
68df3c9afd | ||
|
|
a8aaf5a27d | ||
|
|
80c8107c56 | ||
|
|
5bed375b52 | ||
|
|
1228c5b3fc | ||
|
|
0a8e9318d3 | ||
|
|
22650a61e7 | ||
|
|
8b80039cac | ||
|
|
b18c6fd09b | ||
|
|
88340aab6d | ||
|
|
8a3e64f00e | ||
|
|
6c5585fc0b | ||
|
|
ca1b7feb0f |
2
.github/workflows/ci_docs.yml
vendored
2
.github/workflows/ci_docs.yml
vendored
@@ -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 }}
|
||||
|
||||
2
.github/workflows/ci_packages.yml
vendored
2
.github/workflows/ci_packages.yml
vendored
@@ -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 }})'
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}:
|
||||
|
||||
@@ -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)])
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
16
doc/nimc.rst
16
doc/nimc.rst
@@ -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
|
||||
-------------------
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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``.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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".}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
16
tests/ccgbugs/tmangle.nim
Normal 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)
|
||||
@@ -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 ""
|
||||
|
||||
130
tests/exception/texceptions2.nim
Normal file
130
tests/exception/texceptions2.nim
Normal 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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
54
tests/macros/t14511.nim
Normal 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
12
tests/objects/m19342.c
Normal 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
18
tests/objects/t19342.nim
Normal 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()
|
||||
20
tests/overload/tproc_types_dont_like_subtypes.nim
Normal file
20
tests/overload/tproc_types_dont_like_subtypes.nim
Normal 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)
|
||||
2
tests/slice/tdistinctslice.nim
Normal file
2
tests/slice/tdistinctslice.nim
Normal file
@@ -0,0 +1,2 @@
|
||||
type Foo = distinct uint64
|
||||
const slice = 0 ..< 42.Foo
|
||||
@@ -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
6
tests/stdlib/toids.nim
Normal file
@@ -0,0 +1,6 @@
|
||||
import std/oids
|
||||
|
||||
|
||||
block: # genOid
|
||||
let x = genOid()
|
||||
doAssert ($x).len == 24
|
||||
@@ -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"),
|
||||
|
||||
@@ -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é"
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user