Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Callsite as experimental #11864

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ type
## This requires building nim with `-d:nimHasLibFFI`
## which itself requires `nimble install libffi`, see #10150
## Note: this feature can't be localized with {.push.}
callsiteAccess,
## This feature is on the way out of the laguage. Only use it for legacy code.

LegacyFeature* = enum
allowSemcheckedAstModification,
Expand Down
6 changes: 3 additions & 3 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ const

proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =
pushInfoContext(c.config, nOrig.info, sym.detailedInfo)
pushInfoContext(c.config, n.info, sym.detailedInfo)

let info = getCallLineInfo(n)
markUsed(c, info, sym)
Expand All @@ -472,8 +472,8 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags)
if c.config.macrosToExpand.hasKey(sym.name.s):
message(c.config, nOrig.info, hintExpandMacro, renderTree(result))
result = wrapInComesFrom(nOrig.info, sym, result)
message(c.config, n.info, hintExpandMacro, renderTree(result))
result = wrapInComesFrom(n.info, sym, result)
popInfoContext(c.config)

proc forceBool(c: PContext, n: PNode): PNode =
Expand Down
10 changes: 5 additions & 5 deletions compiler/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,13 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
var hiddenArg = newSymNode(c.p.selfSym)
hiddenArg.typ = nil
n.sons.insert(hiddenArg, 1)
orig.sons.insert(hiddenArg, 1)
if orig != nil: orig.sons.insert(hiddenArg, 1)

pickBest(f)

if result.state != csMatch:
n.sons.delete(1)
orig.sons.delete(1)
if orig != nil: orig.sons.delete(1)
excl n.flags, nfExprCall
else: return

Expand All @@ -380,12 +380,12 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
# leave the op head symbol empty,
# we are going to try multiple variants
n.sons[0..1] = [nil, n[1], f]
orig.sons[0..1] = [nil, orig[1], f]
if orig != nil: orig.sons[0..1] = [nil, orig[1], f]

template tryOp(x) =
let op = newIdentNode(getIdent(c.cache, x), n.info)
n[0] = op
orig[0] = op
if orig != nil: orig[0] = op
pickBest(op)

if nfExplicitCall in n.flags:
Expand All @@ -399,7 +399,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let calleeName = newIdentNode(getIdent(c.cache, f.ident.s[0..^2]), n.info)
let callOp = newIdentNode(getIdent(c.cache, ".="), n.info)
n.sons[0..1] = [callOp, n[1], calleeName]
orig.sons[0..1] = [callOp, orig[1], calleeName]
if orig != nil: orig.sons[0..1] = [callOp, orig[1], calleeName]
pickBest(callOp)

if overloadsState == csEmpty and result.state == csEmpty:
Expand Down
21 changes: 11 additions & 10 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ proc isCastable(conf: ConfigRef; dst, src: PType): bool =
if conf.selectedGC in {gcArc, gcOrc}:
let d = skipTypes(dst, abstractInst)
let s = skipTypes(src, abstractInst)
if d.kind == tyRef and s.kind == tyRef and s[0].isFinal != d[0].isFinal:
if d.kind == tyRef and s.kind == tyRef and s[0].isFinal != d[0].isFinal:
return false

var dstSize, srcSize: BiggestInt
Expand Down Expand Up @@ -927,7 +927,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
setGenericParams(c, n[0])
return semDirectOp(c, n, flags)

let nOrig = n.copyTree
let nOrig: PNode = if callsiteAccess in c.config.features: n.copyTree else: nil
semOpAux(c, n)
var t: PType = nil
if n[0].typ != nil:
Expand Down Expand Up @@ -971,7 +971,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# XXX: hmm, what kind of symbols will end up here?
# do we really need to try the overload resolution?
n[0] = prc
nOrig[0] = prc
if nOrig != nil: nOrig[0] = prc
n.flags.incl nfExprCall
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil: return errorNode(c, n)
Expand All @@ -988,7 +988,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =

proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
# this seems to be a hotspot in the compiler!
let nOrig = n.copyTree
let nOrig: PNode = if callsiteAccess in c.config.features: n.copyTree else: nil
#semLazyOpAux(c, n)
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result != nil: result = afterCallActions(c, result, nOrig, flags)
Expand Down Expand Up @@ -1557,11 +1557,11 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
# a[0] is already checked for semantics, that does ``builtinFieldAccess``
# this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
# nodes?
let aOrig = nOrig[0]
result = newNode(nkCall, n.info, sons = @[setterId, a[0],
semExprWithType(c, n[1])])
result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExprWithType(c, n[1])])
result.flags.incl nfDotSetter
let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
var orig: PNode =
if nOrig != nil: newNode(nkCall, n.info, sons = @[setterId, nOrig[0][0], nOrig[1]])
else: nil
result = semOverloadedCallAnalyseEffects(c, result, orig, {})

if result != nil:
Expand Down Expand Up @@ -1667,7 +1667,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
of nkDotExpr:
# r.f = x
# --> `f=` (r, x)
let nOrig = n.copyTree
let nOrig: PNode = if callsiteAccess in c.config.features: n.copyTree else: nil

a = builtinFieldAccess(c, a, {efLValue})
if a == nil:
a = propertyWriteAccess(c, n, nOrig, n[0])
Expand Down Expand Up @@ -2242,7 +2243,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
of mPlugin:
markUsed(c, n.info, s)
# semDirectOp with conditional 'afterCallActions':
let nOrig = n.copyTree
let nOrig: PNode = if callsiteAccess in c.config.features: n.copyTree else: nil
#semLazyOpAux(c, n)
result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
if result == nil:
Expand Down
9 changes: 4 additions & 5 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2124,10 +2124,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
inc(m.genericMatches)
m.fauxMatch = a.kind
return arg
elif a.kind == tyVoid and f.matchesVoidProc and argOrig.kind == nkStmtList:
elif a.kind == tyVoid and f.matchesVoidProc and arg.kind == nkStmtList:
# lift do blocks without params to lambdas
let p = c.graph
let lifted = c.semExpr(c, newProcNode(nkDo, argOrig.info, body = argOrig,
let lifted = c.semExpr(c, newProcNode(nkDo, arg.info, body = arg,
params = nkFormalParams.newTree(p.emptyNode), name = p.emptyNode, pattern = p.emptyNode,
genericParams = p.emptyNode, pragmas = p.emptyNode, exceptions = p.emptyNode), {})
if f.kind == tyBuiltInTypeClass:
Expand Down Expand Up @@ -2423,8 +2423,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
m.typedescMatched = false
incl(marker, formal.position)
n[a] = prepareOperand(c, formal.typ, n[a])
arg = paramTypesMatch(m, formal.typ, n[a].typ,
n[a], nOrig[a])
arg = paramTypesMatch(m, formal.typ, n[a].typ, n[a], if nOrig != nil: nOrig[a] else: nil)
if arg != nil and m.baseTypeMatch and container != nil:
container.add arg
incrIndexType(container.typ)
Expand Down Expand Up @@ -2462,7 +2461,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
m.typedescMatched = false
n[a] = prepareOperand(c, formal.typ, n[a])
arg = paramTypesMatch(m, formal.typ, n[a].typ,
n[a], nOrig[a])
n.sons[a], if nOrig != nil: nOrig.sons[a] else: nil)
if arg == nil:
noMatch()
return
Expand Down
8 changes: 6 additions & 2 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1750,8 +1750,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
c.errorFlag.setLen 0
of opcCallSite:
ensureKind(rkNode)
if c.callsite != nil: regs[ra].node = c.callsite
else: stackTrace(c, tos, pc, errFieldXNotFound & "callsite")
if callsiteAccess in c.config.features:
if c.callsite != nil: regs[ra].node = c.callsite
else: stackTrace(c, tos, pc, errFieldXNotFound & "callsite")
else:
stackTrace(c, tos, pc, "Access to callsite requires compilation flag `--experimental:callsiteAccess`.")

of opcNGetLineInfo:
decodeBImm(rkNode)
let n = regs[rb].node
Expand Down
11 changes: 4 additions & 7 deletions lib/pure/unittest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ macro check*(conditions: untyped): untyped =
## check:
## "AKB48".toLowerAscii() == "akb48"
## 'C' in teams
let checked = callsite()[1]
let checked = conditions

template asgn(a: untyped, value: typed) =
var a = value # XXX: we need "var: var" here in order to
Expand Down Expand Up @@ -719,7 +719,6 @@ macro expect*(exceptions: varargs[typed], body: untyped): untyped =
##
## expect IOError, OSError, ValueError, AssertionError:
## defectiveRobot()
let exp = callsite()
template expectBody(errorTypes, lineInfoLit, body): NimNode {.dirty.} =
try:
body
Expand All @@ -731,13 +730,11 @@ macro expect*(exceptions: varargs[typed], body: untyped): untyped =
checkpoint(lineInfoLit & ": Expect Failed, unexpected exception was thrown.")
fail()

var body = exp[exp.len - 1]

var errorTypes = newNimNode(nnkBracket)
for i in countup(1, exp.len - 2):
errorTypes.add(exp[i])
for it in exceptions:
errorTypes.add it

result = getAst(expectBody(errorTypes, exp.lineInfo, body))
result = getAst(expectBody(errorTypes, body.lineInfo, body))

proc disableParamFiltering* =
## disables filtering tests with the command line params
Expand Down
1 change: 0 additions & 1 deletion tests/generics/tunique_type.nim
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ type Mapped[Input; predicate: static[string]] = object
input: Input

macro map(input, predicate: untyped): untyped =
let predicate = callsite()[2]
newNimNode(nnkObjConstr).add(
newNimNode(nnkBracketExpr).add(
ident"Mapped",
Expand Down
1 change: 0 additions & 1 deletion tests/macros/tdumpast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ macro call(e: untyped): untyped =

macro dumpAST(n: untyped): untyped =
# dump AST as a side-effect and return the inner node
let n = callsite()
echo n.lispRepr
echo n.treeRepr

Expand Down
3 changes: 0 additions & 3 deletions tests/macros/tdumpast2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ proc dumpit(n: NimNode): string {.compileTime.} =

macro dumpAST(n): untyped =
# dump AST as a side-effect and return the inner node
let n = callsite()
echo dumpit(n)
result = n[1]

Expand All @@ -32,5 +31,3 @@ dumpAST:
return x + y

proc sub(x, y: int): int = return x - y


5 changes: 2 additions & 3 deletions tests/macros/tmacro2.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
discard """
output: "ta-da Your value sir: 'HE!!!!o Wor!!d'"
output: "ta-da Your value sir: 'HE!!!!o Wor!!d'"
cmd: "nim c --experimental:callsiteAccess $file"
"""

import macros, strutils
Expand All @@ -24,5 +25,3 @@ macro mac(n: typed): string =
const s = testBlock()
const t = mac("HEllo World")
echo s, " ", t


2 changes: 1 addition & 1 deletion tests/macros/tmacroaspragma.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import macros

macro foo(x: untyped): untyped =
echo treerepr(callsite())
echo treerepr(x)
result = newNimNode(nnkStmtList)

proc zoo() {.foo.} = echo "hi"
7 changes: 5 additions & 2 deletions tests/macros/tmacros1.nim
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
discard """
output: '''Got: 'nnkCall' hi
cmd: "nim c --experimental:callsiteAccess $file"
output: '''
Got: 'nnkCall' hi
{a}
{b}
{a, b}'''
{a, b}
'''
"""

import macros
Expand Down
1 change: 1 addition & 0 deletions tests/macros/tquotewords.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
discard """
output: "thisanexample"
cmd: "nim c --experimental:callsiteAccess $file"
"""
# Test an idea I recently had:

Expand Down
1 change: 1 addition & 0 deletions tests/macros/tstringinterp.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
discard """
output: "Hello Alice, 64 | Hello Bob, 10$"
cmd: "nim c --experimental:callsiteAccess $file"
"""

import macros, parseutils, strutils
Expand Down
1 change: 1 addition & 0 deletions tests/misc/thallo.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
discard """
action: compile
cmd: "nim c --experimental:callsiteAccess $file"
"""

# noted this seems to be an old test file designed for manual testing.
Expand Down
3 changes: 2 additions & 1 deletion tests/objects/toop1.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
discard """
output: "34[]o 5"
output: "34[]o 5"
cmd: "nim c --experimental:callsiteAccess $file"
"""
# Test the stuff in the tutorial
import macros
Expand Down
10 changes: 4 additions & 6 deletions tests/usingstmt/tusingstatement.nim
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ import
# disposal of resources.
#
macro autoClose(args: varargs[untyped]): untyped =
let e = callsite()
if e.len != 3:
if args.len != 2:
error "Using statement: unexpected number of arguments. Got " &
$e.len & ", expected: 1 or more variable assignments and a block"
$args.len & ", expected: 1 or more variable assignments and a block"

var args = e
var body = e[2]
let body = args[^1]

var
variables : seq[NimNode]
Expand All @@ -27,7 +25,7 @@ macro autoClose(args: varargs[untyped]): untyped =
newSeq(variables, 0)
newSeq(closingCalls, 0)

for i in countup(1, args.len-2):
for i in countup(0, args.len-2):
if args[i].kind == nnkExprEqExpr:
var varName = args[i][0]
var varValue = args[i][1]
Expand Down
4 changes: 0 additions & 4 deletions tools/nimweb.nim
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,10 @@ Compile_options:

macro id(e: untyped): untyped =
## generates the rss xml ``id`` element.
let e = callsite()
result = xmlCheckedTag(e, "id")

macro updated(e: varargs[untyped]): untyped =
## generates the rss xml ``updated`` element.
let e = callsite()
result = xmlCheckedTag(e, "updated")

proc updatedDate(year, month, day: string): string =
Expand All @@ -126,12 +124,10 @@ proc updatedDate(year, month, day: string): string =

macro entry(e: varargs[untyped]): untyped =
## generates the rss xml ``entry`` element.
let e = callsite()
result = xmlCheckedTag(e, "entry")

macro content(e: varargs[untyped]): untyped =
## generates the rss xml ``content`` element.
let e = callsite()
result = xmlCheckedTag(e, "content", reqAttr = "type")

proc parseCmdLine(c: var TConfigData) =
Expand Down