Merge branch 'devel' into araq-fixes-7833

This commit is contained in:
Araq
2018-08-04 15:52:34 +02:00
28 changed files with 399 additions and 173 deletions

View File

@@ -22,7 +22,8 @@
become an error in the future.
- The ``'c`` and ``'C'`` prefix for octal literals is now deprecated to
bring the language in line with the standard library (e.g. ``parseOct``).
- The dot style for import paths (e.g ``import path.to.module`` instead of
``import path/to/module``) has been deprecated.
#### Breaking changes in the standard library
@@ -59,6 +60,8 @@
1-based coordinates on POSIX for correct behaviour; the Windows behaviour
was always correct).
- ``lineInfoObj`` now returns absolute path instead of project path.
It's used by ``lineInfo``, ``check``, ``expect``, ``require``, etc.
#### Breaking changes in the compiler
@@ -193,4 +196,9 @@
- Nintendo Switch was added as a new platform target. See [the compiler user guide](https://nim-lang.org/docs/nimc.html)
for more info.
- macros.bindSym now capable to accepts not only literal string or string constant expression.
bindSym enhancement make it also can accepts computed string or ident node inside macros /
compile time functions / static blocks. Only in templates / regular code it retains it's old behavior.
This new feature can be accessed via {.experimental: "dynamicBindSym".} pragma/switch
### Bugfixes

View File

@@ -517,12 +517,11 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
path = path[cwd.len+1 .. ^1].replace('\\', '/')
let gitUrl = getConfigVar(d.conf, "git.url")
if gitUrl.len > 0:
var commit = getConfigVar(d.conf, "git.commit")
if commit.len == 0: commit = "master"
let commit = getConfigVar(d.conf, "git.commit", "master")
let develBranch = getConfigVar(d.conf, "git.devel", "devel")
dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc,
["path", "line", "url", "commit"], [rope path,
rope($n.info.line), rope gitUrl,
rope commit])])
["path", "line", "url", "commit", "devel"], [rope path,
rope($n.info.line), rope gitUrl, rope commit, rope develBranch])])
add(d.section[k], ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.item"),
["name", "header", "desc", "itemID", "header_plain", "itemSym",

View File

@@ -645,7 +645,7 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var
if optCompileOnly notin conf.globalOptions:
add(cmds, compileCmd)
let (_, name, _) = splitFile(it.cname)
add(prettyCmds, "CC: " & name)
add(prettyCmds, if hintCC in conf.notes: "CC: " & name else: "")
if optGenScript in conf.globalOptions:
add(script, compileCmd)
add(script, "\n")
@@ -659,7 +659,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string =
libname = getCurrentDir() / libname
else:
libname = (libNameTmpl(conf) % splitFile(conf.projectName).name)
result = CC[conf.cCompiler].buildLib % ["libfile", libname,
result = CC[conf.cCompiler].buildLib % ["libfile", quoteShell(libname),
"objfiles", objfiles]
else:
var linkerExe = getConfigVar(conf, conf.cCompiler, ".linkerexe")
@@ -773,7 +773,8 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) =
var prettyCmds: TStringSeq = @[]
let prettyCb = proc (idx: int) =
when declared(echo):
echo prettyCmds[idx]
let cmd = prettyCmds[idx]
if cmd != "": echo cmd
compileCFile(conf, conf.toCompile, script, cmds, prettyCmds)
if optCompileOnly notin conf.globalOptions:
execCmdsInParallel(conf, cmds, prettyCb)

View File

@@ -37,7 +37,7 @@ type
warnProveInit, warnProveField, warnProveIndex, warnGcUnsafe, warnGcUnsafe2,
warnUninit, warnGcMem, warnDestructor, warnLockLevel, warnResultShadowed,
warnInconsistentSpacing, warnUser,
hintSuccess, hintSuccessX,
hintSuccess, hintSuccessX, hintCC,
hintLineTooLong, hintXDeclaredButNotUsed, hintConvToBaseNotNeeded,
hintConvFromXtoItselfNotNeeded, hintExprAlwaysX, hintQuitCalled,
hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
@@ -94,6 +94,7 @@ const
warnUser: "$1",
hintSuccess: "operation successful",
hintSuccessX: "operation successful ($# lines compiled; $# sec total; $#; $#)",
hintCC: "CC: \'$1\'", # unused
hintLineTooLong: "line too long",
hintXDeclaredButNotUsed: "'$1' is declared but not used",
hintConvToBaseNotNeeded: "conversion to base object is not needed",
@@ -136,7 +137,7 @@ const
"Spacing", "User"]
HintsToStr* = [
"Success", "SuccessX", "LineTooLong",
"Success", "SuccessX", "CC", "LineTooLong",
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",

View File

@@ -155,6 +155,7 @@ proc getModuleName*(conf: ConfigRef; n: PNode): string =
# hacky way to implement 'x / y /../ z':
result = renderTree(n, {renderNoComments}).replace(" ")
of nkDotExpr:
localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths")
result = renderTree(n, {renderNoComments}).replace(".", "/")
of nkImportAs:
result = getModuleName(conf, n.sons[0])

View File

@@ -116,7 +116,8 @@ type
callOperator,
parallel,
destructor,
notnil
notnil,
dynamicBindSym
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf
@@ -406,8 +407,8 @@ proc mainCommandArg*(conf: ConfigRef): string =
proc existsConfigVar*(conf: ConfigRef; key: string): bool =
result = hasKey(conf.configVars, key)
proc getConfigVar*(conf: ConfigRef; key: string): string =
result = conf.configVars.getOrDefault key
proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string =
result = conf.configVars.getOrDefault(key, default)
proc setConfigVar*(conf: ConfigRef; key, val: string) =
conf.configVars[key] = val

View File

@@ -207,6 +207,67 @@ proc semBindSym(c: PContext, n: PNode): PNode =
else:
errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal)
proc opBindSym(c: PContext, scope: PScope, n: PNode, isMixin: int, info: PNode): PNode =
if n.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit, nkIdent}:
localError(c.config, info.info, errStringOrIdentNodeExpected)
return errorNode(c, n)
if isMixin < 0 or isMixin > high(TSymChoiceRule).int:
localError(c.config, info.info, errConstExprExpected)
return errorNode(c, n)
let id = if n.kind == nkIdent: n
else: newIdentNode(getIdent(c.cache, n.strVal), info.info)
let tmpScope = c.currentScope
c.currentScope = scope
let s = qualifiedLookUp(c, id, {checkUndeclared})
if s != nil:
# we need to mark all symbols:
result = symChoice(c, id, s, TSymChoiceRule(isMixin))
else:
errorUndeclaredIdentifier(c, info.info, if n.kind == nkIdent: n.ident.s
else: n.strVal)
c.currentScope = tmpScope
proc semDynamicBindSym(c: PContext, n: PNode): PNode =
# inside regular code, bindSym resolves to the sym-choice
# nodes (see tinspectsymbol)
if not (c.inStaticContext > 0 or getCurrOwner(c).isCompileTimeProc):
return semBindSym(c, n)
if c.graph.vm.isNil:
setupGlobalCtx(c.module, c.graph)
let
vm = PCtx c.graph.vm
# cache the current scope to
# prevent it lost into oblivion
scope = c.currentScope
# cannot use this
# vm.config.features.incl dynamicBindSym
proc bindSymWrapper(a: VmArgs) =
# capture PContext and currentScope
# param description:
# 0. ident, a string literal / computed string / or ident node
# 1. bindSym rule
# 2. info node
a.setResult opBindSym(c, scope, a.getNode(0), a.getInt(1).int, a.getNode(2))
let
# altough we use VM callback here, it is not
# executed like 'normal' VM callback
idx = vm.registerCallback("bindSymImpl", bindSymWrapper)
# dummy node to carry idx information to VM
idxNode = newIntTypeNode(nkIntLit, idx, c.graph.getSysType(TLineInfo(), tyInt))
result = copyNode(n)
for x in n: result.add x
result.add n # info node
result.add idxNode
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semOf(c: PContext, n: PNode): PNode =
@@ -270,7 +331,11 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
of mOf: result = semOf(c, n)
of mHigh, mLow: result = semLowHigh(c, n, n[0].sym.magic)
of mShallowCopy: result = semShallowCopy(c, n, flags)
of mNBindSym: result = semBindSym(c, n)
of mNBindSym:
if dynamicBindSym notin c.features:
result = semBindSym(c, n)
else:
result = semDynamicBindSym(c, n)
of mProcCall:
result = n
result.typ = n[1].typ

View File

@@ -11,6 +11,7 @@
# included from sem.nim
const
errStringOrIdentNodeExpected = "string or ident node expected"
errStringLiteralExpected = "string literal expected"
errIntLiteralExpected = "integer literal expected"
errWrongNumberOfVariables = "wrong number of variables"

View File

@@ -616,19 +616,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let rc = instr.regC
case regs[ra].kind
of rkNodeAddr:
# XXX: Workaround for vmgen bug:
let n = regs[rc].regToNode
if (nfIsRef in regs[ra].nodeAddr[].flags or
regs[ra].nodeAddr[].kind == nkNilLit) and nfIsRef notin n.flags:
if regs[ra].nodeAddr[].kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
regs[ra].nodeAddr[][] = n[]
regs[ra].nodeAddr[].flags.incl nfIsRef
# `var object` parameters are sent as rkNodeAddr. When they are mutated
# vmgen generates opcWrDeref, which means that we must dereference
# twice.
# TODO: This should likely be handled differently in vmgen.
elif (nfIsRef notin regs[ra].nodeAddr[].flags and
if (nfIsRef notin regs[ra].nodeAddr[].flags and
nfIsRef notin n.flags):
regs[ra].nodeAddr[][] = n[]
else:
@@ -1229,9 +1222,25 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
node.typ.callConv == ccClosure and node.sons[0].kind == nkNilLit and
node.sons[1].kind == nkNilLit))
of opcNBindSym:
# cannot use this simple check
# if dynamicBindSym notin c.config.features:
# bindSym with static input
decodeBx(rkNode)
regs[ra].node = copyTree(c.constants.sons[rbx])
regs[ra].node.flags.incl nfIsRef
of opcNDynBindSym:
# experimental bindSym
let
rb = instr.regB
rc = instr.regC
idx = int(regs[rb+rc-1].intVal)
callback = c.callbacks[idx].value
args = VmArgs(ra: ra, rb: rb, rc: rc, slots: cast[pointer](regs),
currentException: c.currentExceptionB,
currentLineInfo: c.debug[pc])
callback(args)
regs[ra].node.flags.incl nfIsRef
of opcNChild:
decodeBC(rkNode)
let idx = regs[rc].intVal.int
@@ -1416,7 +1425,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcNGetFile:
decodeB(rkNode)
let n = regs[rb].node
regs[ra].node = newStrNode(nkStrLit, toFilename(c.config, n.info))
regs[ra].node = newStrNode(nkStrLit, toFullPath(c.config, n.info))
regs[ra].node.info = n.info
regs[ra].node.typ = n.typ
of opcNGetLine:
@@ -1780,7 +1789,7 @@ proc getGlobalValue*(c: PCtx; s: PSym): PNode =
include vmops
proc setupGlobalCtx(module: PSym; graph: ModuleGraph) =
proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) =
if graph.vm.isNil:
graph.vm = newCtx(module, graph.cache, graph)
registerAdditionalOps(PCtx graph.vm)

View File

@@ -136,7 +136,7 @@ type
opcLdGlobalAddr, # dest = addr(globals[Bx])
opcLdImmInt, # dest = immediate value
opcNBindSym,
opcNBindSym, opcNDynBindSym,
opcSetType, # dest.typ = types[Bx]
opcTypeTrait,
opcMarshalLoad, opcMarshalStore,
@@ -229,7 +229,8 @@ proc refresh*(c: PCtx, module: PSym) =
c.prc = PProc(blocks: @[])
c.loopIterations = MaxLoopIterations
proc registerCallback*(c: PCtx; name: string; callback: VmCallback) =
proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} =
result = c.callbacks.len
c.callbacks.add((name, callback))
const

View File

@@ -37,7 +37,9 @@ when hasFFI:
import evalffi
type
TGenFlag = enum gfAddrOf, gfFieldAccess
TGenFlag = enum
gfNode # Affects how variables are loaded - always loads as rkNode
gfNodeAddr # Affects how variables are loaded - always loads as rkNodeAddr
TGenFlags = set[TGenFlag]
proc debugInfo(c: PCtx; info: TLineInfo): string =
@@ -563,7 +565,7 @@ proc genIndex(c: PCtx; n: PNode; arr: PType): TRegister =
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
case le.kind
of nkBracketExpr:
let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess})
let dest = c.genx(le.sons[0], {gfNode})
let idx = c.genIndex(le.sons[1], le.sons[0].typ)
c.gABC(le, opcWrArr, dest, idx, value)
c.freeTemp(dest)
@@ -571,17 +573,17 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
of nkDotExpr, nkCheckedFieldExpr:
# XXX field checks here
let left = if le.kind == nkDotExpr: le else: le.sons[0]
let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
let dest = c.genx(left.sons[0], {gfNode})
let idx = genField(c, left.sons[1])
c.gABC(left, opcWrObj, dest, idx, value)
c.freeTemp(dest)
of nkDerefExpr, nkHiddenDeref:
let dest = c.genx(le.sons[0], {gfAddrOf})
let dest = c.genx(le.sons[0], {gfNode})
c.gABC(le, opcWrDeref, dest, 0, value)
c.freeTemp(dest)
of nkSym:
if le.sym.isGlobal:
let dest = c.genx(le, {gfAddrOf})
let dest = c.genx(le, {gfNodeAddr})
c.gABC(le, opcWrDeref, dest, 0, value)
c.freeTemp(dest)
else:
@@ -815,6 +817,43 @@ proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) =
c.freeTemp(tmp2)
c.freeTemp(tmp3)
proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
# nah, cannot use c.config.features because sempass context
# can have local experimental switch
# if dynamicBindSym notin c.config.features:
if n.len == 2: # hmm, reliable?
# bindSym with static input
if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}:
let idx = c.genLiteral(n[1])
if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, opcNBindSym, dest, idx)
else:
localError(c.config, n.info, "invalid bindSym usage")
else:
# experimental bindSym
if dest < 0: dest = c.getTemp(n.typ)
let x = c.getTempRange(n.len, slotTempUnknown)
# callee symbol
var tmp0 = TDest(x)
c.genLit(n.sons[0], tmp0)
# original parameters
for i in 1..<n.len-2:
var r = TRegister(x+i)
c.gen(n.sons[i], r)
# info node
var tmp1 = TDest(x+n.len-2)
c.genLit(n.sons[^2], tmp1)
# payload idx
var tmp2 = TDest(x+n.len-1)
c.genLit(n.sons[^1], tmp2)
c.gABC(n, opcNDynBindSym, dest, x, n.len)
c.freeTempRange(x, n.len)
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
case m
of mAnd: c.genAndOr(n, opcFJmp, dest)
@@ -1135,13 +1174,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
of mNCopyNimTree: genUnaryABC(c, n, dest, opcNCopyNimTree)
of mNBindSym:
if n[1].kind in {nkClosedSymChoice, nkOpenSymChoice, nkSym}:
let idx = c.genLiteral(n[1])
if dest < 0: dest = c.getTemp(n.typ)
c.gABx(n, opcNBindSym, dest, idx)
else:
localError(c.config, n.info, "invalid bindSym usage")
of mNBindSym: genBindSym(c, n, dest)
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
@@ -1252,41 +1285,21 @@ proc canElimAddr(n: PNode): PNode =
# addr ( deref ( x )) --> x
result = n.sons[0].sons[0]
proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
# a nop for certain types
let isAddr = opc in {opcAddrNode, opcAddrReg}
if isAddr and (let m = canElimAddr(n); m != nil):
proc genAddr(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
if (let m = canElimAddr(n); m != nil):
gen(c, m, dest, flags)
return
let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfAddrOf, gfFieldAccess}
else: {gfAddrOf}
let newflags = if isAddr: flags+af else: flags
# consider:
# proc foo(f: var ref int) =
# f = new(int)
# proc blah() =
# var x: ref int
# foo x
#
# The type of 'f' is 'var ref int' and of 'x' is 'ref int'. Hence for
# nkAddr we must not use 'unneededIndirection', but for deref we use it.
if not isAddr and unneededIndirection(n.sons[0]):
gen(c, n.sons[0], dest, newflags)
if gfAddrOf notin flags and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
elif isAddr and isGlobal(n.sons[0]):
let af = if n[0].kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr}: {gfNode}
else: {gfNodeAddr}
let newflags = flags-{gfNode, gfNodeAddr}+af
if isGlobal(n.sons[0]):
gen(c, n.sons[0], dest, flags+af)
else:
let tmp = c.genx(n.sons[0], newflags)
if dest < 0: dest = c.getTemp(n.typ)
if not isAddr:
gABC(c, n, opc, dest, tmp)
assert n.typ != nil
if gfAddrOf notin flags and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
elif c.prc.slots[tmp].kind >= slotTempUnknown:
if c.prc.slots[tmp].kind >= slotTempUnknown:
gABC(c, n, opcAddrNode, dest, tmp)
# hack ahead; in order to fix bug #1781 we mark the temporary as
# permanent, so that it's not used for anything else:
@@ -1297,6 +1310,19 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
gABC(c, n, opcAddrReg, dest, tmp)
c.freeTemp(tmp)
proc genDeref(c: PCtx, n: PNode, dest: var TDest, flags: TGenFlags) =
if unneededIndirection(n.sons[0]):
gen(c, n.sons[0], dest, flags)
if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
else:
let tmp = c.genx(n.sons[0], flags)
if dest < 0: dest = c.getTemp(n.typ)
gABC(c, n, opcLdDeref, dest, tmp)
assert n.typ != nil
if {gfNodeAddr, gfNode} * flags == {} and fitsRegister(n.typ):
c.gABC(n, opcNodeToReg, dest, dest)
proc whichAsgnOpc(n: PNode): TOpcode =
case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
@@ -1382,7 +1408,7 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
case le.kind
of nkBracketExpr:
let dest = c.genx(le.sons[0], {gfAddrOf, gfFieldAccess})
let dest = c.genx(le.sons[0], {gfNode})
let idx = c.genIndex(le.sons[1], le.sons[0].typ)
let tmp = c.genx(ri)
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
@@ -1394,13 +1420,13 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
of nkDotExpr, nkCheckedFieldExpr:
# XXX field checks here
let left = if le.kind == nkDotExpr: le else: le.sons[0]
let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
let dest = c.genx(left.sons[0], {gfNode})
let idx = genField(c, left.sons[1])
let tmp = c.genx(ri)
c.preventFalseAlias(left, opcWrObj, dest, idx, tmp)
c.freeTemp(tmp)
of nkDerefExpr, nkHiddenDeref:
let dest = c.genx(le.sons[0], {gfAddrOf})
let dest = c.genx(le.sons[0], {gfNode})
let tmp = c.genx(ri)
c.preventFalseAlias(le, opcWrDeref, dest, 0, tmp)
c.freeTemp(tmp)
@@ -1409,7 +1435,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
checkCanEval(c, le)
if s.isGlobal:
withTemp(tmp, le.typ):
c.gen(le, tmp, {gfAddrOf})
c.gen(le, tmp, {gfNodeAddr})
let val = c.genx(ri)
c.preventFalseAlias(le, opcWrDeref, tmp, 0, val)
c.freeTemp(val)
@@ -1427,7 +1453,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
else:
gen(c, ri, dest)
else:
let dest = c.genx(le, {gfAddrOf})
let dest = c.genx(le, {gfNodeAddr})
genAsgn(c, dest, ri, requiresCopy)
proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
@@ -1463,6 +1489,8 @@ proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
c.freeTemp(tmp)
proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
# gfNodeAddr and gfNode are mutually exclusive
assert card(flags * {gfNodeAddr, gfNode}) < 2
let s = n.sym
if s.isGlobal:
if sfCompileTime in s.flags or c.mode == emRepl:
@@ -1474,13 +1502,13 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
else: genGlobalInit(c, n, s)
if dest < 0: dest = c.getTemp(n.typ)
assert s.typ != nil
if gfAddrOf notin flags and fitsRegister(s.typ):
if gfNodeAddr in flags:
c.gABx(n, opcLdGlobalAddr, dest, s.position)
elif fitsRegister(s.typ) and gfNode notin flags:
var cc = c.getTemp(n.typ)
c.gABx(n, opcLdGlobal, cc, s.position)
c.gABC(n, opcNodeToReg, dest, cc)
c.freeTemp(cc)
elif {gfAddrOf, gfFieldAccess} * flags == {gfAddrOf}:
c.gABx(n, opcLdGlobalAddr, dest, s.position)
else:
c.gABx(n, opcLdGlobal, dest, s.position)
else:
@@ -1498,7 +1526,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
cannotEval(c, n)
template needsRegLoad(): untyped =
gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar, tyLent}))
{gfNode, gfNodeAddr} * flags == {} and
fitsRegister(n.typ.skipTypes({tyVar, tyLent}))
proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
flags: TGenFlags) =
@@ -1634,7 +1663,7 @@ proc genVarSection(c: PCtx; n: PNode) =
c.globals.add(sa)
s.position = c.globals.len
if a.sons[2].kind != nkEmpty:
let tmp = c.genx(a.sons[0], {gfAddrOf})
let tmp = c.genx(a.sons[0], {gfNodeAddr})
let val = c.genx(a.sons[2])
c.genAdditionalCopy(a.sons[2], opcWrDeref, tmp, 0, val)
c.freeTemp(val)
@@ -1839,8 +1868,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of nkDotExpr: genObjAccess(c, n, dest, flags)
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
of nkBracketExpr: genArrAccess(c, n, dest, flags)
of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcLdDeref, flags)
of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddrNode, flags)
of nkDerefExpr, nkHiddenDeref: genDeref(c, n, dest, flags)
of nkAddr, nkHiddenAddr: genAddr(c, n, dest, flags)
of nkIfStmt, nkIfExpr: genIf(c, n, dest)
of nkWhenStmt:
# This is "when nimvm" node. Chose the first branch.

View File

@@ -55,6 +55,8 @@ doc.item.toc = """
# HTML rendered for doc.item's seeSrc variable. Note that this will render to
# the empty string if you don't pass anything through --docSeeSrcURL. Available
# substitutaion variables here are:
# * $commit: branch/commit to use in source link.
# * $devel: branch to use in edit link.
# * $path: relative path to the file being processed.
# * $line: line of the item in the original source file.
# * $url: whatever you did pass through the --docSeeSrcUrl switch (which also
@@ -62,7 +64,7 @@ doc.item.toc = """
doc.item.seesrc = """&nbsp;&nbsp;<a
href="${url}/tree/${commit}/${path}#L${line}"
class="link-seesrc" target="_blank">Source</a>
<a href="${url}/edit/devel/${path}#L${line}" class="link-seesrc" target="_blank" >Edit</a>
<a href="${url}/edit/${devel}/${path}#L${line}" class="link-seesrc" target="_blank" >Edit</a>
"""
doc.toc = """

View File

@@ -6229,10 +6229,10 @@ imported:
:test: "nim c $1"
:status: 1
import strutils except `%`, toUpper
import strutils except `%`, toUpperAscii
# doesn't work then:
echo "$1" % "abc".toUpper
echo "$1" % "abc".toUpperAscii
It is not checked that the ``except`` list is really exported from the module.
@@ -6261,24 +6261,24 @@ A module alias can be introduced via the ``as`` keyword:
echo su.format("$1", "lalelu")
The original module name is then not accessible. The
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
can be used to refer to a module in subdirectories:
The original module name is then not accessible. The notations
``path/to/module`` or ``"path/to/module"`` can be used to refer to a module
in subdirectories:
.. code-block:: nim
import lib.pure.strutils, lib/pure/os, "lib/pure/times"
import lib/pure/os, "lib/pure/times"
Note that the module name is still ``strutils`` and not ``lib.pure.strutils``
Note that the module name is still ``strutils`` and not ``lib/pure/strutils``
and so one **cannot** do:
.. code-block:: nim
import lib.pure.strutils
echo lib.pure.strutils
import lib/pure/strutils
echo lib/pure/strutils.toUpperAscii("abc")
Likewise the following does not make sense as the name is ``strutils`` already:
.. code-block:: nim
import lib.pure.strutils as strutils
import lib/pure/strutils as strutils
Collective imports from a directory
@@ -6297,7 +6297,8 @@ name is not a valid Nim identifier it needs to be a string literal:
Pseudo import/include paths
~~~~~~~~~~~~~~~~~~~~~~~~~~~
A directory can also be a so called "pseudo directory".
A directory can also be a so called "pseudo directory". They can be used to
avoid ambiguity when there are multiple modules with the same path.
There are two pseudo directories:

View File

@@ -50,6 +50,7 @@ Boot options:
Commands for core developers:
web [options] generates the website and the full documentation
(see `nimweb.nim` for cmd line options)
website [options] generates only the website
csource -d:release builds the C sources for installation
pdf builds the PDF documentation

View File

@@ -382,16 +382,24 @@ type
{.deprecated: [TBindSymRule: BindSymRule].}
proc bindSym*(ident: static[string], rule: BindSymRule = brClosed): NimNode {.
proc bindSym*(ident: string | NimNode, rule: BindSymRule = brClosed): NimNode {.
magic: "NBindSym", noSideEffect.}
## creates a node that binds `ident` to a symbol node. The bound symbol
## may be an overloaded symbol.
## if `ident` is a NimNode, it must have nkIdent kind.
## If ``rule == brClosed`` either an ``nkClosedSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brOpen`` either an ``nkOpenSymChoice`` tree is
## returned or ``nkSym`` if the symbol is not ambiguous.
## If ``rule == brForceOpen`` always an ``nkOpenSymChoice`` tree is
## returned even if the symbol is not ambiguous.
##
## experimental feature:
## use {.experimental: "dynamicBindSym".} to activate it
## if called from template / regular code, `ident` and `rule` must be
## constant expression / literal value.
## if called from macros / compile time procs / static blocks,
## `ident` and `rule` can be VM computed value.
proc genSym*(kind: NimSymKind = nskLet; ident = ""): NimNode {.
magic: "NGenSym", noSideEffect.}
@@ -425,6 +433,7 @@ proc getColumn(arg: NimNode): int {.magic: "NLineInfo", noSideEffect.}
proc getFile(arg: NimNode): string {.magic: "NLineInfo", noSideEffect.}
proc lineInfoObj*(n: NimNode): LineInfo {.compileTime.} =
## returns ``LineInfo`` of ``n``, using absolute path for ``filename``
result.filename = n.getFile
result.line = n.getLine
result.column = n.getColumn

View File

@@ -41,7 +41,7 @@
## immediately.
##
## .. code-block:: Nim
## var socket = newSocket()
## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
## socket.sendTo("192.168.0.1", Port(27960), "status\n")
##
## Creating a server

View File

@@ -436,8 +436,9 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
a.nextChunkSize = PageSize*4
else:
a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2)
var size = size
a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize)
var size = size
if size > a.nextChunkSize:
result = cast[PBigChunk](osAllocPages(size))
else:

View File

@@ -16,9 +16,12 @@ proc main =
dealloc p
# c_fprintf(stdout, "iteration: %ld size: %ld\n", i, size)
when defined(cpu64):
# bug #7120
var x = alloc(((1 shl 29) - 4) * 8)
dealloc x
# see https://github.com/nim-lang/Nim/issues/8509
# this often made appveyor (on windows) fail with out of memory
when defined(posix):
# bug #7120
var x = alloc(((1 shl 29) - 4) * 8)
dealloc x
main()

View File

@@ -1,4 +1,9 @@
discard """
msg: '''initApple
deinitApple
Coral
enum
redCoral, blackCoral'''
output: '''TFoo
TBar'''
"""
@@ -23,3 +28,40 @@ macro test: untyped =
bindSym("TBar"))
test()
# issue 7827, bindSym power up
{.experimental: "dynamicBindSym".}
type
Apple = ref object
name: string
color: int
weight: int
proc initApple(name: string): Apple =
discard
proc deinitApple(x: Apple) =
discard
macro wrapObject(obj: typed, n: varargs[untyped]): untyped =
let m = n[0]
for x in m:
var z = bindSym x
echo z.repr
wrapObject(Apple):
initApple
deinitApple
type
Coral = enum
redCoral
blackCoral
macro mixer(): untyped =
let m = "Co" & "ral"
let x = bindSym(m)
echo x.repr
echo getType(x).repr
mixer()

View File

@@ -145,7 +145,7 @@ else:
echo getLastModificationTime("a") == tm
removeFile("a")
when defined(Linux) or defined(osx):
when defined(posix):
block normalizedPath:
block relative:

18
tests/system/t7894.nim Normal file
View File

@@ -0,0 +1,18 @@
discard """
"""
import os
const size = 250000000
var saved = newSeq[seq[int8]]()
for i in 0..22:
# one of these is 0.25GB.
#echo i
var x = newSeq[int8](size)
sleep(10)
saved.add(x)
for x in saved:
#echo x.len
doAssert x.len == size

View File

@@ -1,54 +1,57 @@
discard """
"""
var x: ptr int
x = cast[ptr int](alloc(7))
assert x != nil
doAssert x != nil
x = cast[ptr int](x.realloc(2))
assert x != nil
doAssert x != nil
x.dealloc()
x = createU(int, 3)
assert x != nil
doAssert x != nil
x.dealloc()
x = create(int, 4)
assert cast[ptr array[4, int]](x)[0] == 0
assert cast[ptr array[4, int]](x)[1] == 0
assert cast[ptr array[4, int]](x)[2] == 0
assert cast[ptr array[4, int]](x)[3] == 0
doAssert cast[ptr array[4, int]](x)[0] == 0
doAssert cast[ptr array[4, int]](x)[1] == 0
doAssert cast[ptr array[4, int]](x)[2] == 0
doAssert cast[ptr array[4, int]](x)[3] == 0
x = x.resize(4)
assert x != nil
doAssert x != nil
x.dealloc()
x = cast[ptr int](allocShared(100))
assert x != nil
doAssert x != nil
deallocShared(x)
x = createSharedU(int, 3)
assert x != nil
doAssert x != nil
x.deallocShared()
x = createShared(int, 3)
assert x != nil
assert cast[ptr array[3, int]](x)[0] == 0
assert cast[ptr array[3, int]](x)[1] == 0
assert cast[ptr array[3, int]](x)[2] == 0
doAssert x != nil
doAssert cast[ptr array[3, int]](x)[0] == 0
doAssert cast[ptr array[3, int]](x)[1] == 0
doAssert cast[ptr array[3, int]](x)[2] == 0
assert x != nil
doAssert x != nil
x = cast[ptr int](x.resizeShared(2))
assert x != nil
doAssert x != nil
x.deallocShared()
x = create(int, 10)
assert x != nil
doAssert x != nil
x = x.resize(12)
assert x != nil
doAssert x != nil
x.dealloc()
x = createShared(int, 1)
assert x != nil
doAssert x != nil
x = x.resizeShared(1)
assert x != nil
doAssert x != nil
x.deallocShared()
x = cast[ptr int](alloc0(125 shl 23))

View File

@@ -1,3 +1,6 @@
discard """
"""
const
nmax = 2*1024*1024*1024

View File

@@ -65,7 +65,7 @@ proc main() =
for val in table.values():
if myObj2.isNil:
myObj2 = val
assert(myObj == myObj2) # passes
doAssert(myObj == myObj2) # passes
var tableCopy: ListTableRef[int, SomeObj]
deepCopy(tableCopy, table)
@@ -80,7 +80,7 @@ proc main() =
#echo cast[int](myObjCopy)
#echo cast[int](myObjCopy2)
assert(myObjCopy == myObjCopy2) # fails
doAssert(myObjCopy == myObjCopy2) # fails
type
@@ -88,7 +88,7 @@ type
counter, max: int
data: array[0..99, (pointer, pointer)]
assert(sizeof(PtrTable) == 2*sizeof(int)+sizeof(pointer)*2*100)
doAssert(sizeof(PtrTable) == 2*sizeof(int)+sizeof(pointer)*2*100)
main()
echo "ok"

View File

@@ -1,3 +1,6 @@
discard """
"""
import
unittest, osproc, streams, os, strformat
const STRING_DATA = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
@@ -36,7 +39,7 @@ proc verifyFileSize(sz: int64) =
discard execProcess(&"dd if=/dev/zero of={fn} bs=1000000 count={size_in_mb}")
doAssert os.getFileSize(fn) == sz # Verify OS filesize by string
var f = open(fn)
doAssert f.getFileSize() == sz # Verify file handle filesize
f.close()

View File

@@ -1,3 +1,6 @@
discard """
"""
import os
import osproc
import parseopt2
@@ -7,12 +10,12 @@ let argv = commandLineParams()
if argv == @[]:
# this won't work with spaces
assert execShellCmd(getAppFilename() & " \"foo bar\" --aa:bar=a --a=c:d --ab -c --a[baz]:doo") == 0
doAssert execShellCmd(getAppFilename() & " \"foo bar\" --aa:bar=a --a=c:d --ab -c --a[baz]:doo") == 0
else:
let f = toSeq(getopt())
echo f.repr
assert f[0].kind == cmdArgument and f[0].key == "foo bar" and f[0].val == ""
assert f[1].kind == cmdLongOption and f[1].key == "aa" and f[1].val == "bar=a"
assert f[2].kind == cmdLongOption and f[2].key == "a=c" and f[2].val == "d"
assert f[3].kind == cmdLongOption and f[3].key == "ab" and f[3].val == ""
assert f[4].kind == cmdShortOption and f[4].key == "c" and f[4].val == ""
doAssert f[0].kind == cmdArgument and f[0].key == "foo bar" and f[0].val == ""
doAssert f[1].kind == cmdLongOption and f[1].key == "aa" and f[1].val == "bar=a"
doAssert f[2].kind == cmdLongOption and f[2].key == "a=c" and f[2].val == "d"
doAssert f[3].kind == cmdLongOption and f[3].key == "ab" and f[3].val == ""
doAssert f[4].kind == cmdShortOption and f[4].key == "c" and f[4].val == ""

View File

@@ -54,4 +54,9 @@ static:
new(s)
var ss = s
s[] = 1
doAssert ss[] == 1
doAssert ss[] == 1
static: # bug #8402
type R = ref object
var empty: R
let otherEmpty = empty

View File

@@ -13,16 +13,18 @@ import
from xmltree import escape
const gitRepo = "https://github.com/nim-lang/Nim"
type
TKeyValPair = tuple[key, id, val: string]
TConfigData = object of RootObj
tabs, links: seq[TKeyValPair]
doc, srcdoc, srcdoc2, webdoc, pdf: seq[string]
authors, projectName, projectTitle, logo, infile, outdir, ticker: string
authors, projectName, projectTitle, logo, infile, ticker: string
vars: StringTableRef
nimCompiler: string
nimArgs: string
gitURL: string
docHTMLOutput: string
webUploadOutput: string
quotations: Table[string, tuple[quote, author: string]]
numProcessors: int # Set by parallelBuild:n, only works for values > 0.
gaId: string # google analytics ID, nil means analytics are disabled
@@ -51,8 +53,10 @@ proc initConfigData(c: var TConfigData) =
c.webdoc = @[]
c.pdf = @[]
c.infile = ""
c.outdir = ""
c.nimArgs = "--hint[Conf]:off --hint[Path]:off --hint[Processing]:off -d:boot "
c.gitURL = "https://github.com/nim-lang/Nim"
c.docHTMLOutput = "doc/html"
c.webUploadOutput = "web/upload"
c.authors = ""
c.projectTitle = ""
c.projectName = ""
@@ -79,14 +83,19 @@ const
Usage:
nimweb [options] ini-file[.ini] [compile_options]
Options:
-o, --output:dir set the output directory (default: same as ini-file)
--var:name=value set the value of a variable
-h, --help shows this help
-v, --version shows the version
-o, --output overrides output directory instead of default
web/upload and doc/html
--nimCompiler overrides nim compiler; default = bin/nim
--var:name=value set the value of a variable
--website only build the website, not the full documentation
--pdf build the PDF version of the documentation
--json2 build JSON of the documentation
--onlyDocs build only the documentation
--git.url override base url in generated doc links
--git.commit override commit/branch in generated doc links 'source'
--git.devel override devel branch in generated doc links 'edit'
Compile_options:
will be passed to the Nim compiler
"""
@@ -145,7 +154,11 @@ proc parseCmdLine(c: var TConfigData) =
of "version", "v":
stdout.write(version & "\n")
quit(0)
of "o", "output": c.outdir = val
of "output", "o":
c.webUploadOutput = val
c.docHTMLOutput = val / "docs"
of "nimcompiler":
c.nimCompiler = val
of "parallelbuild":
try:
let num = parseInt(val)
@@ -163,8 +176,14 @@ proc parseCmdLine(c: var TConfigData) =
of "googleanalytics":
c.gaId = val
c.nimArgs.add("--doc.googleAnalytics:" & val & " ")
of "git.url":
c.gitURL = val
of "git.commit":
c.nimArgs.add("--git.commit:" & val & " ")
of "git.devel":
c.nimArgs.add("--git.devel:" & val & " ")
else:
echo("Invalid argument $1" % [key])
echo("Invalid argument '$1'" % [key])
quit(usage)
of cmdEnd: break
if c.infile.len == 0: quit(usage)
@@ -244,15 +263,14 @@ proc parseIniFile(c: var TConfigData) =
close(p)
if c.projectName.len == 0:
c.projectName = changeFileExt(extractFilename(c.infile), "")
if c.outdir.len == 0:
c.outdir = splitFile(c.infile).dir
# ------------------- main ----------------------------------------------------
proc exe(f: string): string = return addFileExt(f, ExeExt)
proc findNim(): string =
proc findNim(c: TConfigData): string =
if c.nimCompiler.len > 0: return c.nimCompiler
var nim = "nim".exe
result = "bin" / nim
if existsFile(result): return
@@ -289,9 +307,9 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
## it didn't make much sense to integrate into the existing generic
## documentation builders.
const src = "doc"/"docgen_sample.nim"
exec(findNim() & " doc $# -o:$# $#" %
exec(findNim(c) & " doc $# -o:$# $#" %
[c.nimArgs, destPath / "docgen_sample.html", src])
exec(findNim() & " doc2 $# -o:$# $#" %
exec(findNim(c) & " doc2 $# -o:$# $#" %
[c.nimArgs, destPath / "docgen_sample2.html", src])
proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
@@ -302,23 +320,23 @@ proc buildDoc(c: var TConfigData, destPath: string) =
commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
i = 0
for d in items(c.doc):
commands[i] = findNim() & " rst2html $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, gitRepo,
commands[i] = findNim(c) & " rst2html $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, c.gitURL,
destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc
for d in items(c.srcdoc):
commands[i] = findNim() & " doc0 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, gitRepo,
commands[i] = findNim(c) & " doc0 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, c.gitURL,
destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc
for d in items(c.srcdoc2):
commands[i] = findNim() & " doc2 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, gitRepo,
commands[i] = findNim(c) & " doc2 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, c.gitURL,
destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc
mexec(commands, c.numProcessors)
exec(findNim() & " buildIndex -o:$1/theindex.html $1" % [destPath])
exec(findNim(c) & " buildIndex -o:$1/theindex.html $1" % [destPath])
proc buildPdfDoc(c: var TConfigData, destPath: string) =
createDir(destPath)
@@ -327,7 +345,7 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
else:
const pdflatexcmd = "pdflatex -interaction=nonstopmode "
for d in items(c.pdf):
exec(findNim() & " rst2tex $# $#" % [c.nimArgs, d])
exec(findNim(c) & " rst2tex $# $#" % [c.nimArgs, d])
# call LaTeX twice to get cross references right:
exec(pdflatexcmd & changeFileExt(d, "tex"))
exec(pdflatexcmd & changeFileExt(d, "tex"))
@@ -347,8 +365,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
# build additional documentation (without the index):
var commands = newSeq[string](c.webdoc.len)
for i, doc in pairs(c.webdoc):
commands[i] = findNim() & " doc2 $# --git.url:$# -o:$# $#" %
[c.nimArgs, gitRepo,
commands[i] = findNim(c) & " doc2 $# --git.url:$# -o:$# $#" %
[c.nimArgs, c.gitURL,
destPath / changeFileExt(splitFile(doc).name, "html"), doc]
mexec(commands, c.numProcessors)
@@ -431,9 +449,9 @@ proc buildNewsRss(c: var TConfigData, destPath: string) =
generateRss(destFilename, parseNewsTitles(srcFilename))
proc buildJS(destPath: string) =
exec(findNim() & " js -d:release --out:$1 web/nimblepkglist.nim" %
[destPath / "nimblepkglist.js"])
proc buildJS(c: TConfigData) =
exec(findNim(c) & " js -d:release --out:$1 web/nimblepkglist.nim" %
[c.webUploadOutput / "nimblepkglist.js"])
proc readSponsors(sponsorsFile: string): seq[Sponsor] =
result = @[]
@@ -464,7 +482,7 @@ const
cmdRst2Html = " rst2html --compileonly $1 -o:web/$2.temp web/$2.rst"
proc buildPage(c: var TConfigData, file, title, rss: string, assetDir = "") =
exec(findNim() & cmdRst2Html % [c.nimArgs, file])
exec(findNim(c) & cmdRst2Html % [c.nimArgs, file])
var temp = "web" / changeFileExt(file, "temp")
var content: string
try:
@@ -472,7 +490,7 @@ proc buildPage(c: var TConfigData, file, title, rss: string, assetDir = "") =
except IOError:
quit("[Error] cannot open: " & temp)
var f: File
var outfile = "web/upload/$#.html" % file
var outfile = c.webUploadOutput / "$#.html" % file
if not existsDir(outfile.splitFile.dir):
createDir(outfile.splitFile.dir)
if open(f, outfile, fmWrite):
@@ -502,27 +520,25 @@ proc buildWebsite(c: var TConfigData) =
let rss = if file in ["news", "index"]: extractFilename(rssUrl) else: ""
if '.' in file: continue
buildPage(c, file, if file == "question": "FAQ" else: file, rss)
copyDir("web/assets", "web/upload/assets")
buildNewsRss(c, "web/upload")
buildSponsors(c, "web/upload")
buildNews(c, "web/news", "web/upload/news")
copyDir("web/assets", c.webUploadOutput / "assets")
buildNewsRss(c, c.webUploadOutput)
buildSponsors(c, c.webUploadOutput)
buildNews(c, "web/news", c.webUploadOutput / "news")
proc onlyDocs(c: var TConfigData) =
createDir(c.docHTMLOutput)
buildDocSamples(c, c.docHTMLOutput)
buildDoc(c, c.docHTMLOutput)
proc main(c: var TConfigData) =
buildWebsite(c)
buildJS("web/upload")
const docup = "web/upload/" & NimVersion
buildJS(c)
let docup = c.webUploadOutput / NimVersion
createDir(docup)
buildAddDoc(c, docup)
buildDocSamples(c, docup)
buildDoc(c, docup)
createDir("doc/html")
buildDocSamples(c, "doc/html")
buildDoc(c, "doc/html")
proc onlyDocs(c: var TConfigData) =
createDir("doc/html")
buildDocSamples(c, "doc/html")
buildDoc(c, "doc/html")
onlyDocs(c)
proc json2(c: var TConfigData) =
const destPath = "web/json2"
@@ -530,8 +546,8 @@ proc json2(c: var TConfigData) =
var i = 0
for d in items(c.srcdoc2):
createDir(destPath / splitFile(d).dir)
commands[i] = findNim() & " jsondoc2 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, gitRepo,
commands[i] = findNim(c) & " jsondoc2 $# --git.url:$# -o:$# --index:on $#" %
[c.nimArgs, c.gitURL,
destPath / changeFileExt(d, "json"), d]
i.inc