Showing with 961 additions and 293 deletions.
  1. +43 −0 changelog.md
  2. +31 −0 changelogs/changelog.md
  3. +9 −1 compiler/ast.nim
  4. +1 −1 compiler/ccgcalls.nim
  5. +8 −0 compiler/ccgexprs.nim
  6. +12 −1 compiler/ccgstmts.nim
  7. +4 −3 compiler/ccgtypes.nim
  8. +30 −20 compiler/cgen.nim
  9. +3 −2 compiler/commands.nim
  10. +2 −0 compiler/condsyms.nim
  11. +4 −2 compiler/importer.nim
  12. +16 −1 compiler/isolation_check.nim
  13. +10 −0 compiler/liftdestructors.nim
  14. +3 −1 compiler/options.nim
  15. +1 −1 compiler/parser.nim
  16. +3 −1 compiler/pragmas.nim
  17. +8 −8 compiler/semfold.nim
  18. +3 −4 compiler/semobjconstr.nim
  19. +6 −2 compiler/sempass2.nim
  20. +2 −1 compiler/sigmatch.nim
  21. +17 −2 compiler/sizealignoffsetimpl.nim
  22. +3 −0 compiler/types.nim
  23. +1 −8 compiler/varpartitions.nim
  24. +4 −2 compiler/vm.nim
  25. +16 −12 compiler/vmgen.nim
  26. +2 −2 compiler/vmmarshal.nim
  27. +1 −1 compiler/wordrecg.nim
  28. +2 −3 config/nim.cfg
  29. +11 −1 config/nimdoc.tex.cfg
  30. +6 −3 doc/advopt.txt
  31. +13 −49 doc/backends.rst
  32. +2 −2 doc/basicopt.txt
  33. +6 −6 doc/destructors.rst
  34. +2 −2 doc/docs.rst
  35. +2 −2 doc/manual.rst
  36. +95 −0 doc/mm.rst
  37. +32 −9 doc/nimc.rst
  38. +30 −79 doc/{gc.rst → refc.rst}
  39. +1 −1 koch.nim
  40. +15 −2 lib/packages/docutils/rstgen.nim
  41. +2 −2 lib/pure/asyncdispatch.nim
  42. +14 −14 lib/pure/collections/deques.nim
  43. +1 −1 lib/pure/colors.nim
  44. +16 −6 lib/pure/json.nim
  45. +5 −1 lib/pure/os.nim
  46. +2 −0 lib/pure/uri.nim
  47. +6 −3 lib/std/private/digitsutils.nim
  48. +6 −1 lib/std/sysrand.nim
  49. +1 −1 lib/system.nim
  50. +39 −7 lib/system/ansi_c.nim
  51. +8 −5 lib/system/excpt.nim
  52. +1 −1 lib/system/seqs_v2.nim
  53. +1 −1 testament/important_packages.nim
  54. +10 −0 tests/arc/t18971.nim
  55. +15 −0 tests/arc/tarcmisc.nim
  56. +2 −1 tests/arc/tconst_to_sink.nim
  57. +8 −1 tests/ccgbugs/t5296.nim
  58. +8 −4 tests/ccgbugs/t8967.nim
  59. +3 −0 tests/converter/mdontleak.nim
  60. +10 −0 tests/converter/tdontleak.nim
  61. +15 −0 tests/cpp/torc.nim
  62. +63 −0 tests/effects/tnestedprocs.nim
  63. +12 −0 tests/effects/tstrict_effects3.nim
  64. +4 −2 tests/exception/texceptions.nim
  65. +130 −0 tests/exception/texceptions2.nim
  66. +22 −0 tests/isolate/tisolate2.nim
  67. +3 −0 tests/misc/trfc405.nim
  68. +1 −0 tests/pragmas/tcompile_pragma.nim
  69. +2 −0 tests/slice/tdistinct.nim
  70. +32 −0 tests/stdlib/tjson.nim
  71. +31 −4 tests/stdlib/trstgen.nim
  72. +21 −2 tests/vm/tvmmisc.nim
  73. +7 −1 tools/kochdocs.nim
43 changes: 43 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
## Changes affecting backward compatibility


- Optional parameters in combination with `: body` syntax (RFC #405) are now opt-in via
`experimental:flexibleOptionalParams`.

## Standard library additions and changes

## Standard library additions and changes

Expand All @@ -12,6 +16,38 @@
## Language changes


- Pragma macros on type definitions can now return `nnkTypeSection` nodes as well as `nnkTypeDef`,
allowing multiple type definitions to be injected in place of the original type definition.

```nim
import macros
macro multiply(amount: static int, s: untyped): untyped =
let name = $s[0].basename
result = newNimNode(nnkTypeSection)
for i in 1 .. amount:
result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
type
Foo = object
Bar {.multiply: 3.} = object
x, y, z: int
Baz = object
# becomes
type
Foo = object
Bar1 = object
x, y, z: int
Bar2 = object
x, y, z: int
Bar3 = object
x, y, z: int
Baz = object
```
- [Case statement macros](manual.html#macros-case-statement-macros) are no longer experimental,
meaning you no longer need to enable the experimental switch `caseStmtMacros` to use them.

## Compiler changes

Expand All @@ -21,5 +57,12 @@

## Tool changes

- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
reality better. (Nim moved away from all techniques based on "tracing".)

- Nim now supports Nimble version 0.14 which added support for lock-files. This is done by
a simple configuration change setting that you can do yourself too. In `$nim/config/nim.cfg`
replace `pkgs` by `pkgs2`.

- There is a new switch `--nimMainPrefix:prefix` to influence the `NimMain` that the
compiler produces. This is particularly useful for generating static libraries.
31 changes: 31 additions & 0 deletions changelogs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# v1.xx.x - yyyy-mm-dd

## Changes affecting backward compatibility

## Standard library additions and changes

### New compile flag (`-d:nimNoGetRandom`) when building `std/sysrand` to remove dependency on linux `getrandom` syscall

This compile flag only affects linux builds and is necessary if either compiling on a linux kernel version < 3.17, or if code built will be executing on kernel < 3.17.

On linux kernels < 3.17 (such as kernel 3.10 in RHEL7 and CentOS7), the `getrandom` syscall was not yet introduced. Without this, the `std/sysrand` module will not build properly, and if code is built on a kernel >= 3.17 without the flag, any usage of the `std/sysrand` module will fail to execute on a kernel < 3.17 (since it attempts to perform a syscall to `getrandom`, which isn't present in the current kernel). A compile flag has been added to force the `std/sysrand` module to use /dev/urandom (available since linux kernel 1.3.30), rather than the `getrandom` syscall. This allows for use of a cryptographically secure PRNG, regardless of kernel support for the `getrandom` syscall.

When building for RHEL7/CentOS7 for example, the entire build process for nim from a source package would then be:
```sh
$ yum install devtoolset-8 # Install GCC version 8 vs the standard 4.8.5 on RHEL7/CentOS7. Alternatively use -d:nimEmulateOverflowChecks. See issue #13692 for details
$ scl enable devtoolset-8 bash # Run bash shell with default toolchain of gcc 8
$ sh build.sh # per unix install instructions
$ bin/nim c koch # per unix install instructions
$ ./koch boot -d:release # per unix install instructions
$ ./koch tools -d:nimNoGetRandom # pass the nimNoGetRandom flag to compile std/sysrand without support for getrandom syscall
```

This is necessary to pass when building nim on kernel versions < 3.17 in particular to avoid an error of "SYS_getrandom undeclared" during the build process for stdlib (sysrand in particular).

## Language changes


## Compiler changes


## Tool changes
10 changes: 9 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ type
mSwap, mIsNil, mArrToSeq,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy, mTrace,
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mReset,
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mAccessTypeField, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
mOrdinal, mIterableType,
Expand Down Expand Up @@ -2101,3 +2101,11 @@ proc skipAddr*(n: PNode): PNode {.inline.} =
proc isNewStyleConcept*(n: PNode): bool {.inline.} =
assert n.kind == nkTypeClassTy
result = n[0].kind == nkEmpty

const
nodesToIgnoreSet* = {nkNone..pred(nkSym), succ(nkSym)..nkNilLit,
nkTypeSection, nkProcDef, nkConverterDef,
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
nkTypeOfExpr, nkMixinStmt, nkBindStmt}
2 changes: 1 addition & 1 deletion compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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}:
Expand Down
8 changes: 8 additions & 0 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,13 @@ proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
# use the dynamic type stored at offset 0:
putIntoDest(p, d, e, rdMType(p, a, nilCheck))

proc genAccessTypeField(p: BProc; e: PNode; d: var TLoc) =
var a: TLoc
initLocExpr(p, e[1], a)
var nilCheck = Rope(nil)
# use the dynamic type stored at offset 0:
putIntoDest(p, d, e, rdMType(p, a, nilCheck))

template genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
var a: TLoc
initLocExpr(p, n[1], a)
Expand Down Expand Up @@ -2449,6 +2456,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mMove: genMove(p, e, d)
of mDestroy: genDestroy(p, e)
of mAccessEnv: unaryExpr(p, e, d, "$1.ClE_0")
of mAccessTypeField: genAccessTypeField(p, e, d)
of mSlice: genSlice(p, e, d)
of mTrace: discard "no code to generate"
else:
Expand Down
13 changes: 12 additions & 1 deletion compiler/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1356,8 +1356,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])
Expand Down
7 changes: 4 additions & 3 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ proc mangleName(m: BModule; s: PSym): Rope =
result = s.loc.r
if result == nil:
result = s.name.s.mangle.rope
result.add "_"
result.add "__"
result.add m.g.graph.ifaces[s.itemId.module].uniqueName
result.add "_"
result.add rope s.itemId.item
Expand Down Expand Up @@ -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 getSize(conf, rettype) > conf.target.floatSize*3:
result = true
else:
case mapType(conf, rettype, skResult)
of ctArray:
Expand Down Expand Up @@ -582,7 +583,7 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,

if typ.kind == tyObject:
if typ[0] == nil:
if (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags:
if lacksMTypeField(typ):
appcg(m, result, " {$n", [])
else:
if optTinyRtti in m.config.globalOptions:
Expand Down
50 changes: 30 additions & 20 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ macro ropecg(m: BModule, frmt: static[FormatStr], args: untyped): Rope =
inc(i)
result.add newCall(formatValue, resVar, args[num])
inc(num)
of '^':
flushStrLit()
inc(i)
result.add newCall(formatValue, resVar, args[^1])
inc(num)
of '0'..'9':
var j = 0
while true:
Expand Down Expand Up @@ -363,7 +368,8 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
else:
linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfoV1(p.module, t, a.lode.info)])
of frEmbedded:
if optTinyRtti in p.config.globalOptions:
# inheritance in C++ does not allow struct initialization: bug #18410
if not p.module.compileToCpp and optTinyRtti in p.config.globalOptions:
var tmp: TLoc
if mode == constructRefObj:
let objType = t.skipTypes(abstractInst+{tyRef})
Expand Down Expand Up @@ -442,8 +448,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
Expand Down Expand Up @@ -1359,7 +1371,7 @@ proc genMainProc(m: BModule) =
"}$N$N"

MainProcs =
"\tNimMain();$N"
"\t$^NimMain();$N"

MainProcsWithResult =
MainProcs & ("\treturn $1nim_program_result;$N")
Expand All @@ -1369,7 +1381,7 @@ proc genMainProc(m: BModule) =
"}$N$N"

NimMainProc =
"N_CDECL(void, NimMain)(void) {$N" &
"N_CDECL(void, $5NimMain)(void) {$N" &
"\tvoid (*volatile inner)(void);$N" &
"$4" &
"\tinner = NimMainInner;$N" &
Expand Down Expand Up @@ -1449,28 +1461,27 @@ proc genMainProc(m: BModule) =
if optGenGuiApp in m.config.globalOptions:
const nimMain = WinNimMain
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
else:
const nimMain = WinNimDllMain
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
elif m.config.target.targetOS == osGenode:
const nimMain = GenodeNimMain
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
elif optGenDynLib in m.config.globalOptions:
const nimMain = PosixNimDllMain
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
elif m.config.target.targetOS == osStandalone:
const nimMain = NimMainBody
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])
else:
const nimMain = NimMainBody
appcg(m, m.s[cfsProcs], nimMain,
[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode])

[m.g.mainModInit, initStackBottomCall, m.labels, preMainCode, m.config.nimMainPrefix])

if optNoMain notin m.config.globalOptions:
if m.config.cppCustomNamespace.len > 0:
Expand All @@ -1480,23 +1491,22 @@ proc genMainProc(m: BModule) =
m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}:
if optGenGuiApp in m.config.globalOptions:
const otherMain = WinCMain
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""])
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])
else:
const otherMain = WinCDllMain
appcg(m, m.s[cfsProcs], otherMain, [])
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
elif m.config.target.targetOS == osGenode:
const otherMain = ComponentConstruct
appcg(m, m.s[cfsProcs], otherMain, [])
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
elif optGenDynLib in m.config.globalOptions:
const otherMain = PosixCDllMain
appcg(m, m.s[cfsProcs], otherMain, [])
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
elif m.config.target.targetOS == osStandalone:
const otherMain = StandaloneCMain
appcg(m, m.s[cfsProcs], otherMain, [])
appcg(m, m.s[cfsProcs], otherMain, [m.config.nimMainPrefix])
else:
const otherMain = PosixCMain
appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: ""])

appcg(m, m.s[cfsProcs], otherMain, [if m.hcrOn: "*" else: "", m.config.nimMainPrefix])

if m.config.cppCustomNamespace.len > 0:
m.s[cfsProcs].add openNamespaceNim(m.config.cppCustomNamespace)
Expand Down Expand Up @@ -1878,7 +1888,7 @@ proc writeHeader(m: BModule) =

if optGenDynLib in m.config.globalOptions:
result.add("N_LIB_IMPORT ")
result.addf("N_CDECL(void, NimMain)(void);$n", [])
result.addf("N_CDECL(void, $1NimMain)(void);$n", [rope m.config.nimMainPrefix])
if m.config.cppCustomNamespace.len > 0: result.add closeNamespaceNim()
result.addf("#endif /* $1 */$n", [guard])
if not writeRope(result, m.filename):
Expand Down
5 changes: 3 additions & 2 deletions compiler/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ template deprecatedAlias(oldName, newName: string) =

proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
case switch.normalize
of "gc":
of "gc", "mm":
case arg.normalize
of "boehm": result = conf.selectedGC == gcBoehm
of "refc": result = conf.selectedGC == gcRefc
Expand Down Expand Up @@ -596,7 +596,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
processOnOffSwitchG(conf, {optForceFullMake}, arg, pass, info)
of "project":
processOnOffSwitchG(conf, {optWholeProject, optGenIndex}, arg, pass, info)
of "gc":
of "gc", "mm":
if conf.backend == backendJs: return # for: bug #16033
expectArg(conf, switch, arg, pass, info)
if pass in {passCmd2, passPP}:
Expand Down Expand Up @@ -1052,6 +1052,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
of "": # comes from "-" in for example: `nim c -r -` (gets stripped from -)
handleStdinInput(conf)
of "nilseqs", "nilchecks", "mainmodule", "m", "symbol", "taintmode", "cs", "deadcodeelim": warningOptionNoop(switch)
of "nimmainprefix": conf.nimMainPrefix = arg
else:
if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg)
else: invalidCmdLineOption(conf, pass, switch, info)
Expand Down
2 changes: 2 additions & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasHintAll")
defineSymbol("nimHasTrace")
defineSymbol("nimHasEffectsOf")

defineSymbol("nimHasEnforceNoRaises")
6 changes: 4 additions & 2 deletions compiler/importer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,13 @@ template addUnnamedIt(c: PContext, fromMod: PSym; filter: untyped) {.dirty.} =
for it in mitems c.graph.ifaces[fromMod.position].converters:
if filter:
loadPackedSym(c.graph, it)
addConverter(c, it)
if sfExported in it.sym.flags:
addConverter(c, it)
for it in mitems c.graph.ifaces[fromMod.position].patterns:
if filter:
loadPackedSym(c.graph, it)
addPattern(c, it)
if sfExported in it.sym.flags:
addPattern(c, it)
for it in mitems c.graph.ifaces[fromMod.position].pureEnums:
if filter:
loadPackedSym(c.graph, it)
Expand Down
Loading