Skip to content

Commit

Permalink
continue nim-lang#9582 for consts, close nim-lang#9331, fix nim-lang#…
Browse files Browse the repository at this point in the history
…20114

also move extractPragma to ast to pave the way for things like {.strdefine: "abc".} etc
  • Loading branch information
metagn committed Jul 31, 2022
1 parent 528b6d1 commit 2102275
Show file tree
Hide file tree
Showing 18 changed files with 105 additions and 33 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
- `shallowCopy` is removed for ARC/ORC. Use `move` when possible or combine assignment and
`sink` for optimization purposes.

- `macros.getImpl` for `const` symbols will now return the full `nnkConstDef` node


## Standard library additions and changes

[//]: # "Changes:"
Expand Down
13 changes: 12 additions & 1 deletion compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,17 @@ proc getDeclPragma*(n: PNode): PNode =
if result != nil:
assert result.kind == nkPragma, $(result.kind, n.kind)

proc extractPragma*(s: PSym): PNode =
## gets the pragma node of routine/type/var/let/const symbol `s`
if s.kind in routineKinds:
result = s.ast[pragmasPos]
elif s.kind in {skType, skVar, skLet, skConst}:
if s.ast != nil and s.ast.len > 0:
if s.ast[0].kind == nkPragmaExpr and s.ast[0].len > 1:
# s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
result = s.ast[0][1]
assert result == nil or result.kind == nkPragma

when defined(useNodeIds):
const nodeIdToDebug* = -1 # 2322968
var gNodeId: int
Expand Down Expand Up @@ -1308,7 +1319,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, id: ItemId, owner: PSym,

proc astdef*(s: PSym): PNode =
# get only the definition (initializer) portion of the ast
if s.ast != nil and s.ast.kind == nkIdentDefs:
if s.ast != nil and s.ast.kind in {nkIdentDefs, nkConstDef}:
s.ast[2]
else:
s.ast
Expand Down
6 changes: 3 additions & 3 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2694,7 +2694,7 @@ proc genConstSetup(p: BProc; sym: PSym): bool =
let m = p.module
useHeader(m, sym)
if sym.loc.k == locNone:
fillLoc(sym.loc, locData, sym.ast, mangleName(p.module, sym), OnStatic)
fillLoc(sym.loc, locData, sym.astdef, mangleName(p.module, sym), OnStatic)
if m.hcrOn: incl(sym.loc.flags, lfIndirect)
result = lfNoDecl notin sym.loc.flags

Expand All @@ -2719,7 +2719,7 @@ proc genConstDefinition(q: BModule; p: BProc; sym: PSym) =
let actualConstName = if q.hcrOn: sym.loc.r & "_const" else: sym.loc.r
q.s[cfsData].addf("N_LIB_PRIVATE NIM_CONST $1 $2 = $3;$n",
[getTypeDesc(q, sym.typ), actualConstName,
genBracedInit(q.initProc, sym.ast, isConst = true, sym.typ)])
genBracedInit(q.initProc, sym.astdef, isConst = true, sym.typ)])
if q.hcrOn:
# generate the global pointer with the real name
q.s[cfsVars].addf("static $1* $2;$n", [getTypeDesc(q, sym.loc.t, skVar), sym.loc.r])
Expand Down Expand Up @@ -2776,7 +2776,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
putLocIntoDest(p, d, sym.loc)
of skConst:
if isSimpleConst(sym.typ):
putIntoDest(p, d, n, genLiteral(p, sym.ast, sym.typ), OnStatic)
putIntoDest(p, d, n, genLiteral(p, sym.astdef, sym.typ), OnStatic)
elif useAliveDataFromDce in p.module.flags:
genConstHeader(p.module, p.module, p, sym)
assert((sym.loc.r != nil) and (sym.loc.t != nil))
Expand Down
2 changes: 1 addition & 1 deletion compiler/ccgliterals.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ template detectVersion(field, corename) =
if core == nil or core.kind != skConst:
m.g.field = 1
else:
m.g.field = toInt(ast.getInt(core.ast))
m.g.field = toInt(ast.getInt(core.astdef))
result = m.g.field

proc detectStrVersion(m: BModule): int =
Expand Down
2 changes: 1 addition & 1 deletion compiler/guards.nim
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ proc highBound*(conf: ConfigRef; x: PNode; o: Operators): PNode =
nkIntLit.newIntNode(lastOrd(conf, typ))
elif typ.kind == tySequence and x.kind == nkSym and
x.sym.kind == skConst:
nkIntLit.newIntNode(x.sym.ast.len-1)
nkIntLit.newIntNode(x.sym.astdef.len-1)
else:
o.opAdd.buildCall(o.opLen.buildCall(x), minusOne())
result.info = x.info
Expand Down
2 changes: 1 addition & 1 deletion compiler/parampatterns.nim
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
const kinds = {skVar, skResult, skTemp, skParam, skLet, skForVar}
if n.sym.kind == skParam:
result = if n.sym.typ.kind in {tyVar, tySink}: arLValue else: arAddressableConst
elif n.sym.kind == skConst and dontInlineConstant(n, n.sym.ast):
elif n.sym.kind == skConst and dontInlineConstant(n, n.sym.astdef):
result = arAddressableConst
elif n.sym.kind in kinds:
if n.sym.kind in {skParam, skLet, skForVar}:
Expand Down
2 changes: 1 addition & 1 deletion compiler/patterns.nim
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ proc matches(c: PPatternContext, p, n: PNode): bool =
elif n.kind == nkSym and n.sym.kind == skConst:
# try both:
if p.kind == nkSym: result = p.sym == n.sym
elif matches(c, p, n.sym.ast): result = true
elif matches(c, p, n.sym.astdef): result = true
elif p.kind == nkPattern:
# pattern operators: | *
let opr = p[0].ident.s
Expand Down
6 changes: 3 additions & 3 deletions compiler/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
# {.dynlib: myGetProcAddr(...).}
result = c.semExpr(c, n[1])
if result.kind == nkSym and result.sym.kind == skConst:
result = result.sym.ast # look it up
result = result.sym.astdef # look it up
if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}:
localError(c.config, n.info, errStringLiteralExpected)
result = newEmptyStrNode(c, n)
Expand Down Expand Up @@ -995,7 +995,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
of wExplain:
sym.flags.incl sfExplain
of wDeprecated:
if sym != nil and sym.kind in routineKinds + {skType, skVar, skLet}:
if sym != nil and sym.kind in routineKinds + {skType, skVar, skLet, skConst}:
if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it)
incl(sym.flags, sfDeprecated)
elif sym != nil and sym.kind != skModule:
Expand Down Expand Up @@ -1251,7 +1251,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
elif comesFromPush and whichKeyword(ident) != wInvalid:
discard "ignore the .push pragma; it doesn't apply"
else:
if sym == nil or (sym.kind in {skVar, skLet, skParam,
if sym == nil or (sym.kind in {skVar, skLet, skConst, skParam,
skField, skProc, skFunc, skConverter, skMethod, skType}):
n[i] = semCustomPragma(c, it)
elif sym != nil:
Expand Down
4 changes: 2 additions & 2 deletions compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -560,8 +560,8 @@ proc semResolvedCall(c: PContext, x: TCandidate,
for s in instantiateGenericParamList(c, gp, x.bindings):
case s.kind
of skConst:
if not s.ast.isNil:
x.call.add s.ast
if not s.astdef.isNil:
x.call.add s.astdef
else:
x.call.add c.graph.emptyNode
of skType:
Expand Down
4 changes: 2 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = symChoice(c, n, s, scClosed)

proc inlineConst(c: PContext, n: PNode, s: PSym): PNode {.inline.} =
result = copyTree(s.ast)
result = copyTree(s.astdef)
if result.isNil:
localError(c.config, n.info, "constant of type '" & typeToString(s.typ) & "' has no value")
result = newSymNode(s)
Expand Down Expand Up @@ -1211,7 +1211,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
# It is clear that ``[]`` means two totally different things. Thus, we
# copy `x`'s AST into each context, so that the type fixup phase can
# deal with two different ``[]``.
if s.ast.safeLen == 0: result = inlineConst(c, n, s)
if s.astdef.safeLen == 0: result = inlineConst(c, n, s)
else: result = newSymNode(s, n.info)
of tyStatic:
if typ.n != nil:
Expand Down
8 changes: 4 additions & 4 deletions compiler/semfold.nim
Original file line number Diff line number Diff line change
Expand Up @@ -517,12 +517,12 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
"{.intdefine.} const was set to an invalid integer: '" &
g.config.symbols[s.name.s] & "'")
else:
result = copyTree(s.ast)
result = copyTree(s.astdef)
of mStrDefine:
if isDefined(g.config, s.name.s):
result = newStrNodeT(g.config.symbols[s.name.s], n, g)
else:
result = copyTree(s.ast)
result = copyTree(s.astdef)
of mBoolDefine:
if isDefined(g.config, s.name.s):
try:
Expand All @@ -532,9 +532,9 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
"{.booldefine.} const was set to an invalid bool: '" &
g.config.symbols[s.name.s] & "'")
else:
result = copyTree(s.ast)
result = copyTree(s.astdef)
else:
result = copyTree(s.ast)
result = copyTree(s.astdef)
of skProc, skFunc, skMethod:
result = n
of skParam:
Expand Down
12 changes: 10 additions & 2 deletions compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -799,12 +799,20 @@ proc semConst(c: PContext, n: PNode): PNode =

if a.kind != nkVarTuple:
setVarType(c, v, typ)
v.ast = def # no need to copy
when false:
v.ast = def # no need to copy
b = newNodeI(nkConstDef, a.info)
if importantComments(c.config): b.comment = a.comment
b.add newSymNode(v)
if a[j].kind == nkPragmaExpr:
var p = newNodeI(nkPragmaExpr, a.info)
p.add newSymNode(v)
p.add a[j][1].copyTree
b.add p
else:
b.add newSymNode(v)
b.add a[1]
b.add copyTree(def)
v.ast = b
else:
setVarType(c, v, typ[j])
v.ast = if def[j].kind != nkExprColonExpr: def[j]
Expand Down
10 changes: 0 additions & 10 deletions compiler/suggest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -535,16 +535,6 @@ proc suggestSym*(g: ModuleGraph; info: TLineInfo; s: PSym; usageSym: var PSym; i
if parentFileIndex == conf.m.trackPos.fileIndex:
suggestResult(conf, symToSuggest(g, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0))

proc extractPragma(s: PSym): PNode =
if s.kind in routineKinds:
result = s.ast[pragmasPos]
elif s.kind in {skType, skVar, skLet}:
if s.ast != nil and s.ast.len > 0:
if s.ast[0].kind == nkPragmaExpr and s.ast[0].len > 1:
# s.ast = nkTypedef / nkPragmaExpr / [nkSym, nkPragma]
result = s.ast[0][1]
doAssert result == nil or result.kind == nkPragma

proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) =
var pragmaNode: PNode
pragmaNode = if s.kind == skEnumField: extractPragma(s.owner) else: extractPragma(s)
Expand Down
2 changes: 1 addition & 1 deletion compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2001,7 +2001,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
elif importcCond(c, s): c.importcSym(n.info, s)
genLit(c, n, dest)
of skConst:
let constVal = if s.ast != nil: s.ast else: s.typ.n
let constVal = if s.astdef != nil: s.astdef else: s.typ.n
gen(c, constVal, dest)
of skEnumField:
# we never reach this case - as of the time of this comment,
Expand Down
2 changes: 1 addition & 1 deletion lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1545,7 +1545,7 @@ proc customPragmaNode(n: NimNode): NimNode =
let impl = n.getImpl()
if impl.kind in RoutineNodes:
return impl.pragma
elif impl.kind == nnkIdentDefs and impl[0].kind == nnkPragmaExpr:
elif impl.kind in {nnkIdentDefs, nnkConstDef} and impl[0].kind == nnkPragmaExpr:
return impl[0][1]
else:
let timpl = typ.getImpl()
Expand Down
8 changes: 8 additions & 0 deletions tests/deprecated/tconst.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
discard """
nimout: '''
tconst.nim(8, 9) Warning: abcd; foo is deprecated [Deprecated]
'''
"""

const foo* {.deprecated: "abcd".} = 42
discard foo
12 changes: 12 additions & 0 deletions tests/macros/t20114.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
discard """
action: compile
nimout: '''
const
foo {.strdefine.} = "abc"
'''
"""

import macros

expandMacros:
const foo {.strdefine.} = "abc"
40 changes: 40 additions & 0 deletions tests/pragmas/tcustom_pragma.nim
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,43 @@ when false:

# left-to-right priority/override order for getCustomPragmaVal
assert bb.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he")

{.experimental: "dynamicBindSym".}

# const
block:
template myAttr() {.pragma.}
template myAttr2(x: int) {.pragma.}
template myAttr3(x: string) {.pragma.}

type
MyObj2 = ref object

const a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
const b {.myAttr,myAttr2(2),myAttr3:"test".} = 0

macro forceHasCustomPragma(x: untyped, y: typed): untyped =
var x = bindSym(x.repr)
for c in x:
if c.symKind == nskConst:
x = c
break
result = getAst(hasCustomPragma(x, y))

macro forceGetCustomPragmaVal(x: untyped, y: typed): untyped =
var x = bindSym(x.repr)
for c in x:
if c.symKind == nskConst:
x = c
break
result = getAst(getCustomPragmaVal(x, y))

template check(s: untyped) =
doAssert forceHasCustomPragma(s, myAttr)
doAssert forceHasCustomPragma(s, myAttr2)
doAssert forceGetCustomPragmaVal(s, myAttr2) == 2
doAssert forceHasCustomPragma(s, myAttr3)
doAssert forceGetCustomPragmaVal(s, myAttr3) == "test"

check(a)
check(b)

0 comments on commit 2102275

Please sign in to comment.