proper distinction between --gc:none and --os:standalone
This commit is contained in:
parent
8f58ab99eb
commit
a1caef474b
7 changed files with 62 additions and 261 deletions
|
|
@ -1,226 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nim's Runtime Library
|
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
## This module implements portable dialogs for Nim; the implementation
|
|
||||||
## builds on the GTK interface. On Windows, native dialogs are shown instead.
|
|
||||||
|
|
||||||
import
|
|
||||||
glib2, gtk2
|
|
||||||
|
|
||||||
when defined(Windows):
|
|
||||||
import windows, ShellAPI, os
|
|
||||||
|
|
||||||
proc info*(window: PWindow, msg: string) =
|
|
||||||
## Shows an information message to the user. The process waits until the
|
|
||||||
## user presses the OK button.
|
|
||||||
when defined(Windows):
|
|
||||||
discard MessageBoxA(0, msg, "Information", MB_OK or MB_ICONINFORMATION)
|
|
||||||
else:
|
|
||||||
var dialog = message_dialog_new(window,
|
|
||||||
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
||||||
MESSAGE_INFO, BUTTONS_OK, "%s", cstring(msg))
|
|
||||||
setTitle(dialog, "Information")
|
|
||||||
discard run(dialog)
|
|
||||||
destroy(PWidget(dialog))
|
|
||||||
|
|
||||||
proc warning*(window: PWindow, msg: string) =
|
|
||||||
## Shows a warning message to the user. The process waits until the user
|
|
||||||
## presses the OK button.
|
|
||||||
when defined(Windows):
|
|
||||||
discard MessageBoxA(0, msg, "Warning", MB_OK or MB_ICONWARNING)
|
|
||||||
else:
|
|
||||||
var dialog = DIALOG(message_dialog_new(window,
|
|
||||||
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
||||||
MESSAGE_WARNING, BUTTONS_OK, "%s", cstring(msg)))
|
|
||||||
setTitle(dialog, "Warning")
|
|
||||||
discard run(dialog)
|
|
||||||
destroy(PWidget(dialog))
|
|
||||||
|
|
||||||
proc error*(window: PWindow, msg: string) =
|
|
||||||
## Shows an error message to the user. The process waits until the user
|
|
||||||
## presses the OK button.
|
|
||||||
when defined(Windows):
|
|
||||||
discard MessageBoxA(0, msg, "Error", MB_OK or MB_ICONERROR)
|
|
||||||
else:
|
|
||||||
var dialog = DIALOG(message_dialog_new(window,
|
|
||||||
DIALOG_MODAL or DIALOG_DESTROY_WITH_PARENT,
|
|
||||||
MESSAGE_ERROR, BUTTONS_OK, "%s", cstring(msg)))
|
|
||||||
setTitle(dialog, "Error")
|
|
||||||
discard run(dialog)
|
|
||||||
destroy(PWidget(dialog))
|
|
||||||
|
|
||||||
|
|
||||||
proc chooseFileToOpen*(window: PWindow, root: string = ""): string =
|
|
||||||
## Opens a dialog that requests a filename from the user. Returns ""
|
|
||||||
## if the user closed the dialog without selecting a file. On Windows,
|
|
||||||
## the native dialog is used, else the GTK dialog is used.
|
|
||||||
when defined(Windows):
|
|
||||||
var
|
|
||||||
opf: TOPENFILENAME
|
|
||||||
buf: array [0..2047, char]
|
|
||||||
opf.lStructSize = sizeof(opf).int32
|
|
||||||
if root.len > 0:
|
|
||||||
opf.lpstrInitialDir = root
|
|
||||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
||||||
opf.flags = OFN_FILEMUSTEXIST
|
|
||||||
opf.lpstrFile = buf
|
|
||||||
opf.nMaxFile = sizeof(buf).int32
|
|
||||||
var res = GetOpenFileName(addr(opf))
|
|
||||||
if res != 0:
|
|
||||||
result = $buf
|
|
||||||
else:
|
|
||||||
result = ""
|
|
||||||
else:
|
|
||||||
var chooser = file_chooser_dialog_new("Open File", window,
|
|
||||||
FILE_CHOOSER_ACTION_OPEN,
|
|
||||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
||||||
STOCK_OPEN, RESPONSE_OK, nil)
|
|
||||||
if root.len > 0:
|
|
||||||
discard set_current_folder(chooser, root)
|
|
||||||
if run(chooser) == cint(RESPONSE_OK):
|
|
||||||
var x = get_filename(chooser)
|
|
||||||
result = $x
|
|
||||||
g_free(x)
|
|
||||||
else:
|
|
||||||
result = ""
|
|
||||||
destroy(PWidget(chooser))
|
|
||||||
|
|
||||||
proc chooseFilesToOpen*(window: PWindow, root: string = ""): seq[string] =
|
|
||||||
## Opens a dialog that requests filenames from the user. Returns ``@[]``
|
|
||||||
## if the user closed the dialog without selecting a file. On Windows,
|
|
||||||
## the native dialog is used, else the GTK dialog is used.
|
|
||||||
when defined(Windows):
|
|
||||||
var
|
|
||||||
opf: TOPENFILENAME
|
|
||||||
buf: array [0..2047*4, char]
|
|
||||||
opf.lStructSize = sizeof(opf).int32
|
|
||||||
if root.len > 0:
|
|
||||||
opf.lpstrInitialDir = root
|
|
||||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
||||||
opf.flags = OFN_FILEMUSTEXIST or OFN_ALLOWMULTISELECT or OFN_EXPLORER
|
|
||||||
opf.lpstrFile = buf
|
|
||||||
opf.nMaxFile = sizeof(buf).int32
|
|
||||||
var res = GetOpenFileName(addr(opf))
|
|
||||||
result = @[]
|
|
||||||
if res != 0:
|
|
||||||
# parsing the result is horrible:
|
|
||||||
var
|
|
||||||
i = 0
|
|
||||||
s: string
|
|
||||||
path = ""
|
|
||||||
while buf[i] != '\0':
|
|
||||||
add(path, buf[i])
|
|
||||||
inc(i)
|
|
||||||
inc(i)
|
|
||||||
if buf[i] != '\0':
|
|
||||||
while true:
|
|
||||||
s = ""
|
|
||||||
while buf[i] != '\0':
|
|
||||||
add(s, buf[i])
|
|
||||||
inc(i)
|
|
||||||
add(result, s)
|
|
||||||
inc(i)
|
|
||||||
if buf[i] == '\0': break
|
|
||||||
for i in 0..result.len-1: result[i] = os.joinPath(path, result[i])
|
|
||||||
else:
|
|
||||||
# only one file selected --> gosh, what an ungly thing
|
|
||||||
# the windows API is
|
|
||||||
add(result, path)
|
|
||||||
else:
|
|
||||||
var chooser = file_chooser_dialog_new("Open Files", window,
|
|
||||||
FILE_CHOOSER_ACTION_OPEN,
|
|
||||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
||||||
STOCK_OPEN, RESPONSE_OK, nil)
|
|
||||||
if root.len > 0:
|
|
||||||
discard set_current_folder(chooser, root)
|
|
||||||
set_select_multiple(chooser, true)
|
|
||||||
result = @[]
|
|
||||||
if run(chooser) == cint(RESPONSE_OK):
|
|
||||||
var L = get_filenames(chooser)
|
|
||||||
var it = L
|
|
||||||
while it != nil:
|
|
||||||
add(result, $cast[cstring](it.data))
|
|
||||||
g_free(it.data)
|
|
||||||
it = it.next
|
|
||||||
free(L)
|
|
||||||
destroy(PWidget(chooser))
|
|
||||||
|
|
||||||
|
|
||||||
proc chooseFileToSave*(window: PWindow, root: string = ""): string =
|
|
||||||
## Opens a dialog that requests a filename to save to from the user.
|
|
||||||
## Returns "" if the user closed the dialog without selecting a file.
|
|
||||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
|
||||||
when defined(Windows):
|
|
||||||
var
|
|
||||||
opf: TOPENFILENAME
|
|
||||||
buf: array [0..2047, char]
|
|
||||||
opf.lStructSize = sizeof(opf).int32
|
|
||||||
if root.len > 0:
|
|
||||||
opf.lpstrInitialDir = root
|
|
||||||
opf.lpstrFilter = "All Files\0*.*\0\0"
|
|
||||||
opf.flags = OFN_OVERWRITEPROMPT
|
|
||||||
opf.lpstrFile = buf
|
|
||||||
opf.nMaxFile = sizeof(buf).int32
|
|
||||||
var res = GetSaveFileName(addr(opf))
|
|
||||||
if res != 0:
|
|
||||||
result = $buf
|
|
||||||
else:
|
|
||||||
result = ""
|
|
||||||
else:
|
|
||||||
var chooser = file_chooser_dialog_new("Save File", window,
|
|
||||||
FILE_CHOOSER_ACTION_SAVE,
|
|
||||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
||||||
STOCK_SAVE, RESPONSE_OK, nil)
|
|
||||||
if root.len > 0:
|
|
||||||
discard set_current_folder(chooser, root)
|
|
||||||
set_do_overwrite_confirmation(chooser, true)
|
|
||||||
if run(chooser) == cint(RESPONSE_OK):
|
|
||||||
var x = get_filename(chooser)
|
|
||||||
result = $x
|
|
||||||
g_free(x)
|
|
||||||
else:
|
|
||||||
result = ""
|
|
||||||
destroy(PWidget(chooser))
|
|
||||||
|
|
||||||
|
|
||||||
proc chooseDir*(window: PWindow, root: string = ""): string =
|
|
||||||
## Opens a dialog that requests a directory from the user.
|
|
||||||
## Returns "" if the user closed the dialog without selecting a directory.
|
|
||||||
## On Windows, the native dialog is used, else the GTK dialog is used.
|
|
||||||
when defined(Windows):
|
|
||||||
var
|
|
||||||
lpItemID: PItemIDList
|
|
||||||
BrowseInfo: TBrowseInfo
|
|
||||||
DisplayName: array [0..MAX_PATH, char]
|
|
||||||
TempPath: array [0..MAX_PATH, char]
|
|
||||||
result = ""
|
|
||||||
#BrowseInfo.hwndOwner = Application.Handle
|
|
||||||
BrowseInfo.pszDisplayName = DisplayName
|
|
||||||
BrowseInfo.ulFlags = 1 #BIF_RETURNONLYFSDIRS
|
|
||||||
lpItemID = SHBrowseForFolder(cast[LPBrowseInfo](addr(BrowseInfo)))
|
|
||||||
if lpItemId != nil:
|
|
||||||
discard SHGetPathFromIDList(lpItemID, TempPath)
|
|
||||||
result = $TempPath
|
|
||||||
discard GlobalFreePtr(lpItemID)
|
|
||||||
else:
|
|
||||||
var chooser = file_chooser_dialog_new("Select Directory", window,
|
|
||||||
FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
||||||
STOCK_CANCEL, RESPONSE_CANCEL,
|
|
||||||
STOCK_OPEN, RESPONSE_OK, nil)
|
|
||||||
if root.len > 0:
|
|
||||||
discard set_current_folder(chooser, root)
|
|
||||||
if run(chooser) == cint(RESPONSE_OK):
|
|
||||||
var x = get_filename(chooser)
|
|
||||||
result = $x
|
|
||||||
g_free(x)
|
|
||||||
else:
|
|
||||||
result = ""
|
|
||||||
destroy(PWidget(chooser))
|
|
||||||
|
|
||||||
|
|
@ -1196,8 +1196,13 @@ template sysAssert(cond: bool, msg: string) =
|
||||||
echo "[SYSASSERT] ", msg
|
echo "[SYSASSERT] ", msg
|
||||||
quit 1
|
quit 1
|
||||||
|
|
||||||
|
const hasAlloc = hostOS != "standalone" or not defined(nogc)
|
||||||
|
|
||||||
when not defined(JS) and not defined(nimrodVm) and hostOS != "standalone":
|
when not defined(JS) and not defined(nimrodVm) and hostOS != "standalone":
|
||||||
include "system/cgprocs"
|
include "system/cgprocs"
|
||||||
|
when not defined(JS) and not defined(nimrodVm) and hasAlloc:
|
||||||
|
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
|
||||||
|
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
||||||
|
|
||||||
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
|
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
|
||||||
proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
|
proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} =
|
||||||
|
|
@ -1404,7 +1409,7 @@ when not defined(nimrodVM):
|
||||||
## otherwise. Like any procedure dealing with raw memory this is
|
## otherwise. Like any procedure dealing with raw memory this is
|
||||||
## *unsafe*.
|
## *unsafe*.
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when hasAlloc:
|
||||||
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
|
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign.}
|
||||||
## allocates a new memory block with at least ``size`` bytes. The
|
## allocates a new memory block with at least ``size`` bytes. The
|
||||||
## block has to be freed with ``realloc(block, 0)`` or
|
## block has to be freed with ``realloc(block, 0)`` or
|
||||||
|
|
@ -1540,7 +1545,7 @@ proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
|
||||||
## converted to a decimal string.
|
## converted to a decimal string.
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(NimrodVM):
|
||||||
when not defined(JS) and hostOS != "standalone":
|
when not defined(JS) and hasAlloc:
|
||||||
proc `$` *(x: uint64): string {.noSideEffect.}
|
proc `$` *(x: uint64): string {.noSideEffect.}
|
||||||
## The stringify operator for an unsigned integer argument. Returns `x`
|
## The stringify operator for an unsigned integer argument. Returns `x`
|
||||||
## converted to a decimal string.
|
## converted to a decimal string.
|
||||||
|
|
@ -1607,7 +1612,7 @@ const
|
||||||
|
|
||||||
# GC interface:
|
# GC interface:
|
||||||
|
|
||||||
when not defined(nimrodVM) and hostOS != "standalone":
|
when not defined(nimrodVM) and hasAlloc:
|
||||||
proc getOccupiedMem*(): int {.rtl.}
|
proc getOccupiedMem*(): int {.rtl.}
|
||||||
## returns the number of bytes that are owned by the process and hold data.
|
## returns the number of bytes that are owned by the process and hold data.
|
||||||
|
|
||||||
|
|
@ -2163,7 +2168,7 @@ when false:
|
||||||
|
|
||||||
# ----------------- GC interface ---------------------------------------------
|
# ----------------- GC interface ---------------------------------------------
|
||||||
|
|
||||||
when not defined(nimrodVM) and hostOS != "standalone":
|
when not defined(nimrodVM) and hasAlloc:
|
||||||
proc GC_disable*() {.rtl, inl, benign.}
|
proc GC_disable*() {.rtl, inl, benign.}
|
||||||
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
|
## disables the GC. If called n-times, n calls to `GC_enable` are needed to
|
||||||
## reactivate the GC. Note that in most circumstances one should only disable
|
## reactivate the GC. Note that in most circumstances one should only disable
|
||||||
|
|
@ -2288,7 +2293,7 @@ when defined(JS):
|
||||||
"""
|
"""
|
||||||
proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
|
proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".}
|
||||||
|
|
||||||
elif hostOS != "standalone":
|
elif hasAlloc:
|
||||||
{.push stack_trace:off, profiler:off.}
|
{.push stack_trace:off, profiler:off.}
|
||||||
proc add*(x: var string, y: cstring) =
|
proc add*(x: var string, y: cstring) =
|
||||||
var i = 0
|
var i = 0
|
||||||
|
|
@ -2382,7 +2387,7 @@ else:
|
||||||
when not defined(JS): #and not defined(NimrodVM):
|
when not defined(JS): #and not defined(NimrodVM):
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
|
|
||||||
when not defined(NimrodVM) and hostOS != "standalone":
|
when not defined(NimrodVM) and not defined(nogc):
|
||||||
proc initGC()
|
proc initGC()
|
||||||
when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc):
|
when not defined(boehmgc) and not defined(useMalloc) and not defined(gogc):
|
||||||
proc initAllocator() {.inline.}
|
proc initAllocator() {.inline.}
|
||||||
|
|
@ -2402,6 +2407,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
when declared(setStackBottom):
|
when declared(setStackBottom):
|
||||||
setStackBottom(locals)
|
setStackBottom(locals)
|
||||||
|
|
||||||
|
when hasAlloc:
|
||||||
var
|
var
|
||||||
strDesc: TNimType
|
strDesc: TNimType
|
||||||
|
|
||||||
|
|
@ -2625,6 +2631,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
when not defined(nimfix):
|
when not defined(nimfix):
|
||||||
{.deprecated: [fileHandle: getFileHandle].}
|
{.deprecated: [fileHandle: getFileHandle].}
|
||||||
|
|
||||||
|
when declared(newSeq):
|
||||||
proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
|
proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
|
||||||
## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
|
## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
|
||||||
## of length ``len``.
|
## of length ``len``.
|
||||||
|
|
@ -2640,12 +2647,12 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
when not defined(NimrodVM) and hostOS != "standalone":
|
when declared(alloc0) and declared(dealloc):
|
||||||
proc allocCStringArray*(a: openArray[string]): cstringArray =
|
proc allocCStringArray*(a: openArray[string]): cstringArray =
|
||||||
## creates a NULL terminated cstringArray from `a`. The result has to
|
## creates a NULL terminated cstringArray from `a`. The result has to
|
||||||
## be freed with `deallocCStringArray` after it's not needed anymore.
|
## be freed with `deallocCStringArray` after it's not needed anymore.
|
||||||
result = cast[cstringArray](alloc0((a.len+1) * sizeof(cstring)))
|
result = cast[cstringArray](alloc0((a.len+1) * sizeof(cstring)))
|
||||||
let x = cast[ptr array[0..20_000, string]](a)
|
let x = cast[ptr array[0..ArrayDummySize, string]](a)
|
||||||
for i in 0 .. a.high:
|
for i in 0 .. a.high:
|
||||||
result[i] = cast[cstring](alloc0(x[i].len+1))
|
result[i] = cast[cstring](alloc0(x[i].len+1))
|
||||||
copyMem(result[i], addr(x[i][0]), x[i].len)
|
copyMem(result[i], addr(x[i][0]), x[i].len)
|
||||||
|
|
@ -2685,9 +2692,9 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
when hasThreadSupport:
|
when hasThreadSupport:
|
||||||
include "system/syslocks"
|
include "system/syslocks"
|
||||||
when hostOS != "standalone": include "system/threads"
|
when hostOS != "standalone": include "system/threads"
|
||||||
elif not defined(nogc) and not defined(NimrodVM) and hostOS != "standalone":
|
elif not defined(nogc) and not defined(NimrodVM):
|
||||||
when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
|
when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom()
|
||||||
initGC()
|
when declared(initGC): initGC()
|
||||||
|
|
||||||
when not defined(NimrodVM):
|
when not defined(NimrodVM):
|
||||||
proc setControlCHook*(hook: proc () {.noconv.} not nil)
|
proc setControlCHook*(hook: proc () {.noconv.} not nil)
|
||||||
|
|
@ -2748,9 +2755,9 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
else:
|
else:
|
||||||
result = n.sons[n.len]
|
result = n.sons[n.len]
|
||||||
|
|
||||||
when hostOS != "standalone": include "system/mmdisp"
|
when hasAlloc: include "system/mmdisp"
|
||||||
{.push stack_trace: off, profiler:off.}
|
{.push stack_trace: off, profiler:off.}
|
||||||
when hostOS != "standalone": include "system/sysstr"
|
when hasAlloc: include "system/sysstr"
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
when hostOS != "standalone": include "system/sysio"
|
when hostOS != "standalone": include "system/sysio"
|
||||||
|
|
@ -2759,7 +2766,7 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
else:
|
else:
|
||||||
include "system/sysio"
|
include "system/sysio"
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when declared(open) and declared(close) and declared(readline):
|
||||||
iterator lines*(filename: string): TaintedString {.tags: [ReadIOEffect].} =
|
iterator lines*(filename: string): TaintedString {.tags: [ReadIOEffect].} =
|
||||||
## Iterates over any line in the file named `filename`.
|
## Iterates over any line in the file named `filename`.
|
||||||
##
|
##
|
||||||
|
|
@ -2795,10 +2802,11 @@ when not defined(JS): #and not defined(NimrodVM):
|
||||||
var res = TaintedString(newStringOfCap(80))
|
var res = TaintedString(newStringOfCap(80))
|
||||||
while f.readLine(res): yield res
|
while f.readLine(res): yield res
|
||||||
|
|
||||||
when hostOS != "standalone" and not defined(NimrodVM):
|
when not defined(NimrodVM) and hasAlloc:
|
||||||
include "system/assign"
|
include "system/assign"
|
||||||
include "system/repr"
|
include "system/repr"
|
||||||
|
|
||||||
|
when hostOS != "standalone" and not defined(NimrodVM):
|
||||||
proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} =
|
proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} =
|
||||||
## retrieves the current exception; if there is none, nil is returned.
|
## retrieves the current exception; if there is none, nil is returned.
|
||||||
result = currException
|
result = currException
|
||||||
|
|
@ -2949,7 +2957,7 @@ template spliceImpl(s, a, L, b: expr): stmt {.immediate.} =
|
||||||
# fill the hole:
|
# fill the hole:
|
||||||
for i in 0 .. <b.len: s[i+a] = b[i]
|
for i in 0 .. <b.len: s[i+a] = b[i]
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when hasAlloc:
|
||||||
proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
|
proc `[]`*(s: string, x: Slice[int]): string {.inline.} =
|
||||||
## slice operation for strings.
|
## slice operation for strings.
|
||||||
result = s.substr(x.a, x.b)
|
result = s.substr(x.a, x.b)
|
||||||
|
|
@ -3242,7 +3250,7 @@ when false:
|
||||||
macro payload: stmt {.gensym.} = blk
|
macro payload: stmt {.gensym.} = blk
|
||||||
payload()
|
payload()
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when hasAlloc:
|
||||||
proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
|
proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
|
||||||
## inserts `item` into `x` at position `i`.
|
## inserts `item` into `x` at position `i`.
|
||||||
var xl = x.len
|
var xl = x.len
|
||||||
|
|
@ -3269,7 +3277,7 @@ proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
|
||||||
when declared(initDebugger):
|
when declared(initDebugger):
|
||||||
initDebugger()
|
initDebugger()
|
||||||
|
|
||||||
when hostOS != "standalone":
|
when hasAlloc:
|
||||||
# XXX: make these the default (or implement the NilObject optimization)
|
# XXX: make these the default (or implement the NilObject optimization)
|
||||||
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
|
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
|
||||||
if x == nil: x = @[y]
|
if x == nil: x = @[y]
|
||||||
|
|
@ -3307,7 +3315,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
|
||||||
## # -> B is 1
|
## # -> B is 1
|
||||||
discard
|
discard
|
||||||
|
|
||||||
when hostOS != "standalone" and not defined(NimrodVM) and not defined(JS):
|
when hasAlloc and not defined(NimrodVM) and not defined(JS):
|
||||||
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} =
|
||||||
## performs a deep copy of `x`. This is also used by the code generator
|
## performs a deep copy of `x`. This is also used by the code generator
|
||||||
## for the implementation of ``spawn``.
|
## for the implementation of ``spawn``.
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,15 @@
|
||||||
# - make searching for block O(1)
|
# - make searching for block O(1)
|
||||||
{.push profiler:off.}
|
{.push profiler:off.}
|
||||||
|
|
||||||
|
proc roundup(x, v: int): int {.inline.} =
|
||||||
|
result = (x + (v-1)) and not (v-1)
|
||||||
|
sysAssert(result >= x, "roundup: result < x")
|
||||||
|
#return ((-x) and (v-1)) +% x
|
||||||
|
|
||||||
|
sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize")
|
||||||
|
sysAssert(roundup(15, 8) == 16, "roundup broken")
|
||||||
|
sysAssert(roundup(65, 8) == 72, "roundup broken 2")
|
||||||
|
|
||||||
# ------------ platform specific chunk allocation code -----------------------
|
# ------------ platform specific chunk allocation code -----------------------
|
||||||
|
|
||||||
# some platforms have really weird unmap behaviour: unmap(blockStart, PageSize)
|
# some platforms have really weird unmap behaviour: unmap(blockStart, PageSize)
|
||||||
|
|
@ -82,6 +91,21 @@ elif defined(windows):
|
||||||
when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
|
when reallyOsDealloc: virtualFree(p, 0, MEM_RELEASE)
|
||||||
#VirtualFree(p, size, MEM_DECOMMIT)
|
#VirtualFree(p, size, MEM_DECOMMIT)
|
||||||
|
|
||||||
|
elif hostOS == "standalone":
|
||||||
|
var
|
||||||
|
theHeap: array[1024*PageSize, float64] # 'float64' for alignment
|
||||||
|
bumpPointer = cast[int](addr theHeap)
|
||||||
|
|
||||||
|
proc osAllocPages(size: int): pointer {.inline.} =
|
||||||
|
if size+bumpPointer < cast[int](addr theHeap) + sizeof(theHeap):
|
||||||
|
result = cast[pointer](bumpPointer)
|
||||||
|
inc bumpPointer, size
|
||||||
|
else:
|
||||||
|
raiseOutOfMem()
|
||||||
|
|
||||||
|
proc osDeallocPages(p: pointer, size: int) {.inline.} =
|
||||||
|
if bumpPointer-size == cast[int](p):
|
||||||
|
dec bumpPointer, size
|
||||||
else:
|
else:
|
||||||
{.error: "Port memory manager to your platform".}
|
{.error: "Port memory manager to your platform".}
|
||||||
|
|
||||||
|
|
@ -142,15 +166,6 @@ type
|
||||||
template smallChunkOverhead(): expr = sizeof(SmallChunk)-sizeof(AlignType)
|
template smallChunkOverhead(): expr = sizeof(SmallChunk)-sizeof(AlignType)
|
||||||
template bigChunkOverhead(): expr = sizeof(BigChunk)-sizeof(AlignType)
|
template bigChunkOverhead(): expr = sizeof(BigChunk)-sizeof(AlignType)
|
||||||
|
|
||||||
proc roundup(x, v: int): int {.inline.} =
|
|
||||||
result = (x + (v-1)) and not (v-1)
|
|
||||||
sysAssert(result >= x, "roundup: result < x")
|
|
||||||
#return ((-x) and (v-1)) +% x
|
|
||||||
|
|
||||||
sysAssert(roundup(14, PageSize) == PageSize, "invalid PageSize")
|
|
||||||
sysAssert(roundup(15, 8) == 16, "roundup broken")
|
|
||||||
sysAssert(roundup(65, 8) == 72, "roundup broken 2")
|
|
||||||
|
|
||||||
# ------------- chunk table ---------------------------------------------------
|
# ------------- chunk table ---------------------------------------------------
|
||||||
# We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk
|
# We use a PtrSet of chunk starts and a table[Page, chunksize] for chunk
|
||||||
# endings of big chunks. This is needed by the merging operation. The only
|
# endings of big chunks. This is needed by the merging operation. The only
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
# Headers for procs that the code generator depends on ("compilerprocs")
|
# Headers for procs that the code generator depends on ("compilerprocs")
|
||||||
|
|
||||||
proc addChar(s: NimString, c: char): NimString {.compilerProc, benign.}
|
|
||||||
|
|
||||||
type
|
type
|
||||||
LibHandle = pointer # private type
|
LibHandle = pointer # private type
|
||||||
ProcAddr = pointer # library loading and loading of procs:
|
ProcAddr = pointer # library loading and loading of procs:
|
||||||
|
|
@ -21,6 +19,3 @@ proc nimUnloadLibrary(lib: LibHandle) {.compilerproc.}
|
||||||
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc.}
|
proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc.}
|
||||||
|
|
||||||
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
proc nimLoadLibraryError(path: string) {.compilerproc, noinline.}
|
||||||
|
|
||||||
proc setStackBottom(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ const
|
||||||
|
|
||||||
type
|
type
|
||||||
PPointer = ptr pointer
|
PPointer = ptr pointer
|
||||||
ByteArray = array[0..1000_0000, byte]
|
ByteArray = array[0..ArrayDummySize, byte]
|
||||||
PByte = ptr ByteArray
|
PByte = ptr ByteArray
|
||||||
PString = ptr string
|
PString = ptr string
|
||||||
{.deprecated: [TByteArray: ByteArray].}
|
{.deprecated: [TByteArray: ByteArray].}
|
||||||
|
|
@ -42,7 +42,7 @@ type
|
||||||
# Page size of the system; in most cases 4096 bytes. For exotic OS or
|
# Page size of the system; in most cases 4096 bytes. For exotic OS or
|
||||||
# CPU this needs to be changed:
|
# CPU this needs to be changed:
|
||||||
const
|
const
|
||||||
PageShift = 12
|
PageShift = when defined(cpu16): 8 else: 12
|
||||||
PageSize = 1 shl PageShift
|
PageSize = 1 shl PageShift
|
||||||
PageMask = PageSize-1
|
PageMask = PageSize-1
|
||||||
|
|
||||||
|
|
@ -270,7 +270,10 @@ elif defined(gogc):
|
||||||
# Statistics about allocation size classes.
|
# Statistics about allocation size classes.
|
||||||
by_size: array[goNumSizeClasses, goMStats_inner_struct]
|
by_size: array[goNumSizeClasses, goMStats_inner_struct]
|
||||||
|
|
||||||
proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl, importc: "runtime_ReadMemStats", codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3", dynlib: goLib.}
|
proc goRuntime_ReadMemStats(a2: ptr goMStats) {.cdecl,
|
||||||
|
importc: "runtime_ReadMemStats",
|
||||||
|
codegenDecl: "$1 $2$3 __asm__ (\"runtime.ReadMemStats\");\n$1 $2$3",
|
||||||
|
dynlib: goLib.}
|
||||||
|
|
||||||
proc GC_getStatistics(): string =
|
proc GC_getStatistics(): string =
|
||||||
var mstats: goMStats
|
var mstats: goMStats
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
--os:standalone
|
--os:standalone
|
||||||
--deadCodeElim:on
|
--deadCodeElim:on
|
||||||
|
--gc:none
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ News
|
||||||
used: ``import "scene/2d/sprite"``. The former code never was valid Nim.
|
used: ``import "scene/2d/sprite"``. The former code never was valid Nim.
|
||||||
- The Windows API wrapper (``windows.nim``) is now not part of the official
|
- The Windows API wrapper (``windows.nim``) is now not part of the official
|
||||||
distribution anymore. Instead use the ``oldwinapi`` Nimble package.
|
distribution anymore. Instead use the ``oldwinapi`` Nimble package.
|
||||||
|
- There is now a clear distinction between ``--os:standalone``
|
||||||
|
and ``--gc:none``. So if you use ``--os:standalone`` ensure you also use
|
||||||
|
``--gc:none``. ``--os:standalone`` without ``--gc:none`` is now a version
|
||||||
|
that doesn't depend on any OS but includes the GC. However this version
|
||||||
|
is currently untested!
|
||||||
|
|
||||||
|
|
||||||
Library additions
|
Library additions
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue