Koenig's lookup implementation
This commit is contained in:
parent
4741e8f9a1
commit
94f4256811
5 changed files with 137 additions and 131 deletions
119
rod/astalgo.nim
119
rod/astalgo.nim
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue