Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/devel' into pr#20694
Browse files Browse the repository at this point in the history
  • Loading branch information
ringabout committed Nov 1, 2022
2 parents c04c3e0 + d735c44 commit 00b798a
Show file tree
Hide file tree
Showing 22 changed files with 342 additions and 84 deletions.
7 changes: 6 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
- `PInt32`, `PInt64`, `PFloat32`, `PFloat64`, aliases to
`ptr int32`, `ptr int64`, `ptr float32`, `ptr float64`

- Enabling `-d:nimPreviewSlimSystem` removes the import of `channels_builtin` in
in the `system` module.

- The `gc:v2` option is removed.

- The `mainmodule` and `m` options are removed.
Expand Down Expand Up @@ -110,6 +113,8 @@
- `random.rand` now works with `Ordinal`s.
- Undeprecated `os.isvalidfilename`.
- `std/oids` now uses `int64` to store time internally (before it was int32).
- `std/uri.Uri` dollar `$` improved, precalculates the `string` result length from the `Uri`.


[//]: # "Additions:"
- Added ISO 8601 week date utilities in `times`:
Expand All @@ -120,7 +125,7 @@
- Added `getIsoWeeksInYear` to return the number of weeks in a week-based year.
- Added new modules which were part of `std/os`:
- Added `std/oserrors` for OS error reporting. Added `std/envvars` for environment variables handling.
- Added `std/paths`, `std/dirs`, `std/files`, `std/symlinks` and `std/appdirs`.
- Added `std/paths`, `std/dirs`, `std/files`, `std/symlinks` and `std/appdirs`.
- Added `sep` parameter in `std/uri` to specify the query separator.
- Added bindings to [`Array.shift`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
and [`queueMicrotask`](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
Expand Down
2 changes: 1 addition & 1 deletion compiler/closureiters.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: P
result = newType(tyArray, nextTypeId(idgen), owner)

let rng = newType(tyRange, nextTypeId(idgen), owner)
rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n))
rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n - 1))
rng.rawAddSon(t)

result.rawAddSon(rng)
Expand Down
11 changes: 6 additions & 5 deletions compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,16 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
of nkRecCase:
let discriminator = recNode[0]
var selectedBranch: int
let defaultValue = discriminator.sym.ast
var defaultValue = discriminator.sym.ast
if defaultValue == nil:
# None of the branches were explicitly selected by the user and no value
# was given to the discrimator. We can assume that it will be initialized
# to zero and this will select a particular branch as a result:
selectedBranch = recNode.pickCaseBranchIndex newIntNode(nkIntLit#[c.graph]#, 0)
else: # Try to use default value
selectedBranch = recNode.pickCaseBranchIndex defaultValue
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
defaultValue.typ = discriminator.typ
selectedBranch = recNode.pickCaseBranchIndex defaultValue
defaultValue.flags.incl nfUseDefaultField
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1])
of nkSym:
let field = recNode.sym
Expand Down
5 changes: 4 additions & 1 deletion compiler/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,10 @@ proc mutateType(t: PType, iter: TTypeMutator, closure: RootRef): PType =

proc valueToString(a: PNode): string =
case a.kind
of nkCharLit..nkUInt64Lit: result = $a.intVal
of nkCharLit, nkUIntLit..nkUInt64Lit:
result = $cast[uint64](a.intVal)
of nkIntLit..nkInt64Lit:
result = $a.intVal
of nkFloatLit..nkFloat128Lit: result = $a.floatVal
of nkStrLit..nkTripleStrLit: result = a.strVal
else: result = "<invalid value>"
Expand Down
4 changes: 0 additions & 4 deletions doc/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ Automatic imports
Basic Nim thread support. **Note:** This is part of the system module. Do not
import it explicitly. Enabled with `--threads:on`:option:.

* [channels_builtin](channels_builtin.html)
Nim message passing support for threads. **Note:** This is part of the
system module. Do not import it explicitly. Enabled with `--threads:on`:option:.


Core
----
Expand Down
21 changes: 21 additions & 0 deletions lib/genode/constructibles.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2022 Emery Hemingway
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#

type Constructible*[T] {.
importcpp: "Genode::Constructible",
header: "<util/reconstructible.h>", byref, pure.} = object

proc construct*[T](x: Constructible[T]) {.importcpp.}
## Construct a constructible C++ object.

proc destruct*[T](x: Constructible[T]) {.importcpp.}
## Destruct a constructible C++ object.

proc constructed*[T](x: Constructible[T]): bool {.importcpp.}
## Test if an object is constructed.
22 changes: 22 additions & 0 deletions lib/genode/entrypoints.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2022 Emery Hemingway
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#

## See `Genode Foundations - Entrypoint <https://genode.org/documentation/genode-foundations/21.05/functional_specification/Entrypoint.html>`
## for a description of Entrypoints.

type
EntrypointObj {.
importcpp: "Genode::Entrypoint",
header: "<base/entrypoint.h>",
pure.} = object
Entrypoint* = ptr EntrypointObj
## Opaque Entrypoint object.

proc ep*(env: GenodeEnv): Entrypoint {.importcpp: "(&#->ep())".}
## Access the entrypoint associated with `env`.
77 changes: 77 additions & 0 deletions lib/genode/signals.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#
#
# Nim's Runtime Library
# (c) Copyright 2022 Emery Hemingway
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#

## See `Genode Foundations - Asynchronous notifications <https://genode.org/documentation/genode-foundations/21.05/architecture/Inter-component_communication.html#Asynchronous_notifications>`
## for a description of Genode signals.

when not defined(genode) or defined(nimdoc):
{.error: "Genode only module".}

import ./entrypoints, ./constructibles

export ep # Entrypoint accessor on GenodeEnv

type
SignalContextCapability* {.
importcpp: "Genode::Signal_context_capability",
header: "<base/signal.h>", pure.} = object
## Capability to an asynchronous signal context.

proc isValid*(cap: SignalContextCapability): bool {.importcpp: "#.valid()".}
## Call the Genode core to check if this `SignalContextCapability` is valid.
# TODO: RpcEffect

type
HandlerProc = proc () {.closure, gcsafe.}

SignalHandlerBase {.
importcpp: "Nim::SignalHandler",
header: "genode_cpp/signals.h",
pure.} = object

SignalHandlerCpp = Constructible[SignalHandlerBase]

SignalHandlerObj = object
cpp: SignalHandlerCpp
cb: HandlerProc
## Signal handling procedure called during dispatch.

SignalHandler* = ref SignalHandlerObj
## Nim object enclosing a Genode signal handler.

proc construct(cpp: SignalHandlerCpp; ep: Entrypoint; sh: SignalHandler) {.importcpp.}

proc cap(cpp: SignalHandlerCpp): SignalContextCapability {.importcpp: "#->cap()".}

proc newSignalHandler*(ep: Entrypoint; cb: HandlerProc): SignalHandler =
## Create a new signal handler. A label is recommended for
## debugging purposes. A signal handler will not be garbage
## collected until after it has been dissolved.
result = SignalHandler(cb: cb)
result.cpp.construct(ep, result)
GCref result

proc dissolve*(sig: SignalHandler) =
## Dissolve signal dispatcher from entrypoint.
# TODO: =destroy?
destruct sig.cpp
sig.cb = nil # lose the callback
GCunref sig

proc cap*(sig: SignalHandler): SignalContextCapability =
## Signal context capability. Can be delegated to external components.
sig.cpp.cap

proc submit*(cap: SignalContextCapability) {.
importcpp: "Genode::Signal_transmitter(#).submit()".}
## Submit a signal to a context capability.

proc nimHandleSignal(p: pointer) {.exportc.} =
## C symbol invoked by entrypoint during signal dispatch.
cast[SignalHandler](p).cb()
39 changes: 39 additions & 0 deletions lib/genode_cpp/signals.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
*
* Nim's Runtime Library
* (c) Copyright 2022 Emery Hemingway
*
* See the file "copying.txt", included in this
* distribution, for details about the copyright.
*
*/

#ifndef _NIM_SIGNALS_H_
#define _NIM_SIGNALS_H_

#include <libc/component.h>
#include <base/signal.h>
#include <util/reconstructible.h>

// Symbol for calling back into Nim
extern "C" void nimHandleSignal(void *arg);

namespace Nim { struct SignalHandler; }

struct Nim::SignalHandler
{
// Pointer to the Nim handler object.
void *arg;

void handle_signal() {
Libc::with_libc([this] () { nimHandleSignal(arg); }); }

Genode::Signal_handler<SignalHandler> handler;

SignalHandler(Genode::Entrypoint *ep, void *arg)
: arg(arg), handler(*ep, *this, &SignalHandler::handle_signal) { }

Genode::Signal_context_capability cap() { return handler; }
};

#endif
3 changes: 3 additions & 0 deletions lib/impure/rdstdin.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ runnableExamples("-r:off"):
if line.len > 0: echo line
echo "exiting"

when defined(nimPreviewSlimSystem):
import std/syncio

when defined(windows):
proc readLineFromStdin*(prompt: string): string {.
tags: [ReadIOEffect, WriteIOEffect].} =
Expand Down
32 changes: 29 additions & 3 deletions lib/pure/asyncdispatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ proc adjustTimeout(
result = max(nextTimer.get(), 0)
result = min(pollTimeout, result)

proc runOnce(timeout: int): bool {.gcsafe.}

proc callSoon*(cbproc: proc () {.gcsafe.}) {.gcsafe.}
## Schedule `cbproc` to be called as soon as possible.
## The callback is called when control returns to the event loop.
Expand Down Expand Up @@ -390,7 +392,7 @@ when defined(windows) or defined(nimdoc):
let p = getGlobalDispatcher()
p.handles.len != 0 or p.timers.len != 0 or p.callbacks.len != 0

proc runOnce(timeout = 500): bool =
proc runOnce(timeout: int): bool =
let p = getGlobalDispatcher()
if p.handles.len == 0 and p.timers.len == 0 and p.callbacks.len == 0:
raise newException(ValueError,
Expand Down Expand Up @@ -1169,6 +1171,9 @@ else:
MSG_NOSIGNAL
when declared(posix.accept4):
from posix import accept4, SOCK_CLOEXEC
when defined(genode):
include genode/env # get the implicit Genode env
import genode/signals

const
InitCallbackListSize = 4 # initial size of callbacks sequence,
Expand All @@ -1187,6 +1192,8 @@ else:

PDispatcher* = ref object of PDispatcherBase
selector: Selector[AsyncData]
when defined(genode):
signalHandler: SignalHandler

proc `==`*(x, y: AsyncFD): bool {.borrow.}
proc `==`*(x, y: AsyncEvent): bool {.borrow.}
Expand All @@ -1202,6 +1209,10 @@ else:
result.selector = newSelector[AsyncData]()
result.timers.clear()
result.callbacks = initDeque[proc () {.closure, gcsafe.}](InitDelayedCallbackListSize)
when defined(genode):
let entrypoint = ep(cast[GenodeEnv](runtimeEnv))
result.signalHandler = newSignalHandler(entrypoint):
discard runOnce(0)

var gDisp{.threadvar.}: owned PDispatcher ## Global dispatcher

Expand Down Expand Up @@ -1371,10 +1382,11 @@ else:
ValueError, "Expecting async operations to stop when fd has closed."
)


proc runOnce(timeout = 500): bool =
proc runOnce(timeout: int): bool =
let p = getGlobalDispatcher()
if p.selector.isEmpty() and p.timers.len == 0 and p.callbacks.len == 0:
when defined(genode):
if timeout == 0: return
raise newException(ValueError,
"No handles or timers registered in dispatcher.")

Expand Down Expand Up @@ -2025,3 +2037,17 @@ when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
if getrlimit(RLIMIT_NOFILE, fdLim) < 0:
raiseOSError(osLastError())
result = int(fdLim.rlim_cur) - 1

when defined(genode):
proc scheduleCallbacks*(): bool {.discardable.} =
## *Genode only.*
## Schedule callback processing and return immediately.
## Returns `false` if there is nothing to schedule.
## RPC servers should call this to dispatch `callSoon`
## bodies after retiring an RPC to its client.
## This is effectively a non-blocking `poll(…)` and is
## equivalent to scheduling a momentary no-op timeout
## but faster and with less overhead.
let dis = getGlobalDispatcher()
result = dis.callbacks.len > 0
if result: submit(dis.signalHandler.cap)
1 change: 0 additions & 1 deletion lib/pure/collections/deques.nim
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ runnableExamples:
## See also
## ========
## * `lists module <lists.html>`_ for singly and doubly linked lists and rings
## * `channels module <channels_builtin.html>`_ for inter-thread communication

import std/private/since

Expand Down
1 change: 0 additions & 1 deletion lib/pure/concurrency/threadpool.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
## See also
## ========
## * `threads module <threads.html>`_ for basic thread support
## * `channels module <channels_builtin.html>`_ for message passing support
## * `locks module <locks.html>`_ for locks and condition variables
## * `asyncdispatch module <asyncdispatch.html>`_ for asynchronous IO

Expand Down
18 changes: 14 additions & 4 deletions lib/pure/streams.nim
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,20 @@ proc close*(s: Stream) =
## See also:
## * `flush proc <#flush,Stream>`_
runnableExamples:
var strm = newStringStream("The first line\nthe second line\nthe third line")
## do something...
strm.close()
if not isNil(s.closeImpl): s.closeImpl(s)
block:
let strm = newStringStream("The first line\nthe second line\nthe third line")
## do something...
strm.close()

block:
let strm = newFileStream("amissingfile.txt")
# deferring works even if newFileStream fails
defer: strm.close()
if not isNil(strm):
## do something...

if not isNil(s) and not isNil(s.closeImpl):
s.closeImpl(s)

proc atEnd*(s: Stream): bool =
## Checks if more data can be read from `s`. Returns ``true`` if all data has
Expand Down
Loading

0 comments on commit 00b798a

Please sign in to comment.