Skip to content

Commit

Permalink
pragma for sfCallsite instead of name check + better semantics, test (n…
Browse files Browse the repository at this point in the history
…im-lang#20464)

* pragma for sfCallsite instead of name check at every template definition

Not documented because it seems to be for internal use?

Should also make it possible to make comparisons and setops imports, but this doesn't have to be done.

I can reuse a name like `cursor` for the pragma as well, added a new name just to be safe.

* make sfCallsite recursive, add tests
  • Loading branch information
metagn authored Oct 3, 2022
1 parent 81e7811 commit 2cca38d
Show file tree
Hide file tree
Showing 13 changed files with 73 additions and 25 deletions.
6 changes: 6 additions & 0 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions compiler/condsyms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -143,4 +143,5 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasTopDownInference")
defineSymbol("nimHasTemplateRedefinitionPragma")
defineSymbol("nimHasCstringCase")
defineSymbol("nimHasCallsitePragma")
defineSymbol("nimHasAmbiguousEnumHint")
4 changes: 2 additions & 2 deletions compiler/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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:
Expand Down
7 changes: 1 addition & 6 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down
6 changes: 0 additions & 6 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 4 additions & 1 deletion compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion compiler/wordrecg.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
9 changes: 6 additions & 3 deletions lib/system.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
9 changes: 6 additions & 3 deletions lib/system/comparisons.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions lib/system/setops.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand All @@ -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}
Expand Down
17 changes: 17 additions & 0 deletions tests/template/tcallsitelineinfo.nim
Original file line number Diff line number Diff line change
@@ -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()
20 changes: 20 additions & 0 deletions tests/template/tcallsitelineinfo2.nim
Original file line number Diff line number Diff line change
@@ -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")

0 comments on commit 2cca38d

Please sign in to comment.