Merge branch 'devel' into feature/3691
This commit is contained in:
commit
d5bb5e832b
84 changed files with 1381 additions and 492 deletions
|
|
@ -1541,7 +1541,8 @@ proc skipGenericOwner*(s: PSym): PSym =
|
|||
## Generic instantiations are owned by their originating generic
|
||||
## symbol. This proc skips such owners and goes straight to the owner
|
||||
## of the generic itself (the module or the enclosing proc).
|
||||
result = if s.kind in skProcKinds and sfFromGeneric in s.flags:
|
||||
result = if s.kind in skProcKinds and {sfGenSym, sfFromGeneric} * s.flags ==
|
||||
{sfFromGeneric}:
|
||||
s.owner.owner
|
||||
else:
|
||||
s.owner
|
||||
|
|
|
|||
|
|
@ -1210,7 +1210,7 @@ proc genSeqConstr(p: BProc, t: PNode, d: var TLoc) =
|
|||
|
||||
proc genArrToSeq(p: BProc, t: PNode, d: var TLoc) =
|
||||
var elem, a, arr: TLoc
|
||||
if t.kind == nkBracket:
|
||||
if t.sons[1].kind == nkBracket:
|
||||
t.sons[1].typ = t.typ
|
||||
genSeqConstr(p, t.sons[1], d)
|
||||
return
|
||||
|
|
@ -1383,7 +1383,9 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
|||
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||
var a, b: TLoc
|
||||
assert(d.k == locNone)
|
||||
initLocExpr(p, e.sons[1], a)
|
||||
var x = e.sons[1]
|
||||
if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
|
||||
initLocExpr(p, x, a)
|
||||
initLocExpr(p, e.sons[2], b)
|
||||
let t = skipTypes(e.sons[1].typ, {tyVar})
|
||||
let setLenPattern = if not p.module.compileToCpp:
|
||||
|
|
@ -2001,7 +2003,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
|||
if sfThread in sym.flags:
|
||||
accessThreadLocalVar(p, sym)
|
||||
if emulatedThreadVars():
|
||||
putIntoDest(p, d, sym.loc.t, "NimTV->" & sym.loc.r)
|
||||
putIntoDest(p, d, sym.loc.t, "NimTV_->" & sym.loc.r)
|
||||
else:
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
|||
field.r = "$1.Field$2" % [rdLoc(tup), rope(i)]
|
||||
else:
|
||||
if t.n.sons[i].kind != nkSym: internalError(n.info, "genVarTuple")
|
||||
field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(t.n.sons[i].sym, t)]
|
||||
field.r = "$1.$2" % [rdLoc(tup), mangleRecFieldName(p.module, t.n.sons[i].sym, t)]
|
||||
putLocIntoDest(p, v.loc, field)
|
||||
|
||||
proc genDeref(p: BProc, e: PNode, d: var TLoc; enforceDeref=false)
|
||||
|
|
@ -102,7 +102,7 @@ proc assignLabel(b: var TBlock): Rope {.inline.} =
|
|||
proc blockBody(b: var TBlock): Rope =
|
||||
result = b.sections[cpsLocals]
|
||||
if b.frameLen > 0:
|
||||
result.addf("FR.len+=$1;$n", [b.frameLen.rope])
|
||||
result.addf("FR_.len+=$1;$n", [b.frameLen.rope])
|
||||
result.add(b.sections[cpsInit])
|
||||
result.add(b.sections[cpsStmts])
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ proc endBlock(p: BProc) =
|
|||
~"}$n"
|
||||
let frameLen = p.blocks[topBlock].frameLen
|
||||
if frameLen > 0:
|
||||
blockEnd.addf("FR.len-=$1;$n", [frameLen.rope])
|
||||
blockEnd.addf("FR_.len-=$1;$n", [frameLen.rope])
|
||||
endBlock(p, blockEnd)
|
||||
|
||||
proc genSimpleBlock(p: BProc, stmts: PNode) {.inline.} =
|
||||
|
|
@ -156,7 +156,7 @@ proc genGotoState(p: BProc, n: PNode) =
|
|||
initLocExpr(p, n.sons[0], a)
|
||||
lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
|
||||
p.beforeRetNeeded = true
|
||||
lineF(p, cpsStmts, "case -1: goto BeforeRet;$n", [])
|
||||
lineF(p, cpsStmts, "case -1: goto BeforeRet_;$n", [])
|
||||
for i in 0 .. lastOrd(n.sons[0].typ):
|
||||
lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [rope(i)])
|
||||
lineF(p, cpsStmts, "}$n", [])
|
||||
|
|
@ -373,7 +373,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
|||
# consume it before we return.
|
||||
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
|
||||
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
|
||||
lineF(p, cpsStmts, "goto BeforeRet;$n", [])
|
||||
lineF(p, cpsStmts, "goto BeforeRet_;$n", [])
|
||||
|
||||
proc genGotoForCase(p: BProc; caseStmt: PNode) =
|
||||
for i in 1 .. <caseStmt.len:
|
||||
|
|
@ -411,11 +411,11 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
|||
localError(n.info, "no case statement found for computed goto"); return
|
||||
var id = p.labels+1
|
||||
inc p.labels, arraySize+1
|
||||
let tmp = "TMP$1" % [id.rope]
|
||||
let tmp = "TMP$1_" % [id.rope]
|
||||
var gotoArray = "static void* $#[$#] = {" % [tmp, arraySize.rope]
|
||||
for i in 1..arraySize-1:
|
||||
gotoArray.addf("&&TMP$#, ", [(id+i).rope])
|
||||
gotoArray.addf("&&TMP$#};$n", [(id+arraySize).rope])
|
||||
gotoArray.addf("&&TMP$#_, ", [(id+i).rope])
|
||||
gotoArray.addf("&&TMP$#_};$n", [(id+arraySize).rope])
|
||||
line(p, cpsLocals, gotoArray)
|
||||
|
||||
let topBlock = p.blocks.len-1
|
||||
|
|
@ -445,7 +445,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
|||
localError(it.info, "range notation not available for computed goto")
|
||||
return
|
||||
let val = getOrdValue(it.sons[j])
|
||||
lineF(p, cpsStmts, "TMP$#:$n", [intLiteral(val+id+1)])
|
||||
lineF(p, cpsStmts, "TMP$#_:$n", [intLiteral(val+id+1)])
|
||||
genStmts(p, it.lastSon)
|
||||
#for j in casePos+1 .. <n.len: genStmts(p, n.sons[j]) # tailB
|
||||
#for j in 0 .. casePos-1: genStmts(p, n.sons[j]) # tailA
|
||||
|
|
@ -600,7 +600,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
|
|||
for i in 1..until:
|
||||
# bug #4230: avoid false sharing between branches:
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
lineF(p, cpsStmts, "LA$1: ;$n", [rope(labId + i)])
|
||||
lineF(p, cpsStmts, "LA$1_: ;$n", [rope(labId + i)])
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
var length = sonsLen(t.sons[i])
|
||||
exprBlock(p, t.sons[i].sons[length - 1], d)
|
||||
|
|
@ -618,15 +618,15 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
|
|||
inc(p.labels)
|
||||
if t.sons[i].kind == nkOfBranch: # else statement
|
||||
genCaseGenericBranch(p, t.sons[i], a, rangeFormat, eqFormat,
|
||||
"LA" & rope(p.labels))
|
||||
"LA" & rope(p.labels) & "_")
|
||||
else:
|
||||
lineF(p, cpsStmts, "goto LA$1;$n", [rope(p.labels)])
|
||||
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
|
||||
if until < t.len-1:
|
||||
inc(p.labels)
|
||||
var gotoTarget = p.labels
|
||||
lineF(p, cpsStmts, "goto LA$1;$n", [rope(gotoTarget)])
|
||||
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(gotoTarget)])
|
||||
result = genCaseSecondPass(p, t, d, labId, until)
|
||||
lineF(p, cpsStmts, "LA$1: ;$n", [rope(gotoTarget)])
|
||||
lineF(p, cpsStmts, "LA$1_: ;$n", [rope(gotoTarget)])
|
||||
else:
|
||||
result = genCaseSecondPass(p, t, d, labId, until)
|
||||
|
||||
|
|
@ -664,7 +664,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
|||
for i in countup(1, sonsLen(t) - 1):
|
||||
inc(p.labels)
|
||||
if t.sons[i].kind == nkOfBranch:
|
||||
genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels),
|
||||
genCaseStringBranch(p, t.sons[i], a, "LA" & rope(p.labels) & "_",
|
||||
branches)
|
||||
else:
|
||||
# else statement: nothing to do yet
|
||||
|
|
@ -678,7 +678,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
|
|||
[intLiteral(j), branches[j]])
|
||||
lineF(p, cpsStmts, "}$n", []) # else statement:
|
||||
if t.sons[sonsLen(t)-1].kind != nkOfBranch:
|
||||
lineF(p, cpsStmts, "goto LA$1;$n", [rope(p.labels)])
|
||||
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(p.labels)])
|
||||
# third pass: generate statements
|
||||
var lend = genCaseSecondPass(p, t, d, labId, sonsLen(t)-1)
|
||||
fixLabel(p, lend)
|
||||
|
|
@ -802,7 +802,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
|||
let length = sonsLen(t)
|
||||
endBlock(p, ropecg(p.module, "} catch (NimException& $1) {$n", [exc]))
|
||||
if optStackTrace in p.options:
|
||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR);$n")
|
||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
||||
inc p.inExceptBlock
|
||||
var i = 1
|
||||
var catchAllPresent = false
|
||||
|
|
@ -910,7 +910,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
|||
startBlock(p, "else {$n")
|
||||
linefmt(p, cpsStmts, "#popSafePoint();$n")
|
||||
if optStackTrace in p.options:
|
||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR);$n")
|
||||
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
|
||||
inc p.inExceptBlock
|
||||
var i = 1
|
||||
while (i < length) and (t.sons[i].kind == nkExceptBranch):
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ proc accessThreadLocalVar(p: BProc, s: PSym) =
|
|||
if emulatedThreadVars() and not p.threadVarAccessed:
|
||||
p.threadVarAccessed = true
|
||||
incl p.module.flags, usesThreadVars
|
||||
addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV;$n", [])
|
||||
addf(p.procSec(cpsLocals), "\tNimThreadVars* NimTV_;$n", [])
|
||||
add(p.procSec(cpsInit),
|
||||
ropecg(p.module, "\tNimTV = (NimThreadVars*) #GetThreadLocalVars();$n"))
|
||||
ropecg(p.module, "\tNimTV_ = (NimThreadVars*) #GetThreadLocalVars();$n"))
|
||||
|
||||
var
|
||||
nimtv: Rope # Nim thread vars; the struct body
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ proc genTraverseProcForGlobal(m: BModule, s: PSym): Rope =
|
|||
|
||||
if sfThread in s.flags and emulatedThreadVars():
|
||||
accessThreadLocalVar(p, s)
|
||||
sLoc = "NimTV->" & sLoc
|
||||
sLoc = "NimTV_->" & sLoc
|
||||
|
||||
c.visitorFrmt = "#nimGCvisit((void*)$1, 0);$n"
|
||||
c.p = p
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@ proc isKeyword(w: PIdent): bool =
|
|||
ord(wInline): return true
|
||||
else: return false
|
||||
|
||||
proc mangleField(name: PIdent): string =
|
||||
proc mangleField(m: BModule; name: PIdent): string =
|
||||
result = mangle(name.s)
|
||||
if isKeyword(name):
|
||||
result[0] = result[0].toUpperAscii
|
||||
# Mangling makes everything lowercase,
|
||||
# but some identifiers are C keywords
|
||||
if isKeyword(name) or m.g.config.cppDefines.contains(result):
|
||||
result.add "_0"
|
||||
|
||||
when false:
|
||||
proc hashOwner(s: PSym): SigHash =
|
||||
|
|
@ -67,55 +65,50 @@ proc idOrSig(m: BModule; s: PSym): Rope =
|
|||
proc mangleName(m: BModule; s: PSym): Rope =
|
||||
result = s.loc.r
|
||||
if result == nil:
|
||||
let keepOrigName = s.kind in skLocalVars - {skForVar} and
|
||||
{sfFromGeneric, sfGlobal, sfShadowed, sfGenSym} * s.flags == {} and
|
||||
not isKeyword(s.name)
|
||||
# Even with all these inefficient checks, the bootstrap
|
||||
# time is actually improved. This is probably because so many
|
||||
# rope concatenations are now eliminated.
|
||||
#
|
||||
# sfFromGeneric is needed in order to avoid multiple
|
||||
# definitions of certain variables generated in transf with
|
||||
# names such as:
|
||||
# `r`, `res`
|
||||
# I need to study where these come from.
|
||||
#
|
||||
# about sfShadowed:
|
||||
# consider the following Nim code:
|
||||
# var x = 10
|
||||
# block:
|
||||
# var x = something(x)
|
||||
# The generated C code will be:
|
||||
# NI x;
|
||||
# x = 10;
|
||||
# {
|
||||
# NI x;
|
||||
# x = something(x); // Oops, x is already shadowed here
|
||||
# }
|
||||
# Right now, we work-around by not keeping the original name
|
||||
# of the shadowed variable, but we can do better - we can
|
||||
# create an alternative reference to it in the outer scope and
|
||||
# use that in the inner scope.
|
||||
#
|
||||
# about isCKeyword:
|
||||
# Nim variable names can be C keywords.
|
||||
# We need to avoid such names in the generated code.
|
||||
#
|
||||
# about sfGlobal:
|
||||
# This seems to be harder - a top level extern variable from
|
||||
# another modules can have the same name as a local one.
|
||||
# Maybe we should just implement sfShadowed for them too.
|
||||
#
|
||||
# about skForVar:
|
||||
# These are not properly scoped now - we need to add blocks
|
||||
# around for loops in transf
|
||||
result = s.name.s.mangle.rope
|
||||
if keepOrigName:
|
||||
result.add "0"
|
||||
else:
|
||||
add(result, m.idOrSig(s))
|
||||
add(result, m.idOrSig(s))
|
||||
s.loc.r = result
|
||||
writeMangledName(m.ndi, s)
|
||||
|
||||
proc mangleParamName(m: BModule; s: PSym): Rope =
|
||||
## we cannot use 'sigConflicts' here since we have a BModule, not a BProc.
|
||||
## Fortunately C's scoping rules are sane enough so that that doesn't
|
||||
## cause any trouble.
|
||||
result = s.loc.r
|
||||
if result == nil:
|
||||
var res = s.name.s.mangle
|
||||
if isKeyword(s.name) or m.g.config.cppDefines.contains(res):
|
||||
res.add "_0"
|
||||
result = res.rope
|
||||
s.loc.r = result
|
||||
writeMangledName(m.ndi, s)
|
||||
|
||||
proc mangleLocalName(p: BProc; s: PSym): Rope =
|
||||
assert s.kind in skLocalVars+{skTemp}
|
||||
assert sfGlobal notin s.flags
|
||||
result = s.loc.r
|
||||
if result == nil:
|
||||
var key = s.name.s.mangle
|
||||
shallow(key)
|
||||
let counter = p.sigConflicts.getOrDefault(key)
|
||||
result = key.rope
|
||||
if s.kind == skTemp:
|
||||
# speed up conflict search for temps (these are quite common):
|
||||
if counter != 0: result.add "_" & rope(counter+1)
|
||||
elif counter != 0 or isKeyword(s.name) or p.module.g.config.cppDefines.contains(key):
|
||||
result.add "_" & rope(counter+1)
|
||||
p.sigConflicts.inc(key)
|
||||
s.loc.r = result
|
||||
if s.kind != skTemp: writeMangledName(p.module.ndi, s)
|
||||
|
||||
proc scopeMangledParam(p: BProc; param: PSym) =
|
||||
## parameter generation only takes BModule, not a BProc, so we have to
|
||||
## remember these parameter names are already in scope to be able to
|
||||
## generate unique identifiers reliably (consider that ``var a = a`` is
|
||||
## even an idiom in Nim).
|
||||
var key = param.name.s.mangle
|
||||
shallow(key)
|
||||
p.sigConflicts.inc(key)
|
||||
|
||||
const
|
||||
irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation,
|
||||
|
|
@ -393,7 +386,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
|||
var param = t.n.sons[i].sym
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
if params != nil: add(params, ~", ")
|
||||
fillLoc(param.loc, locParam, param.typ, mangleName(m, param),
|
||||
fillLoc(param.loc, locParam, param.typ, mangleParamName(m, param),
|
||||
param.paramStorageLoc)
|
||||
if ccgIntroducedPtr(param):
|
||||
add(params, getTypeDescWeak(m, param.typ, check))
|
||||
|
|
@ -436,12 +429,12 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
|||
else: add(params, ")")
|
||||
params = "(" & params
|
||||
|
||||
proc mangleRecFieldName(field: PSym, rectype: PType): Rope =
|
||||
proc mangleRecFieldName(m: BModule; field: PSym, rectype: PType): Rope =
|
||||
if (rectype.sym != nil) and
|
||||
({sfImportc, sfExportc} * rectype.sym.flags != {}):
|
||||
result = field.loc.r
|
||||
else:
|
||||
result = rope(mangleField(field.name))
|
||||
result = rope(mangleField(m, field.name))
|
||||
if result == nil: internalError(field.info, "mangleRecFieldName")
|
||||
|
||||
proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||
|
|
@ -480,7 +473,7 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
|||
let field = n.sym
|
||||
if field.typ.kind == tyVoid: return
|
||||
#assert(field.ast == nil)
|
||||
let sname = mangleRecFieldName(field, rectype)
|
||||
let sname = mangleRecFieldName(m, field, rectype)
|
||||
let ae = if accessExpr != nil: "$1.$2" % [accessExpr, sname]
|
||||
else: sname
|
||||
fillLoc(field.loc, locField, field.typ, ae, OnUnknown)
|
||||
|
|
@ -1103,13 +1096,11 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
|
|||
discard cgsym(m, "TNimType")
|
||||
discard cgsym(m, "TNimNode")
|
||||
addf(m.s[cfsVars], "extern TNimType $1;$n", [result])
|
||||
#return "(&".rope & result & ")".rope
|
||||
#result = "NTI$1" % [rope($sig)]
|
||||
# also store in local type section:
|
||||
m.typeInfoMarker[sig] = result
|
||||
return "(&".rope & result & ")".rope
|
||||
|
||||
result = "NTI$1" % [rope($sig)]
|
||||
result = "NTI$1_" % [rope($sig)]
|
||||
m.typeInfoMarker[sig] = result
|
||||
|
||||
let owner = t.skipTypes(typedescPtrs).owner.getModule
|
||||
|
|
|
|||
|
|
@ -164,28 +164,50 @@ proc makeSingleLineCString*(s: string): string =
|
|||
result.add('\"')
|
||||
|
||||
proc mangle*(name: string): string =
|
||||
## Lowercases the given name and manges any non-alphanumeric characters
|
||||
## so they are represented as `HEX____`. If the name starts with a number,
|
||||
## `N` is prepended
|
||||
result = newStringOfCap(name.len)
|
||||
case name[0]
|
||||
of Letters:
|
||||
result.add(name[0])
|
||||
of Digits:
|
||||
result.add("N" & name[0])
|
||||
else:
|
||||
result = "HEX" & toHex(ord(name[0]), 2)
|
||||
for i in 1..(name.len-1):
|
||||
var start = 0
|
||||
if name[0] in Digits:
|
||||
result.add("X" & name[0])
|
||||
start = 1
|
||||
var requiresUnderscore = false
|
||||
template special(x) =
|
||||
result.add x
|
||||
requiresUnderscore = true
|
||||
for i in start..(name.len-1):
|
||||
let c = name[i]
|
||||
case c
|
||||
of 'A'..'Z':
|
||||
add(result, c.toLowerAscii)
|
||||
of '_':
|
||||
discard
|
||||
of 'a'..'z', '0'..'9':
|
||||
of 'a'..'z', '0'..'9', 'A'..'Z':
|
||||
add(result, c)
|
||||
of '_':
|
||||
# we generate names like 'foo_9' for scope disambiguations and so
|
||||
# disallow this here:
|
||||
if i < name.len-1 and name[i] in Digits:
|
||||
discard
|
||||
else:
|
||||
add(result, c)
|
||||
of '$': special "dollar"
|
||||
of '%': special "percent"
|
||||
of '&': special "amp"
|
||||
of '^': special "roof"
|
||||
of '!': special "emark"
|
||||
of '?': special "qmark"
|
||||
of '*': special "star"
|
||||
of '+': special "plus"
|
||||
of '-': special "minus"
|
||||
of '/': special "slash"
|
||||
of '=': special "eq"
|
||||
of '<': special "lt"
|
||||
of '>': special "gt"
|
||||
of '~': special "tilde"
|
||||
of ':': special "colon"
|
||||
of '.': special "dot"
|
||||
of '@': special "at"
|
||||
of '|': special "bar"
|
||||
else:
|
||||
add(result, "HEX" & toHex(ord(c), 2))
|
||||
add(result, "X" & toHex(ord(c), 2))
|
||||
requiresUnderscore = true
|
||||
if requiresUnderscore:
|
||||
result.add "_"
|
||||
|
||||
proc makeLLVMString*(s: string): Rope =
|
||||
const MaxLineLength = 64
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import
|
|||
nversion, nimsets, msgs, securehash, bitsets, idents, lists, types,
|
||||
ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||
condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
|
||||
lowerings, semparallel, tables
|
||||
lowerings, semparallel, tables, sets, ndi
|
||||
|
||||
import strutils except `%` # collides with ropes.`%`
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ proc genLineDir(p: BProc, t: PNode) =
|
|||
{optLineTrace, optStackTrace}) and
|
||||
(p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex >= 0:
|
||||
if freshLineInfo(p, tt.info):
|
||||
linefmt(p, cpsStmts, "nimln($1, $2);$n",
|
||||
linefmt(p, cpsStmts, "nimln_($1, $2);$n",
|
||||
line.rope, tt.info.quotedFilename)
|
||||
|
||||
proc postStmtActions(p: BProc) {.inline.} =
|
||||
|
|
@ -338,7 +338,7 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
|
|||
|
||||
proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
||||
inc(p.labels)
|
||||
result.r = "LOC" & rope(p.labels)
|
||||
result.r = "T" & rope(p.labels) & "_"
|
||||
linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r)
|
||||
result.k = locTemp
|
||||
result.t = t
|
||||
|
|
@ -347,12 +347,12 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) =
|
|||
constructLoc(p, result, not needsInit)
|
||||
|
||||
proc initGCFrame(p: BProc): Rope =
|
||||
if p.gcFrameId > 0: result = "struct {$1} GCFRAME;$n" % [p.gcFrameType]
|
||||
if p.gcFrameId > 0: result = "struct {$1} GCFRAME_;$n" % [p.gcFrameType]
|
||||
|
||||
proc deinitGCFrame(p: BProc): Rope =
|
||||
if p.gcFrameId > 0:
|
||||
result = ropecg(p.module,
|
||||
"if (((NU)&GCFRAME) < 4096) #nimGCFrame(&GCFRAME);$n")
|
||||
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n")
|
||||
|
||||
proc localDebugInfo(p: BProc, s: PSym) =
|
||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||
|
|
@ -361,7 +361,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
|||
var a = "&" & s.loc.r
|
||||
if s.kind == skParam and ccgIntroducedPtr(s): a = s.loc.r
|
||||
lineF(p, cpsInit,
|
||||
"FR.s[$1].address = (void*)$3; FR.s[$1].typ = $4; FR.s[$1].name = $2;$n",
|
||||
"FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n",
|
||||
[p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
|
||||
genTypeInfo(p.module, s.loc.t)])
|
||||
inc(p.maxFrameLen)
|
||||
|
|
@ -369,7 +369,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
|
|||
|
||||
proc localVarDecl(p: BProc; s: PSym): Rope =
|
||||
if s.loc.k == locNone:
|
||||
fillLoc(s.loc, locLocalVar, s.typ, mangleName(p.module, s), OnStack)
|
||||
fillLoc(s.loc, locLocalVar, s.typ, mangleLocalName(p, s), OnStack)
|
||||
if s.kind == skLet: incl(s.loc.flags, lfNoDeepCopy)
|
||||
result = getTypeDesc(p.module, s.typ)
|
||||
if s.constraint.isNil:
|
||||
|
|
@ -434,6 +434,7 @@ proc assignGlobalVar(p: BProc, s: PSym) =
|
|||
|
||||
proc assignParam(p: BProc, s: PSym) =
|
||||
assert(s.loc.r != nil)
|
||||
scopeMangledParam(p, s)
|
||||
localDebugInfo(p, s)
|
||||
|
||||
proc fillProcLoc(m: BModule; sym: PSym) =
|
||||
|
|
@ -442,7 +443,7 @@ proc fillProcLoc(m: BModule; sym: PSym) =
|
|||
|
||||
proc getLabel(p: BProc): TLabel =
|
||||
inc(p.labels)
|
||||
result = "LA" & rope(p.labels)
|
||||
result = "LA" & rope(p.labels) & "_"
|
||||
|
||||
proc fixLabel(p: BProc, labl: TLabel) =
|
||||
lineF(p, cpsStmts, "$1: ;$n", [labl])
|
||||
|
|
@ -520,7 +521,7 @@ proc mangleDynLibProc(sym: PSym): Rope =
|
|||
# NOTE: sym.loc.r is the external name!
|
||||
result = rope(sym.name.s)
|
||||
else:
|
||||
result = "Dl_$1" % [rope(sym.id)]
|
||||
result = "Dl_$1_" % [rope(sym.id)]
|
||||
|
||||
proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
var lib = sym.annex
|
||||
|
|
@ -608,11 +609,11 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope =
|
|||
discard cgsym(p.module, "nimFrame")
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "VarSlot")
|
||||
result = rfmt(nil, "\tnimfrs($1, $2, $3, $4)$N",
|
||||
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4)$N",
|
||||
procname, filename, p.maxFrameLen.rope,
|
||||
p.blocks[0].frameLen.rope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr($1, $2)$N", procname, filename)
|
||||
result = rfmt(nil, "\tnimfr_($1, $2)$N", procname, filename)
|
||||
|
||||
proc deinitFrame(p: BProc): Rope =
|
||||
result = rfmt(p.module, "\t#popFrame();$n")
|
||||
|
|
@ -707,7 +708,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
|||
if p.beforeRetNeeded: add(generatedProc, "{")
|
||||
add(generatedProc, p.s(cpsInit))
|
||||
add(generatedProc, p.s(cpsStmts))
|
||||
if p.beforeRetNeeded: add(generatedProc, ~"\t}BeforeRet: ;$n")
|
||||
if p.beforeRetNeeded: add(generatedProc, ~"\t}BeforeRet_: ;$n")
|
||||
add(generatedProc, deinitGCFrame(p))
|
||||
if optStackTrace in prc.options: add(generatedProc, deinitFrame(p))
|
||||
add(generatedProc, returnStmt)
|
||||
|
|
@ -846,7 +847,8 @@ proc genVarPrototype(m: BModule, sym: PSym) =
|
|||
genVarPrototypeAux(m, sym)
|
||||
|
||||
proc addIntTypes(result: var Rope) {.inline.} =
|
||||
addf(result, "#define NIM_INTBITS $1" & tnl, [
|
||||
addf(result, "#define NIM_NEW_MANGLING_RULES" & tnl &
|
||||
"#define NIM_INTBITS $1" & tnl, [
|
||||
platform.CPU[targetCPU].intSize.rope])
|
||||
|
||||
proc getCopyright(cfile: Cfile): Rope =
|
||||
|
|
@ -1058,7 +1060,7 @@ proc genInitCode(m: BModule) =
|
|||
var procname = makeCString(m.module.name.s)
|
||||
add(prc, initFrame(m.initProc, procname, m.module.info.quotedFilename))
|
||||
else:
|
||||
add(prc, ~"\tTFrame FR; FR.len = 0;$N")
|
||||
add(prc, ~"\tTFrame FR_; FR_.len = 0;$N")
|
||||
|
||||
add(prc, genSectionStart(cpsInit))
|
||||
add(prc, m.preInitProc.s(cpsInit))
|
||||
|
|
@ -1123,7 +1125,7 @@ proc initProcOptions(m: BModule): TOptions =
|
|||
|
||||
proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
|
||||
new(result)
|
||||
result.tmpBase = rope("T" & $hashOwner(module) & "_")
|
||||
result.tmpBase = rope("TM" & $hashOwner(module) & "_")
|
||||
initLinkedList(result.headerFiles)
|
||||
result.declaredThings = initIntSet()
|
||||
result.declaredProtos = initIntSet()
|
||||
|
|
@ -1150,6 +1152,9 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
|
|||
incl result.flags, preventStackTrace
|
||||
excl(result.preInitProc.options, optStackTrace)
|
||||
excl(result.postInitProc.options, optStackTrace)
|
||||
let ndiName = if optCDebug in gGlobalOptions: changeFileExt(completeCFilePath(filename), "ndi")
|
||||
else: ""
|
||||
open(result.ndi, ndiName)
|
||||
|
||||
proc nullify[T](arr: var T) =
|
||||
for i in low(arr)..high(arr):
|
||||
|
|
@ -1212,16 +1217,16 @@ proc newModule(g: BModuleList; module: PSym): BModule =
|
|||
if (sfDeadCodeElim in module.flags):
|
||||
internalError("added pending module twice: " & module.filename)
|
||||
|
||||
template injectG() {.dirty.} =
|
||||
template injectG(config) {.dirty.} =
|
||||
if graph.backend == nil:
|
||||
graph.backend = newModuleList()
|
||||
graph.backend = newModuleList(config)
|
||||
let g = BModuleList(graph.backend)
|
||||
|
||||
proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
|
||||
injectG()
|
||||
injectG(graph.config)
|
||||
result = newModule(g, module)
|
||||
if optGenIndex in gGlobalOptions and g.generatedHeader == nil:
|
||||
let f = if headerFile.len > 0: headerFile else: gProjectFull
|
||||
let f = if graph.config.headerFile.len > 0: graph.config.headerFile else: gProjectFull
|
||||
g.generatedHeader = rawNewModule(g, module,
|
||||
changeFileExt(completeCFilePath(f), hExt))
|
||||
incl g.generatedHeader.flags, isHeaderFile
|
||||
|
|
@ -1258,7 +1263,7 @@ proc getCFile(m: BModule): string =
|
|||
result = changeFileExt(completeCFilePath(m.cfilename.withPackageName), ext)
|
||||
|
||||
proc myOpenCached(graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext =
|
||||
injectG()
|
||||
injectG(graph.config)
|
||||
assert optSymbolFiles in gGlobalOptions
|
||||
var m = newModule(g, module)
|
||||
readMergeInfo(getCFile(m), m)
|
||||
|
|
@ -1341,6 +1346,7 @@ proc writeModule(m: BModule, pending: bool) =
|
|||
var cf = Cfile(cname: cfile, obj: completeCFilePath(toObjFile(cfile)), flags: {})
|
||||
if not existsFile(cf.obj): cf.flags = {CfileFlag.Cached}
|
||||
addFileToCompile(cf)
|
||||
close(m.ndi)
|
||||
|
||||
proc updateCachedModule(m: BModule) =
|
||||
let cfile = getCFile(m)
|
||||
|
|
@ -1373,11 +1379,12 @@ proc myClose(b: PPassContext, n: PNode): PNode =
|
|||
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
|
||||
genMainProc(m)
|
||||
|
||||
proc cgenWriteModules*(backend: RootRef) =
|
||||
proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
|
||||
let g = BModuleList(backend)
|
||||
# we need to process the transitive closure because recursive module
|
||||
# deps are allowed (and the system module is processed in the wrong
|
||||
# order anyway)
|
||||
g.config = config
|
||||
if g.generatedHeader != nil: finishModule(g.generatedHeader)
|
||||
while g.forwardedProcsCounter > 0:
|
||||
for m in cgenModules(g):
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
import
|
||||
ast, astalgo, ropes, passes, options, intsets, lists, platform, sighashes,
|
||||
tables
|
||||
tables, ndi
|
||||
|
||||
from msgs import TLineInfo
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ type
|
|||
BProc* = ref TCProc
|
||||
TBlock*{.final.} = object
|
||||
id*: int # the ID of the label; positive means that it
|
||||
label*: Rope # generated text for the label
|
||||
label*: Rope # generated text for the label
|
||||
# nil if label is not used
|
||||
sections*: TCProcSections # the code beloging
|
||||
isLoop*: bool # whether block is a loop
|
||||
|
|
@ -76,7 +76,7 @@ type
|
|||
# leaving such scopes by raise or by return must
|
||||
# execute any applicable finally blocks
|
||||
finallySafePoints*: seq[Rope] # For correctly cleaning up exceptions when
|
||||
# using return in finally statements
|
||||
# using return in finally statements
|
||||
labels*: Natural # for generating unique labels in the C proc
|
||||
blocks*: seq[TBlock] # nested blocks
|
||||
breakIdx*: int # the block that will be exited
|
||||
|
|
@ -92,6 +92,7 @@ type
|
|||
# (yes, C++ is weird like that)
|
||||
gcFrameId*: Natural # for the GC stack marking
|
||||
gcFrameType*: Rope # the struct {} we put the GC markers into
|
||||
sigConflicts*: CountTable[string]
|
||||
|
||||
TTypeSeq* = seq[PType]
|
||||
TypeCache* = Table[SigHash, Rope]
|
||||
|
|
@ -115,6 +116,7 @@ type
|
|||
breakPointId*: int
|
||||
breakpoints*: Rope # later the breakpoints are inserted into the main proc
|
||||
typeInfoMarker*: TypeCache
|
||||
config*: ConfigRef
|
||||
|
||||
TCGen = object of TPassContext # represents a C source file
|
||||
s*: TCFileSections # sections of the C file
|
||||
|
|
@ -144,6 +146,7 @@ type
|
|||
injectStmt*: Rope
|
||||
sigConflicts*: CountTable[SigHash]
|
||||
g*: BModuleList
|
||||
ndi*: NdiFile
|
||||
|
||||
proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
|
||||
# section in the current block
|
||||
|
|
@ -162,9 +165,10 @@ proc newProc*(prc: PSym, module: BModule): BProc =
|
|||
newSeq(result.blocks, 1)
|
||||
result.nestedTryStmts = @[]
|
||||
result.finallySafePoints = @[]
|
||||
result.sigConflicts = initCountTable[string]()
|
||||
|
||||
proc newModuleList*(): BModuleList =
|
||||
BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope]())
|
||||
proc newModuleList*(config: ConfigRef): BModuleList =
|
||||
BModuleList(modules: @[], typeInfoMarker: initTable[SigHash, Rope](), config: config)
|
||||
|
||||
iterator cgenModules*(g: BModuleList): BModule =
|
||||
for i in 0..high(g.modules):
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ type
|
|||
passPP # preprocessor called processCommand()
|
||||
|
||||
proc processCommand*(switch: string, pass: TCmdLinePass)
|
||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo)
|
||||
proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
config: ConfigRef = nil)
|
||||
|
||||
# implementation
|
||||
|
||||
|
|
@ -312,7 +313,8 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
|||
expectArg(switch, arg, pass, info)
|
||||
options.inclDynlibOverride(arg)
|
||||
|
||||
proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
config: ConfigRef = nil) =
|
||||
var
|
||||
theOS: TSystemOS
|
||||
cpu: TSystemCPU
|
||||
|
|
@ -509,10 +511,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
|||
else: localError(info, errGuiConsoleOrLibExpectedButXFound, arg)
|
||||
of "passc", "t":
|
||||
expectArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: extccomp.addCompileOption(arg)
|
||||
if pass in {passCmd2, passPP}: extccomp.addCompileOptionCmd(arg)
|
||||
of "passl", "l":
|
||||
expectArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: extccomp.addLinkOption(arg)
|
||||
if pass in {passCmd2, passPP}: extccomp.addLinkOptionCmd(arg)
|
||||
of "cincludes":
|
||||
expectArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: cIncludes.add arg.processPath(info)
|
||||
|
|
@ -523,7 +525,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
|||
expectArg(switch, arg, pass, info)
|
||||
if pass in {passCmd2, passPP}: cLinkedLibs.add arg.processPath(info)
|
||||
of "header":
|
||||
headerFile = arg
|
||||
if config != nil: config.headerFile = arg
|
||||
incl(gGlobalOptions, optGenIndex)
|
||||
of "index":
|
||||
processOnOffSwitchG({optGenIndex}, arg, pass, info)
|
||||
|
|
@ -646,6 +648,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
|||
expectNoArg(switch, arg, pass, info)
|
||||
incl(gGlobalOptions, optNoCppExceptions)
|
||||
defineSymbol("noCppExceptions")
|
||||
of "cppdefine":
|
||||
expectArg(switch, arg, pass, info)
|
||||
if config != nil:
|
||||
config.cppDefine(arg)
|
||||
else:
|
||||
if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
|
||||
else: invalidCmdLineOption(pass, switch, info)
|
||||
|
|
|
|||
|
|
@ -101,3 +101,4 @@ proc initDefines*() =
|
|||
defineSymbol("nimImmediateDeprecated")
|
||||
defineSymbol("nimNewShiftOps")
|
||||
defineSymbol("nimDistros")
|
||||
defineSymbol("nimHasCppDefine")
|
||||
|
|
|
|||
|
|
@ -209,26 +209,26 @@ proc getPlainDocstring(n: PNode): string =
|
|||
result = getPlainDocstring(n.sons[i])
|
||||
if result.len > 0: return
|
||||
|
||||
when false:
|
||||
proc findDocComment(n: PNode): PNode =
|
||||
if n == nil: return nil
|
||||
if not isNil(n.comment) and startsWith(n.comment, "##"): return n
|
||||
for i in countup(0, safeLen(n)-1):
|
||||
result = findDocComment(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
proc findDocComment(n: PNode): PNode =
|
||||
if n == nil: return nil
|
||||
if not isNil(n.comment) and startsWith(n.comment, "##"): return n
|
||||
for i in countup(0, safeLen(n)-1):
|
||||
result = findDocComment(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
proc extractDocComment*(s: PSym, d: PDoc = nil): string =
|
||||
let n = findDocComment(s.ast)
|
||||
result = ""
|
||||
if not n.isNil:
|
||||
if not d.isNil:
|
||||
var dummyHasToc: bool
|
||||
renderRstToOut(d[], parseRst(n.comment, toFilename(n.info),
|
||||
toLinenumber(n.info), toColumn(n.info),
|
||||
dummyHasToc, d.options + {roSkipPounds}),
|
||||
result)
|
||||
else:
|
||||
result = n.comment.substr(2).replace("\n##", "\n").strip
|
||||
proc extractDocComment*(s: PSym, d: PDoc = nil): string =
|
||||
let n = findDocComment(s.ast)
|
||||
result = ""
|
||||
if not n.isNil:
|
||||
if not d.isNil:
|
||||
var dummyHasToc: bool
|
||||
renderRstToOut(d[], parseRst(n.comment, toFilename(n.info),
|
||||
toLinenumber(n.info), toColumn(n.info),
|
||||
dummyHasToc, d.options + {roSkipPounds}),
|
||||
result)
|
||||
else:
|
||||
result = n.comment.substr(2).replace("\n##", "\n").strip
|
||||
|
||||
proc isVisible(n: PNode): bool =
|
||||
result = false
|
||||
|
|
|
|||
|
|
@ -392,6 +392,8 @@ type
|
|||
var
|
||||
externalToLink: TLinkedList # files to link in addition to the file
|
||||
# we compiled
|
||||
linkOptionsCmd: string = ""
|
||||
compileOptionsCmd: seq[string] = @[]
|
||||
linkOptions: string = ""
|
||||
compileOptions: string = ""
|
||||
ccompilerpath: string = ""
|
||||
|
|
@ -450,6 +452,12 @@ proc addCompileOption*(option: string) =
|
|||
if strutils.find(compileOptions, option, 0) < 0:
|
||||
addOpt(compileOptions, option)
|
||||
|
||||
proc addLinkOptionCmd*(option: string) =
|
||||
addOpt(linkOptionsCmd, option)
|
||||
|
||||
proc addCompileOptionCmd*(option: string) =
|
||||
compileOptionsCmd.add(option)
|
||||
|
||||
proc initVars*() =
|
||||
# we need to define the symbol here, because ``CC`` may have never been set!
|
||||
for i in countup(low(CC), high(CC)): undefSymbol(CC[i].name)
|
||||
|
|
@ -524,6 +532,10 @@ proc add(s: var string, many: openArray[string]) =
|
|||
|
||||
proc cFileSpecificOptions(cfilename: string): string =
|
||||
result = compileOptions
|
||||
for option in compileOptionsCmd:
|
||||
if strutils.find(result, option, 0) < 0:
|
||||
addOpt(result, option)
|
||||
|
||||
var trunk = splitFile(cfilename).name
|
||||
if optCDebug in gGlobalOptions:
|
||||
var key = trunk & ".debug"
|
||||
|
|
@ -544,7 +556,7 @@ proc getCompileOptions: string =
|
|||
result = cFileSpecificOptions("__dummy__")
|
||||
|
||||
proc getLinkOptions: string =
|
||||
result = linkOptions
|
||||
result = linkOptions & " " & linkOptionsCmd & " "
|
||||
for linkedLib in items(cLinkedLibs):
|
||||
result.add(CC[cCompiler].linkLibCmd % linkedLib.quoteShell)
|
||||
for libDir in items(cLibs):
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ Start: "doc/html/overview.html"
|
|||
|
||||
|
||||
[Other]
|
||||
Files: "readme.txt;install.txt;contributors.txt;copying.txt"
|
||||
Files: "readme.txt;copying.txt"
|
||||
Files: "makefile"
|
||||
Files: "koch.nim"
|
||||
Files: "install_nimble.nims"
|
||||
|
|
@ -94,15 +94,17 @@ Files: "bin/vccexe.exe"
|
|||
|
||||
Files: "koch.exe"
|
||||
Files: "finish.exe"
|
||||
Files: "downloader.exe"
|
||||
|
||||
; Files: "dist/mingw"
|
||||
Files: r"tools\start.bat"
|
||||
BinPath: r"bin;dist\mingw\bin;dist"
|
||||
|
||||
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
|
||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
||||
Download: r"Support DLLs|bin|nim_dlls.zip|479|http://nim-lang.org/download/dlls.zip"
|
||||
Download: r"Aporia Text Editor|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.4.0.zip|aporia-0.4.0\bin\aporia.exe"
|
||||
Download: r"Documentation|doc|docs.zip|13824|https://nim-lang.org/download/docs-${version}.zip|overview.html"
|
||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|https://nim-lang.org/download/${mingw}.zip"
|
||||
Download: r"Support DLLs|bin|nim_dlls.zip|479|https://nim-lang.org/download/dlls.zip"
|
||||
Download: r"Aporia Text Editor|dist|aporia.zip|97997|https://nim-lang.org/download/aporia-0.4.0.zip|aporia-0.4.0\bin\aporia.exe"
|
||||
; for now only NSIS supports optional downloads
|
||||
|
||||
[WinBin]
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) =
|
|||
#registerPass(cleanupPass())
|
||||
|
||||
compileProject(graph, cache)
|
||||
cgenWriteModules(graph.backend)
|
||||
cgenWriteModules(graph.backend, graph.config)
|
||||
if gCmd != cmdRun:
|
||||
let proj = changeFileExt(gProjectFull, "")
|
||||
extccomp.callCCompiler(proj)
|
||||
|
|
@ -294,4 +294,4 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
|
|||
|
||||
resetAttributes()
|
||||
|
||||
proc mainCommand*() = mainCommand(newModuleGraph(), newIdentCache())
|
||||
proc mainCommand*() = mainCommand(newModuleGraph(newConfigRef()), newIdentCache())
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
## - Its dependent module stays the same.
|
||||
##
|
||||
|
||||
import ast, intsets, tables
|
||||
import ast, intsets, tables, options
|
||||
|
||||
type
|
||||
ModuleGraph* = ref object
|
||||
|
|
@ -39,16 +39,21 @@ type
|
|||
importStack*: seq[int32] # The current import stack. Used for detecting recursive
|
||||
# module dependencies.
|
||||
backend*: RootRef # minor hack so that a backend can extend this easily
|
||||
config*: ConfigRef
|
||||
|
||||
{.this: g.}
|
||||
|
||||
proc newModuleGraph*(): ModuleGraph =
|
||||
proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph =
|
||||
result = ModuleGraph()
|
||||
initStrTable(result.packageSyms)
|
||||
result.deps = initIntSet()
|
||||
result.modules = @[]
|
||||
result.importStack = @[]
|
||||
result.inclToMod = initTable[int32, int32]()
|
||||
if config.isNil:
|
||||
result.config = newConfigRef()
|
||||
else:
|
||||
result.config = config
|
||||
|
||||
proc resetAllModules*(g: ModuleGraph) =
|
||||
initStrTable(packageSyms)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import
|
|||
|
||||
type
|
||||
TMsgKind* = enum
|
||||
errUnknown, errIllFormedAstX, errInternal, errCannotOpenFile, errGenerated,
|
||||
errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, errGenerated,
|
||||
errXCompilerDoesNotSupportCpp, errStringLiteralExpected,
|
||||
errIntLiteralExpected, errInvalidCharacterConstant,
|
||||
errClosingTripleQuoteExpected, errClosingQuoteExpected,
|
||||
|
|
@ -135,8 +135,8 @@ type
|
|||
const
|
||||
MsgKindToStr*: array[TMsgKind, string] = [
|
||||
errUnknown: "unknown error",
|
||||
errIllFormedAstX: "illformed AST: $1",
|
||||
errInternal: "internal error: $1",
|
||||
errIllFormedAstX: "illformed AST: $1",
|
||||
errCannotOpenFile: "cannot open \'$1\'",
|
||||
errGenerated: "$1",
|
||||
errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++",
|
||||
|
|
|
|||
40
compiler/ndi.nim
Normal file
40
compiler/ndi.nim
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#
|
||||
#
|
||||
# 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 generation of ``.ndi`` files for better debugging
|
||||
## support of Nim code. "ndi" stands for "Nim debug info".
|
||||
|
||||
import ast, msgs, ropes
|
||||
|
||||
type
|
||||
NdiFile* = object
|
||||
enabled: bool
|
||||
f: File
|
||||
buf: string
|
||||
|
||||
proc doWrite(f: var NdiFile; s: PSym) =
|
||||
f.buf.setLen 0
|
||||
f.buf.add s.info.line.int
|
||||
f.buf.add "\t"
|
||||
f.buf.add s.info.col.int
|
||||
f.f.write(s.name.s, "\t")
|
||||
f.f.writeRope(s.loc.r)
|
||||
f.f.writeLine("\t", s.info.toFullPath, "\t", f.buf)
|
||||
|
||||
template writeMangledName*(f: NdiFile; s: PSym) =
|
||||
if f.enabled: doWrite(f, s)
|
||||
|
||||
proc open*(f: var NdiFile; filename: string) =
|
||||
f.enabled = filename.len > 0
|
||||
if f.enabled:
|
||||
f.f = open(filename, fmWrite, 8000)
|
||||
f.buf = newStringOfCap(20)
|
||||
|
||||
proc close*(f: var NdiFile) =
|
||||
if f.enabled: close(f.f)
|
||||
|
|
@ -37,7 +37,7 @@ proc prependCurDir(f: string): string =
|
|||
else:
|
||||
result = f
|
||||
|
||||
proc handleCmdLine(cache: IdentCache) =
|
||||
proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
|
||||
if paramCount() == 0:
|
||||
writeCommandLineUsage()
|
||||
else:
|
||||
|
|
@ -59,22 +59,22 @@ proc handleCmdLine(cache: IdentCache) =
|
|||
gProjectName = p.name
|
||||
else:
|
||||
gProjectPath = canonicalizePath getCurrentDir()
|
||||
loadConfigs(DefaultConfig) # load all config files
|
||||
loadConfigs(DefaultConfig, config) # load all config files
|
||||
let scriptFile = gProjectFull.changeFileExt("nims")
|
||||
if fileExists(scriptFile):
|
||||
runNimScript(cache, scriptFile, freshDefines=false)
|
||||
runNimScript(cache, scriptFile, freshDefines=false, config)
|
||||
# 'nim foo.nims' means to just run the NimScript file and do nothing more:
|
||||
if scriptFile == gProjectFull: return
|
||||
elif fileExists(gProjectPath / "config.nims"):
|
||||
# directory wide NimScript file
|
||||
runNimScript(cache, gProjectPath / "config.nims", freshDefines=false)
|
||||
runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
|
||||
# now process command line arguments again, because some options in the
|
||||
# command line can overwite the config file's settings
|
||||
extccomp.initVars()
|
||||
processCmdLine(passCmd2, "")
|
||||
if options.command == "":
|
||||
rawMessage(errNoCommand, command)
|
||||
mainCommand(newModuleGraph(), cache)
|
||||
mainCommand(newModuleGraph(config), cache)
|
||||
if optHints in gOptions and hintGCStats in gNotes: echo(GC_getStatistics())
|
||||
#echo(GC_getStatistics())
|
||||
if msgs.gErrorCounter == 0:
|
||||
|
|
@ -118,5 +118,5 @@ when compileOption("gc", "v2") or compileOption("gc", "refc"):
|
|||
condsyms.initDefines()
|
||||
|
||||
when not defined(selftest):
|
||||
handleCmdLine(newIdentCache())
|
||||
handleCmdLine(newIdentCache(), newConfigRef())
|
||||
msgQuit(int8(msgs.gErrorCounter > 0))
|
||||
|
|
|
|||
|
|
@ -21,37 +21,37 @@ proc ppGetTok(L: var TLexer, tok: var TToken) =
|
|||
rawGetTok(L, tok)
|
||||
while tok.tokType in {tkComment}: rawGetTok(L, tok)
|
||||
|
||||
proc parseExpr(L: var TLexer, tok: var TToken): bool
|
||||
proc parseAtom(L: var TLexer, tok: var TToken): bool =
|
||||
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool
|
||||
proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||
if tok.tokType == tkParLe:
|
||||
ppGetTok(L, tok)
|
||||
result = parseExpr(L, tok)
|
||||
result = parseExpr(L, tok, config)
|
||||
if tok.tokType == tkParRi: ppGetTok(L, tok)
|
||||
else: lexMessage(L, errTokenExpected, "\')\'")
|
||||
elif tok.ident.id == ord(wNot):
|
||||
ppGetTok(L, tok)
|
||||
result = not parseAtom(L, tok)
|
||||
result = not parseAtom(L, tok, config)
|
||||
else:
|
||||
result = isDefined(tok.ident)
|
||||
ppGetTok(L, tok)
|
||||
|
||||
proc parseAndExpr(L: var TLexer, tok: var TToken): bool =
|
||||
result = parseAtom(L, tok)
|
||||
proc parseAndExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||
result = parseAtom(L, tok, config)
|
||||
while tok.ident.id == ord(wAnd):
|
||||
ppGetTok(L, tok) # skip "and"
|
||||
var b = parseAtom(L, tok)
|
||||
var b = parseAtom(L, tok, config)
|
||||
result = result and b
|
||||
|
||||
proc parseExpr(L: var TLexer, tok: var TToken): bool =
|
||||
result = parseAndExpr(L, tok)
|
||||
proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||
result = parseAndExpr(L, tok, config)
|
||||
while tok.ident.id == ord(wOr):
|
||||
ppGetTok(L, tok) # skip "or"
|
||||
var b = parseAndExpr(L, tok)
|
||||
var b = parseAndExpr(L, tok, config)
|
||||
result = result or b
|
||||
|
||||
proc evalppIf(L: var TLexer, tok: var TToken): bool =
|
||||
proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool =
|
||||
ppGetTok(L, tok) # skip 'if' or 'elif'
|
||||
result = parseExpr(L, tok)
|
||||
result = parseExpr(L, tok, config)
|
||||
if tok.tokType == tkColon: ppGetTok(L, tok)
|
||||
else: lexMessage(L, errTokenExpected, "\':\'")
|
||||
|
||||
|
|
@ -66,20 +66,20 @@ type
|
|||
TJumpDest = enum
|
||||
jdEndif, jdElseEndif
|
||||
|
||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest)
|
||||
proc doElse(L: var TLexer, tok: var TToken) =
|
||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef)
|
||||
proc doElse(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
|
||||
ppGetTok(L, tok)
|
||||
if tok.tokType == tkColon: ppGetTok(L, tok)
|
||||
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif)
|
||||
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif, config)
|
||||
|
||||
proc doElif(L: var TLexer, tok: var TToken) =
|
||||
proc doElif(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
|
||||
var res = evalppIf(L, tok)
|
||||
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif)
|
||||
var res = evalppIf(L, tok, config)
|
||||
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif, config)
|
||||
else: condStack[high(condStack)] = true
|
||||
|
||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
|
||||
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef) =
|
||||
var nestedIfs = 0
|
||||
while true:
|
||||
if tok.ident != nil and tok.ident.s == "@":
|
||||
|
|
@ -89,11 +89,11 @@ proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
|
|||
inc(nestedIfs)
|
||||
of wElse:
|
||||
if dest == jdElseEndif and nestedIfs == 0:
|
||||
doElse(L, tok)
|
||||
doElse(L, tok, config)
|
||||
break
|
||||
of wElif:
|
||||
if dest == jdElseEndif and nestedIfs == 0:
|
||||
doElif(L, tok)
|
||||
doElif(L, tok, config)
|
||||
break
|
||||
of wEnd:
|
||||
if nestedIfs == 0:
|
||||
|
|
@ -108,16 +108,16 @@ proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
|
|||
else:
|
||||
ppGetTok(L, tok)
|
||||
|
||||
proc parseDirective(L: var TLexer, tok: var TToken) =
|
||||
proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
ppGetTok(L, tok) # skip @
|
||||
case whichKeyword(tok.ident)
|
||||
of wIf:
|
||||
setLen(condStack, len(condStack) + 1)
|
||||
let res = evalppIf(L, tok)
|
||||
let res = evalppIf(L, tok, config)
|
||||
condStack[high(condStack)] = res
|
||||
if not res: jumpToDirective(L, tok, jdElseEndif)
|
||||
of wElif: doElif(L, tok)
|
||||
of wElse: doElse(L, tok)
|
||||
if not res: jumpToDirective(L, tok, jdElseEndif, config)
|
||||
of wElif: doElif(L, tok, config)
|
||||
of wElse: doElse(L, tok, config)
|
||||
of wEnd: doEnd(L, tok)
|
||||
of wWrite:
|
||||
ppGetTok(L, tok)
|
||||
|
|
@ -146,58 +146,58 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
|
|||
ppGetTok(L, tok)
|
||||
else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok))
|
||||
|
||||
proc confTok(L: var TLexer, tok: var TToken) =
|
||||
proc confTok(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
ppGetTok(L, tok)
|
||||
while tok.ident != nil and tok.ident.s == "@":
|
||||
parseDirective(L, tok) # else: give the token to the parser
|
||||
parseDirective(L, tok, config) # else: give the token to the parser
|
||||
|
||||
proc checkSymbol(L: TLexer, tok: TToken) =
|
||||
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
|
||||
lexMessage(L, errIdentifierExpected, tokToStr(tok))
|
||||
|
||||
proc parseAssignment(L: var TLexer, tok: var TToken) =
|
||||
proc parseAssignment(L: var TLexer, tok: var TToken; config: ConfigRef) =
|
||||
if tok.ident.s == "-" or tok.ident.s == "--":
|
||||
confTok(L, tok) # skip unnecessary prefix
|
||||
confTok(L, tok, config) # skip unnecessary prefix
|
||||
var info = getLineInfo(L, tok) # save for later in case of an error
|
||||
checkSymbol(L, tok)
|
||||
var s = tokToStr(tok)
|
||||
confTok(L, tok) # skip symbol
|
||||
confTok(L, tok, config) # skip symbol
|
||||
var val = ""
|
||||
while tok.tokType == tkDot:
|
||||
add(s, '.')
|
||||
confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
checkSymbol(L, tok)
|
||||
add(s, tokToStr(tok))
|
||||
confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
if tok.tokType == tkBracketLe:
|
||||
# BUGFIX: val, not s!
|
||||
# BUGFIX: do not copy '['!
|
||||
confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
checkSymbol(L, tok)
|
||||
add(val, tokToStr(tok))
|
||||
confTok(L, tok)
|
||||
if tok.tokType == tkBracketRi: confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
if tok.tokType == tkBracketRi: confTok(L, tok, config)
|
||||
else: lexMessage(L, errTokenExpected, "']'")
|
||||
add(val, ']')
|
||||
let percent = tok.ident != nil and tok.ident.s == "%="
|
||||
if tok.tokType in {tkColon, tkEquals} or percent:
|
||||
if len(val) > 0: add(val, ':')
|
||||
confTok(L, tok) # skip ':' or '=' or '%'
|
||||
confTok(L, tok, config) # skip ':' or '=' or '%'
|
||||
checkSymbol(L, tok)
|
||||
add(val, tokToStr(tok))
|
||||
confTok(L, tok) # skip symbol
|
||||
confTok(L, tok, config) # skip symbol
|
||||
while tok.ident != nil and tok.ident.s == "&":
|
||||
confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
checkSymbol(L, tok)
|
||||
add(val, tokToStr(tok))
|
||||
confTok(L, tok)
|
||||
confTok(L, tok, config)
|
||||
if percent:
|
||||
processSwitch(s, strtabs.`%`(val, options.gConfigVars,
|
||||
{useEnvironment, useEmpty}), passPP, info)
|
||||
{useEnvironment, useEmpty}), passPP, info, config)
|
||||
else:
|
||||
processSwitch(s, val, passPP, info)
|
||||
processSwitch(s, val, passPP, info, config)
|
||||
|
||||
proc readConfigFile(filename: string; cache: IdentCache) =
|
||||
proc readConfigFile(filename: string; cache: IdentCache; config: ConfigRef) =
|
||||
var
|
||||
L: TLexer
|
||||
tok: TToken
|
||||
|
|
@ -207,8 +207,8 @@ proc readConfigFile(filename: string; cache: IdentCache) =
|
|||
initToken(tok)
|
||||
openLexer(L, filename, stream, cache)
|
||||
tok.tokType = tkEof # to avoid a pointless warning
|
||||
confTok(L, tok) # read in the first token
|
||||
while tok.tokType != tkEof: parseAssignment(L, tok)
|
||||
confTok(L, tok, config) # read in the first token
|
||||
while tok.tokType != tkEof: parseAssignment(L, tok, config)
|
||||
if len(condStack) > 0: lexMessage(L, errTokenExpected, "@end")
|
||||
closeLexer(L)
|
||||
rawMessage(hintConf, filename)
|
||||
|
|
@ -225,22 +225,22 @@ proc getSystemConfigPath(filename: string): string =
|
|||
if not existsFile(result): result = joinPath([p, "etc", filename])
|
||||
if not existsFile(result): result = "/etc/" & filename
|
||||
|
||||
proc loadConfigs*(cfg: string; cache: IdentCache) =
|
||||
proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) =
|
||||
setDefaultLibpath()
|
||||
|
||||
if optSkipConfigFile notin gGlobalOptions:
|
||||
readConfigFile(getSystemConfigPath(cfg), cache)
|
||||
readConfigFile(getSystemConfigPath(cfg), cache, config)
|
||||
|
||||
if optSkipUserConfigFile notin gGlobalOptions:
|
||||
readConfigFile(getUserConfigPath(cfg), cache)
|
||||
readConfigFile(getUserConfigPath(cfg), cache, config)
|
||||
|
||||
var pd = if gProjectPath.len > 0: gProjectPath else: getCurrentDir()
|
||||
if optSkipParentConfigFiles notin gGlobalOptions:
|
||||
for dir in parentDirs(pd, fromRoot=true, inclusive=false):
|
||||
readConfigFile(dir / cfg, cache)
|
||||
readConfigFile(dir / cfg, cache, config)
|
||||
|
||||
if optSkipProjConfigFile notin gGlobalOptions:
|
||||
readConfigFile(pd / cfg, cache)
|
||||
readConfigFile(pd / cfg, cache, config)
|
||||
|
||||
if gProjectName.len != 0:
|
||||
# new project wide config file:
|
||||
|
|
@ -251,8 +251,8 @@ proc loadConfigs*(cfg: string; cache: IdentCache) =
|
|||
projectConfig = changeFileExt(gProjectFull, "nimrod.cfg")
|
||||
if fileExists(projectConfig):
|
||||
rawMessage(warnDeprecated, projectConfig)
|
||||
readConfigFile(projectConfig, cache)
|
||||
readConfigFile(projectConfig, cache, config)
|
||||
|
||||
proc loadConfigs*(cfg: string) =
|
||||
proc loadConfigs*(cfg: string; config: ConfigRef = nil) =
|
||||
# for backwards compatibility only.
|
||||
loadConfigs(cfg, newIdentCache())
|
||||
loadConfigs(cfg, newIdentCache(), config)
|
||||
|
|
|
|||
|
|
@ -102,6 +102,17 @@ type
|
|||
ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
|
||||
ideHighlight, ideOutline
|
||||
|
||||
ConfigRef* = ref object ## eventually all global configuration should be moved here
|
||||
cppDefines*: HashSet[string]
|
||||
headerFile*: string
|
||||
|
||||
proc newConfigRef*(): ConfigRef =
|
||||
result = ConfigRef(cppDefines: initSet[string](),
|
||||
headerFile: "")
|
||||
|
||||
proc cppDefine*(c: ConfigRef; define: string) =
|
||||
c.cppDefines.incl define
|
||||
|
||||
var
|
||||
gIdeCmd*: IdeCmd
|
||||
|
||||
|
|
@ -122,7 +133,7 @@ var
|
|||
outFile*: string = ""
|
||||
docSeeSrcUrl*: string = "" # if empty, no seeSrc will be generated. \
|
||||
# The string uses the formatting variables `path` and `line`.
|
||||
headerFile*: string = ""
|
||||
#headerFile*: string = ""
|
||||
gVerbosity* = 1 # how verbose the compiler is
|
||||
gNumberOfProcessors*: int # number of processors
|
||||
gWholeProject*: bool # for 'doc2': output any dependency
|
||||
|
|
|
|||
|
|
@ -665,9 +665,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
|||
of wExportc:
|
||||
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
of wImportc:
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
cppDefine(c.graph.config, name)
|
||||
makeExternImport(sym, name, it.info)
|
||||
of wImportCompilerProc:
|
||||
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||
let name = getOptionalStr(c, it, "$1")
|
||||
cppDefine(c.graph.config, name)
|
||||
processImportCompilerProc(sym, name, it.info)
|
||||
of wExtern: setExternName(sym, expectStrLit(c, it), it.info)
|
||||
of wImmediate:
|
||||
if sym.kind in {skTemplate, skMacro}:
|
||||
|
|
@ -758,6 +763,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
|||
processDynLib(c, it, sym)
|
||||
of wCompilerproc:
|
||||
noVal(it) # compilerproc may not get a string!
|
||||
cppDefine(c.graph.config, sym.name.s)
|
||||
if sfFromGeneric notin sym.flags: markCompilerProc(sym)
|
||||
of wProcVar:
|
||||
noVal(it)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
|
|||
if kind in filter: result.add path
|
||||
setResult(a, result)
|
||||
|
||||
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string): PEvalContext =
|
||||
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
|
||||
config: ConfigRef = nil): PEvalContext =
|
||||
# For Nimble we need to export 'setupVM'.
|
||||
result = newCtx(module, cache)
|
||||
result.mode = emRepl
|
||||
|
|
@ -109,10 +110,13 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string): PEvalContext
|
|||
let arg = a.getString 1
|
||||
if arg.len > 0:
|
||||
gProjectName = arg
|
||||
let path =
|
||||
if gProjectName.isAbsolute: gProjectName
|
||||
else: gProjectPath / gProjectName
|
||||
try:
|
||||
gProjectFull = canonicalizePath(gProjectPath / gProjectName)
|
||||
gProjectFull = canonicalizePath(path)
|
||||
except OSError:
|
||||
gProjectFull = gProjectName
|
||||
gProjectFull = path
|
||||
cbconf getCommand:
|
||||
setResult(a, options.command)
|
||||
cbconf switch:
|
||||
|
|
@ -133,12 +137,15 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string): PEvalContext
|
|||
gModuleOverrides[key] = val
|
||||
cbconf selfExe:
|
||||
setResult(a, os.getAppFilename())
|
||||
cbconf cppDefine:
|
||||
if config != nil:
|
||||
options.cppDefine(config, a.getString(0))
|
||||
|
||||
proc runNimScript*(cache: IdentCache; scriptName: string;
|
||||
freshDefines=true) =
|
||||
freshDefines=true; config: ConfigRef=nil) =
|
||||
passes.gIncludeFile = includeModule
|
||||
passes.gImportModule = importModule
|
||||
let graph = newModuleGraph()
|
||||
let graph = newModuleGraph(config)
|
||||
if freshDefines: initDefines()
|
||||
|
||||
defineSymbol("nimscript")
|
||||
|
|
@ -150,7 +157,7 @@ proc runNimScript*(cache: IdentCache; scriptName: string;
|
|||
|
||||
var m = graph.makeModule(scriptName)
|
||||
incl(m.flags, sfMainModule)
|
||||
vm.globalCtx = setupVM(m, cache, scriptName)
|
||||
vm.globalCtx = setupVM(m, cache, scriptName, config)
|
||||
|
||||
graph.compileSystemModule(cache)
|
||||
discard graph.processModule(m, llStreamOpen(scriptName, fmRead), nil, cache)
|
||||
|
|
|
|||
|
|
@ -1052,6 +1052,8 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
# work without now. template/tsymchoicefield doesn't like an early exit
|
||||
# here at all!
|
||||
#if isSymChoice(n.sons[1]): return
|
||||
when defined(nimsuggest):
|
||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||
|
||||
var s = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared, checkModule})
|
||||
if s != nil:
|
||||
|
|
|
|||
|
|
@ -97,10 +97,17 @@ proc genericCacheGet(genericSym: PSym, entry: TInstantiation;
|
|||
if inst.compilesId == id and sameInstantiation(entry, inst[]):
|
||||
return inst.sym
|
||||
|
||||
when false:
|
||||
proc `$`(x: PSym): string =
|
||||
result = x.name.s & " " & " id " & $x.id
|
||||
|
||||
proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
|
||||
# we need to create a fresh set of gensym'ed symbols:
|
||||
if n.kind == nkSym and sfGenSym in n.sym.flags and
|
||||
(n.sym.owner == orig or n.sym.owner.kind == skPackage):
|
||||
#if n.kind == nkSym and sfGenSym in n.sym.flags:
|
||||
# if n.sym.owner != orig:
|
||||
# echo "symbol ", n.sym.name.s, " orig ", orig, " owner ", n.sym.owner
|
||||
if n.kind == nkSym and {sfGenSym, sfFromGeneric} * n.sym.flags == {sfGenSym}: # and
|
||||
# (n.sym.owner == orig or n.sym.owner.kind in {skPackage}):
|
||||
let s = n.sym
|
||||
var x = PSym(idTableGet(symMap, s))
|
||||
if x == nil:
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ type
|
|||
toBind, toMixin, toInject: IntSet
|
||||
owner: PSym
|
||||
cursorInBody: bool # only for nimsuggest
|
||||
scopeN: int
|
||||
bracketExpr: PNode
|
||||
|
||||
template withBracketExpr(ctx, x, body: untyped) =
|
||||
|
|
@ -141,8 +142,13 @@ proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
|||
|
||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||
|
||||
proc openScope(c: var TemplCtx) = openScope(c.c)
|
||||
proc closeScope(c: var TemplCtx) = closeScope(c.c)
|
||||
proc openScope(c: var TemplCtx) =
|
||||
openScope(c.c)
|
||||
inc c.scopeN
|
||||
|
||||
proc closeScope(c: var TemplCtx) =
|
||||
dec c.scopeN
|
||||
closeScope(c.c)
|
||||
|
||||
proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
|
||||
openScope(c)
|
||||
|
|
@ -166,6 +172,7 @@ proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
|
|||
result = newSym(kind, considerQuotedIdent(n), c.owner, n.info)
|
||||
incl(result.flags, sfGenSym)
|
||||
incl(result.flags, sfShadowed)
|
||||
if c.scopeN == 0: incl(result.flags, sfFromGeneric)
|
||||
|
||||
proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||
# locals default to 'gensym':
|
||||
|
|
|
|||
|
|
@ -659,7 +659,8 @@ proc addInheritedFields(c: PContext, check: var IntSet, pos: var int,
|
|||
addInheritedFieldsAux(c, check, pos, obj.n)
|
||||
|
||||
proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n.sonsLen == 0: return newConstraint(c, tyObject)
|
||||
if n.sonsLen == 0:
|
||||
return newConstraint(c, tyObject)
|
||||
var check = initIntSet()
|
||||
var pos = 0
|
||||
var base, realBase: PType = nil
|
||||
|
|
@ -1159,8 +1160,16 @@ proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType =
|
|||
result.sym = prev.sym
|
||||
assignType(prev, result)
|
||||
|
||||
proc fixupTypeOf(c: PContext, prev: PType, typExpr: PNode) =
|
||||
if prev != nil:
|
||||
let result = newTypeS(tyAlias, c)
|
||||
result.rawAddSon typExpr.typ
|
||||
result.sym = prev.sym
|
||||
assignType(prev, result)
|
||||
|
||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
result = nil
|
||||
|
||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||
case n.kind
|
||||
of nkEmpty: discard
|
||||
|
|
@ -1168,6 +1177,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
|
||||
checkSonsLen(n, 1)
|
||||
let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
|
||||
fixupTypeOf(c, prev, typExpr)
|
||||
result = typExpr.typ
|
||||
of nkPar:
|
||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||
|
|
@ -1234,6 +1244,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
elif op.id == ord(wType):
|
||||
checkSonsLen(n, 2)
|
||||
let typExpr = semExprWithType(c, n.sons[1], {efInTypeof})
|
||||
fixupTypeOf(c, prev, typExpr)
|
||||
result = typExpr.typ
|
||||
else:
|
||||
result = semTypeExpr(c, n, prev)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,20 @@ var
|
|||
|
||||
template origModuleName(m: PSym): string = m.name.s
|
||||
|
||||
proc findDocComment(n: PNode): PNode =
|
||||
if n == nil: return nil
|
||||
if not isNil(n.comment): return n
|
||||
for i in countup(0, safeLen(n)-1):
|
||||
result = findDocComment(n.sons[i])
|
||||
if result != nil: return
|
||||
|
||||
proc extractDocComment(s: PSym): string =
|
||||
let n = findDocComment(s.ast)
|
||||
if not n.isNil:
|
||||
result = n.comment.replace("\n##", "\n").strip
|
||||
else:
|
||||
result = ""
|
||||
|
||||
proc symToSuggest(s: PSym, isLocal: bool, section: string, li: TLineInfo;
|
||||
quality: range[0..100]): Suggest =
|
||||
result.section = parseIdeCmd(section)
|
||||
|
|
|
|||
|
|
@ -559,7 +559,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
if regs[rb].node.kind == nkRefTy:
|
||||
regs[ra].node = regs[rb].node.sons[0]
|
||||
else:
|
||||
stackTrace(c, tos, pc, errGenerated, "limited VM support for pointers")
|
||||
ensureKind(rkNode)
|
||||
regs[ra].node = regs[rb].node
|
||||
else:
|
||||
stackTrace(c, tos, pc, errNilAccess)
|
||||
of opcWrDeref:
|
||||
|
|
@ -932,7 +933,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
c.module
|
||||
var macroCall = newNodeI(nkCall, c.debug[pc])
|
||||
macroCall.add(newSymNode(prc))
|
||||
for i in 1 .. rc-1: macroCall.add(regs[rb+i].regToNode)
|
||||
for i in 1 .. rc-1:
|
||||
let node = regs[rb+i].regToNode
|
||||
node.info = c.debug[pc]
|
||||
macroCall.add(node)
|
||||
let a = evalTemplate(macroCall, prc, genSymOwner)
|
||||
a.recSetFlagIsRef
|
||||
ensureKind(rkNode)
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,13 @@ proc isTemp(c: PCtx; dest: TDest): bool =
|
|||
template needsAdditionalCopy(n): untyped =
|
||||
not c.isTemp(dest) and not fitsRegister(n.typ)
|
||||
|
||||
proc genAdditionalCopy(c: PCtx; n: PNode; opc: TOpcode;
|
||||
dest, idx, value: TRegister) =
|
||||
var cc = c.getTemp(n.typ)
|
||||
c.gABC(n, whichAsgnOpc(n), cc, value, 0)
|
||||
c.gABC(n, opc, dest, idx, cc)
|
||||
c.freeTemp(cc)
|
||||
|
||||
proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
|
||||
dest, idx, value: TRegister) =
|
||||
# opcLdObj et al really means "load address". We sometimes have to create a
|
||||
|
|
@ -1266,10 +1273,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
|
|||
# mylocal = a.b # needs a copy of the data!
|
||||
assert n.typ != nil
|
||||
if needsAdditionalCopy(n):
|
||||
var cc = c.getTemp(n.typ)
|
||||
c.gABC(n, whichAsgnOpc(n), cc, value, 0)
|
||||
c.gABC(n, opc, dest, idx, cc)
|
||||
c.freeTemp(cc)
|
||||
genAdditionalCopy(c, n, opc, dest, idx, value)
|
||||
else:
|
||||
c.gABC(n, opc, dest, idx, value)
|
||||
|
||||
|
|
@ -1352,7 +1356,7 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
|||
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||
if s.ast != nil:
|
||||
let tmp = c.genx(s.ast)
|
||||
c.preventFalseAlias(n, opcWrDeref, dest, 0, tmp)
|
||||
c.genAdditionalCopy(n, opcWrDeref, dest, 0, tmp)
|
||||
c.freeTemp(dest)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
|
|
@ -1506,7 +1510,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
|||
#assert(a.sons[0].kind == nkSym) can happen for transformed vars
|
||||
if a.kind == nkVarTuple:
|
||||
for i in 0 .. a.len-3:
|
||||
setSlot(c, a[i].sym)
|
||||
if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
|
||||
checkCanEval(c, a[i])
|
||||
c.gen(lowerTupleUnpacking(a, c.getOwner))
|
||||
elif a.sons[0].kind == nkSym:
|
||||
|
|
@ -1525,7 +1529,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
|||
if a.sons[2].kind != nkEmpty:
|
||||
let tmp = c.genx(a.sons[0], {gfAddrOf})
|
||||
let val = c.genx(a.sons[2])
|
||||
c.preventFalseAlias(a.sons[2], opcWrDeref, tmp, 0, val)
|
||||
c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
|
||||
c.freeTemp(val)
|
||||
c.freeTemp(tmp)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue