summary refs log tree commit diff stats
path: root/compiler/lookups.nim
diff options
context:
space:
mode:
authorJacek Sieka <arnetheduck@gmail.com>2016-08-25 22:59:51 +0800
committerJacek Sieka <arnetheduck@gmail.com>2016-08-25 22:59:51 +0800
commitdb2f96daba9c04db2f24cb783c79fb37799cd9ea (patch)
tree567beb43c7e4549abfcae1ea66e5232d7525e001 /compiler/lookups.nim
parent3116744c86f37ac4e4e5fec3d6d1635304ed717f (diff)
parent84a09d2f5b0866491e55fef0fef541e8cc548852 (diff)
downloadNim-db2f96daba9c04db2f24cb783c79fb37799cd9ea.tar.gz
Merge remote-tracking branch 'origin/devel' into initallocator-fix
Diffstat (limited to 'compiler/lookups.nim')
-rw-r--r--compiler/lookups.nim51
1 files changed, 38 insertions, 13 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index a337bf0f3..df19a6afb 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -99,8 +99,11 @@ proc debugScopes*(c: PContext; limit=0) {.deprecated.} =
 
 proc searchInScopes*(c: PContext, s: PIdent, filter: TSymKinds): PSym =
   for scope in walkScopes(c.currentScope):
-    result = strTableGet(scope.symbols, s)
-    if result != nil and result.kind in filter: return
+    var ti: TIdentIter
+    var candidate = initIdentIter(ti, scope.symbols, s)
+    while candidate != nil:
+      if candidate.kind in filter: return candidate
+      candidate = nextIdentIter(ti, scope.symbols)
   result = nil
 
 proc errorSym*(c: PContext, n: PNode): PSym =
@@ -153,7 +156,8 @@ proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
       if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
         # XXX: implicit type params are currently skTypes
         # maybe they can be made skGenericParam as well.
-        if s.typ != nil and tfImplicitTypeParam notin s.typ.flags:
+        if s.typ != nil and tfImplicitTypeParam notin s.typ.flags and
+           s.typ.kind != tyGenericParam:
           message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
     s = nextIter(it, scope.symbols)
 
@@ -161,6 +165,10 @@ proc wrongRedefinition*(info: TLineInfo, s: string) =
   if gCmd != cmdInteractive:
     localError(info, errAttemptToRedefine, s)
 
+proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) =
+  if not c.currentScope.addUniqueSym(sym):
+    wrongRedefinition(info, sym.name.s)
+
 proc addDecl*(c: PContext, sym: PSym) =
   if not c.currentScope.addUniqueSym(sym):
     wrongRedefinition(sym.info, sym.name.s)
@@ -212,14 +220,27 @@ when defined(nimfix):
     of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
     else: result = x
 
-  template fixSpelling(n: PNode; ident: PIdent; op: expr) =
+  template fixSpelling(n: PNode; ident: PIdent; op: untyped) =
     let alt = ident.altSpelling
     result = op(c, alt).skipAlias(n)
     if result != nil:
       prettybase.replaceDeprecated(n.info, ident, alt)
       return result
 else:
-  template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
+  template fixSpelling(n: PNode; ident: PIdent; op: untyped) = discard
+
+proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
+  var err = "Error: ambiguous identifier: '" & s.name.s & "'"
+  var ti: TIdentIter
+  var candidate = initIdentIter(ti, c.importTable.symbols, s.name)
+  var i = 0
+  while candidate != nil:
+    if i == 0: err.add " --use "
+    else: err.add " or "
+    err.add candidate.owner.name.s & "." & candidate.name.s
+    candidate = nextIdentIter(ti, c.importTable.symbols)
+    inc i
+  localError(info, errGenerated, err)
 
 proc lookUp*(c: PContext, n: PNode): PSym =
   # Looks up a symbol. Generates an error in case of nil.
@@ -243,32 +264,36 @@ proc lookUp*(c: PContext, n: PNode): PSym =
     internalError(n.info, "lookUp")
     return
   if contains(c.ambiguousSymbols, result.id):
-    localError(n.info, errUseQualifier, result.name.s)
+    errorUseQualifier(c, n.info, result)
   if result.kind == skStub: loadStub(result)
 
 type
   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
   of nkIdent, nkAccQuoted:
     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:
       fixSpelling(n, ident, searchInScopes)
       localError(n.info, errUndeclaredIdentifier, ident.s)
       result = errorSym(c, n)
     elif checkAmbiguity in flags and result != nil and
         contains(c.ambiguousSymbols, result.id):
-      localError(n.info, errUseQualifier, ident.s)
+      errorUseQualifier(c, n.info, result)
   of nkSym:
     result = n.sym
     if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
-      localError(n.info, errUseQualifier, n.sym.name.s)
+      errorUseQualifier(c, n.info, n.sym)
   of nkDotExpr:
     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:
       var ident: PIdent = nil
       if n.sons[1].kind == nkIdent:
@@ -313,7 +338,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     o.mode = oimDone
   of nkDotExpr:
     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:
       var ident: PIdent = nil
       if n.sons[1].kind == nkIdent: