Merge branch 'devel' into pr-remove-encode-overload

This commit is contained in:
AmjadHD
2022-10-03 15:34:31 +01:00
16 changed files with 133 additions and 37 deletions

View File

@@ -1254,6 +1254,12 @@ proc skipPragmaExpr*(n: PNode): PNode =
else:
result = n
proc setInfoRecursive*(n: PNode, info: TLineInfo) =
## set line info recursively
if n != nil:
for i in 0..<n.safeLen: setInfoRecursive(n[i], info)
n.info = info
when defined(useNodeIds):
const nodeIdToDebug* = -1 # 2322968
var gNodeId: int

View File

@@ -143,4 +143,5 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasTopDownInference")
defineSymbol("nimHasTemplateRedefinitionPragma")
defineSymbol("nimHasCstringCase")
defineSymbol("nimHasCallsitePragma")
defineSymbol("nimHasAmbiguousEnumHint")

View File

@@ -26,7 +26,7 @@ type
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a)
if ctx.instLines: result.info = b.info
if ctx.instLines: setInfoRecursive(result, b.info)
proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
template handleParam(param) =
@@ -204,7 +204,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
result = copyNode(body)
ctx.instLines = sfCallsite in tmpl.flags
if ctx.instLines:
result.info = n.info
setInfoRecursive(result, n.info)
for i in 0..<body.safeLen:
evalTemplateAux(body[i], args, ctx, result)
result.flags.incl nfFromTemplate

View File

@@ -77,7 +77,7 @@ proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
proc nestedScope(parent: var Scope; body: PNode): Scope =
Scope(vars: @[], locals: @[], wasMoved: @[], final: @[], body: body, needsTry: false, parent: addr(parent))
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}): PNode
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; isDecl = false): PNode
when false:
@@ -508,14 +508,14 @@ proc processScope(c: var Con; s: var Scope; ret: PNode): PNode =
if s.parent != nil: s.parent[].needsTry = s.parent[].needsTry or s.needsTry
template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: untyped): PNode =
template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: untyped, tmpFlags: TSymFlags): PNode =
assert not ret.typ.isEmptyType
var result = newNodeIT(nkStmtListExpr, ret.info, ret.typ)
# There is a possibility to do this check: s.wasMoved.len > 0 or s.final.len > 0
# later and use it to eliminate the temporary when theres no need for it, but its
# tricky because you would have to intercept moveOrCopy at a certain point
let tmp = c.getTemp(s.parent[], ret.typ, ret.info)
tmp.sym.flags.incl sfSingleUsedTemp
tmp.sym.flags = tmpFlags
let cpy = if hasDestructor(c, ret.typ):
s.parent[].final.add c.genDestroy(tmp)
moveOrCopy(tmp, ret, c, s, isDecl = true)
@@ -542,7 +542,8 @@ template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: unt
result
template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
template handleNestedTempl(n, processCall: untyped, willProduceStmt = false,
tmpFlags = {sfSingleUsedTemp}) =
template maybeVoid(child, s): untyped =
if isEmptyType(child.typ): p(child, c, s, normal)
else: processCall(child, s)
@@ -570,7 +571,7 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
branch[^1] = if it[^1].typ.isEmptyType or willProduceStmt:
processScope(c, ofScope, maybeVoid(it[^1], ofScope))
else:
processScopeExpr(c, ofScope, it[^1], processCall)
processScopeExpr(c, ofScope, it[^1], processCall, tmpFlags)
result.add branch
of nkWhileStmt:
@@ -603,7 +604,7 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
result.add if n[1].typ.isEmptyType or willProduceStmt:
processScope(c, bodyScope, processCall(n[1], bodyScope))
else:
processScopeExpr(c, bodyScope, n[1], processCall)
processScopeExpr(c, bodyScope, n[1], processCall, tmpFlags)
of nkIfStmt, nkIfExpr:
result = copyNode(n)
@@ -618,7 +619,7 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
branch[^1] = if it[^1].typ.isEmptyType or willProduceStmt:
processScope(c, branchScope, maybeVoid(it[^1], branchScope))
else:
processScopeExpr(c, branchScope, it[^1], processCall)
processScopeExpr(c, branchScope, it[^1], processCall, tmpFlags)
result.add branch
of nkTryStmt:
@@ -627,7 +628,7 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
result.add if n[0].typ.isEmptyType or willProduceStmt:
processScope(c, tryScope, maybeVoid(n[0], tryScope))
else:
processScopeExpr(c, tryScope, n[0], maybeVoid)
processScopeExpr(c, tryScope, n[0], maybeVoid, tmpFlags)
for i in 1..<n.len:
let it = n[i]
@@ -637,7 +638,7 @@ template handleNestedTempl(n, processCall: untyped, willProduceStmt = false) =
processScope(c, branchScope, if it.kind == nkFinally: p(it[^1], c, branchScope, normal)
else: maybeVoid(it[^1], branchScope))
else:
processScopeExpr(c, branchScope, it[^1], processCall)
processScopeExpr(c, branchScope, it[^1], processCall, tmpFlags)
result.add branch
of nkWhen: # This should be a "when nimvm" node.
@@ -670,11 +671,11 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
result.add copyNode(n[0])
s.needsTry = true
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkParForStmt, nkTryStmt}:
template process(child, s): untyped = p(child, c, s, mode)
handleNestedTempl(n, process)
handleNestedTempl(n, process, tmpFlags = tmpFlags)
elif mode == sinkArg:
if n.containsConstSeq:
# const sequences are not mutable and so we need to pass a copy to the
@@ -825,7 +826,11 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
var itCopy = copyNode(it)
for j in 0..<it.len-1:
itCopy.add it[j]
itCopy.add p(it[^1], c, s, normal)
var flags = {sfSingleUsedTemp}
if it.kind == nkIdentDefs and it.len == 3 and it[0].kind == nkSym and
sfGlobal in it[0].sym.flags:
flags.incl sfGlobal
itCopy.add p(it[^1], c, s, normal, tmpFlags = flags)
v.add itCopy
result.add v
of nkAsgn, nkFastAsgn:

View File

@@ -38,7 +38,7 @@ const
converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase}-{wImportCpp}
templatePragmas* = {wDeprecated, wError, wGensym, wInject, wDirty,
wDelegator, wExportNims, wUsed, wPragma, wRedefine}
wDelegator, wExportNims, wUsed, wPragma, wRedefine, wCallsite}
macroPragmas* = declPragmas + {FirstCallConv..LastCallConv,
wMagic, wNoSideEffect, wCompilerProc, wNonReloadable, wCore,
wDiscardable, wGensym, wInject, wDelegator}
@@ -873,6 +873,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wRedefine:
if sym.kind == skTemplate: incl(sym.flags, sfTemplateRedefinition)
else: invalidPragma(c, it)
of wCallsite:
if sym.kind == skTemplate: incl(sym.flags, sfCallsite)
else: invalidPragma(c, it)
of wImportCpp:
processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info)
of wCppNonPod:

View File

@@ -2338,11 +2338,6 @@ proc evalInclude(c: PContext, n: PNode): PNode =
else:
incMod(c, n, it, result)
proc setLine(n: PNode, info: TLineInfo) =
if n != nil:
for i in 0..<n.safeLen: setLine(n[i], info)
n.info = info
proc recursiveSetFlag(n: PNode, flag: TNodeFlag) =
if n != nil:
for i in 0..<n.safeLen: recursiveSetFlag(n[i], flag)
@@ -2371,7 +2366,7 @@ proc semPragmaBlock(c: PContext, n: PNode; expectedType: PType = nil): PNode =
result.typ = n[1].typ
for i in 0..<pragmaList.len:
case whichPragma(pragmaList[i])
of wLine: setLine(result, pragmaList[i].info)
of wLine: setInfoRecursive(result, pragmaList[i].info)
of wNoRewrite: recursiveSetFlag(result, nfNoRewrite)
else: discard

View File

@@ -620,12 +620,6 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
s = semIdentVis(c, skTemplate, n[namePos], {})
assert s.kind == skTemplate
if s.owner != nil:
const names = ["!=", ">=", ">", "incl", "excl", "in", "notin", "isnot"]
if sfSystemModule in s.owner.flags and s.name.s in names or
s.owner.name.s == "vm" and s.name.s == "stackTrace":
incl(s.flags, sfCallsite)
styleCheckDef(c, s)
onDef(n[namePos].info, s)
# check parameter list:

View File

@@ -75,8 +75,11 @@ proc stackTraceImpl(c: PCtx, tos: PStackFrame, pc: int,
let lineInfo = if lineInfo == TLineInfo.default: c.debug[pc] else: lineInfo
liMessage(c.config, lineInfo, errGenerated, msg, action, infoOrigin)
when not defined(nimHasCallsitePragma):
{.pragma: callsite.}
template stackTrace(c: PCtx, tos: PStackFrame, pc: int,
msg: string, lineInfo: TLineInfo = TLineInfo.default) =
msg: string, lineInfo: TLineInfo = TLineInfo.default) {.callsite.} =
stackTraceImpl(c, tos, pc, msg, lineInfo, instantiationInfo(-2, fullPaths = true))
return

View File

@@ -87,7 +87,7 @@ type
wGlobal = "global", wCodegenDecl = "codegenDecl", wUnchecked = "unchecked",
wGuard = "guard", wLocks = "locks", wPartial = "partial", wExplain = "explain",
wLiftLocals = "liftlocals", wEnforceNoRaises = "enforceNoRaises",
wRedefine = "redefine",
wRedefine = "redefine", wCallsite = "callsite",
wAuto = "auto", wBool = "bool", wCatch = "catch", wChar = "char",
wClass = "class", wCompl = "compl", wConstCast = "const_cast", wDefault = "default",

View File

@@ -731,13 +731,16 @@ proc contains*[U, V, W](s: HSlice[U, V], value: W): bool {.noSideEffect, inline.
## ```
result = s.a <= value and value <= s.b
template `in`*(x, y: untyped): untyped {.dirty.} = contains(y, x)
when not defined(nimHasCallsitePragma):
{.pragma: callsite.}
template `in`*(x, y: untyped): untyped {.dirty, callsite.} = contains(y, x)
## Sugar for `contains`.
## ```
## assert(1 in (1..3) == true)
## assert(5 in (1..3) == false)
## ```
template `notin`*(x, y: untyped): untyped {.dirty.} = not contains(y, x)
template `notin`*(x, y: untyped): untyped {.dirty, callsite.} = not contains(y, x)
## Sugar for `not contains`.
## ```
## assert(1 notin (1..3) == false)
@@ -762,7 +765,7 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
## assert(test[int](3) == 3)
## assert(test[string]("xyz") == 0)
## ```
template `isnot`*(x, y: untyped): untyped = not (x is y)
template `isnot`*(x, y: untyped): untyped {.callsite.} = not (x is y)
## Negated version of `is <#is,T,S>`_. Equivalent to `not(x is y)`.
## ```
## assert 42 isnot float

View File

@@ -125,15 +125,18 @@ proc `<`*[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
proc `<`*[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
proc `<`*(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
template `!=`*(x, y: untyped): untyped =
when not defined(nimHasCallsitePragma):
{.pragma: callsite.}
template `!=`*(x, y: untyped): untyped {.callsite.} =
## Unequals operator. This is a shorthand for `not (x == y)`.
not (x == y)
template `>=`*(x, y: untyped): untyped =
template `>=`*(x, y: untyped): untyped {.callsite.} =
## "is greater or equals" operator. This is the same as `y <= x`.
y <= x
template `>`*(x, y: untyped): untyped =
template `>`*(x, y: untyped): untyped {.callsite.} =
## "is greater" operator. This is the same as `y < x`.
y < x

View File

@@ -9,7 +9,10 @@ func incl*[T](x: var set[T], y: T) {.magic: "Incl".} =
a.incl(4)
assert a == {1, 2, 3, 4, 5}
template incl*[T](x: var set[T], y: set[T]) =
when not defined(nimHasCallsitePragma):
{.pragma: callsite.}
template incl*[T](x: var set[T], y: set[T]) {.callsite.} =
## Includes the set `y` in the set `x`.
runnableExamples:
var a = {1, 3, 5, 7}
@@ -27,7 +30,7 @@ func excl*[T](x: var set[T], y: T) {.magic: "Excl".} =
b.excl(5)
assert b == {2, 3, 6, 12, 545}
template excl*[T](x: var set[T], y: set[T]) =
template excl*[T](x: var set[T], y: set[T]) {.callsite.} =
## Excludes the set `y` from the set `x`.
runnableExamples:
var a = {1, 3, 5, 7}

18
tests/arc/t18645.nim Normal file
View File

@@ -0,0 +1,18 @@
discard """
matrix: "--gc:arc; --gc:refc"
output: '''
1
2
3
'''
"""
proc bitTypeIdUnion() =
var bitId {.global.} = block:
0
inc bitId
echo bitId
bitTypeIdUnion()
bitTypeIdUnion()
bitTypeIdUnion()

View File

@@ -423,6 +423,31 @@ when false:
doAssert hasMyAttr(TObj)
# bug #11415
template noserialize() {.pragma.}
type
Point[T] = object
x, y: T
ReplayEventKind = enum
FoodAppeared, FoodEaten, DirectionChanged
ReplayEvent = object
case kind: ReplayEventKind
of FoodEaten, FoodAppeared: # foodPos is in multiple branches
foodPos {.noserialize.}: Point[float]
of DirectionChanged:
playerPos: float
let ev = ReplayEvent(
kind: FoodEaten,
foodPos: Point[float](x: 5.0, y: 1.0)
)
doAssert ev.foodPos.hasCustomPragma(noserialize)
when false:
# misc
{.pragma: haha.}

View File

@@ -0,0 +1,17 @@
discard """
nimout: '''
tcallsitelineinfo.nim(17, 4) Warning: abc [User]
'''
exitcode: 1
outputsub: '''
tcallsitelineinfo.nim(17) tcallsitelineinfo
Error: unhandled exception: def [ValueError]
'''
"""
template foo(): untyped {.callsite.} =
{.warning: "abc".}
raise newException(ValueError, "def")
echo "hello"
foo()

View File

@@ -0,0 +1,20 @@
discard """
nimout: '''
tcallsitelineinfo2.nim(18, 1) Warning: abc [User]
tcallsitelineinfo2.nim(19, 12) Warning: def [User]
'''
exitcode: 1
outputsub: '''
tcallsitelineinfo2.nim(20) tcallsitelineinfo2
Error: unhandled exception: ghi [ValueError]
'''
"""
template foo(a: untyped): untyped {.callsite.} =
{.warning: "abc".}
a
echo "hello"
foo: # with `{.line.}:`, the following do not keep their line information:
{.warning: "def".}
raise newException(ValueError, "ghi")