summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-04-03 21:32:55 +0200
committerAraq <rumpf_a@web.de>2011-04-03 21:32:55 +0200
commit94f4256811625f2d9f02b7e885c9476de431f6a2 (patch)
treeab06f3dff68260cb31cc65a6d57efaff3ba32043
parent4741e8f9a1d1148d58e129626952219e14ede255 (diff)
downloadNim-94f4256811625f2d9f02b7e885c9476de431f6a2.tar.gz
Koenig's lookup implementation
-rwxr-xr-xrod/astalgo.nim119
-rwxr-xr-xrod/lookups.nim58
-rwxr-xr-xrod/semgnrc.nim45
-rwxr-xr-xrod/semstmts.nim42
-rw-r--r--tests/accept/run/tkoeniglookup.nim4
5 files changed, 137 insertions, 131 deletions
diff --git a/rod/astalgo.nim b/rod/astalgo.nim
index bb5a6cf56..2bd04618d 100755
--- a/rod/astalgo.nim
+++ b/rod/astalgo.nim
@@ -64,8 +64,8 @@ proc NextIter*(ti: var TTabIter, tab: TStrTable): PSym
   #
 
 type 
-  TIdentIter*{.final.} = object # iterator over all syms with the same identifier
-    h*: THash                 # current hash
+  TIdentIter*{.final.} = object # iterator over all syms with same identifier
+    h*: THash                   # current hash
     name*: PIdent
 
 
@@ -123,7 +123,7 @@ proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
 proc lookupInRecord*(n: PNode, field: PIdent): PSym
 proc getModule*(s: PSym): PSym
 proc mustRehash*(length, counter: int): bool
-proc nextTry*(h, maxHash: THash): THash
+proc nextTry*(h, maxHash: THash): THash {.inline.}
 
 # ------------- table[int, int] ---------------------------------------------
 const 
@@ -193,19 +193,17 @@ proc toYamlChar(c: Char): string =
   case c
   of '\0'..'\x1F', '\x80'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4)
   of '\'', '\"', '\\': result = '\\' & c
-  else: result = c & ""
+  else: result = $c
   
 proc makeYamlString*(s: string): PRope = 
   # We have to split long strings into many ropes. Otherwise
   # this could trigger InternalError(111). See the ropes module for
   # further information.
-  const 
-    MaxLineLength = 64
-  var res: string
+  const MaxLineLength = 64
   result = nil
-  res = "\""
-  for i in countup(0, len(s) + 0 - 1): 
-    if (i - 0 + 1) mod MaxLineLength == 0: 
+  var res = "\""
+  for i in countup(0, len(s) - 1): 
+    if (i + 1) mod MaxLineLength == 0: 
       add(res, '\"')
       add(res, "\n")
       app(result, toRope(res))
@@ -229,17 +227,17 @@ proc lineInfoToStr(info: TLineInfo): PRope =
                                   toRope(toLinenumber(info)), 
                                   toRope(toColumn(info))])
 
-proc treeToYamlAux(n: PNode, marker: var TIntSet, indent, maxRecDepth: int): PRope
-proc symToYamlAux(n: PSym, marker: var TIntSet, indent, maxRecDepth: int): PRope
-proc typeToYamlAux(n: PType, marker: var TIntSet, indent, maxRecDepth: int): PRope
+proc treeToYamlAux(n: PNode, marker: var TIntSet, 
+                   indent, maxRecDepth: int): PRope
+proc symToYamlAux(n: PSym, marker: var TIntSet, 
+                  indent, maxRecDepth: int): PRope
+proc typeToYamlAux(n: PType, marker: var TIntSet, 
+                   indent, maxRecDepth: int): PRope
 proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int, 
                     maxRecDepth: int): PRope = 
-  var 
-    istr: PRope
-    mycount: int
-  istr = spaces(indent + 2)
+  var istr = spaces(indent + 2)
   result = toRope("[")
-  mycount = 0
+  var mycount = 0
   for i in countup(0, high(n.data)): 
     if n.data[i] != nil: 
       if mycount > 0: app(result, ",")
@@ -252,12 +250,9 @@ proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int,
 
 proc ropeConstr(indent: int, c: openarray[PRope]): PRope = 
   # array of (name, value) pairs
-  var 
-    istr: PRope
-    i: int
-  istr = spaces(indent + 2)
+  var istr = spaces(indent + 2)
   result = toRope("{")
-  i = 0
+  var i = 0
   while i <= high(c): 
     if i > 0: app(result, ",")
     appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]])
@@ -315,13 +310,11 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
 
 proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int, 
                    maxRecDepth: int): PRope = 
-  var istr: PRope
   if n == nil: 
     result = toRope("null")
   else: 
-    istr = spaces(indent + 2)
-    result = ropef("{$n$1\"kind\": $2", 
-                   [istr, makeYamlString($n.kind)])
+    var istr = spaces(indent + 2)
+    result = ropef("{$n$1\"kind\": $2", [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
       appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)])
       case n.kind
@@ -386,11 +379,10 @@ proc debugType(n: PType): PRope =
       app(result, ")")
 
 proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = 
-  var istr: PRope
   if n == nil: 
     result = toRope("null")
   else: 
-    istr = spaces(indent + 2)
+    var istr = spaces(indent + 2)
     result = ropef("{$n$1\"kind\": $2", 
                    [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
@@ -443,8 +435,7 @@ proc nextTry(h, maxHash: THash): THash =
   
 proc objectSetContains(t: TObjectSet, obj: PObject): bool = 
   # returns true whether n is in t
-  var h: THash
-  h = hashNode(obj) and high(t.data) # start with real hash value
+  var h: THash = hashNode(obj) and high(t.data) # start with real hash value
   while t.data[h] != nil: 
     if (t.data[h] == obj): 
       return true
@@ -452,8 +443,7 @@ proc objectSetContains(t: TObjectSet, obj: PObject): bool =
   result = false
 
 proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) = 
-  var h: THash
-  h = HashNode(obj) and high(data)
+  var h: THash = HashNode(obj) and high(data)
   while data[h] != nil: 
     assert(data[h] != obj)
     h = nextTry(h, high(data))
@@ -474,12 +464,9 @@ proc objectSetIncl(t: var TObjectSet, obj: PObject) =
 
 proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool = 
   # returns true if obj is already in the string table:
-  var 
-    h: THash
-    it: PObject
-  h = HashNode(obj) and high(t.data)
+  var h: THash = HashNode(obj) and high(t.data)
   while true: 
-    it = t.data[h]
+    var it = t.data[h]
     if it == nil: break 
     if it == obj: 
       return true             # found it
@@ -494,20 +481,18 @@ proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool =
   result = false
 
 proc TableRawGet(t: TTable, key: PObject): int = 
-  var h: THash
-  h = hashNode(key) and high(t.data) # start with real hash value
+  var h: THash = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
-    if (t.data[h].key == key): 
+    if t.data[h].key == key: 
       return h
     h = nextTry(h, high(t.data))
-  result = - 1
+  result = -1
 
 proc TableSearch(t: TTable, key, closure: PObject, 
                  comparator: TCmpProc): PObject = 
-  var h: THash
-  h = hashNode(key) and high(t.data) # start with real hash value
+  var h: THash = hashNode(key) and high(t.data) # start with real hash value
   while t.data[h].key != nil: 
-    if (t.data[h].key == key): 
+    if t.data[h].key == key: 
       if comparator(t.data[h].val, closure): 
         # BUGFIX 1
         return t.data[h].val
@@ -520,8 +505,7 @@ proc TableGet(t: TTable, key: PObject): PObject =
   else: result = nil
   
 proc TableRawInsert(data: var TPairSeq, key, val: PObject) = 
-  var h: THash
-  h = HashNode(key) and high(data)
+  var h: THash = HashNode(key) and high(data)
   while data[h].key != nil: 
     assert(data[h].key != key)
     h = nextTry(h, high(data))
@@ -546,8 +530,7 @@ proc TablePut(t: var TTable, key, val: PObject) =
     inc(t.counter)
 
 proc StrTableContains(t: TStrTable, n: PSym): bool = 
-  var h: THash
-  h = n.name.h and high(t.data) # start with real hash value
+  var h: THash = n.name.h and high(t.data) # start with real hash value
   while t.data[h] != nil: 
     if (t.data[h] == n): 
       return true
@@ -555,8 +538,7 @@ proc StrTableContains(t: TStrTable, n: PSym): bool =
   result = false
 
 proc StrTableRawInsert(data: var TSymSeq, n: PSym) = 
-  var h: THash
-  h = n.name.h and high(data)
+  var h: THash = n.name.h and high(data)
   while data[h] != nil: 
     if data[h] == n: InternalError(n.info, "StrTableRawInsert: " & n.name.s)
     h = nextTry(h, high(data))
@@ -579,12 +561,9 @@ proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
   # returns true if n is already in the string table:
   # It is essential that `n` is written nevertheless!
   # This way the newest redefinition is picked by the semantic analyses!
-  var 
-    h: THash
-    it: PSym
-  h = n.name.h and high(t.data)
+  var h: THash = n.name.h and high(t.data)
   while true: 
-    it = t.data[h]
+    var it = t.data[h]
     if it == nil: break 
     if it.name.id == n.name.id: 
       t.data[h] = n           # overwrite it with newer definition!
@@ -600,8 +579,7 @@ proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
   result = false
 
 proc StrTableGet(t: TStrTable, name: PIdent): PSym = 
-  var h: THash
-  h = name.h and high(t.data)
+  var h: THash = name.h and high(t.data)
   while true: 
     result = t.data[h]
     if result == nil: break 
@@ -619,7 +597,7 @@ proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
   h = ti.h and high(tab.data)
   start = h
   result = tab.data[h]
-  while (result != nil): 
+  while result != nil: 
     if result.Name.id == ti.name.id: break 
     h = nextTry(h, high(tab.data))
     if h == start: 
@@ -627,6 +605,29 @@ proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
       break 
     result = tab.data[h]
   ti.h = nextTry(h, high(tab.data))
+  
+proc NextIdentExcluding*(ti: var TIdentIter, tab: TStrTable, 
+                         excluding: TIntSet): PSym =
+  var h: THash = ti.h and high(tab.data)
+  var start = h
+  result = tab.data[h]
+  while result != nil: 
+    if result.Name.id == ti.name.id and 
+        not IntSetContains(excluding, result.id): break
+    h = nextTry(h, high(tab.data))
+    if h == start: 
+      result = nil
+      break 
+    result = tab.data[h]
+  ti.h = nextTry(h, high(tab.data))
+  if result != nil and IntSetContains(excluding, result.id): result = nil
+
+proc FirstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
+                          excluding: TIntSet): PSym = 
+  ti.h = s.h
+  ti.name = s
+  if tab.Counter == 0: result = nil
+  else: result = NextIdentExcluding(ti, tab, excluding)
 
 proc InitTabIter(ti: var TTabIter, tab: TStrTable): PSym = 
   ti.h = 0                    # we start by zero ...
diff --git a/rod/lookups.nim b/rod/lookups.nim
index 160f9635b..f65fe24b7 100755
--- a/rod/lookups.nim
+++ b/rod/lookups.nim
@@ -14,12 +14,14 @@ import
 
 type 
   TOverloadIterMode* = enum 
-    oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice
+    oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
+    oimSymChoiceLocalLookup
   TOverloadIter*{.final.} = object 
     stackPtr*: int
     it*: TIdentIter
     m*: PSym
     mode*: TOverloadIterMode
+    inSymChoice: TIntSet
 
 proc getSymRepr*(s: PSym): string = 
   case s.kind
@@ -27,12 +29,10 @@ proc getSymRepr*(s: PSym): string =
   else: result = s.name.s
   
 proc CloseScope*(tab: var TSymTab) = 
-  var 
-    it: TTabIter
-    s: PSym
   # check if all symbols have been used and defined:
   if (tab.tos > len(tab.stack)): InternalError("CloseScope")
-  s = InitTabIter(it, tab.stack[tab.tos - 1])
+  var it: TTabIter
+  var s = InitTabIter(it, tab.stack[tab.tos-1])
   while s != nil: 
     if sfForward in s.flags: 
       LocalError(s.info, errImplOfXexpected, getSymRepr(s))
@@ -40,7 +40,7 @@ proc CloseScope*(tab: var TSymTab) =
         (optHints in s.options): # BUGFIX: check options in s!
       if not (s.kind in {skForVar, skParam, skMethod, skUnknown}): 
         Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
-    s = NextIter(it, tab.stack[tab.tos - 1])
+    s = NextIter(it, tab.stack[tab.tos-1])
   astalgo.rawCloseScope(tab)
 
 proc AddSym*(t: var TStrTable, n: PSym) = 
@@ -144,12 +144,11 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
   if (result != nil) and (result.kind == skStub): loadStub(result)
   
 proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
-  result = nil
   case n.kind
   of nkIdent: 
     o.stackPtr = c.tab.tos
     o.mode = oimNoQualifier
-    while (result == nil): 
+    while result == nil: 
       dec(o.stackPtr)
       if o.stackPtr < 0: break 
       result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident)
@@ -159,12 +158,12 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
   of nkDotExpr: 
     o.mode = oimOtherModule
     o.m = qualifiedLookUp(c, n.sons[0])
-    if (o.m != nil) and (o.m.kind == skModule): 
+    if o.m != nil and o.m.kind == skModule:
       var ident: PIdent = nil
-      if (n.sons[1].kind == nkIdent): 
+      if n.sons[1].kind == nkIdent: 
         ident = n.sons[1].ident
-      elif (n.sons[1].kind == nkAccQuoted) and
-          (n.sons[1].sons[0].kind == nkIdent): 
+      elif n.sons[1].kind == nkAccQuoted and
+          n.sons[1].sons[0].kind == nkIdent: 
         ident = n.sons[1].sons[0].ident
       if ident != nil: 
         if o.m == c.module: 
@@ -182,9 +181,10 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     o.mode = oimSymChoice
     result = n.sons[0].sym
     o.stackPtr = 1
-  else: 
-    nil
-  if (result != nil) and (result.kind == skStub): loadStub(result)
+    IntSetInit(o.inSymChoice)
+    IntSetIncl(o.inSymChoice, result.id)
+  else: nil
+  if result != nil and result.kind == skStub: loadStub(result)
   
 proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = 
   case o.mode
@@ -192,10 +192,10 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
     result = nil
   of oimNoQualifier: 
     if n.kind == nkAccQuoted: 
-      result = nextOverloadIter(o, c, n.sons[0]) # BUGFIX
+      result = nextOverloadIter(o, c, n.sons[0])
     elif o.stackPtr >= 0: 
       result = nextIdentIter(o.it, c.tab.stack[o.stackPtr])
-      while (result == nil): 
+      while result == nil: 
         dec(o.stackPtr)
         if o.stackPtr < 0: break 
         result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name) 
@@ -209,8 +209,26 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
   of oimSymChoice: 
     if o.stackPtr < sonsLen(n): 
       result = n.sons[o.stackPtr].sym
+      IntSetIncl(o.inSymChoice, result.id)
       inc(o.stackPtr)
-    else: 
-      result = nil
-  if (result != nil) and (result.kind == skStub): loadStub(result)
+    else:
+      # try 'local' symbols too for Koenig's lookup:
+      o.mode = oimSymChoiceLocalLookup
+      o.stackPtr = c.tab.tos-1
+      result = FirstIdentExcluding(o.it, c.tab.stack[o.stackPtr], 
+                                   n.sons[0].sym.name, o.inSymChoice)
+      while result == nil:
+        dec(o.stackPtr)
+        if o.stackPtr < 0: break 
+        result = FirstIdentExcluding(o.it, c.tab.stack[o.stackPtr], 
+                                     n.sons[0].sym.name, o.inSymChoice)
+  of oimSymChoiceLocalLookup:
+    result = nextIdentExcluding(o.it, c.tab.stack[o.stackPtr], o.inSymChoice)
+    while result == nil:
+      dec(o.stackPtr)
+      if o.stackPtr < 0: break 
+      result = FirstIdentExcluding(o.it, c.tab.stack[o.stackPtr], 
+                                   n.sons[0].sym.name, o.inSymChoice)
+  
+  if result != nil and result.kind == skStub: loadStub(result)
   
diff --git a/rod/semgnrc.nim b/rod/semgnrc.nim
index 633994942..4894843f8 100755
--- a/rod/semgnrc.nim
+++ b/rod/semgnrc.nim
@@ -64,10 +64,8 @@ proc getIdentNode(n: PNode): PNode =
 #    if withinBind in flags: result = symChoice(c, n, s)
 #    else: result = semGenericStmtSymbol(c, n, s)
 
-proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode = 
-  var 
-    L: int
-    a: PNode
+proc semGenericStmt(c: PContext, n: PNode, 
+                    flags: TSemGenericFlags = {}): PNode = 
   result = n
   if gCmd == cmdIdeTools: suggestStmt(c, n)
   case n.kind
@@ -124,14 +122,14 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     openScope(c.tab)
     n.sons[0] = semGenericStmt(c, n.sons[0])
     for i in countup(1, sonsLen(n)-1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       checkMinSonsLen(a, 1)
-      L = sonsLen(a)
+      var L = sonsLen(a)
       for j in countup(0, L - 2): a.sons[j] = semGenericStmt(c, a.sons[j])
       a.sons[L - 1] = semGenericStmtScope(c, a.sons[L - 1])
     closeScope(c.tab)
   of nkForStmt: 
-    L = sonsLen(n)
+    var L = sonsLen(n)
     openScope(c.tab)
     n.sons[L - 2] = semGenericStmt(c, n.sons[L - 2])
     for i in countup(0, L - 3): addDecl(c, newSymS(skUnknown, n.sons[i], c))
@@ -147,36 +145,36 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     checkMinSonsLen(n, 2)
     n.sons[0] = semGenericStmtScope(c, n.sons[0])
     for i in countup(1, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       checkMinSonsLen(a, 1)
-      L = sonsLen(a)
+      var L = sonsLen(a)
       for j in countup(0, L - 2): 
         a.sons[j] = semGenericStmt(c, a.sons[j], {withinTypeDesc})
       a.sons[L - 1] = semGenericStmtScope(c, a.sons[L - 1])
   of nkVarSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
       checkMinSonsLen(a, 3)
-      L = sonsLen(a)
-      a.sons[L - 2] = semGenericStmt(c, a.sons[L - 2], {withinTypeDesc})
-      a.sons[L - 1] = semGenericStmt(c, a.sons[L - 1])
-      for j in countup(0, L - 3): 
+      var L = sonsLen(a)
+      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc})
+      a.sons[L-1] = semGenericStmt(c, a.sons[L-1])
+      for j in countup(0, L-3):
         addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
   of nkGenericParams: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if (a.kind != nkIdentDefs): IllFormedAst(a)
       checkMinSonsLen(a, 3)
-      L = sonsLen(a)
-      a.sons[L - 2] = semGenericStmt(c, a.sons[L - 2], {withinTypeDesc}) 
+      var L = sonsLen(a)
+      a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc}) 
       # do not perform symbol lookup for default expressions 
-      for j in countup(0, L - 3): 
+      for j in countup(0, L-3): 
         addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
   of nkConstSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkConstDef): IllFormedAst(a)
       checkSonsLen(a, 3)
@@ -185,13 +183,13 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
       a.sons[2] = semGenericStmt(c, a.sons[2])
   of nkTypeSection: 
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkTypeDef): IllFormedAst(a)
       checkSonsLen(a, 3)
       addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
     for i in countup(0, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if a.kind == nkCommentStmt: continue 
       if (a.kind != nkTypeDef): IllFormedAst(a)
       checkSonsLen(a, 3)
@@ -207,6 +205,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
     for i in countup(1, sonsLen(n) - 1): 
+      var a: PNode
       case n.sons[i].kind
       of nkEnumFieldDef: a = n.sons[i].sons[0]
       of nkIdent: a = n.sons[i]
@@ -219,10 +218,10 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
     if n.sons[0].kind != nkEmpty: 
       n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
     for i in countup(1, sonsLen(n) - 1): 
-      a = n.sons[i]
+      var a = n.sons[i]
       if (a.kind != nkIdentDefs): IllFormedAst(a)
       checkMinSonsLen(a, 3)
-      L = sonsLen(a)
+      var L = sonsLen(a)
       a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc})
       a.sons[L-1] = semGenericStmt(c, a.sons[L-1])
       for j in countup(0, L-3): 
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index b2fae3f31..5ec504708 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -85,7 +85,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
     of nkIdent: s = lookUp(c, n.sons[0])
     of nkSym: s = n.sons[0].sym
     else: illFormedAst(n)
-    if (s.kind == skLabel) and (s.owner.id == c.p.owner.id): 
+    if s.kind == skLabel and s.owner.id == c.p.owner.id: 
       var x = newSymNode(s)
       x.info = n.info
       incl(s.flags, sfUsed)
@@ -266,6 +266,13 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
   elif not sameType(result.typ, typ): 
     changeType(result, typ)
   
+proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
+  if isTopLevel(c): 
+    result = semIdentWithPragma(c, kind, n, {sfStar, sfMinus})
+    incl(result.flags, sfGlobal)
+  else: 
+    result = semIdentWithPragma(c, kind, n, {})
+  
 proc semVar(c: PContext, n: PNode): PNode = 
   var b: PNode
   result = copyNode(n)
@@ -304,13 +311,8 @@ proc semVar(c: PContext, n: PNode): PNode =
       b.sons[length - 2] = ast.emptyNode # no type desc
       b.sons[length - 1] = def
       addSon(result, b)
-    for j in countup(0, length - 3): 
-      var v: PSym
-      if (c.p.owner.kind == skModule): 
-        v = semIdentWithPragma(c, skVar, a.sons[j], {sfStar, sfMinus})
-        incl(v.flags, sfGlobal)
-      else: 
-        v = semIdentWithPragma(c, skVar, a.sons[j], {})
+    for j in countup(0, length-3): 
+      var v = semIdentDef(c, a.sons[j], skVar)
       if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
       addInterfaceDecl(c, v)
       if a.kind != nkVarTuple: 
@@ -332,12 +334,7 @@ proc semConst(c: PContext, n: PNode): PNode =
     if a.kind == nkCommentStmt: continue 
     if (a.kind != nkConstDef): IllFormedAst(a)
     checkSonsLen(a, 3)
-    var v: PSym
-    if (c.p.owner.kind == skModule): 
-      v = semIdentWithPragma(c, skConst, a.sons[0], {sfStar, sfMinus})
-      incl(v.flags, sfGlobal)
-    else: 
-      v = semIdentWithPragma(c, skConst, a.sons[0], {})
+    var v = semIdentDef(c, a.sons[0], skConst)
     var typ: PType = nil
     if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
     var def = semAndEvalConstExpr(c, a.sons[2]) 
@@ -524,12 +521,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
     if a.kind == nkCommentStmt: continue 
     if a.kind != nkTypeDef: IllFormedAst(a)
     checkSonsLen(a, 3)
-    var s: PSym
-    if c.p.owner.kind == skModule: 
-      s = semIdentWithPragma(c, skType, a.sons[0], {sfStar, sfMinus})
-      incl(s.flags, sfGlobal)
-    else: 
-      s = semIdentWithPragma(c, skType, a.sons[0], {})
+    var s = semIdentDef(c, a.sons[0], skType)
     if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface)
     s.typ = newTypeS(tyForward, c)
     s.typ.sym = s             # process pragmas:
@@ -547,7 +539,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
     checkSonsLen(a, 3)
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
     var s = a.sons[0].sym
-    if (s.magic == mNone) and (a.sons[2].kind == nkEmpty): 
+    if s.magic == mNone and a.sons[2].kind == nkEmpty: 
       GlobalError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
     if a.sons[1].kind != nkEmpty: 
@@ -680,15 +672,11 @@ proc semLambda(c: PContext, n: PNode): PNode =
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind, 
                 validPragmas: TSpecialWords): PNode = 
   var 
-    s, proto: PSym
+    proto: PSym
     gp: PNode
   result = n
   checkSonsLen(n, codePos + 1)
-  if c.p.owner.kind == skModule: 
-    s = semIdentVis(c, kind, n.sons[0], {sfStar})
-    incl(s.flags, sfGlobal)
-  else: 
-    s = semIdentVis(c, kind, n.sons[0], {})
+  var s = semIdentDef(c, n.sons[0], kind)
   n.sons[namePos] = newSymNode(s)
   var oldP = c.p                  # restore later
   if sfStar in s.flags: incl(s.flags, sfInInterface)
diff --git a/tests/accept/run/tkoeniglookup.nim b/tests/accept/run/tkoeniglookup.nim
index 07c5b46be..e6f5c0112 100644
--- a/tests/accept/run/tkoeniglookup.nim
+++ b/tests/accept/run/tkoeniglookup.nim
@@ -9,8 +9,8 @@ type
   TMyObj = object
     x, y: int
 
-proc `$`*(a: TMyObj): bool = 
-  result = "x: " & a.x & " y: " & a.y
+proc `$`*(a: TMyObj): string = 
+  result = "x: " & $a.x & " y: " & $a.y
 
 var a: TMyObj
 echo toString(a)