mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-17 21:12:42 +00:00
big steps torwards an efficient, simple IC implementation (#16543)
* reworked ID handling * the packed AST now has its own ID mechanism * basic serialization code works * extract rodfiles to its own module * rodfiles: store and compare configs * rodfiles: store dependencies * store config at the end * precise dependency tracking * dependency tracking for rodfiles * completed loading of PSym, PType, etc * removed dead code * bugfix: do not realloc seqs when taking addr into an element * make IC opt-in for now * makes tcompilerapi green again * final cleanups Co-authored-by: Andy Davidoff <github@andy.disruptek.com>
This commit is contained in:
@@ -1074,18 +1074,35 @@ template id*(a: PIdObj): int =
|
||||
(x.itemId.module.int shl moduleShift) + x.itemId.item.int
|
||||
|
||||
type
|
||||
IdGenerator* = ref ItemId # unfortunately, we really need the 'shared mutable' aspect here.
|
||||
IdGenerator* = ref object # unfortunately, we really need the 'shared mutable' aspect here.
|
||||
module*: int32
|
||||
symId*: int32
|
||||
typeId*: int32
|
||||
|
||||
proc hash*(x: ItemId): Hash =
|
||||
var h: Hash = hash(x.module)
|
||||
h = h !& hash(x.item)
|
||||
result = !$h
|
||||
|
||||
const
|
||||
PackageModuleId* = -3'i32
|
||||
|
||||
proc idGeneratorFromModule*(m: PSym): IdGenerator =
|
||||
assert m.kind == skModule
|
||||
result = IdGenerator(module: m.itemId.module, item: m.itemId.item)
|
||||
result = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0)
|
||||
|
||||
proc nextId*(x: IdGenerator): ItemId {.inline.} =
|
||||
inc x.item
|
||||
result = x[]
|
||||
proc nextSymId*(x: IdGenerator): ItemId {.inline.} =
|
||||
inc x.symId
|
||||
result = ItemId(module: x.module, item: x.symId)
|
||||
|
||||
proc nextTypeId*(x: IdGenerator): ItemId {.inline.} =
|
||||
inc x.typeId
|
||||
result = ItemId(module: x.module, item: x.typeId)
|
||||
|
||||
when false:
|
||||
proc nextId*(x: IdGenerator): ItemId {.inline.} =
|
||||
inc x.item
|
||||
result = x[]
|
||||
|
||||
when false:
|
||||
proc storeBack*(dest: var IdGenerator; src: IdGenerator) {.inline.} =
|
||||
@@ -1831,7 +1848,7 @@ proc toVar*(typ: PType; kind: TTypeKind; idgen: IdGenerator): PType =
|
||||
## returned. Otherwise ``typ`` is simply returned as-is.
|
||||
result = typ
|
||||
if typ.kind != kind:
|
||||
result = newType(kind, nextId(idgen), typ.owner)
|
||||
result = newType(kind, nextTypeId(idgen), typ.owner)
|
||||
rawAddSon(result, typ)
|
||||
|
||||
proc toRef*(typ: PType; idgen: IdGenerator): PType =
|
||||
@@ -1839,7 +1856,7 @@ proc toRef*(typ: PType; idgen: IdGenerator): PType =
|
||||
## returned. Otherwise ``typ`` is simply returned as-is.
|
||||
result = typ
|
||||
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
|
||||
result = newType(tyRef, nextId(idgen), typ.owner)
|
||||
result = newType(tyRef, nextTypeId(idgen), typ.owner)
|
||||
rawAddSon(result, typ)
|
||||
|
||||
proc toObject*(typ: PType): PType =
|
||||
|
||||
@@ -1772,7 +1772,7 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
else: internalError(p.config, e.info, "genArrayLen()")
|
||||
|
||||
proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
|
||||
result = newType(tyPtr, nextId idgen, baseType.owner)
|
||||
result = newType(tyPtr, nextTypeId idgen, baseType.owner)
|
||||
addSonSkipIntLit(result, baseType, idgen)
|
||||
|
||||
proc makeAddr(n: PNode; idgen: IdGenerator): PNode =
|
||||
|
||||
@@ -1267,9 +1267,9 @@ proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
|
||||
|
||||
proc fakeClosureType(m: BModule; owner: PSym): PType =
|
||||
# we generate the same RTTI as for a tuple[pointer, ref tuple[]]
|
||||
result = newType(tyTuple, nextId m.idgen, owner)
|
||||
result.rawAddSon(newType(tyPointer, nextId m.idgen, owner))
|
||||
var r = newType(tyRef, nextId m.idgen, owner)
|
||||
result = newType(tyTuple, nextTypeId m.idgen, owner)
|
||||
result.rawAddSon(newType(tyPointer, nextTypeId m.idgen, owner))
|
||||
var r = newType(tyRef, nextTypeId m.idgen, owner)
|
||||
let obj = createObj(m.g.graph, m.idgen, owner, owner.info, final=false)
|
||||
r.rawAddSon(obj)
|
||||
result.rawAddSon(r)
|
||||
@@ -1396,9 +1396,9 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
|
||||
result = prefixTI.rope & result & ")".rope
|
||||
|
||||
proc openArrayToTuple(m: BModule; t: PType): PType =
|
||||
result = newType(tyTuple, nextId m.idgen, t.owner)
|
||||
let p = newType(tyPtr, nextId m.idgen, t.owner)
|
||||
let a = newType(tyUncheckedArray, nextId m.idgen, t.owner)
|
||||
result = newType(tyTuple, nextTypeId m.idgen, t.owner)
|
||||
let p = newType(tyPtr, nextTypeId m.idgen, t.owner)
|
||||
let a = newType(tyUncheckedArray, nextTypeId m.idgen, t.owner)
|
||||
a.add t.lastSon
|
||||
p.add a
|
||||
result.add p
|
||||
|
||||
@@ -108,10 +108,10 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) =
|
||||
s.ast[dispatcherPos] = dispatcher
|
||||
|
||||
proc createDispatcher(s: PSym; idgen: IdGenerator): PSym =
|
||||
var disp = copySym(s, nextId(idgen))
|
||||
var disp = copySym(s, nextSymId(idgen))
|
||||
incl(disp.flags, sfDispatcher)
|
||||
excl(disp.flags, sfExported)
|
||||
disp.typ = copyType(disp.typ, nextId(idgen), disp.typ.owner)
|
||||
disp.typ = copyType(disp.typ, nextTypeId(idgen), disp.typ.owner)
|
||||
# we can't inline the dispatcher itself (for now):
|
||||
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
|
||||
disp.ast = copyTree(s.ast)
|
||||
@@ -119,7 +119,7 @@ proc createDispatcher(s: PSym; idgen: IdGenerator): PSym =
|
||||
disp.loc.r = nil
|
||||
if s.typ[0] != nil:
|
||||
if disp.ast.len > resultPos:
|
||||
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextId(idgen))
|
||||
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextSymId(idgen))
|
||||
else:
|
||||
# We've encountered a method prototype without a filled-in
|
||||
# resultPos slot. We put a placeholder in there that will
|
||||
|
||||
@@ -177,7 +177,7 @@ proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode =
|
||||
ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
|
||||
|
||||
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, name), nextId(ctx.idgen), ctx.fn, ctx.fn.info)
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, name), nextSymId(ctx.idgen), ctx.fn, ctx.fn.info)
|
||||
result.typ = typ
|
||||
assert(not typ.isNil)
|
||||
|
||||
@@ -1118,9 +1118,9 @@ proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode=
|
||||
n[i] = ctx.skipThroughEmptyStates(n[i])
|
||||
|
||||
proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: PSym): PType =
|
||||
result = newType(tyArray, nextId(idgen), owner)
|
||||
result = newType(tyArray, nextTypeId(idgen), owner)
|
||||
|
||||
let rng = newType(tyRange, nextId(idgen), owner)
|
||||
let rng = newType(tyRange, nextTypeId(idgen), owner)
|
||||
rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n))
|
||||
rng.rawAddSon(t)
|
||||
|
||||
@@ -1314,7 +1314,7 @@ proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
|
||||
let idefs = copyNode(it)
|
||||
for v in 0..it.len-3:
|
||||
if it[v].kind == nkSym:
|
||||
let x = copySym(it[v].sym, nextId(c.idgen))
|
||||
let x = copySym(it[v].sym, nextSymId(c.idgen))
|
||||
c.tab[it[v].sym.id] = x
|
||||
idefs.add newSymNode(x)
|
||||
else:
|
||||
@@ -1393,9 +1393,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
# Lambda lifting was not done yet. Use temporary :state sym, which will
|
||||
# be handled specially by lambda lifting. Local temp vars (if needed)
|
||||
# should follow the same logic.
|
||||
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), nextId(idgen), fn, fn.info)
|
||||
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), nextSymId(idgen), fn, fn.info)
|
||||
ctx.stateVarSym.typ = g.createClosureIterStateType(fn, idgen)
|
||||
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), nextId(idgen), fn, fn.info)
|
||||
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), nextSymId(idgen), fn, fn.info)
|
||||
var pc = PreprocessContext(finallys: @[], config: g.config, idgen: idgen)
|
||||
var n = preprocess(pc, n.toStmtList)
|
||||
#echo "transformed into ", n
|
||||
|
||||
@@ -31,7 +31,6 @@ import
|
||||
wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
|
||||
pathutils, strtabs
|
||||
|
||||
from incremental import nimIncremental
|
||||
from ast import eqTypeFlags, tfGcSafe, tfNoSideEffect
|
||||
|
||||
# but some have deps to imported modules. Yay.
|
||||
@@ -799,10 +798,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
helpOnError(conf, pass)
|
||||
of "symbolfiles": discard "ignore for backwards compat"
|
||||
of "incremental":
|
||||
when not nimIncremental:
|
||||
localError(conf, info, "the compiler was not built with " &
|
||||
"incremental compilation features; bootstrap with " &
|
||||
"-d:nimIncremental to enable")
|
||||
case arg.normalize
|
||||
of "on": conf.symbolFiles = v2Sf
|
||||
of "off": conf.symbolFiles = disabledSf
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
import ast, idents, lineinfos, modulegraphs, magicsys
|
||||
|
||||
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||
result = newSym(skProc, getIdent(g.cache, "$"), nextId idgen, t.owner, info)
|
||||
result = newSym(skProc, getIdent(g.cache, "$"), nextSymId idgen, t.owner, info)
|
||||
|
||||
let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info)
|
||||
let dest = newSym(skParam, getIdent(g.cache, "e"), nextSymId idgen, result, info)
|
||||
dest.typ = t
|
||||
|
||||
let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info)
|
||||
let res = newSym(skResult, getIdent(g.cache, "result"), nextSymId idgen, result, info)
|
||||
res.typ = getSysType(g, info, tyString)
|
||||
|
||||
result.typ = newType(tyProc, nextId idgen, t.owner)
|
||||
result.typ = newType(tyProc, nextTypeId idgen, t.owner)
|
||||
result.typ.n = newNodeI(nkFormalParams, info)
|
||||
rawAddSon(result.typ, res.typ)
|
||||
result.typ.n.add newNodeI(nkEffectList, info)
|
||||
@@ -63,15 +63,15 @@ proc searchObjCase(t: PType; field: PSym): PNode =
|
||||
doAssert result != nil
|
||||
|
||||
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
|
||||
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), nextId idgen, t.owner, info)
|
||||
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), nextSymId idgen, t.owner, info)
|
||||
|
||||
let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info)
|
||||
let dest = newSym(skParam, getIdent(g.cache, "e"), nextSymId idgen, result, info)
|
||||
dest.typ = field.typ
|
||||
|
||||
let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info)
|
||||
let res = newSym(skResult, getIdent(g.cache, "result"), nextSymId idgen, result, info)
|
||||
res.typ = getSysType(g, info, tyUInt8)
|
||||
|
||||
result.typ = newType(tyProc, nextId idgen, t.owner)
|
||||
result.typ = newType(tyProc, nextTypeId idgen, t.owner)
|
||||
result.typ.n = newNodeI(nkFormalParams, info)
|
||||
rawAddSon(result.typ, res.typ)
|
||||
result.typ.n.add newNodeI(nkEffectList, info)
|
||||
|
||||
@@ -49,7 +49,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
internalAssert c.config, sfGenSym in s.flags or s.kind == skType
|
||||
var x = PSym(idTableGet(c.mapping, s))
|
||||
if x == nil:
|
||||
x = copySym(s, nextId(c.idgen))
|
||||
x = copySym(s, nextSymId(c.idgen))
|
||||
# sem'check needs to set the owner properly later, see bug #9476
|
||||
x.owner = nil # c.genSymOwner
|
||||
#if x.kind == skParam and x.owner.kind == skModule:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## A BiTable is a table that can be seen as an optimized pair
|
||||
## of (Table[LitId, Val], Table[Val, LitId]).
|
||||
|
||||
import hashes
|
||||
import hashes, rodfiles
|
||||
|
||||
type
|
||||
LitId* = distinct uint32
|
||||
@@ -30,7 +30,9 @@ proc mustRehash(length, counter: int): bool {.inline.} =
|
||||
result = (length * 2 < counter * 3) or (length - counter < 4)
|
||||
|
||||
const
|
||||
idStart = 256 # Ids do not start with 0 but with this value. The IR needs it.
|
||||
idStart = 256 ##
|
||||
## Ids do not start with 0 but with this value. The IR needs it.
|
||||
## TODO: explain why
|
||||
|
||||
template idToIdx(x: LitId): int = x.int - idStart
|
||||
|
||||
@@ -94,6 +96,21 @@ proc `[]`*[T](t: BiTable[T]; LitId: LitId): lent T {.inline.} =
|
||||
assert idx < t.vals.len
|
||||
result = t.vals[idx]
|
||||
|
||||
proc hash*[T](t: BiTable[T]): Hash =
|
||||
## as the keys are hashes of the values, we simply use them instead
|
||||
var h: Hash = 0
|
||||
for i, n in pairs t.keys:
|
||||
h = h !& hash((i, n))
|
||||
result = !$h
|
||||
|
||||
proc store*[T](f: var RodFile; t: BiTable[T]) =
|
||||
storeSeq(f, t.vals)
|
||||
storeSeq(f, t.keys)
|
||||
|
||||
proc load*[T](f: var RodFile; t: var BiTable[T]) =
|
||||
loadSeq(f, t.vals)
|
||||
loadSeq(f, t.keys)
|
||||
|
||||
when isMainModule:
|
||||
|
||||
var t: BiTable[string]
|
||||
@@ -113,7 +130,35 @@ when isMainModule:
|
||||
|
||||
for i in 0 ..< 100_000:
|
||||
assert t.getOrIncl($i & "___" & $i).idToIdx == i + 4
|
||||
echo "begin"
|
||||
echo t.vals.len
|
||||
|
||||
echo t.vals[0]
|
||||
echo t.vals[1004]
|
||||
|
||||
echo "middle"
|
||||
|
||||
var tf: BiTable[float]
|
||||
|
||||
discard tf.getOrIncl(0.4)
|
||||
discard tf.getOrIncl(16.4)
|
||||
discard tf.getOrIncl(32.4)
|
||||
echo getKeyId(tf, 32.4)
|
||||
|
||||
var f2 = open("testblah.bin", fmWrite)
|
||||
echo store(f2, tf)
|
||||
f2.close
|
||||
|
||||
var f1 = open("testblah.bin", fmRead)
|
||||
|
||||
var t2: BiTable[float]
|
||||
|
||||
echo f1.load(t2)
|
||||
echo t2.vals.len
|
||||
|
||||
echo getKeyId(t2, 32.4)
|
||||
|
||||
echo "end"
|
||||
|
||||
|
||||
f1.close
|
||||
|
||||
@@ -29,14 +29,13 @@ mechanism needs to be implemented that we could get wrong. ModuleIds
|
||||
are rod-file specific too.
|
||||
|
||||
|
||||
Configuration setup changes
|
||||
---------------------------
|
||||
|
||||
For a MVP these are not detected. Later the configuration will be
|
||||
stored in every `.rod` file.
|
||||
|
||||
|
||||
Global state
|
||||
------------
|
||||
|
||||
Global persistent state will be kept in a project specific `.rod` file.
|
||||
|
||||
Rod File Format
|
||||
---------------
|
||||
|
||||
It's a simple binary file format. `rodfiles.nim` contains some details.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2020 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import std / [hashes, tables]
|
||||
import bitabs
|
||||
import ".." / [ast, lineinfos, options, pathutils]
|
||||
@@ -12,9 +12,9 @@
|
||||
## use this representation directly in all the transformations,
|
||||
## it is superior.
|
||||
|
||||
import std / [hashes, tables]
|
||||
import std / [hashes, tables, strtabs, md5]
|
||||
import bitabs
|
||||
import ".." / [ast, lineinfos, options, pathutils]
|
||||
import ".." / [ast, options]
|
||||
|
||||
const
|
||||
localNamePos* = 0
|
||||
@@ -39,16 +39,29 @@ const
|
||||
routineBodyPos* = 7
|
||||
|
||||
const
|
||||
nkModuleRef = nkNone # pair of (ModuleId, SymId)
|
||||
nkModuleRef* = nkNone # pair of (ModuleId, SymId)
|
||||
|
||||
type
|
||||
SymId* = distinct int32
|
||||
TypeId* = distinct int32
|
||||
ModuleId* = distinct int32
|
||||
NodePos* = distinct int
|
||||
|
||||
NodeId* = distinct int32
|
||||
|
||||
PackedItemId* = object
|
||||
module*: LitId # 0 if it's this module
|
||||
item*: int32 # same as the in-memory representation
|
||||
|
||||
TypeId* = PackedItemId
|
||||
|
||||
const
|
||||
nilTypeId* = PackedItemId(module: LitId(0), item: -1.int32)
|
||||
nilItemId* = PackedItemId(module: LitId(0), item: -1.int32)
|
||||
|
||||
const
|
||||
emptyNodeId* = NodeId(-1)
|
||||
|
||||
type
|
||||
PackedLineInfo* = object
|
||||
line*: uint16
|
||||
col*: int16
|
||||
@@ -64,13 +77,13 @@ type
|
||||
PackedSym* = object
|
||||
kind*: TSymKind
|
||||
name*: LitId
|
||||
typeId*: TypeId
|
||||
typ*: TypeId
|
||||
flags*: TSymFlags
|
||||
magic*: TMagic
|
||||
info*: PackedLineInfo
|
||||
ast*: NodePos
|
||||
owner*: ItemId
|
||||
guard*: ItemId
|
||||
ast*: NodeId
|
||||
owner*: PackedItemId
|
||||
guard*: PackedItemId
|
||||
bitsize*: int
|
||||
alignment*: int # for alignment
|
||||
options*: TOptions
|
||||
@@ -84,25 +97,25 @@ type
|
||||
|
||||
PackedType* = object
|
||||
kind*: TTypeKind
|
||||
nodekind*: TNodeKind
|
||||
callConv*: TCallingConvention
|
||||
#nodekind*: TNodeKind
|
||||
flags*: TTypeFlags
|
||||
types*: int32
|
||||
nodes*: int32
|
||||
methods*: int32
|
||||
nodeflags*: TNodeFlags
|
||||
info*: PackedLineInfo
|
||||
sym*: ItemId
|
||||
owner*: ItemId
|
||||
attachedOps*: array[TTypeAttachedOp, ItemId]
|
||||
types*: seq[TypeId]
|
||||
n*: NodeId
|
||||
methods*: seq[(int, PackedItemId)]
|
||||
#nodeflags*: TNodeFlags
|
||||
sym*: PackedItemId
|
||||
owner*: PackedItemId
|
||||
attachedOps*: array[TTypeAttachedOp, PackedItemId]
|
||||
size*: BiggestInt
|
||||
align*: int16
|
||||
paddingAtEnd*: int16
|
||||
lockLevel*: TLockLevel # lock level as required for deadlock checking
|
||||
# not serialized: loc*: TLoc because it is backend-specific
|
||||
typeInst*: TypeId
|
||||
nonUniqueId*: ItemId
|
||||
nonUniqueId*: int32
|
||||
|
||||
Node* = object # 20 bytes
|
||||
PackedNode* = object # 20 bytes
|
||||
kind*: TNodeKind
|
||||
flags*: TNodeFlags
|
||||
operand*: int32 # for kind in {nkSym, nkSymDef}: SymId
|
||||
@@ -115,72 +128,73 @@ type
|
||||
ModulePhase* = enum
|
||||
preLookup, lookedUpTopLevelStmts
|
||||
|
||||
Module* = object
|
||||
GenericKey* = object
|
||||
module*: int32
|
||||
name*: string
|
||||
file*: AbsoluteFile
|
||||
ast*: PackedTree
|
||||
phase*: ModulePhase
|
||||
iface*: Table[string, seq[SymId]] # 'seq' because of overloading
|
||||
types*: seq[MD5Digest] # is this a joke?
|
||||
|
||||
Program* = ref object
|
||||
modules*: seq[Module]
|
||||
PackedTree* = object ## usually represents a full Nim module
|
||||
nodes*: seq[PackedNode]
|
||||
#sh*: Shared
|
||||
|
||||
Shared* = ref object # shared between different versions of 'Module'.
|
||||
# (though there is always exactly one valid
|
||||
# version of a module)
|
||||
syms*: seq[PackedSym]
|
||||
types*: seq[seq[Node]]
|
||||
types*: seq[PackedType]
|
||||
strings*: BiTable[string] # we could share these between modules.
|
||||
integers*: BiTable[BiggestInt]
|
||||
floats*: BiTable[BiggestFloat]
|
||||
config*: ConfigRef
|
||||
#thisModule*: ModuleId
|
||||
#program*: Program
|
||||
#config*: ConfigRef
|
||||
|
||||
PackedTree* = object ## usually represents a full Nim module
|
||||
nodes*: seq[Node]
|
||||
toPosition*: Table[SymId, NodePos]
|
||||
sh*: Shared
|
||||
proc hash*(key: GenericKey): Hash =
|
||||
var h: Hash = 0
|
||||
h = h !& hash(key.module)
|
||||
h = h !& hash(key.name)
|
||||
h = h !& hash(key.types)
|
||||
result = !$h
|
||||
|
||||
proc `==`*(a, b: SymId): bool {.borrow.}
|
||||
proc hash*(a: SymId): Hash {.borrow.}
|
||||
|
||||
proc `==`*(a, b: NodePos): bool {.borrow.}
|
||||
proc `==`*(a, b: TypeId): bool {.borrow.}
|
||||
proc `==`*(a, b: ModuleId): bool {.borrow.}
|
||||
|
||||
proc declareSym*(tree: var PackedTree; kind: TSymKind;
|
||||
name: LitId; info: PackedLineInfo): SymId =
|
||||
result = SymId(tree.sh.syms.len)
|
||||
tree.sh.syms.add PackedSym(kind: kind, name: name, flags: {}, magic: mNone, info: info)
|
||||
#proc `==`*(a, b: TypeId): bool {.borrow.}
|
||||
proc `==`*(a, b: NodeId): bool {.borrow.}
|
||||
|
||||
proc newTreeFrom*(old: PackedTree): PackedTree =
|
||||
result.nodes = @[]
|
||||
result.sh = old.sh
|
||||
when false: result.sh = old.sh
|
||||
|
||||
proc litIdFromName*(tree: PackedTree; name: string): LitId =
|
||||
result = tree.sh.strings.getOrIncl(name)
|
||||
when false:
|
||||
proc declareSym*(tree: var PackedTree; kind: TSymKind;
|
||||
name: LitId; info: PackedLineInfo): SymId =
|
||||
result = SymId(tree.sh.syms.len)
|
||||
tree.sh.syms.add PackedSym(kind: kind, name: name, flags: {}, magic: mNone, info: info)
|
||||
|
||||
proc add*(tree: var PackedTree; kind: TNodeKind; token: string; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: kind, operand: int32 getOrIncl(tree.sh.strings, token), info: info)
|
||||
proc litIdFromName*(tree: PackedTree; name: string): LitId =
|
||||
result = tree.sh.strings.getOrIncl(name)
|
||||
|
||||
proc add*(tree: var PackedTree; kind: TNodeKind; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: kind, operand: 0, info: info)
|
||||
proc add*(tree: var PackedTree; kind: TNodeKind; token: string; info: PackedLineInfo) =
|
||||
tree.nodes.add PackedNode(kind: kind, info: info,
|
||||
operand: int32 getOrIncl(tree.sh.strings, token))
|
||||
|
||||
proc add*(tree: var PackedTree; kind: TNodeKind; info: PackedLineInfo) =
|
||||
tree.nodes.add PackedNode(kind: kind, operand: 0, info: info)
|
||||
|
||||
proc throwAwayLastNode*(tree: var PackedTree) =
|
||||
tree.nodes.setLen(tree.nodes.len-1)
|
||||
|
||||
proc addIdent*(tree: var PackedTree; s: LitId; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: nkIdent, operand: int32(s), info: info)
|
||||
tree.nodes.add PackedNode(kind: nkIdent, operand: int32(s), info: info)
|
||||
|
||||
proc addSym*(tree: var PackedTree; s: SymId; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: nkSym, operand: int32(s), info: info)
|
||||
proc addSym*(tree: var PackedTree; s: int32; info: PackedLineInfo) =
|
||||
tree.nodes.add PackedNode(kind: nkSym, operand: s, info: info)
|
||||
|
||||
proc addModuleId*(tree: var PackedTree; s: ModuleId; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: nkInt32Lit, operand: int32(s), info: info)
|
||||
tree.nodes.add PackedNode(kind: nkInt32Lit, operand: int32(s), info: info)
|
||||
|
||||
proc addSymDef*(tree: var PackedTree; s: SymId; info: PackedLineInfo) =
|
||||
tree.nodes.add Node(kind: nkSym, operand: int32(s), info: info)
|
||||
tree.nodes.add PackedNode(kind: nkSym, operand: int32(s), info: info)
|
||||
|
||||
proc isAtom*(tree: PackedTree; pos: int): bool {.inline.} = tree.nodes[pos].kind <= nkNilLit
|
||||
|
||||
@@ -194,11 +208,12 @@ proc copyTree*(dest: var PackedTree; tree: PackedTree; n: NodePos) =
|
||||
for i in 0..<L:
|
||||
dest.nodes[d+i] = tree.nodes[pos+i]
|
||||
|
||||
proc copySym*(dest: var PackedTree; tree: PackedTree; s: SymId): SymId =
|
||||
result = SymId(dest.sh.syms.len)
|
||||
assert int(s) < tree.sh.syms.len
|
||||
let oldSym = tree.sh.syms[s.int]
|
||||
dest.sh.syms.add oldSym
|
||||
when false:
|
||||
proc copySym*(dest: var PackedTree; tree: PackedTree; s: SymId): SymId =
|
||||
result = SymId(dest.sh.syms.len)
|
||||
assert int(s) < tree.sh.syms.len
|
||||
let oldSym = tree.sh.syms[s.int]
|
||||
dest.sh.syms.add oldSym
|
||||
|
||||
type
|
||||
PatchPos = distinct int
|
||||
@@ -206,11 +221,12 @@ type
|
||||
when false:
|
||||
proc prepare*(tree: var PackedTree; kind: TNodeKind; info: PackedLineInfo): PatchPos =
|
||||
result = PatchPos tree.nodes.len
|
||||
tree.nodes.add Node(kind: kind, operand: 0, info: info)
|
||||
tree.nodes.add PackedNode(kind: kind, operand: 0, info: info)
|
||||
|
||||
proc prepare*(tree: var PackedTree; kind: TNodeKind; flags: TNodeFlags; typeId: TypeId; info: PackedLineInfo): PatchPos =
|
||||
result = PatchPos tree.nodes.len
|
||||
tree.nodes.add Node(kind: kind, flags: flags, operand: 0, typeId: typeId, info: info)
|
||||
tree.nodes.add PackedNode(kind: kind, flags: flags, operand: 0, info: info,
|
||||
typeId: typeId)
|
||||
|
||||
proc prepare*(dest: var PackedTree; source: PackedTree; sourcePos: NodePos): PatchPos =
|
||||
result = PatchPos dest.nodes.len
|
||||
@@ -224,7 +240,8 @@ proc patch*(tree: var PackedTree; pos: PatchPos) =
|
||||
|
||||
proc len*(tree: PackedTree): int {.inline.} = tree.nodes.len
|
||||
|
||||
proc `[]`*(tree: PackedTree; i: int): lent Node {.inline.} = tree.nodes[i]
|
||||
proc `[]`*(tree: PackedTree; i: int): lent PackedNode {.inline.} =
|
||||
tree.nodes[i]
|
||||
|
||||
proc nextChild(tree: PackedTree; pos: var int) {.inline.} =
|
||||
if tree.nodes[pos].kind > nkNilLit:
|
||||
@@ -247,7 +264,8 @@ iterator sons*(dest: var PackedTree; tree: PackedTree; n: NodePos): NodePos =
|
||||
for x in sonsReadonly(tree, n): yield x
|
||||
patch dest, patchPos
|
||||
|
||||
iterator isons*(dest: var PackedTree; tree: PackedTree; n: NodePos): (int, NodePos) =
|
||||
iterator isons*(dest: var PackedTree; tree: PackedTree;
|
||||
n: NodePos): (int, NodePos) =
|
||||
var i = 0
|
||||
for ch0 in sons(dest, tree, n):
|
||||
yield (i, ch0)
|
||||
@@ -301,10 +319,19 @@ proc hasAtLeastXsons*(tree: PackedTree; n: NodePos; x: int): bool =
|
||||
if count >= x: return true
|
||||
return false
|
||||
|
||||
proc firstSon*(tree: PackedTree; n: NodePos): NodePos {.inline.} = NodePos(n.int+1)
|
||||
proc kind*(tree: PackedTree; n: NodePos): TNodeKind {.inline.} = tree.nodes[n.int].kind
|
||||
proc litId*(tree: PackedTree; n: NodePos): LitId {.inline.} = LitId tree.nodes[n.int].operand
|
||||
proc info*(tree: PackedTree; n: NodePos): PackedLineInfo {.inline.} = tree.nodes[n.int].info
|
||||
proc firstSon*(tree: PackedTree; n: NodePos): NodePos {.inline.} =
|
||||
NodePos(n.int+1)
|
||||
proc kind*(tree: PackedTree; n: NodePos): TNodeKind {.inline.} =
|
||||
tree.nodes[n.int].kind
|
||||
proc litId*(tree: PackedTree; n: NodePos): LitId {.inline.} =
|
||||
LitId tree.nodes[n.int].operand
|
||||
proc info*(tree: PackedTree; n: NodePos): PackedLineInfo {.inline.} =
|
||||
tree.nodes[n.int].info
|
||||
|
||||
template typ*(n: NodePos): PackedItemId =
|
||||
tree.nodes[n.int].typeId
|
||||
template flags*(n: NodePos): TNodeFlags =
|
||||
tree.nodes[n.int].flags
|
||||
|
||||
proc span(tree: PackedTree; pos: int): int {.inline.} =
|
||||
if isAtom(tree, pos): 1 else: tree.nodes[pos].operand
|
||||
@@ -330,7 +357,9 @@ proc ithSon*(tree: PackedTree; n: NodePos; i: int): NodePos =
|
||||
inc count
|
||||
assert false, "node has no i-th child"
|
||||
|
||||
proc `@`*(tree: PackedTree; lit: LitId): lent string {.inline.} = tree.sh.strings[lit]
|
||||
when false:
|
||||
proc `@`*(tree: PackedTree; lit: LitId): lent string {.inline.} =
|
||||
tree.sh.strings[lit]
|
||||
|
||||
template kind*(n: NodePos): TNodeKind = tree.nodes[n.int].kind
|
||||
template info*(n: NodePos): PackedLineInfo = tree.nodes[n.int].info
|
||||
@@ -340,29 +369,30 @@ template symId*(n: NodePos): SymId = SymId tree.nodes[n.int].operand
|
||||
|
||||
proc firstSon*(n: NodePos): NodePos {.inline.} = NodePos(n.int+1)
|
||||
|
||||
proc strLit*(tree: PackedTree; n: NodePos): lent string =
|
||||
assert n.kind == nkStrLit
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
when false:
|
||||
proc strLit*(tree: PackedTree; n: NodePos): lent string =
|
||||
assert n.kind == nkStrLit
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
|
||||
proc strVal*(tree: PackedTree; n: NodePos): string =
|
||||
assert n.kind == nkStrLit
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
#result = cookedStrLit(raw)
|
||||
proc strVal*(tree: PackedTree; n: NodePos): string =
|
||||
assert n.kind == nkStrLit
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
#result = cookedStrLit(raw)
|
||||
|
||||
proc filenameVal*(tree: PackedTree; n: NodePos): string =
|
||||
case n.kind
|
||||
of nkStrLit:
|
||||
result = strVal(tree, n)
|
||||
of nkIdent:
|
||||
result = tree.sh.strings[n.litId]
|
||||
of nkSym:
|
||||
result = tree.sh.strings[tree.sh.syms[int n.symId].name]
|
||||
else:
|
||||
result = ""
|
||||
proc filenameVal*(tree: PackedTree; n: NodePos): string =
|
||||
case n.kind
|
||||
of nkStrLit:
|
||||
result = strVal(tree, n)
|
||||
of nkIdent:
|
||||
result = tree.sh.strings[n.litId]
|
||||
of nkSym:
|
||||
result = tree.sh.strings[tree.sh.syms[int n.symId].name]
|
||||
else:
|
||||
result = ""
|
||||
|
||||
proc identAsStr*(tree: PackedTree; n: NodePos): lent string =
|
||||
assert n.kind == nkIdent
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
proc identAsStr*(tree: PackedTree; n: NodePos): lent string =
|
||||
assert n.kind == nkIdent
|
||||
result = tree.sh.strings[LitId tree.nodes[n.int].operand]
|
||||
|
||||
const
|
||||
externIntLit* = {nkCharLit,
|
||||
@@ -380,7 +410,8 @@ const
|
||||
externUIntLit* = {nkUIntLit, nkUInt8Lit, nkUInt16Lit, nkUInt32Lit, nkUInt64Lit}
|
||||
directIntLit* = nkInt32Lit
|
||||
|
||||
proc toString*(tree: PackedTree; n: NodePos; nesting: int; result: var string) =
|
||||
proc toString*(tree: PackedTree; n: NodePos; sh: Shared; nesting: int;
|
||||
result: var string) =
|
||||
let pos = n.int
|
||||
if result.len > 0 and result[^1] notin {' ', '\n'}:
|
||||
result.add ' '
|
||||
@@ -390,46 +421,47 @@ proc toString*(tree: PackedTree; n: NodePos; nesting: int; result: var string) =
|
||||
of nkNone, nkEmpty, nkNilLit, nkType: discard
|
||||
of nkIdent, nkStrLit..nkTripleStrLit:
|
||||
result.add " "
|
||||
result.add tree.sh.strings[LitId tree.nodes[pos].operand]
|
||||
result.add sh.strings[LitId tree.nodes[pos].operand]
|
||||
of nkSym:
|
||||
result.add " "
|
||||
result.add tree.sh.strings[tree.sh.syms[tree.nodes[pos].operand].name]
|
||||
result.add sh.strings[sh.syms[tree.nodes[pos].operand].name]
|
||||
of directIntLit:
|
||||
result.add " "
|
||||
result.addInt tree.nodes[pos].operand
|
||||
of externSIntLit:
|
||||
result.add " "
|
||||
result.addInt tree.sh.integers[LitId tree.nodes[pos].operand]
|
||||
result.addInt sh.integers[LitId tree.nodes[pos].operand]
|
||||
of externUIntLit:
|
||||
result.add " "
|
||||
result.add $cast[uint64](tree.sh.integers[LitId tree.nodes[pos].operand])
|
||||
result.add $cast[uint64](sh.integers[LitId tree.nodes[pos].operand])
|
||||
else:
|
||||
result.add "(\n"
|
||||
for i in 1..(nesting+1)*2: result.add ' '
|
||||
for child in sonsReadonly(tree, n):
|
||||
toString(tree, child, nesting + 1, result)
|
||||
toString(tree, child, sh, nesting + 1, result)
|
||||
result.add "\n"
|
||||
for i in 1..nesting*2: result.add ' '
|
||||
result.add ")"
|
||||
#for i in 1..nesting*2: result.add ' '
|
||||
|
||||
|
||||
proc toString*(tree: PackedTree; n: NodePos): string =
|
||||
proc toString*(tree: PackedTree; n: NodePos; sh: Shared): string =
|
||||
result = ""
|
||||
toString(tree, n, 0, result)
|
||||
toString(tree, n, sh, 0, result)
|
||||
|
||||
proc debug*(tree: PackedTree) =
|
||||
stdout.write toString(tree, NodePos 0)
|
||||
proc debug*(tree: PackedTree; sh: Shared) =
|
||||
stdout.write toString(tree, NodePos 0, sh)
|
||||
|
||||
proc identIdImpl(tree: PackedTree; n: NodePos): LitId =
|
||||
if n.kind == nkIdent:
|
||||
result = n.litId
|
||||
elif n.kind == nkSym:
|
||||
result = tree.sh.syms[int n.symId].name
|
||||
else:
|
||||
result = LitId(0)
|
||||
when false:
|
||||
proc identIdImpl(tree: PackedTree; n: NodePos): LitId =
|
||||
if n.kind == nkIdent:
|
||||
result = n.litId
|
||||
elif n.kind == nkSym:
|
||||
result = tree.sh.syms[int n.symId].name
|
||||
else:
|
||||
result = LitId(0)
|
||||
|
||||
template identId*(n: NodePos): LitId = identIdImpl(tree, n)
|
||||
template identId*(n: NodePos): LitId = identIdImpl(tree, n)
|
||||
|
||||
template copyInto*(dest, n, body) =
|
||||
let patchPos = prepare(dest, tree, n)
|
||||
@@ -441,17 +473,20 @@ template copyIntoKind*(dest, kind, info, body) =
|
||||
body
|
||||
patch dest, patchPos
|
||||
|
||||
proc hasPragma*(tree: PackedTree; n: NodePos; pragma: string): bool =
|
||||
let litId = tree.sh.strings.getKeyId(pragma)
|
||||
if litId == LitId(0):
|
||||
return false
|
||||
assert n.kind == nkPragma
|
||||
for ch0 in sonsReadonly(tree, n):
|
||||
if ch0.kind == nkExprColonExpr:
|
||||
if ch0.firstSon.identId == litId:
|
||||
when false:
|
||||
proc hasPragma*(tree: PackedTree; n: NodePos; pragma: string): bool =
|
||||
let litId = tree.sh.strings.getKeyId(pragma)
|
||||
if litId == LitId(0):
|
||||
return false
|
||||
assert n.kind == nkPragma
|
||||
for ch0 in sonsReadonly(tree, n):
|
||||
if ch0.kind == nkExprColonExpr:
|
||||
if ch0.firstSon.identId == litId:
|
||||
return true
|
||||
elif ch0.identId == litId:
|
||||
return true
|
||||
elif ch0.identId == litId:
|
||||
return true
|
||||
|
||||
proc getNodeId*(tree: PackedTree): NodeId {.inline.} = NodeId tree.nodes.len
|
||||
|
||||
when false:
|
||||
proc produceError*(dest: var PackedTree; tree: PackedTree; n: NodePos; msg: string) =
|
||||
@@ -459,3 +494,68 @@ when false:
|
||||
dest.add nkStrLit, msg, n.info
|
||||
copyTree(dest, tree, n)
|
||||
patch dest, patchPos
|
||||
|
||||
proc hash*(table: StringTableRef): Hash =
|
||||
## XXX: really should be introduced into strtabs...
|
||||
var h: Hash = 0
|
||||
for pair in pairs table:
|
||||
h = h !& hash(pair)
|
||||
result = !$h
|
||||
|
||||
proc hash*(config: ConfigRef): Hash =
|
||||
## XXX: vet and/or extend this
|
||||
var h: Hash = 0
|
||||
h = h !& hash(config.selectedGC)
|
||||
h = h !& hash(config.features)
|
||||
h = h !& hash(config.legacyFeatures)
|
||||
h = h !& hash(config.configVars)
|
||||
h = h !& hash(config.symbols)
|
||||
result = !$h
|
||||
|
||||
# XXX: lazy hashes for now
|
||||
type
|
||||
LazyHashes = PackedSym or PackedType or PackedLib or
|
||||
PackedLineInfo or PackedTree or PackedNode
|
||||
|
||||
proc hash*(sh: Shared): Hash
|
||||
proc hash*(s: LazyHashes): Hash
|
||||
proc hash*(s: seq[LazyHashes]): Hash
|
||||
|
||||
proc hash*(s: LazyHashes): Hash =
|
||||
var h: Hash = 0
|
||||
for k, v in fieldPairs(s):
|
||||
h = h !& hash((k, v))
|
||||
result = !$h
|
||||
|
||||
proc hash*(s: seq[LazyHashes]): Hash =
|
||||
## critically, we need to hash the indices alongside their values
|
||||
var h: Hash = 0
|
||||
for i, n in pairs s:
|
||||
h = h !& hash((i, n))
|
||||
result = !$h
|
||||
|
||||
proc hash*(sh: Shared): Hash =
|
||||
## might want to edit this...
|
||||
# XXX: these have too many references
|
||||
when false:
|
||||
var h: Hash = 0
|
||||
h = h !& hash(sh.syms)
|
||||
h = h !& hash(sh.types)
|
||||
h = h !& hash(sh.strings)
|
||||
h = h !& hash(sh.integers)
|
||||
h = h !& hash(sh.floats)
|
||||
h = h !& hash(sh.config)
|
||||
result = !$h
|
||||
|
||||
proc hash*(m: Module): Hash =
|
||||
var h: Hash = 0
|
||||
h = h !& hash(m.name)
|
||||
h = h !& hash(m.ast)
|
||||
result = !$h
|
||||
|
||||
template safeItemId*(x: typed; f: untyped): ItemId =
|
||||
## yield a valid ItemId value for the field of a nillable type
|
||||
if x.isNil:
|
||||
nilItemId
|
||||
else:
|
||||
x.`f`
|
||||
|
||||
143
compiler/ic/rodfiles.nim
Normal file
143
compiler/ic/rodfiles.nim
Normal file
@@ -0,0 +1,143 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2020 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
from typetraits import supportsCopyMem
|
||||
|
||||
type
|
||||
RodSection* = enum
|
||||
versionSection
|
||||
configSection
|
||||
stringsSection
|
||||
checkSumsSection
|
||||
depsSection
|
||||
integersSection
|
||||
floatsSection
|
||||
topLevelSection
|
||||
bodiesSection
|
||||
symsSection
|
||||
typesSection
|
||||
|
||||
RodFileError* = enum
|
||||
ok, tooBig, ioFailure, wrongHeader, wrongSection, configMismatch,
|
||||
includeFileChanged
|
||||
|
||||
RodFile* = object
|
||||
f*: File
|
||||
currentSection*: RodSection # for error checking
|
||||
err*: RodFileError # little experiment to see if this works
|
||||
# better than exceptions.
|
||||
|
||||
const
|
||||
RodVersion = 1
|
||||
cookie = [byte(0), byte('R'), byte('O'), byte('D'),
|
||||
byte(0), byte(0), byte(0), byte(RodVersion)]
|
||||
|
||||
proc storePrim*(f: var RodFile; s: string) =
|
||||
if f.err != ok: return
|
||||
if s.len >= high(int32):
|
||||
f.err = tooBig
|
||||
return
|
||||
var lenPrefix = int32(s.len)
|
||||
if writeBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix):
|
||||
f.err = ioFailure
|
||||
else:
|
||||
if s.len != 0:
|
||||
if writeBuffer(f.f, unsafeAddr(s[0]), s.len) != s.len:
|
||||
f.err = ioFailure
|
||||
|
||||
proc storePrim*[T](f: var RodFile; x: T) =
|
||||
if f.err != ok: return
|
||||
when supportsCopyMem(T):
|
||||
if writeBuffer(f.f, unsafeAddr(x), sizeof(x)) != sizeof(x):
|
||||
f.err = ioFailure
|
||||
elif T is tuple:
|
||||
for y in fields(x):
|
||||
storePrim(f, y)
|
||||
else:
|
||||
{.error: "unsupported type for 'storePrim'".}
|
||||
|
||||
proc storeSeq*[T](f: var RodFile; s: seq[T]) =
|
||||
if f.err != ok: return
|
||||
if s.len >= high(int32):
|
||||
f.err = tooBig
|
||||
return
|
||||
var lenPrefix = int32(s.len)
|
||||
if writeBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix):
|
||||
f.err = ioFailure
|
||||
else:
|
||||
for i in 0..<s.len:
|
||||
storePrim(f, s[i])
|
||||
|
||||
proc loadPrim*(f: var RodFile; s: var string) =
|
||||
if f.err != ok: return
|
||||
var lenPrefix = int32(0)
|
||||
if readBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix):
|
||||
f.err = ioFailure
|
||||
else:
|
||||
s = newString(lenPrefix)
|
||||
if lenPrefix > 0:
|
||||
if readBuffer(f.f, unsafeAddr(s[0]), s.len) != s.len:
|
||||
f.err = ioFailure
|
||||
|
||||
proc loadPrim*[T](f: var RodFile; x: var T) =
|
||||
if f.err != ok: return
|
||||
when supportsCopyMem(T):
|
||||
if readBuffer(f.f, unsafeAddr(x), sizeof(x)) != sizeof(x):
|
||||
f.err = ioFailure
|
||||
elif T is tuple:
|
||||
for y in fields(x):
|
||||
loadPrim(f, y)
|
||||
else:
|
||||
{.error: "unsupported type for 'loadPrim'".}
|
||||
|
||||
proc loadSeq*[T](f: var RodFile; s: var seq[T]) =
|
||||
if f.err != ok: return
|
||||
var lenPrefix = int32(0)
|
||||
if readBuffer(f.f, addr lenPrefix, sizeof(lenPrefix)) != sizeof(lenPrefix):
|
||||
f.err = ioFailure
|
||||
else:
|
||||
s = newSeq[T](lenPrefix)
|
||||
for i in 0..<lenPrefix:
|
||||
loadPrim(f, s[i])
|
||||
|
||||
proc storeHeader*(f: var RodFile) =
|
||||
if f.err != ok: return
|
||||
if f.f.writeBytes(cookie, 0, cookie.len) != cookie.len:
|
||||
f.err = ioFailure
|
||||
|
||||
proc loadHeader*(f: var RodFile) =
|
||||
if f.err != ok: return
|
||||
var thisCookie: array[cookie.len, byte]
|
||||
if f.f.readBytes(thisCookie, 0, thisCookie.len) != thisCookie.len:
|
||||
f.err = ioFailure
|
||||
elif thisCookie != cookie:
|
||||
f.err = wrongHeader
|
||||
|
||||
proc storeSection*(f: var RodFile; s: RodSection) =
|
||||
if f.err != ok: return
|
||||
assert f.currentSection == pred s
|
||||
f.currentSection = s
|
||||
storePrim(f, s)
|
||||
|
||||
proc loadSection*(f: var RodFile; expected: RodSection) =
|
||||
if f.err != ok: return
|
||||
var s: RodSection
|
||||
loadPrim(f, s)
|
||||
if expected != s:
|
||||
f.err = wrongSection
|
||||
|
||||
proc create*(filename: string): RodFile =
|
||||
if not open(result.f, filename, fmWrite):
|
||||
result.err = ioFailure
|
||||
|
||||
proc close*(f: var RodFile) = close(f.f)
|
||||
|
||||
proc open*(filename: string): RodFile =
|
||||
if not open(result.f, filename, fmRead):
|
||||
result.err = ioFailure
|
||||
@@ -7,84 +7,680 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
import std / [hashes, tables]
|
||||
import packed_ast, bitabs
|
||||
import ".." / [ast, idents, lineinfos, options, pathutils, msgs]
|
||||
import std / [hashes, tables, intsets, sha1]
|
||||
import packed_ast, bitabs, rodfiles
|
||||
import ".." / [ast, idents, lineinfos, msgs, ropes, options,
|
||||
pathutils, condsyms]
|
||||
|
||||
from std / os import removeFile, isAbsolute
|
||||
|
||||
when not defined(release): import ".." / astalgo # debug()
|
||||
|
||||
type
|
||||
Context = object
|
||||
thisModule: int32
|
||||
lastFile: FileIndex # remember the last lookup entry.
|
||||
lastLit: LitId
|
||||
filenames: Table[FileIndex, LitId]
|
||||
PackedConfig* = object
|
||||
backend: TBackend
|
||||
selectedGC: TGCMode
|
||||
cCompiler: TSystemCC
|
||||
options: TOptions
|
||||
globalOptions: TGlobalOptions
|
||||
|
||||
proc toLitId(x: FileIndex; ir: var PackedTree; c: var Context): LitId =
|
||||
PackedModule* = object ## the parts of a PackedEncoder that are part of the .rod file
|
||||
definedSymbols: string
|
||||
includes: seq[(LitId, string)] # first entry is the module filename itself
|
||||
imports: seq[LitId] # the modules this module depends on
|
||||
topLevel*: PackedTree # top level statements
|
||||
bodies*: PackedTree # other trees. Referenced from typ.n and sym.ast by their position.
|
||||
hidden*: PackedTree # instantiated generics and other trees not directly in the source code.
|
||||
#producedGenerics*: Table[GenericKey, SymId]
|
||||
sh*: Shared
|
||||
cfg: PackedConfig
|
||||
|
||||
PackedEncoder* = object
|
||||
m: PackedModule
|
||||
thisModule*: int32
|
||||
lastFile*: FileIndex # remember the last lookup entry.
|
||||
lastLit*: LitId
|
||||
filenames*: Table[FileIndex, LitId]
|
||||
pendingTypes*: seq[PType]
|
||||
pendingSyms*: seq[PSym]
|
||||
typeMarker*: IntSet #Table[ItemId, TypeId] # ItemId.item -> TypeId
|
||||
symMarker*: IntSet #Table[ItemId, SymId] # ItemId.item -> SymId
|
||||
config*: ConfigRef
|
||||
|
||||
template primConfigFields(fn: untyped) {.dirty.} =
|
||||
fn backend
|
||||
fn selectedGC
|
||||
fn cCompiler
|
||||
fn options
|
||||
fn globalOptions
|
||||
|
||||
proc definedSymbolsAsString(config: ConfigRef): string =
|
||||
result = newStringOfCap(200)
|
||||
result.add "config"
|
||||
for d in definedSymbolNames(config.symbols):
|
||||
result.add ' '
|
||||
result.add d
|
||||
|
||||
proc rememberConfig(c: var PackedEncoder; config: ConfigRef) =
|
||||
c.m.definedSymbols = definedSymbolsAsString(config)
|
||||
|
||||
template rem(x) =
|
||||
c.m.cfg.x = config.x
|
||||
primConfigFields rem
|
||||
|
||||
proc configIdentical(m: PackedModule; config: ConfigRef): bool =
|
||||
result = m.definedSymbols == definedSymbolsAsString(config)
|
||||
template eq(x) =
|
||||
result = result and m.cfg.x == config.x
|
||||
primConfigFields eq
|
||||
|
||||
proc hashFileCached(conf: ConfigRef; fileIdx: FileIndex): string =
|
||||
result = msgs.getHash(conf, fileIdx)
|
||||
if result.len == 0:
|
||||
let fullpath = msgs.toFullPath(conf, fileIdx)
|
||||
result = $secureHashFile(fullpath)
|
||||
msgs.setHash(conf, fileIdx, result)
|
||||
|
||||
proc toLitId(x: FileIndex; c: var PackedEncoder): LitId =
|
||||
## store a file index as a literal
|
||||
if x == c.lastFile:
|
||||
result = c.lastLit
|
||||
else:
|
||||
result = c.filenames.getOrDefault(x)
|
||||
if result == LitId(0):
|
||||
let p = msgs.toFullPath(ir.sh.config, x)
|
||||
result = getOrIncl(ir.sh.strings, p)
|
||||
let p = msgs.toFullPath(c.config, x)
|
||||
result = getOrIncl(c.m.sh.strings, p)
|
||||
c.filenames[x] = result
|
||||
c.lastFile = x
|
||||
c.lastLit = result
|
||||
assert result != LitId(0)
|
||||
|
||||
proc toPackedInfo(x: TLineInfo; ir: var PackedTree; c: var Context): PackedLineInfo =
|
||||
PackedLineInfo(line: x.line, col: x.col, file: toLitId(x.fileIndex, ir, c))
|
||||
proc toFileIndex(x: LitId; m: PackedModule; config: ConfigRef): FileIndex =
|
||||
result = msgs.fileInfoIdx(config, AbsoluteFile m.sh.strings[x])
|
||||
|
||||
proc toPackedType(t: PType; ir: var PackedTree; c: var Context): TypeId =
|
||||
result = TypeId(0)
|
||||
proc includesIdentical(m: var PackedModule; config: ConfigRef): bool =
|
||||
for it in mitems(m.includes):
|
||||
if hashFileCached(config, toFileIndex(it[0], m, config)) != it[1]:
|
||||
return false
|
||||
result = true
|
||||
|
||||
proc toPackedSym(s: PSym; ir: var PackedTree; c: var Context): SymId =
|
||||
result = SymId(0)
|
||||
proc initEncoder*(c: var PackedEncoder; m: PSym; config: ConfigRef) =
|
||||
## setup a context for serializing to packed ast
|
||||
c.m.sh = Shared()
|
||||
c.thisModule = m.itemId.module
|
||||
c.config = config
|
||||
c.m.bodies = newTreeFrom(c.m.topLevel)
|
||||
c.m.hidden = newTreeFrom(c.m.topLevel)
|
||||
|
||||
proc toPackedSymNode(n: PNode; ir: var PackedTree; c: var Context) =
|
||||
let thisNimFile = FileIndex c.thisModule
|
||||
var h = msgs.getHash(config, thisNimFile)
|
||||
if h.len == 0:
|
||||
let fullpath = msgs.toFullPath(config, thisNimFile)
|
||||
if isAbsolute(fullpath):
|
||||
# For NimScript compiler API support the main Nim file might be from a stream.
|
||||
h = $secureHashFile(fullpath)
|
||||
msgs.setHash(config, thisNimFile, h)
|
||||
c.m.includes.add((toLitId(thisNimFile, c), h)) # the module itself
|
||||
|
||||
proc addIncludeFileDep*(c: var PackedEncoder; f: FileIndex) =
|
||||
c.m.includes.add((toLitId(f, c), hashFileCached(c.config, f)))
|
||||
|
||||
proc addImportFileDep*(c: var PackedEncoder; f: FileIndex) =
|
||||
c.m.imports.add toLitId(f, c)
|
||||
|
||||
proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder)
|
||||
proc toPackedSym*(s: PSym; c: var PackedEncoder): PackedItemId
|
||||
proc toPackedType(t: PType; c: var PackedEncoder): PackedItemId
|
||||
|
||||
proc flush(c: var PackedEncoder) =
|
||||
## serialize any pending types or symbols from the context
|
||||
while true:
|
||||
if c.pendingTypes.len > 0:
|
||||
discard toPackedType(c.pendingTypes.pop, c)
|
||||
elif c.pendingSyms.len > 0:
|
||||
discard toPackedSym(c.pendingSyms.pop, c)
|
||||
else:
|
||||
break
|
||||
|
||||
proc toLitId(x: string; c: var PackedEncoder): LitId =
|
||||
## store a string as a literal
|
||||
result = getOrIncl(c.m.sh.strings, x)
|
||||
|
||||
proc toLitId(x: BiggestInt; c: var PackedEncoder): LitId =
|
||||
## store an integer as a literal
|
||||
result = getOrIncl(c.m.sh.integers, x)
|
||||
|
||||
proc toPackedInfo(x: TLineInfo; c: var PackedEncoder): PackedLineInfo =
|
||||
PackedLineInfo(line: x.line, col: x.col, file: toLitId(x.fileIndex, c))
|
||||
|
||||
proc safeItemId(s: PSym; c: var PackedEncoder): PackedItemId {.inline.} =
|
||||
## given a symbol, produce an ItemId with the correct properties
|
||||
## for local or remote symbols, packing the symbol as necessary
|
||||
if s == nil:
|
||||
result = nilItemId
|
||||
elif s.itemId.module == c.thisModule:
|
||||
result = PackedItemId(module: LitId(0), item: s.itemId.item)
|
||||
else:
|
||||
result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c),
|
||||
item: s.itemId.item)
|
||||
|
||||
proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder) =
|
||||
## add a remote symbol reference to the tree
|
||||
let info = n.info.toPackedInfo(c)
|
||||
ir.nodes.add PackedNode(kind: nkModuleRef, operand: 2.int32, # 2 kids...
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
ir.nodes.add PackedNode(kind: nkInt32Lit, info: info,
|
||||
operand: toLitId(n.sym.itemId.module.FileIndex, c).int32)
|
||||
ir.nodes.add PackedNode(kind: nkInt32Lit, info: info,
|
||||
operand: n.sym.itemId.item)
|
||||
|
||||
proc addMissing(c: var PackedEncoder; p: PSym) =
|
||||
## consider queuing a symbol for later addition to the packed tree
|
||||
if p != nil and p.itemId.module == c.thisModule:
|
||||
if p.itemId.item notin c.symMarker:
|
||||
c.pendingSyms.add p
|
||||
|
||||
proc addMissing(c: var PackedEncoder; p: PType) =
|
||||
## consider queuing a type for later addition to the packed tree
|
||||
if p != nil and p.uniqueId.module == c.thisModule:
|
||||
if p.uniqueId.item notin c.typeMarker:
|
||||
c.pendingTypes.add p
|
||||
|
||||
template storeNode(dest, src, field) =
|
||||
var nodeId: NodeId
|
||||
if src.field != nil:
|
||||
nodeId = getNodeId(c.m.bodies)
|
||||
toPackedNode(src.field, c.m.bodies, c)
|
||||
else:
|
||||
nodeId = emptyNodeId
|
||||
dest.field = nodeId
|
||||
|
||||
proc toPackedType(t: PType; c: var PackedEncoder): PackedItemId =
|
||||
## serialize a ptype
|
||||
if t.isNil: return nilTypeId
|
||||
|
||||
if t.uniqueId.module != c.thisModule:
|
||||
# XXX Assert here that it already was serialized in the foreign module!
|
||||
# it is a foreign type:
|
||||
return PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c), item: t.uniqueId.item)
|
||||
|
||||
if not c.typeMarker.containsOrIncl(t.uniqueId.item):
|
||||
if t.uniqueId.item >= c.m.sh.types.len:
|
||||
setLen c.m.sh.types, t.uniqueId.item+1
|
||||
|
||||
var p = PackedType(kind: t.kind, flags: t.flags, callConv: t.callConv,
|
||||
size: t.size, align: t.align, nonUniqueId: t.itemId.item,
|
||||
paddingAtEnd: t.paddingAtEnd, lockLevel: t.lockLevel)
|
||||
storeNode(p, t, n)
|
||||
|
||||
for op, s in pairs t.attachedOps:
|
||||
c.addMissing s
|
||||
p.attachedOps[op] = s.safeItemId(c)
|
||||
|
||||
p.typeInst = t.typeInst.toPackedType(c)
|
||||
for kid in items t.sons:
|
||||
p.types.add kid.toPackedType(c)
|
||||
for i, s in items t.methods:
|
||||
c.addMissing s
|
||||
p.methods.add (i, s.safeItemId(c))
|
||||
c.addMissing t.sym
|
||||
p.sym = t.sym.safeItemId(c)
|
||||
c.addMissing t.owner
|
||||
p.owner = t.owner.safeItemId(c)
|
||||
|
||||
# fill the reserved slot, nothing else:
|
||||
c.m.sh.types[t.uniqueId.item] = p
|
||||
|
||||
result = PackedItemId(module: LitId(0), item: t.uniqueId.item)
|
||||
|
||||
proc toPackedLib(l: PLib; c: var PackedEncoder): PackedLib =
|
||||
## the plib hangs off the psym via the .annex field
|
||||
if l.isNil: return
|
||||
result.kind = l.kind
|
||||
result.generated = l.generated
|
||||
result.isOverriden = l.isOverriden
|
||||
result.name = toLitId($l.name, c)
|
||||
storeNode(result, l, path)
|
||||
|
||||
proc toPackedSym*(s: PSym; c: var PackedEncoder): PackedItemId =
|
||||
## serialize a psym
|
||||
if s.isNil: return nilItemId
|
||||
|
||||
if s.itemId.module != c.thisModule:
|
||||
# XXX Assert here that it already was serialized in the foreign module!
|
||||
# it is a foreign symbol:
|
||||
return PackedItemId(module: toLitId(s.itemId.module.FileIndex, c), item: s.itemId.item)
|
||||
|
||||
if not c.symMarker.containsOrIncl(s.itemId.item):
|
||||
if s.itemId.item >= c.m.sh.syms.len:
|
||||
setLen c.m.sh.syms, s.itemId.item+1
|
||||
|
||||
var p = PackedSym(kind: s.kind, flags: s.flags, info: s.info.toPackedInfo(c), magic: s.magic,
|
||||
position: s.position, offset: s.offset, options: s.options,
|
||||
name: s.name.s.toLitId(c))
|
||||
|
||||
storeNode(p, s, ast)
|
||||
storeNode(p, s, constraint)
|
||||
|
||||
if s.kind in {skLet, skVar, skField, skForVar}:
|
||||
c.addMissing s.guard
|
||||
p.guard = s.guard.safeItemId(c)
|
||||
p.bitsize = s.bitsize
|
||||
p.alignment = s.alignment
|
||||
|
||||
p.externalName = toLitId(if s.loc.r.isNil: "" else: $s.loc.r, c)
|
||||
c.addMissing s.typ
|
||||
p.typ = s.typ.toPackedType(c)
|
||||
c.addMissing s.owner
|
||||
p.owner = s.owner.safeItemId(c)
|
||||
p.annex = toPackedLib(s.annex, c)
|
||||
when hasFFI:
|
||||
p.cname = toLitId(s.cname, c)
|
||||
|
||||
# fill the reserved slot, nothing else:
|
||||
c.m.sh.syms[s.itemId.item] = p
|
||||
|
||||
result = PackedItemId(module: LitId(0), item: s.itemId.item)
|
||||
|
||||
proc toSymNode(n: PNode; ir: var PackedTree; c: var PackedEncoder) =
|
||||
## store a local or remote psym reference in the tree
|
||||
assert n.kind == nkSym
|
||||
let t = toPackedType(n.typ, ir, c)
|
||||
|
||||
if n.sym.itemId.module == c.thisModule:
|
||||
template s: PSym = n.sym
|
||||
let id = s.toPackedSym(c).item
|
||||
if s.itemId.module == c.thisModule:
|
||||
# it is a symbol that belongs to the module we're currently
|
||||
# packing:
|
||||
let sid = toPackedSym(n.sym, ir, c)
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32(sid),
|
||||
typeId: t, info: toPackedInfo(n.info, ir, c))
|
||||
ir.addSym(id, toPackedInfo(n.info, c))
|
||||
else:
|
||||
# store it as an external module reference:
|
||||
# nkModuleRef
|
||||
discard
|
||||
|
||||
|
||||
proc toPackedNode*(n: PNode; ir: var PackedTree; c: var Context) =
|
||||
template toP(x: TLineInfo): PackedLineInfo = toPackedInfo(x, ir, c)
|
||||
addModuleRef(n, ir, c)
|
||||
|
||||
proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder) =
|
||||
## serialize a node into the tree
|
||||
if n.isNil: return
|
||||
let info = toPackedInfo(n.info, c)
|
||||
case n.kind
|
||||
of nkNone, nkEmpty, nkNilLit:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: 0,
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
of nkNone, nkEmpty, nkNilLit, nkType:
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: 0,
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
of nkIdent:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(ir.sh.strings, n.ident.s),
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
|
||||
operand: int32 getOrIncl(c.m.sh.strings, n.ident.s),
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
of nkSym:
|
||||
toPackedSymNode(n, ir, c)
|
||||
toSymNode(n, ir, c)
|
||||
of directIntLit:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32(n.intVal),
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
|
||||
operand: int32(n.intVal),
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
of externIntLit:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(ir.sh.integers, n.intVal),
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
|
||||
operand: int32 getOrIncl(c.m.sh.integers, n.intVal),
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(ir.sh.strings, n.strVal),
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
|
||||
operand: int32 getOrIncl(c.m.sh.strings, n.strVal),
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
ir.nodes.add Node(kind: n.kind, flags: n.flags, operand: int32 getOrIncl(ir.sh.floats, n.floatVal),
|
||||
typeId: toPackedType(n.typ, ir, c), info: toP n.info)
|
||||
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
|
||||
operand: int32 getOrIncl(c.m.sh.floats, n.floatVal),
|
||||
typeId: toPackedType(n.typ, c), info: info)
|
||||
else:
|
||||
let patchPos = ir.prepare(n.kind, n.flags, toPackedType(n.typ, ir, c), toP n.info)
|
||||
let patchPos = ir.prepare(n.kind, n.flags,
|
||||
toPackedType(n.typ, c), info)
|
||||
for i in 0..<n.len:
|
||||
toPackedNode(n[i], ir, c)
|
||||
ir.patch patchPos
|
||||
|
||||
proc moduleToIr*(n: PNode; ir: var PackedTree; module: PSym) =
|
||||
var c = Context(thisModule: module.itemId.module)
|
||||
toPackedNode(n, ir, c)
|
||||
when false:
|
||||
ir.flush c # flush any pending types and symbols
|
||||
|
||||
proc toPackedNodeIgnoreProcDefs*(n: PNode, encoder: var PackedEncoder) =
|
||||
case n.kind
|
||||
of routineDefs:
|
||||
# we serialize n[namePos].sym instead
|
||||
if n[namePos].kind == nkSym:
|
||||
discard toPackedSym(n[namePos].sym, encoder)
|
||||
else:
|
||||
toPackedNode(n, encoder.m.topLevel, encoder)
|
||||
else:
|
||||
toPackedNode(n, encoder.m.topLevel, encoder)
|
||||
|
||||
proc toPackedNodeTopLevel*(n: PNode, encoder: var PackedEncoder) =
|
||||
toPackedNodeIgnoreProcDefs(n, encoder)
|
||||
flush encoder
|
||||
|
||||
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) =
|
||||
echo "Error: ", $err, "\nloading file: ", filename.string
|
||||
|
||||
proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef): RodFileError =
|
||||
m.sh = Shared()
|
||||
var f = rodfiles.open(filename.string)
|
||||
f.loadHeader()
|
||||
f.loadSection configSection
|
||||
|
||||
f.loadPrim m.definedSymbols
|
||||
f.loadPrim m.cfg
|
||||
|
||||
if not configIdentical(m, config):
|
||||
f.err = configMismatch
|
||||
|
||||
f.loadSection stringsSection
|
||||
f.load m.sh.strings
|
||||
|
||||
f.loadSection checkSumsSection
|
||||
f.loadSeq m.includes
|
||||
if not includesIdentical(m, config):
|
||||
f.err = includeFileChanged
|
||||
|
||||
f.loadSection depsSection
|
||||
f.loadSeq m.imports
|
||||
|
||||
f.loadSection integersSection
|
||||
f.load m.sh.integers
|
||||
f.loadSection floatsSection
|
||||
f.load m.sh.floats
|
||||
|
||||
f.loadSection topLevelSection
|
||||
f.loadSeq m.topLevel.nodes
|
||||
|
||||
f.loadSection bodiesSection
|
||||
f.loadSeq m.bodies.nodes
|
||||
|
||||
f.loadSection symsSection
|
||||
f.loadSeq m.sh.syms
|
||||
|
||||
f.loadSection typesSection
|
||||
f.loadSeq m.sh.types
|
||||
|
||||
close(f)
|
||||
result = f.err
|
||||
|
||||
type
|
||||
ModuleStatus* = enum
|
||||
undefined,
|
||||
loading,
|
||||
loaded,
|
||||
outdated
|
||||
|
||||
LoadedModule* = object
|
||||
status: ModuleStatus
|
||||
symsInit, typesInit: bool
|
||||
fromDisk: PackedModule
|
||||
syms: seq[PSym] # indexed by itemId
|
||||
types: seq[PType]
|
||||
|
||||
PackedModuleGraph* = seq[LoadedModule] # indexed by FileIndex
|
||||
|
||||
proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef;
|
||||
fileIdx: FileIndex): bool =
|
||||
let m = int(fileIdx)
|
||||
if m >= g.len:
|
||||
g.setLen(m+1)
|
||||
|
||||
case g[m].status
|
||||
of undefined:
|
||||
g[m].status = loading
|
||||
let fullpath = msgs.toFullPath(conf, fileIdx)
|
||||
let rod = toRodFile(conf, AbsoluteFile fullpath)
|
||||
let err = loadRodFile(rod, g[m].fromDisk, conf)
|
||||
if err == ok:
|
||||
result = false
|
||||
# check its dependencies:
|
||||
for dep in g[m].fromDisk.imports:
|
||||
let fid = toFileIndex(dep, g[m].fromDisk, conf)
|
||||
# Warning: we need to traverse the full graph, so
|
||||
# do **not use break here**!
|
||||
if needsRecompile(g, conf, fid):
|
||||
result = true
|
||||
|
||||
g[m].status = if result: outdated else: loaded
|
||||
else:
|
||||
loadError(err, rod)
|
||||
g[m].status = outdated
|
||||
result = true
|
||||
of loading, loaded:
|
||||
result = false
|
||||
of outdated:
|
||||
result = true
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
proc storeError(err: RodFileError; filename: AbsoluteFile) =
|
||||
echo "Error: ", $err, "; couldn't write to ", filename.string
|
||||
removeFile(filename.string)
|
||||
|
||||
proc saveRodFile*(filename: AbsoluteFile; encoder: var PackedEncoder) =
|
||||
rememberConfig(encoder, encoder.config)
|
||||
|
||||
var f = rodfiles.create(filename.string)
|
||||
f.storeHeader()
|
||||
f.storeSection configSection
|
||||
f.storePrim encoder.m.definedSymbols
|
||||
f.storePrim encoder.m.cfg
|
||||
|
||||
f.storeSection stringsSection
|
||||
f.store encoder.m.sh.strings
|
||||
|
||||
f.storeSection checkSumsSection
|
||||
f.storeSeq encoder.m.includes
|
||||
|
||||
f.storeSection depsSection
|
||||
f.storeSeq encoder.m.imports
|
||||
|
||||
f.storeSection integersSection
|
||||
f.store encoder.m.sh.integers
|
||||
|
||||
f.storeSection floatsSection
|
||||
f.store encoder.m.sh.floats
|
||||
|
||||
f.storeSection topLevelSection
|
||||
f.storeSeq encoder.m.topLevel.nodes
|
||||
|
||||
f.storeSection bodiesSection
|
||||
f.storeSeq encoder.m.bodies.nodes
|
||||
|
||||
f.storeSection symsSection
|
||||
f.storeSeq encoder.m.sh.syms
|
||||
|
||||
f.storeSection typesSection
|
||||
f.storeSeq encoder.m.sh.types
|
||||
close(f)
|
||||
if f.err != ok:
|
||||
loadError(f.err, filename)
|
||||
|
||||
when true:
|
||||
# basic loader testing:
|
||||
var m2: PackedModule
|
||||
discard loadRodFile(filename, m2, encoder.config)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
PackedDecoder* = object
|
||||
thisModule*: int32
|
||||
lastLit*: LitId
|
||||
lastFile*: FileIndex # remember the last lookup entry.
|
||||
config*: ConfigRef
|
||||
ident: IdentCache
|
||||
|
||||
proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; t: PackedItemId): PType
|
||||
proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; s: PackedItemId): PSym
|
||||
|
||||
proc toFileIndexCached(c: var PackedDecoder; g: var PackedModuleGraph; f: LitId): FileIndex =
|
||||
if c.lastLit == f:
|
||||
result = c.lastFile
|
||||
else:
|
||||
result = toFileIndex(f, g[c.thisModule].fromDisk, c.config)
|
||||
c.lastLit = f
|
||||
c.lastFile = result
|
||||
|
||||
proc translateLineInfo(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
x: PackedLineInfo): TLineInfo =
|
||||
assert g[c.thisModule].status == loaded
|
||||
result = TLineInfo(line: x.line, col: x.col,
|
||||
fileIndex: toFileIndexCached(c, g, x.file))
|
||||
|
||||
proc loadNodes(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
tree: PackedTree; n: NodePos): PNode =
|
||||
let k = n.kind
|
||||
result = newNodeIT(k, translateLineInfo(c, g, n.info),
|
||||
loadType(c, g, n.typ))
|
||||
result.flags = n.flags
|
||||
|
||||
case k
|
||||
of nkEmpty, nkNilLit, nkType:
|
||||
discard
|
||||
of nkIdent:
|
||||
result.ident = getIdent(c.ident, g[c.thisModule].fromDisk.sh.strings[n.litId])
|
||||
of nkSym:
|
||||
result.sym = loadSym(c, g, PackedItemId(module: LitId(0), item: tree.nodes[n.int].operand))
|
||||
of directIntLit:
|
||||
result.intVal = tree.nodes[n.int].operand
|
||||
of externIntLit:
|
||||
result.intVal = g[c.thisModule].fromDisk.sh.integers[n.litId]
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
result.strVal = g[c.thisModule].fromDisk.sh.strings[n.litId]
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
result.floatVal = g[c.thisModule].fromDisk.sh.floats[n.litId]
|
||||
of nkModuleRef:
|
||||
let (n1, n2) = sons2(tree, n)
|
||||
assert n1.kind == nkInt32Lit
|
||||
assert n2.kind == nkInt32Lit
|
||||
transitionNoneToSym(result)
|
||||
result.sym = loadSym(c, g, PackedItemId(module: n1.litId, item: tree.nodes[n2.int].operand))
|
||||
else:
|
||||
for n0 in sonsReadonly(tree, n):
|
||||
result.add loadNodes(c, g, tree, n0)
|
||||
|
||||
proc moduleIndex*(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
s: PackedItemId): int32 {.inline.} =
|
||||
result = if s.module == LitId(0): c.thisModule
|
||||
else: toFileIndexCached(c, g, s.module).int32
|
||||
|
||||
proc symHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
s: PackedSym; si, item: int32): PSym =
|
||||
result = PSym(itemId: ItemId(module: si, item: item),
|
||||
kind: s.kind, magic: s.magic, flags: s.flags,
|
||||
info: translateLineInfo(c, g, s.info),
|
||||
options: s.options,
|
||||
position: s.position,
|
||||
name: getIdent(c.ident, g[si].fromDisk.sh.strings[s.name])
|
||||
)
|
||||
|
||||
template loadAstBody(p, field) =
|
||||
if p.field != emptyNodeId:
|
||||
result.field = loadNodes(c, g, g[si].fromDisk.bodies, NodePos p.field)
|
||||
|
||||
proc loadLib(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
si, item: int32; l: PackedLib): PLib =
|
||||
# XXX: hack; assume a zero LitId means the PackedLib is all zero (empty)
|
||||
if l.name.int == 0:
|
||||
result = nil
|
||||
else:
|
||||
result = PLib(generated: l.generated, isOverriden: l.isOverriden,
|
||||
kind: l.kind, name: rope g[si].fromDisk.sh.strings[l.name])
|
||||
loadAstBody(l, path)
|
||||
|
||||
proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
s: PackedSym; si, item: int32; result: PSym) =
|
||||
result.typ = loadType(c, g, s.typ)
|
||||
loadAstBody(s, constraint)
|
||||
loadAstBody(s, ast)
|
||||
result.annex = loadLib(c, g, si, item, s.annex)
|
||||
when hasFFI:
|
||||
result.cname = g[si].fromDisk.sh.strings[s.cname]
|
||||
|
||||
if s.kind in {skLet, skVar, skField, skForVar}:
|
||||
result.guard = loadSym(c, g, s.guard)
|
||||
result.bitsize = s.bitsize
|
||||
result.alignment = s.alignment
|
||||
result.owner = loadSym(c, g, s.owner)
|
||||
let externalName = g[si].fromDisk.sh.strings[s.externalName]
|
||||
if externalName != "":
|
||||
result.loc.r = rope externalName
|
||||
|
||||
proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; s: PackedItemId): PSym =
|
||||
if s == nilTypeId:
|
||||
result = nil
|
||||
else:
|
||||
let si = moduleIndex(c, g, s)
|
||||
assert g[si].status == loaded
|
||||
if not g[si].symsInit:
|
||||
g[si].symsInit = true
|
||||
setLen g[si].syms, g[si].fromDisk.sh.syms.len
|
||||
|
||||
if g[si].syms[s.item] == nil:
|
||||
let packed = addr(g[si].fromDisk.sh.syms[s.item])
|
||||
result = symHeaderFromPacked(c, g, packed[], si, s.item)
|
||||
# store it here early on, so that recursions work properly:
|
||||
g[si].syms[s.item] = result
|
||||
symBodyFromPacked(c, g, packed[], si, s.item, result)
|
||||
else:
|
||||
result = g[si].syms[s.item]
|
||||
|
||||
proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32): PType =
|
||||
result = PType(itemId: ItemId(module: si, item: t.nonUniqueId), kind: t.kind,
|
||||
flags: t.flags, size: t.size, align: t.align,
|
||||
paddingAtEnd: t.paddingAtEnd, lockLevel: t.lockLevel,
|
||||
uniqueId: ItemId(module: si, item: item))
|
||||
|
||||
proc typeBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32; result: PType) =
|
||||
result.sym = loadSym(c, g, t.sym)
|
||||
result.owner = loadSym(c, g, t.owner)
|
||||
for op, item in pairs t.attachedOps:
|
||||
result.attachedOps[op] = loadSym(c, g, item)
|
||||
result.typeInst = loadType(c, g, t.typeInst)
|
||||
for son in items t.types:
|
||||
result.sons.add loadType(c, g, son)
|
||||
loadAstBody(t, n)
|
||||
for gen, id in items t.methods:
|
||||
result.methods.add((gen, loadSym(c, g, id)))
|
||||
|
||||
proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; t: PackedItemId): PType =
|
||||
if t == nilTypeId:
|
||||
result = nil
|
||||
else:
|
||||
let si = moduleIndex(c, g, t)
|
||||
assert g[si].status == loaded
|
||||
if not g[si].typesInit:
|
||||
g[si].typesInit = true
|
||||
setLen g[si].types, g[si].fromDisk.sh.types.len
|
||||
|
||||
if g[si].types[t.item] == nil:
|
||||
let packed = addr(g[si].fromDisk.sh.types[t.item])
|
||||
result = typeHeaderFromPacked(c, g, packed[], si, t.item)
|
||||
# store it here early on, so that recursions work properly:
|
||||
g[si].types[t.item] = result
|
||||
typeBodyFromPacked(c, g, packed[], si, t.item, result)
|
||||
else:
|
||||
result = g[si].types[t.item]
|
||||
|
||||
|
||||
when false:
|
||||
proc initGenericKey*(s: PSym; types: seq[PType]): GenericKey =
|
||||
result.module = s.owner.itemId.module
|
||||
result.name = s.name.s
|
||||
result.types = mapIt types: hashType(it, {CoType, CoDistinct}).MD5Digest
|
||||
|
||||
proc addGeneric*(m: var Module; c: var PackedEncoder; key: GenericKey; s: PSym) =
|
||||
## add a generic to the module
|
||||
if key notin m.generics:
|
||||
m.generics[key] = toPackedSym(s, m.ast, c)
|
||||
toPackedNode(s.ast, m.ast, c)
|
||||
|
||||
@@ -220,12 +220,13 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
|
||||
localError(c.config, n.info, "module alias must be an identifier")
|
||||
elif n[1].ident.id != realModule.name.id:
|
||||
# some misguided guy will write 'import abc.foo as foo' ...
|
||||
result = createModuleAlias(realModule, nextId c.idgen, n[1].ident, realModule.info,
|
||||
result = createModuleAlias(realModule, nextSymId c.idgen, n[1].ident, realModule.info,
|
||||
c.config.options)
|
||||
|
||||
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =
|
||||
let f = checkModuleName(c.config, n)
|
||||
if f != InvalidFileIdx:
|
||||
addImportFileDep(c, f)
|
||||
let L = c.graph.importStack.len
|
||||
let recursion = c.graph.importStack.find(f)
|
||||
c.graph.importStack.add f
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2018 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Basic type definitions the module graph needs in order to support
|
||||
## incremental compilations.
|
||||
|
||||
const nimIncremental* = defined(nimIncremental)
|
||||
|
||||
import options, lineinfos
|
||||
|
||||
when nimIncremental:
|
||||
import ast, msgs, intsets, btrees, db_sqlite, std / sha1, pathutils
|
||||
from strutils import parseInt
|
||||
from os import isAbsolute
|
||||
|
||||
type
|
||||
Writer* = object
|
||||
sstack*: seq[PSym] # a stack of symbols to process
|
||||
tstack*: seq[PType] # a stack of types to process
|
||||
tmarks*, smarks*: IntSet
|
||||
forwardedSyms*: seq[PSym]
|
||||
|
||||
Reader* = object
|
||||
syms*: BTree[int, PSym]
|
||||
types*: BTree[int, PType]
|
||||
|
||||
IncrementalCtx* = object
|
||||
db*: DbConn
|
||||
w*: Writer
|
||||
r*: Reader
|
||||
configChanged*: bool
|
||||
|
||||
proc init*(incr: var IncrementalCtx) =
|
||||
incr.w.sstack = @[]
|
||||
incr.w.tstack = @[]
|
||||
incr.w.tmarks = initIntSet()
|
||||
incr.w.smarks = initIntSet()
|
||||
incr.w.forwardedSyms = @[]
|
||||
incr.r.syms = initBTree[int, PSym]()
|
||||
incr.r.types = initBTree[int, PType]()
|
||||
|
||||
|
||||
proc hashFileCached*(conf: ConfigRef; fileIdx: FileIndex; fullpath: AbsoluteFile): string =
|
||||
result = msgs.getHash(conf, fileIdx)
|
||||
if result.len == 0 and isAbsolute(string fullpath):
|
||||
result = $secureHashFile(string fullpath)
|
||||
msgs.setHash(conf, fileIdx, result)
|
||||
|
||||
proc toDbFileId*(incr: var IncrementalCtx; conf: ConfigRef; fileIdx: FileIndex): int =
|
||||
if fileIdx == FileIndex(-1): return -1
|
||||
let fullpath = toFullPath(conf, fileIdx)
|
||||
let row = incr.db.getRow(sql"select id, fullhash from filenames where fullpath = ?",
|
||||
fullpath)
|
||||
let id = row[0]
|
||||
let fullhash = hashFileCached(conf, fileIdx, AbsoluteFile fullpath)
|
||||
if id.len == 0:
|
||||
result = int incr.db.insertID(sql"insert into filenames(nimid, fullpath, fullhash) values (?, ?, ?)",
|
||||
int(fileIdx), fullpath, fullhash)
|
||||
else:
|
||||
if row[1] != fullhash:
|
||||
incr.db.exec(sql"update filenames set fullhash = ? where fullpath = ?", fullhash, fullpath)
|
||||
result = parseInt(id)
|
||||
|
||||
proc fromDbFileId*(incr: var IncrementalCtx; conf: ConfigRef; dbId: int): FileIndex =
|
||||
if dbId == -1: return FileIndex(-1)
|
||||
let fullpath = incr.db.getValue(sql"select fullpath from filenames where id = ?", dbId)
|
||||
doAssert fullpath.len > 0, "cannot find file name for DB ID " & $dbId
|
||||
result = fileInfoIdx(conf, AbsoluteFile fullpath)
|
||||
|
||||
|
||||
proc addModuleDep*(incr: var IncrementalCtx; conf: ConfigRef;
|
||||
module, fileIdx: FileIndex;
|
||||
isIncludeFile: bool) =
|
||||
if conf.symbolFiles != v2Sf: return
|
||||
|
||||
let a = toDbFileId(incr, conf, module)
|
||||
let b = toDbFileId(incr, conf, fileIdx)
|
||||
|
||||
incr.db.exec(sql"insert into deps(module, dependency, isIncludeFile) values (?, ?, ?)",
|
||||
a, b, ord(isIncludeFile))
|
||||
|
||||
# --------------- Database model ---------------------------------------------
|
||||
|
||||
proc createDb*(db: DbConn) =
|
||||
db.exec(sql"""
|
||||
create table if not exists controlblock(
|
||||
idgen integer not null
|
||||
);
|
||||
""")
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists config(
|
||||
config varchar(8000) not null
|
||||
);
|
||||
""")
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists filenames(
|
||||
id integer primary key,
|
||||
nimid integer not null,
|
||||
fullpath varchar(8000) not null,
|
||||
fullHash varchar(256) not null
|
||||
);
|
||||
""")
|
||||
db.exec sql"create index if not exists FilenameIx on filenames(fullpath);"
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists modules(
|
||||
id integer primary key,
|
||||
nimid integer not null,
|
||||
fullpath varchar(8000) not null,
|
||||
interfHash varchar(256) not null,
|
||||
fullHash varchar(256) not null,
|
||||
|
||||
created timestamp not null default (DATETIME('now'))
|
||||
);""")
|
||||
db.exec(sql"""create unique index if not exists SymNameIx on modules(fullpath);""")
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists deps(
|
||||
id integer primary key,
|
||||
module integer not null,
|
||||
dependency integer not null,
|
||||
isIncludeFile integer not null,
|
||||
foreign key (module) references filenames(id),
|
||||
foreign key (dependency) references filenames(id)
|
||||
);""")
|
||||
db.exec(sql"""create index if not exists DepsIx on deps(module);""")
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists types(
|
||||
id integer primary key,
|
||||
nimid integer not null,
|
||||
module integer not null,
|
||||
data blob not null,
|
||||
foreign key (module) references module(id)
|
||||
);
|
||||
""")
|
||||
db.exec sql"create index TypeByModuleIdx on types(module);"
|
||||
db.exec sql"create index TypeByNimIdIdx on types(nimid);"
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists syms(
|
||||
id integer primary key,
|
||||
nimid integer not null,
|
||||
module integer not null,
|
||||
name varchar(256) not null,
|
||||
data blob not null,
|
||||
exported int not null,
|
||||
foreign key (module) references module(id)
|
||||
);
|
||||
""")
|
||||
db.exec sql"create index if not exists SymNameIx on syms(name);"
|
||||
db.exec sql"create index SymByNameAndModuleIdx on syms(name, module);"
|
||||
db.exec sql"create index SymByModuleIdx on syms(module);"
|
||||
db.exec sql"create index SymByNimIdIdx on syms(nimid);"
|
||||
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists toplevelstmts(
|
||||
id integer primary key,
|
||||
position integer not null,
|
||||
module integer not null,
|
||||
data blob not null,
|
||||
foreign key (module) references module(id)
|
||||
);
|
||||
""")
|
||||
db.exec sql"create index TopLevelStmtByModuleIdx on toplevelstmts(module);"
|
||||
db.exec sql"create index TopLevelStmtByPositionIdx on toplevelstmts(position);"
|
||||
|
||||
db.exec(sql"""
|
||||
create table if not exists statics(
|
||||
id integer primary key,
|
||||
module integer not null,
|
||||
data blob not null,
|
||||
foreign key (module) references module(id)
|
||||
);
|
||||
""")
|
||||
db.exec sql"create index StaticsByModuleIdx on toplevelstmts(module);"
|
||||
db.exec sql"insert into controlblock(idgen) values (0)"
|
||||
|
||||
|
||||
else:
|
||||
type
|
||||
IncrementalCtx* = object
|
||||
|
||||
template init*(incr: IncrementalCtx) = discard
|
||||
|
||||
template addModuleDep*(incr: var IncrementalCtx; conf: ConfigRef;
|
||||
module, fileIdx: FileIndex;
|
||||
isIncludeFile: bool) =
|
||||
discard
|
||||
@@ -62,7 +62,7 @@ template dbg(body) =
|
||||
body
|
||||
|
||||
proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
|
||||
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), nextId c.idgen, c.owner, info)
|
||||
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), nextSymId c.idgen, c.owner, info)
|
||||
sym.typ = typ
|
||||
s.vars.add(sym)
|
||||
result = newSymNode(sym)
|
||||
@@ -252,7 +252,7 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
|
||||
localError(c.graph.config, ri.info, errGenerated, m)
|
||||
|
||||
proc makePtrType(c: var Con, baseType: PType): PType =
|
||||
result = newType(tyPtr, nextId c.idgen, c.owner)
|
||||
result = newType(tyPtr, nextTypeId c.idgen, c.owner)
|
||||
addSonSkipIntLit(result, baseType, c.idgen)
|
||||
|
||||
proc genOp(c: var Con; op: PSym; dest: PNode): PNode =
|
||||
@@ -415,7 +415,7 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
else:
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
|
||||
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), nextId c.idgen, c.owner, n.info)
|
||||
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), nextSymId c.idgen, c.owner, n.info)
|
||||
temp.typ = n.typ
|
||||
var v = newNodeI(nkLetSection, n.info)
|
||||
let tempAsNode = newSymNode(temp)
|
||||
|
||||
@@ -130,14 +130,14 @@ proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator)
|
||||
var n = newNodeI(nkRange, iter.info)
|
||||
n.add newIntNode(nkIntLit, -1)
|
||||
n.add newIntNode(nkIntLit, 0)
|
||||
result = newType(tyRange, nextId(idgen), iter)
|
||||
result = newType(tyRange, nextTypeId(idgen), iter)
|
||||
result.n = n
|
||||
var intType = nilOrSysInt(g)
|
||||
if intType.isNil: intType = newType(tyInt, nextId(idgen), iter)
|
||||
if intType.isNil: intType = newType(tyInt, nextTypeId(idgen), iter)
|
||||
rawAddSon(result, intType)
|
||||
|
||||
proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
result = newSym(skField, getIdent(g.cache, ":state"), nextId(idgen), iter, iter.info)
|
||||
result = newSym(skField, getIdent(g.cache, ":state"), nextSymId(idgen), iter, iter.info)
|
||||
result.typ = createClosureIterStateType(g, iter, idgen)
|
||||
|
||||
proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
|
||||
@@ -151,7 +151,7 @@ proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym
|
||||
result = iter.ast[resultPos].sym
|
||||
else:
|
||||
# XXX a bit hacky:
|
||||
result = newSym(skResult, getIdent(g.cache, ":result"), nextId(idgen), iter, iter.info, {})
|
||||
result = newSym(skResult, getIdent(g.cache, ":result"), nextSymId(idgen), iter, iter.info, {})
|
||||
result.typ = iter.typ[0]
|
||||
incl(result.flags, sfUsed)
|
||||
iter.ast.add newSymNode(result)
|
||||
@@ -259,7 +259,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PN
|
||||
addUniqueField(it.typ.skipTypes({tyOwned})[0], hp, g.cache, idgen)
|
||||
env = indirectAccess(newSymNode(it), hp, hp.info)
|
||||
else:
|
||||
let e = newSym(skLet, iter.name, nextId(idgen), owner, n.info)
|
||||
let e = newSym(skLet, iter.name, nextSymId(idgen), owner, n.info)
|
||||
e.typ = hp.typ
|
||||
e.flags = hp.flags
|
||||
env = newSymNode(e)
|
||||
@@ -330,7 +330,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
|
||||
info: TLineInfo): PType =
|
||||
result = c.ownerToType.getOrDefault(owner.id)
|
||||
if result.isNil:
|
||||
result = newType(tyRef, nextId(c.idgen), owner)
|
||||
result = newType(tyRef, nextTypeId(c.idgen), owner)
|
||||
let obj = createEnvObj(c.graph, c.idgen, owner, info)
|
||||
rawAddSon(result, obj)
|
||||
c.ownerToType[owner.id] = result
|
||||
@@ -338,7 +338,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
|
||||
proc asOwnedRef(c: var DetectionPass; t: PType): PType =
|
||||
if optOwnedRefs in c.graph.config.globalOptions:
|
||||
assert t.kind == tyRef
|
||||
result = newType(tyOwned, nextId(c.idgen), t.owner)
|
||||
result = newType(tyOwned, nextTypeId(c.idgen), t.owner)
|
||||
result.flags.incl tfHasOwned
|
||||
result.rawAddSon t
|
||||
else:
|
||||
@@ -347,7 +347,7 @@ proc asOwnedRef(c: var DetectionPass; t: PType): PType =
|
||||
proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
|
||||
info: TLineInfo): PType =
|
||||
var r = c.getEnvTypeForOwner(owner, info)
|
||||
result = newType(tyPtr, nextId(c.idgen), owner)
|
||||
result = newType(tyPtr, nextTypeId(c.idgen), owner)
|
||||
rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr}))
|
||||
|
||||
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||
@@ -375,7 +375,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) =
|
||||
if c.graph.config.selectedGC == gcDestructors and sfCursor notin upField.flags:
|
||||
localError(c.graph.config, dep.info, "internal error: up reference is not a .cursor")
|
||||
else:
|
||||
let result = newSym(skField, upIdent, nextId(c.idgen), obj.owner, obj.owner.info)
|
||||
let result = newSym(skField, upIdent, nextSymId(c.idgen), obj.owner, obj.owner.info)
|
||||
result.typ = fieldType
|
||||
when false:
|
||||
if c.graph.config.selectedGC == gcDestructors:
|
||||
@@ -413,7 +413,7 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
|
||||
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
|
||||
let t = c.getEnvTypeForOwner(owner, info)
|
||||
if cp == nil:
|
||||
cp = newSym(skParam, getIdent(c.graph.cache, paramName), nextId(c.idgen), fn, fn.info)
|
||||
cp = newSym(skParam, getIdent(c.graph.cache, paramName), nextSymId(c.idgen), fn, fn.info)
|
||||
incl(cp.flags, sfFromGeneric)
|
||||
cp.typ = t
|
||||
addHiddenParam(fn, cp)
|
||||
@@ -539,7 +539,7 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode =
|
||||
result = n
|
||||
|
||||
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo; idgen: IdGenerator): PNode =
|
||||
var v = newSym(skVar, getIdent(cache, envName), nextId(idgen), owner, info)
|
||||
var v = newSym(skVar, getIdent(cache, envName), nextSymId(idgen), owner, info)
|
||||
v.flags = {sfShadowed, sfGeneratedOp}
|
||||
v.typ = typ
|
||||
result = newSymNode(v)
|
||||
@@ -563,7 +563,7 @@ proc setupEnvVar(owner: PSym; d: var DetectionPass;
|
||||
result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info, d.idgen)
|
||||
c.envVars[owner.id] = result
|
||||
if optOwnedRefs in d.graph.config.globalOptions:
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), nextId d.idgen, owner, info)
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), nextSymId d.idgen, owner, info)
|
||||
v.flags = {sfShadowed, sfGeneratedOp}
|
||||
v.typ = envVarType
|
||||
c.unownedEnvVars[owner.id] = newSymNode(v)
|
||||
@@ -647,7 +647,7 @@ proc closureCreationForIter(iter: PNode;
|
||||
d: var DetectionPass; c: var LiftingPass): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ)
|
||||
let owner = iter.sym.skipGenericOwner
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName), nextId(d.idgen), owner, iter.info)
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName), nextSymId(d.idgen), owner, iter.info)
|
||||
incl(v.flags, sfShadowed)
|
||||
v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ)
|
||||
var vnode: PNode
|
||||
@@ -937,7 +937,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym):
|
||||
let iter = op.sym
|
||||
|
||||
let hp = getHiddenParam(g, iter)
|
||||
env = newSym(skLet, iter.name, nextId(idgen), owner, body.info)
|
||||
env = newSym(skLet, iter.name, nextSymId(idgen), owner, body.info)
|
||||
env.typ = hp.typ
|
||||
env.flags = hp.flags
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
# for every field (dependent on dest.kind):
|
||||
# `=` dest.field, src.field
|
||||
# =destroy(blob)
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId c.idgen, c.fn, c.info)
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId c.idgen, c.fn, c.info)
|
||||
temp.typ = x.typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
var v = newNodeI(nkVarSection, c.info)
|
||||
@@ -317,7 +317,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
|
||||
if optSeqDestructors in c.g.config.globalOptions:
|
||||
var op = field
|
||||
let destructorOverriden = destructorOverriden(t)
|
||||
if op != nil and op != c.fn and
|
||||
if op != nil and op != c.fn and
|
||||
(sfOverriden in op.flags or destructorOverriden):
|
||||
if sfError in op.flags:
|
||||
incl c.fn.flags, sfError
|
||||
@@ -412,7 +412,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||
result = true
|
||||
|
||||
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId(c.idgen), c.fn, c.info)
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId(c.idgen), c.fn, c.info)
|
||||
temp.typ = getSysType(c.g, body.info, tyInt)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
@@ -422,7 +422,7 @@ proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
body.add v
|
||||
|
||||
proc declareTempOf(c: var TLiftCtx; body: PNode; value: PNode): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId(c.idgen), c.fn, c.info)
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextSymId(c.idgen), c.fn, c.info)
|
||||
temp.typ = value.typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
|
||||
@@ -899,17 +899,17 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
info: TLineInfo; idgen: IdGenerator): PSym =
|
||||
|
||||
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
||||
result = newSym(skProc, procname, nextId(idgen), owner, info)
|
||||
let dest = newSym(skParam, getIdent(g.cache, "dest"), nextId(idgen), result, info)
|
||||
result = newSym(skProc, procname, nextSymId(idgen), owner, info)
|
||||
let dest = newSym(skParam, getIdent(g.cache, "dest"), nextSymId(idgen), result, info)
|
||||
let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
|
||||
nextId(idgen), result, info)
|
||||
nextSymId(idgen), result, info)
|
||||
dest.typ = makeVarType(typ.owner, typ, idgen)
|
||||
if kind == attachedTrace:
|
||||
src.typ = getSysType(g, info, tyPointer)
|
||||
else:
|
||||
src.typ = typ
|
||||
|
||||
result.typ = newProcType(info, nextId(idgen), owner)
|
||||
result.typ = newProcType(info, nextTypeId(idgen), owner)
|
||||
result.typ.addParam dest
|
||||
if kind notin {attachedDestructor, attachedDispose}:
|
||||
result.typ.addParam src
|
||||
@@ -917,7 +917,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
if kind == attachedAsgn and g.config.selectedGC == gcOrc and
|
||||
cyclicType(typ.skipTypes(abstractInst)):
|
||||
let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"),
|
||||
nextId(idgen), result, info)
|
||||
nextSymId(idgen), result, info)
|
||||
cycleParam.typ = getSysType(g, info, tyBool)
|
||||
result.typ.addParam cycleParam
|
||||
|
||||
@@ -983,7 +983,7 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym,
|
||||
a.addMemReset = true
|
||||
let discrimantDest = result.typ.n[1].sym
|
||||
|
||||
let dst = newSym(skVar, getIdent(g.cache, "dest"), nextId(idgen), result, info)
|
||||
let dst = newSym(skVar, getIdent(g.cache, "dest"), nextSymId(idgen), result, info)
|
||||
dst.typ = makePtrType(typ.owner, typ, idgen)
|
||||
let dstSym = newSymNode(dst)
|
||||
let d = newDeref(dstSym)
|
||||
|
||||
@@ -227,7 +227,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
|
||||
considerQuotedIdent(c, m)
|
||||
else:
|
||||
getIdent(c.cache, "err:" & renderTree(m))
|
||||
result = newSym(skError, ident, nextId(c.idgen), getCurrOwner(c), n.info, {})
|
||||
result = newSym(skError, ident, nextSymId(c.idgen), getCurrOwner(c), n.info, {})
|
||||
result.typ = errorType(c)
|
||||
incl(result.flags, sfDiscardable)
|
||||
# pretend it's from the top level scope to prevent cascading errors:
|
||||
|
||||
@@ -71,7 +71,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: P
|
||||
let value = n.lastSon
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen),
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
@@ -91,7 +91,7 @@ proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): P
|
||||
## freely, multiple times. This is frequently required and such a builtin would also be
|
||||
## handy to have in macros.nim. The value that can be reused is 'result.lastSon'!
|
||||
result = newNodeIT(nkStmtListExpr, value.info, value.typ)
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen),
|
||||
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId(idgen),
|
||||
owner, value.info, g.config.options)
|
||||
temp.typ = skipTypes(value.typ, abstractInst)
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
@@ -117,7 +117,7 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; o
|
||||
let value = n.lastSon
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
var temp = newSym(skTemp, getIdent(g.cache, "_"), nextId(idgen), owner, value.info, owner.options)
|
||||
var temp = newSym(skTemp, getIdent(g.cache, "_"), nextSymId(idgen), owner, value.info, owner.options)
|
||||
var v = newNodeI(nkLetSection, value.info)
|
||||
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
|
||||
|
||||
@@ -135,7 +135,7 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; o
|
||||
proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
|
||||
var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextId(idgen), owner, n.info, owner.options)
|
||||
var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextSymId(idgen), owner, n.info, owner.options)
|
||||
temp.typ = n[1].typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
incl(temp.flags, sfGenSym)
|
||||
@@ -154,7 +154,7 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNod
|
||||
result.add newFastAsgnStmt(n[2], tempAsNode)
|
||||
|
||||
proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType =
|
||||
result = newType(tyObject, nextId(idgen), owner)
|
||||
result = newType(tyObject, nextTypeId(idgen), owner)
|
||||
if final:
|
||||
rawAddSon(result, nil)
|
||||
incl result.flags, tfFinal
|
||||
@@ -162,7 +162,7 @@ proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo
|
||||
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
|
||||
result.n = newNodeI(nkRecList, info)
|
||||
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
|
||||
nextId(idgen),
|
||||
nextSymId(idgen),
|
||||
owner, info, owner.options)
|
||||
incl s.flags, sfAnon
|
||||
s.typ = result
|
||||
@@ -225,7 +225,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) =
|
||||
# because of 'gensym' support, we have to mangle the name with its ID.
|
||||
# This is hacky but the clean solution is much more complex than it looks.
|
||||
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len),
|
||||
nextId(idgen), s.owner, s.info, s.options)
|
||||
nextSymId(idgen), s.owner, s.info, s.options)
|
||||
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
|
||||
let t = skipIntLit(s.typ, idgen)
|
||||
field.typ = t
|
||||
@@ -239,7 +239,7 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) =
|
||||
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} =
|
||||
result = lookupInRecord(obj.n, s.itemId)
|
||||
if result == nil:
|
||||
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextId(idgen),
|
||||
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextSymId(idgen),
|
||||
s.owner, s.info, s.options)
|
||||
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
|
||||
let t = skipIntLit(s.typ, idgen)
|
||||
@@ -326,7 +326,7 @@ proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
|
||||
proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode =
|
||||
result = newNodeI(nkAddr, n.info, 1)
|
||||
result[0] = n
|
||||
result.typ = newType(typeKind, nextId(idgen), n.typ.owner)
|
||||
result.typ = newType(typeKind, nextTypeId(idgen), n.typ.owner)
|
||||
result.typ.rawAddSon(n.typ)
|
||||
|
||||
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
|
||||
|
||||
@@ -21,7 +21,7 @@ proc registerSysType*(g: ModuleGraph; t: PType) =
|
||||
if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t
|
||||
|
||||
proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType =
|
||||
result = newType(kind, nextId(g.idgen), g.systemModule)
|
||||
result = newType(kind, nextTypeId(g.idgen), g.systemModule)
|
||||
result.size = size
|
||||
result.align = size.int16
|
||||
|
||||
@@ -29,8 +29,8 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym =
|
||||
result = strTableGet(g.systemModule.tab, getIdent(g.cache, name))
|
||||
if result == nil:
|
||||
localError(g.config, info, "system module needs: " & name)
|
||||
result = newSym(skError, getIdent(g.cache, name), nextId(g.idgen), g.systemModule, g.systemModule.info, {})
|
||||
result.typ = newType(tyError, nextId(g.idgen), g.systemModule)
|
||||
result = newSym(skError, getIdent(g.cache, name), nextSymId(g.idgen), g.systemModule, g.systemModule.info, {})
|
||||
result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule)
|
||||
if result.kind == skAlias: result = result.owner
|
||||
|
||||
proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym =
|
||||
@@ -45,8 +45,8 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy
|
||||
r = nextIdentIter(ti, g.systemModule.tab)
|
||||
if result != nil: return result
|
||||
localError(g.config, info, "system module needs: " & name)
|
||||
result = newSym(skError, id, nextId(g.idgen), g.systemModule, g.systemModule.info, {})
|
||||
result.typ = newType(tyError, nextId(g.idgen), g.systemModule)
|
||||
result = newSym(skError, id, nextSymId(g.idgen), g.systemModule, g.systemModule.info, {})
|
||||
result.typ = newType(tyError, nextTypeId(g.idgen), g.systemModule)
|
||||
|
||||
proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType =
|
||||
result = getSysSym(g, info, name).typ
|
||||
@@ -101,12 +101,12 @@ proc getIntLitType*(g: ModuleGraph; literal: PNode): PType =
|
||||
result = g.intTypeCache[value.int]
|
||||
if result == nil:
|
||||
let ti = getSysType(g, literal.info, tyInt)
|
||||
result = copyType(ti, nextId(g.idgen), ti.owner)
|
||||
result = copyType(ti, nextTypeId(g.idgen), ti.owner)
|
||||
result.n = literal
|
||||
g.intTypeCache[value.int] = result
|
||||
else:
|
||||
let ti = getSysType(g, literal.info, tyInt)
|
||||
result = copyType(ti, nextId(g.idgen), ti.owner)
|
||||
result = copyType(ti, nextTypeId(g.idgen), ti.owner)
|
||||
result.n = literal
|
||||
|
||||
proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType =
|
||||
@@ -116,7 +116,7 @@ proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType =
|
||||
|
||||
proc skipIntLit*(t: PType; id: IdGenerator): PType {.inline.} =
|
||||
if t.n != nil and t.kind in {tyInt, tyFloat}:
|
||||
result = copyType(t, nextId(id), t.owner)
|
||||
result = copyType(t, nextTypeId(id), t.owner)
|
||||
result.n = nil
|
||||
else:
|
||||
result = t
|
||||
|
||||
@@ -19,7 +19,7 @@ import
|
||||
cgen, json, nversion,
|
||||
platform, nimconf, passaux, depends, vm,
|
||||
modules,
|
||||
modulegraphs, tables, rod, lineinfos, pathutils, vmprofiler
|
||||
modulegraphs, tables, lineinfos, pathutils, vmprofiler
|
||||
|
||||
when not defined(leanCompiler):
|
||||
import jsgen, docgen, docgen2
|
||||
@@ -137,7 +137,7 @@ proc commandInteractive(graph: ModuleGraph) =
|
||||
else:
|
||||
var m = graph.makeStdinModule()
|
||||
incl(m.flags, sfMainModule)
|
||||
var idgen = IdGenerator(module: m.itemId.module, item: m.itemId.item)
|
||||
var idgen = IdGenerator(module: m.itemId.module, symId: m.itemId.item, typeId: 0)
|
||||
let s = llStreamOpenStdIn(onPrompt = proc() = flushDot(graph.config))
|
||||
processModule(graph, m, idgen, s)
|
||||
|
||||
@@ -165,7 +165,6 @@ proc mainCommand*(graph: ModuleGraph) =
|
||||
let conf = graph.config
|
||||
let cache = graph.cache
|
||||
|
||||
setupModuleCache(graph)
|
||||
# In "nim serve" scenario, each command must reset the registered passes
|
||||
clearPasses(graph)
|
||||
conf.lastCmdTime = epochTime()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## This module implements the module graph data structure. The module graph
|
||||
## represents a complete Nim project. Single modules can either be kept in RAM
|
||||
## or stored in a Sqlite database.
|
||||
## or stored in a rod-file.
|
||||
##
|
||||
## The caching of modules is critical for 'nimsuggest' and is tricky to get
|
||||
## right. If module E is being edited, we need autocompletion (and type
|
||||
@@ -26,7 +26,7 @@
|
||||
##
|
||||
|
||||
import ast, intsets, tables, options, lineinfos, hashes, idents,
|
||||
incremental, btrees, md5
|
||||
btrees, md5
|
||||
|
||||
# import ic / packed_ast
|
||||
|
||||
@@ -67,7 +67,6 @@ type
|
||||
intTypeCache*: array[-5..64, PType]
|
||||
opContains*, opNot*: PSym
|
||||
emptyNode*: PNode
|
||||
incr*: IncrementalCtx
|
||||
canonTypes*: Table[SigHash, PType]
|
||||
symBodyHashes*: Table[int, SigHash] # symId to digest mapping
|
||||
importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.}
|
||||
@@ -176,7 +175,7 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
|
||||
result = g.doStopCompile != nil and g.doStopCompile()
|
||||
|
||||
proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
|
||||
result = newSym(skProc, getIdent(g.cache, name), nextId(g.idgen), nil, unknownLineInfo, {})
|
||||
result = newSym(skProc, getIdent(g.cache, name), nextSymId(g.idgen), nil, unknownLineInfo, {})
|
||||
result.magic = m
|
||||
result.flags = {sfNeverRaises}
|
||||
|
||||
@@ -190,7 +189,7 @@ proc registerModule*(g: ModuleGraph; m: PSym) =
|
||||
|
||||
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result = ModuleGraph()
|
||||
result.idgen = IdGenerator(module: -1'i32, item: 0'i32)
|
||||
result.idgen = IdGenerator(module: -1'i32, symId: 0'i32, typeId: 0'i32)
|
||||
initStrTable(result.packageSyms)
|
||||
result.deps = initIntSet()
|
||||
result.importDeps = initTable[FileIndex, seq[FileIndex]]()
|
||||
@@ -206,7 +205,6 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
|
||||
result.opNot = createMagic(result, "not", mNot)
|
||||
result.opContains = createMagic(result, "contains", mInSet)
|
||||
result.emptyNode = newNode(nkEmpty)
|
||||
init(result.incr)
|
||||
result.recordStmt = proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.} =
|
||||
discard
|
||||
result.cacheSeqs = initTable[string, PNode]()
|
||||
@@ -235,7 +233,6 @@ proc dependsOn(a, b: int): int {.inline.} = (a shl 15) + b
|
||||
|
||||
proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
|
||||
assert m.position == m.info.fileIndex.int32
|
||||
addModuleDep(g.incr, g.config, m.info.fileIndex, dep, isIncludeFile = false)
|
||||
if g.suggestMode:
|
||||
g.deps.incl m.position.dependsOn(dep.int)
|
||||
# we compute the transitive closure later when querying the graph lazily.
|
||||
@@ -243,7 +240,6 @@ proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) =
|
||||
#invalidTransitiveClosure = true
|
||||
|
||||
proc addIncludeDep*(g: ModuleGraph; module, includeFile: FileIndex) =
|
||||
addModuleDep(g.incr, g.config, module, includeFile, isIncludeFile = true)
|
||||
discard hasKeyOrPut(g.inclToMod, includeFile, module)
|
||||
|
||||
proc parentModule*(g: ModuleGraph; fileIdx: FileIndex): FileIndex =
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
ast, astalgo, magicsys, msgs, options,
|
||||
idents, lexer, passes, syntaxes, llstream, modulegraphs, rod,
|
||||
idents, lexer, passes, syntaxes, llstream, modulegraphs,
|
||||
lineinfos, pathutils, tables
|
||||
|
||||
proc resetSystemArtifacts*(g: ModuleGraph) =
|
||||
@@ -93,8 +93,10 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
|
||||
discard processModule(graph, result, idGeneratorFromModule(result), s)
|
||||
if result == nil:
|
||||
let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
|
||||
result = loadModuleSym(graph, fileIdx, filename)
|
||||
if result == nil:
|
||||
when false:
|
||||
# XXX entry point for module loading from the rod file
|
||||
result = loadModuleSym(graph, fileIdx, filename)
|
||||
when true:
|
||||
result = newModule(graph, fileIdx)
|
||||
result.flags.incl flags
|
||||
registerModule(graph, result)
|
||||
|
||||
@@ -11,9 +11,9 @@ import ast, renderer, intsets, tables, msgs, options, lineinfos, strformat, iden
|
||||
import sequtils, strutils, std / sets
|
||||
|
||||
# IMPORTANT: notes not up to date, i'll update this comment again
|
||||
#
|
||||
#
|
||||
# notes:
|
||||
#
|
||||
#
|
||||
# Env: int => nilability
|
||||
# a = b
|
||||
# nilability a <- nilability b
|
||||
@@ -111,7 +111,7 @@ type
|
||||
Symbol = distinct int
|
||||
|
||||
## the index of an expression in the pre-indexed sequence of those
|
||||
ExprIndex = distinct int16
|
||||
ExprIndex = distinct int16
|
||||
|
||||
## the set index
|
||||
SetIndex = distinct int
|
||||
@@ -131,7 +131,7 @@ type
|
||||
## the context for the checker: an instance for each procedure
|
||||
NilCheckerContext = ref object
|
||||
# abstractTime: AbstractTime
|
||||
# partitions: Partitions
|
||||
# partitions: Partitions
|
||||
# symbolGraphs: Table[Symbol, ]
|
||||
symbolIndices: Table[Symbol, ExprIndex] ## index for each symbol
|
||||
expressions: SeqOfDistinct[ExprIndex, PNode] ## a sequence of pre-indexed expressions
|
||||
@@ -360,7 +360,7 @@ func `$`(a: Symbol): string =
|
||||
$(a.int)
|
||||
|
||||
template isConstBracket(n: PNode): bool =
|
||||
n.kind == nkBracketExpr and n[1].kind in nkLiterals
|
||||
n.kind == nkBracketExpr and n[1].kind in nkLiterals
|
||||
|
||||
proc index(ctx: NilCheckerContext, n: PNode): ExprIndex =
|
||||
# echo "n ", n, " ", n.kind
|
||||
@@ -373,7 +373,7 @@ proc index(ctx: NilCheckerContext, n: PNode): ExprIndex =
|
||||
#echo n.kind
|
||||
# internalError(ctx.config, n.info, "expected " & $a & " " & $n & " to have a index")
|
||||
return noExprIndex
|
||||
#
|
||||
#
|
||||
#ctx.symbolIndices[symbol(n)]
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ proc aliasSet(ctx: NilCheckerContext, map: NilMap, index: ExprIndex): IntSet =
|
||||
result = map.sets[map.setIndices[index]]
|
||||
|
||||
|
||||
|
||||
|
||||
proc store(map: NilMap, ctx: NilCheckerContext, index: ExprIndex, value: Nilability, kind: TransitionKind, info: TLineInfo, node: PNode = nil) =
|
||||
if index == noExprIndex:
|
||||
return
|
||||
@@ -414,7 +414,7 @@ proc moveOut(ctx: NilCheckerContext, map: NilMap, target: PNode) =
|
||||
var targetSet = map.sets[targetSetIndex]
|
||||
if targetSet.len > 1:
|
||||
var other: ExprIndex
|
||||
|
||||
|
||||
for element in targetSet:
|
||||
if element.ExprIndex != targetIndex:
|
||||
other = element.ExprIndex
|
||||
@@ -440,7 +440,7 @@ proc move(ctx: NilCheckerContext, map: NilMap, target: PNode, assigned: PNode) =
|
||||
#echo "move ", target, " ", assigned
|
||||
var targetIndex = ctx.index(target)
|
||||
var assignedIndex: ExprIndex
|
||||
var targetSetIndex = map.setIndices[targetIndex]
|
||||
var targetSetIndex = map.setIndices[targetIndex]
|
||||
var assignedSetIndex: SetIndex
|
||||
if assigned.kind == nkSym:
|
||||
assignedIndex = ctx.index(assigned)
|
||||
@@ -497,12 +497,12 @@ proc checkCall(n, ctx, map): Check =
|
||||
result.map = map
|
||||
for i, child in n:
|
||||
discard check(child, ctx, map)
|
||||
|
||||
|
||||
if i > 0:
|
||||
# var args make a new map with MaybeNil for our node
|
||||
# as it might have been mutated
|
||||
# TODO similar for normal refs and fields: find dependent exprs: brackets
|
||||
|
||||
|
||||
if child.kind == nkHiddenAddr and not child.typ.isNil and child.typ.kind == tyVar and child.typ[0].kind == tyRef:
|
||||
if not isNew:
|
||||
result.map = newNilMap(map)
|
||||
@@ -526,7 +526,7 @@ proc checkCall(n, ctx, map): Check =
|
||||
isNew = true
|
||||
moveOutDependants(ctx, result.map, child)
|
||||
storeDependants(ctx, result.map, child, MaybeNil)
|
||||
|
||||
|
||||
if n[0].kind == nkSym and n[0].sym.magic == mNew:
|
||||
# new hidden deref?
|
||||
var value = if n[1].kind == nkHiddenDeref: n[1][0] else: n[1]
|
||||
@@ -552,7 +552,7 @@ template event(b: History): string =
|
||||
of TSafe: "it is safe here as it returns false for isNil"
|
||||
of TPotentialAlias: "it might be changed directly or through an alias"
|
||||
of TDependant: "it might be changed because its base might be changed"
|
||||
|
||||
|
||||
proc derefWarning(n, ctx, map; kind: Nilability) =
|
||||
## a warning for potentially unsafe dereference
|
||||
if n.info in ctx.warningLocations:
|
||||
@@ -587,14 +587,14 @@ proc handleNilability(check: Check; n, ctx, map) =
|
||||
else:
|
||||
when defined(nilDebugInfo):
|
||||
message(ctx.config, n.info, hintUser, "can deref " & $n)
|
||||
|
||||
|
||||
proc checkDeref(n, ctx, map): Check =
|
||||
## check dereference: deref n should be ok only if n is Safe
|
||||
result = check(n[0], ctx, map)
|
||||
|
||||
|
||||
handleNilability(result, n[0], ctx, map)
|
||||
|
||||
|
||||
|
||||
proc checkRefExpr(n, ctx; check: Check): Check =
|
||||
## check ref expressions: TODO not sure when this happens
|
||||
result = check
|
||||
@@ -625,7 +625,7 @@ proc checkBracketExpr(n, ctx, map): Check =
|
||||
result = check(n[1], ctx, result.map)
|
||||
result = checkRefExpr(n, ctx, result)
|
||||
# echo n, " ", result.nilability
|
||||
|
||||
|
||||
|
||||
template union(l: Nilability, r: Nilability): Nilability =
|
||||
## unify two states
|
||||
@@ -654,7 +654,7 @@ proc findCommonParent(l: NilMap, r: NilMap): NilMap =
|
||||
result = l.parent
|
||||
while not result.isNil:
|
||||
var rparent = r.parent
|
||||
while not rparent.isNil:
|
||||
while not rparent.isNil:
|
||||
if result == rparent:
|
||||
return result
|
||||
rparent = rparent.parent
|
||||
@@ -666,17 +666,17 @@ proc union(ctx: NilCheckerContext, l: NilMap, r: NilMap): NilMap =
|
||||
## what if they are from different parts of the same tree
|
||||
## e.g.
|
||||
## a -> b -> c
|
||||
## -> b1
|
||||
## -> b1
|
||||
## common then?
|
||||
##
|
||||
##
|
||||
if l.isNil:
|
||||
return r
|
||||
elif r.isNil:
|
||||
return l
|
||||
|
||||
|
||||
let common = findCommonParent(l, r)
|
||||
result = newNilMap(common, ctx.expressions.len.int)
|
||||
|
||||
|
||||
for index, value in l:
|
||||
let h = history(r, index)
|
||||
let info = if h.len > 0: h[^1].info else: TLineInfo(line: 0) # assert h.len > 0
|
||||
@@ -715,11 +715,11 @@ proc checkAsgn(target: PNode, assigned: PNode; ctx, map): Check =
|
||||
result = check(assigned, ctx, map)
|
||||
else:
|
||||
result = Check(nilability: typeNilability(target.typ), map: map)
|
||||
|
||||
|
||||
# we need to visit and check those, but we don't use the result for now
|
||||
# is it possible to somehow have another event happen here?
|
||||
discard check(target, ctx, map)
|
||||
|
||||
|
||||
if result.map.isNil:
|
||||
result.map = map
|
||||
if target.kind in {nkSym, nkDotExpr} or isConstBracket(target):
|
||||
@@ -738,8 +738,8 @@ proc checkAsgn(target: PNode, assigned: PNode; ctx, map): Check =
|
||||
if symbol(elementNode) in ctx.symbolIndices:
|
||||
var elementIndex = ctx.index(elementNode)
|
||||
result.map.store(ctx, elementIndex, value, TAssign, target.info, elementNode)
|
||||
|
||||
|
||||
|
||||
|
||||
proc checkReturn(n, ctx, map): Check =
|
||||
## check return
|
||||
# return n same as result = n; return ?
|
||||
@@ -750,9 +750,9 @@ proc checkReturn(n, ctx, map): Check =
|
||||
proc checkIf(n, ctx, map): Check =
|
||||
## check branches based on condition
|
||||
var mapIf: NilMap = map
|
||||
|
||||
|
||||
# first visit the condition
|
||||
|
||||
|
||||
# the structure is not If(Elif(Elif, Else), Else)
|
||||
# it is
|
||||
# If(Elif, Elif, Else)
|
||||
@@ -765,7 +765,7 @@ proc checkIf(n, ctx, map): Check =
|
||||
var afterLayer: NilMap
|
||||
# the result nilability for expressions
|
||||
var nilability = Safe
|
||||
|
||||
|
||||
for branch in n.sons:
|
||||
var branchConditionLayer = newNilMap(layerHistory)
|
||||
var branchLayer: NilMap
|
||||
@@ -779,7 +779,7 @@ proc checkIf(n, ctx, map): Check =
|
||||
else:
|
||||
branchLayer = layerHistory
|
||||
code = branch
|
||||
|
||||
|
||||
let branchCheck = checkBranch(code, ctx, branchLayer)
|
||||
# handles nil afterLayer -> returns branchCheck.map
|
||||
afterLayer = ctx.union(afterLayer, branchCheck.map)
|
||||
@@ -796,7 +796,7 @@ proc checkIf(n, ctx, map): Check =
|
||||
result.map = ctx.union(layerHistory, afterLayer)
|
||||
result.nilability = Safe # no expr?
|
||||
else:
|
||||
# similar to else: because otherwise we are jumping out of
|
||||
# similar to else: because otherwise we are jumping out of
|
||||
# the branch, so no union with the mapIf (we dont continue if the condition was true)
|
||||
# here it also doesn't matter for the parent branch what happened in the branch, e.g. assigning to nil
|
||||
# as if we continue there, we haven't entered the branch probably
|
||||
@@ -820,7 +820,7 @@ proc checkFor(n, ctx, map): Check =
|
||||
# echo namedMapDebugInfo(ctx, map)
|
||||
var check2 = check(n.sons[2], ctx, m)
|
||||
var map2 = check2.map
|
||||
|
||||
|
||||
result.map = ctx.union(map0, m)
|
||||
result.map = ctx.union(result.map, map2)
|
||||
result.nilability = Safe
|
||||
@@ -848,11 +848,11 @@ proc checkWhile(n, ctx, map): Check =
|
||||
var map1 = m.copyMap()
|
||||
var check2 = check(n.sons[1], ctx, m)
|
||||
var map2 = check2.map
|
||||
|
||||
|
||||
result.map = ctx.union(map0, map1)
|
||||
result.map = ctx.union(result.map, map2)
|
||||
result.nilability = Safe
|
||||
|
||||
|
||||
proc checkInfix(n, ctx, map): Check =
|
||||
## check infix operators in condition
|
||||
## a and b : map is based on a; next b
|
||||
@@ -882,7 +882,7 @@ proc checkInfix(n, ctx, map): Check =
|
||||
result.map = checkCondition(n[2], ctx, map, false, false)
|
||||
elif $n[1] == "false":
|
||||
result.map = checkCondition(n[2], ctx, map, true, false)
|
||||
|
||||
|
||||
if result.map.isNil:
|
||||
result.map = map
|
||||
else:
|
||||
@@ -906,24 +906,24 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode =
|
||||
else: ""
|
||||
|
||||
var cache = newIdentCache()
|
||||
var op = newSym(skVar, cache.getIdent(name), nextId ctx.idgen, nil, r.info)
|
||||
var op = newSym(skVar, cache.getIdent(name), nextSymId ctx.idgen, nil, r.info)
|
||||
|
||||
op.magic = magic
|
||||
result = nkInfix.newTree(
|
||||
newSymNode(op, r.info),
|
||||
l,
|
||||
r)
|
||||
result.typ = newType(tyBool, nextId ctx.idgen, nil)
|
||||
result.typ = newType(tyBool, nextTypeId ctx.idgen, nil)
|
||||
|
||||
proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
|
||||
var cache = newIdentCache()
|
||||
var op = newSym(skVar, cache.getIdent("not"), nextId ctx.idgen, nil, node.info)
|
||||
var op = newSym(skVar, cache.getIdent("not"), nextSymId ctx.idgen, nil, node.info)
|
||||
|
||||
op.magic = mNot
|
||||
result = nkPrefix.newTree(
|
||||
newSymNode(op, node.info),
|
||||
node)
|
||||
result.typ = newType(tyBool, nextId ctx.idgen, nil)
|
||||
result.typ = newType(tyBool, nextTypeId ctx.idgen, nil)
|
||||
|
||||
proc infixEq(ctx: NilCheckerContext, l: PNode, r: PNode): PNode =
|
||||
infix(ctx, l, r, mEqRef)
|
||||
@@ -1016,7 +1016,7 @@ proc checkTry(n, ctx, map): Check =
|
||||
let tryCheck = check(n[0], ctx, currentMap)
|
||||
newMap = ctx.union(currentMap, tryCheck.map)
|
||||
canRaise = n[0].canRaise
|
||||
|
||||
|
||||
var afterTryMap = newMap
|
||||
for a, branch in n:
|
||||
if a > 0:
|
||||
@@ -1026,7 +1026,7 @@ proc checkTry(n, ctx, map): Check =
|
||||
let childCheck = check(branch[0], ctx, newMap)
|
||||
newMap = ctx.union(newMap, childCheck.map)
|
||||
hasFinally = true
|
||||
of nkExceptBranch:
|
||||
of nkExceptBranch:
|
||||
if canRaise:
|
||||
let childCheck = check(branch[^1], ctx, newMap)
|
||||
newMap = ctx.union(newMap, childCheck.map)
|
||||
@@ -1069,7 +1069,7 @@ proc reverse(kind: TransitionKind): TransitionKind =
|
||||
of TNil: TSafe
|
||||
of TSafe: TNil
|
||||
of TPotentialAlias: TPotentialAlias
|
||||
else:
|
||||
else:
|
||||
kind
|
||||
# raise newException(ValueError, "expected TNil or TSafe")
|
||||
|
||||
@@ -1079,41 +1079,41 @@ proc reverseDirect(map: NilMap): NilMap =
|
||||
# because conditions should've stored their changes there
|
||||
# b: Safe (not b.isNil)
|
||||
# b: Parent Parent
|
||||
# b: Nil (b.isNil)
|
||||
# b: Nil (b.isNil)
|
||||
|
||||
# layer block
|
||||
# [ Parent ] [ Parent ]
|
||||
# if -> if state
|
||||
# if -> if state
|
||||
# layer -> reverse
|
||||
# older older0 new
|
||||
# older new
|
||||
# [ b Nil ] [ Parent ]
|
||||
# elif
|
||||
# [ b Nil, c Nil] [ Parent ]
|
||||
#
|
||||
#
|
||||
|
||||
# if b.isNil:
|
||||
# if b.isNil:
|
||||
# # [ b Safe]
|
||||
# c = A() # Safe
|
||||
# elif not b.isNil:
|
||||
# elif not b.isNil:
|
||||
# # [ b Safe ] + [b Nil] MaybeNil Unreachable
|
||||
# # Unreachable defer can't deref b, it is unreachable
|
||||
# discard
|
||||
# else:
|
||||
# b
|
||||
# b
|
||||
|
||||
|
||||
# if
|
||||
|
||||
# if
|
||||
|
||||
|
||||
|
||||
# if: we just pass the map with a new layer for its block
|
||||
# elif: we just pass the original map but with a new layer is the reverse of the previous popped layer (?)
|
||||
# elif:
|
||||
# elif:
|
||||
# else: we just pass the original map but with a new layer which is initialized as the reverse of the
|
||||
# top layer of else
|
||||
# else:
|
||||
#
|
||||
#
|
||||
# [ b MaybeNil ] [b Parent] [b Parent] [b Safe] [b Nil] []
|
||||
# Safe
|
||||
# c == 1
|
||||
@@ -1181,7 +1181,7 @@ proc checkResult(n, ctx, map) =
|
||||
of Unreachable:
|
||||
message(ctx.config, n.info, warnStrictNotNil, "return value is unreachable")
|
||||
of Safe, Parent:
|
||||
discard
|
||||
discard
|
||||
|
||||
proc checkBranch(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
result = check(n, ctx, map)
|
||||
@@ -1191,7 +1191,7 @@ proc checkBranch(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
|
||||
proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
assert not map.isNil
|
||||
|
||||
|
||||
# echo "check n ", n, " ", n.kind
|
||||
# echo "map ", namedMapDebugInfo(ctx, map)
|
||||
case n.kind:
|
||||
@@ -1218,7 +1218,7 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
if n.kind in {nkObjConstr, nkTupleConstr}:
|
||||
# TODO deeper nested elements?
|
||||
# A(field: B()) #
|
||||
# field: Safe ->
|
||||
# field: Safe ->
|
||||
var elements: seq[(PNode, Nilability)]
|
||||
for i, child in n:
|
||||
result = check(child, ctx, result.map)
|
||||
@@ -1230,7 +1230,7 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
else:
|
||||
for child in n:
|
||||
result = check(child, ctx, result.map)
|
||||
|
||||
|
||||
of nkDotExpr:
|
||||
result = checkDotExpr(n, ctx, map)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
@@ -1261,7 +1261,7 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState, nkTypeOfExpr:
|
||||
|
||||
|
||||
discard "don't follow this : same as varpartitions"
|
||||
result = Check(nilability: Nil, map: map)
|
||||
else:
|
||||
@@ -1275,17 +1275,17 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
result = Check(nilability: Nil, map: elementCheck.map)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
proc typeNilability(typ: PType): Nilability =
|
||||
assert not typ.isNil
|
||||
# echo "typeNilability ", $typ.flags, " ", $typ.kind
|
||||
result = if tfNotNil in typ.flags:
|
||||
Safe
|
||||
elif typ.kind in {tyRef, tyCString, tyPtr, tyPointer}:
|
||||
#
|
||||
#
|
||||
# tyVar ? tyVarargs ? tySink ? tyLent ?
|
||||
# TODO spec? tests?
|
||||
# TODO spec? tests?
|
||||
MaybeNil
|
||||
else:
|
||||
Safe
|
||||
@@ -1354,7 +1354,7 @@ proc checkNil*(s: PSym; body: PNode; conf: ConfigRef, idgen: IdGenerator) =
|
||||
var context = NilCheckerContext(config: conf, idgen: idgen)
|
||||
context.preVisit(s, body, conf)
|
||||
var map = newNilMap(nil, context.symbolIndices.len)
|
||||
|
||||
|
||||
for i, child in s.typ.n.sons:
|
||||
if i > 0:
|
||||
if child.kind != nkSym:
|
||||
@@ -1362,7 +1362,7 @@ proc checkNil*(s: PSym; body: PNode; conf: ConfigRef, idgen: IdGenerator) =
|
||||
map.store(context, context.index(child), typeNilability(child.typ), TArg, child.info, child)
|
||||
|
||||
map.store(context, resultExprIndex, if not s.typ[0].isNil and s.typ[0].kind == tyRef: Nil else: Safe, TResult, s.ast.info)
|
||||
|
||||
|
||||
# echo "checking ", s.name.s, " ", filename
|
||||
|
||||
let res = check(body, context, map)
|
||||
@@ -1374,7 +1374,7 @@ proc checkNil*(s: PSym; body: PNode; conf: ConfigRef, idgen: IdGenerator) =
|
||||
res.map.store(context, resultExprIndex, Safe, TAssign, s.ast.info)
|
||||
|
||||
# TODO check for nilability result
|
||||
# (ANotNil, BNotNil) :
|
||||
# (ANotNil, BNotNil) :
|
||||
# do we check on asgn nilability at all?
|
||||
|
||||
if not s.typ[0].isNil and s.typ[0].kind == tyRef and tfNotNil in s.typ[0].flags:
|
||||
|
||||
@@ -722,6 +722,10 @@ proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
|
||||
result = subdir / RelativeFile f.string.splitPath.tail
|
||||
#echo "completeGeneratedFilePath(", f, ") = ", result
|
||||
|
||||
proc toRodFile*(conf: ConfigRef; f: AbsoluteFile): AbsoluteFile =
|
||||
result = changeFileExt(completeGeneratedFilePath(conf,
|
||||
withPackageName(conf, f)), RodExt)
|
||||
|
||||
proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
|
||||
for it in conf.searchPaths:
|
||||
if suppressStdlib and it.string.startsWith(conf.libpath.string):
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import
|
||||
options, ast, llstream, msgs,
|
||||
idents,
|
||||
syntaxes, modulegraphs, reorder, rod,
|
||||
syntaxes, modulegraphs, reorder,
|
||||
lineinfos, pathutils
|
||||
|
||||
type
|
||||
@@ -119,88 +119,65 @@ proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator;
|
||||
s: PLLStream
|
||||
fileIdx = module.fileIdx
|
||||
prepareConfigNotes(graph, module)
|
||||
if module.id < 0:
|
||||
# new module caching mechanism:
|
||||
for i in 0..<graph.passes.len:
|
||||
if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend:
|
||||
a[i] = graph.passes[i].open(graph, module, idgen)
|
||||
else:
|
||||
a[i] = nil
|
||||
|
||||
if not graph.stopCompile():
|
||||
let n = loadNode(graph, module)
|
||||
var m = n
|
||||
for i in 0..<graph.passes.len:
|
||||
if not isNil(graph.passes[i].process) and not graph.passes[i].isFrontend:
|
||||
m = graph.passes[i].process(a[i], m)
|
||||
if isNil(m):
|
||||
break
|
||||
|
||||
var m: PNode = nil
|
||||
for i in 0..<graph.passes.len:
|
||||
if not isNil(graph.passes[i].close) and not graph.passes[i].isFrontend:
|
||||
m = graph.passes[i].close(graph, a[i], m)
|
||||
a[i] = nil
|
||||
openPasses(graph, a, module, idgen)
|
||||
if stream == nil:
|
||||
let filename = toFullPathConsiderDirty(graph.config, fileIdx)
|
||||
s = llStreamOpen(filename, fmRead)
|
||||
if s == nil:
|
||||
rawMessage(graph.config, errCannotOpenFile, filename.string)
|
||||
return false
|
||||
else:
|
||||
openPasses(graph, a, module, idgen)
|
||||
if stream == nil:
|
||||
let filename = toFullPathConsiderDirty(graph.config, fileIdx)
|
||||
s = llStreamOpen(filename, fmRead)
|
||||
if s == nil:
|
||||
rawMessage(graph.config, errCannotOpenFile, filename.string)
|
||||
return false
|
||||
else:
|
||||
s = stream
|
||||
s = stream
|
||||
while true:
|
||||
openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
if module.owner == nil or module.owner.name.s != "stdlib" or module.name.s == "distros":
|
||||
# XXX what about caching? no processing then? what if I change the
|
||||
# modules to include between compilation runs? we'd need to track that
|
||||
# in ROD files. I think we should enable this feature only
|
||||
# for the interactive mode.
|
||||
if module.name.s != "nimscriptapi":
|
||||
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
|
||||
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
|
||||
|
||||
while true:
|
||||
openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
if module.owner == nil or module.owner.name.s != "stdlib" or module.name.s == "distros":
|
||||
# XXX what about caching? no processing then? what if I change the
|
||||
# modules to include between compilation runs? we'd need to track that
|
||||
# in ROD files. I think we should enable this feature only
|
||||
# for the interactive mode.
|
||||
if module.name.s != "nimscriptapi":
|
||||
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
|
||||
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
|
||||
|
||||
while true:
|
||||
if graph.stopCompile(): break
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
if (sfSystemModule notin module.flags and
|
||||
({sfNoForward, sfReorder} * module.flags != {} or
|
||||
codeReordering in graph.config.features)):
|
||||
# read everything, no streaming possible
|
||||
var sl = newNodeI(nkStmtList, n.info)
|
||||
if graph.stopCompile(): break
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
if (sfSystemModule notin module.flags and
|
||||
({sfNoForward, sfReorder} * module.flags != {} or
|
||||
codeReordering in graph.config.features)):
|
||||
# read everything, no streaming possible
|
||||
var sl = newNodeI(nkStmtList, n.info)
|
||||
sl.add n
|
||||
while true:
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
sl.add n
|
||||
while true:
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
sl.add n
|
||||
if sfReorder in module.flags or codeReordering in graph.config.features:
|
||||
sl = reorder(graph, sl, module)
|
||||
discard processTopLevelStmt(graph, sl, a)
|
||||
break
|
||||
elif n.kind in imperativeCode:
|
||||
# read everything until the next proc declaration etc.
|
||||
var sl = newNodeI(nkStmtList, n.info)
|
||||
if sfReorder in module.flags or codeReordering in graph.config.features:
|
||||
sl = reorder(graph, sl, module)
|
||||
discard processTopLevelStmt(graph, sl, a)
|
||||
break
|
||||
elif n.kind in imperativeCode:
|
||||
# read everything until the next proc declaration etc.
|
||||
var sl = newNodeI(nkStmtList, n.info)
|
||||
sl.add n
|
||||
var rest: PNode = nil
|
||||
while true:
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty or n.kind notin imperativeCode:
|
||||
rest = n
|
||||
break
|
||||
sl.add n
|
||||
var rest: PNode = nil
|
||||
while true:
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty or n.kind notin imperativeCode:
|
||||
rest = n
|
||||
break
|
||||
sl.add n
|
||||
#echo "-----\n", sl
|
||||
if not processTopLevelStmt(graph, sl, a): break
|
||||
if rest != nil:
|
||||
#echo "-----\n", rest
|
||||
if not processTopLevelStmt(graph, rest, a): break
|
||||
else:
|
||||
#echo "----- single\n", n
|
||||
if not processTopLevelStmt(graph, n, a): break
|
||||
closeParser(p)
|
||||
if s.kind != llsStdIn: break
|
||||
closePasses(graph, a)
|
||||
#echo "-----\n", sl
|
||||
if not processTopLevelStmt(graph, sl, a): break
|
||||
if rest != nil:
|
||||
#echo "-----\n", rest
|
||||
if not processTopLevelStmt(graph, rest, a): break
|
||||
else:
|
||||
#echo "----- single\n", n
|
||||
if not processTopLevelStmt(graph, n, a): break
|
||||
closeParser(p)
|
||||
if s.kind != llsStdIn: break
|
||||
closePasses(graph, a)
|
||||
result = true
|
||||
|
||||
@@ -31,8 +31,8 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode =
|
||||
return
|
||||
let body = liftIterToProc(c.graph, iter.sym, iter.sym.getBody, t, c.idgen)
|
||||
|
||||
let prc = newSym(skProc, n[3].ident, nextId c.idgen, iter.sym.owner, iter.sym.info)
|
||||
prc.typ = copyType(iter.sym.typ, nextId c.idgen, prc)
|
||||
let prc = newSym(skProc, n[3].ident, nextSymId c.idgen, iter.sym.owner, iter.sym.info)
|
||||
prc.typ = copyType(iter.sym.typ, nextTypeId c.idgen, prc)
|
||||
excl prc.typ.flags, tfCapturesEnv
|
||||
prc.typ.n.add newSymNode(getEnvParam(iter.sym))
|
||||
prc.typ.rawAddSon t
|
||||
|
||||
@@ -26,7 +26,7 @@ proc semLocals*(c: PContext, n: PNode): PNode =
|
||||
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
|
||||
|
||||
if it.owner == owner:
|
||||
var field = newSym(skField, it.name, nextId c.idgen, owner, n.info)
|
||||
var field = newSym(skField, it.name, nextSymId c.idgen, owner, n.info)
|
||||
field.typ = it.typ.skipTypes({tyVar})
|
||||
field.position = counter
|
||||
inc(counter)
|
||||
|
||||
@@ -121,7 +121,7 @@ proc pragmaEnsures(c: PContext, n: PNode) =
|
||||
openScope(c)
|
||||
let o = getCurrOwner(c)
|
||||
if o.kind in routineKinds and o.typ != nil and o.typ.sons[0] != nil:
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), nextId(c.idgen), o, n.info)
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), nextSymId(c.idgen), o, n.info)
|
||||
s.typ = o.typ.sons[0]
|
||||
incl(s.flags, sfUsed)
|
||||
addDecl(c, s)
|
||||
@@ -563,8 +563,6 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
|
||||
var e = searchInScopes(con, getIdent(con.cache, sub), amb)
|
||||
# XXX what to do here if 'amb' is true?
|
||||
if e != nil:
|
||||
when false:
|
||||
if e.kind == skStub: loadStub(e)
|
||||
incl(e.flags, sfUsed)
|
||||
result.add newSymNode(e)
|
||||
else:
|
||||
@@ -638,7 +636,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
|
||||
invalidPragma(c, n)
|
||||
|
||||
var userPragma = newSym(skTemplate, it[1].ident, nextId(c.idgen), nil, it.info, c.config.options)
|
||||
var userPragma = newSym(skTemplate, it[1].ident, nextSymId(c.idgen), nil, it.info, c.config.options)
|
||||
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
|
||||
strTableAdd(c.userPragmas, userPragma)
|
||||
|
||||
@@ -719,7 +717,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) =
|
||||
if dest == nil or dest.kind in routineKinds:
|
||||
localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines")
|
||||
let src = considerQuotedIdent(c, n[0])
|
||||
let alias = newSym(skAlias, src, nextId(c.idgen), dest, n[0].info, c.config.options)
|
||||
let alias = newSym(skAlias, src, nextSymId(c.idgen), dest, n[0].info, c.config.options)
|
||||
incl(alias.flags, sfExported)
|
||||
if sfCompilerProc in dest.flags: markCompilerProc(c, alias)
|
||||
addInterfaceDecl(c, alias)
|
||||
@@ -741,7 +739,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
|
||||
# We return a dummy symbol; later passes over the type will repair it.
|
||||
# Generic instantiation needs to know about this too. But we're lazy
|
||||
# and perform the lookup on demand instead.
|
||||
result = newSym(skUnknown, considerQuotedIdent(c, n), nextId(c.idgen), nil, n.info,
|
||||
result = newSym(skUnknown, considerQuotedIdent(c, n), nextSymId(c.idgen), nil, n.info,
|
||||
c.config.options)
|
||||
else:
|
||||
result = qualifiedLookUp(c, n, {checkUndeclared})
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2017 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements the canonalization for the various caching mechanisms.
|
||||
|
||||
import ast, lineinfos, incremental, modulegraphs, pathutils
|
||||
|
||||
when not nimIncremental:
|
||||
template setupModuleCache*(g: ModuleGraph) = discard
|
||||
template storeNode*(g: ModuleGraph; module: PSym; n: PNode) = discard
|
||||
template loadNode*(g: ModuleGraph; module: PSym): PNode = newNode(nkStmtList)
|
||||
|
||||
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym) {.inline.} = nil
|
||||
|
||||
template addModuleDep*(g: ModuleGraph; module, fileIdx: FileIndex; isIncludeFile: bool) = discard
|
||||
|
||||
template storeRemaining*(g: ModuleGraph; module: PSym) = discard
|
||||
|
||||
#template registerModule*(g: ModuleGraph; module: PSym) = discard
|
||||
|
||||
else:
|
||||
include rodimpl
|
||||
|
||||
# idea for testing all this logic: *Always* load the AST from the DB, whether
|
||||
# we already have it in RAM or not!
|
||||
@@ -1,950 +0,0 @@
|
||||
#
|
||||
#
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2018 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## This module implements the new compilation cache.
|
||||
|
||||
import strutils, intsets, tables, ropes, db_sqlite, msgs, options,
|
||||
renderer, rodutils, idents, astalgo, btrees, magicsys, cgmeth, extccomp,
|
||||
btrees, trees, condsyms, nversion, pathutils
|
||||
|
||||
## Todo:
|
||||
## - Dependency computation should use *signature* hashes in order to
|
||||
## avoid recompiling dependent modules.
|
||||
## - Patch the rest of the compiler to do lazy loading of proc bodies.
|
||||
## - serialize the AST in a smarter way (avoid storing some ASTs twice!)
|
||||
|
||||
template db(): DbConn = g.incr.db
|
||||
|
||||
proc encodeConfig(g: ModuleGraph): string =
|
||||
result = newStringOfCap(100)
|
||||
result.add RodFileVersion
|
||||
for d in definedSymbolNames(g.config.symbols):
|
||||
result.add ' '
|
||||
result.add d
|
||||
|
||||
template serialize(field) =
|
||||
result.add ' '
|
||||
result.add($g.config.field)
|
||||
|
||||
depConfigFields(serialize)
|
||||
|
||||
proc needsRecompile(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile;
|
||||
cycleCheck: var IntSet): bool =
|
||||
let root = db.getRow(sql"select id, fullhash from filenames where fullpath = ?",
|
||||
fullpath.string)
|
||||
if root[0].len == 0: return true
|
||||
if root[1] != hashFileCached(g.config, fileIdx, fullpath):
|
||||
return true
|
||||
# cycle detection: assume "not changed" is correct.
|
||||
if cycleCheck.containsOrIncl(int fileIdx):
|
||||
return false
|
||||
# check dependencies (recursively):
|
||||
for row in db.fastRows(sql"select fullpath from filenames where id in (select dependency from deps where module = ?)",
|
||||
root[0]):
|
||||
let dep = AbsoluteFile row[0]
|
||||
if needsRecompile(g, g.config.fileInfoIdx(dep), dep, cycleCheck):
|
||||
return true
|
||||
return false
|
||||
|
||||
proc getModuleId(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): int =
|
||||
## Analyse the known dependency graph.
|
||||
if g.config.symbolFiles == disabledSf: return getID()
|
||||
when false:
|
||||
if g.config.symbolFiles in {disabledSf, writeOnlySf} or
|
||||
g.incr.configChanged:
|
||||
return getID()
|
||||
let module = g.incr.db.getRow(
|
||||
sql"select id, fullHash, nimid from modules where fullpath = ?", string fullpath)
|
||||
let currentFullhash = hashFileCached(g.config, fileIdx, fullpath)
|
||||
if module[0].len == 0:
|
||||
result = getID()
|
||||
db.exec(sql"insert into modules(fullpath, interfHash, fullHash, nimid) values (?, ?, ?, ?)",
|
||||
string fullpath, "", currentFullhash, result)
|
||||
else:
|
||||
result = parseInt(module[2])
|
||||
if currentFullhash == module[1]:
|
||||
# not changed, so use the cached AST:
|
||||
doAssert(result != 0)
|
||||
var cycleCheck = initIntSet()
|
||||
if not needsRecompile(g, fileIdx, fullpath, cycleCheck):
|
||||
if not g.incr.configChanged or g.config.symbolFiles == readOnlySf:
|
||||
#echo "cached successfully! ", string fullpath
|
||||
return -result
|
||||
elif g.config.symbolFiles == readOnlySf:
|
||||
internalError(g.config, "file needs to be recompiled: " & (string fullpath))
|
||||
db.exec(sql"update modules set fullHash = ? where id = ?", currentFullhash, module[0])
|
||||
db.exec(sql"delete from deps where module = ?", module[0])
|
||||
db.exec(sql"delete from types where module = ?", module[0])
|
||||
db.exec(sql"delete from syms where module = ?", module[0])
|
||||
db.exec(sql"delete from toplevelstmts where module = ?", module[0])
|
||||
db.exec(sql"delete from statics where module = ?", module[0])
|
||||
|
||||
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): PSym =
|
||||
let id = getModuleId(g, fileIdx, fullpath)
|
||||
result = g.incr.r.syms.getOrDefault(abs id)
|
||||
|
||||
proc pushType(w: var Writer, t: PType) =
|
||||
if not containsOrIncl(w.tmarks, t.uniqueId):
|
||||
w.tstack.add(t)
|
||||
|
||||
proc pushSym(w: var Writer, s: PSym) =
|
||||
if not containsOrIncl(w.smarks, s.id):
|
||||
w.sstack.add(s)
|
||||
|
||||
template w: untyped = g.incr.w
|
||||
|
||||
proc encodeNode(g: ModuleGraph; fInfo: TLineInfo, n: PNode,
|
||||
result: var string) =
|
||||
if n == nil:
|
||||
# nil nodes have to be stored too:
|
||||
result.add("()")
|
||||
return
|
||||
result.add('(')
|
||||
encodeVInt(ord(n.kind), result)
|
||||
# we do not write comments for now
|
||||
# Line information takes easily 20% or more of the filesize! Therefore we
|
||||
# omit line information if it is the same as the parent's line information:
|
||||
if fInfo.fileIndex != n.info.fileIndex:
|
||||
result.add('?')
|
||||
encodeVInt(n.info.col, result)
|
||||
result.add(',')
|
||||
encodeVInt(int n.info.line, result)
|
||||
result.add(',')
|
||||
#encodeVInt(toDbFileId(g.incr, g.config, n.info.fileIndex), result)
|
||||
encodeVInt(n.info.fileIndex.int, result)
|
||||
elif fInfo.line != n.info.line:
|
||||
result.add('?')
|
||||
encodeVInt(n.info.col, result)
|
||||
result.add(',')
|
||||
encodeVInt(int n.info.line, result)
|
||||
elif fInfo.col != n.info.col:
|
||||
result.add('?')
|
||||
encodeVInt(n.info.col, result)
|
||||
# No need to output the file index, as this is the serialization of one
|
||||
# file.
|
||||
let f = n.flags * PersistentNodeFlags
|
||||
if f != {}:
|
||||
result.add('$')
|
||||
encodeVInt(cast[int32](f), result)
|
||||
if n.typ != nil:
|
||||
result.add('^')
|
||||
encodeVInt(n.typ.uniqueId, result)
|
||||
pushType(w, n.typ)
|
||||
case n.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if n.intVal != 0:
|
||||
result.add('!')
|
||||
encodeVBiggestInt(n.intVal, result)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if n.floatVal != 0.0:
|
||||
result.add('!')
|
||||
encodeStr($n.floatVal, result)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if n.strVal != "":
|
||||
result.add('!')
|
||||
encodeStr(n.strVal, result)
|
||||
of nkIdent:
|
||||
result.add('!')
|
||||
encodeStr(n.ident.s, result)
|
||||
of nkSym:
|
||||
result.add('!')
|
||||
encodeVInt(n.sym.id, result)
|
||||
pushSym(w, n.sym)
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
encodeNode(g, n.info, n[i], result)
|
||||
result.add(')')
|
||||
|
||||
proc encodeLoc(g: ModuleGraph; loc: TLoc, result: var string) =
|
||||
var oldLen = result.len
|
||||
result.add('<')
|
||||
if loc.k != low(loc.k): encodeVInt(ord(loc.k), result)
|
||||
if loc.storage != low(loc.storage):
|
||||
result.add('*')
|
||||
encodeVInt(ord(loc.storage), result)
|
||||
if loc.flags != {}:
|
||||
result.add('$')
|
||||
encodeVInt(cast[int32](loc.flags), result)
|
||||
if loc.lode != nil:
|
||||
result.add('^')
|
||||
encodeNode(g, unknownLineInfo, loc.lode, result)
|
||||
if loc.r != nil:
|
||||
result.add('!')
|
||||
encodeStr($loc.r, result)
|
||||
if oldLen + 1 == result.len:
|
||||
# no data was necessary, so remove the '<' again:
|
||||
setLen(result, oldLen)
|
||||
else:
|
||||
result.add('>')
|
||||
|
||||
proc encodeType(g: ModuleGraph, t: PType, result: var string) =
|
||||
if t == nil:
|
||||
# nil nodes have to be stored too:
|
||||
result.add("[]")
|
||||
return
|
||||
# we need no surrounding [] here because the type is in a line of its own
|
||||
if t.kind == tyForward: internalError(g.config, "encodeType: tyForward")
|
||||
# for the new rodfile viewer we use a preceding [ so that the data section
|
||||
# can easily be disambiguated:
|
||||
result.add('[')
|
||||
encodeVInt(ord(t.kind), result)
|
||||
result.add('+')
|
||||
encodeVInt(t.uniqueId, result)
|
||||
if t.id != t.uniqueId:
|
||||
result.add('+')
|
||||
encodeVInt(t.id, result)
|
||||
if t.n != nil:
|
||||
encodeNode(g, unknownLineInfo, t.n, result)
|
||||
if t.flags != {}:
|
||||
result.add('$')
|
||||
encodeVInt(cast[int32](t.flags), result)
|
||||
if t.callConv != low(t.callConv):
|
||||
result.add('?')
|
||||
encodeVInt(ord(t.callConv), result)
|
||||
if t.owner != nil:
|
||||
result.add('*')
|
||||
encodeVInt(t.owner.id, result)
|
||||
pushSym(w, t.owner)
|
||||
if t.sym != nil:
|
||||
result.add('&')
|
||||
encodeVInt(t.sym.id, result)
|
||||
pushSym(w, t.sym)
|
||||
if t.size != - 1:
|
||||
result.add('/')
|
||||
encodeVBiggestInt(t.size, result)
|
||||
if t.align != 2:
|
||||
result.add('=')
|
||||
encodeVInt(t.align, result)
|
||||
if t.lockLevel.ord != UnspecifiedLockLevel.ord:
|
||||
result.add('\14')
|
||||
encodeVInt(t.lockLevel.int16, result)
|
||||
if t.paddingAtEnd != 0:
|
||||
result.add('\15')
|
||||
encodeVInt(t.paddingAtEnd, result)
|
||||
for a in t.attachedOps:
|
||||
result.add('\16')
|
||||
if a == nil:
|
||||
encodeVInt(-1, result)
|
||||
else:
|
||||
encodeVInt(a.id, result)
|
||||
pushSym(w, a)
|
||||
for i, s in items(t.methods):
|
||||
result.add('\19')
|
||||
encodeVInt(i, result)
|
||||
result.add('\20')
|
||||
encodeVInt(s.id, result)
|
||||
pushSym(w, s)
|
||||
encodeLoc(g, t.loc, result)
|
||||
if t.typeInst != nil:
|
||||
result.add('\21')
|
||||
encodeVInt(t.typeInst.uniqueId, result)
|
||||
pushType(w, t.typeInst)
|
||||
for i in 0..<t.len:
|
||||
if t[i] == nil:
|
||||
result.add("^()")
|
||||
else:
|
||||
result.add('^')
|
||||
encodeVInt(t[i].uniqueId, result)
|
||||
pushType(w, t[i])
|
||||
|
||||
proc encodeLib(g: ModuleGraph, lib: PLib, info: TLineInfo, result: var string) =
|
||||
result.add('|')
|
||||
encodeVInt(ord(lib.kind), result)
|
||||
result.add('|')
|
||||
encodeStr($lib.name, result)
|
||||
result.add('|')
|
||||
encodeNode(g, info, lib.path, result)
|
||||
|
||||
proc encodeInstantiations(g: ModuleGraph; s: seq[PInstantiation];
|
||||
result: var string) =
|
||||
for t in s:
|
||||
result.add('\15')
|
||||
encodeVInt(t.sym.id, result)
|
||||
pushSym(w, t.sym)
|
||||
for tt in t.concreteTypes:
|
||||
result.add('\17')
|
||||
encodeVInt(tt.uniqueId, result)
|
||||
pushType(w, tt)
|
||||
result.add('\20')
|
||||
encodeVInt(t.compilesId, result)
|
||||
|
||||
proc encodeSym(g: ModuleGraph, s: PSym, result: var string) =
|
||||
if s == nil:
|
||||
# nil nodes have to be stored too:
|
||||
result.add("{}")
|
||||
return
|
||||
# we need no surrounding {} here because the symbol is in a line of its own
|
||||
encodeVInt(ord(s.kind), result)
|
||||
result.add('+')
|
||||
encodeVInt(s.id, result)
|
||||
result.add('&')
|
||||
encodeStr(s.name.s, result)
|
||||
if s.typ != nil:
|
||||
result.add('^')
|
||||
encodeVInt(s.typ.uniqueId, result)
|
||||
pushType(w, s.typ)
|
||||
result.add('?')
|
||||
if s.info.col != -1'i16: encodeVInt(s.info.col, result)
|
||||
result.add(',')
|
||||
encodeVInt(int s.info.line, result)
|
||||
result.add(',')
|
||||
#encodeVInt(toDbFileId(g.incr, g.config, s.info.fileIndex), result)
|
||||
encodeVInt(s.info.fileIndex.int, result)
|
||||
if s.owner != nil:
|
||||
result.add('*')
|
||||
encodeVInt(s.owner.id, result)
|
||||
pushSym(w, s.owner)
|
||||
if s.flags != {}:
|
||||
result.add('$')
|
||||
encodeVBiggestInt(cast[int64](s.flags), result)
|
||||
if s.magic != mNone:
|
||||
result.add('@')
|
||||
encodeVInt(ord(s.magic), result)
|
||||
result.add('!')
|
||||
encodeVInt(cast[int32](s.options), result)
|
||||
if s.position != 0:
|
||||
result.add('%')
|
||||
encodeVInt(s.position, result)
|
||||
if s.offset != - 1:
|
||||
result.add('`')
|
||||
encodeVInt(s.offset, result)
|
||||
encodeLoc(g, s.loc, result)
|
||||
if s.annex != nil: encodeLib(g, s.annex, s.info, result)
|
||||
if s.constraint != nil:
|
||||
result.add('#')
|
||||
encodeNode(g, unknownLineInfo, s.constraint, result)
|
||||
case s.kind
|
||||
of skType, skGenericParam:
|
||||
for t in s.typeInstCache:
|
||||
result.add('\14')
|
||||
encodeVInt(t.uniqueId, result)
|
||||
pushType(w, t)
|
||||
of routineKinds:
|
||||
encodeInstantiations(g, s.procInstCache, result)
|
||||
if s.gcUnsafetyReason != nil:
|
||||
result.add('\16')
|
||||
encodeVInt(s.gcUnsafetyReason.id, result)
|
||||
pushSym(w, s.gcUnsafetyReason)
|
||||
if s.transformedBody != nil:
|
||||
result.add('\24')
|
||||
encodeNode(g, s.info, s.transformedBody, result)
|
||||
of skModule, skPackage:
|
||||
encodeInstantiations(g, s.usedGenerics, result)
|
||||
# we don't serialize:
|
||||
#tab*: TStrTable # interface table for modules
|
||||
of skLet, skVar, skField, skForVar:
|
||||
if s.guard != nil:
|
||||
result.add('\18')
|
||||
encodeVInt(s.guard.id, result)
|
||||
pushSym(w, s.guard)
|
||||
if s.bitsize != 0:
|
||||
result.add('\19')
|
||||
encodeVInt(s.bitsize, result)
|
||||
else: discard
|
||||
# lazy loading will soon reload the ast lazily, so the ast needs to be
|
||||
# the last entry of a symbol:
|
||||
if s.ast != nil:
|
||||
# we used to attempt to save space here by only storing a dummy AST if
|
||||
# it is not necessary, but Nim's heavy compile-time evaluation features
|
||||
# make that unfeasible nowadays:
|
||||
encodeNode(g, s.info, s.ast, result)
|
||||
|
||||
proc storeSym(g: ModuleGraph; s: PSym) =
|
||||
if sfForward in s.flags and s.kind != skModule:
|
||||
w.forwardedSyms.add s
|
||||
return
|
||||
var buf = newStringOfCap(160)
|
||||
encodeSym(g, s, buf)
|
||||
# XXX only store the name for exported symbols in order to speed up lookup
|
||||
# times once we enable the skStub logic.
|
||||
let m = getModule(s)
|
||||
let mid = if m == nil: 0 else: abs(m.id)
|
||||
db.exec(sql"insert into syms(nimid, module, name, data, exported) values (?, ?, ?, ?, ?)",
|
||||
s.id, mid, s.name.s, buf, ord(sfExported in s.flags))
|
||||
|
||||
proc storeType(g: ModuleGraph; t: PType) =
|
||||
var buf = newStringOfCap(160)
|
||||
encodeType(g, t, buf)
|
||||
let m = if t.owner != nil: getModule(t.owner) else: nil
|
||||
let mid = if m == nil: 0 else: abs(m.id)
|
||||
db.exec(sql"insert into types(nimid, module, data) values (?, ?, ?)",
|
||||
t.uniqueId, mid, buf)
|
||||
|
||||
proc transitiveClosure(g: ModuleGraph) =
|
||||
var i = 0
|
||||
while true:
|
||||
if i > 100_000:
|
||||
doAssert false, "loop never ends!"
|
||||
if w.sstack.len > 0:
|
||||
let s = w.sstack.pop()
|
||||
when false:
|
||||
echo "popped ", s.name.s, " ", s.id
|
||||
storeSym(g, s)
|
||||
elif w.tstack.len > 0:
|
||||
let t = w.tstack.pop()
|
||||
storeType(g, t)
|
||||
when false:
|
||||
echo "popped type ", typeToString(t), " ", t.uniqueId
|
||||
else:
|
||||
break
|
||||
inc i
|
||||
|
||||
proc storeNode*(g: ModuleGraph; module: PSym; n: PNode) =
|
||||
if g.config.symbolFiles == disabledSf: return
|
||||
var buf = newStringOfCap(160)
|
||||
encodeNode(g, module.info, n, buf)
|
||||
db.exec(sql"insert into toplevelstmts(module, position, data) values (?, ?, ?)",
|
||||
abs(module.id), module.offset, buf)
|
||||
inc module.offset
|
||||
transitiveClosure(g)
|
||||
|
||||
proc recordStmt*(g: ModuleGraph; module: PSym; n: PNode) =
|
||||
storeNode(g, module, n)
|
||||
|
||||
proc storeFilename(g: ModuleGraph; fullpath: AbsoluteFile; fileIdx: FileIndex) =
|
||||
let id = db.getValue(sql"select id from filenames where fullpath = ?", fullpath.string)
|
||||
if id.len == 0:
|
||||
let fullhash = hashFileCached(g.config, fileIdx, fullpath)
|
||||
db.exec(sql"insert into filenames(nimid, fullpath, fullhash) values (?, ?, ?)",
|
||||
int(fileIdx), fullpath.string, fullhash)
|
||||
|
||||
proc storeRemaining*(g: ModuleGraph; module: PSym) =
|
||||
if g.config.symbolFiles == disabledSf: return
|
||||
var stillForwarded: seq[PSym] = @[]
|
||||
for s in w.forwardedSyms:
|
||||
if sfForward notin s.flags:
|
||||
storeSym(g, s)
|
||||
else:
|
||||
stillForwarded.add s
|
||||
swap w.forwardedSyms, stillForwarded
|
||||
transitiveClosure(g)
|
||||
var nimid = 0
|
||||
for x in items(g.config.m.fileInfos):
|
||||
storeFilename(g, x.fullPath, FileIndex(nimid))
|
||||
inc nimid
|
||||
|
||||
# ---------------- decoder -----------------------------------
|
||||
|
||||
type
|
||||
BlobReader = object
|
||||
s: string
|
||||
pos: int
|
||||
|
||||
using
|
||||
b: var BlobReader
|
||||
g: ModuleGraph
|
||||
|
||||
proc loadSym(g; id: int, info: TLineInfo): PSym
|
||||
proc loadType(g; id: int, info: TLineInfo): PType
|
||||
|
||||
proc decodeLineInfo(g; b; info: var TLineInfo) =
|
||||
if b.s[b.pos] == '?':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == ',': info.col = -1'i16
|
||||
else: info.col = int16(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] == ',':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == ',': info.line = 0'u16
|
||||
else: info.line = uint16(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] == ',':
|
||||
inc(b.pos)
|
||||
#info.fileIndex = fromDbFileId(g.incr, g.config, decodeVInt(b.s, b.pos))
|
||||
info.fileIndex = FileIndex decodeVInt(b.s, b.pos)
|
||||
|
||||
proc skipNode(b) =
|
||||
# ')' itself cannot be part of a string literal so that this is correct.
|
||||
assert b.s[b.pos] == '('
|
||||
var par = 0
|
||||
var pos = b.pos+1
|
||||
while true:
|
||||
case b.s[pos]
|
||||
of ')':
|
||||
if par == 0: break
|
||||
dec par
|
||||
of '(': inc par
|
||||
else: discard
|
||||
inc pos
|
||||
b.pos = pos+1 # skip ')'
|
||||
|
||||
proc decodeNodeLazyBody(g; b; fInfo: TLineInfo,
|
||||
belongsTo: PSym): PNode =
|
||||
result = nil
|
||||
if b.s[b.pos] == '(':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == ')':
|
||||
inc(b.pos)
|
||||
return # nil node
|
||||
result = newNodeI(TNodeKind(decodeVInt(b.s, b.pos)), fInfo)
|
||||
decodeLineInfo(g, b, result.info)
|
||||
if b.s[b.pos] == '$':
|
||||
inc(b.pos)
|
||||
result.flags = cast[TNodeFlags](int32(decodeVInt(b.s, b.pos)))
|
||||
if b.s[b.pos] == '^':
|
||||
inc(b.pos)
|
||||
var id = decodeVInt(b.s, b.pos)
|
||||
result.typ = loadType(g, id, result.info)
|
||||
case result.kind
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
result.intVal = decodeVBiggestInt(b.s, b.pos)
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
var fl = decodeStr(b.s, b.pos)
|
||||
result.floatVal = parseFloat(fl)
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
result.strVal = decodeStr(b.s, b.pos)
|
||||
else:
|
||||
result.strVal = ""
|
||||
of nkIdent:
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
var fl = decodeStr(b.s, b.pos)
|
||||
result.ident = g.cache.getIdent(fl)
|
||||
else:
|
||||
internalError(g.config, result.info, "decodeNode: nkIdent")
|
||||
of nkSym:
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
var id = decodeVInt(b.s, b.pos)
|
||||
result.sym = loadSym(g, id, result.info)
|
||||
else:
|
||||
internalError(g.config, result.info, "decodeNode: nkSym")
|
||||
else:
|
||||
var i = 0
|
||||
while b.s[b.pos] != ')':
|
||||
when false:
|
||||
if belongsTo != nil and i == bodyPos:
|
||||
addSonNilAllowed(result, nil)
|
||||
belongsTo.offset = b.pos
|
||||
skipNode(b)
|
||||
else:
|
||||
discard
|
||||
addSonNilAllowed(result, decodeNodeLazyBody(g, b, result.info, nil))
|
||||
inc i
|
||||
if b.s[b.pos] == ')': inc(b.pos)
|
||||
else: internalError(g.config, result.info, "decodeNode: ')' missing")
|
||||
else:
|
||||
internalError(g.config, fInfo, "decodeNode: '(' missing " & $b.pos)
|
||||
|
||||
proc decodeNode(g; b; fInfo: TLineInfo): PNode =
|
||||
result = decodeNodeLazyBody(g, b, fInfo, nil)
|
||||
|
||||
proc decodeLoc(g; b; loc: var TLoc, info: TLineInfo) =
|
||||
if b.s[b.pos] == '<':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] in {'0'..'9', 'a'..'z', 'A'..'Z'}:
|
||||
loc.k = TLocKind(decodeVInt(b.s, b.pos))
|
||||
else:
|
||||
loc.k = low(loc.k)
|
||||
if b.s[b.pos] == '*':
|
||||
inc(b.pos)
|
||||
loc.storage = TStorageLoc(decodeVInt(b.s, b.pos))
|
||||
else:
|
||||
loc.storage = low(loc.storage)
|
||||
if b.s[b.pos] == '$':
|
||||
inc(b.pos)
|
||||
loc.flags = cast[TLocFlags](int32(decodeVInt(b.s, b.pos)))
|
||||
else:
|
||||
loc.flags = {}
|
||||
if b.s[b.pos] == '^':
|
||||
inc(b.pos)
|
||||
loc.lode = decodeNode(g, b, info)
|
||||
# rrGetType(b, decodeVInt(b.s, b.pos), info)
|
||||
else:
|
||||
loc.lode = nil
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
loc.r = rope(decodeStr(b.s, b.pos))
|
||||
else:
|
||||
loc.r = nil
|
||||
if b.s[b.pos] == '>': inc(b.pos)
|
||||
else: internalError(g.config, info, "decodeLoc " & b.s[b.pos])
|
||||
|
||||
proc loadBlob(g; query: SqlQuery; id: int): BlobReader =
|
||||
let blob = db.getValue(query, id)
|
||||
if blob.len == 0:
|
||||
internalError(g.config, "symbolfiles: cannot find ID " & $ id)
|
||||
result = BlobReader(pos: 0)
|
||||
shallowCopy(result.s, blob)
|
||||
# ensure we can read without index checks:
|
||||
result.s.add '\0'
|
||||
|
||||
proc loadType(g; id: int; info: TLineInfo): PType =
|
||||
result = g.incr.r.types.getOrDefault(id)
|
||||
if result != nil: return result
|
||||
var b = loadBlob(g, sql"select data from types where nimid = ?", id)
|
||||
|
||||
if b.s[b.pos] == '[':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == ']':
|
||||
inc(b.pos)
|
||||
return # nil type
|
||||
new(result)
|
||||
result.kind = TTypeKind(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] == '+':
|
||||
inc(b.pos)
|
||||
result.uniqueId = decodeVInt(b.s, b.pos)
|
||||
setId(result.uniqueId)
|
||||
#if debugIds: registerID(result)
|
||||
else:
|
||||
internalError(g.config, info, "decodeType: no id")
|
||||
if b.s[b.pos] == '+':
|
||||
inc(b.pos)
|
||||
result.id = decodeVInt(b.s, b.pos)
|
||||
else:
|
||||
result.id = result.uniqueId
|
||||
# here this also avoids endless recursion for recursive type
|
||||
g.incr.r.types.add(result.uniqueId, result)
|
||||
if b.s[b.pos] == '(': result.n = decodeNode(g, b, unknownLineInfo)
|
||||
if b.s[b.pos] == '$':
|
||||
inc(b.pos)
|
||||
result.flags = cast[TTypeFlags](int32(decodeVInt(b.s, b.pos)))
|
||||
if b.s[b.pos] == '?':
|
||||
inc(b.pos)
|
||||
result.callConv = TCallingConvention(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] == '*':
|
||||
inc(b.pos)
|
||||
result.owner = loadSym(g, decodeVInt(b.s, b.pos), info)
|
||||
if b.s[b.pos] == '&':
|
||||
inc(b.pos)
|
||||
result.sym = loadSym(g, decodeVInt(b.s, b.pos), info)
|
||||
if b.s[b.pos] == '/':
|
||||
inc(b.pos)
|
||||
result.size = decodeVInt(b.s, b.pos)
|
||||
else:
|
||||
result.size = -1
|
||||
if b.s[b.pos] == '=':
|
||||
inc(b.pos)
|
||||
result.align = decodeVInt(b.s, b.pos).int16
|
||||
else:
|
||||
result.align = 2
|
||||
|
||||
if b.s[b.pos] == '\14':
|
||||
inc(b.pos)
|
||||
result.lockLevel = decodeVInt(b.s, b.pos).TLockLevel
|
||||
else:
|
||||
result.lockLevel = UnspecifiedLockLevel
|
||||
|
||||
if b.s[b.pos] == '\15':
|
||||
inc(b.pos)
|
||||
result.paddingAtEnd = decodeVInt(b.s, b.pos).int16
|
||||
|
||||
for a in low(result.attachedOps)..high(result.attachedOps):
|
||||
if b.s[b.pos] == '\16':
|
||||
inc(b.pos)
|
||||
let id = decodeVInt(b.s, b.pos)
|
||||
if id >= 0:
|
||||
result.attachedOps[a] = loadSym(g, id, info)
|
||||
|
||||
while b.s[b.pos] == '\19':
|
||||
inc(b.pos)
|
||||
let x = decodeVInt(b.s, b.pos)
|
||||
doAssert b.s[b.pos] == '\20'
|
||||
inc(b.pos)
|
||||
let y = loadSym(g, decodeVInt(b.s, b.pos), info)
|
||||
result.methods.add((x, y))
|
||||
decodeLoc(g, b, result.loc, info)
|
||||
if b.s[b.pos] == '\21':
|
||||
inc(b.pos)
|
||||
let d = decodeVInt(b.s, b.pos)
|
||||
result.typeInst = loadType(g, d, info)
|
||||
while b.s[b.pos] == '^':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == '(':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == ')': inc(b.pos)
|
||||
else: internalError(g.config, info, "decodeType ^(" & b.s[b.pos])
|
||||
rawAddSon(result, nil)
|
||||
else:
|
||||
let d = decodeVInt(b.s, b.pos)
|
||||
result.sons.add loadType(g, d, info)
|
||||
|
||||
proc decodeLib(g; b; info: TLineInfo): PLib =
|
||||
result = nil
|
||||
if b.s[b.pos] == '|':
|
||||
new(result)
|
||||
inc(b.pos)
|
||||
result.kind = TLibKind(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] != '|': internalError(g.config, "decodeLib: 1")
|
||||
inc(b.pos)
|
||||
result.name = rope(decodeStr(b.s, b.pos))
|
||||
if b.s[b.pos] != '|': internalError(g.config, "decodeLib: 2")
|
||||
inc(b.pos)
|
||||
result.path = decodeNode(g, b, info)
|
||||
|
||||
proc decodeInstantiations(g; b; info: TLineInfo;
|
||||
s: var seq[PInstantiation]) =
|
||||
while b.s[b.pos] == '\15':
|
||||
inc(b.pos)
|
||||
var ii: PInstantiation
|
||||
new ii
|
||||
ii.sym = loadSym(g, decodeVInt(b.s, b.pos), info)
|
||||
ii.concreteTypes = @[]
|
||||
while b.s[b.pos] == '\17':
|
||||
inc(b.pos)
|
||||
ii.concreteTypes.add loadType(g, decodeVInt(b.s, b.pos), info)
|
||||
if b.s[b.pos] == '\20':
|
||||
inc(b.pos)
|
||||
ii.compilesId = decodeVInt(b.s, b.pos)
|
||||
s.add ii
|
||||
|
||||
proc loadSymFromBlob(g; b; info: TLineInfo): PSym =
|
||||
if b.s[b.pos] == '{':
|
||||
inc(b.pos)
|
||||
if b.s[b.pos] == '}':
|
||||
inc(b.pos)
|
||||
return # nil sym
|
||||
var k = TSymKind(decodeVInt(b.s, b.pos))
|
||||
var id: int
|
||||
if b.s[b.pos] == '+':
|
||||
inc(b.pos)
|
||||
id = decodeVInt(b.s, b.pos)
|
||||
setId(id)
|
||||
else:
|
||||
internalError(g.config, info, "decodeSym: no id")
|
||||
var ident: PIdent
|
||||
if b.s[b.pos] == '&':
|
||||
inc(b.pos)
|
||||
ident = g.cache.getIdent(decodeStr(b.s, b.pos))
|
||||
else:
|
||||
internalError(g.config, info, "decodeSym: no ident")
|
||||
#echo "decoding: {", ident.s
|
||||
result = PSym(id: id, kind: k, name: ident)
|
||||
# read the rest of the symbol description:
|
||||
g.incr.r.syms.add(result.id, result)
|
||||
if b.s[b.pos] == '^':
|
||||
inc(b.pos)
|
||||
result.typ = loadType(g, decodeVInt(b.s, b.pos), info)
|
||||
decodeLineInfo(g, b, result.info)
|
||||
if b.s[b.pos] == '*':
|
||||
inc(b.pos)
|
||||
result.owner = loadSym(g, decodeVInt(b.s, b.pos), result.info)
|
||||
if b.s[b.pos] == '$':
|
||||
inc(b.pos)
|
||||
result.flags = cast[TSymFlags](decodeVBiggestInt(b.s, b.pos))
|
||||
if b.s[b.pos] == '@':
|
||||
inc(b.pos)
|
||||
result.magic = TMagic(decodeVInt(b.s, b.pos))
|
||||
if b.s[b.pos] == '!':
|
||||
inc(b.pos)
|
||||
result.options = cast[TOptions](int32(decodeVInt(b.s, b.pos)))
|
||||
if b.s[b.pos] == '%':
|
||||
inc(b.pos)
|
||||
result.position = decodeVInt(b.s, b.pos)
|
||||
if b.s[b.pos] == '`':
|
||||
inc(b.pos)
|
||||
result.offset = decodeVInt(b.s, b.pos)
|
||||
else:
|
||||
result.offset = -1
|
||||
decodeLoc(g, b, result.loc, result.info)
|
||||
result.annex = decodeLib(g, b, info)
|
||||
if b.s[b.pos] == '#':
|
||||
inc(b.pos)
|
||||
result.constraint = decodeNode(g, b, unknownLineInfo)
|
||||
case result.kind
|
||||
of skType, skGenericParam:
|
||||
while b.s[b.pos] == '\14':
|
||||
inc(b.pos)
|
||||
result.typeInstCache.add loadType(g, decodeVInt(b.s, b.pos), result.info)
|
||||
of routineKinds:
|
||||
decodeInstantiations(g, b, result.info, result.procInstCache)
|
||||
if b.s[b.pos] == '\16':
|
||||
inc(b.pos)
|
||||
result.gcUnsafetyReason = loadSym(g, decodeVInt(b.s, b.pos), result.info)
|
||||
if b.s[b.pos] == '\24':
|
||||
inc b.pos
|
||||
result.transformedBody = decodeNode(g, b, result.info)
|
||||
#result.transformedBody = nil
|
||||
of skModule, skPackage:
|
||||
decodeInstantiations(g, b, result.info, result.usedGenerics)
|
||||
of skLet, skVar, skField, skForVar:
|
||||
if b.s[b.pos] == '\18':
|
||||
inc(b.pos)
|
||||
result.guard = loadSym(g, decodeVInt(b.s, b.pos), result.info)
|
||||
if b.s[b.pos] == '\19':
|
||||
inc(b.pos)
|
||||
result.bitsize = decodeVInt(b.s, b.pos).int16
|
||||
else: discard
|
||||
|
||||
if b.s[b.pos] == '(':
|
||||
#if result.kind in routineKinds:
|
||||
# result.ast = nil
|
||||
#else:
|
||||
result.ast = decodeNode(g, b, result.info)
|
||||
if sfCompilerProc in result.flags:
|
||||
registerCompilerProc(g, result)
|
||||
#echo "loading ", result.name.s
|
||||
|
||||
proc loadSym(g; id: int; info: TLineInfo): PSym =
|
||||
result = g.incr.r.syms.getOrDefault(id)
|
||||
if result != nil: return result
|
||||
var b = loadBlob(g, sql"select data from syms where nimid = ?", id)
|
||||
result = loadSymFromBlob(g, b, info)
|
||||
doAssert id == result.id, "symbol ID is not consistent!"
|
||||
|
||||
proc registerModule*(g; module: PSym) =
|
||||
g.incr.r.syms.add(abs module.id, module)
|
||||
|
||||
proc loadModuleSymTab(g; module: PSym) =
|
||||
## goal: fill module.tab
|
||||
g.incr.r.syms.add(module.id, module)
|
||||
for row in db.fastRows(sql"select nimid, data from syms where module = ? and exported = 1", abs(module.id)):
|
||||
let id = parseInt(row[0])
|
||||
var s = g.incr.r.syms.getOrDefault(id)
|
||||
if s == nil:
|
||||
var b = BlobReader(pos: 0)
|
||||
shallowCopy(b.s, row[1])
|
||||
# ensure we can read without index checks:
|
||||
b.s.add '\0'
|
||||
s = loadSymFromBlob(g, b, module.info)
|
||||
assert s != nil
|
||||
if s.kind != skField:
|
||||
strTableAdd(module.tab, s)
|
||||
if sfSystemModule in module.flags:
|
||||
g.systemModule = module
|
||||
|
||||
proc replay(g: ModuleGraph; module: PSym; n: PNode) =
|
||||
# XXX check if we need to replay nkStaticStmt here.
|
||||
case n.kind
|
||||
#of nkStaticStmt:
|
||||
#evalStaticStmt(module, g, n[0], module)
|
||||
#of nkVarSection, nkLetSection:
|
||||
# nkVarSections are already covered by the vmgen which produces nkStaticStmt
|
||||
of nkMethodDef:
|
||||
methodDef(g, n[namePos].sym, fromCache=true)
|
||||
of nkCommentStmt:
|
||||
# pragmas are complex and can be user-overriden via templates. So
|
||||
# instead of using the original ``nkPragma`` nodes, we rely on the
|
||||
# fact that pragmas.nim was patched to produce specialized recorded
|
||||
# statements for us in the form of ``nkCommentStmt`` with (key, value)
|
||||
# pairs. Ordinary nkCommentStmt nodes never have children so this is
|
||||
# not ambiguous.
|
||||
# Fortunately only a tiny subset of the available pragmas need to
|
||||
# be replayed here. This is always a subset of ``pragmas.stmtPragmas``.
|
||||
if n.len >= 2:
|
||||
internalAssert g.config, n[0].kind == nkStrLit and n[1].kind == nkStrLit
|
||||
case n[0].strVal
|
||||
of "hint": message(g.config, n.info, hintUser, n[1].strVal)
|
||||
of "warning": message(g.config, n.info, warnUser, n[1].strVal)
|
||||
of "error": localError(g.config, n.info, errUser, n[1].strVal)
|
||||
of "compile":
|
||||
internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit
|
||||
let cname = AbsoluteFile n[1].strVal
|
||||
var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
|
||||
obj: AbsoluteFile n[2].strVal,
|
||||
flags: {CfileFlag.External},
|
||||
customArgs: n[3].strVal)
|
||||
extccomp.addExternalFileToCompile(g.config, cf)
|
||||
of "link":
|
||||
extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal)
|
||||
of "passl":
|
||||
extccomp.addLinkOption(g.config, n[1].strVal)
|
||||
of "passc":
|
||||
extccomp.addCompileOption(g.config, n[1].strVal)
|
||||
of "localpassc":
|
||||
extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex))
|
||||
of "cppdefine":
|
||||
options.cppDefine(g.config, n[1].strVal)
|
||||
of "inc":
|
||||
let destKey = n[1].strVal
|
||||
let by = n[2].intVal
|
||||
let v = getOrDefault(g.cacheCounters, destKey)
|
||||
g.cacheCounters[destKey] = v+by
|
||||
of "put":
|
||||
let destKey = n[1].strVal
|
||||
let key = n[2].strVal
|
||||
let val = n[3]
|
||||
if not contains(g.cacheTables, destKey):
|
||||
g.cacheTables[destKey] = initBTree[string, PNode]()
|
||||
if not contains(g.cacheTables[destKey], key):
|
||||
g.cacheTables[destKey].add(key, val)
|
||||
else:
|
||||
internalError(g.config, n.info, "key already exists: " & key)
|
||||
of "incl":
|
||||
let destKey = n[1].strVal
|
||||
let val = n[2]
|
||||
if not contains(g.cacheSeqs, destKey):
|
||||
g.cacheSeqs[destKey] = newTree(nkStmtList, val)
|
||||
else:
|
||||
block search:
|
||||
for existing in g.cacheSeqs[destKey]:
|
||||
if exprStructuralEquivalent(existing, val, strictSymEquality=true):
|
||||
break search
|
||||
g.cacheSeqs[destKey].add val
|
||||
of "add":
|
||||
let destKey = n[1].strVal
|
||||
let val = n[2]
|
||||
if not contains(g.cacheSeqs, destKey):
|
||||
g.cacheSeqs[destKey] = newTree(nkStmtList, val)
|
||||
else:
|
||||
g.cacheSeqs[destKey].add val
|
||||
else:
|
||||
internalAssert g.config, false
|
||||
of nkImportStmt:
|
||||
for x in n:
|
||||
internalAssert g.config, x.kind == nkSym
|
||||
let modpath = AbsoluteFile toFullPath(g.config, x.sym.info)
|
||||
let imported = g.importModuleCallback(g, module, fileInfoIdx(g.config, modpath))
|
||||
internalAssert g.config, imported.id < 0
|
||||
of nkStmtList, nkStmtListExpr:
|
||||
for x in n: replay(g, module, x)
|
||||
of nkExportStmt:
|
||||
for x in n:
|
||||
doAssert x.kind == nkSym
|
||||
strTableAdd(module.tab, x.sym)
|
||||
else: discard "nothing to do for this node"
|
||||
|
||||
proc loadNode*(g: ModuleGraph; module: PSym): PNode =
|
||||
loadModuleSymTab(g, module)
|
||||
result = newNodeI(nkStmtList, module.info)
|
||||
for row in db.rows(sql"select data from toplevelstmts where module = ? order by position asc",
|
||||
abs module.id):
|
||||
var b = BlobReader(pos: 0)
|
||||
# ensure we can read without index checks:
|
||||
b.s = row[0] & '\0'
|
||||
result.add decodeNode(g, b, module.info)
|
||||
db.exec(sql"insert into controlblock(idgen) values (?)", gFrontEndId)
|
||||
replay(g, module, result)
|
||||
|
||||
proc setupModuleCache*(g: ModuleGraph) =
|
||||
# historical note: there used to be a `rodfiles` dir with special tests
|
||||
# for incremental compilation via symbol files. This was likely replaced by ic.
|
||||
if g.config.symbolFiles == disabledSf: return
|
||||
g.recordStmt = recordStmt
|
||||
let dbfile = getNimcacheDir(g.config) / RelativeFile"rodfiles.db"
|
||||
if g.config.symbolFiles == writeOnlySf:
|
||||
removeFile(dbfile)
|
||||
createDir getNimcacheDir(g.config)
|
||||
let ec = encodeConfig(g)
|
||||
if not fileExists(dbfile):
|
||||
db = open(connection=string dbfile, user="nim", password="",
|
||||
database="nim")
|
||||
createDb(db)
|
||||
db.exec(sql"insert into config(config) values (?)", ec)
|
||||
else:
|
||||
db = open(connection=string dbfile, user="nim", password="",
|
||||
database="nim")
|
||||
let oldConfig = db.getValue(sql"select config from config")
|
||||
g.incr.configChanged = oldConfig != ec
|
||||
# ensure the filename IDs stay consistent:
|
||||
for row in db.rows(sql"select fullpath, nimid from filenames order by nimid"):
|
||||
let id = fileInfoIdx(g.config, AbsoluteFile row[0])
|
||||
doAssert id.int == parseInt(row[1])
|
||||
db.exec(sql"update config set config = ?", ec)
|
||||
db.exec(sql"pragma journal_mode=off")
|
||||
# This MUST be turned off, otherwise it's way too slow even for testing purposes:
|
||||
db.exec(sql"pragma SYNCHRONOUS=off")
|
||||
db.exec(sql"pragma LOCKING_MODE=exclusive")
|
||||
let lastId = db.getValue(sql"select max(idgen) from controlblock")
|
||||
if lastId.len > 0:
|
||||
idgen.setId(parseInt lastId)
|
||||
@@ -16,7 +16,7 @@ import
|
||||
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
|
||||
intsets, transf, vmdef, vm, aliases, cgmeth, lambdalifting,
|
||||
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
|
||||
lowerings, plugins/active, rod, lineinfos, strtabs, int128,
|
||||
lowerings, plugins/active, lineinfos, strtabs, int128,
|
||||
isolation_check, typeallowed
|
||||
|
||||
from modulegraphs import ModuleGraph, PPassContext, onUse, onDef, onDefResolveForward
|
||||
@@ -124,8 +124,8 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
# turn any concrete typedesc into the abstract typedesc type
|
||||
if a.len == 0: result = a
|
||||
else:
|
||||
result = newType(tyTypeDesc, nextId(c.idgen), a.owner)
|
||||
rawAddSon(result, newType(tyNone, nextId(c.idgen), a.owner))
|
||||
result = newType(tyTypeDesc, nextTypeId(c.idgen), a.owner)
|
||||
rawAddSon(result, newType(tyNone, nextTypeId(c.idgen), a.owner))
|
||||
elif b.kind in {tyArray, tySet, tySequence} and
|
||||
a.kind == b.kind:
|
||||
# check for seq[empty] vs. seq[int]
|
||||
@@ -137,7 +137,7 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
let aEmpty = isEmptyContainer(a[i])
|
||||
let bEmpty = isEmptyContainer(b[i])
|
||||
if aEmpty != bEmpty:
|
||||
if nt.isNil: nt = copyType(a, nextId(c.idgen), a.owner)
|
||||
if nt.isNil: nt = copyType(a, nextTypeId(c.idgen), a.owner)
|
||||
nt[i] = if aEmpty: b[i] else: a[i]
|
||||
if not nt.isNil: result = nt
|
||||
#elif b[idx].kind == tyEmpty: return x
|
||||
@@ -176,7 +176,7 @@ proc commonType*(c: PContext; x, y: PType): PType =
|
||||
# ill-formed AST, no need for additional tyRef/tyPtr
|
||||
if k != tyNone and x.kind != tyGenericInst:
|
||||
let r = result
|
||||
result = newType(k, nextId(c.idgen), r.owner)
|
||||
result = newType(k, nextTypeId(c.idgen), r.owner)
|
||||
result.addSonSkipIntLit(r, c.idgen)
|
||||
|
||||
proc endsInNoReturn(n: PNode): bool =
|
||||
@@ -193,7 +193,7 @@ proc commonType*(c: PContext; x: PType, y: PNode): PType =
|
||||
commonType(c, x, y.typ)
|
||||
|
||||
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
result = newSym(kind, considerQuotedIdent(c, n), nextId c.idgen, getCurrOwner(c), n.info)
|
||||
result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
when defined(nimsuggest):
|
||||
suggestDecl(c, n, result)
|
||||
|
||||
@@ -216,7 +216,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
# template; we must fix it here: see #909
|
||||
result.owner = getCurrOwner(c)
|
||||
else:
|
||||
result = newSym(kind, considerQuotedIdent(c, n), nextId c.idgen, getCurrOwner(c), n.info)
|
||||
result = newSym(kind, considerQuotedIdent(c, n), nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
#if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
|
||||
# incl(result.flags, sfGlobal)
|
||||
when defined(nimsuggest):
|
||||
@@ -255,7 +255,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
|
||||
proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym =
|
||||
if t.sym != nil: return t.sym
|
||||
result = newSym(skType, getIdent(c.cache, "AnonType"), nextId c.idgen, t.owner, info)
|
||||
result = newSym(skType, getIdent(c.cache, "AnonType"), nextSymId c.idgen, t.owner, info)
|
||||
result.flags.incl sfAnon
|
||||
result.typ = t
|
||||
|
||||
@@ -616,7 +616,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode {.nosinks.} =
|
||||
else:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
#if c.config.cmd == cmdIdeTools: findSuggest(c, n)
|
||||
rod.storeNode(c.graph, c.module, result)
|
||||
storeRodNode(c, result)
|
||||
|
||||
proc reportUnusedModules(c: PContext) =
|
||||
for i in 0..high(c.unusedImports):
|
||||
@@ -638,7 +638,7 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
|
||||
result.add(c.module.ast)
|
||||
popOwner(c)
|
||||
popProcCon(c)
|
||||
storeRemaining(c.graph, c.module)
|
||||
saveRodFile(c)
|
||||
|
||||
const semPass* = makePass(myOpen, myProcess, myClose,
|
||||
isFrontend = true)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
|
||||
import
|
||||
intsets, options, ast, astalgo, msgs, idents, renderer,
|
||||
magicsys, vmdef, modulegraphs, lineinfos, sets
|
||||
magicsys, vmdef, modulegraphs, lineinfos, sets, pathutils
|
||||
|
||||
import ic / to_packed_ast
|
||||
|
||||
type
|
||||
TOptionEntry* = object # entries to put on a stack for pragma parsing
|
||||
@@ -77,9 +79,9 @@ type
|
||||
case mode*: ImportMode
|
||||
of importAll: discard
|
||||
of importSet:
|
||||
imported*: IntSet
|
||||
imported*: IntSet # of PIdent.id
|
||||
of importExcept:
|
||||
exceptSet*: IntSet
|
||||
exceptSet*: IntSet # of PIdent.id
|
||||
|
||||
PContext* = ref TContext
|
||||
TContext* = object of TPassContext # a context represents the module
|
||||
@@ -140,6 +142,7 @@ type
|
||||
selfName*: PIdent
|
||||
cache*: IdentCache
|
||||
graph*: ModuleGraph
|
||||
encoder*: PackedEncoder
|
||||
signatures*: TStrTable
|
||||
recursiveDep*: string
|
||||
suggestionsMade*: bool
|
||||
@@ -264,6 +267,16 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext =
|
||||
initStrTable(result.signatures)
|
||||
result.typesWithOps = @[]
|
||||
result.features = graph.config.features
|
||||
if graph.config.symbolFiles != disabledSf:
|
||||
initEncoder result.encoder, module, graph.config
|
||||
|
||||
proc addIncludeFileDep*(c: PContext; f: FileIndex) =
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
addIncludeFileDep(c.encoder, f)
|
||||
|
||||
proc addImportFileDep*(c: PContext; f: FileIndex) =
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
addImportFileDep(c.encoder, f)
|
||||
|
||||
proc inclSym(sq: var seq[PSym], s: PSym) =
|
||||
for i in 0..<sq.len:
|
||||
@@ -273,6 +286,7 @@ proc inclSym(sq: var seq[PSym], s: PSym) =
|
||||
proc addConverter*(c: PContext, conv: PSym) =
|
||||
inclSym(c.converters, conv)
|
||||
inclSym(c.graph.ifaces[c.module.position].converters, conv)
|
||||
#addConverter(c.graph, c.module, conv) # upcoming
|
||||
|
||||
proc addPureEnum*(c: PContext, e: PSym) =
|
||||
inclSym(c.graph.ifaces[c.module.position].pureEnums, e)
|
||||
@@ -280,6 +294,7 @@ proc addPureEnum*(c: PContext, e: PSym) =
|
||||
proc addPattern*(c: PContext, p: PSym) =
|
||||
inclSym(c.patterns, p)
|
||||
inclSym(c.graph.ifaces[c.module.position].patterns, p)
|
||||
#addPattern(c.graph, c.module, p) # upcoming
|
||||
|
||||
proc newLib*(kind: TLibKind): PLib =
|
||||
new(result)
|
||||
@@ -291,10 +306,10 @@ proc addToLib*(lib: PLib, sym: PSym) =
|
||||
sym.annex = lib
|
||||
|
||||
proc newTypeS*(kind: TTypeKind, c: PContext): PType =
|
||||
result = newType(kind, nextId(c.idgen), getCurrOwner(c))
|
||||
result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c))
|
||||
|
||||
proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType =
|
||||
result = newType(tyPtr, nextId(idgen), owner)
|
||||
result = newType(tyPtr, nextTypeId(idgen), owner)
|
||||
addSonSkipIntLit(result, baseType, idgen)
|
||||
|
||||
proc makePtrType*(c: PContext, baseType: PType): PType =
|
||||
@@ -322,7 +337,7 @@ proc makeVarType*(owner: PSym, baseType: PType; idgen: IdGenerator; kind = tyVar
|
||||
if baseType.kind == kind:
|
||||
result = baseType
|
||||
else:
|
||||
result = newType(kind, nextId(idgen), owner)
|
||||
result = newType(kind, nextTypeId(idgen), owner)
|
||||
addSonSkipIntLit(result, baseType, idgen)
|
||||
|
||||
proc makeTypeDesc*(c: PContext, typ: PType): PType =
|
||||
@@ -338,7 +353,7 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||
incl typedesc.flags, tfCheckedForDestructor
|
||||
internalAssert(c.config, typ != nil)
|
||||
typedesc.addSonSkipIntLit(typ, c.idgen)
|
||||
let sym = newSym(skType, c.cache.idAnon, nextId(c.idgen), getCurrOwner(c), info,
|
||||
let sym = newSym(skType, c.cache.idAnon, nextSymId(c.idgen), getCurrOwner(c), info,
|
||||
c.config.options).linkTo(typedesc)
|
||||
return newSymNode(sym, info)
|
||||
|
||||
@@ -349,12 +364,12 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
|
||||
|
||||
proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType];
|
||||
idgen: IdGenerator): PType =
|
||||
result = newType(kind, nextId(idgen), owner)
|
||||
result = newType(kind, nextTypeId(idgen), owner)
|
||||
result.sons = sons
|
||||
|
||||
proc newTypeWithSons*(c: PContext, kind: TTypeKind,
|
||||
sons: seq[PType]): PType =
|
||||
result = newType(kind, nextId(c.idgen), getCurrOwner(c))
|
||||
result = newType(kind, nextTypeId(c.idgen), getCurrOwner(c))
|
||||
result.sons = sons
|
||||
|
||||
proc makeStaticExpr*(c: PContext, n: PNode): PNode =
|
||||
@@ -463,3 +478,15 @@ proc popCaseContext*(c: PContext) =
|
||||
|
||||
proc setCaseContextIdx*(c: PContext, idx: int) =
|
||||
c.p.caseContext[^1].idx = idx
|
||||
|
||||
template addExport*(c: PContext; s: PSym) =
|
||||
## convenience to export a symbol from the current module
|
||||
addExport(c.graph, c.module, s)
|
||||
|
||||
proc storeRodNode*(c: PContext, n: PNode) =
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
toPackedNodeTopLevel(n, c.encoder)
|
||||
|
||||
proc saveRodFile*(c: PContext) =
|
||||
if c.config.symbolFiles != disabledSf:
|
||||
saveRodFile(toRodFile(c.config, c.filename.AbsoluteFile), c.encoder)
|
||||
|
||||
@@ -1119,7 +1119,7 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
# This seems semantically correct and then we'll be able
|
||||
# to return the section symbol directly here
|
||||
let foundType = makeTypeDesc(c, def[2].typ)
|
||||
return newSymNode(copySym(def[0].sym, nextId c.idgen).linkTo(foundType), info)
|
||||
return newSymNode(copySym(def[0].sym, nextSymId c.idgen).linkTo(foundType), info)
|
||||
|
||||
of nkConstSection:
|
||||
for def in statement:
|
||||
@@ -1144,7 +1144,7 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
return c.graph.emptyNode
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym, nextId c.idgen).linkTo(foundTyp), info)
|
||||
return newSymNode(copySym(tParam.sym, nextSymId c.idgen).linkTo(foundTyp), info)
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1941,7 +1941,7 @@ proc expectString(c: PContext, n: PNode): string =
|
||||
localError(c.config, n.info, errStringLiteralExpected)
|
||||
|
||||
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
|
||||
result = newSym(kind, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), info)
|
||||
result = newSym(kind, c.cache.idAnon, nextSymId c.idgen, getCurrOwner(c), info)
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
let macroCall = n[1]
|
||||
@@ -2156,7 +2156,7 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType =
|
||||
result = newType(tyGenericInvocation, nextId c.idgen, c.module)
|
||||
result = newType(tyGenericInvocation, nextTypeId c.idgen, c.module)
|
||||
addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ, c.idgen)
|
||||
addSonSkipIntLit(result, t, c.idgen)
|
||||
result = instGenericContainer(c, info, result, allowMetaTypes = false)
|
||||
@@ -2631,7 +2631,7 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode)
|
||||
let paramPos = defExpr.sym.position + 1
|
||||
|
||||
if call[paramPos].kind != nkSym:
|
||||
let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), nextId c.idgen,
|
||||
let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), nextSymId c.idgen,
|
||||
c.p.owner, letSection.info, c.p.owner.options)
|
||||
hoistedVarSym.typ = call[paramPos].typ
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
var trueSymbol = strTableGet(c.graph.systemModule.tab, getIdent(c.cache, "true"))
|
||||
if trueSymbol == nil:
|
||||
localError(c.config, n.info, "system needs: 'true'")
|
||||
trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), nextId c.idgen, getCurrOwner(c), n.info)
|
||||
trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
trueSymbol.typ = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
result[0] = newSymNode(trueSymbol, n.info)
|
||||
|
||||
@@ -17,7 +17,7 @@ import
|
||||
|
||||
proc errorType*(g: ModuleGraph): PType =
|
||||
## creates a type representing an error state
|
||||
result = newType(tyError, nextId(g.idgen), g.owners[^1])
|
||||
result = newType(tyError, nextTypeId(g.idgen), g.owners[^1])
|
||||
result.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode =
|
||||
@@ -476,7 +476,7 @@ proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
|
||||
result = newSymNode(s, info)
|
||||
if s.typ.kind != tyTypeDesc:
|
||||
result.typ = newType(tyTypeDesc, idgen.nextId, s.owner)
|
||||
result.typ = newType(tyTypeDesc, idgen.nextTypeId, s.owner)
|
||||
result.typ.addSonSkipIntLit(s.typ, idgen)
|
||||
else:
|
||||
result.typ = s.typ
|
||||
|
||||
@@ -472,7 +472,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
flags, ctx)
|
||||
if n[paramsPos].kind != nkEmpty:
|
||||
if n[paramsPos][0].kind != nkEmpty:
|
||||
addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextId c.idgen, nil, n.info))
|
||||
addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextSymId c.idgen, nil, n.info))
|
||||
n[paramsPos] = semGenericStmt(c, n[paramsPos], flags, ctx)
|
||||
n[pragmasPos] = semGenericStmt(c, n[pragmasPos], flags, ctx)
|
||||
var body: PNode
|
||||
|
||||
@@ -65,7 +65,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
|
||||
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
|
||||
continue
|
||||
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
||||
var s = newSym(symKind, q.name, nextId c.idgen, getCurrOwner(c), q.info)
|
||||
var s = newSym(symKind, q.name, nextSymId c.idgen, getCurrOwner(c), q.info)
|
||||
s.flags.incl {sfUsed, sfFromGeneric}
|
||||
var t = PType(idTableGet(pt, q.typ))
|
||||
if t == nil:
|
||||
@@ -118,7 +118,7 @@ proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var TIdTable
|
||||
n.sym = x
|
||||
elif s.owner == nil or s.owner.kind == skPackage:
|
||||
#echo "copied this ", s.name.s
|
||||
x = copySym(s, nextId c.idgen)
|
||||
x = copySym(s, nextSymId c.idgen)
|
||||
x.owner = owner
|
||||
idTablePut(symMap, s, x)
|
||||
n.sym = x
|
||||
@@ -200,7 +200,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
|
||||
var param: PSym
|
||||
|
||||
template paramSym(kind): untyped =
|
||||
newSym(kind, genParam.sym.name, nextId c.idgen, genericTyp.sym, genParam.sym.info)
|
||||
newSym(kind, genParam.sym.name, nextSymId c.idgen, genericTyp.sym, genParam.sym.info)
|
||||
|
||||
if genParam.kind == tyStatic:
|
||||
param = paramSym skConst
|
||||
@@ -270,7 +270,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
|
||||
internalAssert c.config, originalParams[i].kind == nkSym
|
||||
let oldParam = originalParams[i].sym
|
||||
let param = copySym(oldParam, nextId c.idgen)
|
||||
let param = copySym(oldParam, nextSymId c.idgen)
|
||||
param.owner = prc
|
||||
param.typ = result[i]
|
||||
|
||||
@@ -339,7 +339,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
c.matchedConcept = nil
|
||||
let oldScope = c.currentScope
|
||||
while not isTopLevel(c): c.currentScope = c.currentScope.parent
|
||||
result = copySym(fn, nextId c.idgen)
|
||||
result = copySym(fn, nextSymId c.idgen)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
result.owner = fn
|
||||
result.ast = n
|
||||
@@ -401,3 +401,6 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
dec(c.instCounter)
|
||||
c.matchedConcept = oldMatchedConcept
|
||||
if result.kind == skMethod: finishMethod(c, result)
|
||||
|
||||
# inform IC of the generic
|
||||
#addGeneric(c.ic, result, entry.concreteTypes)
|
||||
|
||||
@@ -119,7 +119,7 @@ proc uninstantiate(t: PType): PType =
|
||||
else: t
|
||||
|
||||
proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode =
|
||||
var resType = newType(tyTypeDesc, nextId c.idgen, sym)
|
||||
var resType = newType(tyTypeDesc, nextTypeId c.idgen, sym)
|
||||
rawAddSon(resType, typ)
|
||||
result = toNode(resType, info)
|
||||
|
||||
@@ -160,7 +160,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
result.info = traitCall.info
|
||||
of "arity":
|
||||
result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc))
|
||||
result.typ = newType(tyInt, nextId c.idgen, context)
|
||||
result.typ = newType(tyInt, nextTypeId c.idgen, context)
|
||||
result.info = traitCall.info
|
||||
of "genericHead":
|
||||
var arg = operand
|
||||
@@ -172,7 +172,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
# result = toNode(resType, traitCall.info) # doesn't work yet
|
||||
else:
|
||||
localError(c.config, traitCall.info, "expected generic type, got: type $2 of kind $1" % [arg.kind.toHumanStr, typeToString(operand)])
|
||||
result = newType(tyError, nextId c.idgen, context).toNode(traitCall.info)
|
||||
result = newType(tyError, nextTypeId c.idgen, context).toNode(traitCall.info)
|
||||
of "stripGenericParams":
|
||||
result = uninstantiate(operand).toNode(traitCall.info)
|
||||
of "supportsCopyMem":
|
||||
@@ -198,7 +198,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
else:
|
||||
localError(c.config, traitCall.info,
|
||||
"distinctBase expects a distinct type as argument. The given type was " & typeToString(operand))
|
||||
result = newType(tyError, nextId c.idgen, context).toNode(traitCall.info)
|
||||
result = newType(tyError, nextTypeId c.idgen, context).toNode(traitCall.info)
|
||||
else:
|
||||
localError(c.config, traitCall.info, "unknown trait: " & s)
|
||||
result = newNodeI(nkEmpty, traitCall.info)
|
||||
@@ -370,7 +370,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||
elems[i] = unownedType(c, t[i])
|
||||
if elems[i] != t[i]: someChange = true
|
||||
if someChange:
|
||||
result = newType(tyTuple, nextId c.idgen, t.owner)
|
||||
result = newType(tyTuple, nextTypeId c.idgen, t.owner)
|
||||
# we have to use 'rawAddSon' here so that type flags are
|
||||
# properly computed:
|
||||
for e in elems: result.rawAddSon(e)
|
||||
@@ -381,7 +381,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||
tyGenericInst, tyAlias:
|
||||
let b = unownedType(c, t[^1])
|
||||
if b != t[^1]:
|
||||
result = copyType(t, nextId c.idgen, t.owner)
|
||||
result = copyType(t, nextTypeId c.idgen, t.owner)
|
||||
result[^1] = b
|
||||
result.flags.excl tfHasOwned
|
||||
else:
|
||||
@@ -407,26 +407,26 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
|
||||
if n.sym == oldParam:
|
||||
result.sym = newParam
|
||||
elif n.sym.owner == orig:
|
||||
result.sym = copySym(n.sym, nextId c.idgen)
|
||||
result.sym = copySym(n.sym, nextSymId c.idgen)
|
||||
result.sym.owner = procSym
|
||||
for i in 0 ..< safeLen(n):
|
||||
result[i] = transform(c, procSym, n[i], old, fresh, oldParam, newParam)
|
||||
#if n.kind == nkDerefExpr and sameType(n[0].typ, old):
|
||||
# result =
|
||||
|
||||
result = copySym(orig, nextId c.idgen)
|
||||
result = copySym(orig, nextSymId c.idgen)
|
||||
result.info = info
|
||||
result.flags.incl sfFromGeneric
|
||||
result.owner = orig
|
||||
let origParamType = orig.typ[1]
|
||||
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs), c.idgen)
|
||||
let oldParam = orig.typ.n[1].sym
|
||||
let newParam = newSym(skParam, oldParam.name, nextId c.idgen, result, result.info)
|
||||
let newParam = newSym(skParam, oldParam.name, nextSymId c.idgen, result, result.info)
|
||||
newParam.typ = newParamType
|
||||
# proc body:
|
||||
result.ast = transform(c, result, orig.ast, origParamType, newParamType, oldParam, newParam)
|
||||
# proc signature:
|
||||
result.typ = newProcType(result.info, nextId c.idgen, result)
|
||||
result.typ = newProcType(result.info, nextTypeId c.idgen, result)
|
||||
result.typ.addParam newParam
|
||||
|
||||
proc semQuantifier(c: PContext; n: PNode): PNode =
|
||||
@@ -528,10 +528,10 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
elif optTinyRtti in c.config.globalOptions:
|
||||
let nfin = skipConvCastAndClosure(n[^1])
|
||||
let fin = case nfin.kind
|
||||
let fin = case nfin.kind
|
||||
of nkSym: nfin.sym
|
||||
of nkLambda, nkDo: nfin[namePos].sym
|
||||
else:
|
||||
else:
|
||||
localError(c.config, n.info, "finalizer must be a direct reference to a proc")
|
||||
nil
|
||||
if fin != nil:
|
||||
|
||||
@@ -482,7 +482,7 @@ proc liftParallel*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): P
|
||||
checkArgs(a, body)
|
||||
|
||||
var varSection = newNodeI(nkVarSection, n.info)
|
||||
var temp = newSym(skTemp, getIdent(g.cache, "barrier"), nextId idgen, owner, n.info)
|
||||
var temp = newSym(skTemp, getIdent(g.cache, "barrier"), nextSymId idgen, owner, n.info)
|
||||
temp.typ = magicsys.getCompilerProc(g, "Barrier").typ
|
||||
incl(temp.flags, sfFromGeneric)
|
||||
let tempNode = newSymNode(temp)
|
||||
|
||||
@@ -219,7 +219,7 @@ proc markGcUnsafe(a: PEffects; reason: PNode) =
|
||||
if reason.kind == nkSym:
|
||||
a.owner.gcUnsafetyReason = reason.sym
|
||||
else:
|
||||
a.owner.gcUnsafetyReason = newSym(skUnknown, a.owner.name, nextId a.c.idgen,
|
||||
a.owner.gcUnsafetyReason = newSym(skUnknown, a.owner.name, nextSymId a.c.idgen,
|
||||
a.owner, reason.info, {})
|
||||
|
||||
when true:
|
||||
|
||||
@@ -410,7 +410,7 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
|
||||
let y = considerQuotedIdent(c, n[1])
|
||||
let obj = x.typ.skipTypes(abstractPtrs)
|
||||
if obj.kind == tyObject and tfPartial in obj.flags:
|
||||
let field = newSym(skField, getIdent(c.cache, y.s), nextId c.idgen, obj.sym, n[1].info)
|
||||
let field = newSym(skField, getIdent(c.cache, y.s), nextSymId c.idgen, obj.sym, n[1].info)
|
||||
field.typ = skipIntLit(typ, c.idgen)
|
||||
field.position = obj.n.len
|
||||
obj.n.add newSymNode(field)
|
||||
@@ -1278,7 +1278,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
|
||||
internalAssert c.config, st.lastSon.sym == nil
|
||||
incl st.flags, tfRefsAnonObj
|
||||
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
|
||||
nextId c.idgen, getCurrOwner(c), s.info)
|
||||
nextSymId c.idgen, getCurrOwner(c), s.info)
|
||||
let symNode = newSymNode(obj)
|
||||
obj.ast = a.shallowCopy
|
||||
case a[0].kind
|
||||
@@ -1449,7 +1449,7 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
|
||||
localError(c.config, n.info, "incorrect result proc symbol")
|
||||
c.p.resultSym = n[resultPos].sym
|
||||
else:
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), nextId c.idgen, getCurrOwner(c), n.info)
|
||||
var s = newSym(skResult, getIdent(c.cache, "result"), nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
s.typ = t
|
||||
incl(s.flags, sfUsed)
|
||||
c.p.resultSym = s
|
||||
@@ -1548,7 +1548,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
checkSonsLen(n, bodyPos + 1, c.config)
|
||||
var s: PSym
|
||||
if n[namePos].kind != nkSym:
|
||||
s = newSym(skProc, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), n.info)
|
||||
s = newSym(skProc, c.cache.idAnon, nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
s.ast = n
|
||||
n[namePos] = newSymNode(s)
|
||||
else:
|
||||
@@ -1856,7 +1856,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
assert phase == stepRegisterSymbol
|
||||
|
||||
if n[namePos].kind == nkEmpty:
|
||||
s = newSym(kind, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), n.info)
|
||||
s = newSym(kind, c.cache.idAnon, nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
incl(s.flags, sfUsed)
|
||||
isAnon = true
|
||||
else:
|
||||
@@ -2011,7 +2011,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
if s.kind == skMethod: semMethodPrototype(c, s, n)
|
||||
else:
|
||||
if (s.typ[0] != nil and kind != skIterator) or kind == skMacro:
|
||||
addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextId c.idgen, nil, n.info))
|
||||
addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextSymId c.idgen, nil, n.info))
|
||||
|
||||
openScope(c)
|
||||
n[bodyPos] = semGenericStmt(c, n[bodyPos])
|
||||
@@ -2149,6 +2149,7 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
|
||||
var f = checkModuleName(c.config, it)
|
||||
if f != InvalidFileIdx:
|
||||
addIncludeFileDep(c, f)
|
||||
if containsOrIncl(c.includedFiles, f.int):
|
||||
localError(c.config, n.info, errRecursiveDependencyX % toMsgFilename(c.config, f))
|
||||
else:
|
||||
|
||||
@@ -176,7 +176,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
|
||||
result[i] = onlyReplaceParams(c, n[i])
|
||||
|
||||
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
|
||||
result = newSym(kind, considerQuotedIdent(c.c, n), nextId c.c.idgen, c.owner, n.info)
|
||||
result = newSym(kind, considerQuotedIdent(c.c, n), nextSymId c.c.idgen, c.owner, n.info)
|
||||
incl(result.flags, sfGenSym)
|
||||
incl(result.flags, sfShadowed)
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
if result.typ.sym == nil:
|
||||
localError(c.config, n.info, errTypeExpected)
|
||||
return errorSym(c, n)
|
||||
result = result.typ.sym.copySym(nextId c.idgen)
|
||||
result = result.typ.sym.copySym(nextSymId c.idgen)
|
||||
result.typ = exactReplica(result.typ)
|
||||
result.typ.flags.incl tfUnresolved
|
||||
|
||||
@@ -965,7 +965,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
if kind == skMacro:
|
||||
let staticType = findEnforcedStaticType(param.typ)
|
||||
if staticType != nil:
|
||||
var a = copySym(param, nextId c.idgen)
|
||||
var a = copySym(param, nextSymId c.idgen)
|
||||
a.typ = staticType.base
|
||||
addDecl(c, a)
|
||||
#elif param.typ != nil and param.typ.kind == tyTypeDesc:
|
||||
@@ -973,7 +973,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
else:
|
||||
# within a macro, every param has the type NimNode!
|
||||
let nn = getSysSym(c.graph, param.info, "NimNode")
|
||||
var a = copySym(param, nextId c.idgen)
|
||||
var a = copySym(param, nextSymId c.idgen)
|
||||
a.typ = nn.typ
|
||||
addDecl(c, a)
|
||||
else:
|
||||
@@ -1003,7 +1003,7 @@ proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent;
|
||||
|
||||
let owner = if typeClass.sym != nil: typeClass.sym
|
||||
else: getCurrOwner(c)
|
||||
var s = newSym(skType, finalTypId, nextId c.idgen, owner, info)
|
||||
var s = newSym(skType, finalTypId, nextSymId c.idgen, owner, info)
|
||||
if sfExplain in owner.flags: s.flags.incl sfExplain
|
||||
if typId == nil: s.flags.incl(sfAnon)
|
||||
s.linkTo(typeClass)
|
||||
@@ -1109,7 +1109,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
|
||||
of tyGenericInst:
|
||||
if paramType.lastSon.kind == tyUserTypeClass:
|
||||
var cp = copyType(paramType, nextId c.idgen, getCurrOwner(c))
|
||||
var cp = copyType(paramType, nextTypeId c.idgen, getCurrOwner(c))
|
||||
cp.kind = tyUserTypeClassInst
|
||||
return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName)
|
||||
|
||||
@@ -1146,7 +1146,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass,
|
||||
tyAnd, tyOr, tyNot:
|
||||
result = addImplicitGeneric(c,
|
||||
copyType(paramType, nextId c.idgen, getCurrOwner(c)), paramTypId,
|
||||
copyType(paramType, nextTypeId c.idgen, getCurrOwner(c)), paramTypId,
|
||||
info, genericParams, paramName)
|
||||
|
||||
of tyGenericParam:
|
||||
@@ -1522,7 +1522,7 @@ proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
|
||||
|
||||
proc freshType(c: PContext; res, prev: PType): PType {.inline.} =
|
||||
if prev.isNil:
|
||||
result = copyType(res, nextId c.idgen, res.owner)
|
||||
result = copyType(res, nextTypeId c.idgen, res.owner)
|
||||
else:
|
||||
result = res
|
||||
|
||||
@@ -1579,7 +1579,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||
|
||||
internalAssert c.config, dummyName.kind == nkIdent
|
||||
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar,
|
||||
dummyName.ident, nextId c.idgen, owner, param.info)
|
||||
dummyName.ident, nextSymId c.idgen, owner, param.info)
|
||||
dummyParam.typ = dummyType
|
||||
incl dummyParam.flags, sfUsed
|
||||
addDecl(c, dummyParam)
|
||||
@@ -1836,7 +1836,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of mExpr:
|
||||
result = semTypeNode(c, n[0], nil)
|
||||
if result != nil:
|
||||
result = copyType(result, nextId c.idgen, getCurrOwner(c))
|
||||
result = copyType(result, nextTypeId c.idgen, getCurrOwner(c))
|
||||
for i in 1..<n.len:
|
||||
result.rawAddSon(semTypeNode(c, n[i], nil))
|
||||
of mDistinct:
|
||||
@@ -2115,7 +2115,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
|
||||
for j in 0..<a.len-2:
|
||||
let finalType = if j == 0: typ
|
||||
else: copyType(typ, nextId c.idgen, typ.owner)
|
||||
else: copyType(typ, nextTypeId c.idgen, typ.owner)
|
||||
# it's important the we create an unique
|
||||
# type for each generic param. the index
|
||||
# of the parameter will be stored in the
|
||||
|
||||
@@ -279,7 +279,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
var g: G[string]
|
||||
|
||||
]#
|
||||
result = copySym(s, nextId cl.c.idgen)
|
||||
result = copySym(s, nextSymId cl.c.idgen)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
#idTablePut(cl.symMap, s, result)
|
||||
result.owner = s.owner
|
||||
@@ -305,7 +305,7 @@ proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
|
||||
if cl.allowMetaTypes:
|
||||
result = t.exactReplica
|
||||
else:
|
||||
result = copyType(t, nextId(cl.c.idgen), t.owner)
|
||||
result = copyType(t, nextTypeId(cl.c.idgen), t.owner)
|
||||
#cl.typeMap.topLayer.idTablePut(result, t)
|
||||
|
||||
if cl.allowMetaTypes: return
|
||||
@@ -360,7 +360,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
|
||||
else:
|
||||
header = instCopyType(cl, t)
|
||||
|
||||
result = newType(tyGenericInst, nextId(cl.c.idgen), t[0].owner)
|
||||
result = newType(tyGenericInst, nextTypeId(cl.c.idgen), t[0].owner)
|
||||
result.flags = header.flags
|
||||
# be careful not to propagate unnecessary flags here (don't use rawAddSon)
|
||||
result.sons = @[header[0]]
|
||||
|
||||
@@ -568,7 +568,7 @@ proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
|
||||
|
||||
proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
## For example we have:
|
||||
##
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## proc myMap[T,S](sIn: seq[T], f: proc(x: T): S): seq[S] = ...
|
||||
## proc innerProc[Q,W](q: Q): W = ...
|
||||
@@ -728,7 +728,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
if alreadyBound != nil: typ = alreadyBound
|
||||
|
||||
template paramSym(kind): untyped =
|
||||
newSym(kind, typeParamName, nextId(c.idgen), typeClass.sym, typeClass.sym.info, {})
|
||||
newSym(kind, typeParamName, nextSymId(c.idgen), typeClass.sym, typeClass.sym.info, {})
|
||||
|
||||
block addTypeParam:
|
||||
for prev in typeParams:
|
||||
@@ -741,7 +741,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
of tyStatic:
|
||||
param = paramSym skConst
|
||||
param.typ = typ.exactReplica
|
||||
#copyType(typ, nextId(c.idgen), typ.owner)
|
||||
#copyType(typ, nextTypeId(c.idgen), typ.owner)
|
||||
if typ.n == nil:
|
||||
param.typ.flags.incl tfInferrableStatic
|
||||
else:
|
||||
@@ -749,7 +749,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
of tyUnknown:
|
||||
param = paramSym skVar
|
||||
param.typ = typ.exactReplica
|
||||
#copyType(typ, nextId(c.idgen), typ.owner)
|
||||
#copyType(typ, nextTypeId(c.idgen), typ.owner)
|
||||
else:
|
||||
param = paramSym skType
|
||||
param.typ = if typ.isMetaType:
|
||||
@@ -801,7 +801,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff)
|
||||
else:
|
||||
result = ff.exactReplica
|
||||
#copyType(ff, nextId(c.idgen), ff.owner)
|
||||
#copyType(ff, nextTypeId(c.idgen), ff.owner)
|
||||
|
||||
result.n = checkedBody
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
|
||||
if sfWasForwarded notin owner.flags:
|
||||
let argType = arg.sym.typ
|
||||
|
||||
let sinkType = newType(tySink, nextId(idgen), owner)
|
||||
let sinkType = newType(tySink, nextTypeId(idgen), owner)
|
||||
sinkType.size = argType.size
|
||||
sinkType.align = argType.align
|
||||
sinkType.paddingAtEnd = argType.paddingAtEnd
|
||||
|
||||
@@ -55,7 +55,7 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
|
||||
|
||||
proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator; owner: PSym; typ: PType;
|
||||
v: PNode; useShallowCopy=false): PSym =
|
||||
result = newSym(skTemp, getIdent(g.cache, genPrefix), nextId idgen, owner, varSection.info,
|
||||
result = newSym(skTemp, getIdent(g.cache, genPrefix), nextSymId idgen, owner, varSection.info,
|
||||
owner.options)
|
||||
result.typ = typ
|
||||
incl(result.flags, sfFromGeneric)
|
||||
@@ -169,7 +169,7 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
|
||||
params.add threadParam.newSymNode
|
||||
params.add argsParam.newSymNode
|
||||
|
||||
var t = newType(tyProc, nextId idgen, threadParam.owner)
|
||||
var t = newType(tyProc, nextTypeId idgen, threadParam.owner)
|
||||
t.rawAddSon nil
|
||||
t.rawAddSon threadParam.typ
|
||||
t.rawAddSon argsParam.typ
|
||||
@@ -189,7 +189,7 @@ proc createCastExpr(argsParam: PSym; objType: PType; idgen: IdGenerator): PNode
|
||||
result = newNodeI(nkCast, argsParam.info)
|
||||
result.add newNodeI(nkEmpty, argsParam.info)
|
||||
result.add newSymNode(argsParam)
|
||||
result.typ = newType(tyPtr, nextId idgen, objType.owner)
|
||||
result.typ = newType(tyPtr, nextTypeId idgen, objType.owner)
|
||||
result.typ.rawAddSon(objType)
|
||||
|
||||
proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType;
|
||||
@@ -211,7 +211,7 @@ proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType;
|
||||
# localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
|
||||
|
||||
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
|
||||
var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options)
|
||||
var field = newSym(skField, fieldname, nextSymId idgen, objType.owner, n.info, g.config.options)
|
||||
field.typ = argType
|
||||
objType.addField(field, g.cache, idgen)
|
||||
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
|
||||
@@ -239,7 +239,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
|
||||
# localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
|
||||
|
||||
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
|
||||
var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options)
|
||||
var field = newSym(skField, fieldname, nextSymId idgen, objType.owner, n.info, g.config.options)
|
||||
|
||||
if argType.kind in {tyVarargs, tyOpenArray}:
|
||||
# important special case: we always create a zero-copy slice:
|
||||
@@ -247,7 +247,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
|
||||
slice.typ = n.typ
|
||||
slice[0] = newSymNode(createMagic(g, "slice", mSlice))
|
||||
slice[0].typ = getSysType(g, n.info, tyInt) # fake type
|
||||
var fieldB = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options)
|
||||
var fieldB = newSym(skField, tmpName, nextSymId idgen, objType.owner, n.info, g.config.options)
|
||||
fieldB.typ = getSysType(g, n.info, tyInt)
|
||||
objType.addField(fieldB, g.cache, idgen)
|
||||
|
||||
@@ -257,7 +257,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
|
||||
objType.addField(field, g.cache, idgen)
|
||||
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
|
||||
|
||||
var fieldA = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options)
|
||||
var fieldA = newSym(skField, tmpName, nextSymId idgen, objType.owner, n.info, g.config.options)
|
||||
fieldA.typ = getSysType(g, n.info, tyInt)
|
||||
objType.addField(fieldA, g.cache, idgen)
|
||||
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
|
||||
@@ -332,9 +332,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
var fn = n[0]
|
||||
let
|
||||
name = (if fn.kind == nkSym: fn.sym.name.s else: genPrefix) & "Wrapper"
|
||||
wrapperProc = newSym(skProc, getIdent(g.cache, name), nextId idgen, owner, fn.info, g.config.options)
|
||||
threadParam = newSym(skParam, getIdent(g.cache, "thread"), nextId idgen, wrapperProc, n.info, g.config.options)
|
||||
argsParam = newSym(skParam, getIdent(g.cache, "args"), nextId idgen, wrapperProc, n.info, g.config.options)
|
||||
wrapperProc = newSym(skProc, getIdent(g.cache, name), nextSymId idgen, owner, fn.info, g.config.options)
|
||||
threadParam = newSym(skParam, getIdent(g.cache, "thread"), nextSymId idgen, wrapperProc, n.info, g.config.options)
|
||||
argsParam = newSym(skParam, getIdent(g.cache, "args"), nextSymId idgen, wrapperProc, n.info, g.config.options)
|
||||
|
||||
wrapperProc.flags.incl sfInjectDestructors
|
||||
block:
|
||||
@@ -347,7 +347,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
incl(objType.flags, tfFinal)
|
||||
let castExpr = createCastExpr(argsParam, objType, idgen)
|
||||
|
||||
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), nextId idgen, owner, n.info, g.config.options)
|
||||
var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), nextSymId idgen, owner, n.info, g.config.options)
|
||||
block:
|
||||
scratchObj.typ = objType
|
||||
incl(scratchObj.flags, sfFromGeneric)
|
||||
@@ -364,7 +364,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
skFunc, skMethod, skConverter}):
|
||||
# for indirect calls we pass the function pointer in the scratchObj
|
||||
var argType = n[0].typ.skipTypes(abstractInst)
|
||||
var field = newSym(skField, getIdent(g.cache, "fn"), nextId idgen, owner, n.info, g.config.options)
|
||||
var field = newSym(skField, getIdent(g.cache, "fn"), nextSymId idgen, owner, n.info, g.config.options)
|
||||
field.typ = argType
|
||||
objType.addField(field, g.cache, idgen)
|
||||
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
|
||||
@@ -386,9 +386,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
|
||||
var barrierAsExpr: PNode = nil
|
||||
if barrier != nil:
|
||||
let typ = newType(tyPtr, nextId idgen, owner)
|
||||
let typ = newType(tyPtr, nextTypeId idgen, owner)
|
||||
typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
|
||||
var field = newSym(skField, getIdent(g.cache, "barrier"), nextId idgen, owner, n.info, g.config.options)
|
||||
var field = newSym(skField, getIdent(g.cache, "barrier"), nextSymId idgen, owner, n.info, g.config.options)
|
||||
field.typ = typ
|
||||
objType.addField(field, g.cache, idgen)
|
||||
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
|
||||
@@ -396,7 +396,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
|
||||
var fvField, fvAsExpr: PNode = nil
|
||||
if spawnKind == srFlowVar:
|
||||
var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options)
|
||||
var field = newSym(skField, getIdent(g.cache, "fv"), nextSymId idgen, owner, n.info, g.config.options)
|
||||
field.typ = retType
|
||||
objType.addField(field, g.cache, idgen)
|
||||
fvField = newDotExpr(scratchObj, field)
|
||||
@@ -407,8 +407,8 @@ proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExp
|
||||
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, fvField)
|
||||
|
||||
elif spawnKind == srByVar:
|
||||
var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options)
|
||||
field.typ = newType(tyPtr, nextId idgen, objType.owner)
|
||||
var field = newSym(skField, getIdent(g.cache, "fv"), nextSymId idgen, owner, n.info, g.config.options)
|
||||
field.typ = newType(tyPtr, nextTypeId idgen, objType.owner)
|
||||
field.typ.rawAddSon(retType)
|
||||
objType.addField(field, g.cache, idgen)
|
||||
fvAsExpr = indirectAccess(castExpr, field, n.info)
|
||||
|
||||
@@ -87,7 +87,7 @@ proc getCurrOwner(c: PTransf): PSym =
|
||||
else: result = c.module
|
||||
|
||||
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), nextId(c.idgen), getCurrOwner(c), info)
|
||||
let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), nextSymId(c.idgen), getCurrOwner(c), info)
|
||||
r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
|
||||
incl(r.flags, sfFromGeneric)
|
||||
let owner = getCurrOwner(c)
|
||||
@@ -163,7 +163,7 @@ proc freshVar(c: PTransf; v: PSym): PNode =
|
||||
if owner.isIterator and not c.tooEarly:
|
||||
result = freshVarForClosureIter(c.graph, v, c.idgen, owner)
|
||||
else:
|
||||
var newVar = copySym(v, nextId(c.idgen))
|
||||
var newVar = copySym(v, nextSymId(c.idgen))
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
newVar.owner = owner
|
||||
result = newSymNode(newVar)
|
||||
@@ -233,7 +233,7 @@ proc hasContinue(n: PNode): bool =
|
||||
if hasContinue(n[i]): return true
|
||||
|
||||
proc newLabel(c: PTransf, n: PNode): PSym =
|
||||
result = newSym(skLabel, nil, nextId(c.idgen), getCurrOwner(c), n.info)
|
||||
result = newSym(skLabel, nil, nextSymId(c.idgen), getCurrOwner(c), n.info)
|
||||
result.name = getIdent(c.graph.cache, genPrefix)
|
||||
|
||||
proc transformBlock(c: PTransf, n: PNode): PNode =
|
||||
|
||||
@@ -1311,7 +1311,7 @@ proc baseOfDistinct*(t: PType; idgen: IdGenerator): PType =
|
||||
if t.kind == tyDistinct:
|
||||
result = t[0]
|
||||
else:
|
||||
result = copyType(t, nextId idgen, t.owner)
|
||||
result = copyType(t, nextTypeId idgen, t.owner)
|
||||
var parent: PType = nil
|
||||
var it = result
|
||||
while it.kind in {tyPtr, tyRef, tyOwned}:
|
||||
@@ -1457,7 +1457,7 @@ proc takeType*(formal, arg: PType; idgen: IdGenerator): PType =
|
||||
result = formal
|
||||
elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and
|
||||
arg.isEmptyContainer:
|
||||
let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), nextId(idgen), arg.owner)
|
||||
let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), nextTypeId(idgen), arg.owner)
|
||||
a[ord(arg.kind == tyArray)] = formal[0]
|
||||
result = a
|
||||
elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind:
|
||||
|
||||
@@ -688,7 +688,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let s = regs[rb].node.strVal.addr # or `byaddr`
|
||||
if idx <% s[].len:
|
||||
# `makePtrType` not accessible from vm.nim
|
||||
let typ = newType(tyPtr, nextId c.idgen, c.module.owner)
|
||||
let typ = newType(tyPtr, nextTypeId c.idgen, c.module.owner)
|
||||
typ.add getSysType(c.graph, c.debug[pc], tyChar)
|
||||
let node = newNodeIT(nkIntLit, c.debug[pc], typ) # xxx nkPtrLit
|
||||
node.intVal = cast[int](s[][idx].addr)
|
||||
@@ -1962,7 +1962,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
else: regs[rc].node.strVal
|
||||
if k < 0 or k > ord(high(TSymKind)):
|
||||
internalError(c.config, c.debug[pc], "request to create symbol of invalid kind")
|
||||
var sym = newSym(k.TSymKind, getIdent(c.cache, name), nextId c.idgen, c.module.owner, c.debug[pc])
|
||||
var sym = newSym(k.TSymKind, getIdent(c.cache, name), nextSymId c.idgen, c.module.owner, c.debug[pc])
|
||||
incl(sym.flags, sfGenSym)
|
||||
regs[ra].node = newSymNode(sym)
|
||||
regs[ra].node.flags.incl nfIsRef
|
||||
@@ -2257,7 +2257,7 @@ const evalMacroLimit = 1000
|
||||
|
||||
proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.typ = newType(tyError, nextId idgen, owner)
|
||||
result.typ = newType(tyError, nextTypeId idgen, owner)
|
||||
result.typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstCounter: ref int;
|
||||
|
||||
@@ -26,7 +26,7 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): str
|
||||
|
||||
proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo;
|
||||
idgen: IdGenerator): PNode =
|
||||
let sym = newSym(skType, getIdent(cache, name), nextId(idgen), t.owner, info)
|
||||
let sym = newSym(skType, getIdent(cache, name), nextSymId(idgen), t.owner, info)
|
||||
sym.magic = m
|
||||
sym.typ = t
|
||||
result = newSymNode(sym)
|
||||
@@ -47,7 +47,7 @@ proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; inf
|
||||
for i in 0..<t.len:
|
||||
if t[i] == nil:
|
||||
let void = atomicTypeX(cache, "void", mVoid, t, info, idgen)
|
||||
void.typ = newType(tyVoid, nextId(idgen), t.owner)
|
||||
void.typ = newType(tyVoid, nextTypeId(idgen), t.owner)
|
||||
result.add void
|
||||
else:
|
||||
result.add mapTypeToAstX(cache, t[i], info, idgen, inst)
|
||||
|
||||
@@ -220,7 +220,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
if pos >= result.len:
|
||||
setLen(result.sons, pos + 1)
|
||||
let fieldNode = newNode(nkExprColonExpr)
|
||||
fieldNode.add newSymNode(newSym(skField, ident, nextId(idgen), nil, unknownLineInfo))
|
||||
fieldNode.add newSymNode(newSym(skField, ident, nextSymId(idgen), nil, unknownLineInfo))
|
||||
fieldNode.add loadAny(p, field.typ, tab, cache, conf, idgen)
|
||||
result[pos] = fieldNode
|
||||
if p.kind == jsonObjectEnd: next(p)
|
||||
|
||||
@@ -455,9 +455,9 @@ macro `{}`*(typ: typedesc, xs: varargs[untyped]): auto =
|
||||
# from a proc, `this` being the first argument.
|
||||
|
||||
proc replaceSyms(n: NimNode): NimNode =
|
||||
if n.kind == nnkSym:
|
||||
if n.kind == nnkSym:
|
||||
result = newIdentNode($n)
|
||||
else:
|
||||
else:
|
||||
result = n
|
||||
for i in 0..<n.len:
|
||||
result[i] = replaceSyms(n[i])
|
||||
|
||||
@@ -18,7 +18,7 @@ import std / [os]
|
||||
|
||||
proc initInterpreter(script: string): Interpreter =
|
||||
let std = findNimStdLibCompileTime()
|
||||
result = createInterpreter(script , [std, parentDir(currentSourcePath),
|
||||
result = createInterpreter(script, [std, parentDir(currentSourcePath),
|
||||
std / "pure", std / "core"])
|
||||
|
||||
proc main() =
|
||||
|
||||
Reference in New Issue
Block a user