fixes merge conflict

This commit is contained in:
Andreas Rumpf
2018-06-11 01:25:48 +02:00
24 changed files with 360 additions and 105 deletions

View File

@@ -25,6 +25,8 @@ before_install:
before_script:
- set -e
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then unset -f cd; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then shell_session_update() { :; }; fi
- git clone --depth 1 https://github.com/nim-lang/csources.git
- cd csources
- sh build.sh

View File

@@ -42,6 +42,12 @@
- ``math.`mod` `` for floats now behaves the same as ``mod`` for integers
(previously it used floor division like Python). Use ``math.floorMod`` for the old behavior.
- For string inputs, ``unicode.isUpper`` and ``unicode.isLower`` now require a
second mandatory parameter ``skipNonAlpha``.
- For string inputs, ``strutils.isUpperAscii`` and ``strutils.isLowerAscii`` now
require a second mandatory parameter ``skipNonAlpha``.
#### Breaking changes in the compiler
- The undocumented ``#? braces`` parsing mode was removed.
@@ -91,6 +97,7 @@
API". Using the Nim compiler and its VM as a scripting engine has never been
easier. See ``tests/compilerapi/tcompilerapi.nim`` for an example of how to
use the Nim VM in a native Nim application.
- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc.
- The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated.

View File

@@ -731,8 +731,6 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
else: addAbiCheck(m, t, result)
of tyObject, tyTuple:
if isImportedCppType(t) and origTyp.kind == tyGenericInst:
# for instantiated templates we do not go through the type cache as the
# the type cache is not aware of 'tyGenericInst'.
let cppName = getTypeName(m, t, sig)
var i = 0
var chunkStart = 0

View File

@@ -1036,14 +1036,19 @@ proc genMainProc(m: BModule) =
"}$N$N"
GenodeNimMain =
"Libc::Env *genodeEnv;$N" &
"extern Genode::Env *nim_runtime_env;$N" &
"extern void nim_component_construct(Genode::Env*);$N$N" &
NimMainBody
ComponentConstruct =
"void Libc::Component::construct(Libc::Env &env) {$N" &
"\tgenodeEnv = &env;$N" &
"\t// Set Env used during runtime initialization$N" &
"\tnim_runtime_env = &env;$N" &
"\tLibc::with_libc([&] () {$N\t" &
"\t// Initialize runtime and globals$N" &
MainProcs &
"\t// Call application construct$N" &
"\t\tnim_component_construct(&env);$N" &
"\t});$N" &
"}$N$N"
@@ -1060,6 +1065,7 @@ proc genMainProc(m: BModule) =
elif m.config.target.targetOS == osGenode:
nimMain = GenodeNimMain
otherMain = ComponentConstruct
m.includeHeader("<libc/component.h>")
elif optGenDynLib in m.config.globalOptions:
nimMain = PosixNimDllMain
otherMain = PosixCDllMain

View File

@@ -496,7 +496,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
def = fitNode(c, typ, def, def.info)
#changeType(def.skipConv, typ, check=true)
else:
typ = skipIntLit(def.typ)
typ = def.typ.skipTypes({tyStatic}).skipIntLit
if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
typ = typ.lastSon
if hasEmpty(typ):

View File

@@ -12,7 +12,7 @@
import ast, md5, tables, ropes
from hashes import Hash
from astalgo import debug
from types import typeToString, preferDesc
import types
from strutils import startsWith, contains
when false:
@@ -148,19 +148,23 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
of tyGenericInvocation:
for i in countup(0, sonsLen(t) - 1):
c.hashType t.sons[i], flags
return
of tyDistinct:
if CoType in flags:
c.hashType t.lastSon, flags
else:
c.hashSym(t.sym)
return
of tyAlias, tySink, tyGenericInst, tyUserTypeClasses:
of tyGenericInst:
if sfInfixCall in t.base.sym.flags:
# This is an imported C++ generic type.
# We cannot trust the `lastSon` to hold a properly populated and unique
# value for each instantiation, so we hash the generic parameters here:
let normalizedType = t.skipGenericAlias
for i in 0 .. normalizedType.len - 2:
c.hashType t.sons[i], flags
else:
c.hashType t.lastSon, flags
of tyAlias, tySink, tyUserTypeClasses:
c.hashType t.lastSon, flags
return
else:
discard
case t.kind
of tyBool, tyChar, tyInt..tyUInt64:
# no canonicalization for integral types, so that e.g. ``pid_t`` is
# produced instead of ``NI``:
@@ -168,11 +172,12 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
if t.sym != nil and {sfImportc, sfExportc} * t.sym.flags != {}:
c.hashSym(t.sym)
of tyObject, tyEnum:
c &= char(t.kind)
if t.typeInst != nil:
assert t.typeInst.kind == tyGenericInst
for i in countup(1, sonsLen(t.typeInst) - 2):
for i in countup(0, sonsLen(t.typeInst) - 2):
c.hashType t.typeInst.sons[i], flags
return
c &= char(t.kind)
# Every cyclic type in Nim need to be constructed via some 't.sym', so this
# is actually safe without an infinite recursion check:
if t.sym != nil:

View File

@@ -8,10 +8,15 @@
#
# Low level dataspace allocator for Genode.
# For interacting with dataspaces outside of the
# standard library see the Genode Nimble package.
when not defined(genode):
{.error: "Genode only module".}
when not declared(GenodeEnv):
include genode/env
type DataspaceCapability {.
importcpp: "Genode::Dataspace_capability", pure.} = object
@@ -31,35 +36,35 @@ type
const SlabBackendSize = 4096
proc ramAvail(): int {.
importcpp: "genodeEnv->pd().avail_ram().value".}
proc ramAvail(env: GenodeEnv): int {.
importcpp: "#->pd().avail_ram().value".}
## Return number of bytes available for allocation.
proc capsAvail(): int {.
importcpp: "genodeEnv->pd().avail_caps().value".}
proc capsAvail(env: GenodeEnv): int {.
importcpp: "#->pd().avail_caps().value".}
## Return the number of available capabilities.
## Each dataspace allocation consumes a capability.
proc allocDataspace(size: int): DataspaceCapability {.
importcpp: "genodeEnv->pd().alloc(@)".}
proc allocDataspace(env: GenodeEnv; size: int): DataspaceCapability {.
importcpp: "#->pd().alloc(@)".}
## Allocate a dataspace and its capability.
proc attachDataspace(ds: DataspaceCapability): pointer {.
importcpp: "genodeEnv->rm().attach(@)".}
proc attachDataspace(env: GenodeEnv; ds: DataspaceCapability): pointer {.
importcpp: "#->rm().attach(@)".}
## Attach a dataspace into the component address-space.
proc detachAddress(p: pointer) {.
importcpp: "genodeEnv->rm().detach(@)".}
proc detachAddress(env: GenodeEnv; p: pointer) {.
importcpp: "#->rm().detach(@)".}
## Detach a dataspace from the component address-space.
proc freeDataspace(ds: DataspaceCapability) {.
importcpp: "genodeEnv->pd().free(@)".}
proc freeDataspace(env: GenodeEnv; ds: DataspaceCapability) {.
importcpp: "#->pd().free(@)".}
## Free a dataspace.
proc newMapSlab(): ptr MapSlab =
let
ds = allocDataspace SlabBackendSize
p = attachDataspace ds
ds = runtimeEnv.allocDataspace SlabBackendSize
p = runtimeEnv.attachDataspace ds
result = cast[ptr MapSlab](p)
result.meta.ds = ds
@@ -89,13 +94,13 @@ proc osAllocPages(size: int): pointer =
# tack a new slab on the tail
slab = slab.meta.next
# move to next slab in linked list
map.ds = allocDataspace size
map.ds = runtimeEnv.allocDataspace size
map.size = size
map.attachment = attachDataspace map.ds
map.attachment = runtimeEnv.attachDataspace map.ds
result = map.attachment
proc osTryAllocPages(size: int): pointer =
if ramAvail() >= size and capsAvail() > 1:
if runtimeEnv.ramAvail() >= size and runtimeEnv.capsAvail() > 4:
result = osAllocPages size
proc osDeallocPages(p: pointer; size: int) =
@@ -107,8 +112,8 @@ proc osDeallocPages(p: pointer; size: int) =
if m.size != size:
echo "cannot partially detach dataspace"
quit -1
detachAddress m.attachment
freeDataspace m.ds
runtimeEnv.detachAddress m.attachment
runtimeEnv.freeDataspace m.ds
m[] = Map()
return
slab = slab.meta.next

29
lib/genode/env.nim Normal file
View File

@@ -0,0 +1,29 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2018 Emery Hemingway
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
#
# This file contains the minimum required definitions
# for interacting with the initial Genode environment.
# It is reserved for use only within the standard
# library. See ``componentConstructHook`` in the system
# module for accessing the Genode environment after the
# standard library has finished initializating.
#
when not defined(genode):
{.error: "Genode only include".}
type
GenodeEnvObj {.importcpp: "Genode::Env", header: "<base/env.h>", pure.} = object
GenodeEnvPtr = ptr GenodeEnvObj
const runtimeEnvSym = "nim_runtime_env"
when not defined(nimscript):
var runtimeEnv {.importcpp: runtimeEnvSym.}: GenodeEnvPtr

View File

@@ -13,6 +13,7 @@
#define _GENODE_CPP__THREAD_H_
#include <base/thread.h>
#include <base/env.h>
#include <util/reconstructible.h>
namespace Nim { struct SysThread; }

View File

@@ -502,11 +502,6 @@ typedef int Nim_and_C_compiler_disagree_on_target_architecture[sizeof(NI) == siz
# include <sys/types.h>
#endif
#if defined(__GENODE__)
#include <libc/component.h>
extern Libc::Env *genodeEnv;
#endif
/* Compile with -d:checkAbi and a sufficiently C11:ish compiler to enable */
#define NIM_CHECK_SIZE(typ, sz) \
_Static_assert(sizeof(typ) == sz, "Nim & C disagree on type size")

View File

@@ -129,6 +129,20 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
proc sendStatus(client: AsyncSocket, status: string): Future[void] =
client.send("HTTP/1.1 " & status & "\c\L\c\L")
proc parseUppercaseMethod(name: string): HttpMethod =
result =
case name
of "GET": HttpGet
of "POST": HttpPost
of "HEAD": HttpHead
of "PUT": HttpPut
of "DELETE": HttpDelete
of "PATCH": HttpPatch
of "OPTIONS": HttpOptions
of "CONNECT": HttpConnect
of "TRACE": HttpTrace
else: raise newException(ValueError, "Invalid HTTP method " & name)
proc processRequest(server: AsyncHttpServer, req: FutureVar[Request],
client: AsyncSocket,
address: string, lineFut: FutureVar[string],
@@ -172,8 +186,7 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request],
case i
of 0:
try:
# TODO: this is likely slow.
request.reqMethod = parseEnum[HttpMethod]("http" & linePart)
request.reqMethod = parseUppercaseMethod(linePart)
except ValueError:
asyncCheck request.respondError(Http400)
return

View File

@@ -165,16 +165,18 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
proc inc*(c: var CritBitTree[int]; key: string, val: int = 1) =
## increments `c[key]` by `val`.
let oldCount = c.count
var n = rawInsert(c, key)
if c.count >= oldCount or oldCount == 0:
# not a new key:
inc n.val, val
inc n.val, val
proc incl*(c: var CritBitTree[void], key: string) =
## includes `key` in `c`.
discard rawInsert(c, key)
proc incl*[T](c: var CritBitTree[T], key: string, val: T) =
## inserts `key` with value `val` into `c`.
var n = rawInsert(c, key)
n.val = val
proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) =
## puts a (key, value)-pair into `t`.
var n = rawInsert(c, key)
@@ -375,3 +377,18 @@ when isMainModule:
c.inc("a", 1)
assert c["a"] == 1
var cf = CritBitTree[float]()
cf.incl("a", 1.0)
assert cf["a"] == 1.0
cf.incl("b", 2.0)
assert cf["b"] == 2.0
cf.incl("c", 3.0)
assert cf["c"] == 3.0
assert cf.len == 3
cf.excl("c")
assert cf.len == 2

View File

@@ -38,8 +38,10 @@ when defined(macosx) or defined(bsd):
importc: "sysctl", nodecl.}
when defined(genode):
proc affinitySpaceTotal(): cuint {.
importcpp: "genodeEnv->cpu().affinity_space().total()".}
include genode/env
proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
importcpp: "@->cpu().affinity_space().total()".}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has.
@@ -83,7 +85,7 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
result = sysconf(SC_NPROC_ONLN)
elif defined(genode):
result = affinitySpaceTotal().int
result = runtimeEnv.affinitySpaceTotal().int
else:
result = sysconf(SC_NPROCESSORS_ONLN)
if result <= 0: result = 0

View File

@@ -447,7 +447,7 @@ proc fromSockAddr*(sa: Sockaddr_storage | SockAddr | Sockaddr_in | Sockaddr_in6,
sl: Socklen, address: var IpAddress, port: var Port) {.inline.} =
## Converts `SockAddr` and `Socklen` to `IpAddress` and `Port`. Raises
## `ObjectConversionError` in case of invalid `sa` and `sl` arguments.
fromSockAddrAux(unsafeAddr sa, sl, address, port)
fromSockAddrAux(cast[ptr Sockaddr_storage](unsafeAddr sa), sl, address, port)
when defineSsl:
CRYPTO_malloc_init()

View File

@@ -1440,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
elif defined(solaris):
result = getApplAux("/proc/" & $getpid() & "/path/a.out")
elif defined(genode):
raiseOSError("POSIX command line not supported")
raiseOSError(OSErrorCode(-1), "POSIX command line not supported")
elif defined(freebsd) or defined(dragonfly):
result = getApplFreebsd()
# little heuristic that may work on other POSIX-like systems:

View File

@@ -150,23 +150,52 @@ proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
## characters and there is at least one character in `s`.
isImpl isSpaceAscii
proc isLowerAscii*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nsuIsLowerAsciiStr".} =
## Checks whether or not `s` contains all lower case characters.
##
## This checks ASCII characters only.
## Returns true if all characters in `s` are lower case
## and there is at least one character in `s`.
isImpl isLowerAscii
template isCaseImpl(s, charProc, skipNonAlpha) =
var hasAtleastOneAlphaChar = false
if s.len == 0: return false
for c in s:
if skipNonAlpha:
var charIsAlpha = c.isAlphaAscii()
if not hasAtleastOneAlphaChar:
hasAtleastOneAlphaChar = charIsAlpha
if charIsAlpha and (not charProc(c)):
return false
else:
if not charProc(c):
return false
return if skipNonAlpha: hasAtleastOneAlphaChar else: true
proc isUpperAscii*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nsuIsUpperAsciiStr".} =
## Checks whether or not `s` contains all upper case characters.
proc isLowerAscii*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is lower case.
##
## This checks ASCII characters only.
## Returns true if all characters in `s` are upper case
## and there is at least one character in `s`.
isImpl isUpperAscii
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## characters in ``s`` are lower case. Returns false if none of the
## characters in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all characters
## in ``s`` are alphabetical and lower case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
isCaseImpl(s, isLowerAscii, skipNonAlpha)
proc isUpperAscii*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is upper case.
##
## This checks ASCII characters only.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## characters in ``s`` are upper case. Returns false if none of the
## characters in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all characters
## in ``s`` are alphabetical and upper case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
isCaseImpl(s, isUpperAscii, skipNonAlpha)
proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
rtl, extern: "nsuToLowerAsciiChar".} =
@@ -2516,19 +2545,34 @@ when isMainModule:
doAssert(not isLowerAscii('A'))
doAssert(not isLowerAscii('5'))
doAssert(not isLowerAscii('&'))
doAssert(not isLowerAscii(' '))
doAssert isLowerAscii("abcd")
doAssert(not isLowerAscii("abCD"))
doAssert(not isLowerAscii("33aa"))
doAssert isLowerAscii("abcd", false)
doAssert(not isLowerAscii("33aa", false))
doAssert(not isLowerAscii("a b", false))
doAssert(not isLowerAscii("abCD", true))
doAssert isLowerAscii("33aa", true)
doAssert isLowerAscii("a b", true)
doAssert isLowerAscii("1, 2, 3 go!", true)
doAssert(not isLowerAscii(" ", true))
doAssert(not isLowerAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets
doAssert isUpperAscii('A')
doAssert(not isUpperAscii('b'))
doAssert(not isUpperAscii('5'))
doAssert(not isUpperAscii('%'))
doAssert isUpperAscii("ABC")
doAssert(not isUpperAscii("AAcc"))
doAssert(not isUpperAscii("A#$"))
doAssert isUpperAscii("ABC", false)
doAssert(not isUpperAscii("A#$", false))
doAssert(not isUpperAscii("A B", false))
doAssert(not isUpperAscii("AAcc", true))
doAssert isUpperAscii("A#$", true)
doAssert isUpperAscii("A B", true)
doAssert isUpperAscii("1, 2, 3 GO!", true)
doAssert(not isUpperAscii(" ", true))
doAssert(not isUpperAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets
doAssert rsplit("foo bar", seps=Whitespace) == @["foo", "bar"]
doAssert rsplit(" foo bar", seps=Whitespace, maxsplit=1) == @[" foo", "bar"]
@@ -2601,4 +2645,3 @@ bar
nonStaticTests()
staticTests()
static: staticTests()

View File

@@ -1392,7 +1392,7 @@ proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
(c >= 0xfe20 and c <= 0xfe2f))
template runeCheck(s, runeProc) =
## Common code for rune.isLower, rune.isUpper, etc
## Common code for isAlpha and isSpace.
result = if len(s) == 0: false else: true
var
@@ -1403,16 +1403,6 @@ template runeCheck(s, runeProc) =
fastRuneAt(s, i, rune, doInc=true)
result = runeProc(rune) and result
proc isUpper*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all upper case unicode characters.
runeCheck(s, isUpper)
proc isLower*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all lower case unicode characters.
runeCheck(s, isLower)
proc isAlpha*(s: string): bool {.noSideEffect, procvar,
rtl, extern: "nuc$1Str".} =
## Returns true iff `s` contains all alphabetic unicode characters.
@@ -1423,6 +1413,56 @@ proc isSpace*(s: string): bool {.noSideEffect, procvar,
## Returns true iff `s` contains all whitespace unicode characters.
runeCheck(s, isWhiteSpace)
template runeCaseCheck(s, runeProc, skipNonAlpha) =
## Common code for rune.isLower and rune.isUpper.
if len(s) == 0: return false
var
i = 0
rune: Rune
hasAtleastOneAlphaRune = false
while i < len(s):
fastRuneAt(s, i, rune, doInc=true)
if skipNonAlpha:
var runeIsAlpha = isAlpha(rune)
if not hasAtleastOneAlphaRune:
hasAtleastOneAlphaRune = runeIsAlpha
if runeIsAlpha and (not runeProc(rune)):
return false
else:
if not runeProc(rune):
return false
return if skipNonAlpha: hasAtleastOneAlphaRune else: true
proc isLower*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is lower case.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## runes in ``s`` are lower case. Returns false if none of the
## runes in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all runes in
## ``s`` are alphabetical and lower case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runeCaseCheck(s, isLower, skipNonAlpha)
proc isUpper*(s: string, skipNonAlpha: bool): bool =
## Checks whether ``s`` is upper case.
##
## If ``skipNonAlpha`` is true, returns true if all alphabetical
## runes in ``s`` are upper case. Returns false if none of the
## runes in ``s`` are alphabetical.
##
## If ``skipNonAlpha`` is false, returns true only if all runes in
## ``s`` are alphabetical and upper case.
##
## For either value of ``skipNonAlpha``, returns false if ``s`` is
## an empty string.
runeCaseCheck(s, isUpper, skipNonAlpha)
template convertRune(s, runeProc) =
## Convert runes in `s` using `runeProc` as the converter.
result = newString(len(s))
@@ -1755,25 +1795,39 @@ when isMainModule:
doAssert(not isSpace(""))
doAssert(not isSpace("ΑΓc \td"))
doAssert isLower("a")
doAssert isLower("γ")
doAssert(not isLower("Γ"))
doAssert(not isLower("4"))
doAssert(not isLower(""))
doAssert(not isLower(' '.Rune))
doAssert isLower("abcdγ")
doAssert(not isLower("abCDΓ"))
doAssert(not isLower("33aaΓ"))
doAssert isLower("a", false)
doAssert isLower("γ", true)
doAssert(not isLower("Γ", false))
doAssert(not isLower("4", true))
doAssert(not isLower("", false))
doAssert isLower("abcdγ", false)
doAssert(not isLower("33aaΓ", false))
doAssert(not isLower("a b", false))
doAssert isUpper("Γ")
doAssert(not isUpper("b"))
doAssert(not isUpper("α"))
doAssert(not isUpper(""))
doAssert(not isUpper(""))
doAssert(not isLower("abCDΓ", true))
doAssert isLower("a b", true)
doAssert isLower("1, 2, 3 go!", true)
doAssert(not isLower(" ", true))
doAssert(not isLower("(*&#@(^#$", true)) # None of the string runes are alphabets
doAssert isUpper("ΑΒΓ")
doAssert(not isUpper("AAccβ"))
doAssert(not isUpper("A#"))
doAssert(not isUpper(' '.Rune))
doAssert isUpper("Γ", false)
doAssert(not isUpper("α", false))
doAssert(not isUpper("", false))
doAssert isUpper("ΑΒΓ", false)
doAssert(not isUpper("A#", false))
doAssert(not isUpper("A B", false))
doAssert(not isUpper("b", true))
doAssert(not isUpper("", true))
doAssert(not isUpper("AAccβ", true))
doAssert isUpper("A B", true)
doAssert isUpper("1, 2, 3 GO!", true)
doAssert(not isUpper(" ", true))
doAssert(not isUpper("(*&#@(^#$", true)) # None of the string runes are alphabets
doAssert toUpper("Γ") == "Γ"
doAssert toUpper("b") == "B"

View File

@@ -1498,11 +1498,21 @@ when defined(nimdoc):
## macro, use the `error <manual.html#error-pragma>`_ or `fatal
## <manual.html#fatal-pragma>`_ pragmas.
elif defined(genode):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn,
importcpp: "genodeEnv->parent().exit(@); Genode::sleep_forever()",
header: "<base/sleep.h>".}
include genode/env
var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr
type GenodeEnv* = GenodeEnvPtr
## Opaque type representing Genode environment.
proc quit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn,
importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".}
proc quit*(errorcode: int = QuitSuccess) =
systemEnv.quit(errorCode)
elif defined(nodejs):
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit",
@@ -4215,3 +4225,22 @@ when not defined(js):
type
ForLoopStmt* {.compilerProc.} = object ## special type that marks a macro
## as a `for-loop macro`:idx:
when defined(genode):
var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.}
## Hook into the Genode component bootstrap process.
## This hook is called after all globals are initialized.
## When this hook is set the component will not automatically exit,
## call ``quit`` explicitly to do so. This is the only available method
## of accessing the initial Genode environment.
proc nim_component_construct(env: GenodeEnv) {.exportc.} =
## Procedure called during ``Component::construct`` by the loader.
if componentConstructHook.isNil:
env.quit(programResult)
# No native Genode application initialization,
# exit as would POSIX.
else:
componentConstructHook(env)
# Perform application initialization
# and return to thread entrypoint.

View File

@@ -78,7 +78,7 @@ when defined(emscripten):
munmap(mmapDescr.realPointer, mmapDescr.realSize)
elif defined(genode):
include genodealloc # osAllocPages, osTryAllocPages, osDeallocPages
include genode/alloc # osAllocPages, osTryAllocPages, osDeallocPages
elif defined(posix):
const

View File

@@ -116,6 +116,7 @@ when defined(windows):
importc: "SetThreadAffinityMask", stdcall, header: "<windows.h>".}
elif defined(genode):
import genode/env
const
GenodeHeader = "genode_cpp/threads.h"
type
@@ -125,11 +126,12 @@ elif defined(genode):
ThreadVarSlot = int
proc initThread(s: var SysThread,
env: GenodeEnv,
stackSize: culonglong,
entry: GenodeThreadProc,
arg: pointer,
affinity: cuint) {.
importcpp: "#.initThread(genodeEnv, @)".}
importcpp: "#.initThread(@)".}
proc threadVarAlloc(): ThreadVarSlot = 0
@@ -569,7 +571,7 @@ when hostOS == "windows":
elif defined(genode):
var affinityOffset: cuint = 1
# CPU affinity offset for next thread, safe to roll-over
## CPU affinity offset for next thread, safe to roll-over
proc createThread*[TArg](t: var Thread[TArg],
tp: proc (arg: TArg) {.thread, nimcall.},
@@ -580,6 +582,7 @@ elif defined(genode):
t.dataFn = tp
when hasSharedHeap: t.stackSize = ThreadStackSize
t.sys.initThread(
runtimeEnv,
ThreadStackSize.culonglong,
threadProcWrapper[TArg], addr(t), affinityOffset)
inc affinityOffset

View File

@@ -44,6 +44,10 @@ else:
const
DLLSSLName* = "libssl" & versions & ".dylib"
DLLUtilName* = "libcrypto" & versions & ".dylib"
elif defined(genode):
const
DLLSSLName* = "libssl.lib.so"
DLLUtilName* = "libcrypto.lib.so"
else:
const
DLLSSLName* = "libssl.so" & versions

View File

@@ -20,3 +20,19 @@ v.doSomething()
var vf = initVector[float]()
vf.doSomething() # Nim uses doSomething[int] here in C++
# Alternative definition:
# https://github.com/nim-lang/Nim/issues/7653
type VectorAlt* {.importcpp: "std::vector", header: "<vector>", nodecl.} [T] = object
proc mkVector*[T]: VectorAlt[T] {.importcpp: "std::vector<'*0>()", header: "<vector>", constructor, nodecl.}
proc foo(): VectorAlt[cint] =
mkVector[cint]()
proc bar(): VectorAlt[cstring] =
mkVector[cstring]()
var x = foo()
var y = bar()

14
tests/generics/t3977.nim Normal file
View File

@@ -0,0 +1,14 @@
discard """
output: "42\n42"
"""
type
Foo[N: static[int]] = object
proc foo[N](x: Foo[N]) =
let n = N
echo N
echo n
var f1: Foo[42]
f1.foo

View File

@@ -66,6 +66,18 @@ block: # "IpAddress/Sockaddr conversion"
doAssert(ipaddr_1 == ipaddr_2)
doAssert($ipaddr_1 == $ipaddr_2)
if sockaddr.ss_family == AF_INET.toInt:
var sockaddr4: Sockaddr_in
copyMem(addr sockaddr4, addr sockaddr, sizeof(sockaddr4))
fromSockAddr(sockaddr4, socklen, ipaddr_2, port_2)
elif sockaddr.ss_family == AF_INET6.toInt:
var sockaddr6: Sockaddr_in6
copyMem(addr sockaddr6, addr sockaddr, sizeof(sockaddr6))
fromSockAddr(sockaddr6, socklen, ipaddr_2, port_2)
doAssert(ipaddr_1 == ipaddr_2)
doAssert($ipaddr_1 == $ipaddr_2)
# ipv6 address of example.com
test("2606:2800:220:1:248:1893:25c8:1946")