Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq 2017-05-02 01:24:19 +02:00
commit 6377b52d8e
13 changed files with 132 additions and 39 deletions

View file

@ -1315,8 +1315,11 @@ proc shouldRecompile(code: Rope, cfile: Cfile): bool =
if optForceFullMake notin gGlobalOptions: if optForceFullMake notin gGlobalOptions:
if not equalsFile(code, cfile.cname): if not equalsFile(code, cfile.cname):
if isDefined("nimdiff"): if isDefined("nimdiff"):
if fileExists(cfile.cname):
copyFile(cfile.cname, cfile.cname & ".backup") copyFile(cfile.cname, cfile.cname & ".backup")
echo "diff ", cfile.cname, ".backup ", cfile.cname echo "diff ", cfile.cname, ".backup ", cfile.cname
else:
echo "new file ", cfile.cname
writeRope(code, cfile.cname) writeRope(code, cfile.cname)
return return
if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname): if existsFile(cfile.obj) and os.fileNewer(cfile.obj, cfile.cname):

View file

@ -449,7 +449,8 @@ proc unsignedTrimmerPHP(size: BiggestInt): Rope =
template unsignedTrimmer(size: BiggestInt): Rope = template unsignedTrimmer(size: BiggestInt): Rope =
size.unsignedTrimmerJS | size.unsignedTrimmerPHP size.unsignedTrimmerJS | size.unsignedTrimmerPHP
proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string, reassign: bool = false) = proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
reassign = false) =
var x, y: TCompRes var x, y: TCompRes
gen(p, n.sons[1], x) gen(p, n.sons[1], x)
gen(p, n.sons[2], y) gen(p, n.sons[2], y)
@ -2128,6 +2129,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
else: r.res = rope(f.toStrMaxPrecision) else: r.res = rope(f.toStrMaxPrecision)
r.kind = resExpr r.kind = resExpr
of nkCallKinds: of nkCallKinds:
if isEmptyType(n.typ): genLineDir(p, n)
if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone): if (n.sons[0].kind == nkSym) and (n.sons[0].sym.magic != mNone):
genMagic(p, n, r) genMagic(p, n, r)
elif n.sons[0].kind == nkSym and sfInfixCall in n.sons[0].sym.flags and elif n.sons[0].kind == nkSym and sfInfixCall in n.sons[0].sym.flags and

View file

@ -74,7 +74,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode =
let value = n.lastSon let value = n.lastSon
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
var temp = newSym(skLet, getIdent(genPrefix), owner, value.info) var temp = newSym(skLet, getIdent("_"), owner, value.info)
var v = newNodeI(nkLetSection, value.info) var v = newNodeI(nkLetSection, value.info)
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info) let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)

View file

@ -178,7 +178,7 @@ proc bundleNimbleExe() =
bundleNimbleSrc() bundleNimbleSrc()
# now compile Nimble and copy it to $nim/bin for the installer.ini # now compile Nimble and copy it to $nim/bin for the installer.ini
# to pick it up: # to pick it up:
nimexec("c dist/nimble/src/nimble.nim") nimexec("c -d:release dist/nimble/src/nimble.nim")
copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe) copyExe("dist/nimble/src/nimble".exe, "bin/nimble".exe)
proc buildNimble(latest: bool) = proc buildNimble(latest: bool) =
@ -205,7 +205,7 @@ proc buildNimble(latest: bool) =
else: else:
exec("git checkout -f stable") exec("git checkout -f stable")
exec("git pull") exec("git pull")
nimexec("c --noNimblePath -p:compiler " & installDir / "src/nimble.nim") nimexec("c --noNimblePath -p:compiler -d:release " & installDir / "src/nimble.nim")
copyExe(installDir / "src/nimble".exe, "bin/nimble".exe) copyExe(installDir / "src/nimble".exe, "bin/nimble".exe)
proc bundleNimsuggest(buildExe: bool) = proc bundleNimsuggest(buildExe: bool) =

View file

@ -97,15 +97,6 @@ when not defined(macosx):
## Second-granularity time of last status change. ## Second-granularity time of last status change.
result = s.st_ctim.tv_sec result = s.st_ctim.tv_sec
proc WIFCONTINUED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
## True if child has been continued.
proc WIFEXITED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
## True if child exited normally.
proc WIFSIGNALED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
## True if child exited due to uncaught signal.
proc WIFSTOPPED*(s:cint) : bool {.importc, header: "<sys/wait.h>".}
## True if child is currently stopped.
when hasAioH: when hasAioH:
proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".} proc aio_cancel*(a1: cint, a2: ptr Taiocb): cint {.importc, header: "<aio.h>".}
proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".} proc aio_error*(a1: ptr Taiocb): cint {.importc, header: "<aio.h>".}

View file

@ -602,3 +602,12 @@ var
include posix_linux_amd64_consts include posix_linux_amd64_consts
const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE! const POSIX_SPAWN_USEVFORK* = cint(0x40) # needs _GNU_SOURCE!
# <sys/wait.h>
proc WEXITSTATUS*(s: cint): cint = (s and 0xff00) shr 8
proc WTERMSIG*(s:cint): cint = s and 0x7f
proc WSTOPSIG*(s:cint): cint = WEXITSTATUS(s)
proc WIFEXITED*(s:cint) : bool = WTERMSIG(s) == 0
proc WIFSIGNALED*(s:cint) : bool = (cast[int8]((s and 0x7f) + 1) shr 1) > 0
proc WIFSTOPPED*(s:cint) : bool = (s and 0xff) == 0x7f
proc WIFCONTINUED*(s:cint) : bool = s == W_CONTINUED

View file

@ -611,3 +611,18 @@ when hasSpawnH:
# OR'ing of flags: # OR'ing of flags:
const POSIX_SPAWN_USEVFORK* = cint(0) const POSIX_SPAWN_USEVFORK* = cint(0)
# <sys/wait.h>
proc WEXITSTATUS*(s: cint): cint {.importc, header: "<sys/wait.h>".}
## Exit code, iff WIFEXITED(s)
proc WTERMSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
## Termination signal, iff WIFSIGNALED(s)
proc WSTOPSIG*(s: cint): cint {.importc, header: "<sys/wait.h>".}
## Stop signal, iff WIFSTOPPED(s)
proc WIFEXITED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
## True if child exited normally.
proc WIFSIGNALED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
## True if child exited due to uncaught signal.
proc WIFSTOPPED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
## True if child is currently stopped.
proc WIFCONTINUED*(s: cint): bool {.importc, header: "<sys/wait.h>".}
## True if child has been continued.

View file

@ -1213,22 +1213,22 @@ when not defined(js):
proc parseJson*(s: Stream, filename: string): JsonNode = proc parseJson*(s: Stream, filename: string): JsonNode =
## Parses from a stream `s` into a `JsonNode`. `filename` is only needed ## Parses from a stream `s` into a `JsonNode`. `filename` is only needed
## for nice error messages. ## for nice error messages.
## If `s` contains extra data, it will raising `JsonParsingError`. ## If `s` contains extra data, it will raise `JsonParsingError`.
var p: JsonParser var p: JsonParser
p.open(s, filename) p.open(s, filename)
defer: p.close() defer: p.close()
discard getTok(p) # read first token discard getTok(p) # read first token
result = p.parseJson() result = p.parseJson()
eat(p, tkEof) # check there are no exstra data eat(p, tkEof) # check if there is no extra data
proc parseJson*(buffer: string): JsonNode = proc parseJson*(buffer: string): JsonNode =
## Parses JSON from `buffer`. ## Parses JSON from `buffer`.
## If `buffer` contains extra data, it will raising `JsonParsingError`. ## If `buffer` contains extra data, it will raise `JsonParsingError`.
result = parseJson(newStringStream(buffer), "input") result = parseJson(newStringStream(buffer), "input")
proc parseFile*(filename: string): JsonNode = proc parseFile*(filename: string): JsonNode =
## Parses `file` into a `JsonNode`. ## Parses `file` into a `JsonNode`.
## If `file` contains extra data, it will raising `JsonParsingError`. ## If `file` contains extra data, it will raise `JsonParsingError`.
var stream = newFileStream(filename, fmRead) var stream = newFileStream(filename, fmRead)
if stream == nil: if stream == nil:
raise newException(IOError, "cannot read from file: " & filename) raise newException(IOError, "cannot read from file: " & filename)

View file

@ -209,9 +209,16 @@ proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
## ##
## **Warning**: Be careful when using waitForExit for processes created without ## **Warning**: Be careful when using waitForExit for processes created without
## poParentStreams because they may fill output buffers, causing deadlock. ## poParentStreams because they may fill output buffers, causing deadlock.
##
## On posix, if the process has exited because of a signal, 128 + signal
## number will be returned.
proc peekExitCode*(p: Process): int {.tags: [].} proc peekExitCode*(p: Process): int {.tags: [].}
## return -1 if the process is still running. Otherwise the process' exit code ## return -1 if the process is still running. Otherwise the process' exit code
##
## On posix, if the process has exited because of a signal, 128 + signal
## number will be returned.
proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].} proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
## returns ``p``'s input stream for writing to. ## returns ``p``'s input stream for writing to.
@ -679,6 +686,16 @@ elif not defined(useNimRtl):
readIdx = 0 readIdx = 0
writeIdx = 1 writeIdx = 1
proc isExitStatus(status: cint): bool =
WIFEXITED(status) or WIFSIGNALED(status)
proc exitStatus(status: cint): cint =
if WIFSIGNALED(status):
# like the shell!
128 + WTERMSIG(status)
else:
WEXITSTATUS(status)
proc envToCStringArray(t: StringTableRef): cstringArray = proc envToCStringArray(t: StringTableRef): cstringArray =
result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring))) result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring)))
var i = 0 var i = 0
@ -967,7 +984,7 @@ elif not defined(useNimRtl):
var status : cint = 1 var status : cint = 1
ret = waitpid(p.id, status, WNOHANG) ret = waitpid(p.id, status, WNOHANG)
if ret == int(p.id): if ret == int(p.id):
if WIFEXITED(status): if isExitStatus(status):
p.exitStatus = status p.exitStatus = status
return false return false
else: else:
@ -990,7 +1007,9 @@ elif not defined(useNimRtl):
import kqueue, times import kqueue, times
proc waitForExit(p: Process, timeout: int = -1): int = proc waitForExit(p: Process, timeout: int = -1): int =
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8) if p.exitStatus != -3:
return exitStatus(p.exitStatus)
if timeout == -1: if timeout == -1:
var status : cint = 1 var status : cint = 1
if waitpid(p.id, status, 0) < 0: if waitpid(p.id, status, 0) < 0:
@ -1041,7 +1060,7 @@ elif not defined(useNimRtl):
finally: finally:
discard posix.close(kqFD) discard posix.close(kqFD)
result = ((p.exitStatus and 0xFF00) shr 8) result = exitStatus(p.exitStatus)
else: else:
import times import times
@ -1077,7 +1096,9 @@ elif not defined(useNimRtl):
# ``waitPid`` fails if the process is not running anymore. But then # ``waitPid`` fails if the process is not running anymore. But then
# ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is # ``running`` probably set ``p.exitStatus`` for us. Since ``p.exitStatus`` is
# initialized with -3, wrong success exit codes are prevented. # initialized with -3, wrong success exit codes are prevented.
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8) if p.exitStatus != -3:
return exitStatus(p.exitStatus)
if timeout == -1: if timeout == -1:
var status : cint = 1 var status : cint = 1
if waitpid(p.id, status, 0) < 0: if waitpid(p.id, status, 0) < 0:
@ -1151,17 +1172,19 @@ elif not defined(useNimRtl):
if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1: if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
raiseOSError(osLastError()) raiseOSError(osLastError())
result = ((p.exitStatus and 0xFF00) shr 8) result = exitStatus(p.exitStatus)
proc peekExitCode(p: Process): int = proc peekExitCode(p: Process): int =
var status = cint(0) var status = cint(0)
result = -1 result = -1
if p.exitStatus != -3: return((p.exitStatus and 0xFF00) shr 8) if p.exitStatus != -3:
return exitStatus(p.exitStatus)
var ret = waitpid(p.id, status, WNOHANG) var ret = waitpid(p.id, status, WNOHANG)
if ret > 0: if ret > 0:
if WIFEXITED(status): if isExitStatus(status):
p.exitStatus = status p.exitStatus = status
result = (status and 0xFF00) shr 8 result = exitStatus(status)
proc createStream(stream: var Stream, handle: var FileHandle, proc createStream(stream: var Stream, handle: var FileHandle,
fileMode: FileMode) = fileMode: FileMode) =
@ -1189,7 +1212,8 @@ elif not defined(useNimRtl):
proc execCmd(command: string): int = proc execCmd(command: string): int =
when defined(linux): when defined(linux):
result = csystem(command) shr 8 let tmp = csystem(command)
result = if tmp == -1: tmp else: exitStatus(tmp)
else: else:
result = csystem(command) result = csystem(command)

View file

@ -2016,6 +2016,12 @@ proc min*(x, y: float): float {.magic: "MinF64", noSideEffect.} =
if x <= y: x else: y if x <= y: x else: y
proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} = proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} =
if y <= x: x else: y if y <= x: x else: y
proc min*[T](x, y: T): T =
if x <= y: x else: y
proc max*[T](x, y: T): T =
if y <= x: x else: y
{.pop.} {.pop.}
proc clamp*[T](x, a, b: T): T = proc clamp*[T](x, a, b: T): T =

View file

@ -0,0 +1,36 @@
discard """
output: '''true
true'''
targets: "c"
"""
import os, osproc
when not defined(windows):
import posix
# Checks that the environment is passed correctly in startProcess
# To do that launches a copy of itself with a new environment.
if paramCount() == 0:
# Parent process
let p = startProcess(
getAppFilename(),
args = @["child"],
options = {poStdErrToStdOut, poUsePath, poParentStreams}
)
echo p.running()
p.kill()
when defined(windows):
# windows kill happens using TerminateProcess(h, 0), so we should get a
# 0 here
echo p.waitForExit() == 0
else:
# on posix (non-windows), kill sends SIGKILL
echo p.waitForExit() == 128 + SIGKILL
else:
sleep(5000) # should get killed before this

View file

@ -21,6 +21,8 @@ proc pg[T](x, y: var T) =
# test as a top level statement: # test as a top level statement:
var x, y, a, b: int var x, y, a, b: int
# test for regression:
(x, y) = (1, 2)
(x, y) = fooBar() (x, y) = fooBar()
echo x, " ", y echo x, " ", y

View file

@ -13,6 +13,9 @@ Changelog
Changes affecting backwards compatibility Changes affecting backwards compatibility
----------------------------------------- -----------------------------------------
- There are now two different HTTP response types, ``Response`` and
``AsyncResponse``. ``AsyncResponse``'s ``body`` accessor returns a
``Future[string]``!
- ``httpclient.request`` now respects ``maxRedirects`` option. Previously - ``httpclient.request`` now respects ``maxRedirects`` option. Previously
redirects were handled only by ``get`` and ``post`` procs. redirects were handled only by ``get`` and ``post`` procs.
- The IO routines now raise ``EOFError`` for the "end of file" condition. - The IO routines now raise ``EOFError`` for the "end of file" condition.
@ -56,6 +59,8 @@ Changes affecting backwards compatibility
checks. When fields within case objects are initialiazed, the compiler will checks. When fields within case objects are initialiazed, the compiler will
now demand that the respective discriminator field has a matching known now demand that the respective discriminator field has a matching known
compile-time value. compile-time value.
- On posix, the results of `waitForExit`, `peekExitCode`, `execCmd` will return
128 + signal number if the application terminates via signal.
Library Additions Library Additions
----------------- -----------------