big refactoring: mores stuff compiles

This commit is contained in:
Andreas Rumpf
2018-05-10 13:39:23 +02:00
parent 0d56dd4677
commit 5bf31fcabe
6 changed files with 82 additions and 99 deletions

View File

@@ -113,16 +113,16 @@ when false:
localError(pkg.info, "package name must be an identifier or string literal")
result = ""
proc getModuleName*(n: PNode): string =
proc getModuleName*(conf: ConfigRef; n: PNode): string =
# This returns a short relative module name without the nim extension
# e.g. like "system", "importer" or "somepath/module"
# The proc won't perform any checks that the path is actually valid
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
result = pathSubs(n.strVal, n.info.toFullPath().splitFile().dir)
result = pathSubs(conf, n.strVal, n.info.toFullPath().splitFile().dir)
except ValueError:
localError(n.info, "invalid path: " & n.strVal)
localError(conf, n.info, "invalid path: " & n.strVal)
result = n.strVal
of nkIdent:
result = n.ident.s
@@ -137,7 +137,7 @@ proc getModuleName*(n: PNode): string =
n.sons[0] = n.sons[1]
n.sons[1] = n.sons[2]
n.sons.setLen(2)
return getModuleName(n.sons[0])
return getModuleName(conf, n.sons[0])
when false:
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
if n0.kind == nkIdent and n0.ident.s == "/":
@@ -146,7 +146,7 @@ proc getModuleName*(n: PNode): string =
localError(n.info, "only '/' supported with $package notation")
result = ""
else:
let modname = getModuleName(n[2])
let modname = getModuleName(conf, n[2])
if $n1 == "std":
template attempt(a) =
let x = addFileExt(a, "nim")
@@ -155,7 +155,7 @@ proc getModuleName*(n: PNode): string =
attempt(options.libpath / candidate / modname)
# hacky way to implement 'x / y /../ z':
result = getModuleName(n1)
result = getModuleName(conf, n1)
result.add renderTree(n0, {renderNoComments})
result.add modname
of nkPrefix:
@@ -169,19 +169,19 @@ proc getModuleName*(n: PNode): string =
of nkDotExpr:
result = renderTree(n, {renderNoComments}).replace(".", "/")
of nkImportAs:
result = getModuleName(n.sons[0])
result = getModuleName(conf, n.sons[0])
else:
localError(n.info, errGenerated, "invalid module name: '$1'" % n.renderTree)
localError(conf, n.info, "invalid module name: '$1'" % n.renderTree)
result = ""
proc checkModuleName*(n: PNode; doLocalError=true): FileIndex =
proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex =
# This returns the full canonical path for a given module import
let modulename = n.getModuleName
let fullPath = findModule(modulename, n.info.toFullPath)
let modulename = getModuleName(conf, n)
let fullPath = findModule(conf, modulename, n.info.toFullPath)
if fullPath.len == 0:
if doLocalError:
let m = if modulename.len > 0: modulename else: $n
localError(n.info, errCannotOpenFile, m)
localError(conf, n.info, "cannot open file: " & m)
result = InvalidFileIDX
else:
result = fullPath.fileInfoIdx
result = fileInfoIdx(conf, fullPath)

View File

@@ -12,27 +12,10 @@
import
ast, astalgo, trees, nversion, msgs, platform, bitsets, types, renderer
proc toBitSet*(s: PNode, b: var TBitSet)
# this function is used for case statement checking:
proc overlap*(a, b: PNode): bool
proc inSet*(s: PNode, elem: PNode): bool
proc someInSet*(s: PNode, a, b: PNode): bool
proc emptyRange*(a, b: PNode): bool
proc setHasRange*(s: PNode): bool
# returns true if set contains a range (needed by the code generator)
# these are used for constant folding:
proc unionSets*(a, b: PNode): PNode
proc diffSets*(a, b: PNode): PNode
proc intersectSets*(a, b: PNode): PNode
proc symdiffSets*(a, b: PNode): PNode
proc containsSets*(a, b: PNode): bool
proc equalSets*(a, b: PNode): bool
proc cardSet*(a: PNode): BiggestInt
# implementation
proc inSet(s: PNode, elem: PNode): bool =
proc inSet*(s: PNode, elem: PNode): bool =
assert s.kind == nkCurly
if s.kind != nkCurly:
internalError(s.info, "inSet")
#internalError(s.info, "inSet")
return false
for i in countup(0, sonsLen(s) - 1):
if s.sons[i].kind == nkRange:
@@ -44,7 +27,7 @@ proc inSet(s: PNode, elem: PNode): bool =
return true
result = false
proc overlap(a, b: PNode): bool =
proc overlap*(a, b: PNode): bool =
if a.kind == nkRange:
if b.kind == nkRange:
# X..Y and C..D overlap iff (X <= D and C <= Y)
@@ -58,10 +41,11 @@ proc overlap(a, b: PNode): bool =
else:
result = sameValue(a, b)
proc someInSet(s: PNode, a, b: PNode): bool =
proc someInSet*(s: PNode, a, b: PNode): bool =
# checks if some element of a..b is in the set s
assert s.kind == nkCurly
if s.kind != nkCurly:
internalError(s.info, "SomeInSet")
#internalError(s.info, "SomeInSet")
return false
for i in countup(0, sonsLen(s) - 1):
if s.sons[i].kind == nkRange:
@@ -74,7 +58,7 @@ proc someInSet(s: PNode, a, b: PNode): bool =
return true
result = false
proc toBitSet(s: PNode, b: var TBitSet) =
proc toBitSet*(s: PNode, b: var TBitSet) =
var first, j: BiggestInt
first = firstOrd(s.typ.sons[0])
bitSetInit(b, int(getSize(s.typ)))
@@ -87,7 +71,7 @@ proc toBitSet(s: PNode, b: var TBitSet) =
else:
bitSetIncl(b, getOrdValue(s.sons[i]) - first)
proc toTreeSet(s: TBitSet, settype: PType, info: TLineInfo): PNode =
proc toTreeSet*(s: TBitSet, settype: PType, info: TLineInfo): PNode =
var
a, b, e, first: BiggestInt # a, b are interval borders
elemType: PType
@@ -128,18 +112,18 @@ template nodeSetOp(a, b: PNode, op: untyped) {.dirty.} =
op(x, y)
result = toTreeSet(x, a.typ, a.info)
proc unionSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
proc diffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
proc intersectSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
proc symdiffSets(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
proc unionSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetUnion)
proc diffSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetDiff)
proc intersectSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetIntersect)
proc symdiffSets*(a, b: PNode): PNode = nodeSetOp(a, b, bitSetSymDiff)
proc containsSets(a, b: PNode): bool =
proc containsSets*(a, b: PNode): bool =
var x, y: TBitSet
toBitSet(a, x)
toBitSet(b, y)
result = bitSetContains(x, y)
proc equalSets(a, b: PNode): bool =
proc equalSets*(a, b: PNode): bool =
var x, y: TBitSet
toBitSet(a, x)
toBitSet(b, y)
@@ -156,20 +140,19 @@ proc deduplicate*(a: PNode): PNode =
toBitSet(a, x)
result = toTreeSet(x, a.typ, a.info)
proc cardSet(a: PNode): BiggestInt =
proc cardSet*(a: PNode): BiggestInt =
var x: TBitSet
toBitSet(a, x)
result = bitSetCard(x)
proc setHasRange(s: PNode): bool =
proc setHasRange*(s: PNode): bool =
assert s.kind == nkCurly
if s.kind != nkCurly:
internalError(s.info, "SetHasRange")
return false
for i in countup(0, sonsLen(s) - 1):
if s.sons[i].kind == nkRange:
return true
result = false
proc emptyRange(a, b: PNode): bool =
proc emptyRange*(a, b: PNode): bool =
result = not leValue(a, b) # a > b iff not (a <= b)

View File

@@ -13,7 +13,8 @@
import
strutils, options, ast, astalgo, llstream, msgs, platform, os,
condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder, rod
nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder, rod,
configuration
type
@@ -57,11 +58,11 @@ var
# implementation
proc skipCodegen*(n: PNode): bool {.inline.} =
proc skipCodegen*(config: ConfigRef; n: PNode): bool {.inline.} =
# can be used by codegen passes to determine whether they should do
# something with `n`. Currently, this ignores `n` and uses the global
# error count instead.
result = msgs.gErrorCounter > 0
result = config.errorCounter > 0
const
maxPasses = 10
@@ -139,20 +140,21 @@ proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) =
m = gPasses[i].close(graph, a[i], m)
a[i] = nil # free the memory here
proc resolveMod(module, relativeTo: string): FileIndex =
let fullPath = findModule(module, relativeTo)
proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
let fullPath = findModule(conf, module, relativeTo)
if fullPath.len == 0:
result = InvalidFileIDX
else:
result = fullPath.fileInfoIdx
result = fileInfoIdx(conf, fullPath)
proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
proc processImplicits(conf: ConfigRef; implicits: seq[string], nodeKind: TNodeKind,
a: var TPassContextArray; m: PSym) =
# XXX fixme this should actually be relative to the config file!
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
let relativeTo = m.info.toFullPath
for module in items(implicits):
# implicit imports should not lead to a module importing itself
if m.position != resolveMod(module, relativeTo).int32:
if m.position != resolveMod(conf, module, relativeTo).int32:
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
var str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
@@ -202,7 +204,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
let filename = fileIdx.toFullPathConsiderDirty
s = llStreamOpen(filename, fmRead)
if s == nil:
rawMessage(errCannotOpenFile, filename)
rawMessage(graph.config, errCannotOpenFile, filename)
return false
else:
s = stream
@@ -214,8 +216,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
# 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.
processImplicits implicitImports, nkImportStmt, a, module
processImplicits implicitIncludes, nkIncludeStmt, a, module
processImplicits graph.config, implicitImports, nkImportStmt, a, module
processImplicits graph.config, implicitIncludes, nkIncludeStmt, a, module
while true:
if graph.stopCompile(): break

View File

@@ -1,7 +1,8 @@
import
intsets, ast, idents, algorithm, renderer, parser, ospaths, strutils,
sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables
sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables,
configuration
type
DepN = ref object
@@ -151,10 +152,10 @@ proc expandIncludes(graph: ModuleGraph, module: PSym, n: PNode,
for a in n:
if a.kind == nkIncludeStmt:
for i in 0..<a.len:
var f = checkModuleName(a.sons[i])
var f = checkModuleName(graph.config, a.sons[i])
if f != InvalidFileIDX:
if containsOrIncl(includedFiles, f.int):
localError(a.info, errRecursiveDependencyX, f.toFilename)
localError(graph.config, a.info, "recursive dependency: '$1'" % f.toFilename)
else:
let nn = includeModule(graph, module, f, cache)
let nnn = expandIncludes(graph, module, nn, modulePath,
@@ -189,7 +190,7 @@ proc haveSameKind(dns: seq[DepN]): bool =
if dn.pnode.kind != kind:
return false
proc mergeSections(comps: seq[seq[DepN]], res: PNode) =
proc mergeSections(conf: ConfigRef; comps: seq[seq[DepN]], res: PNode) =
# Merges typeSections and ConstSections when they form
# a strong component (ex: circular type definition)
for c in comps:
@@ -229,7 +230,7 @@ proc mergeSections(comps: seq[seq[DepN]], res: PNode) =
wmsg &= "line " & $cs[^1].pnode.info.line &
" depends on line " & $cs[j].pnode.info.line &
": " & cs[^1].expls[ci] & "\n"
message(cs[0].pnode.info, warnUser, wmsg)
message(conf, cs[0].pnode.info, warnUser, wmsg)
var i = 0
while i < cs.len:
@@ -441,4 +442,4 @@ proc reorder*(graph: ModuleGraph, n: PNode, module: PSym, cache: IdentCache): PN
var g = buildGraph(n, deps)
let comps = getStrongComponents(g)
mergeSections(comps, result)
mergeSections(graph.config, comps, result)

View File

@@ -37,12 +37,13 @@ type
files: TStringSeq
origFile: string
cache: IdentCache
config: ConfigRef
PRodWriter = ref TRodWriter
proc getDefines(): string =
proc getDefines(conf: ConfigRef): string =
result = ""
for d in definedSymbolNames():
for d in definedSymbolNames(conf.symbols):
if result.len != 0: add(result, " ")
add(result, d)
@@ -57,8 +58,10 @@ proc fileIdx(w: PRodWriter, filename: string): int =
template filename*(w: PRodWriter): string =
toFilename(FileIndex w.module.position)
proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache): PRodWriter =
proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache;
config: ConfigRef): PRodWriter =
new(result)
result.config = config
result.sstack = @[]
result.tstack = @[]
initIiTable(result.index.tab)
@@ -67,7 +70,7 @@ proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache): PRodWriter
result.imports.r = ""
result.hash = hash
result.module = module
result.defines = getDefines()
result.defines = getDefines(config)
result.options = options.gOptions
result.files = @[]
result.inclDeps = ""
@@ -83,14 +86,14 @@ proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache): PRodWriter
proc addModDep(w: PRodWriter, dep: string; info: TLineInfo) =
if w.modDeps.len != 0: add(w.modDeps, ' ')
let resolved = dep.findModule(info.toFullPath)
let resolved = findModule(w.config, dep, info.toFullPath)
encodeVInt(fileIdx(w, resolved), w.modDeps)
const
rodNL = "\x0A"
proc addInclDep(w: PRodWriter, dep: string; info: TLineInfo) =
let resolved = dep.findModule(info.toFullPath)
let resolved = findModule(w.config, dep, info.toFullPath)
encodeVInt(fileIdx(w, resolved), w.inclDeps)
add(w.inclDeps, " ")
encodeStr($secureHashFile(resolved), w.inclDeps)
@@ -201,7 +204,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
result.add("[]")
return
# we need no surrounding [] here because the type is in a line of its own
if t.kind == tyForward: internalError("encodeType: tyForward")
if t.kind == tyForward: internalError(w.config, "encodeType: tyForward")
# for the new rodfile viewer we use a preceding [ so that the data section
# can easily be disambiguated:
add(result, '[')
@@ -454,7 +457,7 @@ proc processStacks(w: PRodWriter, finalPass: bool) =
oldS = slen
oldT = tlen
if finalPass and (oldS != 0 or oldT != 0):
internalError("could not serialize some forwarded symbols/types")
internalError(w.config, "could not serialize some forwarded symbols/types")
proc rawAddInterfaceSym(w: PRodWriter, s: PSym) =
pushSym(w, s)
@@ -476,7 +479,7 @@ proc addStmt(w: PRodWriter, n: PNode) =
proc writeRod(w: PRodWriter) =
processStacks(w, true)
var f: File
if not open(f, completeGeneratedFilePath(changeFileExt(
if not open(f, completeGeneratedFilePath(w.config, changeFileExt(
w.filename.withPackageName, RodExt)),
fmWrite):
#echo "couldn't write rod file for: ", w.filename
@@ -587,17 +590,17 @@ proc process(c: PPassContext, n: PNode): PNode =
of nkProcDef, nkFuncDef, nkIteratorDef, nkConverterDef,
nkTemplateDef, nkMacroDef:
let s = n.sons[namePos].sym
if s == nil: internalError(n.info, "rodwrite.process")
if s == nil: internalError(w.config, n.info, "rodwrite.process")
if n.sons[bodyPos] == nil:
internalError(n.info, "rodwrite.process: body is nil")
internalError(w.config, n.info, "rodwrite.process: body is nil")
if n.sons[bodyPos].kind != nkEmpty or s.magic != mNone or
sfForward notin s.flags:
addInterfaceSym(w, s)
of nkMethodDef:
let s = n.sons[namePos].sym
if s == nil: internalError(n.info, "rodwrite.process")
if s == nil: internalError(w.config, n.info, "rodwrite.process")
if n.sons[bodyPos] == nil:
internalError(n.info, "rodwrite.process: body is nil")
internalError(w.config, n.info, "rodwrite.process: body is nil")
if n.sons[bodyPos].kind != nkEmpty or s.magic != mNone or
sfForward notin s.flags:
pushSym(w, s)
@@ -612,7 +615,7 @@ proc process(c: PPassContext, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i]
if a.kind == nkCommentStmt: continue
if a.sons[0].kind != nkSym: internalError(a.info, "rodwrite.process")
if a.sons[0].kind != nkSym: internalError(w.config, a.info, "rodwrite.process")
var s = a.sons[0].sym
addInterfaceSym(w, s)
# this takes care of enum fields too
@@ -627,22 +630,22 @@ proc process(c: PPassContext, n: PNode): PNode =
# end
of nkImportStmt:
for i in countup(0, sonsLen(n) - 1):
addModDep(w, getModuleName(n.sons[i]), n.info)
addModDep(w, getModuleName(w.config, n.sons[i]), n.info)
addStmt(w, n)
of nkFromStmt, nkImportExceptStmt:
addModDep(w, getModuleName(n.sons[0]), n.info)
addModDep(w, getModuleName(w.config, n.sons[0]), n.info)
addStmt(w, n)
of nkIncludeStmt:
for i in countup(0, sonsLen(n) - 1):
addInclDep(w, getModuleName(n.sons[i]), n.info)
addInclDep(w, getModuleName(w.config, n.sons[i]), n.info)
of nkPragma:
addStmt(w, n)
else:
discard
proc myOpen(g: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
if module.id < 0: internalError("rodwrite: module ID not set")
var w = newRodWriter(rodread.getHash FileIndex module.position, module, cache)
if module.id < 0: internalError(g.config, "rodwrite: module ID not set")
var w = newRodWriter(rodread.getHash FileIndex module.position, module, cache, g.config)
rawAddInterfaceSym(w, module)
result = w
@@ -650,7 +653,7 @@ proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
result = process(c, n)
var w = PRodWriter(c)
writeRod(w)
idgen.saveMaxIds(options.gProjectPath / options.gProjectName)
idgen.saveMaxIds(graph.config, options.gProjectPath / options.gProjectName)
const rodwritePass* = makePass(open = myOpen, close = myClose, process = process)

View File

@@ -13,16 +13,12 @@
import
strutils, options, ast, astalgo, trees, treetab, nimsets, times,
nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
commands, magicsys
commands, magicsys, modulegraphs
proc getConstExpr*(m: PSym, n: PNode): PNode
# evaluates the constant expression or returns nil if it is no constant
# expression
proc evalOp*(m: TMagic, n, a, b, c: PNode): PNode
proc leValueConv*(a, b: PNode): bool
proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode
proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode
proc newStrNodeT*(strVal: string, n: PNode): PNode
proc checkInRange(n: PNode, res: BiggestInt): bool =
if res in firstOrd(n.typ)..lastOrd(n.typ):
@@ -32,7 +28,7 @@ proc foldAdd(a, b: BiggestInt, n: PNode): PNode =
let res = a +% b
if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
checkInRange(n, res):
result = newIntNodeT(res, n)
result = newIntNodeT(res, n)
proc foldSub*(a, b: BiggestInt, n: PNode): PNode =
let res = a -% b
@@ -43,7 +39,7 @@ proc foldSub*(a, b: BiggestInt, n: PNode): PNode =
proc foldAbs*(a: BiggestInt, n: PNode): PNode =
if a != firstOrd(n.typ):
result = newIntNodeT(a, n)
proc foldMod*(a, b: BiggestInt, n: PNode): PNode =
if b != 0'i64:
result = newIntNodeT(a mod b, n)
@@ -81,9 +77,7 @@ proc foldMul*(a, b: BiggestInt, n: PNode): PNode =
checkInRange(n, res):
return newIntNodeT(res, n)
# implementation
proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode =
proc newIntNodeT*(intVal: BiggestInt, n: PNode): PNode =
case skipTypes(n.typ, abstractVarRange).kind
of tyInt:
result = newIntNode(nkIntLit, intVal)
@@ -103,7 +97,7 @@ proc newIntNodeT(intVal: BiggestInt, n: PNode): PNode =
result.typ = n.typ
result.info = n.info
proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode =
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode): PNode =
result = newFloatNode(nkFloatLit, floatVal)
if skipTypes(n.typ, abstractVarRange).kind == tyFloat:
result.typ = getFloatLitType(result)
@@ -111,7 +105,7 @@ proc newFloatNodeT(floatVal: BiggestFloat, n: PNode): PNode =
result.typ = n.typ
result.info = n.info
proc newStrNodeT(strVal: string, n: PNode): PNode =
proc newStrNodeT*(strVal: string, n: PNode): PNode =
result = newStrNode(nkStrLit, strVal)
result.typ = n.typ
result.info = n.info
@@ -378,7 +372,7 @@ proc getConstIfExpr(c: PSym, n: PNode): PNode =
if result == nil: result = getConstExpr(c, it.sons[0])
else: internalError(it.info, "getConstIfExpr()")
proc leValueConv(a, b: PNode): bool =
proc leValueConv*(a, b: PNode): bool =
result = false
case a.kind
of nkCharLit..nkUInt64Lit: