Showing with 693 additions and 261 deletions.
  1. +25 −15 azure-pipelines.yml
  2. +13 −0 changelog.md
  3. +1 −1 compiler/ast.nim
  4. +43 −24 compiler/ccgexprs.nim
  5. +102 −3 compiler/closureiters.nim
  6. +1 −0 compiler/condsyms.nim
  7. +2 −2 compiler/injectdestructors.nim
  8. +1 −0 compiler/installer.ini
  9. +1 −0 compiler/lexer.nim
  10. +1 −0 compiler/nim.cfg
  11. +19 −11 compiler/renderer.nim
  12. +2 −3 compiler/semfields.nim
  13. +1 −1 compiler/sempass2.nim
  14. +4 −4 compiler/semstmts.nim
  15. +2 −2 compiler/sigmatch.nim
  16. +6 −4 compiler/sizealignoffsetimpl.nim
  17. +3 −10 compiler/transf.nim
  18. +7 −0 compiler/trees.nim
  19. +1 −0 compiler/vm.nim
  20. +4 −2 compiler/vmgen.nim
  21. +11 −11 doc/destructors.rst
  22. +6 −30 koch.nim
  23. +1 −1 lib/core/typeinfo.nim
  24. +4 −4 lib/impure/nre.nim
  25. +10 −3 lib/pure/asyncfutures.nim
  26. +4 −1 lib/pure/asyncnet.nim
  27. +1 −1 lib/pure/base64.nim
  28. +12 −12 lib/pure/collections/tables.nim
  29. +25 −11 lib/pure/nativesockets.nim
  30. +2 −1 lib/pure/net.nim
  31. +4 −1 lib/pure/osproc.nim
  32. +3 −0 lib/pure/parsexml.nim
  33. +1 −1 lib/pure/strscans.nim
  34. +32 −13 lib/pure/strutils.nim
  35. +10 −0 lib/pure/sugar.nim
  36. +17 −23 lib/pure/terminal.nim
  37. +7 −1 lib/system.nim
  38. +3 −0 lib/system/chcks.nim
  39. +5 −0 lib/system/exceptions.nim
  40. +21 −25 lib/system/excpt.nim
  41. +83 −0 lib/system/stacktraces.nim
  42. +3 −3 lib/system/syslocks.nim
  43. +4 −1 lib/system/threads.nim
  44. +14 −16 lib/windows/winlean.nim
  45. +2 −2 lib/wrappers/openssl.nim
  46. +2 −2 testament/important_packages.nim
  47. +25 −0 tests/async/tbreak_must_exec_finally.nim
  48. +1 −1 tests/destructor/tconsume_twice.nim
  49. +1 −1 tests/destructor/tprevent_assign.nim
  50. +1 −1 tests/destructor/tprevent_assign2.nim
  51. +1 −1 tests/destructor/tprevent_assign3.nim
  52. +1 −1 tests/destructor/tuse_ownedref_after_move.nim
  53. +2 −2 tests/errmsgs/tunknown_named_parameter.nim
  54. +7 −0 tests/iter/titer.nim
  55. +17 −1 tests/misc/tsizeof.nim
  56. +11 −0 tests/misc/tunsignedconv.nim
  57. +29 −0 tests/stdlib/tnativesockets.nim
  58. +15 −1 tests/stdlib/tstrscans.nim
  59. +4 −2 tests/stdlib/tstrutil.nim
  60. +8 −0 tests/stdlib/tterminal.nim
  61. +18 −0 tests/system/tnim_stacktrace_override.nim
  62. +1 −1 tests/vm/tslow_tables.nim
  63. +25 −4 tools/deps.nim
40 changes: 25 additions & 15 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ jobs:
condition: eq(variables['Agent.OS'], 'Windows_NT')

- checkout: self
fetchDepth: 1

- bash: git clone --depth 1 https://github.com/nim-lang/csources.git
displayName: 'Checkout csources'
- bash: git clone --depth 1 https://github.com/nim-lang/csources
displayName: 'Checkout Nim csources'

- task: NodeTool@0
inputs:
Expand All @@ -71,19 +72,12 @@ jobs:
- bash: |
sudo dpkg --add-architecture i386
# Downgrade llvm, libgcc and libstdc++:
# Downgrade llvm:
# - llvm has to be downgraded to have 32bit version installed for sfml.
# - libgcc and libstdc++ have to be downgraded as an optimization to
# prevent the use of the toolchain ppa, which has a terrible download
# speed.
cat << EOF | sudo tee /etc/apt/preferences.d/pin-to-rel
Package: libllvm6.0 libgcc1 libstdc++6
Package: libllvm6.0
Pin: origin "azure.archive.ubuntu.com"
Pin-Priority: 1001
Package: *
Pin: release o=LP-PPA-ubuntu-toolchain-r-test
Pin-Priority: 100
EOF
sudo apt-fast update -qq
Expand Down Expand Up @@ -139,8 +133,18 @@ jobs:
make -v
displayName: 'System information'
- bash: echo '##vso[task.setvariable variable=csources_version]'"$(git -C csources rev-parse HEAD)"
displayName: 'Get csources version'

- task: Cache@2
inputs:
key: 'csources | "$(Agent.OS)" | $(CPU) | $(csources_version)'
path: csources/bin
displayName: 'Restore built csources'

- bash: |
ncpu=
ext=
case '$(Agent.OS)' in
'Linux')
ncpu=$(nproc)
Expand All @@ -150,19 +154,25 @@ jobs:
;;
'Windows_NT')
ncpu=$NUMBER_OF_PROCESSORS
ext=.exe
;;
esac
[[ -z "$ncpu" || $ncpu -le 0 ]] && ncpu=1
make -C csources -j $ncpu CC=gcc ucpu=$(CPU)
displayName: 'Build csources'
if [[ -x csources/bin/nim$ext ]]; then
echo "Found cached compiler, skipping build"
else
make -C csources -j $ncpu CC=gcc ucpu=$(CPU) koch=no
fi
cp csources/bin/nim$ext bin
displayName: 'Build 1-stage compiler from csources'
- bash: nim c koch
displayName: 'Build koch'

# set result to omit the "bash exited with error code '1'" message
- bash: |
./koch runCI || echo '##vso[task.complete result=Failed]'
- bash: ./koch runCI || echo '##vso[task.complete result=Failed]'
displayName: 'Run CI'
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
13 changes: 13 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@

## Language changes
- In newruntime it is now allowed to assign discriminator field without restrictions as long as case object doesn't have custom destructor. Discriminator value doesn't have to be a constant either. If you have custom destructor for case object and you do want to freely assign discriminator fields, it is recommended to refactor object into 2 objects like this:

- The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts
`wasMoved` calls where needed.
- The `=` hook is now called `=copy` for clarity. The old name `=` is still available so there
is no need to update your code. This change was backported to 1.2 too so you can use the
more readability `=copy` without loss of compatibility.

- In the newruntime it is now allowed to assign to the discriminator field
without restrictions as long as case object doesn't have custom destructor.
The discriminator value doesn't have to be a constant either. If you have a
custom destructor for a case object and you do want to freely assign discriminator
fields, it is recommended to refactor object into 2 objects like this:

```nim
type
MyObj = object
Expand Down
2 changes: 1 addition & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ const
MaxLockLevel* = 1000'i16
UnknownLockLevel* = TLockLevel(1001'i16)
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
"=destroy", "=", "=sink", "=trace", "=dispose", "=deepcopy"]
"=destroy", "=copy", "=sink", "=trace", "=dispose", "=deepcopy"]

proc `$`*(x: TLockLevel): string =
if x.ord == UnspecifiedLockLevel.ord: result = "<unspecified>"
Expand Down
67 changes: 43 additions & 24 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1781,9 +1781,9 @@ template binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) =

proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) =
case int(getSize(p.config, skipTypes(e[1].typ, abstractVar)))
of 1: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&7U)))!=0)")
of 2: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&15U)))!=0)")
of 4: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&31U)))!=0)")
of 1: binaryExprIn(p, e, a, b, d, "(($1 &((NU8)1<<((NU)($2)&7U)))!=0)")
of 2: binaryExprIn(p, e, a, b, d, "(($1 &((NU16)1<<((NU)($2)&15U)))!=0)")
of 4: binaryExprIn(p, e, a, b, d, "(($1 &((NU32)1<<((NU)($2)&31U)))!=0)")
of 8: binaryExprIn(p, e, a, b, d, "(($1 &((NU64)1<<((NU)($2)&63U)))!=0)")
else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)")

Expand Down Expand Up @@ -1981,25 +1981,30 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
checkUnsignedConversions notin p.config.legacyFeatures):
discard "no need to generate a check because it was disabled"
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)
# This seems to be bug-compatible with Nim version 1 but what we
# should really do here is to check if uint64Value < high(int)
let n0t = n[0].typ
let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""

# emit range check:
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
if n0t.kind in {tyUInt, tyUInt64}:
linefmt(p, cpsStmts, "if ($1 > ($6)($3)){ #raiseRangeErrorNoArgs(); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), getTypeDesc(p.module, n0t)])
else:
let raiser =
case skipTypes(n.typ, abstractVarRange).kind
of tyUInt..tyUInt64, tyChar: "raiseRangeErrorU"
of tyFloat..tyFloat128: "raiseRangeErrorF"
else: "raiseRangeErrorI"
discard cgsym(p.module, raiser)

let boundaryCast =
if n0t.skipTypes(abstractVarRange).kind in {tyUInt, tyUInt32, tyUInt64} or
(n0t.sym != nil and sfSystemModule in n0t.sym.owner.flags and n0t.sym.name.s == "csize"):
"(NI64)"
else:
""
linefmt(p, cpsStmts, "if ($6($1) < $2 || $6($1) > $3){ $4($1, $2, $3); $5}$n",
[rdCharLoc(a), genLiteral(p, n[1], dest), genLiteral(p, n[2], dest),
raiser, raiseInstr(p), boundaryCast])
putIntoDest(p, d, n, "(($1) ($2))" %
[getTypeDesc(p.module, dest), rdCharLoc(a)], a.storage)

Expand Down Expand Up @@ -2665,9 +2670,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
expr(p, n[1][0], d)
of nkObjDownConv: downConv(p, n, d)
of nkObjUpConv: upConv(p, n, d)
of nkChckRangeF: genRangeChck(p, n, d)
of nkChckRange64: genRangeChck(p, n, d)
of nkChckRange: genRangeChck(p, n, d)
of nkChckRangeF, nkChckRange64, nkChckRange: genRangeChck(p, n, d)
of nkStringToCString: convStrToCStr(p, n, d)
of nkCStringToString: convCStrToStr(p, n, d)
of nkLambdaKinds:
Expand Down Expand Up @@ -2941,7 +2944,23 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope =
proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
case n.kind
of nkHiddenStdConv, nkHiddenSubConv:
result = genBracedInit(p, n[1], isConst)
when false:
# XXX The frontend doesn't keep conversions to openArray for us. :-(
# We need to change 'transformConv' first, but that is hard.
if n.typ.kind == tyOpenArray:
assert n[1].kind == nkBracket
let data = genBracedInit(p, n[1], isConst)

let payload = getTempName(p.module)
let ctype = getTypeDesc(p.module, n.typ.skipTypes(abstractInst)[0])
let arrLen = n[1].len
appcg(p.module, cfsData,
"static $5 $1 $3[$2] = $4;$n", [
ctype, arrLen, payload, data,
if isConst: "const" else: ""])
result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen]
else:
result = genBracedInit(p, n[1], isConst)
else:
var ty = tyNone
if n.typ == nil:
Expand Down
105 changes: 102 additions & 3 deletions compiler/closureiters.nim
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@

import
ast, msgs, idents,
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
tables, options

type
Ctx = object
Expand Down Expand Up @@ -1102,7 +1103,7 @@ proc skipEmptyStates(ctx: Ctx, stateIdx: int): int =

result = ctx.states[stateIdx][0].intVal.int

proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode =
proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode=
result = n
case n.kind
of nkSkip:
Expand Down Expand Up @@ -1282,6 +1283,101 @@ proc deleteEmptyStates(ctx: var Ctx) =
else:
inc i

type
PreprocessContext = object
finallys: seq[PNode]
config: ConfigRef
blocks: seq[(PNode, int)]
FreshVarsContext = object
tab: Table[int, PSym]
config: ConfigRef
info: TLineInfo

proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
case n.kind
of nkSym:
let x = c.tab.getOrDefault(n.sym.id)
if x == nil:
result = n
else:
result = newSymNode(x, n.info)
of nkSkip - {nkSym}:
result = n
of nkLetSection, nkVarSection:
result = copyNode(n)
for it in n:
if it.kind in {nkIdentDefs, nkVarTuple}:
let idefs = copyNode(it)
for v in 0..it.len-3:
if it[v].kind == nkSym:
let x = copySym(it[v].sym)
c.tab[it[v].sym.id] = x
idefs.add newSymNode(x)
else:
idefs.add it[v]

for rest in it.len-2 ..< it.len: idefs.add it[rest]
result.add idefs
else:
result.add it
of nkRaiseStmt:
localError(c.config, c.info, "unsupported control flow: 'finally: ... raise' duplicated because of 'break'")
else:
result = n
for i in 0..<n.safeLen:
result[i] = freshVars(n[i], c)

proc preprocess(c: var PreprocessContext; n: PNode): PNode =
# in order to fix bug #15243 without risking regressions, we preprocess
# the AST so that 'break' statements inside a 'try finally' also have the
# finally section. We need to duplicate local variables here and also
# detect: 'finally: raises X' which is currently not supported. We produce
# an error for this case for now. All this will be done properly with Yuriy's
# patch.
result = n
case n.kind
of nkTryStmt:
let f = n.lastSon
if f.kind == nkFinally:
c.finallys.add f.lastSon

for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])

if f.kind == nkFinally:
discard c.finallys.pop()

of nkWhileStmt, nkBlockStmt:
c.blocks.add((n, c.finallys.len))
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])
discard c.blocks.pop()

of nkBreakStmt:
if c.blocks.len == 0:
discard
else:
var fin = -1
if n[0].kind == nkEmpty:
fin = c.blocks[^1][1]
elif n[0].kind == nkSym:
for i in countdown(c.blocks.high, 0):
if c.blocks[i][0].kind == nkBlockStmt and c.blocks[i][0][0].kind == nkSym and
c.blocks[i][0][0].sym == n[0].sym:
fin = c.blocks[i][1]
break

if fin >= 0:
result = newNodeI(nkStmtList, n.info)
for i in countdown(c.finallys.high, fin):
var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info)
result.add freshVars(preprocess(c, c.finallys[i]), vars)
result.add n
of nkSkip: discard
else:
for i in 0 ..< n.len:
result[i] = preprocess(c, n[i])

proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
var ctx: Ctx
ctx.g = g
Expand All @@ -1294,7 +1390,10 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
var n = n.toStmtList
var pc = PreprocessContext(finallys: @[], config: g.config)
var n = preprocess(pc, n.toStmtList)
#echo "transformed into ", n
#var n = n.toStmtList

discard ctx.newState(n, nil)
let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1))
Expand Down
1 change: 1 addition & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimNewIntegerOps")
defineSymbol("nimHasInvariant")
defineSymbol("nimHasStacktraceMsgs")
defineSymbol("nimHasStacktracesModule")
4 changes: 2 additions & 2 deletions compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ template isUnpackedTuple(n: PNode): bool =

proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
if opname == "=" and ri != nil:
if (opname == "=" or opname == "=copy") and ri != nil:
m.add "; requires a copy because it's not the last read of '"
m.add renderTree(ri)
m.add '\''
Expand Down Expand Up @@ -301,7 +301,7 @@ proc genCopy(c: var Con; dest, ri: PNode): PNode =
if tfHasOwned in t.flags and ri.kind != nkNilLit:
# try to improve the error message here:
if c.otherRead == nil: discard isLastRead(ri, c)
checkForErrorPragma(c, t, ri, "=")
checkForErrorPragma(c, t, ri, "=copy")
result = genCopyNoCheck(c, dest, ri)

proc addTopVar(c: var Con; v: PNode) =
Expand Down
1 change: 1 addition & 0 deletions compiler/installer.ini
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ Files: "lib"
[Other]
Files: "examples"
Files: "dist/nimble"
Files: "dist/fusion"

Files: "tests"

Expand Down
1 change: 1 addition & 0 deletions compiler/lexer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type
tkComma, tkSemiColon,
tkColon, tkColonColon, tkEquals, tkDot, tkDotDot, tkBracketLeColon,
tkOpr, tkComment, tkAccent,
# these are fake tokens used by renderer.nim
tkSpaces, tkInfixOpr, tkPrefixOpr, tkPostfixOpr

TTokTypes* = set[TTokType]
Expand Down
1 change: 1 addition & 0 deletions compiler/nim.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ define:useStdoutAsStdmsg
styleCheck:error
@end


#define:useNodeIds
#gc:markAndSweep
Loading