Koenig's lookup implementation

This commit is contained in:
Araq 2011-04-03 21:32:55 +02:00
commit 94f4256811
5 changed files with 137 additions and 131 deletions

View file

@ -64,8 +64,8 @@ proc NextIter*(ti: var TTabIter, tab: TStrTable): PSym
# #
type type
TIdentIter*{.final.} = object # iterator over all syms with the same identifier TIdentIter*{.final.} = object # iterator over all syms with same identifier
h*: THash # current hash h*: THash # current hash
name*: PIdent name*: PIdent
@ -123,7 +123,7 @@ proc getSymFromList*(list: PNode, ident: PIdent, start: int = 0): PSym
proc lookupInRecord*(n: PNode, field: PIdent): PSym proc lookupInRecord*(n: PNode, field: PIdent): PSym
proc getModule*(s: PSym): PSym proc getModule*(s: PSym): PSym
proc mustRehash*(length, counter: int): bool proc mustRehash*(length, counter: int): bool
proc nextTry*(h, maxHash: THash): THash proc nextTry*(h, maxHash: THash): THash {.inline.}
# ------------- table[int, int] --------------------------------------------- # ------------- table[int, int] ---------------------------------------------
const const
@ -193,19 +193,17 @@ proc toYamlChar(c: Char): string =
case c case c
of '\0'..'\x1F', '\x80'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4) of '\0'..'\x1F', '\x80'..'\xFF': result = "\\u" & strutils.toHex(ord(c), 4)
of '\'', '\"', '\\': result = '\\' & c of '\'', '\"', '\\': result = '\\' & c
else: result = c & "" else: result = $c
proc makeYamlString*(s: string): PRope = proc makeYamlString*(s: string): PRope =
# We have to split long strings into many ropes. Otherwise # We have to split long strings into many ropes. Otherwise
# this could trigger InternalError(111). See the ropes module for # this could trigger InternalError(111). See the ropes module for
# further information. # further information.
const const MaxLineLength = 64
MaxLineLength = 64
var res: string
result = nil result = nil
res = "\"" var res = "\""
for i in countup(0, len(s) + 0 - 1): for i in countup(0, len(s) - 1):
if (i - 0 + 1) mod MaxLineLength == 0: if (i + 1) mod MaxLineLength == 0:
add(res, '\"') add(res, '\"')
add(res, "\n") add(res, "\n")
app(result, toRope(res)) app(result, toRope(res))
@ -229,17 +227,17 @@ proc lineInfoToStr(info: TLineInfo): PRope =
toRope(toLinenumber(info)), toRope(toLinenumber(info)),
toRope(toColumn(info))]) toRope(toColumn(info))])
proc treeToYamlAux(n: PNode, marker: var TIntSet, indent, maxRecDepth: int): PRope proc treeToYamlAux(n: PNode, marker: var TIntSet,
proc symToYamlAux(n: PSym, marker: var TIntSet, indent, maxRecDepth: int): PRope indent, maxRecDepth: int): PRope
proc typeToYamlAux(n: PType, 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, proc strTableToYaml(n: TStrTable, marker: var TIntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): PRope =
var var istr = spaces(indent + 2)
istr: PRope
mycount: int
istr = spaces(indent + 2)
result = toRope("[") result = toRope("[")
mycount = 0 var mycount = 0
for i in countup(0, high(n.data)): for i in countup(0, high(n.data)):
if n.data[i] != nil: if n.data[i] != nil:
if mycount > 0: app(result, ",") 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 = proc ropeConstr(indent: int, c: openarray[PRope]): PRope =
# array of (name, value) pairs # array of (name, value) pairs
var var istr = spaces(indent + 2)
istr: PRope
i: int
istr = spaces(indent + 2)
result = toRope("{") result = toRope("{")
i = 0 var i = 0
while i <= high(c): while i <= high(c):
if i > 0: app(result, ",") if i > 0: app(result, ",")
appf(result, "$n$1\"$2\": $3", [istr, c[i], c[i + 1]]) 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, proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
maxRecDepth: int): PRope = maxRecDepth: int): PRope =
var istr: PRope
if n == nil: if n == nil:
result = toRope("null") result = toRope("null")
else: else:
istr = spaces(indent + 2) var istr = spaces(indent + 2)
result = ropef("{$n$1\"kind\": $2", result = ropef("{$n$1\"kind\": $2", [istr, makeYamlString($n.kind)])
[istr, makeYamlString($n.kind)])
if maxRecDepth != 0: if maxRecDepth != 0:
appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)]) appf(result, ",$n$1\"info\": $2", [istr, lineInfoToStr(n.info)])
case n.kind case n.kind
@ -386,11 +379,10 @@ proc debugType(n: PType): PRope =
app(result, ")") app(result, ")")
proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope = proc debugTree(n: PNode, indent: int, maxRecDepth: int): PRope =
var istr: PRope
if n == nil: if n == nil:
result = toRope("null") result = toRope("null")
else: else:
istr = spaces(indent + 2) var istr = spaces(indent + 2)
result = ropef("{$n$1\"kind\": $2", result = ropef("{$n$1\"kind\": $2",
[istr, makeYamlString($n.kind)]) [istr, makeYamlString($n.kind)])
if maxRecDepth != 0: if maxRecDepth != 0:
@ -443,8 +435,7 @@ proc nextTry(h, maxHash: THash): THash =
proc objectSetContains(t: TObjectSet, obj: PObject): bool = proc objectSetContains(t: TObjectSet, obj: PObject): bool =
# returns true whether n is in t # returns true whether n is in t
var h: THash var h: THash = hashNode(obj) and high(t.data) # start with real hash value
h = hashNode(obj) and high(t.data) # start with real hash value
while t.data[h] != nil: while t.data[h] != nil:
if (t.data[h] == obj): if (t.data[h] == obj):
return true return true
@ -452,8 +443,7 @@ proc objectSetContains(t: TObjectSet, obj: PObject): bool =
result = false result = false
proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) = proc objectSetRawInsert(data: var TObjectSeq, obj: PObject) =
var h: THash var h: THash = HashNode(obj) and high(data)
h = HashNode(obj) and high(data)
while data[h] != nil: while data[h] != nil:
assert(data[h] != obj) assert(data[h] != obj)
h = nextTry(h, high(data)) h = nextTry(h, high(data))
@ -474,12 +464,9 @@ proc objectSetIncl(t: var TObjectSet, obj: PObject) =
proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool = proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool =
# returns true if obj is already in the string table: # returns true if obj is already in the string table:
var var h: THash = HashNode(obj) and high(t.data)
h: THash
it: PObject
h = HashNode(obj) and high(t.data)
while true: while true:
it = t.data[h] var it = t.data[h]
if it == nil: break if it == nil: break
if it == obj: if it == obj:
return true # found it return true # found it
@ -494,20 +481,18 @@ proc objectSetContainsOrIncl(t: var TObjectSet, obj: PObject): bool =
result = false result = false
proc TableRawGet(t: TTable, key: PObject): int = proc TableRawGet(t: TTable, key: PObject): int =
var h: THash var h: THash = hashNode(key) and high(t.data) # start with real hash value
h = hashNode(key) and high(t.data) # start with real hash value
while t.data[h].key != nil: while t.data[h].key != nil:
if (t.data[h].key == key): if t.data[h].key == key:
return h return h
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
result = - 1 result = -1
proc TableSearch(t: TTable, key, closure: PObject, proc TableSearch(t: TTable, key, closure: PObject,
comparator: TCmpProc): PObject = comparator: TCmpProc): PObject =
var h: THash var h: THash = hashNode(key) and high(t.data) # start with real hash value
h = hashNode(key) and high(t.data) # start with real hash value
while t.data[h].key != nil: 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): if comparator(t.data[h].val, closure):
# BUGFIX 1 # BUGFIX 1
return t.data[h].val return t.data[h].val
@ -520,8 +505,7 @@ proc TableGet(t: TTable, key: PObject): PObject =
else: result = nil else: result = nil
proc TableRawInsert(data: var TPairSeq, key, val: PObject) = proc TableRawInsert(data: var TPairSeq, key, val: PObject) =
var h: THash var h: THash = HashNode(key) and high(data)
h = HashNode(key) and high(data)
while data[h].key != nil: while data[h].key != nil:
assert(data[h].key != key) assert(data[h].key != key)
h = nextTry(h, high(data)) h = nextTry(h, high(data))
@ -546,8 +530,7 @@ proc TablePut(t: var TTable, key, val: PObject) =
inc(t.counter) inc(t.counter)
proc StrTableContains(t: TStrTable, n: PSym): bool = proc StrTableContains(t: TStrTable, n: PSym): bool =
var h: THash var h: THash = n.name.h and high(t.data) # start with real hash value
h = n.name.h and high(t.data) # start with real hash value
while t.data[h] != nil: while t.data[h] != nil:
if (t.data[h] == n): if (t.data[h] == n):
return true return true
@ -555,8 +538,7 @@ proc StrTableContains(t: TStrTable, n: PSym): bool =
result = false result = false
proc StrTableRawInsert(data: var TSymSeq, n: PSym) = proc StrTableRawInsert(data: var TSymSeq, n: PSym) =
var h: THash var h: THash = n.name.h and high(data)
h = n.name.h and high(data)
while data[h] != nil: while data[h] != nil:
if data[h] == n: InternalError(n.info, "StrTableRawInsert: " & n.name.s) if data[h] == n: InternalError(n.info, "StrTableRawInsert: " & n.name.s)
h = nextTry(h, high(data)) 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: # returns true if n is already in the string table:
# It is essential that `n` is written nevertheless! # It is essential that `n` is written nevertheless!
# This way the newest redefinition is picked by the semantic analyses! # This way the newest redefinition is picked by the semantic analyses!
var var h: THash = n.name.h and high(t.data)
h: THash
it: PSym
h = n.name.h and high(t.data)
while true: while true:
it = t.data[h] var it = t.data[h]
if it == nil: break if it == nil: break
if it.name.id == n.name.id: if it.name.id == n.name.id:
t.data[h] = n # overwrite it with newer definition! t.data[h] = n # overwrite it with newer definition!
@ -600,8 +579,7 @@ proc StrTableIncl*(t: var TStrTable, n: PSym): bool =
result = false result = false
proc StrTableGet(t: TStrTable, name: PIdent): PSym = proc StrTableGet(t: TStrTable, name: PIdent): PSym =
var h: THash var h: THash = name.h and high(t.data)
h = name.h and high(t.data)
while true: while true:
result = t.data[h] result = t.data[h]
if result == nil: break if result == nil: break
@ -619,7 +597,7 @@ proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
h = ti.h and high(tab.data) h = ti.h and high(tab.data)
start = h start = h
result = tab.data[h] result = tab.data[h]
while (result != nil): while result != nil:
if result.Name.id == ti.name.id: break if result.Name.id == ti.name.id: break
h = nextTry(h, high(tab.data)) h = nextTry(h, high(tab.data))
if h == start: if h == start:
@ -628,6 +606,29 @@ proc NextIdentIter(ti: var TIdentIter, tab: TStrTable): PSym =
result = tab.data[h] result = tab.data[h]
ti.h = nextTry(h, high(tab.data)) 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 = proc InitTabIter(ti: var TTabIter, tab: TStrTable): PSym =
ti.h = 0 # we start by zero ... ti.h = 0 # we start by zero ...
if tab.counter == 0: if tab.counter == 0:

View file

@ -14,12 +14,14 @@ import
type type
TOverloadIterMode* = enum TOverloadIterMode* = enum
oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice oimDone, oimNoQualifier, oimSelfModule, oimOtherModule, oimSymChoice,
oimSymChoiceLocalLookup
TOverloadIter*{.final.} = object TOverloadIter*{.final.} = object
stackPtr*: int stackPtr*: int
it*: TIdentIter it*: TIdentIter
m*: PSym m*: PSym
mode*: TOverloadIterMode mode*: TOverloadIterMode
inSymChoice: TIntSet
proc getSymRepr*(s: PSym): string = proc getSymRepr*(s: PSym): string =
case s.kind case s.kind
@ -27,12 +29,10 @@ proc getSymRepr*(s: PSym): string =
else: result = s.name.s else: result = s.name.s
proc CloseScope*(tab: var TSymTab) = proc CloseScope*(tab: var TSymTab) =
var
it: TTabIter
s: PSym
# check if all symbols have been used and defined: # check if all symbols have been used and defined:
if (tab.tos > len(tab.stack)): InternalError("CloseScope") 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: while s != nil:
if sfForward in s.flags: if sfForward in s.flags:
LocalError(s.info, errImplOfXexpected, getSymRepr(s)) LocalError(s.info, errImplOfXexpected, getSymRepr(s))
@ -40,7 +40,7 @@ proc CloseScope*(tab: var TSymTab) =
(optHints in s.options): # BUGFIX: check options in s! (optHints in s.options): # BUGFIX: check options in s!
if not (s.kind in {skForVar, skParam, skMethod, skUnknown}): if not (s.kind in {skForVar, skParam, skMethod, skUnknown}):
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s)) 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) astalgo.rawCloseScope(tab)
proc AddSym*(t: var TStrTable, n: PSym) = 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) if (result != nil) and (result.kind == skStub): loadStub(result)
proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
result = nil
case n.kind case n.kind
of nkIdent: of nkIdent:
o.stackPtr = c.tab.tos o.stackPtr = c.tab.tos
o.mode = oimNoQualifier o.mode = oimNoQualifier
while (result == nil): while result == nil:
dec(o.stackPtr) dec(o.stackPtr)
if o.stackPtr < 0: break if o.stackPtr < 0: break
result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], n.ident) 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: of nkDotExpr:
o.mode = oimOtherModule o.mode = oimOtherModule
o.m = qualifiedLookUp(c, n.sons[0]) 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 var ident: PIdent = nil
if (n.sons[1].kind == nkIdent): if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident ident = n.sons[1].ident
elif (n.sons[1].kind == nkAccQuoted) and elif n.sons[1].kind == nkAccQuoted and
(n.sons[1].sons[0].kind == nkIdent): n.sons[1].sons[0].kind == nkIdent:
ident = n.sons[1].sons[0].ident ident = n.sons[1].sons[0].ident
if ident != nil: if ident != nil:
if o.m == c.module: if o.m == c.module:
@ -182,9 +181,10 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoice o.mode = oimSymChoice
result = n.sons[0].sym result = n.sons[0].sym
o.stackPtr = 1 o.stackPtr = 1
else: IntSetInit(o.inSymChoice)
nil IntSetIncl(o.inSymChoice, result.id)
if (result != nil) and (result.kind == skStub): loadStub(result) else: nil
if result != nil and result.kind == skStub: loadStub(result)
proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
case o.mode case o.mode
@ -192,10 +192,10 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
result = nil result = nil
of oimNoQualifier: of oimNoQualifier:
if n.kind == nkAccQuoted: if n.kind == nkAccQuoted:
result = nextOverloadIter(o, c, n.sons[0]) # BUGFIX result = nextOverloadIter(o, c, n.sons[0])
elif o.stackPtr >= 0: elif o.stackPtr >= 0:
result = nextIdentIter(o.it, c.tab.stack[o.stackPtr]) result = nextIdentIter(o.it, c.tab.stack[o.stackPtr])
while (result == nil): while result == nil:
dec(o.stackPtr) dec(o.stackPtr)
if o.stackPtr < 0: break if o.stackPtr < 0: break
result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], o.it.name) 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: of oimSymChoice:
if o.stackPtr < sonsLen(n): if o.stackPtr < sonsLen(n):
result = n.sons[o.stackPtr].sym result = n.sons[o.stackPtr].sym
IntSetIncl(o.inSymChoice, result.id)
inc(o.stackPtr) inc(o.stackPtr)
else: else:
result = nil # try 'local' symbols too for Koenig's lookup:
if (result != nil) and (result.kind == skStub): loadStub(result) 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)

View file

@ -64,10 +64,8 @@ proc getIdentNode(n: PNode): PNode =
# if withinBind in flags: result = symChoice(c, n, s) # if withinBind in flags: result = symChoice(c, n, s)
# else: result = semGenericStmtSymbol(c, n, s) # else: result = semGenericStmtSymbol(c, n, s)
proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode = proc semGenericStmt(c: PContext, n: PNode,
var flags: TSemGenericFlags = {}): PNode =
L: int
a: PNode
result = n result = n
if gCmd == cmdIdeTools: suggestStmt(c, n) if gCmd == cmdIdeTools: suggestStmt(c, n)
case n.kind case n.kind
@ -124,14 +122,14 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
openScope(c.tab) openScope(c.tab)
n.sons[0] = semGenericStmt(c, n.sons[0]) n.sons[0] = semGenericStmt(c, n.sons[0])
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
a = n.sons[i] var a = n.sons[i]
checkMinSonsLen(a, 1) 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]) 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]) a.sons[L - 1] = semGenericStmtScope(c, a.sons[L - 1])
closeScope(c.tab) closeScope(c.tab)
of nkForStmt: of nkForStmt:
L = sonsLen(n) var L = sonsLen(n)
openScope(c.tab) openScope(c.tab)
n.sons[L - 2] = semGenericStmt(c, n.sons[L - 2]) 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)) 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) checkMinSonsLen(n, 2)
n.sons[0] = semGenericStmtScope(c, n.sons[0]) n.sons[0] = semGenericStmtScope(c, n.sons[0])
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
a = n.sons[i] var a = n.sons[i]
checkMinSonsLen(a, 1) checkMinSonsLen(a, 1)
L = sonsLen(a) var L = sonsLen(a)
for j in countup(0, L - 2): for j in countup(0, L - 2):
a.sons[j] = semGenericStmt(c, a.sons[j], {withinTypeDesc}) a.sons[j] = semGenericStmt(c, a.sons[j], {withinTypeDesc})
a.sons[L - 1] = semGenericStmtScope(c, a.sons[L - 1]) a.sons[L - 1] = semGenericStmtScope(c, a.sons[L - 1])
of nkVarSection: of nkVarSection:
for i in countup(0, sonsLen(n) - 1): 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 == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a) if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
L = sonsLen(a) var L = sonsLen(a)
a.sons[L - 2] = semGenericStmt(c, a.sons[L - 2], {withinTypeDesc}) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc})
a.sons[L - 1] = semGenericStmt(c, a.sons[L - 1]) a.sons[L-1] = semGenericStmt(c, a.sons[L-1])
for j in countup(0, L - 3): for j in countup(0, L-3):
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c)) addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
of nkGenericParams: of nkGenericParams:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
a = n.sons[i] var a = n.sons[i]
if (a.kind != nkIdentDefs): IllFormedAst(a) if (a.kind != nkIdentDefs): IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
L = sonsLen(a) var L = sonsLen(a)
a.sons[L - 2] = semGenericStmt(c, a.sons[L - 2], {withinTypeDesc}) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc})
# do not perform symbol lookup for default expressions # 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)) addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[j]), c))
of nkConstSection: of nkConstSection:
for i in countup(0, sonsLen(n) - 1): 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 == nkCommentStmt: continue
if (a.kind != nkConstDef): IllFormedAst(a) if (a.kind != nkConstDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
@ -185,13 +183,13 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
a.sons[2] = semGenericStmt(c, a.sons[2]) a.sons[2] = semGenericStmt(c, a.sons[2])
of nkTypeSection: of nkTypeSection:
for i in countup(0, sonsLen(n) - 1): 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 == nkCommentStmt: continue
if (a.kind != nkTypeDef): IllFormedAst(a) if (a.kind != nkTypeDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c)) addDecl(c, newSymS(skUnknown, getIdentNode(a.sons[0]), c))
for i in countup(0, sonsLen(n) - 1): 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 == nkCommentStmt: continue
if (a.kind != nkTypeDef): IllFormedAst(a) if (a.kind != nkTypeDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
@ -207,6 +205,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags: TSemGenericFlags = {}): PNode
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc}) n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
var a: PNode
case n.sons[i].kind case n.sons[i].kind
of nkEnumFieldDef: a = n.sons[i].sons[0] of nkEnumFieldDef: a = n.sons[i].sons[0]
of nkIdent: a = n.sons[i] 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: if n.sons[0].kind != nkEmpty:
n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc}) n.sons[0] = semGenericStmt(c, n.sons[0], {withinTypeDesc})
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
a = n.sons[i] var a = n.sons[i]
if (a.kind != nkIdentDefs): IllFormedAst(a) if (a.kind != nkIdentDefs): IllFormedAst(a)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3)
L = sonsLen(a) var L = sonsLen(a)
a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc}) a.sons[L-2] = semGenericStmt(c, a.sons[L-2], {withinTypeDesc})
a.sons[L-1] = semGenericStmt(c, a.sons[L-1]) a.sons[L-1] = semGenericStmt(c, a.sons[L-1])
for j in countup(0, L-3): for j in countup(0, L-3):

View file

@ -85,7 +85,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
of nkIdent: s = lookUp(c, n.sons[0]) of nkIdent: s = lookUp(c, n.sons[0])
of nkSym: s = n.sons[0].sym of nkSym: s = n.sons[0].sym
else: illFormedAst(n) 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) var x = newSymNode(s)
x.info = n.info x.info = n.info
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
@ -266,6 +266,13 @@ proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode =
elif not sameType(result.typ, typ): elif not sameType(result.typ, typ):
changeType(result, 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 = proc semVar(c: PContext, n: PNode): PNode =
var b: PNode var b: PNode
result = copyNode(n) 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 - 2] = ast.emptyNode # no type desc
b.sons[length - 1] = def b.sons[length - 1] = def
addSon(result, b) addSon(result, b)
for j in countup(0, length - 3): for j in countup(0, length-3):
var v: PSym var v = semIdentDef(c, a.sons[j], skVar)
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], {})
if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface) if v.flags * {sfStar, sfMinus} != {}: incl(v.flags, sfInInterface)
addInterfaceDecl(c, v) addInterfaceDecl(c, v)
if a.kind != nkVarTuple: if a.kind != nkVarTuple:
@ -332,12 +334,7 @@ proc semConst(c: PContext, n: PNode): PNode =
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): IllFormedAst(a) if (a.kind != nkConstDef): IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
var v: PSym var v = semIdentDef(c, a.sons[0], skConst)
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 typ: PType = nil var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
var def = semAndEvalConstExpr(c, a.sons[2]) 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 == nkCommentStmt: continue
if a.kind != nkTypeDef: IllFormedAst(a) if a.kind != nkTypeDef: IllFormedAst(a)
checkSonsLen(a, 3) checkSonsLen(a, 3)
var s: PSym var s = semIdentDef(c, a.sons[0], skType)
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], {})
if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface) if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface)
s.typ = newTypeS(tyForward, c) s.typ = newTypeS(tyForward, c)
s.typ.sym = s # process pragmas: s.typ.sym = s # process pragmas:
@ -547,7 +539,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
checkSonsLen(a, 3) checkSonsLen(a, 3)
if (a.sons[0].kind != nkSym): IllFormedAst(a) if (a.sons[0].kind != nkSym): IllFormedAst(a)
var s = a.sons[0].sym 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) GlobalError(a.info, errImplOfXexpected, s.name.s)
if s.magic != mNone: processMagicType(c, s) if s.magic != mNone: processMagicType(c, s)
if a.sons[1].kind != nkEmpty: 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, proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
validPragmas: TSpecialWords): PNode = validPragmas: TSpecialWords): PNode =
var var
s, proto: PSym proto: PSym
gp: PNode gp: PNode
result = n result = n
checkSonsLen(n, codePos + 1) checkSonsLen(n, codePos + 1)
if c.p.owner.kind == skModule: var s = semIdentDef(c, n.sons[0], kind)
s = semIdentVis(c, kind, n.sons[0], {sfStar})
incl(s.flags, sfGlobal)
else:
s = semIdentVis(c, kind, n.sons[0], {})
n.sons[namePos] = newSymNode(s) n.sons[namePos] = newSymNode(s)
var oldP = c.p # restore later var oldP = c.p # restore later
if sfStar in s.flags: incl(s.flags, sfInInterface) if sfStar in s.flags: incl(s.flags, sfInInterface)

View file

@ -9,8 +9,8 @@ type
TMyObj = object TMyObj = object
x, y: int x, y: int
proc `$`*(a: TMyObj): bool = proc `$`*(a: TMyObj): string =
result = "x: " & a.x & " y: " & a.y result = "x: " & $a.x & " y: " & $a.y
var a: TMyObj var a: TMyObj
echo toString(a) echo toString(a)