Merge branch 'devel' into araq-misc

This commit is contained in:
Andreas Rumpf 2018-08-16 01:22:21 +02:00
commit e4c759fbff
28 changed files with 286 additions and 71 deletions

View file

@ -1680,6 +1680,14 @@ proc skipStmtList*(n: PNode): PNode =
else: else:
result = n result = n
proc toVar*(typ: PType): PType =
## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is.
result = typ
if typ.kind != tyVar:
result = newType(tyVar, typ.owner)
rawAddSon(result, typ)
proc toRef*(typ: PType): PType = proc toRef*(typ: PType): PType =
## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is. ## returned. Otherwise ``typ`` is simply returned as-is.

View file

@ -412,6 +412,8 @@ proc debugTree(conf: ConfigRef; n: PNode, indent: int, maxRecDepth: int;
else: else:
addf(result, ",$N$1\"ident\": null", [istr]) addf(result, ",$N$1\"ident\": null", [istr])
else: else:
if renderType and n.typ != nil:
addf(result, ",$N$1\"typ\": $2", [istr, debugType(conf, n.typ, 2)])
if sonsLen(n) > 0: if sonsLen(n) > 0:
addf(result, ",$N$1\"sons\": [", [istr]) addf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):

View file

@ -217,7 +217,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
if n.typ != nil and n.typ.kind == tyVar: if n.typ != nil and n.typ.kind == tyVar:
result = arLValue result = arLValue
of nkSym: of nkSym:
let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet} let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet, skForVar}
else: {skVar, skResult, skTemp} else: {skVar, skResult, skTemp}
if n.sym.kind in kinds: if n.sym.kind in kinds:
if owner != nil and owner == n.sym.owner and if owner != nil and owner == n.sym.owner and

View file

@ -369,6 +369,8 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
result = PTransNode(n.sons[0]) result = PTransNode(n.sons[0])
if n.typ.skipTypes(abstractVar).kind != tyOpenArray: if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
PNode(result).typ = n.typ PNode(result).typ = n.typ
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
PNode(result).typ = toVar(PNode(result).typ)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var m = n.sons[0].sons[1] var m = n.sons[0].sons[1]
if m.kind == a or m.kind == b: if m.kind == a or m.kind == b:
@ -377,6 +379,8 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
result = PTransNode(n.sons[0]) result = PTransNode(n.sons[0])
if n.typ.skipTypes(abstractVar).kind != tyOpenArray: if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
PNode(result).typ = n.typ PNode(result).typ = n.typ
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
PNode(result).typ = toVar(PNode(result).typ)
else: else:
if n.sons[0].kind == a or n.sons[0].kind == b: if n.sons[0].kind == a or n.sons[0].kind == b:
# addr ( deref ( x )) --> x # addr ( deref ( x )) --> x

View file

@ -82,19 +82,21 @@ path="$lib/pure"
clang.cpp.options.linker = "-ldl" clang.cpp.options.linker = "-ldl"
tcc.options.linker = "-ldl" tcc.options.linker = "-ldl"
@end @end
@if bsd or haiku: @if bsd:
# BSD got posix_spawn only recently, so we deactivate it for osproc: # BSD got posix_spawn only recently, so we deactivate it for osproc:
define:useFork define:useFork
# at least NetBSD has problems with thread local storage: # at least NetBSD has problems with thread local storage:
tlsEmulation:on tlsEmulation:on
@end @end
@if haiku: @if haiku:
# -fopenmp # Haiku currently have problems with TLS
gcc.options.linker = "-lroot -lnetwork" # https://dev.haiku-os.org/ticket/14342
gcc.cpp.options.linker = "-lroot -lnetwork" tlsEmulation:on
clang.options.linker = "-lroot -lnetwork" gcc.options.linker = "-Wl,--as-needed -lnetwork"
clang.cpp.options.linker = "-lroot -lnetwork" gcc.cpp.options.linker = "-Wl,--as-needed -lnetwork"
tcc.options.linker = "-lroot -lnetwork" clang.options.linker = "-Wl,--as-needed -lnetwork"
clang.cpp.options.linker = "-Wl,--as-needed -lnetwork"
tcc.options.linker = "-Wl,--as-needed -lnetwork"
@end @end
@end @end

View file

@ -68,6 +68,46 @@ User Some user defined warning.
========================== ============================================ ========================== ============================================
List of hints
-------------
Each hint can be activated individually with ``--hint[NAME]:on|off`` or in a
``push`` pragma.
========================== ============================================
Name Description
========================== ============================================
CC Shows when the C compiler is called.
CodeBegin
CodeEnd
CondTrue
Conf A config file was loaded.
ConvToBaseNotNeeded
ConvFromXtoItselfNotNeeded
Dependency
Exec Program is executed.
ExprAlwaysX
ExtendedContext
GCStats Dumps statistics about the Garbage Collector.
GlobalVar Shows global variables declarations.
LineTooLong Line exceeds the maximum length.
Link Linking phase.
Name
Path Search paths modifications.
Pattern
Performance
Processing Artifact being compiled.
QuitCalled
Source The source line that triggered a diagnostic
message.
StackTrace
Success, SuccessX Successful compilation of a library or a binary.
User
UserRaw
XDeclaredButNotUsed Unused symbols in the code.
========================== ============================================
Verbosity levels Verbosity levels
---------------- ----------------

View file

@ -36,6 +36,8 @@ include "system/inclrtl"
when hostOS == "solaris": when hostOS == "solaris":
{.passl: "-lsocket -lnsl".} {.passl: "-lsocket -lnsl".}
elif hostOS == "haiku":
{.passl: "-lnetwork".}
import os, parseutils import os, parseutils
from times import epochTime from times import epochTime

View file

@ -10,7 +10,7 @@
{.deadCodeElim: on.} # dce option deprecated {.deadCodeElim: on.} # dce option deprecated
const const
hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays hasSpawnH = true # should exist for every Posix system nowadays
hasAioH = defined(linux) hasAioH = defined(linux)
when defined(linux) and not defined(android): when defined(linux) and not defined(android):
@ -43,6 +43,9 @@ type
Dirent* {.importc: "struct dirent", Dirent* {.importc: "struct dirent",
header: "<dirent.h>", final, pure.} = object ## dirent_t struct header: "<dirent.h>", final, pure.} = object ## dirent_t struct
when defined(haiku):
d_dev*: Dev ## Device (not POSIX)
d_pdev*: Dev ## Parent device (only for queries) (not POSIX)
d_ino*: Ino ## File serial number. d_ino*: Ino ## File serial number.
when defined(dragonfly): when defined(dragonfly):
# DragonflyBSD doesn't have `d_reclen` field. # DragonflyBSD doesn't have `d_reclen` field.
@ -54,6 +57,9 @@ type
## (not POSIX) ## (not POSIX)
when defined(linux) or defined(openbsd): when defined(linux) or defined(openbsd):
d_off*: Off ## Not an offset. Value that ``telldir()`` would return. d_off*: Off ## Not an offset. Value that ``telldir()`` would return.
elif defined(haiku):
d_pino*: Ino ## Parent inode (only for queries) (not POSIX)
d_reclen*: cushort ## Length of this record. (not POSIX)
d_name*: array[0..255, char] ## Name of entry. d_name*: array[0..255, char] ## Name of entry.
@ -599,6 +605,10 @@ else:
MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
## No SIGPIPE generated when an attempt to send is made on a stream-oriented socket that is no longer connected. ## No SIGPIPE generated when an attempt to send is made on a stream-oriented socket that is no longer connected.
when defined(haiku):
const
SIGKILLTHR* = 21 ## BeOS specific: Kill just the thread, not team
when hasSpawnH: when hasSpawnH:
when defined(linux): when defined(linux):
# better be safe than sorry; Linux has this flag, macosx doesn't, don't # better be safe than sorry; Linux has this flag, macosx doesn't, don't

View file

@ -25,6 +25,28 @@ import macros
when not defined(nimhygiene): when not defined(nimhygiene):
{.pragma: dirty.} {.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] = proc concat*[T](seqs: varargs[seq[T]]): seq[T] =
## Takes several sequences' items and returns them inside a new sequence. ## 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.add(op)
result result
# This is needed in order not to break the bootstrap, the fallback template mapIt*(s: typed, op: untyped): untyped =
# 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 =
## Convenience template around the ``map`` proc to reduce typing. ## Convenience template around the ``map`` proc to reduce typing.
## ##
## The template injects the ``it`` variable which you can use directly in an ## The template injects the ``it`` variable which you can use directly in an
@ -675,19 +674,24 @@ template mapIt*(s, op: untyped): untyped =
block: block:
var it{.inject.}: type(items(s)); var it{.inject.}: type(items(s));
op)) op))
var result: seq[outType]
when compiles(s.len): when compiles(s.len):
evalOnce(t, s) block: # using a block avoids https://github.com/nim-lang/Nim/issues/8580
var i = 0
result = newSeq[outType](t.len) # BUG: `evalOnceAs(s2, s, false)` would lead to C compile errors
for it {.inject.} in t: # (`error: use of undeclared identifier`) instead of Nim compile errors
result[i] = op evalOnceAs(s2, s, compiles((let _ = s)))
i += 1
var i = 0
var result = newSeq[outType](s2.len)
for it {.inject.} in s2:
result[i] = op
i += 1
result
else: else:
result = @[] var result: seq[outType] = @[]
for it {.inject.} in s: for it {.inject.} in s:
result.add(op) result.add(op)
result result
template applyIt*(varSeq, op: untyped) = template applyIt*(varSeq, op: untyped) =
## Convenience template around the mutable ``apply`` proc to reduce typing. ## Convenience template around the mutable ``apply`` proc to reduce typing.
@ -774,6 +778,14 @@ macro mapLiterals*(constructor, op: untyped;
when isMainModule: when isMainModule:
import strutils 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 block: # concat test
let let
s1 = @[1, 2, 3] s1 = @[1, 2, 3]
@ -1045,10 +1057,12 @@ when isMainModule:
assert multiplication == 495, "Multiplication is (5*(9*(11)))" assert multiplication == 495, "Multiplication is (5*(9*(11)))"
assert concatenation == "nimiscool" assert concatenation == "nimiscool"
block: # mapIt tests block: # mapIt + applyIt test
counter = 0
var var
nums = @[1, 2, 3, 4] nums = @[1, 2, 3, 4]
strings = nums.mapIt($(4 * it)) strings = nums.identity.mapIt($(4 * it))
doAssert counter == 1
nums.applyIt(it * 3) nums.applyIt(it * 3)
assert nums[0] + nums[3] == 15 assert nums[0] + nums[3] == 15
assert strings[2] == "12" assert strings[2] == "12"
@ -1067,9 +1081,43 @@ when isMainModule:
doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2") doAssert mapLiterals(([1], ("abc"), 2), `$`, nested=true) == (["1"], "abc", "2")
block: # mapIt with openArray block: # mapIt with openArray
when declared(macros.symKind): counter = 0
proc foo(x: openArray[int]): seq[int] = x.mapIt(it + 1) proc foo(x: openArray[int]): seq[int] = x.mapIt(it * 10)
doAssert foo([1,2,3]) == @[2,3,4] 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) block: # mapIt with invalid RHS for `let` (#8566)
type X = enum type X = enum

View file

@ -43,6 +43,14 @@ when defined(genode):
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {. proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
importcpp: "@->cpu().affinity_space().total()".} 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".} = proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has. ## returns the numer of the processors/cores the machine has.
## Returns 0 if it cannot be detected. ## Returns 0 if it cannot be detected.
@ -86,6 +94,10 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
result = sysconf(SC_NPROC_ONLN) result = sysconf(SC_NPROC_ONLN)
elif defined(genode): elif defined(genode):
result = runtimeEnv.affinitySpaceTotal().int result = runtimeEnv.affinitySpaceTotal().int
elif defined(haiku):
var sysinfo: SystemInfo
if getSystemInfo(addr sysinfo) == 0:
result = sysinfo.cpuCount.int
else: else:
result = sysconf(SC_NPROCESSORS_ONLN) result = sysconf(SC_NPROCESSORS_ONLN)
if result <= 0: result = 0 if result <= 0: result = 0

View file

@ -43,6 +43,10 @@ when defined(windows):
{.warning: "ucontext coroutine backend is not available on windows, defaulting to fibers.".} {.warning: "ucontext coroutine backend is not available on windows, defaulting to fibers.".}
when defined(nimCoroutinesSetjmp): when defined(nimCoroutinesSetjmp):
{.warning: "setjmp coroutine backend is not available on windows, defaulting to fibers.".} {.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): elif defined(nimCoroutinesSetjmp) or defined(nimCoroutinesSetjmpBundled):
const coroBackend = CORO_BACKEND_SETJMP const coroBackend = CORO_BACKEND_SETJMP
else: else:
@ -55,21 +59,21 @@ when coroBackend == CORO_BACKEND_FIBERS:
elif coroBackend == CORO_BACKEND_UCONTEXT: elif coroBackend == CORO_BACKEND_UCONTEXT:
type type
stack_t {.importc, header: "<sys/ucontext.h>".} = object stack_t {.importc, header: "<ucontext.h>".} = object
ss_sp: pointer ss_sp: pointer
ss_flags: int ss_flags: int
ss_size: 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_link: ptr ucontext_t
uc_stack: stack_t uc_stack: stack_t
Context = ucontext_t Context = ucontext_t
proc getcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".} proc getcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc setcontext(context: var ucontext_t): int32 {.importc, header: "<sys/ucontext.h>".} proc setcontext(context: var ucontext_t): int32 {.importc, header: "<ucontext.h>".}
proc swapcontext(fromCtx, toCtx: var ucontext_t): int32 {.importc, header: "<sys/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: "<sys/ucontext.h>", varargs.} proc makecontext(context: var ucontext_t, fn: pointer, argc: int32) {.importc, header: "<ucontext.h>", varargs.}
elif coroBackend == CORO_BACKEND_SETJMP: elif coroBackend == CORO_BACKEND_SETJMP:
proc coroExecWithStack*(fn: pointer, stack: pointer) {.noreturn, importc: "narch_$1", fastcall.} 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: elif to.state == CORO_CREATED:
# Coroutine is started. # Coroutine is started.
coroExecWithStack(runCurrentTask, to.stack.bottom) coroExecWithStack(runCurrentTask, to.stack.bottom)
doAssert false #doAssert false
else: else:
{.error: "Invalid coroutine backend set.".} {.error: "Invalid coroutine backend set.".}
# Execution was just resumed. Restore frame information and set active stack. # Execution was just resumed. Restore frame information and set active stack.

View file

@ -126,6 +126,8 @@ type
OpenBSD OpenBSD
DragonFlyBSD DragonFlyBSD
Haiku
const const
LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware, LacksDevPackages* = {Distribution.Gentoo, Distribution.Slackware,
@ -166,6 +168,8 @@ proc detectOsImpl(d: Distribution): bool =
of Distribution.Solaris: of Distribution.Solaris:
let uname = toLowerAscii(uname()) let uname = toLowerAscii(uname())
result = ("sun" in uname) or ("solaris" in uname) result = ("sun" in uname) or ("solaris" in uname)
of Distribution.Haiku:
result = defined(haiku)
else: else:
let dd = toLowerAscii($d) let dd = toLowerAscii($d)
result = dd in toLowerAscii(uname()) or dd in toLowerAscii(release()) 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) result = ("pacman -S " & p, true)
else: else:
result = ("<your package manager here> install " & p, true) result = ("<your package manager here> install " & p, true)
elif defined(haiku):
result = ("pkgman install " & p, true)
else: else:
result = ("brew install " & p, false) result = ("brew install " & p, false)

View file

@ -255,7 +255,7 @@ when defined(windows):
else: else:
when defined(haiku): when defined(haiku):
const iconvDll = "(libc.so.6|libiconv.so|libtextencoding.so)" const iconvDll = "libiconv.so"
elif defined(macosx): elif defined(macosx):
const iconvDll = "libiconv.dylib" const iconvDll = "libiconv.dylib"
else: else:
@ -272,6 +272,8 @@ else:
const EILSEQ = 86.cint const EILSEQ = 86.cint
elif defined(solaris): elif defined(solaris):
const EILSEQ = 88.cint const EILSEQ = 88.cint
elif defined(haiku):
const EILSEQ = -2147454938.cint
var errno {.importc, header: "<errno.h>".}: cint var errno {.importc, header: "<errno.h>".}: cint

View file

@ -12,7 +12,7 @@
{.deadCodeElim: on.} # dce option deprecated {.deadCodeElim: on.} # dce option deprecated
when defined(Posix) and not defined(haiku): when defined(Posix):
{.passl: "-lm".} {.passl: "-lm".}
var var

View file

@ -49,7 +49,7 @@ proc fac*(n: int): int =
{.push checks:off, line_dir:off, stack_trace:off.} {.push checks:off, line_dir:off, stack_trace:off.}
when defined(Posix) and not defined(haiku): when defined(Posix):
{.passl: "-lm".} {.passl: "-lm".}
const const
@ -529,8 +529,8 @@ proc sgn*[T: SomeNumber](x: T): int {.inline.} =
{.pop.} {.pop.}
proc `^`*[T](x: T, y: Natural): T = proc `^`*[T](x: T, y: Natural): T =
## Computes ``x`` to the power ``y`. ``x`` must be non-negative, use ## Computes ``x`` to the power ``y``. ``x`` must be non-negative, use
## `pow <#pow,float,float>` for negative exponents. ## `pow <#pow,float,float>`_ for negative exponents.
when compiles(y >= T(0)): when compiles(y >= T(0)):
assert y >= T(0) assert y >= T(0)
else: else:

View file

@ -248,9 +248,10 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
hints.ai_socktype = toInt(sockType) hints.ai_socktype = toInt(sockType)
hints.ai_protocol = toInt(protocol) hints.ai_protocol = toInt(protocol)
# OpenBSD doesn't support AI_V4MAPPED and doesn't define the macro AI_V4MAPPED. # 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 # 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: if domain == AF_INET6:
hints.ai_flags = AI_V4MAPPED hints.ai_flags = AI_V4MAPPED
var gaiResult = getaddrinfo(address, $port, addr(hints), result) var gaiResult = getaddrinfo(address, $port, addr(hints), result)

View file

@ -129,7 +129,7 @@ proc get*[T](self: Option[T]): T =
## Returns contents of the Option. If it is none, then an exception is ## Returns contents of the Option. If it is none, then an exception is
## thrown. ## thrown.
if self.isNone: 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 self.val
proc get*[T](self: Option[T], otherwise: T): T = proc get*[T](self: Option[T], otherwise: T): T =
@ -139,6 +139,13 @@ proc get*[T](self: Option[T], otherwise: T): T =
else: else:
otherwise 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)) = proc map*[T](self: Option[T], callback: proc (input: T)) =
## Applies a callback to the value in this Option ## Applies a callback to the value in this Option
if self.isSome: if self.isSome:

View file

@ -615,7 +615,10 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
when not declared(ENOENT) and not defined(Windows): when not declared(ENOENT) and not defined(Windows):
when NoFakeVars: 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: else:
var ENOENT {.importc, header: "<errno.h>".}: cint var ENOENT {.importc, header: "<errno.h>".}: cint
@ -972,6 +975,14 @@ proc rawCreateDir(dir: string): bool =
result = false result = false
else: else:
raiseOSError(osLastError(), dir) 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): elif defined(posix):
let res = mkdir(dir, 0o777) let res = mkdir(dir, 0o777)
if res == 0'i32: if res == 0'i32:

View file

@ -892,7 +892,7 @@ else:
weekday {.importc: "tm_wday".}, weekday {.importc: "tm_wday".},
yearday {.importc: "tm_yday".}, yearday {.importc: "tm_yday".},
isdst {.importc: "tm_isdst".}: cint 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 gmtoff {.importc: "tm_gmtoff".}: clong
zone {.importc: "tm_zone".}: cstring zone {.importc: "tm_zone".}: cstring
type type

View file

@ -1327,7 +1327,7 @@ const
hostOS* {.magic: "HostOS".}: string = "" hostOS* {.magic: "HostOS".}: string = ""
## a string that describes the host operating system. Possible values: ## a string that describes the host operating system. Possible values:
## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris", ## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris",
## "aix", "standalone". ## "aix", "haiku", "standalone".
hostCPU* {.magic: "HostCPU".}: string = "" hostCPU* {.magic: "HostCPU".}: string = ""
## a string that describes the host CPU. Possible values: ## a string that describes the host CPU. Possible values:

View file

@ -59,6 +59,15 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or
SIGSEGV = cint(11) SIGSEGV = cint(11)
SIGTERM = cint(15) SIGTERM = cint(15)
SIGPIPE = cint(13) SIGPIPE = cint(13)
elif defined(haiku):
const
SIGABRT = cint(6)
SIGFPE = cint(8)
SIGILL = cint(4)
SIGINT = cint(2)
SIGSEGV = cint(11)
SIGTERM = cint(15)
SIGPIPE = cint(7)
else: else:
when NoFakeVars: when NoFakeVars:
{.error: "SIGABRT not ported to your platform".} {.error: "SIGABRT not ported to your platform".}
@ -74,6 +83,8 @@ else:
when defined(macosx): when defined(macosx):
const SIGBUS = cint(10) const SIGBUS = cint(10)
elif defined(haiku):
const SIGBUS = cint(30)
else: else:
template SIGBUS: untyped = SIGSEGV template SIGBUS: untyped = SIGSEGV

View file

@ -207,6 +207,9 @@ elif defined(posix):
# some arches like mips and alpha use different values # some arches like mips and alpha use different values
const MAP_ANONYMOUS = 0x20 const MAP_ANONYMOUS = 0x20
const MAP_PRIVATE = 0x02 # Changes are private const MAP_PRIVATE = 0x02 # Changes are private
elif defined(haiku):
const MAP_ANONYMOUS = 0x08
const MAP_PRIVATE = 0x02
else: else:
var var
MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint MAP_ANONYMOUS {.importc: "MAP_ANONYMOUS", header: "<sys/mman.h>".}: cint

View file

@ -162,10 +162,12 @@ elif defined(genode):
mainTls mainTls
else: else:
when not defined(macosx): when not (defined(macosx) or defined(haiku)):
{.passL: "-pthread".} {.passL: "-pthread".}
{.passC: "-pthread".} when not defined(haiku):
{.passC: "-pthread".}
const const
schedh = "#define _GNU_SOURCE\n#include <sched.h>" schedh = "#define _GNU_SOURCE\n#include <sched.h>"
pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>" pthreadh = "#define _GNU_SOURCE\n#include <pthread.h>"
@ -714,3 +716,13 @@ elif defined(solaris):
if threadId == 0: if threadId == 0:
threadId = int(thr_self()) threadId = int(thr_self())
result = threadId result = threadId
elif defined(haiku):
type thr_id {.importc: "thread_id", header: "<OS.h>".} = distinct int32
proc find_thread(name: cstring): thr_id {.importc, header: "<OS.h>".}
proc getThreadId*(): int =
## get the ID of the currently running thread.
if threadId == 0:
threadId = int(find_thread(nil))
result = threadId

View file

@ -0,0 +1,8 @@
proc foo[T](s: var openArray[T]): T =
for x in s: result += x
proc bar(xyz: var seq[int]) =
doAssert 6 == (seq[int](xyz)).foo()
var t = @[1,2,3]
bar(t)

13
tests/compiles/t8630.nim Normal file
View file

@ -0,0 +1,13 @@
discard """
output: '''
foo
bar
'''
"""
proc test(strings: seq[string]) =
for s in strings:
var p3 = unsafeAddr(s)
echo p3[]
test(@["foo", "bar"])

View file

@ -28,9 +28,12 @@ if paramCount() == 0:
# windows kill happens using TerminateProcess(h, 0), so we should get a # windows kill happens using TerminateProcess(h, 0), so we should get a
# 0 here # 0 here
echo p.waitForExit() == 0 echo p.waitForExit() == 0
elif defined(haiku):
# on Haiku, the program main thread receive SIGKILLTHR
echo p.waitForExit() == 128 + SIGKILLTHR
else: else:
# on posix (non-windows), kill sends SIGKILL # on posix (non-windows), kill sends SIGKILL
echo p.waitForExit() == 128 + SIGKILL echo p.waitForExit() == 128 + SIGKILL
else: else:
sleep(5000) # should get killed before this sleep(5000) # should get killed before this

View file

@ -12,6 +12,8 @@ else:
var process: Process var process: Process
when defined(android): when defined(android):
process = startProcess("/system/bin/env", "/system/bin", ["true"]) process = startProcess("/system/bin/env", "/system/bin", ["true"])
elif defined(haiku):
process = startProcess("/bin/env", "/bin", ["true"])
else: else:
process = startProcess("/usr/bin/env", "/usr/bin", ["true"]) process = startProcess("/usr/bin/env", "/usr/bin", ["true"])
let dir2 = getCurrentDir() let dir2 = getCurrentDir()

View file

@ -109,10 +109,14 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) =
safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll) safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)
else: else:
# posix relies on crappy LD_LIBRARY_PATH (ugh!): # posix relies on crappy LD_LIBRARY_PATH (ugh!):
var libpath = getEnv"LD_LIBRARY_PATH".string const libpathenv = when defined(haiku):
"LIBRARY_PATH"
else:
"LD_LIBRARY_PATH"
var libpath = getEnv(libpathenv).string
# Temporarily add the lib directory to LD_LIBRARY_PATH: # Temporarily add the lib directory to LD_LIBRARY_PATH:
putEnv("LD_LIBRARY_PATH", "tests/dll" & (if libpath.len > 0: ":" & libpath else: "")) putEnv(libpathenv, "tests/dll" & (if libpath.len > 0: ":" & libpath else: ""))
defer: putEnv("LD_LIBRARY_PATH", libpath) defer: putEnv(libpathenv, libpath)
var nimrtlDll = DynlibFormat % "nimrtl" var nimrtlDll = DynlibFormat % "nimrtl"
safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll) safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)