This commit is contained in:
Andreas Rumpf 2016-08-02 12:47:02 +02:00
commit de6198c747
8 changed files with 38 additions and 14 deletions

View file

@ -99,8 +99,11 @@ proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym = proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
for scope in walkScopes(c.currentScope): for scope in walkScopes(c.currentScope):
result = strTableGet(scope.symbols, s) var ti: TIdentIter
if result != nil and result.kind in filter: return var candidate = initIdentIter(ti, scope.symbols, s)
while candidate != nil:
if candidate.kind in filter: return candidate
candidate = nextIdentIter(ti, scope.symbols)
result = nil result = nil
proc errorSym*(c: PContext, n: PNode): PSym = proc errorSym*(c: PContext, n: PNode): PSym =
@ -266,13 +269,17 @@ proc lookUp*(c: PContext, n: PNode): PSym =
type type
TLookupFlag* = enum TLookupFlag* = enum
checkAmbiguity, checkUndeclared checkAmbiguity, checkUndeclared, checkModule
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
const allExceptModule = {low(TSymKind)..high(TSymKind)}-{skModule,skPackage}
case n.kind case n.kind
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
var ident = considerQuotedIdent(n) var ident = considerQuotedIdent(n)
result = searchInScopes(c, ident).skipAlias(n) if checkModule in flags:
result = searchInScopes(c, ident).skipAlias(n)
else:
result = searchInScopes(c, ident, allExceptModule).skipAlias(n)
if result == nil and checkUndeclared in flags: if result == nil and checkUndeclared in flags:
fixSpelling(n, ident, searchInScopes) fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s) localError(n.info, errUndeclaredIdentifier, ident.s)
@ -286,7 +293,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
errorUseQualifier(c, n.info, n.sym) errorUseQualifier(c, n.info, n.sym)
of nkDotExpr: of nkDotExpr:
result = nil result = nil
var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) var m = qualifiedLookUp(c, n.sons[0], (flags*{checkUndeclared})+{checkModule})
if m != nil and m.kind == skModule: if m != nil and m.kind == skModule:
var ident: PIdent = nil var ident: PIdent = nil
if n.sons[1].kind == nkIdent: if n.sons[1].kind == nkIdent:
@ -331,7 +338,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimDone o.mode = oimDone
of nkDotExpr: of nkDotExpr:
o.mode = oimOtherModule o.mode = oimOtherModule
o.m = qualifiedLookUp(c, n.sons[0]) o.m = qualifiedLookUp(c, n.sons[0], {checkUndeclared, checkModule})
if o.m != nil and o.m.kind == skModule: if o.m != nil and o.m.kind == skModule:
var ident: PIdent = nil var ident: PIdent = nil
if n.sons[1].kind == nkIdent: if n.sons[1].kind == nkIdent:

View file

@ -569,7 +569,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) =
localError(pragma.info, "list of key:value pairs expected"); return localError(pragma.info, "list of key:value pairs expected"); return
for n in pragma: for n in pragma:
if n.kind in {nkExprColonExpr, nkExprEqExpr}: if n.kind in {nkExprColonExpr, nkExprEqExpr}:
let dest = qualifiedLookUp(c, n[1]) let dest = qualifiedLookUp(c, n[1], {checkUndeclared})
let src = considerQuotedIdent(n[0]) let src = considerQuotedIdent(n[0])
let alias = newSym(skAlias, src, dest, n[0].info) let alias = newSym(skAlias, src, dest, n[0].info)
incl(alias.flags, sfExported) incl(alias.flags, sfExported)
@ -594,7 +594,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
# and perform the lookup on demand instead. # and perform the lookup on demand instead.
result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info) result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info)
else: else:
result = qualifiedLookUp(c, n) result = qualifiedLookUp(c, n, {checkUndeclared})
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
validPragmas: TSpecialWords): bool = validPragmas: TSpecialWords): bool =

View file

@ -1107,7 +1107,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
# here at all! # here at all!
#if isSymChoice(n.sons[1]): return #if isSymChoice(n.sons[1]): return
var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared, checkModule})
if s != nil: if s != nil:
if s.kind in OverloadableSyms: if s.kind in OverloadableSyms:
result = symChoice(c, n, s, scClosed) result = symChoice(c, n, s, scClosed)

View file

@ -127,7 +127,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
assert n.kind == nkDotExpr assert n.kind == nkDotExpr
semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody)
let luf = if withinMixin notin flags: {checkUndeclared} else: {} let luf = if withinMixin notin flags: {checkUndeclared, checkModule} else: {checkModule}
var s = qualifiedLookUp(c, n, luf) var s = qualifiedLookUp(c, n, luf)
if s != nil: if s != nil:

View file

@ -133,7 +133,7 @@ proc semBindSym(c: PContext, n: PNode): PNode =
return errorNode(c, n) return errorNode(c, n)
let id = newIdentNode(getIdent(sl.strVal), n.info) let id = newIdentNode(getIdent(sl.strVal), n.info)
let s = qualifiedLookUp(c, id) let s = qualifiedLookUp(c, id, {checkUndeclared})
if s != nil: if s != nil:
# we need to mark all symbols: # we need to mark all symbols:
var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal)) var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))

View file

@ -675,7 +675,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
let name = a.sons[0] let name = a.sons[0]
var s: PSym var s: PSym
if name.kind == nkDotExpr: if name.kind == nkDotExpr:
s = qualifiedLookUp(c, name) s = qualifiedLookUp(c, name, {checkUndeclared, checkModule})
if s.kind != skType or s.typ.skipTypes(abstractPtrs).kind != tyObject or tfPartial notin s.typ.skipTypes(abstractPtrs).flags: if s.kind != skType or s.typ.skipTypes(abstractPtrs).kind != tyObject or tfPartial notin s.typ.skipTypes(abstractPtrs).flags:
localError(name.info, "only .partial objects can be extended") localError(name.info, "only .partial objects can be extended")
else: else:

View file

@ -80,7 +80,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
# the same symbol! # the same symbol!
# This is however not true anymore for hygienic templates as semantic # This is however not true anymore for hygienic templates as semantic
# processing for them changes the symbol table... # processing for them changes the symbol table...
let s = qualifiedLookUp(c, a) let s = qualifiedLookUp(c, a, {checkUndeclared})
if s != nil: if s != nil:
# we need to mark all symbols: # we need to mark all symbols:
let sc = symChoice(c, n, s, scClosed) let sc = symChoice(c, n, s, scClosed)

17
tests/lookups/test.nim Normal file
View file

@ -0,0 +1,17 @@
# This file needs to be called 'test' nim to provoke a clash
# with the unittest.test name. Issue #
import unittest, macros
# bug #4555
macro memo(n: untyped): typed =
result = n
proc fastFib(n: int): int {.memo.} = 40
proc fib(n: int): int = 40
suite "memoization":
test "recursive function memoization":
check fastFib(40) == fib(40)