IC: final implementation steps (#16801)
* removed dead code * we need even more laziness for the generic caches * make it bootstrap on older Nims * wrote more deserialization code * IC: replay required methods information
This commit is contained in:
parent
0436a7cffd
commit
25745ad195
12 changed files with 259 additions and 105 deletions
|
|
@ -2236,7 +2236,6 @@ proc genSlice(p: BProc; e: PNode; d: var TLoc) =
|
||||||
"'toOpenArray' is only valid within a call expression")
|
"'toOpenArray' is only valid within a call expression")
|
||||||
|
|
||||||
proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
|
proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
const ToStringProcSlot = -4
|
|
||||||
let t = e[1].typ.skipTypes(abstractInst+{tyRange})
|
let t = e[1].typ.skipTypes(abstractInst+{tyRange})
|
||||||
let toStrProc = getToStringProc(p.module.g.graph, t)
|
let toStrProc = getToStringProc(p.module.g.graph, t)
|
||||||
# XXX need to modify this logic for IC.
|
# XXX need to modify this logic for IC.
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
|
||||||
if disp.typ.lockLevel < meth.typ.lockLevel:
|
if disp.typ.lockLevel < meth.typ.lockLevel:
|
||||||
disp.typ.lockLevel = meth.typ.lockLevel
|
disp.typ.lockLevel = meth.typ.lockLevel
|
||||||
|
|
||||||
proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) =
|
proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym) =
|
||||||
var witness: PSym
|
var witness: PSym
|
||||||
for i in 0..<g.methods.len:
|
for i in 0..<g.methods.len:
|
||||||
let disp = g.methods[i].dispatcher
|
let disp = g.methods[i].dispatcher
|
||||||
|
|
@ -182,8 +182,6 @@ proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) =
|
||||||
# create a new dispatcher:
|
# create a new dispatcher:
|
||||||
g.methods.add((methods: @[s], dispatcher: createDispatcher(s, g, idgen)))
|
g.methods.add((methods: @[s], dispatcher: createDispatcher(s, g, idgen)))
|
||||||
#echo "adding ", s.info
|
#echo "adding ", s.info
|
||||||
#if fromCache:
|
|
||||||
# internalError(s.info, "no method dispatcher found")
|
|
||||||
if witness != nil:
|
if witness != nil:
|
||||||
localError(g.config, s.info, "invalid declaration order; cannot attach '" & s.name.s &
|
localError(g.config, s.info, "invalid declaration order; cannot attach '" & s.name.s &
|
||||||
"' to method defined here: " & g.config$witness.info)
|
"' to method defined here: " & g.config$witness.info)
|
||||||
|
|
|
||||||
|
|
@ -74,11 +74,9 @@ type
|
||||||
flags*: TTypeFlags
|
flags*: TTypeFlags
|
||||||
types*: seq[PackedItemId]
|
types*: seq[PackedItemId]
|
||||||
n*: NodeId
|
n*: NodeId
|
||||||
methods*: seq[(int, PackedItemId)]
|
|
||||||
#nodeflags*: TNodeFlags
|
#nodeflags*: TNodeFlags
|
||||||
sym*: PackedItemId
|
sym*: PackedItemId
|
||||||
owner*: PackedItemId
|
owner*: PackedItemId
|
||||||
attachedOps*: array[TTypeAttachedOp, PackedItemId]
|
|
||||||
size*: BiggestInt
|
size*: BiggestInt
|
||||||
align*: int16
|
align*: int16
|
||||||
paddingAtEnd*: int16
|
paddingAtEnd*: int16
|
||||||
|
|
@ -111,6 +109,10 @@ type
|
||||||
floats*: BiTable[BiggestFloat]
|
floats*: BiTable[BiggestFloat]
|
||||||
#config*: ConfigRef
|
#config*: ConfigRef
|
||||||
|
|
||||||
|
PackedInstantiation* = object
|
||||||
|
key*, sym*: PackedItemId
|
||||||
|
concreteTypes*: seq[PackedItemId]
|
||||||
|
|
||||||
proc `==`*(a, b: SymId): bool {.borrow.}
|
proc `==`*(a, b: SymId): bool {.borrow.}
|
||||||
proc hash*(a: SymId): Hash {.borrow.}
|
proc hash*(a: SymId): Hash {.borrow.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@
|
||||||
## support.
|
## support.
|
||||||
|
|
||||||
import ".." / [ast, modulegraphs, trees, extccomp, btrees,
|
import ".." / [ast, modulegraphs, trees, extccomp, btrees,
|
||||||
msgs, lineinfos, pathutils, options]
|
msgs, lineinfos, pathutils, options, cgmeth]
|
||||||
|
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
|
import packed_ast, to_packed_ast, bitabs
|
||||||
|
|
||||||
proc replayStateChanges*(module: PSym; g: ModuleGraph) =
|
proc replayStateChanges*(module: PSym; g: ModuleGraph) =
|
||||||
let list = module.ast
|
let list = module.ast
|
||||||
assert list != nil
|
assert list != nil
|
||||||
|
|
@ -84,6 +86,44 @@ proc replayStateChanges*(module: PSym; g: ModuleGraph) =
|
||||||
else:
|
else:
|
||||||
internalAssert g.config, false
|
internalAssert g.config, false
|
||||||
|
|
||||||
# of nkMethodDef:
|
proc replayGenericCacheInformation*(g: ModuleGraph; module: int) =
|
||||||
# methodDef(g, n[namePos].sym, fromCache=true)
|
## We remember the generic instantiations a module performed
|
||||||
|
## in order to to avoid the code bloat that generic code tends
|
||||||
|
## to imply. This is cheaper than deduplication of identical
|
||||||
|
## generic instantiations. However, deduplication is more
|
||||||
|
## powerful and general and I hope to implement it soon too
|
||||||
|
## (famous last words).
|
||||||
|
assert g.packed[module].status == loaded
|
||||||
|
for it in g.packed[module].fromDisk.typeInstCache:
|
||||||
|
let key = translateId(it[0], g.packed, module, g.config)
|
||||||
|
g.typeInstCache.mgetOrPut(key, @[]).add LazyType(id: FullId(module: module, packed: it[1]), typ: nil)
|
||||||
|
|
||||||
|
for it in mitems(g.packed[module].fromDisk.procInstCache):
|
||||||
|
let key = translateId(it.key, g.packed, module, g.config)
|
||||||
|
let sym = translateId(it.sym, g.packed, module, g.config)
|
||||||
|
var concreteTypes = newSeq[FullId](it.concreteTypes.len)
|
||||||
|
for i in 0..high(it.concreteTypes):
|
||||||
|
let tmp = translateId(it.concreteTypes[i], g.packed, module, g.config)
|
||||||
|
concreteTypes[i] = FullId(module: tmp.module, packed: it.concreteTypes[i])
|
||||||
|
|
||||||
|
g.procInstCache.mgetOrPut(key, @[]).add LazyInstantiation(
|
||||||
|
module: module, sym: FullId(module: sym.module, packed: it.sym),
|
||||||
|
concreteTypes: concreteTypes, inst: nil)
|
||||||
|
|
||||||
|
for it in mitems(g.packed[module].fromDisk.methodsPerType):
|
||||||
|
let key = translateId(it[0], g.packed, module, g.config)
|
||||||
|
let col = it[1]
|
||||||
|
let tmp = translateId(it[2], g.packed, module, g.config)
|
||||||
|
let symId = FullId(module: tmp.module, packed: it[2])
|
||||||
|
g.methodsPerType.mgetOrPut(key, @[]).add (col, LazySym(id: symId, sym: nil))
|
||||||
|
|
||||||
|
for it in mitems(g.packed[module].fromDisk.enumToStringProcs):
|
||||||
|
let key = translateId(it[0], g.packed, module, g.config)
|
||||||
|
let tmp = translateId(it[1], g.packed, module, g.config)
|
||||||
|
let symId = FullId(module: tmp.module, packed: it[1])
|
||||||
|
g.enumToStringProcs[key] = LazySym(id: symId, sym: nil)
|
||||||
|
|
||||||
|
for it in mitems(g.packed[module].fromDisk.methods):
|
||||||
|
let sym = loadSymFromId(g.config, g.cache, g.packed, module,
|
||||||
|
PackedItemId(module: LitId(0), item: it))
|
||||||
|
methodDef(g, g.idgen, sym)
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,11 @@ type
|
||||||
bodiesSection
|
bodiesSection
|
||||||
symsSection
|
symsSection
|
||||||
typesSection
|
typesSection
|
||||||
|
typeInstCacheSection
|
||||||
|
procInstCacheSection
|
||||||
|
attachedOpsSection
|
||||||
|
methodsPerTypeSection
|
||||||
|
enumToStringProcsSection
|
||||||
aliveSymsSection # beware, this is stored in a `.alivesyms` file.
|
aliveSymsSection # beware, this is stored in a `.alivesyms` file.
|
||||||
|
|
||||||
RodFileError* = enum
|
RodFileError* = enum
|
||||||
|
|
@ -73,6 +78,12 @@ proc storePrim*[T](f: var RodFile; x: T) =
|
||||||
elif T is tuple:
|
elif T is tuple:
|
||||||
for y in fields(x):
|
for y in fields(x):
|
||||||
storePrim(f, y)
|
storePrim(f, y)
|
||||||
|
elif T is object:
|
||||||
|
for y in fields(x):
|
||||||
|
when y is seq:
|
||||||
|
storeSeq(f, y)
|
||||||
|
else:
|
||||||
|
storePrim(f, y)
|
||||||
else:
|
else:
|
||||||
{.error: "unsupported type for 'storePrim'".}
|
{.error: "unsupported type for 'storePrim'".}
|
||||||
|
|
||||||
|
|
@ -107,6 +118,12 @@ proc loadPrim*[T](f: var RodFile; x: var T) =
|
||||||
elif T is tuple:
|
elif T is tuple:
|
||||||
for y in fields(x):
|
for y in fields(x):
|
||||||
loadPrim(f, y)
|
loadPrim(f, y)
|
||||||
|
elif T is object:
|
||||||
|
for y in fields(x):
|
||||||
|
when y is seq:
|
||||||
|
loadSeq(f, y)
|
||||||
|
else:
|
||||||
|
loadPrim(f, y)
|
||||||
else:
|
else:
|
||||||
{.error: "unsupported type for 'loadPrim'".}
|
{.error: "unsupported type for 'loadPrim'".}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,15 @@ type
|
||||||
exports*: seq[(LitId, int32)]
|
exports*: seq[(LitId, int32)]
|
||||||
reexports*: seq[(LitId, PackedItemId)]
|
reexports*: seq[(LitId, PackedItemId)]
|
||||||
compilerProcs*, trmacros*, converters*, pureEnums*: seq[(LitId, int32)]
|
compilerProcs*, trmacros*, converters*, pureEnums*: seq[(LitId, int32)]
|
||||||
methods*: seq[(LitId, PackedItemId, int32)]
|
methods*: seq[int32]
|
||||||
macroUsages*: seq[(PackedItemId, PackedLineInfo)]
|
macroUsages*: seq[(PackedItemId, PackedLineInfo)]
|
||||||
|
|
||||||
|
typeInstCache*: seq[(PackedItemId, PackedItemId)]
|
||||||
|
procInstCache*: seq[PackedInstantiation]
|
||||||
|
attachedOps*: seq[(TTypeAttachedOp, PackedItemId, PackedItemId)]
|
||||||
|
methodsPerType*: seq[(PackedItemId, int, PackedItemId)]
|
||||||
|
enumToStringProcs*: seq[(PackedItemId, PackedItemId)]
|
||||||
|
|
||||||
sh*: Shared
|
sh*: Shared
|
||||||
cfg: PackedConfig
|
cfg: PackedConfig
|
||||||
|
|
||||||
|
|
@ -160,9 +167,7 @@ proc addPureEnum*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
|
||||||
m.pureEnums.add((nameId, s.itemId.item))
|
m.pureEnums.add((nameId, s.itemId.item))
|
||||||
|
|
||||||
proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
|
proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
|
||||||
let nameId = getOrIncl(m.sh.strings, s.name.s)
|
m.methods.add s.itemId.item
|
||||||
discard "to do"
|
|
||||||
# c.m.methods.add((nameId, s.itemId.item))
|
|
||||||
|
|
||||||
proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
|
proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
|
||||||
let nameId = getOrIncl(m.sh.strings, s.name.s)
|
let nameId = getOrIncl(m.sh.strings, s.name.s)
|
||||||
|
|
@ -415,6 +420,17 @@ proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pa
|
||||||
toPackedNode(n[i], ir, c, m)
|
toPackedNode(n[i], ir, c, m)
|
||||||
ir.patch patchPos
|
ir.patch patchPos
|
||||||
|
|
||||||
|
proc storeInstantiation*(c: var PackedEncoder; m: var PackedModule; s: PSym; i: PInstantiation) =
|
||||||
|
var t = newSeq[PackedItemId](i.concreteTypes.len)
|
||||||
|
for j in 0..high(i.concreteTypes):
|
||||||
|
t[j] = storeTypeLater(i.concreteTypes[j], c, m)
|
||||||
|
m.procInstCache.add PackedInstantiation(key: storeSymLater(s, c, m),
|
||||||
|
sym: storeSymLater(i.sym, c, m),
|
||||||
|
concreteTypes: t)
|
||||||
|
|
||||||
|
proc storeTypeInst*(c: var PackedEncoder; m: var PackedModule; s: PSym; inst: PType) =
|
||||||
|
m.typeInstCache.add (storeSymLater(s, c, m), storeTypeLater(inst, c, m))
|
||||||
|
|
||||||
proc addPragmaComputation*(c: var PackedEncoder; m: var PackedModule; n: PNode) =
|
proc addPragmaComputation*(c: var PackedEncoder; m: var PackedModule; n: PNode) =
|
||||||
toPackedNode(n, m.toReplay, c, m)
|
toPackedNode(n, m.toReplay, c, m)
|
||||||
|
|
||||||
|
|
@ -436,20 +452,6 @@ proc toPackedNodeTopLevel*(n: PNode, encoder: var PackedEncoder; m: var PackedMo
|
||||||
toPackedNodeIgnoreProcDefs(n, encoder, m)
|
toPackedNodeIgnoreProcDefs(n, encoder, m)
|
||||||
flush encoder, m
|
flush encoder, m
|
||||||
|
|
||||||
proc storePrim*(f: var RodFile; x: PackedType) =
|
|
||||||
for y in fields(x):
|
|
||||||
when y is seq:
|
|
||||||
storeSeq(f, y)
|
|
||||||
else:
|
|
||||||
storePrim(f, y)
|
|
||||||
|
|
||||||
proc loadPrim*(f: var RodFile; x: var PackedType) =
|
|
||||||
for y in fields(x):
|
|
||||||
when y is seq:
|
|
||||||
loadSeq(f, y)
|
|
||||||
else:
|
|
||||||
loadPrim(f, y)
|
|
||||||
|
|
||||||
proc loadError(err: RodFileError; filename: AbsoluteFile) =
|
proc loadError(err: RodFileError; filename: AbsoluteFile) =
|
||||||
echo "Error: ", $err, "\nloading file: ", filename.string
|
echo "Error: ", $err, "\nloading file: ", filename.string
|
||||||
|
|
||||||
|
|
@ -503,6 +505,12 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef
|
||||||
loadSeqSection symsSection, m.sh.syms
|
loadSeqSection symsSection, m.sh.syms
|
||||||
loadSeqSection typesSection, m.sh.types
|
loadSeqSection typesSection, m.sh.types
|
||||||
|
|
||||||
|
loadSeqSection typeInstCacheSection, m.typeInstCache
|
||||||
|
loadSeqSection procInstCacheSection, m.procInstCache
|
||||||
|
loadSeqSection attachedOpsSection, m.attachedOps
|
||||||
|
loadSeqSection methodsPerTypeSection, m.methodsPerType
|
||||||
|
loadSeqSection enumToStringProcsSection, m.enumToStringProcs
|
||||||
|
|
||||||
close(f)
|
close(f)
|
||||||
result = f.err
|
result = f.err
|
||||||
|
|
||||||
|
|
@ -557,6 +565,13 @@ proc saveRodFile*(filename: AbsoluteFile; encoder: var PackedEncoder; m: var Pac
|
||||||
storeSeqSection symsSection, m.sh.syms
|
storeSeqSection symsSection, m.sh.syms
|
||||||
|
|
||||||
storeSeqSection typesSection, m.sh.types
|
storeSeqSection typesSection, m.sh.types
|
||||||
|
|
||||||
|
storeSeqSection typeInstCacheSection, m.typeInstCache
|
||||||
|
storeSeqSection procInstCacheSection, m.procInstCache
|
||||||
|
storeSeqSection attachedOpsSection, m.attachedOps
|
||||||
|
storeSeqSection methodsPerTypeSection, m.methodsPerType
|
||||||
|
storeSeqSection enumToStringProcsSection, m.enumToStringProcs
|
||||||
|
|
||||||
close(f)
|
close(f)
|
||||||
if f.err != ok:
|
if f.err != ok:
|
||||||
storeError(f.err, filename)
|
storeError(f.err, filename)
|
||||||
|
|
@ -902,6 +917,36 @@ proc loadProcBody*(config: ConfigRef, cache: IdentCache;
|
||||||
assert pos != emptyNodeId
|
assert pos != emptyNodeId
|
||||||
result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos)
|
result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos)
|
||||||
|
|
||||||
|
proc loadTypeFromId*(config: ConfigRef, cache: IdentCache;
|
||||||
|
g: var PackedModuleGraph; module: int; id: PackedItemId): PType =
|
||||||
|
result = g[module].types[id.item]
|
||||||
|
if result == nil:
|
||||||
|
var decoder = PackedDecoder(
|
||||||
|
lastModule: int32(-1),
|
||||||
|
lastLit: LitId(0),
|
||||||
|
lastFile: FileIndex(-1),
|
||||||
|
config: config,
|
||||||
|
cache: cache)
|
||||||
|
result = loadType(decoder, g, module, id)
|
||||||
|
|
||||||
|
proc loadSymFromId*(config: ConfigRef, cache: IdentCache;
|
||||||
|
g: var PackedModuleGraph; module: int; id: PackedItemId): PSym =
|
||||||
|
result = g[module].syms[id.item]
|
||||||
|
if result == nil:
|
||||||
|
var decoder = PackedDecoder(
|
||||||
|
lastModule: int32(-1),
|
||||||
|
lastLit: LitId(0),
|
||||||
|
lastFile: FileIndex(-1),
|
||||||
|
config: config,
|
||||||
|
cache: cache)
|
||||||
|
result = loadSym(decoder, g, module, id)
|
||||||
|
|
||||||
|
proc translateId*(id: PackedItemId; g: PackedModuleGraph; thisModule: int; config: ConfigRef): ItemId =
|
||||||
|
if id.module == LitId(0):
|
||||||
|
ItemId(module: thisModule.int32, item: id.item)
|
||||||
|
else:
|
||||||
|
ItemId(module: toFileIndex(id.module, g[thisModule].fromDisk, config).int32, item: id.item)
|
||||||
|
|
||||||
proc checkForHoles(m: PackedModule; config: ConfigRef; moduleId: int) =
|
proc checkForHoles(m: PackedModule; config: ConfigRef; moduleId: int) =
|
||||||
var bugs = 0
|
var bugs = 0
|
||||||
for i in 1 .. high(m.sh.syms):
|
for i in 1 .. high(m.sh.syms):
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
import ast, astalgo, intsets, tables, options, lineinfos, hashes, idents,
|
import ast, astalgo, intsets, tables, options, lineinfos, hashes, idents,
|
||||||
btrees, md5
|
btrees, md5
|
||||||
|
|
||||||
import ic / to_packed_ast
|
import ic / [packed_ast, to_packed_ast]
|
||||||
|
|
||||||
type
|
type
|
||||||
SigHash* = distinct MD5Digest
|
SigHash* = distinct MD5Digest
|
||||||
|
|
@ -31,15 +31,33 @@ type
|
||||||
opNot*, opContains*, opLe*, opLt*, opAnd*, opOr*, opIsNil*, opEq*: PSym
|
opNot*, opContains*, opLe*, opLt*, opAnd*, opOr*, opIsNil*, opEq*: PSym
|
||||||
opAdd*, opSub*, opMul*, opDiv*, opLen*: PSym
|
opAdd*, opSub*, opMul*, opDiv*, opLen*: PSym
|
||||||
|
|
||||||
|
FullId* = object
|
||||||
|
module*: int
|
||||||
|
packed*: PackedItemId
|
||||||
|
|
||||||
|
LazySym* = object
|
||||||
|
id*: FullId
|
||||||
|
sym*: PSym
|
||||||
|
|
||||||
|
LazyType* = object
|
||||||
|
id*: FullId
|
||||||
|
typ*: PType
|
||||||
|
|
||||||
|
LazyInstantiation* = object
|
||||||
|
module*: int
|
||||||
|
sym*: FullId
|
||||||
|
concreteTypes*: seq[FullId]
|
||||||
|
inst*: PInstantiation
|
||||||
|
|
||||||
ModuleGraph* = ref object
|
ModuleGraph* = ref object
|
||||||
ifaces*: seq[Iface] ## indexed by int32 fileIdx
|
ifaces*: seq[Iface] ## indexed by int32 fileIdx
|
||||||
packed*: PackedModuleGraph
|
packed*: PackedModuleGraph
|
||||||
|
|
||||||
typeInstCache*: Table[ItemId, seq[PType]] # A symbol's ItemId.
|
typeInstCache*: Table[ItemId, seq[LazyType]] # A symbol's ItemId.
|
||||||
procInstCache*: Table[ItemId, seq[PInstantiation]] # A symbol's ItemId.
|
procInstCache*: Table[ItemId, seq[LazyInstantiation]] # A symbol's ItemId.
|
||||||
attachedOps*: array[TTypeAttachedOp, Table[ItemId, PSym]] # Type ID, destructors, etc.
|
attachedOps*: array[TTypeAttachedOp, Table[ItemId, PSym]] # Type ID, destructors, etc.
|
||||||
methodsPerType*: Table[ItemId, seq[(int, PSym)]] # Type ID, attached methods
|
methodsPerType*: Table[ItemId, seq[(int, LazySym)]] # Type ID, attached methods
|
||||||
enumToStringProcs*: Table[ItemId, PSym]
|
enumToStringProcs*: Table[ItemId, LazySym]
|
||||||
|
|
||||||
startupPackedConfig*: PackedConfig
|
startupPackedConfig*: PackedConfig
|
||||||
packageSyms*: TStrTable
|
packageSyms*: TStrTable
|
||||||
|
|
@ -97,68 +115,6 @@ type
|
||||||
close: TPassClose,
|
close: TPassClose,
|
||||||
isFrontend: bool]
|
isFrontend: bool]
|
||||||
|
|
||||||
iterator typeInstCacheItems*(g: ModuleGraph; s: PSym): PType =
|
|
||||||
if g.typeInstCache.contains(s.itemId):
|
|
||||||
let x = addr(g.typeInstCache[s.itemId])
|
|
||||||
for t in x[]:
|
|
||||||
yield t
|
|
||||||
|
|
||||||
proc addToGenericCache*(g: ModuleGraph; module: int; s: PSym; inst: PType) =
|
|
||||||
g.typeInstCache.mgetOrPut(s.itemId, @[]).add inst
|
|
||||||
# XXX Also add to the packed module!
|
|
||||||
|
|
||||||
iterator procInstCacheItems*(g: ModuleGraph; s: PSym): PInstantiation =
|
|
||||||
if g.procInstCache.contains(s.itemId):
|
|
||||||
let x = addr(g.procInstCache[s.itemId])
|
|
||||||
for t in x[]:
|
|
||||||
yield t
|
|
||||||
|
|
||||||
proc addToGenericProcCache*(g: ModuleGraph; module: int; s: PSym; inst: PInstantiation) =
|
|
||||||
g.procInstCache.mgetOrPut(s.itemId, @[]).add inst
|
|
||||||
# XXX Also add to the packed module!
|
|
||||||
|
|
||||||
proc getAttachedOp*(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym =
|
|
||||||
## returns the requested attached operation for type `t`. Can return nil
|
|
||||||
## if no such operation exists.
|
|
||||||
result = g.attachedOps[op].getOrDefault(t.itemId)
|
|
||||||
|
|
||||||
proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
|
||||||
## we also need to record this to the packed module.
|
|
||||||
g.attachedOps[op][t.itemId] = value
|
|
||||||
# XXX Also add to the packed module!
|
|
||||||
|
|
||||||
proc setAttachedOpPartial*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
|
||||||
## we also need to record this to the packed module.
|
|
||||||
g.attachedOps[op][t.itemId] = value
|
|
||||||
# XXX Also add to the packed module!
|
|
||||||
|
|
||||||
proc completePartialOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
|
||||||
discard "To implement"
|
|
||||||
|
|
||||||
proc getToStringProc*(g: ModuleGraph; t: PType): PSym =
|
|
||||||
result = g.enumToStringProcs.getOrDefault(t.itemId)
|
|
||||||
assert result != nil
|
|
||||||
|
|
||||||
proc setToStringProc*(g: ModuleGraph; t: PType; value: PSym) =
|
|
||||||
g.enumToStringProcs[t.itemId] = value
|
|
||||||
|
|
||||||
iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) =
|
|
||||||
for a, b in items g.methodsPerType.getOrDefault(t.itemId):
|
|
||||||
yield (a, b)
|
|
||||||
|
|
||||||
proc addMethodToGeneric*(g: ModuleGraph; module: int; t: PType; col: int; m: PSym) =
|
|
||||||
g.methodsPerType.mgetOrPut(t.itemId, @[]).add (col, m)
|
|
||||||
|
|
||||||
proc hasDisabledAsgn*(g: ModuleGraph; t: PType): bool =
|
|
||||||
let op = getAttachedOp(g, t, attachedAsgn)
|
|
||||||
result = op != nil and sfError in op.flags
|
|
||||||
|
|
||||||
proc copyTypeProps*(g: ModuleGraph; module: int; dest, src: PType) =
|
|
||||||
for k in low(TTypeAttachedOp)..high(TTypeAttachedOp):
|
|
||||||
let op = getAttachedOp(g, src, k)
|
|
||||||
if op != nil:
|
|
||||||
setAttachedOp(g, module, dest, k, op)
|
|
||||||
|
|
||||||
const
|
const
|
||||||
cb64 = [
|
cb64 = [
|
||||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
|
||||||
|
|
@ -196,8 +152,11 @@ proc toBase64a(s: cstring, len: int): string =
|
||||||
template semtab*(m: PSym; g: ModuleGraph): TStrTable =
|
template semtab*(m: PSym; g: ModuleGraph): TStrTable =
|
||||||
g.ifaces[m.position].interf
|
g.ifaces[m.position].interf
|
||||||
|
|
||||||
proc cachedModule(g: ModuleGraph; m: PSym): bool {.inline.} =
|
proc isCachedModule(g: ModuleGraph; module: int): bool {.inline.} =
|
||||||
m.position < g.packed.len and g.packed[m.position].status == loaded
|
module < g.packed.len and g.packed[module].status == loaded
|
||||||
|
|
||||||
|
proc isCachedModule(g: ModuleGraph; m: PSym): bool {.inline.} =
|
||||||
|
isCachedModule(g, m.position)
|
||||||
|
|
||||||
proc simulateCachedModule*(g: ModuleGraph; moduleSym: PSym; m: PackedModule) =
|
proc simulateCachedModule*(g: ModuleGraph; moduleSym: PSym; m: PackedModule) =
|
||||||
when false:
|
when false:
|
||||||
|
|
@ -227,7 +186,7 @@ proc nextModuleIter*(mi: var ModuleIter; g: ModuleGraph): PSym =
|
||||||
result = nextIdentIter(mi.ti, g.ifaces[mi.modIndex].interf)
|
result = nextIdentIter(mi.ti, g.ifaces[mi.modIndex].interf)
|
||||||
|
|
||||||
iterator allSyms*(g: ModuleGraph; m: PSym): PSym =
|
iterator allSyms*(g: ModuleGraph; m: PSym): PSym =
|
||||||
if cachedModule(g, m):
|
if isCachedModule(g, m):
|
||||||
var rodIt: RodIter
|
var rodIt: RodIter
|
||||||
var r = initRodIterAllSyms(rodIt, g.config, g.cache, g.packed, FileIndex m.position)
|
var r = initRodIterAllSyms(rodIt, g.config, g.cache, g.packed, FileIndex m.position)
|
||||||
while r != nil:
|
while r != nil:
|
||||||
|
|
@ -239,7 +198,7 @@ iterator allSyms*(g: ModuleGraph; m: PSym): PSym =
|
||||||
yield s
|
yield s
|
||||||
|
|
||||||
proc someSym*(g: ModuleGraph; m: PSym; name: PIdent): PSym =
|
proc someSym*(g: ModuleGraph; m: PSym; name: PIdent): PSym =
|
||||||
if cachedModule(g, m):
|
if isCachedModule(g, m):
|
||||||
result = interfaceSymbol(g.config, g.cache, g.packed, FileIndex(m.position), name)
|
result = interfaceSymbol(g.config, g.cache, g.packed, FileIndex(m.position), name)
|
||||||
else:
|
else:
|
||||||
result = strTableGet(g.ifaces[m.position].interf, name)
|
result = strTableGet(g.ifaces[m.position].interf, name)
|
||||||
|
|
@ -254,6 +213,87 @@ iterator systemModuleSyms*(g: ModuleGraph; name: PIdent): PSym =
|
||||||
yield r
|
yield r
|
||||||
r = nextModuleIter(mi, g)
|
r = nextModuleIter(mi, g)
|
||||||
|
|
||||||
|
proc resolveType(g: ModuleGraph; t: var LazyType): PType =
|
||||||
|
result = t.typ
|
||||||
|
if result == nil and isCachedModule(g, t.id.module):
|
||||||
|
result = loadTypeFromId(g.config, g.cache, g.packed, t.id.module, t.id.packed)
|
||||||
|
t.typ = result
|
||||||
|
assert result != nil
|
||||||
|
|
||||||
|
proc resolveSym(g: ModuleGraph; t: var LazySym): PSym =
|
||||||
|
result = t.sym
|
||||||
|
if result == nil and isCachedModule(g, t.id.module):
|
||||||
|
result = loadSymFromId(g.config, g.cache, g.packed, t.id.module, t.id.packed)
|
||||||
|
t.sym = result
|
||||||
|
assert result != nil
|
||||||
|
|
||||||
|
proc resolveInst(g: ModuleGraph; t: var LazyInstantiation): PInstantiation =
|
||||||
|
result = t.inst
|
||||||
|
if result == nil and isCachedModule(g, t.module):
|
||||||
|
result = PInstantiation(sym: loadSymFromId(g.config, g.cache, g.packed, t.sym.module, t.sym.packed))
|
||||||
|
result.concreteTypes = newSeq[PType](t.concreteTypes.len)
|
||||||
|
for i in 0..high(result.concreteTypes):
|
||||||
|
result.concreteTypes[i] = loadTypeFromId(g.config, g.cache, g.packed,
|
||||||
|
t.concreteTypes[i].module, t.concreteTypes[i].packed)
|
||||||
|
t.inst = result
|
||||||
|
assert result != nil
|
||||||
|
|
||||||
|
iterator typeInstCacheItems*(g: ModuleGraph; s: PSym): PType =
|
||||||
|
if g.typeInstCache.contains(s.itemId):
|
||||||
|
let x = addr(g.typeInstCache[s.itemId])
|
||||||
|
for t in mitems(x[]):
|
||||||
|
yield resolveType(g, t)
|
||||||
|
|
||||||
|
iterator procInstCacheItems*(g: ModuleGraph; s: PSym): PInstantiation =
|
||||||
|
if g.procInstCache.contains(s.itemId):
|
||||||
|
let x = addr(g.procInstCache[s.itemId])
|
||||||
|
for t in mitems(x[]):
|
||||||
|
yield resolveInst(g, t)
|
||||||
|
|
||||||
|
proc getAttachedOp*(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym =
|
||||||
|
## returns the requested attached operation for type `t`. Can return nil
|
||||||
|
## if no such operation exists.
|
||||||
|
result = g.attachedOps[op].getOrDefault(t.itemId)
|
||||||
|
|
||||||
|
proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
||||||
|
## we also need to record this to the packed module.
|
||||||
|
g.attachedOps[op][t.itemId] = value
|
||||||
|
# XXX Also add to the packed module!
|
||||||
|
|
||||||
|
proc setAttachedOpPartial*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
||||||
|
## we also need to record this to the packed module.
|
||||||
|
g.attachedOps[op][t.itemId] = value
|
||||||
|
# XXX Also add to the packed module!
|
||||||
|
|
||||||
|
proc completePartialOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
|
||||||
|
discard "To implement"
|
||||||
|
|
||||||
|
proc getToStringProc*(g: ModuleGraph; t: PType): PSym =
|
||||||
|
result = resolveSym(g, g.enumToStringProcs[t.itemId])
|
||||||
|
assert result != nil
|
||||||
|
|
||||||
|
proc setToStringProc*(g: ModuleGraph; t: PType; value: PSym) =
|
||||||
|
g.enumToStringProcs[t.itemId] = LazySym(sym: value)
|
||||||
|
|
||||||
|
iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) =
|
||||||
|
if g.methodsPerType.contains(t.itemId):
|
||||||
|
for it in mitems g.methodsPerType[t.itemId]:
|
||||||
|
yield (it[0], resolveSym(g, it[1]))
|
||||||
|
|
||||||
|
proc addMethodToGeneric*(g: ModuleGraph; module: int; t: PType; col: int; m: PSym) =
|
||||||
|
g.methodsPerType.mgetOrPut(t.itemId, @[]).add (col, LazySym(sym: m))
|
||||||
|
|
||||||
|
proc hasDisabledAsgn*(g: ModuleGraph; t: PType): bool =
|
||||||
|
let op = getAttachedOp(g, t, attachedAsgn)
|
||||||
|
result = op != nil and sfError in op.flags
|
||||||
|
|
||||||
|
proc copyTypeProps*(g: ModuleGraph; module: int; dest, src: PType) =
|
||||||
|
for k in low(TTypeAttachedOp)..high(TTypeAttachedOp):
|
||||||
|
let op = getAttachedOp(g, src, k)
|
||||||
|
if op != nil:
|
||||||
|
setAttachedOp(g, module, dest, k, op)
|
||||||
|
|
||||||
|
|
||||||
proc `$`*(u: SigHash): string =
|
proc `$`*(u: SigHash): string =
|
||||||
toBase64a(cast[cstring](unsafeAddr u), sizeof(u))
|
toBase64a(cast[cstring](unsafeAddr u), sizeof(u))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
|
||||||
else:
|
else:
|
||||||
partialInitModule(result, graph, fileIdx, filename)
|
partialInitModule(result, graph, fileIdx, filename)
|
||||||
replayStateChanges(result, graph)
|
replayStateChanges(result, graph)
|
||||||
|
replayGenericCacheInformation(graph, fileIdx.int)
|
||||||
elif graph.isDirty(result):
|
elif graph.isDirty(result):
|
||||||
result.flags.excl sfDirty
|
result.flags.excl sfDirty
|
||||||
# reset module fields:
|
# reset module fields:
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
## This module contains the data structures for the semantic checking phase.
|
## This module contains the data structures for the semantic checking phase.
|
||||||
|
|
||||||
|
import std / tables
|
||||||
|
|
||||||
import
|
import
|
||||||
intsets, options, ast, astalgo, msgs, idents, renderer,
|
intsets, options, ast, astalgo, msgs, idents, renderer,
|
||||||
magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils
|
magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils
|
||||||
|
|
@ -551,6 +553,16 @@ proc storeRodNode*(c: PContext, n: PNode) =
|
||||||
if c.config.symbolFiles != disabledSf:
|
if c.config.symbolFiles != disabledSf:
|
||||||
toPackedNodeTopLevel(n, c.encoder, c.packedRepr)
|
toPackedNodeTopLevel(n, c.encoder, c.packedRepr)
|
||||||
|
|
||||||
|
proc addToGenericProcCache*(c: PContext; s: PSym; inst: PInstantiation) =
|
||||||
|
c.graph.procInstCache.mgetOrPut(s.itemId, @[]).add LazyInstantiation(module: c.module.position, inst: inst)
|
||||||
|
if c.config.symbolFiles != disabledSf:
|
||||||
|
storeInstantiation(c.encoder, c.packedRepr, s, inst)
|
||||||
|
|
||||||
|
proc addToGenericCache*(c: PContext; s: PSym; inst: PType) =
|
||||||
|
c.graph.typeInstCache.mgetOrPut(s.itemId, @[]).add LazyType(typ: inst)
|
||||||
|
if c.config.symbolFiles != disabledSf:
|
||||||
|
storeTypeInst(c.encoder, c.packedRepr, s, inst)
|
||||||
|
|
||||||
proc saveRodFile*(c: PContext) =
|
proc saveRodFile*(c: PContext) =
|
||||||
if c.config.symbolFiles != disabledSf:
|
if c.config.symbolFiles != disabledSf:
|
||||||
for (m, n) in PCtx(c.graph.vm).vmstateDiff:
|
for (m, n) in PCtx(c.graph.vm).vmstateDiff:
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
#if c.compilesContextId == 0:
|
#if c.compilesContextId == 0:
|
||||||
rawHandleSelf(c, result)
|
rawHandleSelf(c, result)
|
||||||
entry.compilesId = c.compilesContextId
|
entry.compilesId = c.compilesContextId
|
||||||
addToGenericProcCache(c.graph, c.module.position, fn, entry)
|
addToGenericProcCache(c, fn, entry)
|
||||||
c.generics.add(makeInstPair(fn, entry))
|
c.generics.add(makeInstPair(fn, entry))
|
||||||
if n[pragmasPos].kind != nkEmpty:
|
if n[pragmasPos].kind != nkEmpty:
|
||||||
pragma(c, result, n[pragmasPos], allRoutinePragmas)
|
pragma(c, result, n[pragmasPos], allRoutinePragmas)
|
||||||
|
|
|
||||||
|
|
@ -1814,7 +1814,7 @@ proc hasObjParam(s: PSym): bool =
|
||||||
|
|
||||||
proc finishMethod(c: PContext, s: PSym) =
|
proc finishMethod(c: PContext, s: PSym) =
|
||||||
if hasObjParam(s):
|
if hasObjParam(s):
|
||||||
methodDef(c.graph, c.idgen, s, false)
|
methodDef(c.graph, c.idgen, s)
|
||||||
|
|
||||||
proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
||||||
if isGenericRoutine(s):
|
if isGenericRoutine(s):
|
||||||
|
|
@ -1839,7 +1839,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
||||||
# no sense either.
|
# no sense either.
|
||||||
# and result[bodyPos].kind != nkEmpty:
|
# and result[bodyPos].kind != nkEmpty:
|
||||||
if hasObjParam(s):
|
if hasObjParam(s):
|
||||||
methodDef(c.graph, c.idgen, s, fromCache=false)
|
methodDef(c.graph, c.idgen, s)
|
||||||
else:
|
else:
|
||||||
localError(c.config, n.info, "'method' needs a parameter that has an object type")
|
localError(c.config, n.info, "'method' needs a parameter that has an object type")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,12 +54,12 @@ proc searchInstTypes*(g: ModuleGraph; key: PType): PType =
|
||||||
|
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
proc cacheTypeInst(g: ModuleGraph; moduleId: int; inst: PType) =
|
proc cacheTypeInst(c: PContext; inst: PType) =
|
||||||
let gt = inst[0]
|
let gt = inst[0]
|
||||||
let t = if gt.kind == tyGenericBody: gt.lastSon else: gt
|
let t = if gt.kind == tyGenericBody: gt.lastSon else: gt
|
||||||
if t.kind in {tyStatic, tyError, tyGenericParam} + tyTypeClasses:
|
if t.kind in {tyStatic, tyError, tyGenericParam} + tyTypeClasses:
|
||||||
return
|
return
|
||||||
addToGenericCache(g, moduleId, gt.sym, inst)
|
addToGenericCache(c, gt.sym, inst)
|
||||||
|
|
||||||
type
|
type
|
||||||
LayeredIdTable* = ref object
|
LayeredIdTable* = ref object
|
||||||
|
|
@ -323,7 +323,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
var body = t[0]
|
var body = t[0]
|
||||||
if body.kind != tyGenericBody:
|
if body.kind != tyGenericBody:
|
||||||
internalError(cl.c.config, cl.info, "no generic body")
|
internalError(cl.c.config, cl.info, "no generic body")
|
||||||
var header: PType = t
|
var header = t
|
||||||
# search for some instantiation here:
|
# search for some instantiation here:
|
||||||
if cl.allowMetaTypes:
|
if cl.allowMetaTypes:
|
||||||
result = PType(idTableGet(cl.localCache, t))
|
result = PType(idTableGet(cl.localCache, t))
|
||||||
|
|
@ -364,7 +364,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||||
# we need to add the candidate here, before it's fully instantiated for
|
# we need to add the candidate here, before it's fully instantiated for
|
||||||
# recursive instantions:
|
# recursive instantions:
|
||||||
if not cl.allowMetaTypes:
|
if not cl.allowMetaTypes:
|
||||||
cacheTypeInst(cl.c.graph, cl.c.module.position, result)
|
cacheTypeInst(cl.c, result)
|
||||||
else:
|
else:
|
||||||
idTablePut(cl.localCache, t, result)
|
idTablePut(cl.localCache, t, result)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue