mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 09:54:49 +00:00
Merge remote-tracking branch 'upstream/devel' into pr_object
This commit is contained in:
@@ -510,7 +510,7 @@ type
|
||||
nfLastRead # this node is a last read
|
||||
nfFirstWrite # this node is a first write
|
||||
nfHasComment # node has a comment
|
||||
nfUseDefaultField # node has a default value (object constructor)
|
||||
nfSkipFieldChecking # node skips field visable checking
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 46)
|
||||
@@ -1081,7 +1081,7 @@ const
|
||||
nfIsRef, nfIsPtr, nfPreventCg, nfLL,
|
||||
nfFromTemplate, nfDefaultRefsParam,
|
||||
nfExecuteOnReload, nfLastRead,
|
||||
nfFirstWrite, nfUseDefaultField}
|
||||
nfFirstWrite, nfSkipFieldChecking}
|
||||
namePos* = 0
|
||||
patternPos* = 1 # empty except for term rewriting macros
|
||||
genericParamsPos* = 2
|
||||
|
||||
@@ -572,7 +572,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
|
||||
let asgnExpr = defaultNodeField(c, recNode, recNode.typ)
|
||||
if asgnExpr != nil:
|
||||
hasDefault = true
|
||||
asgnExpr.flags.incl nfUseDefaultField
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
return
|
||||
|
||||
@@ -582,7 +582,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): s
|
||||
newSymNode(getSysMagic(c.graph, recNode.info, "zeroDefault", mZeroDefault)),
|
||||
newNodeIT(nkType, recNode.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfUseDefaultField
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recType
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
@@ -604,7 +604,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
|
||||
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
|
||||
defaultValue.typ = discriminator.typ
|
||||
selectedBranch = recNode.pickCaseBranchIndex defaultValue
|
||||
defaultValue.flags.incl nfUseDefaultField
|
||||
defaultValue.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
|
||||
result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1])
|
||||
of nkSym:
|
||||
@@ -616,7 +616,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
|
||||
let asgnExpr = defaultNodeField(c, recNode, recType)
|
||||
if asgnExpr != nil:
|
||||
asgnExpr.typ = recType
|
||||
asgnExpr.flags.incl nfUseDefaultField
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
doAssert false
|
||||
|
||||
@@ -338,7 +338,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||
if n[0].kind in nkIdentKinds:
|
||||
let ident = considerQuotedIdent(c, n[0], n).s
|
||||
localError(c.config, n.info, errUndeclaredRoutine % ident)
|
||||
else:
|
||||
else:
|
||||
localError(c.config, n.info, "expression '$1' cannot be called" % n[0].renderTree)
|
||||
return
|
||||
|
||||
@@ -630,7 +630,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
if efExplain notin flags:
|
||||
# repeat the overload resolution,
|
||||
# this time enabling all the diagnostic output (this should fail again)
|
||||
discard semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
|
||||
result = semOverloadedCall(c, n, nOrig, filter, flags + {efExplain})
|
||||
elif efNoUndeclared notin flags:
|
||||
notFoundError(c, n, errors)
|
||||
|
||||
|
||||
@@ -302,7 +302,7 @@ proc semConv(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkConv, n.info)
|
||||
|
||||
var targetType = semTypeNode(c, n[0], nil)
|
||||
case targetType.kind
|
||||
case targetType.skipTypes({tyDistinct}).kind
|
||||
of tyTypeDesc:
|
||||
internalAssert c.config, targetType.len > 0
|
||||
if targetType.base.kind == tyNone:
|
||||
@@ -787,7 +787,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode, isOutParam: bool): PNode =
|
||||
else:
|
||||
result = newHiddenAddrTaken(c, n, isOutParam)
|
||||
|
||||
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
proc analyseIfAddressTakenInCall(c: PContext, n: PNode, isConverter = false) =
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
const
|
||||
FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl,
|
||||
@@ -795,10 +795,15 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
mAppendSeqElem, mNewSeq, mReset, mShallowCopy, mDeepCopy, mMove,
|
||||
mWasMoved}
|
||||
|
||||
template checkIfConverterCalled(c: PContext, n: PNode) =
|
||||
## Checks if there is a converter call which wouldn't be checked otherwise
|
||||
# Call can sometimes be wrapped in a deref
|
||||
let node = if n.kind == nkHiddenDeref: n[0] else: n
|
||||
if node.kind == nkHiddenCallConv:
|
||||
analyseIfAddressTakenInCall(c, node, true)
|
||||
# get the real type of the callee
|
||||
# it may be a proc var with a generic alias type, so we skip over them
|
||||
var t = n[0].typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
|
||||
if n[0].kind == nkSym and n[0].sym.magic in FakeVarParams:
|
||||
# BUGFIX: check for L-Value still needs to be done for the arguments!
|
||||
# note sometimes this is eval'ed twice so we check for nkHiddenAddr here:
|
||||
@@ -813,6 +818,8 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
discard "allow access within a cast(unsafeAssign) section"
|
||||
else:
|
||||
localError(c.config, it.info, errVarForOutParamNeededX % $it)
|
||||
# Make sure to still check arguments for converters
|
||||
c.checkIfConverterCalled(n[i])
|
||||
# bug #5113: disallow newSeq(result) where result is a 'var T':
|
||||
if n[0].sym.magic in {mNew, mNewFinalize, mNewSeq}:
|
||||
var arg = n[1] #.skipAddr
|
||||
@@ -824,15 +831,14 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||
return
|
||||
for i in 1..<n.len:
|
||||
let n = if n.kind == nkHiddenDeref: n[0] else: n
|
||||
if n[i].kind == nkHiddenCallConv:
|
||||
# we need to recurse explicitly here as converters can create nested
|
||||
# calls and then they wouldn't be analysed otherwise
|
||||
analyseIfAddressTakenInCall(c, n[i])
|
||||
c.checkIfConverterCalled(n[i])
|
||||
if i < t.len and
|
||||
skipTypes(t[i], abstractInst-{tyTypeDesc}).kind in {tyVar}:
|
||||
if n[i].kind != nkHiddenAddr:
|
||||
n[i] = analyseIfAddressTaken(c, n[i], isOutParam(skipTypes(t[i], abstractInst-{tyTypeDesc})))
|
||||
|
||||
# Converters wrap var parameters in nkHiddenAddr but they haven't been analysed yet.
|
||||
# So we need to make sure we are checking them still when in a converter call
|
||||
if n[i].kind != nkHiddenAddr or isConverter:
|
||||
n[i] = analyseIfAddressTaken(c, n[i].skipAddr(), isOutParam(skipTypes(t[i], abstractInst-{tyTypeDesc})))
|
||||
|
||||
include semmagic
|
||||
|
||||
proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
|
||||
@@ -78,14 +78,18 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
if macroToExpandSym(s):
|
||||
onUse(n.info, s)
|
||||
result = semTemplateExpr(c, n, s, {efNoSemCheck})
|
||||
c.friendModules.add(s.owner.getModule)
|
||||
result = semGenericStmt(c, result, {}, ctx)
|
||||
discard c.friendModules.pop()
|
||||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skMacro:
|
||||
if macroToExpandSym(s):
|
||||
onUse(n.info, s)
|
||||
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
|
||||
c.friendModules.add(s.owner.getModule)
|
||||
result = semGenericStmt(c, result, {}, ctx)
|
||||
discard c.friendModules.pop()
|
||||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skGenericParam:
|
||||
@@ -245,7 +249,9 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
if macroToExpand(s) and sc.safeLen <= 1:
|
||||
onUse(fn.info, s)
|
||||
result = semMacroExpr(c, n, n, s, {efNoSemCheck})
|
||||
c.friendModules.add(s.owner.getModule)
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
discard c.friendModules.pop()
|
||||
else:
|
||||
n[0] = sc
|
||||
result = n
|
||||
@@ -254,7 +260,9 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
if macroToExpand(s) and sc.safeLen <= 1:
|
||||
onUse(fn.info, s)
|
||||
result = semTemplateExpr(c, n, s, {efNoSemCheck})
|
||||
c.friendModules.add(s.owner.getModule)
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
discard c.friendModules.pop()
|
||||
else:
|
||||
n[0] = sc
|
||||
result = n
|
||||
@@ -493,6 +501,20 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
of nkExprColonExpr, nkExprEqExpr:
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
result[1] = semGenericStmt(c, n[1], flags, ctx)
|
||||
of nkObjConstr:
|
||||
for i in 0..<n.len:
|
||||
result[i] = semGenericStmt(c, n[i], flags, ctx)
|
||||
if result[0].kind == nkSym:
|
||||
let fmoduleId = getModule(result[0].sym).id
|
||||
var isVisable = false
|
||||
for module in c.friendModules:
|
||||
if module.id == fmoduleId:
|
||||
isVisable = true
|
||||
break
|
||||
if isVisable:
|
||||
for i in 1..<result.len:
|
||||
if result[i].kind == nkExprColonExpr:
|
||||
result[i][1].flags.incl nfSkipFieldChecking
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
result[i] = semGenericStmt(c, n[i], flags, ctx)
|
||||
|
||||
@@ -76,7 +76,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
|
||||
let assignment = locateFieldInInitExpr(c, field, initExpr)
|
||||
if assignment != nil:
|
||||
if nfSem in assignment.flags: return assignment[1]
|
||||
if nfUseDefaultField in assignment[1].flags:
|
||||
if nfSkipFieldChecking in assignment[1].flags:
|
||||
discard
|
||||
elif not fieldVisible(c, field):
|
||||
localError(c.config, initExpr.info,
|
||||
@@ -178,7 +178,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
|
||||
newSymNode(getSysMagic(c.graph, constrCtx.initExpr.info, "zeroDefault", mZeroDefault)),
|
||||
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfUseDefaultField
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recTyp
|
||||
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)
|
||||
|
||||
|
||||
@@ -519,7 +519,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
let fSym = newSymNode(field)
|
||||
if hasDefaultField:
|
||||
fSym.sym.ast = a[^1]
|
||||
fSym.sym.ast.flags.incl nfUseDefaultField
|
||||
fSym.sym.ast.flags.incl nfSkipFieldChecking
|
||||
result.n.add fSym
|
||||
addSonSkipIntLit(result, typ, c.idgen)
|
||||
styleCheckDef(c, a[j].info, field)
|
||||
@@ -868,7 +868,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
let fSym = newSymNode(f)
|
||||
if hasDefaultField:
|
||||
fSym.sym.ast = n[^1]
|
||||
fSym.sym.ast.flags.incl nfUseDefaultField
|
||||
fSym.sym.ast.flags.incl nfSkipFieldChecking
|
||||
if a.kind == nkEmpty: father.add fSym
|
||||
else: a.add fSym
|
||||
styleCheckDef(c, f)
|
||||
|
||||
@@ -1979,8 +1979,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
if srca == isSubtype:
|
||||
param = implicitConv(nkHiddenSubConv, src, copyTree(arg), m, c)
|
||||
elif src.kind in {tyVar}:
|
||||
# Analyse the converter return type
|
||||
arg.sym.flags.incl sfAddrTaken
|
||||
# Analyse the converter return type.
|
||||
param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1])
|
||||
param.add copyTree(arg)
|
||||
else:
|
||||
|
||||
@@ -1829,7 +1829,7 @@ proc getNullValueAux(t: PType; obj: PNode, result: PNode; conf: ConfigRef; currP
|
||||
let field = newNodeI(nkExprColonExpr, result.info)
|
||||
field.add(obj)
|
||||
let value = getNullValue(obj.sym.typ, result.info, conf)
|
||||
value.flags.incl nfUseDefaultField
|
||||
value.flags.incl nfSkipFieldChecking
|
||||
field.add(value)
|
||||
result.add field
|
||||
doAssert obj.sym.position == currPosition
|
||||
|
||||
@@ -5455,7 +5455,7 @@ more complex type classes:
|
||||
|
||||
```nim
|
||||
# create a type class that will match all tuple and object types
|
||||
type RecordType = tuple or object
|
||||
type RecordType = (tuple or object)
|
||||
|
||||
proc printFields[T: RecordType](rec: T) =
|
||||
for key, value in fieldPairs(rec):
|
||||
@@ -5504,7 +5504,7 @@ A type class can be used directly as the parameter's type.
|
||||
|
||||
```nim
|
||||
# create a type class that will match all tuple and object types
|
||||
type RecordType = tuple or object
|
||||
type RecordType = (tuple or object)
|
||||
|
||||
proc printFields(rec: RecordType) =
|
||||
for key, value in fieldPairs(rec):
|
||||
|
||||
@@ -958,7 +958,7 @@ proc `==`*(x, y: SocketHandle): bool {.borrow.}
|
||||
proc accept*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen): SocketHandle {.
|
||||
importc, header: "<sys/socket.h>", sideEffect.}
|
||||
|
||||
when defined(linux) or defined(bsd):
|
||||
when defined(linux) or defined(bsd) or defined(nuttx):
|
||||
proc accept4*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen,
|
||||
flags: cint): SocketHandle {.importc, header: "<sys/socket.h>".}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
when defined(freertos) or defined(zephyr) or defined(nuttx):
|
||||
when defined(freertos) or defined(zephyr):
|
||||
const
|
||||
hasSpawnH = false # should exist for every Posix system nowadays
|
||||
hasAioH = false
|
||||
@@ -646,7 +646,7 @@ elif defined(nuttx):
|
||||
else:
|
||||
var SO_REUSEPORT* {.importc, header: "<sys/socket.h>".}: cint
|
||||
|
||||
when defined(linux) or defined(bsd):
|
||||
when defined(linux) or defined(bsd) or defined(nuttx):
|
||||
var SOCK_CLOEXEC* {.importc, header: "<sys/socket.h>".}: cint
|
||||
|
||||
when defined(macosx):
|
||||
@@ -675,14 +675,14 @@ when defined(haiku):
|
||||
|
||||
when hasSpawnH:
|
||||
when defined(linux):
|
||||
# better be safe than sorry; Linux has this flag, macosx doesn't, don't
|
||||
# know about the other OSes
|
||||
# better be safe than sorry; Linux has this flag, macosx and NuttX don't,
|
||||
# don't know about the other OSes
|
||||
|
||||
# Non-GNU systems like TCC and musl-libc don't define __USE_GNU, so we
|
||||
# Non-GNU systems like TCC and musl-libc don't define __USE_GNU, so we
|
||||
# can't get the magic number from spawn.h
|
||||
const POSIX_SPAWN_USEVFORK* = cint(0x40)
|
||||
else:
|
||||
# macosx lacks this, so we define the constant to be 0 to not affect
|
||||
# macosx and NuttX lack this, so we define the constant to be 0 to not affect
|
||||
# OR'ing of flags:
|
||||
const POSIX_SPAWN_USEVFORK* = cint(0)
|
||||
|
||||
|
||||
@@ -1077,9 +1077,9 @@ template newSeqWith*(len: int, init: untyped): untyped =
|
||||
import std/random
|
||||
var seqRand = newSeqWith(20, rand(1.0))
|
||||
assert seqRand[0] != seqRand[1]
|
||||
|
||||
var result = newSeq[typeof(init)](len)
|
||||
for i in 0 ..< len:
|
||||
let newLen = len
|
||||
var result = newSeq[typeof(init)](newLen)
|
||||
for i in 0 ..< newLen:
|
||||
result[i] = init
|
||||
move(result) # refs bug #7295
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
## This module implements a simple HTTP client that can be used to retrieve
|
||||
## webpages and other data.
|
||||
##
|
||||
## .. warning:: Validate untrusted inputs: URI parsers and getters are not detecting malicious URIs.
|
||||
##
|
||||
## Retrieving a website
|
||||
## ====================
|
||||
##
|
||||
|
||||
@@ -1053,13 +1053,15 @@ elif not defined(useNimRtl):
|
||||
var mask: Sigset
|
||||
chck sigemptyset(mask)
|
||||
chck posix_spawnattr_setsigmask(attr, mask)
|
||||
if poDaemon in data.options:
|
||||
chck posix_spawnattr_setpgroup(attr, 0'i32)
|
||||
when not defined(nuttx):
|
||||
if poDaemon in data.options:
|
||||
chck posix_spawnattr_setpgroup(attr, 0'i32)
|
||||
|
||||
var flags = POSIX_SPAWN_USEVFORK or
|
||||
POSIX_SPAWN_SETSIGMASK
|
||||
if poDaemon in data.options:
|
||||
flags = flags or POSIX_SPAWN_SETPGROUP
|
||||
when not defined(nuttx):
|
||||
if poDaemon in data.options:
|
||||
flags = flags or POSIX_SPAWN_SETPGROUP
|
||||
chck posix_spawnattr_setflags(attr, flags)
|
||||
|
||||
if not (poParentStreams in data.options):
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
## as a locator, a name, or both. The term "Uniform Resource Locator"
|
||||
## (URL) refers to the subset of URIs.
|
||||
##
|
||||
## .. warning:: URI parsers in this module do not perform security validation.
|
||||
##
|
||||
## # Basic usage
|
||||
|
||||
|
||||
|
||||
@@ -190,7 +190,7 @@ proc text*(n: XmlNode): lent string {.inline.} =
|
||||
assert $c == "<!-- my comment -->"
|
||||
assert c.text == "my comment"
|
||||
|
||||
n.expect {xnText, xnComment, xnCData, xnEntity}
|
||||
n.expect {xnText, xnVerbatimText, xnComment, xnCData, xnEntity}
|
||||
result = n.fText
|
||||
|
||||
proc `text=`*(n: XmlNode, text: sink string) {.inline.} =
|
||||
@@ -208,7 +208,7 @@ proc `text=`*(n: XmlNode, text: sink string) {.inline.} =
|
||||
e.text = "a new entity text"
|
||||
assert $e == "&a new entity text;"
|
||||
|
||||
n.expect {xnText, xnComment, xnCData, xnEntity}
|
||||
n.expect {xnText, xnVerbatimText, xnComment, xnCData, xnEntity}
|
||||
n.fText = text
|
||||
|
||||
proc tag*(n: XmlNode): lent string {.inline.} =
|
||||
@@ -735,7 +735,7 @@ proc addImpl(result: var string, n: XmlNode, indent = 0, indWidth = 2,
|
||||
addNewLines = true, lastNodeIsText = false) =
|
||||
proc noWhitespace(n: XmlNode): bool =
|
||||
for i in 0 ..< n.len:
|
||||
if n[i].kind in {xnText, xnEntity}: return true
|
||||
if n[i].kind in {xnText, xnVerbatimText, xnEntity}: return true
|
||||
|
||||
proc addEscapedAttr(result: var string, s: string) =
|
||||
# `addEscaped` alternative with less escaped characters.
|
||||
@@ -784,7 +784,7 @@ proc addImpl(result: var string, n: XmlNode, indent = 0, indWidth = 2,
|
||||
var lastNodeIsText = false
|
||||
for i in 0 ..< n.len:
|
||||
result.addImpl(n[i], indentNext, indWidth, addNewLines, lastNodeIsText)
|
||||
lastNodeIsText = n[i].kind == xnText
|
||||
lastNodeIsText = (n[i].kind == xnText) or (n[i].kind == xnVerbatimText)
|
||||
|
||||
if not n.noWhitespace():
|
||||
result.addIndent(indent, addNewLines)
|
||||
|
||||
@@ -268,6 +268,20 @@ proc getMaxMem(a: var MemRegion): int =
|
||||
# maximum of these both values here:
|
||||
result = max(a.currMem, a.maxMem)
|
||||
|
||||
const nimMaxHeap {.intdefine.} = 0
|
||||
|
||||
proc allocPages(a: var MemRegion, size: int): pointer =
|
||||
when nimMaxHeap != 0:
|
||||
if a.occ + size > nimMaxHeap * 1024 * 1024:
|
||||
raiseOutOfMem()
|
||||
osAllocPages(size)
|
||||
|
||||
proc tryAllocPages(a: var MemRegion, size: int): pointer =
|
||||
when nimMaxHeap != 0:
|
||||
if a.occ + size > nimMaxHeap * 1024 * 1024:
|
||||
raiseOutOfMem()
|
||||
osTryAllocPages(size)
|
||||
|
||||
proc llAlloc(a: var MemRegion, size: int): pointer =
|
||||
# *low-level* alloc for the memory managers data structures. Deallocation
|
||||
# is done at the end of the allocator's life time.
|
||||
@@ -277,7 +291,7 @@ proc llAlloc(a: var MemRegion, size: int): pointer =
|
||||
# is one page:
|
||||
sysAssert roundup(size+sizeof(LLChunk), PageSize) == PageSize, "roundup 6"
|
||||
var old = a.llmem # can be nil and is correct with nil
|
||||
a.llmem = cast[PLLChunk](osAllocPages(PageSize))
|
||||
a.llmem = cast[PLLChunk](allocPages(a, PageSize))
|
||||
when defined(nimAvlcorruption):
|
||||
trackLocation(a.llmem, PageSize)
|
||||
incCurrMem(a, PageSize)
|
||||
@@ -453,15 +467,10 @@ when false:
|
||||
it, it.next, it.prev, it.size)
|
||||
it = it.next
|
||||
|
||||
const nimMaxHeap {.intdefine.} = 0
|
||||
|
||||
proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
|
||||
when not defined(emscripten):
|
||||
if not a.blockChunkSizeIncrease:
|
||||
let usedMem = a.occ #a.currMem # - a.freeMem
|
||||
when nimMaxHeap != 0:
|
||||
if usedMem > nimMaxHeap * 1024 * 1024:
|
||||
raiseOutOfMem()
|
||||
if usedMem < 64 * 1024:
|
||||
a.nextChunkSize = PageSize*4
|
||||
else:
|
||||
@@ -470,11 +479,11 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
|
||||
|
||||
var size = size
|
||||
if size > a.nextChunkSize:
|
||||
result = cast[PBigChunk](osAllocPages(size))
|
||||
result = cast[PBigChunk](allocPages(a, size))
|
||||
else:
|
||||
result = cast[PBigChunk](osTryAllocPages(a.nextChunkSize))
|
||||
result = cast[PBigChunk](tryAllocPages(a, a.nextChunkSize))
|
||||
if result == nil:
|
||||
result = cast[PBigChunk](osAllocPages(size))
|
||||
result = cast[PBigChunk](allocPages(a, size))
|
||||
a.blockChunkSizeIncrease = true
|
||||
else:
|
||||
size = a.nextChunkSize
|
||||
@@ -654,7 +663,7 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
|
||||
releaseSys a.lock
|
||||
|
||||
proc getHugeChunk(a: var MemRegion; size: int): PBigChunk =
|
||||
result = cast[PBigChunk](osAllocPages(size))
|
||||
result = cast[PBigChunk](allocPages(a, size))
|
||||
when RegionHasLock:
|
||||
if not a.lockActive:
|
||||
a.lockActive = true
|
||||
@@ -811,9 +820,9 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
|
||||
sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
|
||||
var size = roundup(requestedSize, MemAlign)
|
||||
sysAssert(size >= sizeof(FreeCell), "rawAlloc: requested size too small")
|
||||
|
||||
sysAssert(size >= requestedSize, "insufficient allocated size!")
|
||||
#c_fprintf(stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
|
||||
|
||||
if size <= SmallChunkSize-smallChunkOverhead():
|
||||
# allocate a small block: for small chunks, we use only its next pointer
|
||||
let s = size div MemAlign
|
||||
|
||||
@@ -391,7 +391,6 @@ else:
|
||||
let regEnd = sp +% sizeof(registers)
|
||||
while sp <% regEnd:
|
||||
gcMark(gch, cast[PPointer](sp)[])
|
||||
gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
|
||||
sp = sp +% sizeof(pointer)
|
||||
# Make sure sp is word-aligned
|
||||
sp = sp and not (sizeof(pointer) - 1)
|
||||
|
||||
@@ -10,6 +10,8 @@ skipDirs = @["build" , "changelogs" , "ci" , "csources_v2" , "drnim" , "nimdoc",
|
||||
|
||||
before install:
|
||||
when defined(windows):
|
||||
exec "build_all.bat"
|
||||
if not "bin\nim.exe".fileExists:
|
||||
exec "build_all.bat"
|
||||
else:
|
||||
exec "./build_all.sh"
|
||||
if not "bin/nim".fileExists:
|
||||
exec "./build_all.sh"
|
||||
|
||||
@@ -234,7 +234,7 @@ proc executeNoHooks(cmd: IdeCmd, file, dirtyfile: AbsoluteFile, line, col: int,
|
||||
localError(conf, conf.m.trackPos, "found no symbol at this position " & (conf $ conf.m.trackPos))
|
||||
|
||||
proc executeNoHooks(cmd: IdeCmd, file, dirtyfile: AbsoluteFile, line, col: int, graph: ModuleGraph) =
|
||||
executeNoHooks(cmd, file, dirtyfile, line, col, graph)
|
||||
executeNoHooks(cmd, file, dirtyfile, line, col, "", graph)
|
||||
|
||||
proc execute(cmd: IdeCmd, file, dirtyfile: AbsoluteFile, line, col: int; tag: string,
|
||||
graph: ModuleGraph) =
|
||||
|
||||
@@ -5,6 +5,7 @@ discard """
|
||||
t20588.nim(20, 12) Error: illegal type conversion to 'auto'
|
||||
t20588.nim(21, 14) Error: illegal type conversion to 'typed'
|
||||
t20588.nim(22, 16) Error: illegal type conversion to 'untyped'
|
||||
t20588.nim(24, 7) Error: illegal type conversion to 'any'
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -16,7 +17,9 @@ t20588.nim(22, 16) Error: illegal type conversion to 'untyped'
|
||||
|
||||
|
||||
|
||||
|
||||
discard 0.0.auto
|
||||
discard typed("abc")
|
||||
discard untyped(4)
|
||||
var a = newSeq[bool](1000)
|
||||
if any(a):
|
||||
echo "ok?"
|
||||
10
tests/converter/t21531.nim
Normal file
10
tests/converter/t21531.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
import std/typetraits
|
||||
|
||||
type Foo* = distinct string
|
||||
|
||||
converter toBase*(headers: var Foo): var string =
|
||||
headers.distinctBase
|
||||
|
||||
proc bar*(headers: var Foo) =
|
||||
for x in headers: discard
|
||||
|
||||
6
tests/generics/m3770.nim
Normal file
6
tests/generics/m3770.nim
Normal file
@@ -0,0 +1,6 @@
|
||||
type
|
||||
Noice* = object
|
||||
hidden: int
|
||||
|
||||
template jjj*: Noice =
|
||||
Noice(hidden: 15)
|
||||
9
tests/generics/t3770.nim
Normal file
9
tests/generics/t3770.nim
Normal file
@@ -0,0 +1,9 @@
|
||||
# bug #3770
|
||||
import m3770
|
||||
|
||||
doAssert $jjj() == "(hidden: 15)" # works
|
||||
|
||||
proc someGeneric(_: type) =
|
||||
doAssert $jjj() == "(hidden: 15)" # fails: "Error: the field 'hidden' is not accessible."
|
||||
|
||||
someGeneric(int)
|
||||
@@ -388,6 +388,11 @@ block: # newSeqWith tests
|
||||
seq2D[0][1] = true
|
||||
doAssert seq2D == @[@[true, true], @[true, false], @[false, false], @[false, false]]
|
||||
|
||||
block: # bug #21538
|
||||
var x: seq[int] = @[2, 4]
|
||||
var y = newSeqWith(x.pop(), true)
|
||||
doAssert y == @[true, true, true, true]
|
||||
|
||||
block: # mapLiterals tests
|
||||
let x = mapLiterals([0.1, 1.2, 2.3, 3.4], int)
|
||||
doAssert x is array[4, int]
|
||||
|
||||
@@ -99,3 +99,18 @@ block: # bug #21290
|
||||
doAssert s == """<foo>
|
||||
<bar>Hola<qux> <plugh /> </qux></bar>
|
||||
</foo>"""
|
||||
|
||||
block: #21541
|
||||
let root = <>root()
|
||||
root.add <>child(newText("hello"))
|
||||
root.add <>more(newVerbatimText("hola"))
|
||||
let s = $root
|
||||
doAssert s == """<root>
|
||||
<child>hello</child>
|
||||
<more>hola</more>
|
||||
</root>"""
|
||||
|
||||
let temp = newVerbatimText("Hello!")
|
||||
doAssert temp.text == "Hello!"
|
||||
temp.text = "Hola!"
|
||||
doAssert temp.text == "Hola!"
|
||||
|
||||
@@ -79,3 +79,9 @@ in its description (or name or list of tags).
|
||||
### Install <proj.nimble>
|
||||
|
||||
Use the .nimble file to setup the project's dependencies.
|
||||
|
||||
### Update [filter]
|
||||
|
||||
Update every package in the workspace that has a remote URL that
|
||||
matches `filter` if a filter is given. The package is only updated
|
||||
if there are no uncommitted changes.
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
## Simple tool to automate frequent workflows: Can "clone"
|
||||
## a Nimble dependency and its dependencies recursively.
|
||||
|
||||
import std/[parseopt, strutils, os, osproc, unicode, tables, sets, json, jsonutils]
|
||||
import std/[parseopt, strutils, os, osproc, tables, sets, json, jsonutils]
|
||||
import parse_requires, osutils, packagesjson
|
||||
|
||||
from unicode import nil
|
||||
|
||||
const
|
||||
Version = "0.2"
|
||||
Usage = "atlas - Nim Package Cloner Version " & Version & """
|
||||
@@ -25,6 +27,8 @@ Command:
|
||||
search keyw keywB... search for package that contains the given keywords
|
||||
extract file.nimble extract the requirements and custom commands from
|
||||
the given Nimble file
|
||||
update [filter] update every package in the workspace that has a remote
|
||||
URL that matches `filter` if a filter is given
|
||||
|
||||
Options:
|
||||
--keepCommits do not perform any `git checkouts`
|
||||
@@ -146,7 +150,7 @@ proc toDepRelation(s: string): DepRelation =
|
||||
of ">": strictlyGreater
|
||||
else: normal
|
||||
|
||||
proc isCleanGit(c: var AtlasContext; dir: string): string =
|
||||
proc isCleanGit(c: var AtlasContext): string =
|
||||
result = ""
|
||||
let (outp, status) = exec(c, GitDiff, [])
|
||||
if outp.len != 0:
|
||||
@@ -264,7 +268,7 @@ proc checkoutCommit(c: var AtlasContext; w: Dependency) =
|
||||
if w.commit.len == 0 or cmpIgnoreCase(w.commit, "head") == 0:
|
||||
gitPull(c, w.name)
|
||||
else:
|
||||
let err = isCleanGit(c, dir)
|
||||
let err = isCleanGit(c)
|
||||
if err != "":
|
||||
warn c, w.name, err
|
||||
else:
|
||||
@@ -448,6 +452,27 @@ proc installDependencies(c: var AtlasContext; nimbleFile: string) =
|
||||
let paths = cloneLoop(c, work)
|
||||
patchNimCfg(c, paths, if c.cfgHere: getCurrentDir() else: findSrcDir(c))
|
||||
|
||||
proc updateWorkspace(c: var AtlasContext; filter: string) =
|
||||
for kind, file in walkDir(c.workspace):
|
||||
if kind == pcDir and dirExists(file / ".git"):
|
||||
c.withDir file:
|
||||
let pkg = PackageName(file)
|
||||
let (remote, _) = osproc.execCmdEx("git remote -v")
|
||||
if filter.len == 0 or filter in remote:
|
||||
let diff = isCleanGit(c)
|
||||
if diff != "":
|
||||
warn(c, pkg, "has uncommitted changes; skipped")
|
||||
else:
|
||||
let (branch, _) = osproc.execCmdEx("git rev-parse --abbrev-ref HEAD")
|
||||
if branch.strip.len > 0:
|
||||
let (output, exitCode) = osproc.execCmdEx("git pull origin " & branch.strip)
|
||||
if exitCode != 0:
|
||||
error c, pkg, output
|
||||
else:
|
||||
message(c, "[Hint] ", pkg, "successfully updated")
|
||||
else:
|
||||
error c, pkg, "could not fetch current branch name"
|
||||
|
||||
proc main =
|
||||
var action = ""
|
||||
var args: seq[string] = @[]
|
||||
@@ -525,6 +550,8 @@ proc main =
|
||||
of "search", "list":
|
||||
updatePackages(c)
|
||||
search getPackages(c.workspace), args
|
||||
of "update":
|
||||
updateWorkspace(c, if args.len == 0: "" else: args[0])
|
||||
of "extract":
|
||||
singleArg()
|
||||
if fileExists(args[0]):
|
||||
|
||||
Reference in New Issue
Block a user