diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2018-08-16 01:22:21 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-08-16 01:22:21 +0200 |
commit | e4c759fbffae852b938a076de38ba2df4eab6afa (patch) | |
tree | f793335b31a460cae2966dd407ec934671ecc9ee /lib/pure | |
parent | b78114ce507757cd79649212bd17dc86965aa4ef (diff) | |
parent | 531c66d1ec583a35d8d6bc637c94457fcd87a8e3 (diff) | |
download | Nim-e4c759fbffae852b938a076de38ba2df4eab6afa.tar.gz |
Merge branch 'devel' into araq-misc
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/collections/sequtils.nim | 124 | ||||
-rw-r--r-- | lib/pure/concurrency/cpuinfo.nim | 12 | ||||
-rw-r--r-- | lib/pure/coro.nim | 18 | ||||
-rw-r--r-- | lib/pure/distros.nim | 6 | ||||
-rw-r--r-- | lib/pure/encodings.nim | 4 | ||||
-rw-r--r-- | lib/pure/fenv.nim | 2 | ||||
-rw-r--r-- | lib/pure/math.nim | 6 | ||||
-rw-r--r-- | lib/pure/nativesockets.nim | 5 | ||||
-rw-r--r-- | lib/pure/options.nim | 9 | ||||
-rw-r--r-- | lib/pure/os.nim | 13 | ||||
-rw-r--r-- | lib/pure/times.nim | 2 |
11 files changed, 146 insertions, 55 deletions
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 99ce91979..c8080546a 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -25,6 +25,28 @@ import macros when not defined(nimhygiene): {.pragma: dirty.} + +macro evalOnceAs(expAlias, exp: untyped, letAssigneable: static[bool]): untyped = + ## Injects ``expAlias`` in caller scope, to avoid bugs involving multiple + ## substitution in macro arguments such as + ## https://github.com/nim-lang/Nim/issues/7187 + ## ``evalOnceAs(myAlias, myExp)`` will behave as ``let myAlias = myExp`` + ## except when ``letAssigneable`` is false (eg to handle openArray) where + ## it just forwards ``exp`` unchanged + expectKind(expAlias, nnkIdent) + var val = exp + + result = newStmtList() + # If `exp` is not a symbol we evaluate it once here and then use the temporary + # symbol as alias + if exp.kind != nnkSym and letAssigneable: + val = genSym() + result.add(newLetStmt(val, exp)) + + result.add( + newProc(name = genSym(nskTemplate, $expAlias), params = [getType(untyped)], + body = val, procType = nnkTemplateDef)) + proc concat*[T](seqs: varargs[seq[T]]): seq[T] = ## Takes several sequences' items and returns them inside a new sequence. ## @@ -635,30 +657,7 @@ template mapIt*(s, typ, op: untyped): untyped = result.add(op) result -# This is needed in order not to break the bootstrap, the fallback -# implementation is a "dumb" let that won't work in some cases (eg. when `exp` -# is an openArray) -when declared(macros.symKind): - macro evalOnce(v, exp: untyped): untyped = - expectKind(v, nnkIdent) - var val = exp - - result = newStmtList() - - # Not a parameter we can pass as-is, evaluate and store in a temporary - # variable - if exp.kind != nnkSym or exp.symKind != nskParam: - val = genSym() - result.add(newLetStmt(val, exp)) - - result.add( - newProc(name = genSym(nskTemplate, $v), params = [getType(untyped)], - body = val, procType = nnkTemplateDef)) -else: - macro evalOnce(v, exp: untyped): untyped = - result = newLetStmt(v, exp) - -template mapIt*(s, op: untyped): untyped = +template mapIt*(s: typed, op: untyped): untyped = ## Convenience template around the ``map`` proc to reduce typing. ## ## The template injects the ``it`` variable which you can use directly in an @@ -675,19 +674,24 @@ template mapIt*(s, op: untyped): untyped = block: var it{.inject.}: type(items(s)); op)) - var result: seq[outType] when compiles(s.len): - evalOnce(t, s) - var i = 0 - result = newSeq[outType](t.len) - for it {.inject.} in t: - result[i] = op - i += 1 + block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580 + + # BUG: `evalOnceAs(s2, s, false)` would lead to C compile errors + # (`error: use of undeclared identifier`) instead of Nim compile errors + evalOnceAs(s2, s, compiles((let _ = s))) + + var i = 0 + var result = newSeq[outType](s2.len) + for it {.inject.} in s2: + result[i] = op + i += 1 + result else: - result = @[] + var result: seq[outType] = @[] for it {.inject.} in s: result.add(op) - result + result template applyIt*(varSeq, op: untyped) = ## Convenience template around the mutable ``apply`` proc to reduce typing. @@ -774,6 +778,14 @@ macro mapLiterals*(constructor, op: untyped; when isMainModule: import strutils + + # helper for testing double substitution side effects which are handled + # by `evalOnceAs` + var counter = 0 + proc identity[T](a:T):auto= + counter.inc + a + block: # concat test let s1 = @[1, 2, 3] @@ -1045,10 +1057,12 @@ when isMainModule: assert multiplication == 495, "Multiplication is (5*(9*(11)))" assert concatenation == "nimiscool" - block: # mapIt tests + block: # mapIt + applyIt test + counter = 0 var nums = @[1, 2, 3, 4] - strings = nums.mapIt($(4 * it)) + strings = nums.identity.mapIt($(4 * it)) + doAssert counter == 1 nums.applyIt(it * 3) assert nums[0] + nums[3] == 15 assert strings[2] == "12" @@ -1067,9 +1081,43 @@ when isMainModule: doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2") block: # mapIt with openArray - when declared(macros.symKind): - proc foo(x: openArray[int]): seq[int] = x.mapIt(it + 1) - doAssert foo([1,2,3]) == @[2,3,4] + counter = 0 + proc foo(x: openArray[int]): seq[int] = x.mapIt(it * 10) + doAssert foo([identity(1),identity(2)]) == @[10, 20] + doAssert counter == 2 + + block: # mapIt with direct openArray + proc foo1(x: openArray[int]): seq[int] = x.mapIt(it * 10) + counter = 0 + doAssert foo1(openArray[int]([identity(1),identity(2)])) == @[10,20] + doAssert counter == 2 + + template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10) + counter = 0 + doAssert foo2(openArray[int]([identity(1),identity(2)])) == @[10,20] + # TODO: this fails; not sure how to fix this case + # doAssert counter == 2 + + block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468 + # NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type + # of elements) + doAssert: not compiles(mapIt(@[], it)) + doAssert: not compiles(mapIt([], it)) + doAssert newSeq[int](0).mapIt(it) == @[] + + block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580 + let t = [1,2].mapIt(it) + doAssert t == @[1,2] + + block: + var counter = 0 + proc getInput():auto = + counter.inc + [1, 2] + doAssert getInput().mapIt(it*2).mapIt(it*10) == @[20, 40] + # make sure argument evaluated only once, analog to + # https://github.com/nim-lang/Nim/issues/7187 test case + doAssert counter == 1 block: # mapIt with invalid RHS for `let` (#8566) type X = enum diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index 6d41aa1b2..541265da9 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -43,6 +43,14 @@ when defined(genode): proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {. importcpp: "@->cpu().affinity_space().total()".} +when defined(haiku): + {.emit: "#include <OS.h>".} + type + SystemInfo {.importc: "system_info", bycopy.} = object + cpuCount {.importc: "cpu_count".}: uint32 + + proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info".} + proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. ## Returns 0 if it cannot be detected. @@ -86,6 +94,10 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = result = sysconf(SC_NPROC_ONLN) elif defined(genode): result = runtimeEnv.affinitySpaceTotal().int + elif defined(haiku): + var sysinfo: SystemInfo + if getSystemInfo(addr sysinfo) == 0: + result = sysinfo.cpuCount.int else: result = sysconf(SC_NPROCESSORS_ONLN) if result <= 0: result = 0 diff --git a/lib/pure/coro.nim b/lib/pure/coro.nim index b6ef30e7c..6d7dcf078 100644 --- a/lib/pure/coro.nim +++ b/lib/pure/coro.nim @@ -43,6 +43,10 @@ when defined(windows): {.warning: "ucontext coroutine backend is not available on windows, defaulting to fibers.".} when defined(nimCoroutinesSetjmp): {.warning: "setjmp coroutine backend is not available on windows, defaulting to fibers.".} +elif defined(haiku): + const coroBackend = CORO_BACKEND_SETJMP + when defined(nimCoroutinesUcontext): + {.warning: "ucontext coroutine backend is not available on haiku, defaulting to setjmp".} elif defined(nimCoroutinesSetjmp) or defined(nimCoroutinesSetjmpBundled): const coroBackend = CORO_BACKEND_SETJMP else: @@ -55,21 +59,21 @@ when coroBackend == CORO_BACKEND_FIBERS: elif coroBackend == CORO_BACKEND_UCONTEXT: type - stack_t {.importc, header: "<sys/ucontext.h>".} = object + stack_t {.importc, header: "<ucontext.h>".} = object ss_sp: pointer ss_flags: int ss_size: int - ucontext_t {.importc, header: "<sys/ucontext.h>".} = object + ucontext_t {.importc, header: "<ucontext.h>".} = object uc_link: ptr ucontext_t uc_stack: stack_t Context = ucontext_t - proc getcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".} - proc setcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".} - proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".} - proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<sys/ucontext.h>", varargs.} + proc getcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".} + proc setcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".} + proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<ucontext.h>".} + proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<ucontext.h>", varargs.} elif coroBackend == CORO_BACKEND_SETJMP: proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn, importc: "narch_$1", fastcall.} @@ -190,7 +194,7 @@ proc switchTo(current, to: CoroutinePtr) = elif to.state == CORO_CREATED: # Coroutine is started. coroExecWithStack(runCurrentTask, to.stack.bottom) - doAssert false + #doAssert false else: {.error: "Invalid coroutine backend set.".} # Execution was just resumed. Restore frame information and set active stack. diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim index 0adba5b1e..5847cfadb 100644 --- a/lib/pure/distros.nim +++ b/lib/pure/distros.nim @@ -126,6 +126,8 @@ type OpenBSD DragonFlyBSD + Haiku + const LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware, @@ -166,6 +168,8 @@ proc detectOsImpl(d: Distribution): bool = of Distribution.Solaris: let uname = toLowerAscii(uname()) result = ("sun" in uname) or ("solaris" in uname) + of Distribution.Haiku: + result = defined(haiku) else: let dd = toLowerAscii($d) result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) @@ -224,6 +228,8 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) = result = ("pacman -S " & p, true) else: result = ("<your package manager here> install " & p, true) + elif defined(haiku): + result = ("pkgman install " & p, true) else: result = ("brew install " & p, false) diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index 3c1cf73f4..2039a31be 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -255,7 +255,7 @@ when defined(windows): else: when defined(haiku): - const iconvDll = "(libc.so.6|libiconv.so|libtextencoding.so)" + const iconvDll = "libiconv.so" elif defined(macosx): const iconvDll = "libiconv.dylib" else: @@ -272,6 +272,8 @@ else: const EILSEQ = 86.cint elif defined(solaris): const EILSEQ = 88.cint + elif defined(haiku): + const EILSEQ = -2147454938.cint var errno {.importc, header: "<errno.h>".}: cint diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index c946c4261..0725973ca 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -12,7 +12,7 @@ {.deadCodeElim: on.} # dce option deprecated -when defined(Posix) and not defined(haiku): +when defined(Posix): {.passl: "-lm".} var diff --git a/lib/pure/math.nim b/lib/pure/math.nim index eb09bf4a7..79f287651 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -49,7 +49,7 @@ proc fac*(n: int): int = {.push checks:off, line_dir:off, stack_trace:off.} -when defined(Posix) and not defined(haiku): +when defined(Posix): {.passl: "-lm".} const @@ -529,8 +529,8 @@ proc sgn*[T: SomeNumber](x: T): int {.inline.} = {.pop.} proc `^`*[T](x: T, y: Natural): T = - ## Computes ``x`` to the power ``y`. ``x`` must be non-negative, use - ## `pow <#pow,float,float>` for negative exponents. + ## Computes ``x`` to the power ``y``. ``x`` must be non-negative, use + ## `pow <#pow,float,float>`_ for negative exponents. when compiles(y >= T(0)): assert y >= T(0) else: diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index 5545ca2d1..d5fb0f89b 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -248,9 +248,10 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET, hints.ai_socktype = toInt(sockType) hints.ai_protocol = toInt(protocol) # OpenBSD doesn't support AI_V4MAPPED and doesn't define the macro AI_V4MAPPED. - # FreeBSD doesn't support AI_V4MAPPED but defines the macro. + # FreeBSD, Haiku don't support AI_V4MAPPED but defines the macro. # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092 - when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android): + # https://dev.haiku-os.org/ticket/14323 + when not defined(freebsd) and not defined(openbsd) and not defined(netbsd) and not defined(android) and not defined(haiku): if domain == AF_INET6: hints.ai_flags = AI_V4MAPPED var gaiResult = getaddrinfo(address, $port, addr(hints), result) diff --git a/lib/pure/options.nim b/lib/pure/options.nim index ce58943f9..b547c722a 100644 --- a/lib/pure/options.nim +++ b/lib/pure/options.nim @@ -129,7 +129,7 @@ proc get*[T](self: Option[T]): T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: - raise UnpackError(msg : "Can't obtain a value from a `none`") + raise UnpackError(msg: "Can't obtain a value from a `none`") self.val proc get*[T](self: Option[T], otherwise: T): T = @@ -139,6 +139,13 @@ proc get*[T](self: Option[T], otherwise: T): T = else: otherwise +proc get*[T](self: var Option[T]): var T = + ## Returns contents of the Option. If it is none, then an exception is + ## thrown. + if self.isNone: + raise UnpackError(msg: "Can't obtain a value from a `none`") + return self.val + proc map*[T](self: Option[T], callback: proc (input: T)) = ## Applies a callback to the value in this Option if self.isSome: diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 9cc83c372..c05e33e31 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -615,7 +615,10 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", when not declared(ENOENT) and not defined(Windows): when NoFakeVars: - const ENOENT = cint(2) # 2 on most systems including Solaris + when not defined(haiku): + const ENOENT = cint(2) # 2 on most systems including Solaris + else: + const ENOENT = cint(-2147459069) else: var ENOENT {.importc, header: "<errno.h>".}: cint @@ -972,6 +975,14 @@ proc rawCreateDir(dir: string): bool = result = false else: raiseOSError(osLastError(), dir) + elif defined(haiku): + let res = mkdir(dir, 0o777) + if res == 0'i32: + result = true + elif errno == EEXIST or errno == EROFS: + result = false + else: + raiseOSError(osLastError(), dir) elif defined(posix): let res = mkdir(dir, 0o777) if res == 0'i32: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index cdb7a4466..073216e22 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -892,7 +892,7 @@ else: weekday {.importc: "tm_wday".}, yearday {.importc: "tm_yday".}, isdst {.importc: "tm_isdst".}: cint - when defined(linux) and defined(amd64): + when defined(linux) and defined(amd64) or defined(haiku): gmtoff {.importc: "tm_gmtoff".}: clong zone {.importc: "tm_zone".}: cstring type |