Compare commits

...

39 Commits

Author SHA1 Message Date
tersec
772b62cdeb don't access void* out of alignment in refc GC to avoid UB (#21560)
(cherry picked from commit e8a70ff179)
2023-04-05 08:10:11 +02:00
ringabout
82e9ec3b5c 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:49:17 +02:00
narimiran
7e3e04c469 use --stylecheck:hint for chronicles package 2022-07-20 12:01:17 +02:00
Tanguy
f2bbff989f 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:16:06 +02:00
narimiran
de715892ac fix one more Defect 2022-06-22 10:19:00 +02:00
narimiran
24fb72c8ad no Defects in Nim 1.2 2022-06-21 12:24:12 +02:00
Tanguy
7e5686a828 Fix nimRawSetjmp for VCC [backport: 1.2] (#19899)
(cherry picked from commit 40464fa762)
2022-06-20 08:52:56 +02:00
Tanguy
843c479593 Windows: enable nimRawSetjmp by default [backport] (#19891)
* Windows: enable nimRawSetjmp by default

See #19197. The default setjmp can randomly segfault on windows

* Attempt to disable the flag for bootstraping

* Disable styleCheck for c_setjmp

(cherry picked from commit 251bdc1d5a)
2022-06-20 08:52:17 +02:00
flywind
7b35ce9812 fix NimNode comment repr() regression [backport: 1.2] (#19726)
(cherry picked from commit 15ae9323e8)
2022-06-20 08:49:34 +02:00
flywind
0798bd020b setjump => setjmp [backport: 1.2] (#19496)
(cherry picked from commit d0287748fe)
2022-06-20 08:48:57 +02:00
narimiran
c956aeae7f bump NimVersion to 1.2.19 2022-06-20 08:47:19 +02:00
narimiran
af3d1342c0 disable more packages that don't work anymore on Nim 1.2.x 2022-06-10 10:33:26 +02:00
narimiran
aa0dbaf3a1 disable packages that don't work anymore on Nim 1.2.x 2022-05-04 18:21:24 +02:00
narimiran
8a5c8d3e22 bump NimVersion to 1.2.18 2022-02-08 15:19:37 +01:00
narimiran
315a286d7c disable 'fragments' and 'telebot' packages 2022-01-17 11:27:23 +01:00
flywind
1d92e79dac 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:36 +01:00
narimiran
01c8262426 bump NimVersion to 1.2.17 2022-01-17 07:41:23 +01:00
flywind
5e102df04d nrvo shouldn't touch bycopy object[backport:1.2] (#19385)
fix nim-lang#19342

(cherry picked from commit 9b9ae8a487)
2022-01-17 07:40:54 +01:00
Andreas Rumpf
57c9de181a Revert "Update uri.nim (#19148) [backport:1.0]" (#19280)
This reverts commit a3ef5df680.

(cherry picked from commit 81d32cf7e5)
2021-12-31 05:23:04 +01:00
narimiran
eeea72060c bump NimVersion to 1.2.16 2021-12-16 09:05:32 +01:00
Miran
0b1fee5d66 [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:23:42 +01:00
flywind
594831620b 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:00:32 +01:00
Dominik Picheta
2eb0442a9a Update uri.nim (#19148) [backport:1.0]
(cherry picked from commit a3ef5df680)
2021-12-11 09:25:46 +01:00
Ștefan Talpalaru
002621b61d nimc.rst: fix table markup (#19239)
(cherry picked from commit 1a92edeb89)
2021-12-11 05:48:38 +01:00
Ștefan Talpalaru
8ea5475dd9 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:35 +01:00
Andreas Rumpf
3e6d708175 implements https://github.com/nim-lang/RFCs/issues/260 (#15505)
* implements https://github.com/nim-lang/RFCs/issues/260

* added a test case

(cherry picked from commit 51e3e0c7c4)
2021-12-10 14:59:44 +01:00
narimiran
e3fb2c21d7 rename the file to prevent clashes in megatest 2021-12-08 14:58:18 +01:00
narimiran
c4ab020f0f correctly enable chronos 2021-12-08 08:26:01 +01:00
Tanguy
6e4fdbc4a9 fix #19193 (#19195) [backport:1.2]
(cherry picked from commit cd592ed85b)
2021-12-07 21:51:46 +01:00
Andreas Rumpf
497d061cd1 re-enable chronos testing once again [backport:1.2] (#19222)
(cherry picked from commit 93c8427fca)
2021-12-07 21:49:26 +01:00
Etan Kissling
4cb522fb8a 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-07 21:48:08 +01:00
narimiran
84c1b1af0e we must use Ubuntu 18.04 2021-12-07 19:27:45 +01:00
narimiran
a683ca3fac bigints are not supposed to work on 1.2.x 2021-12-07 19:15:47 +01:00
narimiran
f7ea7b3c4f disable nimpy 2021-12-07 18:09:57 +01:00
Andreas Rumpf
a34845b66c fixes #11225; generic sandwich problems; [backport:1.2] (#17255)
* fixes #11225; generic sandwich problems; [backport:1.2]
* progress
* delegating these symbols must be done via 'bind'

(cherry picked from commit 2f213db7ee)
2021-12-07 16:34:58 +01:00
Andreas Rumpf
79f95a2efc misc bugfixes [backport:1.2] (#19203)
(cherry picked from commit 23c117a950)
2021-12-06 12:53:37 +01:00
Andreas Rumpf
8a3f542532 fixes #14470 [backport:1.2] (#19115)
(cherry picked from commit 15157d06c3)
2021-12-06 12:51:56 +01:00
Andreas Rumpf
2009df72cb fixes a 'mixin' statement handling regression [backport:1.2] (#18968)
(cherry picked from commit 8eef557157)
2021-12-06 12:51:32 +01:00
narimiran
f4216f12b3 bump NimVersion to 1.2.15 2021-12-06 12:50:03 +01:00
53 changed files with 662 additions and 122 deletions

View File

@@ -27,7 +27,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

@@ -15,23 +15,23 @@ 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:
vmImage: 'windows-2019'
CPU: amd64
Linux_amd64_pkg:
vmImage: 'ubuntu-16.04'
vmImage: 'ubuntu-18.04'
CPU: amd64
NIM_TEST_PACKAGES: true
OSX_amd64_pkg:

View File

@@ -2741,6 +2741,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
inc p.splitDecls
genGotoState(p, n)
of nkBreakState: genBreakState(p, n, d)
of nkMixinStmt, nkBindStmt: discard
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope =

View File

@@ -1330,8 +1330,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])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])

View File

@@ -220,7 +220,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)
of ctArray:

View File

@@ -432,8 +432,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)])
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)])
else:
if not isTemp or containsGarbageCollectedRef(loc.t):
# don't use nimZeroMem for temporary values for performance if we can
@@ -838,7 +844,8 @@ proc containsResult(n: PNode): bool =
for i in 0..<n.safeLen:
if containsResult(n[i]): return true
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef, nkMacroDef} +
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
nkMacroDef, nkMixinStmt, nkBindStmt} +
declarativeDefs
proc easyResultAsgn(n: PNode): PNode =

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
@@ -156,7 +159,7 @@ type
const
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
nkCommentStmt} + procDefs
nkCommentStmt, nkMixinStmt, nkBindStmt} + procDefs
proc newStateAccess(ctx: var Ctx): PNode =
if ctx.stateVarSym.isNil:
@@ -793,7 +796,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()
@@ -802,11 +808,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)
@@ -850,6 +862,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

@@ -225,7 +225,7 @@ const
errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
case switch.normalize

View File

@@ -651,6 +651,10 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
if useCpp(conf, cfile.cname):
options.add(' ' & CC[c].cppXsupport)
if cfile.customArgs != "":
options.add ' '
options.add cfile.customArgs
var compilePattern: string
# compute include paths:
var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)

View File

@@ -945,7 +945,8 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState:
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
nkMixinStmt, nkBindStmt:
result = n
of nkBreakStmt:
inc c.hasUnstructuredCf

View File

@@ -2479,7 +2479,8 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
of nkRaiseStmt: genRaiseStmt(p, n)
of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt,
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt: discard
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt,
nkMixinStmt, nkBindStmt: discard
of nkPragma: genPragma(p, n)
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
var s = n[namePos].sym

View File

@@ -493,7 +493,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
w = up
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt,
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
discard
of nkLambdaKinds, nkIteratorDef:
if n.typ != nil:
@@ -747,7 +748,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
result = accessViaEnvVar(n, owner, d, c)
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef, nkConverterDef,
nkMacroDef, nkFuncDef:
nkMacroDef, nkFuncDef, nkMixinStmt, nkBindStmt:
discard
of nkClosure:
if n[1].kind == nkNilLit:

View File

@@ -42,7 +42,7 @@ proc liftLocals(n: PNode; i: int; c: var Ctx) =
of nkSym:
if interestingVar(it.sym):
n[i] = lookupOrAdd(c, it.sym, it.info)
of procDefs, nkTypeSection: discard
of procDefs, nkTypeSection, nkMixinStmt, nkBindStmt: discard
else:
for i in 0..<it.safeLen:
liftLocals(it, i, c)

View File

@@ -181,6 +181,7 @@ type
nimname*: string
cname*, obj*: AbsoluteFile
flags*: set[CfileFlag]
customArgs*: string
CfileList* = seq[Cfile]
Suggest* = ref object

View File

@@ -92,11 +92,10 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
isStatement: bool = false)
proc recordPragma(c: PContext; n: PNode; key, val: string; val2 = "") =
proc recordPragma(c: PContext; n: PNode; args: varargs[string]) =
var recorded = newNodeI(nkCommentStmt, n.info)
recorded.add newStrNode(key, n.info)
recorded.add newStrNode(val, n.info)
if val2.len > 0: recorded.add newStrNode(val2, n.info)
for i in 0..args.high:
recorded.add newStrNode(args[i], n.info)
c.graph.recordStmt(c.graph, c.module, recorded)
const
@@ -496,11 +495,12 @@ proc relativeFile(c: PContext; n: PNode; ext=""): AbsoluteFile =
if result.isEmpty: result = AbsoluteFile s
proc processCompile(c: PContext, n: PNode) =
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile) =
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile; customArgs: string) =
var cf = Cfile(nimname: splitFile(src).name,
cname: src, obj: dest, flags: {CfileFlag.External})
cname: src, obj: dest, flags: {CfileFlag.External},
customArgs: customArgs)
extccomp.addExternalFileToCompile(c.config, cf)
recordPragma(c, it, "compile", src.string, dest.string)
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
proc getStrLit(c: PContext, n: PNode; i: int): string =
n[i] = c.semConstExpr(c, n[i])
@@ -518,9 +518,19 @@ proc processCompile(c: PContext, n: PNode) =
var found = parentDir(toFullPath(c.config, n.info)) / s
for f in os.walkFiles(found):
let obj = completeCfilePath(c.config, AbsoluteFile(dest % extractFilename(f)))
docompile(c, it, AbsoluteFile f, obj)
docompile(c, it, AbsoluteFile f, obj, "")
else:
let s = expectStrLit(c, n)
var s = ""
var customArgs = ""
if n.kind in nkCallKinds:
s = getStrLit(c, n, 1)
if n.len <= 3:
customArgs = getStrLit(c, n, 2)
else:
localError(c.config, n.info, "'.compile' pragma takes up 2 arguments")
else:
s = expectStrLit(c, n)
var found = AbsoluteFile(parentDir(toFullPath(c.config, n.info)) / s)
if not fileExists(found):
if isAbsolute(s): found = AbsoluteFile s
@@ -528,7 +538,7 @@ proc processCompile(c: PContext, n: PNode) =
found = findFile(c.config, s)
if found.isEmpty: found = AbsoluteFile s
let obj = toObjFile(c.config, completeCfilePath(c.config, found, false))
docompile(c, it, found, obj)
docompile(c, it, found, obj, customArgs)
proc processLink(c: PContext, n: PNode) =
let found = relativeFile(c, n, CC[c.config.cCompiler].objExt)

View File

@@ -150,6 +150,7 @@ proc putNL(g: var TSrcGen) =
proc optNL(g: var TSrcGen, indent: int) =
g.pendingNL = indent
g.lineLen = indent
g.col = g.indent
when defined(nimpretty): g.pendingNewlineCount = 0
proc optNL(g: var TSrcGen) =
@@ -158,6 +159,7 @@ proc optNL(g: var TSrcGen) =
proc optNL(g: var TSrcGen; a, b: PNode) =
g.pendingNL = g.indent
g.lineLen = g.indent
g.col = g.indent
when defined(nimpretty): g.pendingNewlineCount = lineDiff(a, b)
proc indentNL(g: var TSrcGen) =

View File

@@ -106,6 +106,7 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
decl(a[1])
else:
for i in 0..<n.safeLen: deps(n[i])
of nkMixinStmt, nkBindStmt: discard
else:
for i in 0..<n.safeLen: deps(n[i])

View File

@@ -838,11 +838,12 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
of "warning": message(g.config, n.info, warnUser, n[1].strVal)
of "error": localError(g.config, n.info, errUser, n[1].strVal)
of "compile":
internalAssert g.config, n.len == 3 and n[2].kind == nkStrLit
internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit
let cname = AbsoluteFile n[1].strVal
var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
obj: AbsoluteFile n[2].strVal,
flags: {CfileFlag.External})
flags: {CfileFlag.External},
customArgs: n[3].strVal)
extccomp.addExternalFileToCompile(g.config, cf)
of "link":
extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal)

View File

@@ -38,6 +38,7 @@ type
mappingExists*: bool
mapping*: TIdTable
caseContext*: seq[tuple[n: PNode, idx: int]]
localBindStmts*: seq[PNode]
TMatchedConcept* = object
candidateType*: PType

View File

@@ -2833,6 +2833,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
for i in 0..<n.len:
n[i] = semExpr(c, n[i])
of nkComesFrom: discard "ignore the comes from information for now"
of nkMixinStmt: discard
of nkBindStmt:
if c.p != nil:
c.p.localBindStmts.add n
else:
localError(c.config, n.info, "invalid context for 'bind' statement: " &
renderTree(n, {renderNoComments}))
else:
localError(c.config, n.info, "invalid expression: " &
renderTree(n, {renderNoComments}))

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

@@ -319,6 +319,14 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
prc.typ = result
popInfoContext(c.config)
proc fillMixinScope(c: PContext) =
var p = c.p
while p != nil:
for bnd in p.localBindStmts:
for n in bnd:
addSym(c.currentScope, n.sym)
p = p.next
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
info: TLineInfo): PSym =
## Generates a new instance of a generic procedure.
@@ -345,6 +353,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
result.ast = n
pushOwner(c, result)
# mixin scope:
openScope(c)
fillMixinScope(c)
openScope(c)
let gp = n[genericParamsPos]
internalAssert c.config, gp.kind != nkEmpty
@@ -395,6 +407,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
popProcCon(c)
popInfoContext(c.config)
closeScope(c) # close scope for parameters
closeScope(c) # close scope for 'mixin' declarations
popOwner(c)
c.currentScope = oldScope
discard c.friendModules.pop()

View File

@@ -359,12 +359,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

@@ -391,7 +391,8 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
addFactNeg(c.guards, canon(n[0], c.guards.o))
dec c.inLoop
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef:
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef,
nkMixinStmt, nkBindStmt, nkExportStmt:
discard
else:
analyseSons(c, n)

View File

@@ -1828,8 +1828,8 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
let t = tt[col]
if t != nil and t.kind == tyGenericInvocation:
var x = skipTypes(t[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
tyGenericInvocation, tyGenericBody,
tyAlias, tySink, tyOwned})
tyGenericInvocation, tyGenericBody,
tyAlias, tySink, tyOwned})
if x.kind == tyObject and t.len-1 == n[genericParamsPos].len:
foundObj = true
x.methods.add((col,s))

View File

@@ -86,6 +86,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
a = nextOverloadIter(o, c, n)
proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
result = copyNode(n)
for i in 0..<n.len:
var a = n[i]
# If 'a' is an overloaded symbol, we used to use the first symbol
@@ -99,16 +100,24 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
let sc = symChoice(c, n, s, scClosed)
if sc.kind == nkSym:
toBind.incl(sc.sym.id)
result.add sc
else:
for x in items(sc): toBind.incl(x.sym.id)
for x in items(sc):
toBind.incl(x.sym.id)
result.add x
else:
illFormedAst(a, c.config)
result = newNodeI(nkEmpty, n.info)
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 = newNodeI(nkEmpty, n.info)
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

@@ -993,7 +993,7 @@ proc transform(c: PTransf, n: PNode): PNode =
of nkConstSection:
# do not replace ``const c = 3`` with ``const 3 = 3``
return transformConstSection(c, n)
of nkTypeSection, nkTypeOfExpr:
of nkTypeSection, nkTypeOfExpr, nkMixinStmt, nkBindStmt:
# no need to transform type sections:
return n
of nkVarSection, nkLetSection:

View File

@@ -2106,7 +2106,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
else:
dest = tmp0
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt,
nkMixinStmt, nkBindStmt:
unused(c, n, dest)
of nkStringToCString, nkCStringToString:
gen(c, n[0], dest)

View File

@@ -3,3 +3,13 @@
when defined(nimHasCppDefine):
cppDefine "errno"
cppDefine "unix"
# mangle the macro names in nimbase.h
cppDefine "NAN_INFINITY"
cppDefine "INF"
cppDefine "NAN"
when defined(windows) and not defined(booting):
# Avoid some rare stack corruption while using exceptions with a SEH-enabled
# toolchain: https://github.com/nim-lang/Nim/pull/19197
switch("define", "nimRawSetjmp")

View File

@@ -47,9 +47,11 @@ 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
into a project using any of these languages. Here are some typical command
line invocations::
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:
.. code:: cmd
$ nim c hallo.nim
$ nim cpp hallo.nim
@@ -108,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>`_
@@ -230,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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -253,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();
@@ -268,13 +266,14 @@ Now you can run the following Unix like commands to first generate C sources
form 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 form ``nimcache``. In addition to this path, you also
have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
@@ -282,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

@@ -4789,6 +4789,50 @@ scope is the default.
``bind`` statements only make sense in templates and generics.
Delegating bind statements
--------------------------
The following example outlines a problem that can arise when generic
instantiations cross multiple different modules:
.. code-block:: nim
# module A
proc genericA*[T](x: T) =
mixin init
init(x)
.. code-block:: nim
import C
# module B
proc genericB*[T](x: T) =
# Without the `bind init` statement C's init proc is
# not available when `genericB` is instantiated:
bind init
genericA(x)
.. code-block:: nim
# module C
type O = object
proc init*(x: var O) = discard
.. code-block:: nim
# module main
import B, C
genericB O()
In module B has an `init` proc from module C in its scope that is not
taken into account when `genericB` is instantiated which leads to the
instantiation of `genericA`. The solution is to `forward`:idx these
symbols by a `bind` statement inside `genericB`.
Templates
=========
@@ -6608,6 +6652,14 @@ with the project:
has changed. One can use the ``-f`` command line option to force recompilation
of the file.
Since 1.4 the `compile` pragma is also available with this syntax:
.. code-block:: Nim
{.compile("myfile.cpp", "--custom flags here").}
As can be seen in the example, this new variant allows for custom flags
that are passed to the C compiler when the file is recompiled.
Link pragma
-----------

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

@@ -181,6 +181,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)
@@ -771,7 +773,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): JsonNode =
proc parseJson(p: var JsonParser, depth=0): JsonNode =
## Parses JSON from a JSON Parser `p`.
case p.tok
of tkString:
@@ -795,6 +797,8 @@ proc parseJson(p: var JsonParser): JsonNode =
result = newJNull()
discard getTok(p)
of tkCurlyLe:
if depth > DepthLimit:
raiseParseErr(p, "}")
result = newJObject()
discard getTok(p)
while p.tok != tkCurlyRi:
@@ -803,16 +807,18 @@ proc parseJson(p: var JsonParser): JsonNode =
var key = p.a
discard getTok(p)
eat(p, tkColon)
var val = parseJson(p)
var val = parseJson(p, 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))
result.add(parseJson(p, depth+1))
if p.tok != tkComma: break
discard getTok(p)
eat(p, tkBracketRi)

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

@@ -2058,7 +2058,7 @@ const
NimMinor* {.intdefine.}: int = 2
## is the minor number of Nim's version.
NimPatch* {.intdefine.}: int = 14
NimPatch* {.intdefine.}: int = 19
## is the patch number of Nim's version.
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch

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,54 @@ 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) and not defined(vcc):
# 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
when defined(nimHasStyleChecks):
{.push styleChecks: off.}
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)
when defined(nimHasStyleChecks):
{.pop.}
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

@@ -381,7 +381,6 @@ else:
let regEnd = sp +% sizeof(registers)
while sp <% regEnd:
gcMark(gch, cast[PPointer](sp)[])
gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
sp = sp +% sizeof(pointer)
# Make sure sp is word-aligned
sp = sp and not (sizeof(pointer) - 1)

View File

@@ -9,16 +9,14 @@ pkg "argparse"
pkg "arraymancer", true, "nim c tests/tests_cpu.nim"
pkg "ast_pattern_matching", false, "nim c -r --oldgensym:on tests/test1.nim"
pkg "asyncmysql", true
pkg "bigints"
pkg "binaryheap", false, "nim c -r binaryheap.nim"
# pkg "blscurve", true # pending https://github.com/status-im/nim-blscurve/issues/39
pkg "bncurve", true
pkg "c2nim", false, "nim c testsuite/tester.nim"
pkg "cascade"
pkg "chroma"
pkg "chronicles", true, "nim c -o:chr -r chronicles.nim"
# disable until my chronos fix was merged
#pkg "chronos", true
pkg "chronicles", true, "nim c --stylecheck:hint -o:chr -r chronicles.nim"
pkg "chronos", true, "nim c -r -d:release tests/testall"
pkg "cligen", false, "nim c -o:cligenn -r cligen.nim"
pkg "coco", true
pkg "combparser"
@@ -28,8 +26,8 @@ pkg "comprehension", false, "nimble test", "https://github.com/alehander42/compr
pkg "dashing", false, "nim c tests/functional.nim"
pkg "docopt"
pkg "easygl", true, "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl"
pkg "elvis"
pkg "fragments", false, "nim c -r fragments/dsl.nim"
# pkg "elvis"
# pkg "fragments", false, "nim c -r fragments/dsl.nim"
pkg "gara"
# pkg "ggplotnim", true, "nimble testCI"
pkg "glob"
@@ -57,7 +55,7 @@ pkg "nimfp", true, "nim c -o:nfp -r src/fp.nim"
# pkg "nimlsp", true
# pkg "nimly", true
# pkg "nimongo", true, "nimble test_ci"
pkg "nimpy", false, "nim c -r tests/nimfrompy.nim"
# pkg "nimpy", false, "nim c -r tests/nimfrompy.nim"
# pkg "nimquery"
pkg "nimsl", true
pkg "nimsvg"
@@ -70,7 +68,7 @@ pkg "ormin", true, "nim c -o:orminn ormin.nim"
pkg "patty"
pkg "plotly", true, "nim c --oldgensym:on examples/all.nim"
pkg "pnm"
pkg "polypbren"
# pkg "polypbren"
pkg "protobuf", true, "nim c -o:protobuff -r src/protobuf.nim"
pkg "rbtree"
pkg "react", false, "nimble example"
@@ -82,10 +80,10 @@ pkg "sdl2_nim", false, "nim c -r sdl2/sdl.nim"
pkg "snip", false, "nimble test", "https://github.com/genotrance/snip"
pkg "stint", false, "nim c -o:stintt -r stint.nim"
pkg "strunicode", true, "nim c -r src/strunicode.nim"
pkg "telebot", true, "nim c -o:tbot -r src/telebot.nim"
# pkg "telebot", true, "nim c -o:tbot -r src/telebot.nim"
pkg "tempdir"
pkg "tensordsl", false, "nim c -r tests/tests.nim", "https://krux02@bitbucket.org/krux02/tensordslnim.git"
pkg "tiny_sqlite"
# pkg "tiny_sqlite"
pkg "unicodedb"
pkg "unicodeplus", true
pkg "unpack"
@@ -93,4 +91,4 @@ pkg "unpack"
pkg "with"
# pkg "ws"
pkg "yaml"
pkg "zero_functional", false, "nim c -r test.nim"
# pkg "zero_functional", false, "nim c -r test.nim"

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(AssertionError, "a")
finally:
result.add(42)
except AssertionError:
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 IndexError:
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

@@ -18,6 +18,14 @@ end
1
2
7
nested finally
outer finally
nested finally
outer finally
nested finally
outer finally
nested finally
outer finally
'''
"""
@@ -213,3 +221,71 @@ block t2023_objiter:
var o = init()
echo(o.iter())
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

@@ -60,3 +60,22 @@ macro foo(t: static Tuple): untyped =
doAssert t.b == 12345
foo((a: "foo", b: 12345))
# bug #16307
macro bug(x: untyped): string =
newLit repr(x)
let res = bug:
block:
## one
## two
## three
doAssert res == """
block:
## one
## two
## three"""

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,4 @@
int cfunction(void) {
return NUMBER_HERE;
}

View File

@@ -0,0 +1,9 @@
discard """
output: '''34'''
"""
{.compile("cfunction.c", "-DNUMBER_HERE=34").}
proc cfunction(): cint {.importc.}
echo cfunction()

View File

@@ -0,0 +1,6 @@
proc libraryFunc*[T](x: T) =
mixin mixedIn, indirectlyMixedIn
echo mixedIn()
echo indirectlyMixedIn()

View File

@@ -0,0 +1,3 @@
proc indirectlyMixedIn*: int =
200

View File

@@ -0,0 +1,12 @@
import
generic_library, helper_module
proc mixedIn: int = 100
proc makeUseOfLibrary*[T](x: T) =
bind mixedIn, indirectlyMixedIn
libraryFunc(x)
when isMainModule:
makeUseOfLibrary "test"

9
tests/sandwich/tmain.nim Normal file
View File

@@ -0,0 +1,9 @@
discard """
output: '''100
200'''
"""
import
module_using_generic_library
makeUseOfLibrary "test"

View File

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

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