Skip to content

Commit

Permalink
Merge #162
Browse files Browse the repository at this point in the history
162: Remove the nOrig from all over the compiler r=alaviss a=krux02

`nOrig` is pretty much only used for `macros.callsite` which is
deprecated/redundant since Nim has `untyped` as macro arguments. Since
then it has huge negative value on both developers as well as the
computer because all of this copyTree that is happening to preserve it.

Before this change, callsite returned an AST like it got spit out by
the parser. But overload resolution does modify the ast. arguments get
converted into nkArgList for varargs for example. To actually preserve
the unchanged AST, there is this `nOrig` parameter all over the
compiler. The idea is, befere a change is applied to the ast, deep copy
the tree and store it as `nOrig` and pass that down along `n`. But it
this strict AST preservation isn't tested, so I wouldn't assume that it
actually work.
 
Now I am passing down the node `n` instead of `nOrig` to callsite. So
when the macro expects typed arguments, the corresponding children in
the call node are also sem checked. Varargs are grouped to
`nkArgsList`.

So callsite in `myMacro(a,b)` is now often
`(nnkCall (ident "mymacro") (nnkArgsList (ident "a") (ident "b")))`
instead of `(nnkCall (ident "mymacro") (ident "a") (ident "b"))` which
causes indices to be wrong and the macro crashes or generates an
invalid ast.

The one thing to preserve callsite for, that can't be done with simply
reading the argument (which should have been done for years now), is to
get line information of the actual macro invocation. But for this it
might be better to just pass the the first child of call, the `symbol`
of the macro down to callsite.


Co-authored-by: Arne Döring <arne.doering@gmx.net>
  • Loading branch information
bors[bot] and krux02 authored Jan 28, 2022
2 parents afbd5fe + 8302719 commit 138a842
Show file tree
Hide file tree
Showing 18 changed files with 115 additions and 139 deletions.
13 changes: 6 additions & 7 deletions compiler/sem/hlo.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@

proc hlo(c: PContext, n: PNode): PNode

proc evalPattern(c: PContext, n, orig: PNode): PNode =
proc evalPattern(c: PContext, n: PNode): PNode =
internalAssert(
c.config,
n.kind == nkCall and n[0].kind == nkSym,
"Expected call node")

# we need to ensure that the resulting AST is semchecked. However, it's
# awful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context.
Expand All @@ -27,7 +26,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
let s = n[0].sym
case s.kind
of skMacro:
result = semMacroExpr(c, n, orig, s)
result = semMacroExpr(c, n, s)

of skTemplate:
result = semTemplateExpr(c, n, s, {efFromHlo})
Expand All @@ -36,9 +35,9 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
result = semDirectOp(c, n, {})

if c.config.hasHint(rsemPattern):
c.config.localReport(orig.info, SemReport(
c.config.localReport(n.info, SemReport(
kind: rsemPattern,
ast: original,
ast: n,
expandedAst: result))

proc applyPatterns(c: PContext, n: PNode): PNode =
Expand All @@ -62,10 +61,10 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
c.patterns[i] = nil
if x.kind == nkStmtList:
assert x.len == 3
x[1] = evalPattern(c, x[1], result)
x[1] = evalPattern(c, x[1])
result = flattenStmts(x)
else:
result = evalPattern(c, x, result)
result = evalPattern(c, x)
dec(c.config.evalTemplateCounter)
# activate this pattern again:
c.patterns[i] = pattern
Expand Down
2 changes: 1 addition & 1 deletion compiler/sem/pragmas.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
# invalidPragma(c, n)
# return n

let r = c.semOverloadedCall(c, callNode, n, {skTemplate}, {efNoUndeclared})
let r = c.semOverloadedCall(c, callNode, {skTemplate}, {efNoUndeclared})
if r.isNil or sfCustomPragma notin r[0].sym.flags:
result = c.config.newError(n, reportAst(rsemInvalidPragma, n))
return
Expand Down
16 changes: 8 additions & 8 deletions compiler/sem/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
flags: TExprFlags = {}): PNode

proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym =
Expand Down Expand Up @@ -570,10 +570,10 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
dec(c.config.evalTemplateCounter)
discard c.friendModules.pop()

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

let info = getCallLineInfo(n)
markUsed(c, info, sym)
Expand All @@ -595,19 +595,19 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
original = n

result = evalMacroCall(
c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym)
c.module, c.idgen, c.graph, c.templInstCounter, n, sym)

if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags)

if reportTraceExpand:
c.config.localReport(nOrig.info, SemReport(
c.config.localReport(n.info, SemReport(
sym: sym,
kind: rsemExpandMacro,
ast: original,
ast: n,
expandedAst: result))

result = wrapInComesFrom(nOrig.info, sym, result)
result = wrapInComesFrom(n.info, sym, result)
popInfoContext(c.config)

proc forceBool(c: PContext, n: PNode): PNode =
Expand Down
25 changes: 10 additions & 15 deletions compiler/sem/semcall.nim
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ proc initCandidateSymbols(c: PContext, headSymbol: PNode,
best.state = csNoMatch

proc pickBestCandidate(c: PContext, headSymbol: PNode,
n, orig: PNode,
n: PNode,
initialBinding: PNode,
filter: TSymKinds,
best, alt: var TCandidate,
Expand Down Expand Up @@ -92,7 +92,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
determineType(c, sym)
initCandidate(c, z, sym, initialBinding, scope, diagnosticsFlag)
if c.currentScope.symbols.counter == counterInitial or syms.len != 0:
matches(c, n, orig, z)
matches(c, n, z)
if z.state == csMatch:
# little hack so that iterators are preferred over everything else:
if sym.kind == skIterator:
Expand Down Expand Up @@ -328,7 +328,7 @@ proc getMsgDiagnostic(
result.spellingCandidates = fixSpelling(c, f.ident)


proc resolveOverloads(c: PContext, n, orig: PNode,
proc resolveOverloads(c: PContext, n: PNode,
filter: TSymKinds, flags: TExprFlags,
errors: var CandidateErrors,
errorsEnabled: bool = true): TCandidate =
Expand All @@ -344,7 +344,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
initialBinding = nil

template pickBest(headSymbol) =
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
pickBestCandidate(c, headSymbol, n, initialBinding,
filter, result, alt, errors, efExplain in flags,
errorsEnabled, flags)
pickBest(f)
Expand All @@ -357,13 +357,11 @@ 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)

pickBest(f)

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

Expand All @@ -374,12 +372,10 @@ 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]

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

if nfExplicitCall in n.flags:
Expand All @@ -393,7 +389,6 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
let calleeName = newIdentNode(getIdent(c.cache, f.ident.s[0..^2]), f.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]
pickBest(callOp)

if overloadsState == csEmpty and result.state == csEmpty:
Expand Down Expand Up @@ -459,15 +454,15 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =

proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
var m = newCandidate(c, f)
result = paramTypesMatch(m, f, a, arg, nil)
result = paramTypesMatch(m, f, a, arg)
if m.genericConverter and result != nil:
instGenericConvertersArg(c, result, m)

proc inferWithMetatype(c: PContext, formal: PType,
arg: PNode, coerceDistincts = false): PNode =
var m = newCandidate(c, formal)
m.coerceDistincts = coerceDistincts
result = paramTypesMatch(m, formal, arg.typ, arg, nil)
result = paramTypesMatch(m, formal, arg.typ, arg)
if m.genericConverter and result != nil:
instGenericConvertersArg(c, result, m)
if result != nil:
Expand Down Expand Up @@ -564,12 +559,12 @@ proc tryDeref(n: PNode): PNode =
result.typ = n.typ.skipTypes(abstractInst)[0]
result.add n

proc semOverloadedCall(c: PContext, n, nOrig: PNode,
proc semOverloadedCall(c: PContext, n: PNode,
filter: TSymKinds, flags: TExprFlags): PNode {.nosinks.} =
addInNimDebugUtils(c.config, "semOverloadedCall")
var errors: CandidateErrors = @[]

var r = resolveOverloads(c, n, nOrig, filter, flags, errors)
var r = resolveOverloads(c, n, filter, flags, errors)

if r.state != csMatch and implicitDeref in c.features and canDeref(n):
# try to deref the first argument and then try overloading resolution again:
Expand All @@ -580,7 +575,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
# into sigmatch with hidden conversion produced there

n[1] = n[1].tryDeref
r = resolveOverloads(c, n, nOrig, filter, flags, errors)
r = resolveOverloads(c, n, filter, flags, errors)

if r.state == csMatch:
# this may be triggered, when the explain pragma is used
Expand Down Expand Up @@ -708,7 +703,7 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
call.add(newNodeIT(nkEmpty, fn.info, x))
if hasDistinct:
let filter = if fn.kind in {skProc, skFunc}: {skProc, skFunc} else: {fn.kind}
var resolved = semOverloadedCall(c, call, call, filter, {})
var resolved = semOverloadedCall(c, call, filter, {})
if resolved != nil:
if resolved.kind == nkError:
localReport(c.config, resolved)
Expand Down
2 changes: 1 addition & 1 deletion compiler/sem/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ type

semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
semOverloadedCall*: proc (c: PContext, n: PNode,
filter: TSymKinds, flags: TExprFlags): PNode {.nimcall.}
semTypeNode*: proc(c: PContext, n: PNode, prev: PType): PType {.nimcall.}
semInferredLambda*: proc(c: PContext, pt: TIdTable, n: PNode): PNode
Expand Down
Loading

0 comments on commit 138a842

Please sign in to comment.