intsets are now a proper module and part of the stdlib
This commit is contained in:
parent
ca637c019c
commit
ade67f1abc
25 changed files with 297 additions and 286 deletions
144
compiler/ast.nim
144
compiler/ast.nim
|
|
@ -10,7 +10,7 @@
|
||||||
# abstract syntax tree + symbol table
|
# abstract syntax tree + symbol table
|
||||||
|
|
||||||
import
|
import
|
||||||
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists
|
msgs, hashes, nversion, options, strutils, crc, ropes, idents, lists, intsets
|
||||||
|
|
||||||
const
|
const
|
||||||
ImportTablePos* = 0
|
ImportTablePos* = 0
|
||||||
|
|
@ -620,39 +620,6 @@ proc leValue*(a, b: PNode): bool
|
||||||
# a <= b? a, b are literals
|
# a <= b? a, b are literals
|
||||||
proc ValueToString*(a: PNode): string
|
proc ValueToString*(a: PNode): string
|
||||||
|
|
||||||
# ------------- efficient integer sets -------------------------------------
|
|
||||||
type
|
|
||||||
TBitScalar* = int
|
|
||||||
|
|
||||||
const
|
|
||||||
InitIntSetSize* = 8 # must be a power of two!
|
|
||||||
TrunkShift* = 9
|
|
||||||
BitsPerTrunk* = 1 shl TrunkShift # needs to be a power of 2 and
|
|
||||||
# divisible by 64
|
|
||||||
TrunkMask* = BitsPerTrunk - 1
|
|
||||||
IntsPerTrunk* = BitsPerTrunk div (sizeof(TBitScalar) * 8)
|
|
||||||
IntShift* = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width
|
|
||||||
IntMask* = 1 shl IntShift - 1
|
|
||||||
|
|
||||||
type
|
|
||||||
PTrunk* = ref TTrunk
|
|
||||||
TTrunk*{.final.} = object
|
|
||||||
next*: PTrunk # all nodes are connected with this pointer
|
|
||||||
key*: int # start address at bit 0
|
|
||||||
bits*: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector
|
|
||||||
|
|
||||||
TTrunkSeq* = seq[PTrunk]
|
|
||||||
TIntSet*{.final.} = object
|
|
||||||
counter*, max*: int
|
|
||||||
head*: PTrunk
|
|
||||||
data*: TTrunkSeq
|
|
||||||
|
|
||||||
|
|
||||||
proc IntSetContains*(s: TIntSet, key: int): bool
|
|
||||||
proc IntSetIncl*(s: var TIntSet, key: int)
|
|
||||||
proc IntSetExcl*(s: var TIntSet, key: int)
|
|
||||||
proc IntSetInit*(s: var TIntSet)
|
|
||||||
proc IntSetContainsOrIncl*(s: var TIntSet, key: int): bool
|
|
||||||
const
|
const
|
||||||
debugIds* = false
|
debugIds* = false
|
||||||
|
|
||||||
|
|
@ -663,7 +630,7 @@ var usedIds: TIntSet
|
||||||
|
|
||||||
proc registerID(id: PIdObj) =
|
proc registerID(id: PIdObj) =
|
||||||
if debugIDs:
|
if debugIDs:
|
||||||
if (id.id == - 1) or IntSetContainsOrIncl(usedIds, id.id):
|
if (id.id == - 1) or ContainsOrIncl(usedIds, id.id):
|
||||||
InternalError("ID already used: " & $(id.id))
|
InternalError("ID already used: " & $(id.id))
|
||||||
|
|
||||||
proc getID(): int =
|
proc getID(): int =
|
||||||
|
|
@ -1036,109 +1003,4 @@ proc getStrOrChar*(a: PNode): string =
|
||||||
internalError(a.info, "getStrOrChar")
|
internalError(a.info, "getStrOrChar")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc mustRehash(length, counter: int): bool {.inline.} =
|
if debugIDs: usedIds = InitIntSet()
|
||||||
assert(length > counter)
|
|
||||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
|
||||||
|
|
||||||
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
|
||||||
result = ((5 * h) + 1) and maxHash
|
|
||||||
# For any initial h in range(maxHash), repeating that maxHash times
|
|
||||||
# generates each int in range(maxHash) exactly once (see any text on
|
|
||||||
# random-number generation for proof).
|
|
||||||
|
|
||||||
proc IntSetInit(s: var TIntSet) =
|
|
||||||
newSeq(s.data, InitIntSetSize)
|
|
||||||
s.max = InitIntSetSize - 1
|
|
||||||
s.counter = 0
|
|
||||||
s.head = nil
|
|
||||||
|
|
||||||
proc IntSetGet(t: TIntSet, key: int): PTrunk =
|
|
||||||
var h = key and t.max
|
|
||||||
while t.data[h] != nil:
|
|
||||||
if t.data[h].key == key:
|
|
||||||
return t.data[h]
|
|
||||||
h = nextTry(h, t.max)
|
|
||||||
result = nil
|
|
||||||
|
|
||||||
proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
|
|
||||||
var h = desc.key and t.max
|
|
||||||
while data[h] != nil:
|
|
||||||
assert(data[h] != desc)
|
|
||||||
h = nextTry(h, t.max)
|
|
||||||
assert(data[h] == nil)
|
|
||||||
data[h] = desc
|
|
||||||
|
|
||||||
proc IntSetEnlarge(t: var TIntSet) =
|
|
||||||
var
|
|
||||||
n: TTrunkSeq
|
|
||||||
oldMax: int
|
|
||||||
oldMax = t.max
|
|
||||||
t.max = ((t.max + 1) * 2) - 1
|
|
||||||
newSeq(n, t.max + 1)
|
|
||||||
for i in countup(0, oldmax):
|
|
||||||
if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i])
|
|
||||||
swap(t.data, n)
|
|
||||||
|
|
||||||
proc IntSetPut(t: var TIntSet, key: int): PTrunk =
|
|
||||||
var h = key and t.max
|
|
||||||
while t.data[h] != nil:
|
|
||||||
if t.data[h].key == key:
|
|
||||||
return t.data[h]
|
|
||||||
h = nextTry(h, t.max)
|
|
||||||
if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t)
|
|
||||||
inc(t.counter)
|
|
||||||
h = key and t.max
|
|
||||||
while t.data[h] != nil: h = nextTry(h, t.max)
|
|
||||||
assert(t.data[h] == nil)
|
|
||||||
new(result)
|
|
||||||
result.next = t.head
|
|
||||||
result.key = key
|
|
||||||
t.head = result
|
|
||||||
t.data[h] = result
|
|
||||||
|
|
||||||
proc IntSetContains(s: TIntSet, key: int): bool =
|
|
||||||
var
|
|
||||||
u: TBitScalar
|
|
||||||
t: PTrunk
|
|
||||||
t = IntSetGet(s, `shr`(key, TrunkShift))
|
|
||||||
if t != nil:
|
|
||||||
u = key and TrunkMask
|
|
||||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
|
||||||
else:
|
|
||||||
result = false
|
|
||||||
|
|
||||||
proc IntSetIncl(s: var TIntSet, key: int) =
|
|
||||||
var
|
|
||||||
u: TBitScalar
|
|
||||||
t: PTrunk
|
|
||||||
t = IntSetPut(s, `shr`(key, TrunkShift))
|
|
||||||
u = key and TrunkMask
|
|
||||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
|
||||||
`shl`(1, u and IntMask)
|
|
||||||
|
|
||||||
proc IntSetExcl(s: var TIntSet, key: int) =
|
|
||||||
var
|
|
||||||
u: TBitScalar
|
|
||||||
t: PTrunk
|
|
||||||
t = IntSetGet(s, `shr`(key, TrunkShift))
|
|
||||||
if t != nil:
|
|
||||||
u = key and TrunkMask
|
|
||||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
|
|
||||||
not `shl`(1, u and IntMask)
|
|
||||||
|
|
||||||
proc IntSetContainsOrIncl(s: var TIntSet, key: int): bool =
|
|
||||||
var
|
|
||||||
u: TBitScalar
|
|
||||||
t: PTrunk
|
|
||||||
t = IntSetGet(s, `shr`(key, TrunkShift))
|
|
||||||
if t != nil:
|
|
||||||
u = key and TrunkMask
|
|
||||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
|
||||||
if not result:
|
|
||||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
|
||||||
`shl`(1, u and IntMask)
|
|
||||||
else:
|
|
||||||
IntSetIncl(s, key)
|
|
||||||
result = false
|
|
||||||
|
|
||||||
if debugIDs: IntSetInit(usedIds)
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
# the data structures here are used in various places of the compiler.
|
# the data structures here are used in various places of the compiler.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, hashes, strutils, options, msgs, ropes, idents, rodutils
|
ast, hashes, intsets, strutils, options, msgs, ropes, idents, rodutils
|
||||||
|
|
||||||
proc hashNode*(p: PObject): THash
|
proc hashNode*(p: PObject): THash
|
||||||
proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
|
proc treeToYaml*(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope
|
||||||
|
|
@ -263,7 +263,7 @@ proc symToYamlAux(n: PSym, marker: var TIntSet, indent: int,
|
||||||
maxRecDepth: int): PRope =
|
maxRecDepth: int): PRope =
|
||||||
if n == nil:
|
if n == nil:
|
||||||
result = toRope("null")
|
result = toRope("null")
|
||||||
elif IntSetContainsOrIncl(marker, n.id):
|
elif ContainsOrIncl(marker, n.id):
|
||||||
result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope(
|
result = ropef("\"$1 @$2\"", [toRope(n.name.s), toRope(
|
||||||
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
|
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
|
||||||
else:
|
else:
|
||||||
|
|
@ -284,7 +284,7 @@ proc typeToYamlAux(n: PType, marker: var TIntSet, indent: int,
|
||||||
maxRecDepth: int): PRope =
|
maxRecDepth: int): PRope =
|
||||||
if n == nil:
|
if n == nil:
|
||||||
result = toRope("null")
|
result = toRope("null")
|
||||||
elif intSetContainsOrIncl(marker, n.id):
|
elif ContainsOrIncl(marker, n.id):
|
||||||
result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope(
|
result = ropef("\"$1 @$2\"", [toRope($n.kind), toRope(
|
||||||
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
|
strutils.toHex(cast[TAddress](n), sizeof(n) * 2))])
|
||||||
else:
|
else:
|
||||||
|
|
@ -346,18 +346,15 @@ proc treeToYamlAux(n: PNode, marker: var TIntSet, indent: int,
|
||||||
appf(result, "$n$1}", [spaces(indent)])
|
appf(result, "$n$1}", [spaces(indent)])
|
||||||
|
|
||||||
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = treeToYamlAux(n, marker, indent, maxRecDepth)
|
result = treeToYamlAux(n, marker, indent, maxRecDepth)
|
||||||
|
|
||||||
proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
proc typeToYaml(n: PType, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = typeToYamlAux(n, marker, indent, maxRecDepth)
|
result = typeToYamlAux(n, marker, indent, maxRecDepth)
|
||||||
|
|
||||||
proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
proc symToYaml(n: PSym, indent: int = 0, maxRecDepth: int = - 1): PRope =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = symToYamlAux(n, marker, indent, maxRecDepth)
|
result = symToYamlAux(n, marker, indent, maxRecDepth)
|
||||||
|
|
||||||
proc debugType(n: PType): PRope =
|
proc debugType(n: PType): PRope =
|
||||||
|
|
@ -612,15 +609,15 @@ proc NextIdentExcluding*(ti: var TIdentIter, tab: TStrTable,
|
||||||
var start = h
|
var start = h
|
||||||
result = tab.data[h]
|
result = tab.data[h]
|
||||||
while result != nil:
|
while result != nil:
|
||||||
if result.Name.id == ti.name.id and
|
if result.Name.id == ti.name.id and not Contains(excluding, result.id):
|
||||||
not IntSetContains(excluding, result.id): break
|
break
|
||||||
h = nextTry(h, high(tab.data))
|
h = nextTry(h, high(tab.data))
|
||||||
if h == start:
|
if h == start:
|
||||||
result = nil
|
result = nil
|
||||||
break
|
break
|
||||||
result = tab.data[h]
|
result = tab.data[h]
|
||||||
ti.h = nextTry(h, high(tab.data))
|
ti.h = nextTry(h, high(tab.data))
|
||||||
if result != nil and IntSetContains(excluding, result.id): result = nil
|
if result != nil and Contains(excluding, result.id): result = nil
|
||||||
|
|
||||||
proc FirstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
|
proc FirstIdentExcluding*(ti: var TIdentIter, tab: TStrTable, s: PIdent,
|
||||||
excluding: TIntSet): PSym =
|
excluding: TIntSet): PSym =
|
||||||
|
|
|
||||||
|
|
@ -709,7 +709,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
discard genTypeInfo(p.module, t)
|
discard genTypeInfo(p.module, t)
|
||||||
var L = lengthOrd(field.typ)
|
var L = lengthOrd(field.typ)
|
||||||
if not IntSetContainsOrIncl(p.module.declaredThings, field.id):
|
if not ContainsOrIncl(p.module.declaredThings, field.id):
|
||||||
appcg(p.module, cfsVars, "extern $1",
|
appcg(p.module, cfsVars, "extern $1",
|
||||||
discriminatorTableDecl(p.module, t, field))
|
discriminatorTableDecl(p.module, t, field))
|
||||||
appcg(p, cpsStmts,
|
appcg(p, cpsStmts,
|
||||||
|
|
|
||||||
|
|
@ -387,7 +387,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
||||||
if t.sym != nil: useHeader(m, t.sym)
|
if t.sym != nil: useHeader(m, t.sym)
|
||||||
result = getTypePre(m, t)
|
result = getTypePre(m, t)
|
||||||
if result != nil: return
|
if result != nil: return
|
||||||
if IntSetContainsOrIncl(check, t.id):
|
if ContainsOrIncl(check, t.id):
|
||||||
InternalError("cannot generate C type for: " & typeToString(typ))
|
InternalError("cannot generate C type for: " & typeToString(typ))
|
||||||
# XXX: this BUG is hard to fix -> we need to introduce helper structs,
|
# XXX: this BUG is hard to fix -> we need to introduce helper structs,
|
||||||
# but determining when this needs to be done is hard. We should split
|
# but determining when this needs to be done is hard. We should split
|
||||||
|
|
@ -490,8 +490,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
proc getTypeDesc(m: BModule, typ: PType): PRope =
|
proc getTypeDesc(m: BModule, typ: PType): PRope =
|
||||||
var check: TIntSet
|
var check = initIntSet()
|
||||||
IntSetInit(check)
|
|
||||||
result = getTypeDescAux(m, typ, check)
|
result = getTypeDescAux(m, typ, check)
|
||||||
|
|
||||||
proc getTypeDesc(m: BModule, magic: string): PRope =
|
proc getTypeDesc(m: BModule, magic: string): PRope =
|
||||||
|
|
@ -511,10 +510,9 @@ proc finishTypeDescriptions(m: BModule) =
|
||||||
proc genProcHeader(m: BModule, prc: PSym): PRope =
|
proc genProcHeader(m: BModule, prc: PSym): PRope =
|
||||||
var
|
var
|
||||||
rettype, params: PRope
|
rettype, params: PRope
|
||||||
check: TIntSet
|
|
||||||
# using static is needed for inline procs
|
# using static is needed for inline procs
|
||||||
if (prc.typ.callConv == ccInline): result = toRope"static "
|
if (prc.typ.callConv == ccInline): result = toRope"static "
|
||||||
IntSetInit(check)
|
var check = initIntSet()
|
||||||
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown)
|
fillLoc(prc.loc, locProc, prc.typ, mangleName(prc), OnUnknown)
|
||||||
genProcParams(m, prc.typ, rettype, params, check)
|
genProcParams(m, prc.typ, rettype, params, check)
|
||||||
appf(result, "$1($2, $3)$4",
|
appf(result, "$1($2, $3)$4",
|
||||||
|
|
@ -736,7 +734,7 @@ proc genTypeInfo(m: BModule, typ: PType): PRope =
|
||||||
else:
|
else:
|
||||||
dataGenerated = true
|
dataGenerated = true
|
||||||
result = ropef("NTI$1", [toRope(id)])
|
result = ropef("NTI$1", [toRope(id)])
|
||||||
if not IntSetContainsOrIncl(m.typeInfoMarker, id):
|
if not ContainsOrIncl(m.typeInfoMarker, id):
|
||||||
# declare type information structures:
|
# declare type information structures:
|
||||||
discard cgsym(m, "TNimType")
|
discard cgsym(m, "TNimType")
|
||||||
discard cgsym(m, "TNimNode")
|
discard cgsym(m, "TNimNode")
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
||||||
options,
|
options, intsets,
|
||||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||||
rodutils
|
rodutils
|
||||||
|
|
@ -690,12 +690,12 @@ proc genProcPrototype(m: BModule, sym: PSym) =
|
||||||
if lfNoDecl in sym.loc.Flags: return
|
if lfNoDecl in sym.loc.Flags: return
|
||||||
if lfDynamicLib in sym.loc.Flags:
|
if lfDynamicLib in sym.loc.Flags:
|
||||||
if sym.owner.id != m.module.id and
|
if sym.owner.id != m.module.id and
|
||||||
not intSetContainsOrIncl(m.declaredThings, sym.id):
|
not ContainsOrIncl(m.declaredThings, sym.id):
|
||||||
appff(m.s[cfsVars], "extern $1 $2;$n",
|
appff(m.s[cfsVars], "extern $1 $2;$n",
|
||||||
"@$2 = linkonce global $1 zeroinitializer$n",
|
"@$2 = linkonce global $1 zeroinitializer$n",
|
||||||
[getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
|
[getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
|
||||||
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
|
if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
|
||||||
elif not IntSetContainsOrIncl(m.declaredProtos, sym.id):
|
elif not ContainsOrIncl(m.declaredProtos, sym.id):
|
||||||
appf(m.s[cfsProcHeaders], "$1;$n", [genProcHeader(m, sym)])
|
appf(m.s[cfsProcHeaders], "$1;$n", [genProcHeader(m, sym)])
|
||||||
|
|
||||||
proc genProcNoForward(m: BModule, prc: PSym) =
|
proc genProcNoForward(m: BModule, prc: PSym) =
|
||||||
|
|
@ -707,12 +707,12 @@ proc genProcNoForward(m: BModule, prc: PSym) =
|
||||||
# We add inline procs to the calling module to enable C based inlining.
|
# We add inline procs to the calling module to enable C based inlining.
|
||||||
# This also means that a check with ``gGeneratedSyms`` is wrong, we need
|
# This also means that a check with ``gGeneratedSyms`` is wrong, we need
|
||||||
# a check for ``m.declaredThings``.
|
# a check for ``m.declaredThings``.
|
||||||
if not intSetContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
|
if not ContainsOrIncl(m.declaredThings, prc.id): genProcAux(m, prc)
|
||||||
elif lfDynamicLib in prc.loc.flags:
|
elif lfDynamicLib in prc.loc.flags:
|
||||||
if not IntSetContainsOrIncl(gGeneratedSyms, prc.id):
|
if not ContainsOrIncl(gGeneratedSyms, prc.id):
|
||||||
SymInDynamicLib(findPendingModule(m, prc), prc)
|
SymInDynamicLib(findPendingModule(m, prc), prc)
|
||||||
elif not (sfImportc in prc.flags):
|
elif not (sfImportc in prc.flags):
|
||||||
if not IntSetContainsOrIncl(gGeneratedSyms, prc.id):
|
if not ContainsOrIncl(gGeneratedSyms, prc.id):
|
||||||
genProcAux(findPendingModule(m, prc), prc)
|
genProcAux(findPendingModule(m, prc), prc)
|
||||||
|
|
||||||
proc genProc(m: BModule, prc: PSym) =
|
proc genProc(m: BModule, prc: PSym) =
|
||||||
|
|
@ -726,7 +726,7 @@ proc genVarPrototype(m: BModule, sym: PSym) =
|
||||||
useHeader(m, sym)
|
useHeader(m, sym)
|
||||||
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
|
fillLoc(sym.loc, locGlobalVar, sym.typ, mangleName(sym), OnHeap)
|
||||||
if (lfNoDecl in sym.loc.Flags) or
|
if (lfNoDecl in sym.loc.Flags) or
|
||||||
intSetContainsOrIncl(m.declaredThings, sym.id):
|
ContainsOrIncl(m.declaredThings, sym.id):
|
||||||
return
|
return
|
||||||
if sym.owner.id != m.module.id:
|
if sym.owner.id != m.module.id:
|
||||||
# else we already have the symbol generated!
|
# else we already have the symbol generated!
|
||||||
|
|
@ -748,7 +748,7 @@ proc genConstPrototype(m: BModule, sym: PSym) =
|
||||||
if sym.loc.k == locNone:
|
if sym.loc.k == locNone:
|
||||||
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
|
fillLoc(sym.loc, locData, sym.typ, mangleName(sym), OnUnknown)
|
||||||
if (lfNoDecl in sym.loc.Flags) or
|
if (lfNoDecl in sym.loc.Flags) or
|
||||||
intSetContainsOrIncl(m.declaredThings, sym.id):
|
ContainsOrIncl(m.declaredThings, sym.id):
|
||||||
return
|
return
|
||||||
if sym.owner.id != m.module.id:
|
if sym.owner.id != m.module.id:
|
||||||
# else we already have the symbol generated!
|
# else we already have the symbol generated!
|
||||||
|
|
@ -903,14 +903,14 @@ proc genModule(m: BModule, cfilenoext: string): PRope =
|
||||||
proc rawNewModule(module: PSym, filename: string): BModule =
|
proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
new(result)
|
new(result)
|
||||||
InitLinkedList(result.headerFiles)
|
InitLinkedList(result.headerFiles)
|
||||||
intSetInit(result.declaredThings)
|
result.declaredThings = initIntSet()
|
||||||
intSetInit(result.declaredProtos)
|
result.declaredProtos = initIntSet()
|
||||||
result.cfilename = filename
|
result.cfilename = filename
|
||||||
result.filename = filename
|
result.filename = filename
|
||||||
initIdTable(result.typeCache)
|
initIdTable(result.typeCache)
|
||||||
initIdTable(result.forwTypeCache)
|
initIdTable(result.forwTypeCache)
|
||||||
result.module = module
|
result.module = module
|
||||||
intSetInit(result.typeInfoMarker)
|
result.typeInfoMarker = initIntSet()
|
||||||
result.initProc = newProc(nil, result)
|
result.initProc = newProc(nil, result)
|
||||||
result.initProc.options = gOptions
|
result.initProc.options = gOptions
|
||||||
initNodeTable(result.dataCache)
|
initNodeTable(result.dataCache)
|
||||||
|
|
@ -1037,4 +1037,4 @@ proc cgenPass(): TPass =
|
||||||
result.close = myClose
|
result.close = myClose
|
||||||
|
|
||||||
InitIiTable(gToTypeInfoId)
|
InitIiTable(gToTypeInfoId)
|
||||||
IntSetInit(gGeneratedSyms)
|
gGeneratedSyms = initIntSet()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
## This module implements code generation for multi methods.
|
## This module implements code generation for multi methods.
|
||||||
|
|
||||||
import
|
import
|
||||||
options, ast, astalgo, msgs, idents, renderer, types, magicsys
|
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys
|
||||||
|
|
||||||
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
|
||||||
var dest = skipTypes(d, abstractPtrs)
|
var dest = skipTypes(d, abstractPtrs)
|
||||||
|
|
@ -95,7 +95,7 @@ proc relevantCol(methods: TSymSeq, col: int): bool =
|
||||||
proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
|
proc cmpSignatures(a, b: PSym, relevantCols: TIntSet): int =
|
||||||
result = 0
|
result = 0
|
||||||
for col in countup(1, sonsLen(a.typ) - 1):
|
for col in countup(1, sonsLen(a.typ) - 1):
|
||||||
if intSetContains(relevantCols, col):
|
if Contains(relevantCols, col):
|
||||||
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
var aa = skipTypes(a.typ.sons[col], skipPtrs)
|
||||||
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
var bb = skipTypes(b.typ.sons[col], skipPtrs)
|
||||||
var d = inheritanceDiff(aa, bb)
|
var d = inheritanceDiff(aa, bb)
|
||||||
|
|
@ -132,7 +132,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
|
||||||
var curr = methods[meth] # generate condition:
|
var curr = methods[meth] # generate condition:
|
||||||
var cond: PNode = nil
|
var cond: PNode = nil
|
||||||
for col in countup(1, paramLen - 1):
|
for col in countup(1, paramLen - 1):
|
||||||
if IntSetContains(relevantCols, col):
|
if Contains(relevantCols, col):
|
||||||
var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
|
||||||
addSon(isn, newSymNode(iss))
|
addSon(isn, newSymNode(iss))
|
||||||
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
addSon(isn, newSymNode(base.typ.n.sons[col].sym))
|
||||||
|
|
@ -169,12 +169,11 @@ proc genDispatcher(methods: TSymSeq, relevantCols: TIntSet): PSym =
|
||||||
result.ast.sons[codePos] = disp
|
result.ast.sons[codePos] = disp
|
||||||
|
|
||||||
proc generateMethodDispatchers*(): PNode =
|
proc generateMethodDispatchers*(): PNode =
|
||||||
var relevantCols: TIntSet
|
|
||||||
result = newNode(nkStmtList)
|
result = newNode(nkStmtList)
|
||||||
for bucket in countup(0, len(gMethods) - 1):
|
for bucket in countup(0, len(gMethods) - 1):
|
||||||
IntSetInit(relevantCols)
|
var relevantCols = initIntSet()
|
||||||
for col in countup(1, sonsLen(gMethods[bucket][0].typ) - 1):
|
for col in countup(1, sonsLen(gMethods[bucket][0].typ) - 1):
|
||||||
if relevantCol(gMethods[bucket], col): IntSetIncl(relevantCols, col)
|
if relevantCol(gMethods[bucket], col): Incl(relevantCols, col)
|
||||||
sortBucket(gMethods[bucket], relevantCols)
|
sortBucket(gMethods[bucket], relevantCols)
|
||||||
addSon(result, newSymNode(genDispatcher(gMethods[bucket], relevantCols)))
|
addSon(result, newSymNode(genDispatcher(gMethods[bucket], relevantCols)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
import
|
import
|
||||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
||||||
options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
|
options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
|
||||||
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils
|
times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
|
||||||
|
intsets
|
||||||
|
|
||||||
proc ecmasgenPass*(): TPass
|
proc ecmasgenPass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
@ -67,7 +68,7 @@ type
|
||||||
|
|
||||||
proc newGlobals(): PGlobals =
|
proc newGlobals(): PGlobals =
|
||||||
new(result)
|
new(result)
|
||||||
IntSetInit(result.typeInfoGenerated)
|
result.typeInfoGenerated = initIntSet()
|
||||||
|
|
||||||
proc initCompRes(r: var TCompRes) =
|
proc initCompRes(r: var TCompRes) =
|
||||||
r.com = nil
|
r.com = nil
|
||||||
|
|
@ -228,7 +229,7 @@ proc genTypeInfo(p: var TProc, typ: PType): PRope =
|
||||||
var t = typ
|
var t = typ
|
||||||
if t.kind == tyGenericInst: t = lastSon(t)
|
if t.kind == tyGenericInst: t = lastSon(t)
|
||||||
result = ropef("NTI$1", [toRope(t.id)])
|
result = ropef("NTI$1", [toRope(t.id)])
|
||||||
if IntSetContainsOrIncl(p.globals.TypeInfoGenerated, t.id): return
|
if ContainsOrIncl(p.globals.TypeInfoGenerated, t.id): return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
result = genTypeInfo(p, typ.sons[0])
|
result = genTypeInfo(p, typ.sons[0])
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@
|
||||||
# This module implements the symbol importing mechanism.
|
# This module implements the symbol importing mechanism.
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups, semdata,
|
intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups,
|
||||||
passes
|
semdata, passes
|
||||||
|
|
||||||
proc evalImport*(c: PContext, n: PNode): PNode
|
proc evalImport*(c: PContext, n: PNode): PNode
|
||||||
proc evalFrom*(c: PContext, n: PNode): PNode
|
proc evalFrom*(c: PContext, n: PNode): PNode
|
||||||
|
|
@ -45,8 +45,8 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||||
if (check != nil) and (check.id != copy.id):
|
if (check != nil) and (check.id != copy.id):
|
||||||
if not (s.kind in OverloadableSyms):
|
if not (s.kind in OverloadableSyms):
|
||||||
# s and check need to be qualified:
|
# s and check need to be qualified:
|
||||||
IntSetIncl(c.AmbiguousSymbols, copy.id)
|
Incl(c.AmbiguousSymbols, copy.id)
|
||||||
IntSetIncl(c.AmbiguousSymbols, check.id)
|
Incl(c.AmbiguousSymbols, check.id)
|
||||||
StrTableAdd(c.tab.stack[importTablePos], copy)
|
StrTableAdd(c.tab.stack[importTablePos], copy)
|
||||||
if s.kind == skType:
|
if s.kind == skType:
|
||||||
var etyp = s.typ
|
var etyp = s.typ
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
# This module implements lookup helpers.
|
# This module implements lookup helpers.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, idents, semdata, types, msgs, options, rodread, renderer
|
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
|
||||||
|
renderer
|
||||||
|
|
||||||
proc considerAcc*(n: PNode): PIdent =
|
proc considerAcc*(n: PNode): PIdent =
|
||||||
case n.kind
|
case n.kind
|
||||||
|
|
@ -115,7 +116,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
|
||||||
result = SymtabGet(c.Tab, ident)
|
result = SymtabGet(c.Tab, ident)
|
||||||
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s)
|
if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s)
|
||||||
else: InternalError(n.info, "lookUp")
|
else: InternalError(n.info, "lookUp")
|
||||||
if IntSetContains(c.AmbiguousSymbols, result.id):
|
if Contains(c.AmbiguousSymbols, result.id):
|
||||||
LocalError(n.info, errUseQualifier, result.name.s)
|
LocalError(n.info, errUseQualifier, result.name.s)
|
||||||
if result.kind == skStub: loadStub(result)
|
if result.kind == skStub: loadStub(result)
|
||||||
|
|
||||||
|
|
@ -131,12 +132,11 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||||
if result == nil and checkUndeclared in flags:
|
if result == nil and checkUndeclared in flags:
|
||||||
GlobalError(n.info, errUndeclaredIdentifier, ident.s)
|
GlobalError(n.info, errUndeclaredIdentifier, ident.s)
|
||||||
elif checkAmbiguity in flags and result != nil and
|
elif checkAmbiguity in flags and result != nil and
|
||||||
IntSetContains(c.AmbiguousSymbols, result.id):
|
Contains(c.AmbiguousSymbols, result.id):
|
||||||
LocalError(n.info, errUseQualifier, ident.s)
|
LocalError(n.info, errUseQualifier, ident.s)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result = n.sym
|
result = n.sym
|
||||||
if checkAmbiguity in flags and IntSetContains(c.AmbiguousSymbols,
|
if checkAmbiguity in flags and Contains(c.AmbiguousSymbols, result.id):
|
||||||
result.id):
|
|
||||||
LocalError(n.info, errUseQualifier, n.sym.name.s)
|
LocalError(n.info, errUseQualifier, n.sym.name.s)
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -197,8 +197,8 @@ 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
|
||||||
IntSetInit(o.inSymChoice)
|
o.inSymChoice = initIntSet()
|
||||||
IntSetIncl(o.inSymChoice, result.id)
|
Incl(o.inSymChoice, result.id)
|
||||||
else: nil
|
else: nil
|
||||||
if result != nil and result.kind == skStub: loadStub(result)
|
if result != nil and result.kind == skStub: loadStub(result)
|
||||||
|
|
||||||
|
|
@ -223,7 +223,7 @@ 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)
|
Incl(o.inSymChoice, result.id)
|
||||||
inc(o.stackPtr)
|
inc(o.stackPtr)
|
||||||
else:
|
else:
|
||||||
# try 'local' symbols too for Koenig's lookup:
|
# try 'local' symbols too for Koenig's lookup:
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@
|
||||||
# writing of rod files is split into two different modules.
|
# writing of rod files is split into two different modules.
|
||||||
|
|
||||||
import
|
import
|
||||||
os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms,
|
intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform,
|
||||||
ropes, idents, crc, rodread, passes, importer
|
condsyms, ropes, idents, crc, rodread, passes, importer
|
||||||
|
|
||||||
proc rodwritePass*(): TPass
|
proc rodwritePass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
@ -446,4 +446,4 @@ proc rodwritePass(): TPass =
|
||||||
result.close = myClose
|
result.close = myClose
|
||||||
result.process = process
|
result.process = process
|
||||||
|
|
||||||
IntSetInit(debugWritten)
|
debugWritten= initIntSet()
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import
|
||||||
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
|
wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
|
||||||
magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer,
|
magicsys, parser, nversion, nimsets, semdata, evals, semfold, importer,
|
||||||
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
|
procfind, lookups, rodread, pragmas, passes, semtypinst, sigmatch, suggest,
|
||||||
semthreads
|
semthreads, intsets
|
||||||
|
|
||||||
proc semPass*(): TPass
|
proc semPass*(): TPass
|
||||||
# implementation
|
# implementation
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@
|
||||||
# This module contains the data structures for the semantic checking phase.
|
# This module contains the data structures for the semantic checking phase.
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, lists, options, lexer, ast, astalgo, trees, treetab, wordrecg,
|
strutils, lists, intsets, options, lexer, ast, astalgo, trees, treetab,
|
||||||
|
wordrecg,
|
||||||
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
|
ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
|
||||||
magicsys, nversion, nimsets, parser, times, passes, rodread
|
magicsys, nversion, nimsets, parser, times, passes, rodread
|
||||||
|
|
||||||
|
|
@ -118,7 +119,7 @@ proc newOptionEntry(): POptionEntry =
|
||||||
proc newContext(module: PSym, nimfile: string): PContext =
|
proc newContext(module: PSym, nimfile: string): PContext =
|
||||||
new(result)
|
new(result)
|
||||||
InitSymTab(result.tab)
|
InitSymTab(result.tab)
|
||||||
IntSetInit(result.AmbiguousSymbols)
|
result.AmbiguousSymbols = initIntset()
|
||||||
initLinkedList(result.optionStack)
|
initLinkedList(result.optionStack)
|
||||||
initLinkedList(result.libs)
|
initLinkedList(result.libs)
|
||||||
append(result.optionStack, newOptionEntry())
|
append(result.optionStack, newOptionEntry())
|
||||||
|
|
@ -127,7 +128,7 @@ proc newContext(module: PSym, nimfile: string): PContext =
|
||||||
result.threadEntries = newNode(nkStmtList)
|
result.threadEntries = newNode(nkStmtList)
|
||||||
result.converters = @[]
|
result.converters = @[]
|
||||||
result.filename = nimfile
|
result.filename = nimfile
|
||||||
IntSetInit(result.includedFiles)
|
result.includedFiles = initIntSet()
|
||||||
initStrTable(result.userPragmas)
|
initStrTable(result.userPragmas)
|
||||||
|
|
||||||
proc addConverter(c: PContext, conv: PSym) =
|
proc addConverter(c: PContext, conv: PSym) =
|
||||||
|
|
|
||||||
|
|
@ -888,11 +888,10 @@ proc checkPar(n: PNode): TParKind =
|
||||||
return paNone
|
return paNone
|
||||||
|
|
||||||
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||||
var ids: TIntSet
|
|
||||||
result = newNodeI(nkPar, n.info)
|
result = newNodeI(nkPar, n.info)
|
||||||
var typ = newTypeS(tyTuple, c)
|
var typ = newTypeS(tyTuple, c)
|
||||||
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs
|
||||||
IntSetInit(ids)
|
var ids = initIntSet()
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if (n.sons[i].kind != nkExprColonExpr) or
|
if (n.sons[i].kind != nkExprColonExpr) or
|
||||||
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
|
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
|
||||||
|
|
@ -900,7 +899,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode): PNode =
|
||||||
var id: PIdent
|
var id: PIdent
|
||||||
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
|
||||||
else: id = n.sons[i].sons[0].sym.name
|
else: id = n.sons[i].sons[0].sym.name
|
||||||
if IntSetContainsOrIncl(ids, id.id):
|
if ContainsOrIncl(ids, id.id):
|
||||||
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
localError(n.sons[i].info, errFieldInitTwice, id.s)
|
||||||
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
|
||||||
var f = newSymS(skField, n.sons[i].sons[0], c)
|
var f = newSymS(skField, n.sons[i].sons[0], c)
|
||||||
|
|
|
||||||
|
|
@ -476,11 +476,10 @@ proc semRaise(c: PContext, n: PNode): PNode =
|
||||||
localError(n.info, errExprCannotBeRaised)
|
localError(n.info, errExprCannotBeRaised)
|
||||||
|
|
||||||
proc semTry(c: PContext, n: PNode): PNode =
|
proc semTry(c: PContext, n: PNode): PNode =
|
||||||
var check: TIntSet
|
|
||||||
result = n
|
result = n
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
n.sons[0] = semStmtScope(c, n.sons[0])
|
n.sons[0] = semStmtScope(c, n.sons[0])
|
||||||
IntSetInit(check)
|
var check = initIntSet()
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
checkMinSonsLen(a, 1)
|
checkMinSonsLen(a, 1)
|
||||||
|
|
@ -493,7 +492,7 @@ proc semTry(c: PContext, n: PNode): PNode =
|
||||||
GlobalError(a.sons[j].info, errExprCannotBeRaised)
|
GlobalError(a.sons[j].info, errExprCannotBeRaised)
|
||||||
a.sons[j] = newNodeI(nkType, a.sons[j].info)
|
a.sons[j] = newNodeI(nkType, a.sons[j].info)
|
||||||
a.sons[j].typ = typ
|
a.sons[j].typ = typ
|
||||||
if IntSetContainsOrIncl(check, typ.id):
|
if ContainsOrIncl(check, typ.id):
|
||||||
localError(a.sons[j].info, errExceptionAlreadyHandled)
|
localError(a.sons[j].info, errExceptionAlreadyHandled)
|
||||||
elif a.kind != nkFinally:
|
elif a.kind != nkFinally:
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
|
|
@ -820,10 +819,10 @@ proc evalInclude(c: PContext, n: PNode): PNode =
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var f = getModuleFile(n.sons[i])
|
var f = getModuleFile(n.sons[i])
|
||||||
var fileIndex = includeFilename(f)
|
var fileIndex = includeFilename(f)
|
||||||
if IntSetContainsOrIncl(c.includedFiles, fileIndex):
|
if ContainsOrIncl(c.includedFiles, fileIndex):
|
||||||
GlobalError(n.info, errRecursiveDependencyX, f)
|
GlobalError(n.info, errRecursiveDependencyX, f)
|
||||||
addSon(result, semStmt(c, gIncludeFile(f)))
|
addSon(result, semStmt(c, gIncludeFile(f)))
|
||||||
IntSetExcl(c.includedFiles, fileIndex)
|
Excl(c.includedFiles, fileIndex)
|
||||||
|
|
||||||
proc SemStmt(c: PContext, n: PNode): PNode =
|
proc SemStmt(c: PContext, n: PNode): PNode =
|
||||||
const # must be last statements in a block:
|
const # must be last statements in a block:
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
|
||||||
var s: PSym
|
var s: PSym
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
if not withinBind and not IntSetContains(toBind, n.ident.id):
|
if not withinBind and not Contains(toBind, n.ident.id):
|
||||||
s = SymTabLocalGet(c.Tab, n.ident)
|
s = SymTabLocalGet(c.Tab, n.ident)
|
||||||
if (s != nil):
|
if (s != nil):
|
||||||
result = newSymNode(s)
|
result = newSymNode(s)
|
||||||
|
|
@ -125,7 +125,7 @@ proc resolveTemplateParams(c: PContext, n: PNode, withinBind: bool,
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
IntSetIncl(toBind, n.ident.id)
|
Incl(toBind, n.ident.id)
|
||||||
result = symChoice(c, n, lookup(c, n))
|
result = symChoice(c, n, lookup(c, n))
|
||||||
of nkEmpty, nkSym..nkNilLit: # atom
|
of nkEmpty, nkSym..nkNilLit: # atom
|
||||||
result = n
|
result = n
|
||||||
|
|
@ -160,7 +160,6 @@ proc transformToExpr(n: PNode): PNode =
|
||||||
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
var
|
var
|
||||||
s: PSym
|
s: PSym
|
||||||
toBind: TIntSet
|
|
||||||
if c.p.owner.kind == skModule:
|
if c.p.owner.kind == skModule:
|
||||||
s = semIdentVis(c, skTemplate, n.sons[0], {sfStar})
|
s = semIdentVis(c, skTemplate, n.sons[0], {sfStar})
|
||||||
incl(s.flags, sfGlobal)
|
incl(s.flags, sfGlobal)
|
||||||
|
|
@ -189,7 +188,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
s.typ.sons[0] = newTypeS(tyStmt, c)
|
s.typ.sons[0] = newTypeS(tyStmt, c)
|
||||||
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0])
|
||||||
addParams(c, s.typ.n) # resolve parameters:
|
addParams(c, s.typ.n) # resolve parameters:
|
||||||
IntSetInit(toBind)
|
var toBind = initIntSet()
|
||||||
n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
|
n.sons[codePos] = resolveTemplateParams(c, n.sons[codePos], false, toBind)
|
||||||
if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}):
|
if not (s.typ.sons[0].kind in {tyStmt, tyTypeDesc}):
|
||||||
n.sons[codePos] = transformToExpr(n.sons[codePos])
|
n.sons[codePos] = transformToExpr(n.sons[codePos])
|
||||||
|
|
|
||||||
|
|
@ -192,10 +192,9 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var
|
var
|
||||||
typ: PType
|
typ: PType
|
||||||
check: TIntSet
|
|
||||||
result = newOrPrevType(tyTuple, prev, c)
|
result = newOrPrevType(tyTuple, prev, c)
|
||||||
result.n = newNodeI(nkRecList, n.info)
|
result.n = newNodeI(nkRecList, n.info)
|
||||||
IntSetInit(check)
|
var check = initIntSet()
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
|
|
@ -212,7 +211,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||||
field.typ = typ
|
field.typ = typ
|
||||||
field.position = counter
|
field.position = counter
|
||||||
inc(counter)
|
inc(counter)
|
||||||
if IntSetContainsOrIncl(check, field.name.id):
|
if ContainsOrIncl(check, field.name.id):
|
||||||
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
|
GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
|
||||||
addSon(result.n, newSymNode(field))
|
addSon(result.n, newSymNode(field))
|
||||||
addSon(result, typ)
|
addSon(result, typ)
|
||||||
|
|
@ -396,7 +395,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
f.loc.r = toRope(f.name.s)
|
f.loc.r = toRope(f.name.s)
|
||||||
f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
|
f.flags = f.flags + ({sfImportc, sfExportc} * rectype.flags)
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if IntSetContainsOrIncl(check, f.name.id):
|
if ContainsOrIncl(check, f.name.id):
|
||||||
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
||||||
if a.kind == nkEmpty: addSon(father, newSymNode(f))
|
if a.kind == nkEmpty: addSon(father, newSymNode(f))
|
||||||
else: addSon(a, newSymNode(f))
|
else: addSon(a, newSymNode(f))
|
||||||
|
|
@ -419,7 +418,7 @@ proc addInheritedFieldsAux(c: PContext, check: var TIntSet, pos: var int,
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
addInheritedFieldsAux(c, check, pos, n.sons[i])
|
addInheritedFieldsAux(c, check, pos, n.sons[i])
|
||||||
of nkSym:
|
of nkSym:
|
||||||
IntSetIncl(check, n.sym.name.id)
|
Incl(check, n.sym.name.id)
|
||||||
inc(pos)
|
inc(pos)
|
||||||
else: InternalError(n.info, "addInheritedFieldsAux()")
|
else: InternalError(n.info, "addInheritedFieldsAux()")
|
||||||
|
|
||||||
|
|
@ -437,8 +436,7 @@ proc skipGenericInvokation(t: PType): PType {.inline.} =
|
||||||
result = lastSon(result)
|
result = lastSon(result)
|
||||||
|
|
||||||
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var check: TIntSet
|
var check = initIntSet()
|
||||||
IntSetInit(check)
|
|
||||||
var pos = 0
|
var pos = 0
|
||||||
var base: PType = nil
|
var base: PType = nil
|
||||||
# n.sons[0] contains the pragmas (if any). We process these later...
|
# n.sons[0] contains the pragmas (if any). We process these later...
|
||||||
|
|
@ -460,7 +458,7 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
||||||
cl: var TIntSet): PType =
|
cl: var TIntSet): PType =
|
||||||
result = t
|
result = t
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
if IntSetContainsOrIncl(cl, t.id): return
|
if ContainsOrIncl(cl, t.id): return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
#debug(t)
|
#debug(t)
|
||||||
|
|
@ -470,7 +468,7 @@ proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode,
|
||||||
if t.sons[i].kind != tyGenericParam:
|
if t.sons[i].kind != tyGenericParam:
|
||||||
InternalError("addTypeVarsOfGenericBody")
|
InternalError("addTypeVarsOfGenericBody")
|
||||||
# do not declare ``TKey`` twice:
|
# do not declare ``TKey`` twice:
|
||||||
#if not IntSetContainsOrIncl(cl, t.sons[i].sym.ident.id):
|
#if not ContainsOrIncl(cl, t.sons[i].sym.ident.id):
|
||||||
var s = copySym(t.sons[i].sym)
|
var s = copySym(t.sons[i].sym)
|
||||||
s.position = sonsLen(genericParams)
|
s.position = sonsLen(genericParams)
|
||||||
if s.typ == nil or s.typ.kind != tyGenericParam:
|
if s.typ == nil or s.typ.kind != tyGenericParam:
|
||||||
|
|
@ -501,16 +499,17 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
var
|
var
|
||||||
def, res: PNode
|
def, res: PNode
|
||||||
typ: PType
|
typ: PType
|
||||||
check, cl: TIntSet
|
cl: TIntSet
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
result = newOrPrevType(tyProc, prev, c)
|
result = newOrPrevType(tyProc, prev, c)
|
||||||
result.callConv = lastOptionEntry(c).defaultCC
|
result.callConv = lastOptionEntry(c).defaultCC
|
||||||
result.n = newNodeI(nkFormalParams, n.info)
|
result.n = newNodeI(nkFormalParams, n.info)
|
||||||
if (genericParams != nil) and (sonsLen(genericParams) == 0): IntSetInit(cl)
|
if (genericParams != nil) and (sonsLen(genericParams) == 0):
|
||||||
|
cl = initIntSet()
|
||||||
addSon(result, nil) # return type
|
addSon(result, nil) # return type
|
||||||
res = newNodeI(nkType, n.info)
|
res = newNodeI(nkType, n.info)
|
||||||
addSon(result.n, res)
|
addSon(result.n, res)
|
||||||
IntSetInit(check)
|
var check = initIntSet()
|
||||||
var counter = 0
|
var counter = 0
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
|
|
@ -539,7 +538,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
arg.position = counter
|
arg.position = counter
|
||||||
inc(counter)
|
inc(counter)
|
||||||
if def.kind != nkEmpty: arg.ast = copyTree(def)
|
if def.kind != nkEmpty: arg.ast = copyTree(def)
|
||||||
if IntSetContainsOrIncl(check, arg.name.id):
|
if ContainsOrIncl(check, arg.name.id):
|
||||||
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
|
LocalError(a.sons[j].info, errAttemptToRedefine, arg.name.s)
|
||||||
addSon(result.n, newSymNode(arg))
|
addSon(result.n, newSymNode(arg))
|
||||||
addSon(result, typ)
|
addSon(result, typ)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
# the call to overloaded procs, generic procs and operators.
|
# the call to overloaded procs, generic procs and operators.
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
|
intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
|
||||||
magicsys
|
magicsys
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -608,7 +608,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
|
||||||
# no error message!
|
# no error message!
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
return
|
return
|
||||||
if IntSetContainsOrIncl(marker, formal.position):
|
if ContainsOrIncl(marker, formal.position):
|
||||||
# already in namedParams:
|
# already in namedParams:
|
||||||
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
|
|
@ -653,7 +653,7 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
|
||||||
if m.callee.n.sons[f].kind != nkSym:
|
if m.callee.n.sons[f].kind != nkSym:
|
||||||
InternalError(n.sons[a].info, "matches")
|
InternalError(n.sons[a].info, "matches")
|
||||||
formal = m.callee.n.sons[f].sym
|
formal = m.callee.n.sons[f].sym
|
||||||
if IntSetContainsOrIncl(marker, formal.position):
|
if ContainsOrIncl(marker, formal.position):
|
||||||
# already in namedParams:
|
# already in namedParams:
|
||||||
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
LocalError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
|
|
@ -677,20 +677,18 @@ proc matchesAux*(c: PContext, n: PNode, m: var TCandidate,
|
||||||
|
|
||||||
proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) =
|
proc partialMatch*(c: PContext, n: PNode, m: var TCandidate) =
|
||||||
# for 'suggest' support:
|
# for 'suggest' support:
|
||||||
var marker: TIntSet
|
var marker = initIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
matchesAux(c, n, m, marker)
|
matchesAux(c, n, m, marker)
|
||||||
|
|
||||||
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
proc matches*(c: PContext, n: PNode, m: var TCandidate) =
|
||||||
var marker: TIntSet
|
var marker = initIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
matchesAux(c, n, m, marker)
|
matchesAux(c, n, m, marker)
|
||||||
if m.state == csNoMatch: return
|
if m.state == csNoMatch: return
|
||||||
# check that every formal parameter got a value:
|
# check that every formal parameter got a value:
|
||||||
var f = 1
|
var f = 1
|
||||||
while f < sonsLen(m.callee.n):
|
while f < sonsLen(m.callee.n):
|
||||||
var formal = m.callee.n.sons[f].sym
|
var formal = m.callee.n.sons[f].sym
|
||||||
if not IntSetContainsOrIncl(marker, formal.position):
|
if not ContainsOrIncl(marker, formal.position):
|
||||||
if formal.ast == nil:
|
if formal.ast == nil:
|
||||||
if formal.typ.kind == tyOpenArray:
|
if formal.typ.kind == tyOpenArray:
|
||||||
var container = newNodeI(nkBracket, n.info)
|
var container = newNodeI(nkBracket, n.info)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
# * introduces method dispatchers
|
# * introduces method dispatchers
|
||||||
|
|
||||||
import
|
import
|
||||||
strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
|
intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
|
||||||
idents, renderer, types, passes, semfold, magicsys, cgmeth
|
idents, renderer, types, passes, semfold, magicsys, cgmeth
|
||||||
|
|
||||||
const
|
const
|
||||||
|
|
@ -528,8 +528,7 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
|
||||||
of skVar: found = not (sfGlobal in s.flags)
|
of skVar: found = not (sfGlobal in s.flags)
|
||||||
of skTemp, skForVar, skParam: found = true
|
of skTemp, skForVar, skParam: found = true
|
||||||
else: nil
|
else: nil
|
||||||
if found and (owner.id != s.owner.id) and
|
if found and (owner.id != s.owner.id) and not ContainsOrIncl(marked, s.id):
|
||||||
not IntSetContainsOrIncl(marked, s.id):
|
|
||||||
incl(s.flags, sfInClosure)
|
incl(s.flags, sfInClosure)
|
||||||
addSon(container, copyNode(n)) # DON'T make a copy of the symbol!
|
addSon(container, copyNode(n)) # DON'T make a copy of the symbol!
|
||||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||||
|
|
@ -555,9 +554,8 @@ proc indirectAccess(a, b: PSym): PNode =
|
||||||
result.typ = y.typ
|
result.typ = y.typ
|
||||||
|
|
||||||
proc transformLambda(c: PTransf, n: PNode): PNode =
|
proc transformLambda(c: PTransf, n: PNode): PNode =
|
||||||
var marked: TIntSet
|
var marked = initIntSet()
|
||||||
result = n
|
result = n
|
||||||
IntSetInit(marked)
|
|
||||||
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
|
if (n.sons[namePos].kind != nkSym): InternalError(n.info, "transformLambda")
|
||||||
var s = n.sons[namePos].sym
|
var s = n.sons[namePos].sym
|
||||||
var closure = newNodeI(nkRecList, n.sons[codePos].info)
|
var closure = newNodeI(nkRecList, n.sons[codePos].info)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
# this module contains routines for accessing and iterating over types
|
# this module contains routines for accessing and iterating over types
|
||||||
|
|
||||||
import
|
import
|
||||||
ast, astalgo, trees, msgs, strutils, platform
|
intsets, ast, astalgo, trees, msgs, strutils, platform
|
||||||
|
|
||||||
proc firstOrd*(t: PType): biggestInt
|
proc firstOrd*(t: PType): biggestInt
|
||||||
proc lastOrd*(t: PType): biggestInt
|
proc lastOrd*(t: PType): biggestInt
|
||||||
|
|
@ -219,7 +219,7 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
result = iter(t, closure)
|
result = iter(t, closure)
|
||||||
if result: return
|
if result: return
|
||||||
if not IntSetContainsOrIncl(marker, t.id):
|
if not ContainsOrIncl(marker, t.id):
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericInst, tyGenericBody:
|
of tyGenericInst, tyGenericBody:
|
||||||
result = iterOverTypeAux(marker, lastSon(t), iter, closure)
|
result = iterOverTypeAux(marker, lastSon(t), iter, closure)
|
||||||
|
|
@ -230,8 +230,7 @@ proc iterOverTypeAux(marker: var TIntSet, t: PType, iter: TTypeIter,
|
||||||
if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
|
if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
|
||||||
|
|
||||||
proc IterOverType(t: PType, iter: TTypeIter, closure: PObject): bool =
|
proc IterOverType(t: PType, iter: TTypeIter, closure: PObject): bool =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = iterOverTypeAux(marker, t, iter, closure)
|
result = iterOverTypeAux(marker, t, iter, closure)
|
||||||
|
|
||||||
proc searchTypeForAux(t: PType, predicate: TTypePredicate,
|
proc searchTypeForAux(t: PType, predicate: TTypePredicate,
|
||||||
|
|
@ -263,7 +262,7 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, marker: var TIntSet):
|
||||||
# iterates over VALUE types!
|
# iterates over VALUE types!
|
||||||
result = false
|
result = false
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
if IntSetContainsOrIncl(marker, t.id): return
|
if ContainsOrIncl(marker, t.id): return
|
||||||
result = Predicate(t)
|
result = Predicate(t)
|
||||||
if result: return
|
if result: return
|
||||||
case t.kind
|
case t.kind
|
||||||
|
|
@ -280,8 +279,7 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate, marker: var TIntSet):
|
||||||
nil
|
nil
|
||||||
|
|
||||||
proc searchTypeFor(t: PType, predicate: TTypePredicate): bool =
|
proc searchTypeFor(t: PType, predicate: TTypePredicate): bool =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = searchTypeForAux(t, predicate, marker)
|
result = searchTypeForAux(t, predicate, marker)
|
||||||
|
|
||||||
proc isObjectPredicate(t: PType): bool =
|
proc isObjectPredicate(t: PType): bool =
|
||||||
|
|
@ -322,8 +320,7 @@ proc analyseObjectWithTypeFieldAux(t: PType, marker: var TIntSet): TTypeFieldRes
|
||||||
nil
|
nil
|
||||||
|
|
||||||
proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
|
proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = analyseObjectWithTypeFieldAux(t, marker)
|
result = analyseObjectWithTypeFieldAux(t, marker)
|
||||||
|
|
||||||
proc isGBCRef(t: PType): bool =
|
proc isGBCRef(t: PType): bool =
|
||||||
|
|
@ -365,7 +362,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
||||||
if tfAcyclic in t.flags: return
|
if tfAcyclic in t.flags: return
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray:
|
of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray:
|
||||||
if not IntSetContainsOrIncl(marker, t.id):
|
if not ContainsOrIncl(marker, t.id):
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
result = canFormAcycleAux(marker, t.sons[i], startId)
|
result = canFormAcycleAux(marker, t.sons[i], startId)
|
||||||
if result: return
|
if result: return
|
||||||
|
|
@ -376,8 +373,7 @@ proc canFormAcycleAux(marker: var TIntSet, typ: PType, startId: int): bool =
|
||||||
nil
|
nil
|
||||||
|
|
||||||
proc canFormAcycle(typ: PType): bool =
|
proc canFormAcycle(typ: PType): bool =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = canFormAcycleAux(marker, typ, typ.id)
|
result = canFormAcycleAux(marker, typ, typ.id)
|
||||||
|
|
||||||
proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
|
proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
|
||||||
|
|
@ -400,7 +396,7 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
|
||||||
result = nil
|
result = nil
|
||||||
if t == nil: return
|
if t == nil: return
|
||||||
result = iter(t, closure)
|
result = iter(t, closure)
|
||||||
if not IntSetContainsOrIncl(marker, t.id):
|
if not ContainsOrIncl(marker, t.id):
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
|
result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
|
||||||
if (result.sons[i] == nil) and (result.kind == tyGenericInst):
|
if (result.sons[i] == nil) and (result.kind == tyGenericInst):
|
||||||
|
|
@ -409,8 +405,7 @@ proc mutateTypeAux(marker: var TIntSet, t: PType, iter: TTypeMutator,
|
||||||
assert(result != nil)
|
assert(result != nil)
|
||||||
|
|
||||||
proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
|
proc mutateType(t: PType, iter: TTypeMutator, closure: PObject): PType =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = mutateTypeAux(marker, t, iter, closure)
|
result = mutateTypeAux(marker, t, iter, closure)
|
||||||
|
|
||||||
proc rangeToStr(n: PNode): string =
|
proc rangeToStr(n: PNode): string =
|
||||||
|
|
@ -591,17 +586,14 @@ proc equalParam(a, b: PSym): TParamsEquality =
|
||||||
result = paramsNotEqual
|
result = paramsNotEqual
|
||||||
|
|
||||||
proc equalParams(a, b: PNode): TParamsEquality =
|
proc equalParams(a, b: PNode): TParamsEquality =
|
||||||
var
|
|
||||||
length: int
|
|
||||||
m, n: PSym
|
|
||||||
result = paramsEqual
|
result = paramsEqual
|
||||||
length = sonsLen(a)
|
var length = sonsLen(a)
|
||||||
if length != sonsLen(b):
|
if length != sonsLen(b):
|
||||||
result = paramsNotEqual
|
result = paramsNotEqual
|
||||||
else:
|
else:
|
||||||
for i in countup(1, length - 1):
|
for i in countup(1, length - 1):
|
||||||
m = a.sons[i].sym
|
var m = a.sons[i].sym
|
||||||
n = b.sons[i].sym
|
var n = b.sons[i].sym
|
||||||
assert((m.kind == skParam) and (n.kind == skParam))
|
assert((m.kind == skParam) and (n.kind == skParam))
|
||||||
case equalParam(m, n)
|
case equalParam(m, n)
|
||||||
of paramsNotEqual:
|
of paramsNotEqual:
|
||||||
|
|
@ -646,7 +638,6 @@ proc sameTuple(a, b: PType, DistinctOf: bool): bool =
|
||||||
# two tuples are equivalent iff the names, types and positions are the same;
|
# two tuples are equivalent iff the names, types and positions are the same;
|
||||||
# however, both types may not have any field names (t.n may be nil) which
|
# however, both types may not have any field names (t.n may be nil) which
|
||||||
# complicates the matter a bit.
|
# complicates the matter a bit.
|
||||||
var x, y: PSym
|
|
||||||
if sonsLen(a) == sonsLen(b):
|
if sonsLen(a) == sonsLen(b):
|
||||||
result = true
|
result = true
|
||||||
for i in countup(0, sonsLen(a) - 1):
|
for i in countup(0, sonsLen(a) - 1):
|
||||||
|
|
@ -658,8 +649,8 @@ proc sameTuple(a, b: PType, DistinctOf: bool): bool =
|
||||||
# check field names:
|
# check field names:
|
||||||
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
|
if a.n.sons[i].kind != nkSym: InternalError(a.n.info, "sameTuple")
|
||||||
if b.n.sons[i].kind != nkSym: InternalError(b.n.info, "sameTuple")
|
if b.n.sons[i].kind != nkSym: InternalError(b.n.info, "sameTuple")
|
||||||
x = a.n.sons[i].sym
|
var x = a.n.sons[i].sym
|
||||||
y = b.n.sons[i].sym
|
var y = b.n.sons[i].sym
|
||||||
result = x.name.id == y.name.id
|
result = x.name.id == y.name.id
|
||||||
if not result: break
|
if not result: break
|
||||||
else:
|
else:
|
||||||
|
|
@ -758,17 +749,16 @@ proc typeAllowedNode(marker: var TIntSet, n: PNode, kind: TSymKind): bool =
|
||||||
if not result: return
|
if not result: return
|
||||||
|
|
||||||
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
var t, t2: PType
|
|
||||||
assert(kind in {skVar, skConst, skParam})
|
assert(kind in {skVar, skConst, skParam})
|
||||||
|
# if we have already checked the type, return true, because we stop the
|
||||||
|
# evaluation if something is wrong:
|
||||||
result = true
|
result = true
|
||||||
if typ == nil:
|
if typ == nil: return
|
||||||
return # if we have already checked the type, return true, because we stop the
|
if ContainsOrIncl(marker, typ.id): return
|
||||||
# evaluation if something is wrong:
|
var t = skipTypes(typ, abstractInst)
|
||||||
if IntSetContainsOrIncl(marker, typ.id): return
|
|
||||||
t = skipTypes(typ, abstractInst)
|
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyVar:
|
of tyVar:
|
||||||
t2 = skipTypes(t.sons[0], abstractInst)
|
var t2 = skipTypes(t.sons[0], abstractInst)
|
||||||
case t2.kind
|
case t2.kind
|
||||||
of tyVar:
|
of tyVar:
|
||||||
result = false # ``var var`` is always an invalid type:
|
result = false # ``var var`` is always an invalid type:
|
||||||
|
|
@ -815,8 +805,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
|
||||||
if t.n != nil: result = typeAllowedNode(marker, t.n, skVar)
|
if t.n != nil: result = typeAllowedNode(marker, t.n, skVar)
|
||||||
|
|
||||||
proc typeAllowed(t: PType, kind: TSymKind): bool =
|
proc typeAllowed(t: PType, kind: TSymKind): bool =
|
||||||
var marker: TIntSet
|
var marker = InitIntSet()
|
||||||
IntSetInit(marker)
|
|
||||||
result = typeAllowedAux(marker, t, kind)
|
result = typeAllowedAux(marker, t, kind)
|
||||||
|
|
||||||
proc align(address, alignment: biggestInt): biggestInt =
|
proc align(address, alignment: biggestInt): biggestInt =
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ Core
|
||||||
Contains procs for serialization and deseralization of arbitrary Nimrod
|
Contains procs for serialization and deseralization of arbitrary Nimrod
|
||||||
data structures.
|
data structures.
|
||||||
|
|
||||||
|
* `typeinfo <typeinfo.html>`_
|
||||||
|
Provides (unsafe) access to Nimrod's run time type information.
|
||||||
|
|
||||||
|
|
||||||
Collections and algorithms
|
Collections and algorithms
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
@ -53,6 +56,8 @@ Collections and algorithms
|
||||||
* `lists <lists.html>`_
|
* `lists <lists.html>`_
|
||||||
Nimrod linked list support. Contains singly and doubly linked lists and
|
Nimrod linked list support. Contains singly and doubly linked lists and
|
||||||
circular lists ("rings").
|
circular lists ("rings").
|
||||||
|
* `intsets <intsets.html>`_
|
||||||
|
Efficient implementation of a set of ints as a sparse bit set.
|
||||||
|
|
||||||
|
|
||||||
String handling
|
String handling
|
||||||
|
|
|
||||||
177
lib/pure/collections/intsets.nim
Normal file
177
lib/pure/collections/intsets.nim
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Nimrod's Runtime Library
|
||||||
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## The ``intsets`` module implements an efficient int set implemented as a
|
||||||
|
## sparse bit set.
|
||||||
|
## **Note**: Since Nimrod does not allow the assignment operator to be
|
||||||
|
## overloaded, ``=`` for int sets performs some rather meaningless shallow
|
||||||
|
## copy.
|
||||||
|
|
||||||
|
import
|
||||||
|
os, hashes, math
|
||||||
|
|
||||||
|
type
|
||||||
|
TBitScalar = int
|
||||||
|
|
||||||
|
const
|
||||||
|
InitIntSetSize = 8 # must be a power of two!
|
||||||
|
TrunkShift = 9
|
||||||
|
BitsPerTrunk = 1 shl TrunkShift # needs to be a power of 2 and
|
||||||
|
# divisible by 64
|
||||||
|
TrunkMask = BitsPerTrunk - 1
|
||||||
|
IntsPerTrunk = BitsPerTrunk div (sizeof(TBitScalar) * 8)
|
||||||
|
IntShift = 5 + ord(sizeof(TBitScalar) == 8) # 5 or 6, depending on int width
|
||||||
|
IntMask = 1 shl IntShift - 1
|
||||||
|
|
||||||
|
type
|
||||||
|
PTrunk = ref TTrunk
|
||||||
|
TTrunk {.final.} = object
|
||||||
|
next: PTrunk # all nodes are connected with this pointer
|
||||||
|
key: int # start address at bit 0
|
||||||
|
bits: array[0..IntsPerTrunk - 1, TBitScalar] # a bit vector
|
||||||
|
|
||||||
|
TTrunkSeq = seq[PTrunk]
|
||||||
|
TIntSet* {.final.} = object ## an efficient set of 'int' implemented as a
|
||||||
|
## sparse bit set
|
||||||
|
counter, max: int
|
||||||
|
head: PTrunk
|
||||||
|
data: TTrunkSeq
|
||||||
|
|
||||||
|
proc mustRehash(length, counter: int): bool {.inline.} =
|
||||||
|
assert(length > counter)
|
||||||
|
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||||
|
|
||||||
|
proc nextTry(h, maxHash: THash): THash {.inline.} =
|
||||||
|
result = ((5 * h) + 1) and maxHash
|
||||||
|
|
||||||
|
proc IntSetGet(t: TIntSet, key: int): PTrunk =
|
||||||
|
var h = key and t.max
|
||||||
|
while t.data[h] != nil:
|
||||||
|
if t.data[h].key == key:
|
||||||
|
return t.data[h]
|
||||||
|
h = nextTry(h, t.max)
|
||||||
|
result = nil
|
||||||
|
|
||||||
|
proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) =
|
||||||
|
var h = desc.key and t.max
|
||||||
|
while data[h] != nil:
|
||||||
|
assert(data[h] != desc)
|
||||||
|
h = nextTry(h, t.max)
|
||||||
|
assert(data[h] == nil)
|
||||||
|
data[h] = desc
|
||||||
|
|
||||||
|
proc IntSetEnlarge(t: var TIntSet) =
|
||||||
|
var n: TTrunkSeq
|
||||||
|
var oldMax = t.max
|
||||||
|
t.max = ((t.max + 1) * 2) - 1
|
||||||
|
newSeq(n, t.max + 1)
|
||||||
|
for i in countup(0, oldmax):
|
||||||
|
if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i])
|
||||||
|
swap(t.data, n)
|
||||||
|
|
||||||
|
proc IntSetPut(t: var TIntSet, key: int): PTrunk =
|
||||||
|
var h = key and t.max
|
||||||
|
while t.data[h] != nil:
|
||||||
|
if t.data[h].key == key:
|
||||||
|
return t.data[h]
|
||||||
|
h = nextTry(h, t.max)
|
||||||
|
if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t)
|
||||||
|
inc(t.counter)
|
||||||
|
h = key and t.max
|
||||||
|
while t.data[h] != nil: h = nextTry(h, t.max)
|
||||||
|
assert(t.data[h] == nil)
|
||||||
|
new(result)
|
||||||
|
result.next = t.head
|
||||||
|
result.key = key
|
||||||
|
t.head = result
|
||||||
|
t.data[h] = result
|
||||||
|
|
||||||
|
proc contains*(s: TIntSet, key: int): bool =
|
||||||
|
## returns true iff `key` is in `s`.
|
||||||
|
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||||
|
if t != nil:
|
||||||
|
var u = key and TrunkMask
|
||||||
|
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||||
|
else:
|
||||||
|
result = false
|
||||||
|
|
||||||
|
proc incl*(s: var TIntSet, key: int) =
|
||||||
|
## includes an element `key` in `s`.
|
||||||
|
var t = IntSetPut(s, `shr`(key, TrunkShift))
|
||||||
|
var u = key and TrunkMask
|
||||||
|
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||||
|
`shl`(1, u and IntMask)
|
||||||
|
|
||||||
|
proc excl*(s: var TIntSet, key: int) =
|
||||||
|
## excludes `key` from the set `s`.
|
||||||
|
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||||
|
if t != nil:
|
||||||
|
var u = key and TrunkMask
|
||||||
|
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
|
||||||
|
not `shl`(1, u and IntMask)
|
||||||
|
|
||||||
|
proc containsOrIncl*(s: var TIntSet, key: int): bool =
|
||||||
|
## returns true if `s` contains `key`, otherwise `key` is included in `s`
|
||||||
|
## and false is returned.
|
||||||
|
var t = IntSetGet(s, `shr`(key, TrunkShift))
|
||||||
|
if t != nil:
|
||||||
|
var u = key and TrunkMask
|
||||||
|
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||||
|
if not result:
|
||||||
|
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||||
|
`shl`(1, u and IntMask)
|
||||||
|
else:
|
||||||
|
incl(s, key)
|
||||||
|
result = false
|
||||||
|
|
||||||
|
proc initIntSet*: TIntSet =
|
||||||
|
## creates a new int set that is empty.
|
||||||
|
newSeq(result.data, InitIntSetSize)
|
||||||
|
result.max = InitIntSetSize-1
|
||||||
|
result.counter = 0
|
||||||
|
result.head = nil
|
||||||
|
|
||||||
|
template dollarImpl(): stmt =
|
||||||
|
result = "{"
|
||||||
|
for key in items(s):
|
||||||
|
if result.len > 1: result.add(", ")
|
||||||
|
result.add($key)
|
||||||
|
result.add("}")
|
||||||
|
|
||||||
|
proc `$`*(s: TIntSet): string =
|
||||||
|
## The `$` operator for int sets.
|
||||||
|
dollarImpl()
|
||||||
|
|
||||||
|
iterator items*(s: TIntSet): int {.inline.} =
|
||||||
|
## iterates over any included element of `s`.
|
||||||
|
var r = s.head
|
||||||
|
while r != nil:
|
||||||
|
var i = 0
|
||||||
|
while i <= high(r.bits):
|
||||||
|
var w = r.bits[i]
|
||||||
|
# taking a copy of r.bits[i] here is correct, because
|
||||||
|
# modifying operations are not allowed during traversation
|
||||||
|
var j = 0
|
||||||
|
while w != 0: # test all remaining bits for zero
|
||||||
|
if (w and 1) != 0: # the bit is set!
|
||||||
|
yield (r.key shl TrunkShift) or (i shl IntShift +% j)
|
||||||
|
inc(j)
|
||||||
|
w = w shr 1
|
||||||
|
inc(i)
|
||||||
|
r = r.next
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
var x = initIntSet()
|
||||||
|
x.incl(1)
|
||||||
|
x.incl(2)
|
||||||
|
x.incl(7)
|
||||||
|
x.incl(1056)
|
||||||
|
for e in items(x): echo e
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nimrod's Runtime Library
|
|
||||||
# (c) Copyright 2006 Andreas Rumpf
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2
todo.txt
2
todo.txt
|
|
@ -78,7 +78,7 @@ Low priority
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
- specialized bit sets; specialized string sets
|
- radix tree for strings; maybe suffix tree
|
||||||
- locale support
|
- locale support
|
||||||
- conversion between character sets
|
- conversion between character sets
|
||||||
- bignums
|
- bignums
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ Additions
|
||||||
- Added ``lists`` module which contains generic linked lists.
|
- Added ``lists`` module which contains generic linked lists.
|
||||||
- Added ``sets`` module which contains generic hash sets.
|
- Added ``sets`` module which contains generic hash sets.
|
||||||
- Added ``tables`` module which contains generic hash tables.
|
- Added ``tables`` module which contains generic hash tables.
|
||||||
|
- Added ``intsets`` module which contains a specialized int set data type.
|
||||||
- Added ``scgi`` module.
|
- Added ``scgi`` module.
|
||||||
- Added ``smtp`` module.
|
- Added ``smtp`` module.
|
||||||
- Added ``re.findAll``, ``pegs.findAll``.
|
- Added ``re.findAll``, ``pegs.findAll``.
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ file: ticker
|
||||||
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview"
|
doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview"
|
||||||
doc: "tools;c2nim;niminst"
|
doc: "tools;c2nim;niminst"
|
||||||
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
|
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
|
||||||
srcdoc: "core/macros;core/marshal"
|
srcdoc: "core/macros;core/marshal;core/typeinfo"
|
||||||
srcdoc: "impure/graphics;pure/sockets"
|
srcdoc: "impure/graphics;pure/sockets"
|
||||||
srcdoc: "system.nim;system/threads.nim;pure/os;pure/strutils;pure/math"
|
srcdoc: "system.nim;system/threads.nim;pure/os;pure/strutils;pure/math"
|
||||||
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
|
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
|
||||||
|
|
@ -39,6 +39,7 @@ srcdoc: "pure/xmlparser;pure/htmlparser;pure/xmltree;pure/colors"
|
||||||
srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
|
srcdoc: "pure/json;pure/base64;pure/scgi;pure/redis;impure/graphics"
|
||||||
srcdoc: "impure/rdstdin;wrappers/zmq"
|
srcdoc: "impure/rdstdin;wrappers/zmq"
|
||||||
srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
|
srcdoc: "pure/collections/tables;pure/collections/sets;pure/collections/lists"
|
||||||
|
srcdoc: "pure/collections/intsets"
|
||||||
|
|
||||||
webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
|
webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
|
||||||
webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"
|
webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue