diff options
52 files changed, 742 insertions, 261 deletions
diff --git a/compiler.nimble b/compiler.nimble index d949aa754..2a528ea8b 100644 --- a/compiler.nimble +++ b/compiler.nimble @@ -5,7 +5,7 @@ author = "Andreas Rumpf" description = "Compiler package providing the compiler sources as a library." license = "MIT" -InstallDirs = "doc, compiler" +InstallDirs = "compiler" [Deps] Requires: "nim >= 0.14.0" diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index a173095e8..aa0b983ff 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -116,16 +116,18 @@ proc mangleName(m: BModule; s: PSym): Rope = add(result, m.idOrSig(s)) s.loc.r = result + +const + irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation, + tyDistinct, tyRange, tyStatic, tyAlias} + proc typeName(typ: PType): Rope = + let typ = typ.skipTypes(irrelevantForBackend) result = if typ.sym != nil and typ.kind in {tyObject, tyEnum}: typ.sym.name.s.mangle.rope else: ~"TY" -const - irrelevantForBackend = {tyGenericBody, tyGenericInst, tyGenericInvocation, - tyDistinct, tyRange, tyStatic, tyAlias} - proc getTypeName(m: BModule; typ: PType; sig: SigHash): Rope = var t = typ while true: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 2fcc80eda..eca3c6db2 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -589,6 +589,7 @@ proc generateHeaders(m: BModule) = else: addf(m.s[cfsHeaders], "#include $1$N", [rope(it.data)]) it = PStrEntry(it.next) + add(m.s[cfsHeaders], "#undef linux" & tnl) proc initFrame(p: BProc, procname, filename: Rope): Rope = discard cgsym(p.module, "nimFrame") diff --git a/compiler/commands.nim b/compiler/commands.nim index f85e53511..1ddc85b23 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -56,8 +56,8 @@ const "Copyright (c) 2006-" & CompileDate.substr(0, 3) & " by Andreas Rumpf\n" const - Usage = slurp"doc/basicopt.txt".replace("//", "") - AdvancedUsage = slurp"doc/advopt.txt".replace("//", "") + Usage = slurp"../doc/basicopt.txt".replace("//", "") + AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") proc getCommandLineDesc(): string = result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, @@ -331,10 +331,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = nimblePath(path, info) of "nonimblepath", "nobabelpath": expectNoArg(switch, arg, pass, info) - options.gNoNimblePath = true - options.lazyPaths.head = nil - options.lazyPaths.tail = nil - options.lazyPaths.counter = 0 + disableNimblePath() of "excludepath": expectArg(switch, arg, pass, info) let path = processPath(arg, info) diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index bcd9592e6..98c72f862 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -99,3 +99,5 @@ proc initDefines*() = defineSymbol("nimKnowsNimvm") defineSymbol("nimArrIdx") defineSymbol("nimImmediateDeprecated") + defineSymbol("nimNewShiftOps") + defineSymbol("nimDistros") diff --git a/compiler/depends.nim b/compiler/depends.nim index 9087f89f2..e8c295a34 100644 --- a/compiler/depends.nim +++ b/compiler/depends.nim @@ -24,7 +24,7 @@ type var gDotGraph: Rope # the generated DOT file; we need a global variable proc addDependencyAux(importing, imported: string) = - addf(gDotGraph, "$1 -> $2;$n", [rope(importing), rope(imported)]) + addf(gDotGraph, "$1 -> \"$2\";$n", [rope(importing), rope(imported)]) # s1 -> s2_4[label="[0-9]"]; proc addDotDependency(c: PPassContext, n: PNode): PNode = diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 692d9265b..8d4badb4e 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -240,16 +240,22 @@ proc liftIterSym*(n: PNode; owner: PSym): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let hp = getHiddenParam(iter) - let env = newSym(skLet, iter.name, owner, n.info) - env.typ = hp.typ - env.flags = hp.flags - var v = newNodeI(nkVarSection, n.info) - addVar(v, newSymNode(env)) - result.add(v) + var env: PNode + if owner.isIterator: + let it = getHiddenParam(owner) + addUniqueField(it.typ.sons[0], hp) + env = indirectAccess(newSymNode(it), hp, hp.info) + else: + let e = newSym(skLet, iter.name, owner, n.info) + e.typ = hp.typ + e.flags = hp.flags + env = newSymNode(e) + var v = newNodeI(nkVarSection, n.info) + addVar(v, env) + result.add(v) # add 'new' statement: - let envAsNode = env.newSymNode - result.add newCall(getSysSym"internalNew", envAsNode) - result.add makeClosure(iter, envAsNode, n.info) + result.add newCall(getSysSym"internalNew", env) + result.add makeClosure(iter, env, n.info) proc freshVarForClosureIter*(s, owner: PSym): PNode = let envParam = getHiddenParam(owner) diff --git a/compiler/main.nim b/compiler/main.nim index e3ff99870..e6563f281 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -31,11 +31,19 @@ proc semanticPasses = registerPass verbosePass registerPass semPass +proc writeDepsFile(g: ModuleGraph; project: string) = + let f = open(changeFileExt(project, "deps"), fmWrite) + for m in g.modules: + if m != nil: + f.writeLine(toFullPath(m.position.int32)) + f.close() + proc commandGenDepend(graph: ModuleGraph; cache: IdentCache) = semanticPasses() registerPass(gendependPass) - registerPass(cleanupPass) + #registerPass(cleanupPass) compileProject(graph, cache) + writeDepsFile(graph, gProjectFull) generateDot(gProjectFull) execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") & ' ' & changeFileExt(gProjectFull, "dot")) diff --git a/compiler/options.nim b/compiler/options.nim index 50f12d843..e7c9346a7 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -254,6 +254,12 @@ proc removeTrailingDirSep*(path: string): string = else: result = path +proc disableNimblePath*() = + gNoNimblePath = true + lazyPaths.head = nil + lazyPaths.tail = nil + lazyPaths.counter = 0 + include packagehandling proc getNimcacheDir*: string = diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index b9f00399e..a21705208 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -27,7 +27,7 @@ const wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wOverride, wConstructor, wExportNims} converterPragmas* = procPragmas - methodPragmas* = procPragmas+{wBase} + methodPragmas* = procPragmas+{wBase}-{wImportCpp} templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, wDelegator, wExportNims} macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 523ea2e2f..137765ddb 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -71,7 +71,7 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = result = initIdentIter(it, scope.symbols, fn.name) while result != nil: - if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags): + if result.kind == fn.kind and sameType(result.typ, fn.typ, flags): case equalParams(result.typ.n, fn.typ.n) of paramsEqual: if (sfExported notin result.flags) and (sfExported in fn.flags): diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 2fec8c757..641dc3304 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -243,7 +243,16 @@ proc makeAndType*(c: PContext, t1, t2: PType): PType = proc makeOrType*(c: PContext, t1, t2: PType): PType = result = newTypeS(tyOr, c) - result.sons = @[t1, t2] + if t1.kind != tyOr and t2.kind != tyOr: + result.sons = @[t1, t2] + else: + template addOr(t1) = + if t1.kind == tyOr: + for x in t1.sons: result.rawAddSon x + else: + result.rawAddSon t1 + addOr(t1) + addOr(t2) propagateToOwner(result, t1) propagateToOwner(result, t2) result.flags.incl((t1.flags + t2.flags) * {tfHasStatic}) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 45d973d86..54a301322 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -903,7 +903,7 @@ proc makeDeref(n: PNode): PNode = const tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} - tyDotOpTransparent = {tyVar, tyPtr, tyRef} + tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias} proc readTypeParameter(c: PContext, typ: PType, paramName: PIdent, info: TLineInfo): PNode = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ec4279e60..365109249 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -70,7 +70,7 @@ proc toCover(t: PType): BiggestInt = else: result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc})) -proc performProcvarCheck(c: PContext, n: PNode, s: PSym) = +proc performProcvarCheck(c: PContext, info: TLineInfo, s: PSym) = ## Checks that the given symbol is a proper procedure variable, meaning ## that it var smoduleId = getModule(s).id @@ -80,13 +80,17 @@ proc performProcvarCheck(c: PContext, n: PNode, s: PSym) = for module in c.friendModules: if smoduleId == module.id: break outer - localError(n.info, errXCannotBePassedToProcVar, s.name.s) + localError(info, errXCannotBePassedToProcVar, s.name.s) proc semProcvarCheck(c: PContext, n: PNode) = - let n = n.skipConv - if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter, + var n = n.skipConv + if n.kind in nkSymChoices: + for x in n: + if x.sym.kind in {skProc, skMethod, skConverter, skIterator}: + performProcvarCheck(c, n.info, x.sym) + elif n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter, skIterator}: - performProcvarCheck(c, n, n.sym) + performProcvarCheck(c, n.info, n.sym) proc semProc(c: PContext, n: PNode): PNode diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 145d3ff5a..4883479fa 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -12,7 +12,7 @@ import ast, md5 from hashes import Hash from astalgo import debug -from types import typeToString +from types import typeToString, preferDesc from strutils import startsWith, contains when false: @@ -82,6 +82,13 @@ else: result = 0 for x in 0..3: result = (result shl 8) or u.MD5Digest[x].int +type + ConsiderFlag* = enum + CoProc + CoType + CoOwnerSig + +proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) proc hashSym(c: var MD5Context, s: PSym) = if sfAnon in s.flags or s.kind == skGenericParam: @@ -93,6 +100,19 @@ proc hashSym(c: var MD5Context, s: PSym) = c &= "." it = it.owner +proc hashTypeSym(c: var MD5Context, s: PSym) = + if sfAnon in s.flags or s.kind == skGenericParam: + c &= ":anon" + else: + var it = s + while it != nil: + if sfFromGeneric in it.flags and it.kind in routineKinds and + it.typ != nil: + hashType c, it.typ, {CoProc} + c &= it.name.s + c &= "." + it = it.owner + proc hashTree(c: var MD5Context, n: PNode) = if n == nil: c &= "\255" @@ -118,11 +138,6 @@ proc hashTree(c: var MD5Context, n: PNode) = else: for i in 0.. <n.len: hashTree(c, n.sons[i]) -type - ConsiderFlag* = enum - CoProc - CoType - proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = if t == nil: c &= "\254" @@ -163,16 +178,22 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) = # writeStackTrace() # echo "yes ", t.sym.name.s # #quit 1 - c.hashSym(t.sym) + if CoOwnerSig in flags: + c.hashTypeSym(t.sym) + else: + c.hashSym(t.sym) if sfAnon in t.sym.flags: # generated object names can be identical, so we need to # disambiguate furthermore by hashing the field types and names: + # mild hack to prevent endless recursions (makes nimforum compile again): + excl t.sym.flags, sfAnon let n = t.n for i in 0 ..< n.len: assert n[i].kind == nkSym let s = n[i].sym c.hashSym s c.hashType s.typ, flags + incl t.sym.flags, sfAnon else: c &= t.id if t.len > 0 and t.sons[0] != nil: @@ -246,7 +267,7 @@ when defined(debugSigHashes): proc hashType*(t: PType; flags: set[ConsiderFlag] = {CoType}): SigHash = var c: MD5Context md5Init c - hashType c, t, flags + hashType c, t, flags+{CoOwnerSig} md5Final c, result.Md5Digest when defined(debugSigHashes): db.exec(sql"INSERT OR IGNORE INTO sighashes(type, hash) VALUES (?, ?)", diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index a94579339..7f7572968 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -180,7 +180,7 @@ proc sumGeneric(t: PType): int = of tyAlias: t = t.lastSon of tyBool, tyChar, tyEnum, tyObject, tyPointer, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128, - tyUInt..tyUInt64: + tyUInt..tyUInt64, tyCompositeTypeClass: return isvar else: return 0 diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 69249abfe..e0f737f08 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -261,8 +261,9 @@ proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) = proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister = var tmp: TDest = -1 gen(c, n, tmp, flags) - internalAssert tmp >= 0 - result = TRegister(tmp) + #internalAssert tmp >= 0 # 'nim check' does not like this internalAssert. + if tmp >= 0: + result = TRegister(tmp) proc clearDest(c: PCtx; n: PNode; dest: var TDest) {.inline.} = # stmt is different from 'void' in meta programming contexts. diff --git a/doc/manual/ffi.txt b/doc/manual/ffi.txt index d7d9596d2..e9b52eaca 100644 --- a/doc/manual/ffi.txt +++ b/doc/manual/ffi.txt @@ -226,4 +226,8 @@ conjunction with the ``exportc`` pragma: proc exportme(): int {.cdecl, exportc, dynlib.} This is only useful if the program is compiled as a dynamic library via the -``--app:lib`` command line option. +``--app:lib`` command line option. This pragma only has an effect for the code +generation on the Windows target, so when this pragma is forgotten and the dynamic +library is only tested on Mac and/or Linux, there won't be an error. On Windows +this pragma adds ``__declspec(dllexport)`` to the function declaration. + diff --git a/doc/nims.rst b/doc/nims.rst index 12d86a905..967dd4149 100644 --- a/doc/nims.rst +++ b/doc/nims.rst @@ -19,6 +19,7 @@ following modules are available: * `strutils <strutils.html>`_ * `ospaths <ospaths.html>`_ * `math <math.html>`_ +* `distros <distros.html>`_ The `system <system.html>`_ module in NimScript mode additionally supports these operations: `nimscript <nimscript.html>`_. @@ -72,6 +73,10 @@ done: setCommand "nop" +Look at the module `distros <distros.html>`_ for some support of the +OS's native package managers. + + Nimble integration ================== diff --git a/doc/tut1.rst b/doc/tut1.rst index d896a7044..32faf6168 100644 --- a/doc/tut1.rst +++ b/doc/tut1.rst @@ -380,6 +380,28 @@ Since counting up occurs so often in programs, Nim also has a `.. for i in 1..10: ... +Zero-indexed counting have two shortcuts ``..<`` and ``..^`` to simplify counting to one less then the higher index: + +.. code-block:: nim + for i in 0..<10: + ... # 0..9 + +or + +.. code-block:: nim + var s = "some string" + for i in 0..<s.len: + ... + +Other useful iterators for collections (like arrays and sequences) are +* ``items`` and ``mitems``, which provides immutable and mutable elements respectively, and +* ``pairs`` and ``mpairs`` which provides the element and an index number (immutable and mutable respectively) + +.. code-block:: nim + for indx, itm in ["a","b"].pairs: + echo itm, " at index ", indx + # => a at index 0 + # => b at index 1 Scopes and the block statement ------------------------------ @@ -1516,8 +1538,14 @@ Example: A subtle issue with procedural types is that the calling convention of the procedure influences the type compatibility: procedural types are only compatible if they have the same calling convention. The different calling conventions are -listed in the `manual <manual.html>`_. +listed in the `manual <manual.html#types-procedural-type>`_. +Distinct type +------------- +A Distinct type allows for the creation of new type that "does not imply a subtype relationship between it and its base type". +You must EXPLICITLY define all behaviour for the distinct type. +To help with this, both the distinct type and its base type can cast from one type to the other. +Examples are provided in the `manual <manual.html#types-distinct-type>`_. Modules ======= diff --git a/install_nimble.nims b/install_nimble.nims index 6e929f499..e1b665d58 100644 --- a/install_nimble.nims +++ b/install_nimble.nims @@ -1,25 +1,6 @@ -import ospaths - mode = ScriptMode.Verbose echo "This script is deprecated. Use 'koch nimble' instead." -var id = 0 -while dirExists("nimble" & $id): - inc id - -exec "git clone https://github.com/nim-lang/nimble.git nimble" & $id - -withDir "nimble" & $id & "/src": - exec "nim c nimble" - -mkDir "bin/nimblepkg" -for file in listFiles("nimble" & $id & "/src/nimblepkg/"): - cpFile file, "bin/nimblepkg/" & file.extractFilename - -try: - mvFile "nimble" & $id & "/src/nimble".toExe, "bin/nimble".toExe -except OSError: - cpFile "nimble" & $id & "/src/nimble".toExe, "bin/nimble".toExe - +exec "koch nimble" diff --git a/install_tools.nims b/install_tools.nims index f5f320f78..e7f0aee2c 100644 --- a/install_tools.nims +++ b/install_tools.nims @@ -1,20 +1,6 @@ -import ospaths - mode = ScriptMode.Verbose echo "This script is deprecated. Use 'koch tools' instead." -if not dirExists"dist/nimble": - echo "[Error] This script only works for the tarball." -else: - let nimbleExe = "./bin/nimble".toExe - selfExec "c --noNimblePath -p:compiler -o:" & nimbleExe & - " dist/nimble/src/nimble.nim" - - let nimsugExe = "./bin/nimsuggest".toExe - selfExec "c --noNimblePath -d:release -p:compiler -o:" & nimsugExe & - " dist/nimsuggest/nimsuggest.nim" - - let nimgrepExe = "./bin/nimgrep".toExe - selfExec "c -d:release -o:" & nimgrepExe & " tools/nimgrep.nim" +exec "koch tools" diff --git a/koch.nim b/koch.nim index 586565fc7..f117f136c 100644 --- a/koch.nim +++ b/koch.nim @@ -23,7 +23,7 @@ when defined(i386) and defined(windows) and defined(vcc): import os, strutils, parseopt, osproc, streams -const VersionAsString = system.NimVersion #"0.10.2" +const VersionAsString = system.NimVersion const HelpText = """ @@ -75,6 +75,14 @@ proc exe(f: string): string = when defined(windows): result = result.replace('/','\\') +template withDir(dir, body) = + let old = getCurrentDir() + try: + setCurrentDir(dir) + body + finally: + setCurrentdir(old) + proc findNim(): string = var nim = "nim".exe result = "bin" / nim @@ -131,7 +139,7 @@ proc testUnixInstall() = # check the docs build: execCleanPath("./koch web", destDir / "bin") # check nimble builds: - execCleanPath("./bin/nim e install_tools.nims") + execCleanPath("./koch tools") # check the tests work: execCleanPath("./koch tests", destDir / "bin") else: @@ -162,13 +170,11 @@ proc csource(args: string) = proc bundleNimbleSrc() = ## bunldeNimbleSrc() bundles a specific Nimble commit with the tarball. We ## always bundle the latest official release. - if dirExists("dist/nimble/.git"): - exec("git --git-dir dist/nimble/.git pull") - else: + if not dirExists("dist/nimble/.git"): exec("git clone https://github.com/nim-lang/nimble.git dist/nimble") - let tags = execProcess("git --git-dir dist/nimble/.git tag -l v*").splitLines - let tag = tags[^1] - exec("git --git-dir dist/nimble/.git checkout " & tag) + withDir("dist/nimble"): + exec("git checkout -f stable") + exec("git pull") proc bundleNimbleExe() = bundleNimbleSrc() @@ -177,13 +183,13 @@ proc bundleNimbleExe() = nimexec("c dist/nimble/src/nimble.nim") copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe) -proc buildNimble() = - ## buildNimble() builds Nimble for the building via "github". As such, we - ## choose the most recent commit of Nimble too. +proc buildNimble(latest: bool) = + # old installations created nim/nimblepkg/*.nim files. We remove these + # here so that it cannot cause problems (nimble bug #306): + if dirExists("bin/nimblepkg"): + removeDir("bin/nimblepkg") var installDir = "dist/nimble" - if dirExists("dist/nimble/.git"): - exec("git --git-dir dist/nimble/.git pull") - else: + if not dirExists("dist/nimble/.git"): # if dist/nimble exist, but is not a git repo, don't mess with it: if dirExists(installDir): var id = 0 @@ -191,7 +197,13 @@ proc buildNimble() = inc id installDir = "dist/nimble" & $id exec("git clone https://github.com/nim-lang/nimble.git " & installDir) - nimexec("c " & installDir / "src/nimble.nim") + withDir(installDir): + if latest: + exec("git checkout -f master") + else: + exec("git checkout -f stable") + exec("git pull") + nimexec("c --noNimblePath -p:compiler " & installDir / "src/nimble.nim") copyExe(installDir / "src/nimble".exe, "bin/nimble".exe) proc bundleNimsuggest(buildExe: bool) = @@ -227,19 +239,14 @@ proc buildTool(toolname, args: string) = nimexec("cc $# $#" % [args, toolname]) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) -proc buildTools() = +proc buildTools(latest: bool) = let nimsugExe = "bin/nimsuggest".exe nimexec "c --noNimblePath -p:compiler -d:release -o:" & nimsugExe & " tools/nimsuggest/nimsuggest.nim" let nimgrepExe = "bin/nimgrep".exe nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim" - if dirExists"dist/nimble": - let nimbleExe = "bin/nimble".exe - nimexec "c --noNimblePath -p:compiler -o:" & nimbleExe & - " dist/nimble/src/nimble.nim" - else: - buildNimble() + buildNimble(latest) proc nsis(args: string) = bundleNimbleExe() @@ -477,8 +484,8 @@ of cmdArgument: of "test", "tests": tests(op.cmdLineRest) of "temp": temp(op.cmdLineRest) of "winrelease": winRelease() - of "nimble": buildNimble() - of "tools": buildTools() + of "nimble": buildNimble(existsDir(".git")) + of "tools": buildTools(existsDir(".git")) of "pushcsource", "pushcsources": pushCsources() else: showHelp() of cmdEnd: showHelp() diff --git a/lib/core/macros.nim b/lib/core/macros.nim index b0ef54397..3adf4670d 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -80,7 +80,7 @@ type NimNodeKinds* = set[NimNodeKind] NimTypeKind* = enum # some types are no longer used, see ast.nim ntyNone, ntyBool, ntyChar, ntyEmpty, - ntyArrayConstr, ntyNil, ntyExpr, ntyStmt, + ntyAlias, ntyNil, ntyExpr, ntyStmt, ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst, ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal, ntyArray, ntyObject, ntyTuple, ntySet, diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index 1367bc411..b72596060 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -254,8 +254,14 @@ when defined(windows) or defined(nimdoc): "Operation performed on a socket which has not been registered with" & " the dispatcher yet.") + proc hasPendingOperations*(): bool = + ## Returns `true` if the global dispatcher has pending operations. + let p = getGlobalDispatcher() + p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0 + proc poll*(timeout = 500) = - ## Waits for completion events and processes them. + ## Waits for completion events and processes them. Raises ``ValueError`` + ## if there are no pending operations. let p = getGlobalDispatcher() if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0: raise newException(ValueError, @@ -1056,8 +1062,15 @@ else: newCBs.add(cb) callbacks = newCBs & callbacks + proc hasPendingOperations*(): bool = + let p = getGlobalDispatcher() + p.selector.len != 0 or p.timers.len != 0 or p.callbacks.len != 0 + proc poll*(timeout = 500) = let p = getGlobalDispatcher() + if p.selector.len == 0 and p.timers.len == 0 and p.callbacks.len == 0: + raise newException(ValueError, + "No handles or timers registered in dispatcher.") if p.selector.len > 0: for info in p.selector.select(p.adjustedTimeout(timeout)): diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 3b64c278f..5ad3b5263 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -36,12 +36,14 @@ ## proc processClient(client: AsyncSocket) {.async.} = ## while true: ## let line = await client.recvLine() +## if line.len == 0: break ## for c in clients: ## await c.send(line & "\c\L") ## ## proc serve() {.async.} = ## clients = @[] ## var server = newAsyncSocket() +## server.setSockOpt(OptReuseAddr, true) ## server.bindAddr(Port(12345)) ## server.listen() ## diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim new file mode 100644 index 000000000..ff30f6134 --- /dev/null +++ b/lib/pure/distros.nim @@ -0,0 +1,244 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2016 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module implements the basics for Linux distribution ("distro") +## detection and the OS's native package manager. Its primary purpose is to +## produce output for Nimble packages like:: +## +## To complete the installation, run: +## +## sudo apt-get libblas-dev +## sudo apt-get libvoodoo +## +## The above output could be the result of a code snippet like: +## +## .. code-block:: nim +## +## if detectOs(Ubuntu): +## foreignDep "lbiblas-dev" +## foreignDep "libvoodoo" +## + +from strutils import contains, toLowerAscii + +when not defined(nimscript): + from osproc import execProcess + +type + Distribution* {.pure.} = enum ## the list of known distributions + Windows ## some version of Windows + Posix ## some Posix system + MacOSX ## some version of OSX + Linux ## some version of Linux + Ubuntu + Debian + Gentoo + Fedora + RedHat + + OpenSUSE + Manjaro + Elementary + Zorin + CentOS + Deepin + ArchLinux + Antergos + PCLinuxOS + Mageia + LXLE + Solus + Lite + Slackware + Androidx86 + Puppy + Peppermint + Tails + AntiX + Kali + SparkyLinux + Apricity + BlackLab + Bodhi + TrueOS + ArchBang + KaOS + WattOS + Korora + Simplicity + RemixOS + OpenMandriva + Netrunner + Alpine + BlackArch + Ultimate + Gecko + Parrot + KNOPPIX + GhostBSD + Sabayon + Salix + Q4OS + ClearOS + Container + ROSA + Zenwalk + Parabola + ChaletOS + BackBox + MXLinux + Vector + Maui + Qubes + RancherOS + Oracle + TinyCore + Robolinux + Trisquel + Voyager + Clonezilla + SteamOS + Absolute + NixOS + AUSTRUMI + Arya + Porteus + AVLinux + Elive + Bluestar + SliTaz + Solaris + Chakra + Wifislax + Scientific + ExTiX + Rockstor + GoboLinux + + BSD + FreeBSD + OpenBSD + DragonFlyBSD + + +const + LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware, + Distribution.ArchLinux} + +var unameRes, releaseRes: string ## we cache the result of the 'uname -a' + ## execution for faster platform detections. + +template unameRelease(cmd, cache): untyped = + if cache.len == 0: + cache = (when defined(nimscript): gorge(cmd) else: execProcess(cmd)) + cache + +template uname(): untyped = unameRelease("uname -a", unameRes) +template release(): untyped = unameRelease("lsb_release -a", releaseRes) + +proc detectOsImpl(d: Distribution): bool = + case d + of Distribution.Windows: ## some version of Windows + result = defined(windows) + of Distribution.Posix: result = defined(posix) + of Distribution.MacOSX: result = defined(macosx) + of Distribution.Linux: result = defined(linux) + of Distribution.Ubuntu, Distribution.Gentoo, Distribution.FreeBSD, + Distribution.OpenBSD: + result = ("-" & $d & " ") in uname() + of Distribution.RedHat: + result = "Red Hat" in uname() + of Distribution.BSD: result = defined(bsd) + of Distribution.ArchLinux: + result = "arch" in toLowerAscii(uname()) + of Distribution.OpenSUSE: + result = "suse" in toLowerAscii(uname()) + of Distribution.GoboLinux: + result = "-Gobo " in uname() + of Distribution.OpenMandriva: + result = "mandriva" in toLowerAscii(uname()) + of Distribution.Solaris: + let uname = toLowerAscii(uname()) + result = ("sun" in uname) or ("solaris" in uname) + else: + let dd = toLowerAscii($d) + result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) + +template detectOs*(d: untyped): bool = + ## Distro/OS detection. For convenience the + ## required ``Distribution.`` qualifier is added to the + ## enum value. + detectOsImpl(Distribution.d) + +when not defined(nimble): + var foreignDeps: seq[string] = @[] + +proc foreignCmd*(cmd: string; requiresSudo=false) = + ## Registers a foreign command to the intern list of commands + ## that can be queried later. + let c = (if requiresSudo: "sudo " else: "") & cmd + when defined(nimble): + nimscriptapi.foreignDeps.add(c) + else: + foreignDeps.add(c) + +proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) = + ## Returns the distro's native command line to install 'foreignPackageName' + ## and whether it requires root/admin rights. + let p = foreignPackageName + when defined(windows): + result = ("Chocolatey install " & p, false) + elif defined(bsd): + result = ("ports install " & p, true) + elif defined(linux): + if detectOs(Ubuntu) or detectOs(Elementary) or detectOs(Debian) or + detectOs(KNOPPIX) or detectOs(SteamOS): + result = ("apt-get install " & p, true) + elif detectOs(Gentoo): + result = ("emerge install " & p, true) + elif detectOs(Fedora): + result = ("yum install " & p, true) + elif detectOs(RedHat): + result = ("rpm install " & p, true) + elif detectOs(OpenSUSE): + result = ("yast -i " & p, true) + elif detectOs(Slackware): + result = ("installpkg " & p, true) + elif detectOs(OpenMandriva): + result = ("urpmi " & p, true) + elif detectOs(ZenWalk): + result = ("netpkg install " & p, true) + elif detectOs(NixOS): + result = ("nix-env -i " & p, false) + elif detectOs(Solaris): + result = ("pkg install " & p, true) + elif detectOs(PCLinuxOS): + result = ("rpm -ivh " & p, true) + elif detectOs(ArchLinux): + result = ("pacman -S " & p, true) + else: + result = ("<your package manager here> install " & p, true) + else: + result = ("brew install " & p, true) + +proc foreignDep*(foreignPackageName: string) = + ## Registers 'foreignPackageName' to the internal list of foreign deps. + ## It is your job to ensure the package name + let (installCmd, sudo) = foreignDepInstallCmd(foreignPackageName) + foreignCmd installCmd, sudo + +proc echoForeignDeps*() = + ## Writes the list of registered foreign deps to stdout. + for d in foreignDeps: + echo d + +when false: + foreignDep("libblas-dev") + foreignDep "libfoo" + echoForeignDeps() diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim index 5a23169d4..6f80d56ef 100644 --- a/lib/pure/endians.nim +++ b/lib/pure/endians.nim @@ -10,38 +10,87 @@ ## This module contains helpers that deal with different byte orders ## (`endian`:idx:). -proc swapEndian64*(outp, inp: pointer) = - ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to - ## contain at least 8 bytes. - var i = cast[cstring](inp) - var o = cast[cstring](outp) - o[0] = i[7] - o[1] = i[6] - o[2] = i[5] - o[3] = i[4] - o[4] = i[3] - o[5] = i[2] - o[6] = i[1] - o[7] = i[0] - -proc swapEndian32*(outp, inp: pointer) = - ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to - ## contain at least 4 bytes. - var i = cast[cstring](inp) - var o = cast[cstring](outp) - o[0] = i[3] - o[1] = i[2] - o[2] = i[1] - o[3] = i[0] - -proc swapEndian16*(outp, inp: pointer) = - ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to - ## contain at least 2 bytes. - var - i = cast[cstring](inp) - o = cast[cstring](outp) - o[0] = i[1] - o[1] = i[0] +when defined(gcc) or defined(llvm_gcc) or defined(clang): + const useBuiltinSwap = true + proc builtin_bswap16(a: uint16): uint16 {. + importc: "__builtin_bswap16", nodecl, nosideeffect.} + + proc builtin_bswap32(a: uint32): uint32 {. + importc: "__builtin_bswap32", nodecl, nosideeffect.} + + proc builtin_bswap64(a: uint64): uint64 {. + importc: "__builtin_bswap64", nodecl, nosideeffect.} +elif defined(icc): + const useBuiltinSwap = true + proc builtin_bswap16(a: uint16): uint16 {. + importc: "_bswap16", nodecl, nosideeffect.} + + proc builtin_bswap32(a: uint32): uint32 {. + importc: "_bswap", nodecl, nosideeffect.} + + proc builtin_bswap64(a: uint64): uint64 {. + importc: "_bswap64", nodecl, nosideeffect.} +elif defined(vcc): + const useBuiltinSwap = true + proc builtin_bswap16(a: uint16): uint16 {. + importc: "_byteswap_ushort", nodecl, header: "<intrin.h>", nosideeffect.} + + proc builtin_bswap32(a: uint32): uint32 {. + importc: "_byteswap_ulong", nodecl, header: "<intrin.h>", nosideeffect.} + + proc builtin_bswap64(a: uint64): uint64 {. + importc: "_byteswap_uint64", nodecl, header: "<intrin.h>", nosideeffect.} +else: + const useBuiltinSwap = false + +when useBuiltinSwap: + proc swapEndian64*(outp, inp: pointer) {.inline, nosideeffect.}= + var i = cast[ptr uint64](inp) + var o = cast[ptr uint64](outp) + o[] = builtin_bswap64(i[]) + + proc swapEndian32*(outp, inp: pointer) {.inline, nosideeffect.}= + var i = cast[ptr uint32](inp) + var o = cast[ptr uint32](outp) + o[] = builtin_bswap32(i[]) + + proc swapEndian16*(outp, inp: pointer) {.inline, nosideeffect.}= + var i = cast[ptr uint16](inp) + var o = cast[ptr uint16](outp) + o[] = builtin_bswap16(i[]) + +else: + proc swapEndian64*(outp, inp: pointer) = + ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to + ## contain at least 8 bytes. + var i = cast[cstring](inp) + var o = cast[cstring](outp) + o[0] = i[7] + o[1] = i[6] + o[2] = i[5] + o[3] = i[4] + o[4] = i[3] + o[5] = i[2] + o[6] = i[1] + o[7] = i[0] + + proc swapEndian32*(outp, inp: pointer) = + ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to + ## contain at least 4 bytes. + var i = cast[cstring](inp) + var o = cast[cstring](outp) + o[0] = i[3] + o[1] = i[2] + o[2] = i[1] + o[3] = i[0] + + proc swapEndian16*(outp, inp: pointer) = + ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to + ## contain at least 2 bytes. + var i = cast[cstring](inp) + var o = cast[cstring](outp) + o[0] = i[1] + o[1] = i[0] when system.cpuEndian == bigEndian: proc littleEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp) diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 4ef169b4f..a8432b6f0 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -213,7 +213,7 @@ when not defined(JS): ## .. code-block:: nim ## echo ceil(-2.1) ## -2.0 - when defined(windows) and defined(vcc): + when defined(windows) and (defined(vcc) or defined(bcc)): # MSVC 2010 don't have trunc/truncf # this implementation was inspired by Go-lang Math.Trunc proc truncImpl(f: float64): float64 = diff --git a/lib/pure/os.nim b/lib/pure/os.nim index f077e798a..8a5461567 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1427,7 +1427,7 @@ elif defined(windows): if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) return TaintedString(ownArgv[i]) -elif not defined(createNimRtl): +elif not defined(createNimRtl) and not(defined(posix) and appType == "lib"): # On Posix, there is no portable way to get the command line from a DLL. var cmdCount {.importc: "cmdCount".}: cint diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 99fdb5b0e..39d46c675 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -70,7 +70,7 @@ when defined(posix) and not defined(JS): elif defined(windows): import winlean - when defined(vcc): + when defined(vcc) or defined(bcc): # newest version of Visual C++ defines time_t to be of 64 bits type TimeImpl {.importc: "time_t", header: "<time.h>".} = int64 # visual c's c runtime exposes these under a different name diff --git a/lib/pure/xmldom.nim b/lib/pure/xmldom.nim index 559f45348..3c891c81b 100644 --- a/lib/pure/xmldom.nim +++ b/lib/pure/xmldom.nim @@ -890,7 +890,7 @@ proc tagName*(el: PElement): string = return el.fTagName # Procedures -proc getAttribute*(el: PElement, name: string): string = +proc getAttribute*(el: PNode, name: string): string = ## Retrieves an attribute value by ``name`` if isNil(el.attributes): return nil @@ -900,7 +900,7 @@ proc getAttribute*(el: PElement, name: string): string = else: return nil -proc getAttributeNS*(el: PElement, namespaceURI: string, localName: string): string = +proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string = ## Retrieves an attribute value by ``localName`` and ``namespaceURI`` if isNil(el.attributes): return nil diff --git a/lib/system.nim b/lib/system.nim index 8209dbc23..309df7f84 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -551,8 +551,6 @@ type ## ## See the full `exception hierarchy`_. - TResult* {.deprecated.} = enum Failure, Success - {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect, FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect, FWriteIO: WriteIOEffect, FExecIO: ExecIOEffect, @@ -870,29 +868,43 @@ when defined(nimnomagic64): else: proc `mod` *(x, y: int64): int64 {.magic: "ModI64", noSideEffect.} -proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int64): int64 {.magic: "ShrI", noSideEffect.} - ## computes the `shift right` operation of `x` and `y`, filling - ## vacant bit positions with zeros. - ## - ## .. code-block:: Nim - ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 - ## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8 - ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 - -proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int64): int64 {.magic: "ShlI", noSideEffect.} - ## computes the `shift left` operation of `x` and `y`. - ## - ## .. code-block:: Nim - ## 1'i32 shl 4 == 0x0000_0010 - ## 1'i64 shl 4 == 0x0000_0000_0000_0010 +when defined(nimNewShiftOps): + proc `shr` *(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect.} + proc `shr` *(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect.} + ## computes the `shift right` operation of `x` and `y`, filling + ## vacant bit positions with zeros. + ## + ## .. code-block:: Nim + ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 + ## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8 + ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 + + + proc `shl` *(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.} + proc `shl` *(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.} + ## computes the `shift left` operation of `x` and `y`. + ## + ## .. code-block:: Nim + ## 1'i32 shl 4 == 0x0000_0010 + ## 1'i64 shl 4 == 0x0000_0000_0000_0010 +else: + proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.} + proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.} + proc `shr` *(x, y: int64): int64 {.magic: "ShrI", noSideEffect.} + + proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.} + proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.} + proc `shl` *(x, y: int64): int64 {.magic: "ShlI", noSideEffect.} proc `and` *(x, y: int): int {.magic: "BitandI", noSideEffect.} proc `and` *(x, y: int8): int8 {.magic: "BitandI", noSideEffect.} @@ -993,11 +1005,18 @@ proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.} proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.} ## computes the `bitwise complement` of the integer `x`. -proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.} - ## computes the `shift right` operation of `x` and `y`. +when defined(nimNewShiftOps): + proc `shr`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShrI", noSideEffect.} + ## computes the `shift right` operation of `x` and `y`. + + proc `shl`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShlI", noSideEffect.} + ## computes the `shift left` operation of `x` and `y`. +else: + proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.} + ## computes the `shift right` operation of `x` and `y`. -proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.} - ## computes the `shift left` operation of `x` and `y`. + proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.} + ## computes the `shift left` operation of `x` and `y`. proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.} ## computes the `bitwise and` of numbers `x` and `y`. @@ -2706,8 +2725,9 @@ when not defined(JS): #and not defined(nimscript): when defined(windows): # work-around C's sucking abstraction: # BUGFIX: stdin and stdout should be binary files! - proc c_setmode(handle, mode: cint) {.importc: "_setmode", - header: "<io.h>".} + proc c_setmode(handle, mode: cint) {. + importc: when defined(bcc): "setmode" else: "_setmode", + header: "<io.h>".} var O_BINARY {.importc: "O_BINARY", nodecl.}: cint diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 5b0955132..3b886b2fc 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -276,10 +276,11 @@ proc pageAddr(p: pointer): PChunk {.inline.} = #sysAssert(Contains(allocator.chunkStarts, pageIndex(result))) proc requestOsChunks(a: var MemRegion, size: int): PBigChunk = - if not a.blockChunkSizeIncrease: - a.nextChunkSize = - if a.currMem < 64 * 1024: PageSize*4 - else: a.nextChunkSize*2 + when not defined(emscripten): + if not a.blockChunkSizeIncrease: + a.nextChunkSize = + if a.currMem < 64 * 1024: PageSize*4 + else: a.nextChunkSize*2 var size = size if size > a.nextChunkSize: diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim index 29466c34d..f675a9472 100644 --- a/lib/system/nimscript.nim +++ b/lib/system/nimscript.nim @@ -293,26 +293,28 @@ template task*(name: untyped; description: string; body: untyped): untyped = setCommand "nop" `name Task`() -var - packageName* = "" ## Nimble support: Set this to the package name. It - ## is usually not required to do that, nims' filename is - ## the default. - version*: string ## Nimble support: The package's version. - author*: string ## Nimble support: The package's author. - description*: string ## Nimble support: The package's description. - license*: string ## Nimble support: The package's license. - srcDir*: string ## Nimble support: The package's source directory. - binDir*: string ## Nimble support: The package's binary directory. - backend*: string ## Nimble support: The package's backend. - - skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*, - installExt*, bin*: seq[string] = @[] ## Nimble metadata. - requiresData*: seq[string] = @[] ## Exposes the list of requirements for read - ## and write accesses. - -proc requires*(deps: varargs[string]) = - ## Nimble support: Call this to set the list of requirements of your Nimble - ## package. - for d in deps: requiresData.add(d) +when not defined(nimble): + # nimble has its own implementation for these things. + var + packageName* = "" ## Nimble support: Set this to the package name. It + ## is usually not required to do that, nims' filename is + ## the default. + version*: string ## Nimble support: The package's version. + author*: string ## Nimble support: The package's author. + description*: string ## Nimble support: The package's description. + license*: string ## Nimble support: The package's license. + srcDir*: string ## Nimble support: The package's source directory. + binDir*: string ## Nimble support: The package's binary directory. + backend*: string ## Nimble support: The package's backend. + + skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*, + installExt*, bin*: seq[string] = @[] ## Nimble metadata. + requiresData*: seq[string] = @[] ## Exposes the list of requirements for read + ## and write accesses. + + proc requires*(deps: varargs[string]) = + ## Nimble support: Call this to set the list of requirements of your Nimble + ## package. + for d in deps: requiresData.add(d) {.pop.} diff --git a/lib/upcoming/asyncdispatch.nim b/lib/upcoming/asyncdispatch.nim index ca5c1f64c..78c7afffc 100644 --- a/lib/upcoming/asyncdispatch.nim +++ b/lib/upcoming/asyncdispatch.nim @@ -231,8 +231,14 @@ when defined(windows) or defined(nimdoc): "Operation performed on a socket which has not been registered with" & " the dispatcher yet.") + proc hasPendingOperations*(): bool = + ## Returns `true` if the global dispatcher has pending operations. + let p = getGlobalDispatcher() + p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0 + proc poll*(timeout = 500) = - ## Waits for completion events and processes them. + ## Waits for completion events and processes them. Raises ``ValueError`` + ## if there are no pending operations. let p = getGlobalDispatcher() if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0: raise newException(ValueError, @@ -1182,6 +1188,10 @@ else: raise newException(ValueError, "File descriptor not registered.") p.selector.updateHandle(fd.SocketHandle, newEvents) + proc hasPendingOperations*(): bool = + let p = getGlobalDispatcher() + not p.selector.isEmpty() or p.timers.len != 0 or p.callbacks.len != 0 + proc poll*(timeout = 500) = var keys: array[64, ReadyKey[AsyncData]] diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 2441c7267..bb0e7a648 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -790,7 +790,7 @@ const IOC_WS2* = 0x08000000 IOC_INOUT* = IOC_IN or IOC_OUT -template WSAIORW*(x,y): expr = (IOC_INOUT or x or y) +template WSAIORW*(x,y): untyped = (IOC_INOUT or x or y) const SIO_GET_EXTENSION_FUNCTION_POINTER* = WSAIORW(IOC_WS2,6).DWORD diff --git a/tests/async/tpendingcheck.nim b/tests/async/tpendingcheck.nim new file mode 100644 index 000000000..825acb613 --- /dev/null +++ b/tests/async/tpendingcheck.nim @@ -0,0 +1,21 @@ +discard """ + file: "tpendingcheck.nim" + exitcode: 0 + output: "" +""" + +import asyncdispatch + +doAssert(not hasPendingOperations()) + +proc test() {.async.} = + await sleepAsync(100) + +var f = test() +while not f.finished: + doAssert(hasPendingOperations()) + poll(10) +f.read + +doAssert(not hasPendingOperations()) + diff --git a/tests/async/tupcoming_async.nim b/tests/async/tupcoming_async.nim index 7d255f213..9cdc6fd0a 100644 --- a/tests/async/tupcoming_async.nim +++ b/tests/async/tupcoming_async.nim @@ -1,4 +1,5 @@ discard """ + cmd: "nim c -r -f $file" output: ''' OK OK diff --git a/tests/ccgbugs/tsighash_typename_regression.nim b/tests/ccgbugs/tsighash_typename_regression.nim new file mode 100644 index 000000000..7122902d9 --- /dev/null +++ b/tests/ccgbugs/tsighash_typename_regression.nim @@ -0,0 +1,10 @@ +# bug #5147 + +proc foo[T](t: T) = + type Wrapper = object + get: T + let w = Wrapper(get: t) + echo w.get + +foo(123) +foo("baz") diff --git a/tests/cpp/tembarrassing_generic_failure.nim b/tests/cpp/tembarrassing_generic_failure.nim new file mode 100644 index 000000000..3c31dcdb8 --- /dev/null +++ b/tests/cpp/tembarrassing_generic_failure.nim @@ -0,0 +1,8 @@ +discard """ + cmd: "nim cpp --threads:on $file" +""" + +# bug #5142 + +var ci: Channel[int] +ci.open diff --git a/tests/enum/tenumalias.nim b/tests/enum/tenumalias.nim new file mode 100644 index 000000000..2d1f70d0e --- /dev/null +++ b/tests/enum/tenumalias.nim @@ -0,0 +1,7 @@ +# bug #5148 + +type + A = enum foo, bar + B = A + +echo B.foo diff --git a/tests/errmsgs/tcannot_capture_builtin.nim b/tests/errmsgs/tcannot_capture_builtin.nim new file mode 100644 index 000000000..3b8aae241 --- /dev/null +++ b/tests/errmsgs/tcannot_capture_builtin.nim @@ -0,0 +1,8 @@ +discard """ +errormsg: "'+' cannot be passed to a procvar" +line: 8 +""" + +# bug #2050 + +let v: proc (a, b: int): int = `+` diff --git a/tests/iter/t2closureiters.nim b/tests/iter/t2closureiters.nim new file mode 100644 index 000000000..ceb24548c --- /dev/null +++ b/tests/iter/t2closureiters.nim @@ -0,0 +1,14 @@ +discard """ + output: '''1''' +""" +# bug #3837 + +iterator t1(): int {.closure.} = + yield 1 + +iterator t2(): int {.closure.} = + for i in t1(): + yield i + +for i in t2(): + echo $i diff --git a/tools/finish.nim b/tools/finish.nim index cac001d79..afb3d9fc1 100644 --- a/tools/finish.nim +++ b/tools/finish.nim @@ -85,14 +85,33 @@ when defined(windows): let arch = execProcess(gccExe, ["-dumpmachine"], nil, {poStdErrToStdOut, poUsePath}) when hostCPU == "i386": - result = arch.startsWith("i686-") + result = arch.contains("i686-") elif hostCPU == "amd64": - result = arch.startsWith("x86_64-") + result = arch.contains("x86_64-") else: {.error: "Unknown CPU for Windows.".} except OSError, IOError: result = false + proc defaultMingwLocations(): seq[string] = + proc probeDir(dir: string; result: var seq[string]) = + for k, x in walkDir(dir, relative=true): + if k in {pcDir, pcLinkToDir}: + if x.contains("mingw") or x.contains("posix"): + let dest = dir / x + probeDir(dest, result) + result.add(dest) + + result = @["dist/mingw", "../mingw", r"C:\mingw"] + let pfx86 = getEnv("programfiles(x86)") + let pf = getEnv("programfiles") + when hostCPU == "i386": + probeDir(pfx86, result) + probeDir(pf, result) + else: + probeDir(pf, result) + probeDir(pfx86, result) + proc tryDirs(incompat: var seq[string]; dirs: varargs[string]): string = let bits = $(sizeof(pointer)*8) for d in dirs: @@ -132,7 +151,7 @@ proc main() = addToPathEnv(desiredPath) if mingWchoices.len == 0: # No mingw in path, so try a few locations: - let alternative = tryDirs(incompat, "dist/mingw", "../mingw", r"C:\mingw") + let alternative = tryDirs(incompat, defaultMingwLocations()) if alternative.len == 0: if incompat.len > 0: echo "The following *incompatible* MingW installations exist" diff --git a/tools/niminst/buildsh.tmpl b/tools/niminst/buildsh.tmpl index c571f4d66..aaefa88c6 100644 --- a/tools/niminst/buildsh.tmpl +++ b/tools/niminst/buildsh.tmpl @@ -126,6 +126,8 @@ case $ucpu in mycpu="mips" ;; *arm*|*armv6l* ) mycpu="arm" ;; + *aarch64* ) + mycpu="arm64" ;; *) echo 2>&1 "Error: unknown processor: $ucpu" exit 1 diff --git a/tools/niminst/install.tmpl b/tools/niminst/install.tmpl index d72b132ef..91504891d 100644 --- a/tools/niminst/install.tmpl +++ b/tools/niminst/install.tmpl @@ -3,35 +3,7 @@ # result = "#! /bin/sh\n# Generated by niminst\n" # var proj = c.name.toLowerAscii -## Current directory you start script from -BASE_DIR=$(pwd) - -## The following one-liner takes directory path which contains install script. -## `command -v -- "$0"` takes path if script sourced from interactive shell -## `dirname` returns relative directory path to install script -## `cd -P` dive into directory to use `pwd` -## `pwd -P` prints full path to install script directory path -## -P option allows to use symlinks in path -## Good explanation can be found here: -## http://stackoverflow.com/questions/29832037/how-to-get-script-directory-in-posix-sh -NIM_DIR=$(cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P) - -go_back() { - cd $BASE_DIR -} - -## Go to base dir on exit -trap go_back EXIT - -install_error() { - echo "Nim installation failed!" - exit 1 -} - -## Exit if any command failed -trap install_error ERR ## `set -e` alternative - -cd $NIM_DIR +set -e if [ $# -eq 1 ] ; then # if c.cat[fcUnixBin].len > 0: diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim index e0b8ad9b3..e7e978dc0 100644 --- a/tools/niminst/niminst.nim +++ b/tools/niminst/niminst.nim @@ -14,7 +14,8 @@ when haveZipLib: import zipfiles import - os, osproc, strutils, parseopt, parsecfg, strtabs, streams, debcreation + os, osproc, strutils, parseopt, parsecfg, strtabs, streams, debcreation, + securehash const maxOS = 20 # max number of OSes @@ -476,23 +477,23 @@ proc writeFile(filename, content, newline: string) = else: quit("Cannot open for writing: " & filename) -proc removeDuplicateFiles(c: var ConfigData) = - for osA in countdown(c.oses.len, 1): - for cpuA in countdown(c.cpus.len, 1): +proc deduplicateFiles(c: var ConfigData) = + var tab = newStringTable() + let build = getOutputDir(c) + for osA in countup(1, c.oses.len): + for cpuA in countup(1, c.cpus.len): if c.cfiles[osA][cpuA].isNil: c.cfiles[osA][cpuA] = @[] if c.explicitPlatforms and not c.platforms[osA][cpuA]: continue - for i in 0..c.cfiles[osA][cpuA].len-1: - var dup = c.cfiles[osA][cpuA][i] - var f = extractFilename(dup) - for osB in 1..c.oses.len: - for cpuB in 1..c.cpus.len: - if osB != osA or cpuB != cpuA: - var orig = buildDir(osB, cpuB) / f - if existsFile(orig) and existsFile(dup) and - sameFileContent(orig, dup): - # file is identical, so delete duplicate: - removeFile(dup) - c.cfiles[osA][cpuA][i] = orig + for dup in mitems(c.cfiles[osA][cpuA]): + let key = $secureHashFile(build / dup) + let val = build / buildDir(osA, cpuA) / extractFilename(dup) + let orig = tab.getOrDefault(key) + if orig.len > 0: + # file is identical, so delete duplicate: + removeFile(dup) + dup = orig + else: + tab[key] = val proc writeInstallScripts(c: var ConfigData) = if c.installScript: @@ -536,7 +537,7 @@ proc srcdist(c: var ConfigData) = copyFile(dest=dest, source=c.cfiles[osA][cpuA][i]) c.cfiles[osA][cpuA][i] = relDest # second pass: remove duplicate files - removeDuplicateFiles(c) + deduplicateFiles(c) writeFile(getOutputDir(c) / buildShFile, generateBuildShellScript(c), "\10") inclFilePermissions(getOutputDir(c) / buildShFile, {fpUserExec, fpGroupExec, fpOthersExec}) writeFile(getOutputDir(c) / makeFile, generateMakefile(c), "\10") diff --git a/tools/trimcc.nim b/tools/trimcc.nim index 276ea1dbe..959eaf310 100644 --- a/tools/trimcc.nim +++ b/tools/trimcc.nim @@ -1,6 +1,6 @@ # Trim C compiler installation to a minimum -import strutils, os, pegs, strtabs, math, threadpool, times +import strutils, os, pegs, strtabs, math, times const Essential = """gcc.exe g++.exe gdb.exe ld.exe as.exe c++.exe cpp.exe cc1.exe @@ -20,7 +20,7 @@ proc includes(headerpath, headerfile: string, whitelist: StringTableRef) = comment <- '/*' @ '*/' / '//' .* ws <- (comment / \s+)* """: let m = matches[0].extractFilename - if whitelist[m] != "processed": + if whitelist.getOrDefault(m) != "processed": whitelist[m] = "found" proc processIncludes(dir: string, whitelist: StringTableRef) = @@ -29,10 +29,10 @@ proc processIncludes(dir: string, whitelist: StringTableRef) = of pcFile: let name = extractFilename(path) if ('.' notin name and "include" in path) or ("c++" in path): - let n = whitelist[name] + let n = whitelist.getOrDefault(name) if n != "processed": whitelist[name] = "found" if name.endswith(".h"): - let n = whitelist[name] + let n = whitelist.getOrDefault(name) if n == "found": includes(path, name, whitelist) of pcDir: processIncludes(path, whitelist) else: discard @@ -72,8 +72,8 @@ proc newName(f: string): string = proc ccStillWorks(): bool = const c1 = r"nim c --verbosity:0 --force_build koch" - c2 = r"nim c --verbosity:0 --force_build --threads:on --out:tempOne.exe trimcc" - c3 = r"nim c --verbosity:0 --force_build --threads:on --out:tempTwo.exe fakeDeps" + c2 = r"nim c --verbosity:0 --force_build --threads:on --out:tempOne.exe tools/trimcc" + c3 = r"nim c --verbosity:0 --force_build --threads:on --out:tempTwo.exe tools/fakeDeps" c4 = r".\koch.exe" c5 = r".\tempOne.exe" c6 = r".\tempTwo.exe" diff --git a/web/community.rst b/web/community.rst index 9ce87b546..1e4faff91 100644 --- a/web/community.rst +++ b/web/community.rst @@ -97,7 +97,7 @@ Nim's Community Meetup ------ - + The `Nim BR Meetup <http://www.meetup.com/pt-BR/nim-br>`_ is a brazilian user group about Nim where they are having discussions, talks or workshops about Nim programming language. .. container:: standout @@ -132,7 +132,7 @@ Nim's Community BountySource .. raw:: html - + <img src="https://img.shields.io/bountysource/team/mozilla-core/activity.svg"> Paypal @@ -140,10 +140,11 @@ Nim's Community <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top"> <input type="hidden" name="cmd" value="_s-xclick"> - <input type="hidden" name="hosted_button_id" value="ZQC6CVEEYNTLN"> - <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"> - <img alt="" border="0" src="https://www.paypalobjects.com/de_DE/i/scr/pixel.gif" width="1" height="1"> + <input type="hidden" name="hosted_button_id" value="C6PBFRF4WDR2E"> + <input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online!"> + <img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1"> </form> + Bitcoin Bitcoin address: 1BXfuKM2uvoD6mbx4g5xM3eQhLzkCK77tJ diff --git a/web/news/e029_version_0_16_0.rst b/web/news/e029_version_0_16_0.rst index 4f5571256..a1cc54417 100644 --- a/web/news/e029_version_0_16_0.rst +++ b/web/news/e029_version_0_16_0.rst @@ -43,6 +43,10 @@ Library Additions ``terminalWidthIoctl`` and ``terminalSize`` to the ``terminal`` `(doc) <http://nim-lang.org/docs/terminal.html>`_ module. +- Added new module ``distros`` + `(doc) <http://nim-lang.org/docs/distros.html>`_ that can be used in Nimble + packages to aid in supporting the OS's native package managers. + Tool Additions -------------- @@ -51,6 +55,10 @@ Tool Additions Compiler Additions ------------------ +- The C/C++ code generator has been rewritten to use stable + name mangling rules. This means that compile times for + edit-compile-run cycles are much reduced. + Language Additions ------------------ diff --git a/web/website.ini b/web/website.ini index 3b8203cc0..b929712bf 100644 --- a/web/website.ini +++ b/web/website.ini @@ -62,7 +62,7 @@ srcdoc2: "pure/nativesockets;pure/asynchttpserver;pure/net;pure/selectors;pure/f srcdoc2: "deprecated/pure/ftpclient" srcdoc2: "pure/asyncfile;pure/asyncftpclient" srcdoc2: "pure/md5;pure/rationals" -srcdoc2: "posix/posix" +srcdoc2: "posix/posix;distros" srcdoc2: "pure/fenv;pure/securehash;impure/rdstdin" srcdoc2: "pure/basic2d;pure/basic3d;pure/mersenne;pure/coro;pure/httpcore" |