Merge branch 'devel' of https://github.com/nim-lang/Nim into devel

This commit is contained in:
ringabout
2024-10-21 19:43:09 +08:00
47 changed files with 319 additions and 189 deletions

View File

@@ -14,6 +14,11 @@ rounding guarantees (via the
## Standard library additions and changes
[//]: # "Additions:"
- `setutils.symmetricDifference` along with its operator version
`` setutils.`-+-` `` and in-place version `setutils.toggle` have been added
to more efficiently calculate the symmetric difference of bitsets.
[//]: # "Changes:"
- `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type.

View File

@@ -491,7 +491,7 @@ type
mAnd, mOr,
mImplies, mIff, mExists, mForall, mOld,
mEqStr, mLeStr, mLtStr,
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
mConStrStr, mSlice,
mDotDot, # this one is only necessary to give nice compile time warnings
mFields, mFieldPairs, mOmpParFor,
@@ -559,7 +559,7 @@ const
mStrToStr, mEnumToStr,
mAnd, mOr,
mEqStr, mLeStr, mLtStr,
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
mInSet, mRepr, mOpenArrayToSeq}

View File

@@ -89,6 +89,17 @@ template addTypedef(builder: var Builder, name: string, typeBody: typed) =
builder.add(name)
builder.add(";\n")
template addArrayTypedef(builder: var Builder, name: string, len: int, typeBody: typed) =
## adds an array typedef declaration to the builder with name `name`,
## length `len`, and element type as built in `typeBody`
builder.add("typedef ")
typeBody
builder.add(" ")
builder.add(name)
builder.add("[")
builder.addInt(len)
builder.add("];\n")
type
StructInitializerKind = enum
siOrderedStruct ## struct constructor, but without named fields on C

View File

@@ -1,4 +1,5 @@
# XXX make complex ones like bitOr use builder instead
# XXX add stuff like NI, NIM_NIL as constants
proc ptrType(t: Snippet): Snippet =
t & "*"

View File

@@ -2044,7 +2044,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
const
lookupOpr: array[mLeSet..mMinusSet, string] = [
lookupOpr: array[mLeSet..mXorSet, string] = [
"for ($1 = 0; $1 < $2; $1++) { $n" &
" $3 = (($4[$1] & ~ $5[$1]) == 0);$n" &
" if (!$3) break;}$n",
@@ -2054,7 +2054,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
"if ($3) $3 = (#nimCmpMem($4, $5, $2) != 0);$n",
"&",
"|",
"& ~"]
"& ~",
"^"]
var a, b: TLoc
var i: TLoc
var setType = skipTypes(e[1].typ, abstractVar)
@@ -2085,6 +2086,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
of mXorSet: binaryExpr(p, e, d, "($1 ^ $2)")
of mInSet:
genInOp(p, e, d)
else: internalError(p.config, e.info, "genSetOp()")
@@ -2112,7 +2114,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
var a = initLocExpr(p, e[1])
var b = initLocExpr(p, e[2])
putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size]))
of mMulSet, mPlusSet, mMinusSet:
of mMulSet, mPlusSet, mMinusSet, mXorSet:
# we inline the simple for loop for better code generation:
i = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
a = initLocExpr(p, e[1])
@@ -2548,7 +2550,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mSetLengthStr: genSetLengthStr(p, e, d)
of mSetLengthSeq: genSetLengthSeq(p, e, d)
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
mInSet:
mInSet, mXorSet:
genSetOp(p, e, d, op)
of mNewString, mNewStringOfCap, mExit, mParseBiggestFloat:
var opr = e[0].sym

View File

@@ -373,6 +373,7 @@ proc getTypePre(m: BModule; typ: PType; sig: SigHash): Rope =
if result == "": result = cacheGetType(m.typeCache, sig)
proc addForwardStructFormat(m: BModule; structOrUnion: Rope, typename: Rope) =
# XXX should be no-op in NIFC
if m.compileToCpp:
m.s[cfsForwardTypes].addf "$1 $2;$n", [structOrUnion, typename]
else:
@@ -923,17 +924,28 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
(sfImportc in t.sym.flags and t.sym.magic == mNone)):
m.typeCache[sig] = result
var size: int
var typedef = newBuilder("")
if firstOrd(m.config, t) < 0:
m.s[cfsTypes].addf("typedef NI32 $1;$n", [result])
typedef.addTypedef(name = result):
typedef.add("NI32")
size = 4
else:
size = int(getSize(m.config, t))
case size
of 1: m.s[cfsTypes].addf("typedef NU8 $1;$n", [result])
of 2: m.s[cfsTypes].addf("typedef NU16 $1;$n", [result])
of 4: m.s[cfsTypes].addf("typedef NI32 $1;$n", [result])
of 8: m.s[cfsTypes].addf("typedef NI64 $1;$n", [result])
of 1:
typedef.addTypedef(name = result):
typedef.add("NU8")
of 2:
typedef.addTypedef(name = result):
typedef.add("NU16")
of 4:
typedef.addTypedef(name = result):
typedef.add("NI32")
of 8:
typedef.addTypedef(name = result):
typedef.add("NI64")
else: internalError(m.config, t.sym.info, "getTypeDescAux: enum")
m.s[cfsTypes].add(typedef)
when false:
let owner = hashOwner(t.sym)
if not gDebugInfo.hasEnum(t.sym.name.s, t.sym.info.line, owner):
@@ -993,7 +1005,10 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
m.typeCache[sig] = result
if not isImportedType(t):
let foo = getTypeDescAux(m, t.elementType, check, kind)
m.s[cfsTypes].addf("typedef $1 $2[1];$n", [foo, result])
var typedef = newBuilder("")
typedef.addArrayTypedef(name = result, len = 1):
typedef.add(foo)
m.s[cfsTypes].add(typedef)
of tyArray:
var n: BiggestInt = toInt64(lengthOrd(m.config, t))
if n <= 0: n = 1 # make an array of at least one element
@@ -1001,8 +1016,10 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
m.typeCache[sig] = result
if not isImportedType(t):
let e = getTypeDescAux(m, t.elementType, check, kind)
m.s[cfsTypes].addf("typedef $1 $2[$3];$n",
[e, result, rope(n)])
var typedef = newBuilder("")
typedef.addArrayTypedef(name = result, len = n):
typedef.add(e)
m.s[cfsTypes].add(typedef)
of tyObject, tyTuple:
let tt = origTyp.skipTypes({tyDistinct})
if isImportedCppType(t) and tt.kind == tyGenericInst:
@@ -1048,7 +1065,8 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
# with the C macros for defining procs such as N_NIMCALL. We must
# create a typedef for the type and use it in the proc signature:
let typedefName = "TY" & $sig
m.s[cfsTypes].addf("typedef $1 $2;$n", [result, typedefName])
m.s[cfsTypes].addTypedef(name = typedefName):
m.s[cfsTypes].add(result)
m.typeCache[sig] = typedefName
result = typedefName
else:
@@ -1076,9 +1094,12 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
if not isImportedType(t):
let s = int(getSize(m.config, t))
case s
of 1, 2, 4, 8: m.s[cfsTypes].addf("typedef NU$2 $1;$n", [result, rope(s*8)])
else: m.s[cfsTypes].addf("typedef NU8 $1[$2];$n",
[result, rope(getSize(m.config, t))])
of 1, 2, 4, 8:
m.s[cfsTypes].addTypedef(name = result):
m.s[cfsTypes].add("NU" & rope(s*8))
else:
m.s[cfsTypes].addArrayTypedef(name = result, len = s):
m.s[cfsTypes].add("NU8")
of tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias, tySink, tyOwned,
tyUserTypeClass, tyUserTypeClassInst, tyInferred:
result = getTypeDescAux(m, skipModifier(t), check, kind)

View File

@@ -170,3 +170,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasGenericsOpenSym3")
defineSymbol("nimHasJsNoLambdaLifting")
defineSymbol("nimHasDefaultFloatRoundtrip")
defineSymbol("nimHasXorSet")

View File

@@ -830,7 +830,7 @@ proc getName(n: PNode): string =
of nkAccQuoted:
result = "`"
for i in 0..<n.len: result.add(getName(n[i]))
result = "`"
result.add('`')
of nkOpenSymChoice, nkClosedSymChoice, nkOpenSym:
result = getName(n[0])
else:

View File

@@ -2458,6 +2458,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
of mMulSet: binaryExpr(p, n, r, "SetMul", "SetMul($1, $2)")
of mPlusSet: binaryExpr(p, n, r, "SetPlus", "SetPlus($1, $2)")
of mMinusSet: binaryExpr(p, n, r, "SetMinus", "SetMinus($1, $2)")
of mXorSet: binaryExpr(p, n, r, "SetXor", "SetXor($1, $2)")
of mIncl: binaryExpr(p, n, r, "", "$1[$2] = true")
of mExcl: binaryExpr(p, n, r, "", "delete $1[$2]")
of mInSet:

View File

@@ -864,7 +864,7 @@ proc explicitGenericInstError(c: PContext; n: PNode): PNode =
localError(c.config, getCallLineInfo(n), errCannotInstantiateX % renderTree(n))
result = n
proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
proc explicitGenericSym(c: PContext, n: PNode, s: PSym, errors: var CandidateErrors, doError: bool): PNode =
if s.kind in {skTemplate, skMacro}:
internalError c.config, n.info, "cannot get explicitly instantiated symbol of " &
(if s.kind == skTemplate: "template" else: "macro")
@@ -874,6 +874,11 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
if m.state != csMatch:
# state is csMatch only if *all* generic params were matched,
# including implicit parameters
if doError:
errors.add(CandidateError(
sym: s,
firstMismatch: m.firstMismatch,
diagnostics: m.diagnostics))
return nil
var newInst = generateInstance(c, s, m.bindings, n.info)
newInst.typ.flags.excl tfUnresolved
@@ -897,42 +902,39 @@ proc setGenericParams(c: PContext, n, expectedParams: PNode) =
else:
n[i].typ() = e.typ.skipTypes({tyTypeDesc})
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
assert n.kind == nkBracketExpr
setGenericParams(c, n, s.ast[genericParamsPos])
var s = s
var a = n[0]
var errors: CandidateErrors = @[]
if a.kind == nkSym:
# common case; check the only candidate has the right
# number of generic type parameters:
if s.ast[genericParamsPos].safeLen != n.len-1:
let expected = s.ast[genericParamsPos].safeLen
localError(c.config, getCallLineInfo(n), errGenerated, "cannot instantiate: '" & renderTree(n) &
"'; got " & $(n.len-1) & " typeof(s) but expected " & $expected)
return n
result = explicitGenericSym(c, n, s)
if result == nil: result = explicitGenericInstError(c, n)
result = explicitGenericSym(c, n, s, errors, doError)
if doError and result == nil:
notFoundError(c, n, errors)
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
# choose the generic proc with the proper number of type parameters.
# XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
# It's good enough for now.
result = newNodeI(a.kind, getCallLineInfo(n))
for i in 0..<a.len:
var candidate = a[i].sym
if candidate.kind in {skProc, skMethod, skConverter,
skFunc, skIterator}:
# it suffices that the candidate has the proper number of generic
# type parameters:
if candidate.ast[genericParamsPos].safeLen == n.len-1:
let x = explicitGenericSym(c, n, candidate)
if x != nil: result.add(x)
let x = explicitGenericSym(c, n, candidate, errors, doError)
if x != nil: result.add(x)
# get rid of nkClosedSymChoice if not ambiguous:
if result.len == 1 and a.kind == nkClosedSymChoice:
result = result[0]
elif result.len == 0: result = explicitGenericInstError(c, n)
# candidateCount != 1: return explicitGenericInstError(c, n)
if result.len == 0:
result = nil
if doError:
notFoundError(c, n, errors)
else:
result = explicitGenericInstError(c, n)
# probably unreachable: we are trying to instantiate `a` which is not
# a sym/symchoice
if doError:
result = explicitGenericInstError(c, n)
else:
result = nil
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): tuple[s: PSym, state: TBorrowState] =
# Searches for the fn in the symbol table. If the parameter lists are suitable

View File

@@ -1724,27 +1724,15 @@ proc semDeref(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: result = nil
#GlobalError(n[0].info, errCircumNeedsPointer)
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym): PNode =
## Instantiates generic if not lacking implicit generics,
## otherwise returns n.
let
neededGenParams = s.ast[genericParamsPos].len
heldGenParams = n.len - 1
var implicitParams = 0
for x in s.ast[genericParamsPos]:
if tfImplicitTypeParam in x.typ.flags:
inc implicitParams
if heldGenParams != neededGenParams and implicitParams + heldGenParams == neededGenParams:
# This is an implicit + explicit generic procedure without all args passed,
# kicking back the sem'd symbol fixes #17212
# Uncertain the hackiness of this solution.
result = n
else:
result = explicitGenericInstantiation(c, n, s)
if result == n:
n[0] = copyTree(result[0])
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
## Attempts to instantiate generic proc symbol(s) with given parameters.
## If instantiation causes errors; if `doError` is `true`, a type mismatch
## error is given, otherwise `nil` is returned.
result = explicitGenericInstantiation(c, n, s, doError)
if result == n:
n[0] = copyTree(result[0])
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = false): PNode =
## returns nil if not a built-in subscript operator; also called for the
## checking of assignments
result = nil
@@ -1768,7 +1756,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
result.typ() = semStaticType(c, n[1], nil)
return
elif arr.n != nil:
return semSubscript(c, arr.n, flags)
return semSubscript(c, arr.n, flags, afterOverloading)
else:
arr = arr.base
@@ -1825,7 +1813,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
of skProc, skFunc, skMethod, skConverter, skIterator:
# type parameters: partial generic specialization
n[0] = semSymGenericInstantiation(c, n[0], s)
result = maybeInstantiateGeneric(c, n, s)
result = maybeInstantiateGeneric(c, n, s, doError = afterOverloading)
if result != nil:
# check newly created sym/symchoice
result = semExpr(c, result, flags)
of skMacro, skTemplate:
if efInCall in flags:
# We are processing macroOrTmpl[] in macroOrTmpl[](...) call.

View File

@@ -302,6 +302,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
of mMinusSet:
result = nimsets.diffSets(g.config, a, b)
result.info = n.info
of mXorSet:
result = nimsets.symdiffSets(g.config, a, b)
result.info = n.info
of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g)
of mInSet: result = newIntNodeT(toInt128(ord(inSet(a, b))), n, idgen, g)
of mRepr:

View File

@@ -61,12 +61,12 @@ type
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = false): PNode
proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
result = newNodeI(nkBracketExpr, n.info)
for i in 1..<n.len: result.add(n[i])
result = semSubscript(c, result, flags)
result = semSubscript(c, result, flags, afterOverloading = true)
if result.isNil:
let x = copyTree(n)
x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
@@ -79,9 +79,20 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
result.typ() = makeTypeFromExpr(c, copyTree(result))
result.typ.flags.incl tfNonConstExpr
return
bracketNotFoundError(c, x, flags)
#localError(c.config, n.info, "could not resolve: " & $n)
result = errorNode(c, n)
let s = # extract sym from first arg
if n.len > 1:
if n[1].kind == nkSym: n[1].sym
elif n[1].kind in nkSymChoices + {nkOpenSym} and n[1].len != 0:
n[1][0].sym
else: nil
else: nil
if s != nil and s.kind in routineKinds:
# this is a failed generic instantiation
# semSubscript should already error but this is better for cascading errors
result = explicitGenericInstError(c, n)
else:
bracketNotFoundError(c, x, flags)
result = errorNode(c, n)
proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
# rewrite `[]=`(a, i, x) back to ``a[i] = x``.

View File

@@ -200,6 +200,9 @@ proc matchGenericParams*(m: var TCandidate, binding: PNode, callee: PSym) =
elif tfImplicitTypeParam in paramSym.typ.flags:
# not a mismatch, but can't create sym
m.state = csEmpty
m.firstMismatch.kind = kMissingGenericParam
m.firstMismatch.arg = i + 1
m.firstMismatch.formal = paramSym
return
else:
m.state = csNoMatch

View File

@@ -1276,6 +1276,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
createSet(regs[ra])
move(regs[ra].node.sons,
nimsets.diffSets(c.config, regs[rb].node, regs[rc].node).sons)
of opcXorSet:
decodeBC(rkNode)
createSet(regs[ra])
move(regs[ra].node.sons,
nimsets.symdiffSets(c.config, regs[rb].node, regs[rc].node).sons)
of opcConcatStr:
decodeBC(rkNode)
createStr regs[ra]

View File

@@ -100,7 +100,7 @@ type
opcEqRef, opcEqNimNode, opcSameNodeType,
opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
opcEqStr, opcEqCString, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcMulSet, opcPlusSet, opcMinusSet, opcConcatStr,
opcMulSet, opcPlusSet, opcMinusSet, opcXorSet, opcConcatStr,
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcIsNil, opcOf, opcIs,
opcParseFloat, opcConv, opcCast,

View File

@@ -1212,6 +1212,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
of mMulSet: genBinarySet(c, n, dest, opcMulSet)
of mPlusSet: genBinarySet(c, n, dest, opcPlusSet)
of mMinusSet: genBinarySet(c, n, dest, opcMinusSet)
of mXorSet: genBinarySet(c, n, dest, opcXorSet)
of mConStrStr: genVarargsABC(c, n, dest, opcConcatStr)
of mInSet: genBinarySet(c, n, dest, opcContainsSet)
of mRepr: genUnaryABC(c, n, dest, opcRepr)

View File

@@ -77,10 +77,10 @@ proc newDate*(): DateTime {.
proc newDate*(date: int|string): DateTime {.
importcpp: "new Date(#)".}
whenJsNoBigInt64:
when jsNoBigInt64:
proc newDate*(date: int64): DateTime {.
importcpp: "new Date(#)".}
do:
else:
proc newDate*(date: int64): DateTime {.
importcpp: "new Date(Number(#))".}

View File

@@ -1095,7 +1095,21 @@ proc setprotoent*(a1: cint) {.importc, header: "<netdb.h>".}
proc setservent*(a1: cint) {.importc, header: "<netdb.h>".}
when not defined(lwip):
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: int): cint {.
# Linux and Haiku emulate SVR4, which used unsigned long.
# Meanwhile, BSD derivatives had used unsigned int; we will use this
# for the else case, because it is more widely cloned than SVR4's
# behavior.
when defined(linux) or defined(haiku):
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
elif defined(zephyr):
type
Tnfds* = distinct cint
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cuint
proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {.
importc, header: "<poll.h>", sideEffect.}
proc realpath*(name, resolved: cstring): cstring {.

View File

@@ -519,8 +519,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -563,8 +563,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -533,8 +533,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -484,8 +484,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = culong
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -517,8 +517,6 @@ type
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -604,13 +604,6 @@ when not defined(lwip):
events*: cshort ## The input event flags (see below).
revents*: cshort ## The output event flags (see below).
when defined(zephyr):
type
Tnfds* = distinct cint
else:
type
Tnfds* {.importc: "nfds_t", header: "<poll.h>".} = cint
var
errno* {.importc, header: "<errno.h>".}: cint ## error variable
h_errno* {.importc, header: "<netdb.h>".}: cint

View File

@@ -65,7 +65,7 @@ runnableExamples:
## * `sha1 module <sha1.html>`_ for the SHA-1 checksum algorithm
## * `tables module <tables.html>`_ for hash tables
import std/private/since
import std/private/[since, jsutils]
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -518,17 +518,10 @@ proc hashFarm(s: openArray[byte]): uint64 {.inline.} =
swap z, x
len16 len16(v[0],w[0],mul) + shiftMix(y)*k0 + z, len16(v[1],w[1],mul) + x, mul
template jsNoInt64: untyped =
when defined js:
when compiles(compileOption("jsbigint64")):
when not compileOption("jsbigint64"): true
else: false
else: false
else: false
const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false)
const sHash2 = defined(nimStringHash2) or jsNoBigInt64
template maybeFailJS_Number =
when jsNoInt64() and not defined(nimStringHash2):
when jsNoBigInt64 and not defined(nimStringHash2):
{.error: "Must use `-d:nimStringHash2` when using `--jsbigint64:off`".}
proc hash*(x: string): Hash =

View File

@@ -231,7 +231,7 @@ proc selectInto*[T](s: Selector[T], timeout: int,
verifySelectParams(timeout)
s.withPollLock():
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), timeout)
let count = posix.poll(addr(s.pollfds[0]), Tnfds(s.pollcnt), cint(timeout))
if count < 0:
result = 0
let err = osLastError()

View File

@@ -211,7 +211,7 @@ when defined(nimHasStyleChecks):
when defined(posix) and not defined(lwip):
from std/posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int =
template monitorPollEvent(x: var SocketHandle, y, timeout: cint): int =
var tpollfd: TPollfd
tpollfd.fd = cast[cint](x)
tpollfd.events = y
@@ -222,14 +222,14 @@ proc timeoutRead(fd: var SocketHandle, timeout = 500): int =
var fds = @[fd]
selectRead(fds, timeout)
else:
monitorPollEvent(fd, POLLIN or POLLPRI, timeout)
monitorPollEvent(fd, POLLIN or POLLPRI, cint(timeout))
proc timeoutWrite(fd: var SocketHandle, timeout = 500): int =
when defined(windows) or defined(lwip):
var fds = @[fd]
selectWrite(fds, timeout)
else:
monitorPollEvent(fd, POLLOUT or POLLWRBAND, timeout)
monitorPollEvent(fd, POLLOUT or POLLWRBAND, cint(timeout))
proc socketError*(socket: Socket, err: int = -1, async = false,
lastError = (-1).OSErrorCode,

View File

@@ -79,24 +79,13 @@ when defined(nimPreviewSlimSystem):
include system/inclrtl
{.push debugger: off.}
template whenHasBigInt64(yes64, no64): untyped =
when defined(js):
when compiles(compileOption("jsbigint64")):
when compileOption("jsbigint64"):
yes64
else:
no64
else:
no64
else:
yes64
whenHasBigInt64:
when hasWorkingInt64:
type Ui = uint64
const randMax = 18_446_744_073_709_551_615u64
do:
else:
type Ui = uint32
const randMax = 4_294_967_295u32
@@ -118,14 +107,14 @@ type
## generator are **not** thread-safe!
a0, a1: Ui
whenHasBigInt64:
when hasWorkingInt64:
const DefaultRandSeed = Rand(
a0: 0x69B4C98CB8530805u64,
a1: 0xFED1DD3004688D67CAu64)
# racy for multi-threading but good enough for now:
var state = DefaultRandSeed # global for backwards compatibility
do:
else:
var state = Rand(
a0: 0x69B4C98Cu32,
a1: 0xFED1DD30u32) # global for backwards compatibility
@@ -221,9 +210,9 @@ proc skipRandomNumbers*(s: var Rand) =
doAssert vals == [501737, 497901, 500683, 500157]
whenHasBigInt64:
when hasWorkingInt64:
const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64]
do:
else:
const helper = [0xbeac0467u32, 0xd86b048bu32]
var
s0 = Ui 0
@@ -359,9 +348,9 @@ proc rand*[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T =
when T is SomeFloat:
result = rand(r, x.b - x.a) + x.a
else: # Integers and Enum types
whenJsNoBigInt64:
when jsNoBigInt64:
result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a))
do:
else:
result = cast[T](rand(r, cast[uint64](x.b) - cast[uint64](x.a)) + cast[uint64](x.a))
proc rand*[T: Ordinal or SomeFloat](x: HSlice[T, T]): T =
@@ -402,9 +391,9 @@ proc rand*[T: Ordinal](r: var Rand; t: typedesc[T]): T {.since: (1, 7, 1).} =
elif T is bool:
result = r.next < randMax div 2
else:
whenJsNoBigInt64:
when jsNoBigInt64:
result = cast[T](r.next shr (sizeof(uint)*8 - sizeof(T)*8))
do:
else:
result = cast[T](r.next shr (sizeof(uint64)*8 - sizeof(T)*8))
proc rand*[T: Ordinal](t: typedesc[T]): T =

View File

@@ -998,9 +998,9 @@ func toHex*[T: SomeInteger](x: T, len: Positive): string =
doAssert b.toHex(4) == "1001"
doAssert toHex(62, 3) == "03E"
doAssert toHex(-8, 6) == "FFFFF8"
whenJsNoBigInt64:
when jsNoBigInt64:
toHexImpl(cast[BiggestUInt](x), len, x < 0)
do:
else:
when T is SomeSignedInt:
toHexImpl(cast[BiggestUInt](BiggestInt(x)), len, x < 0)
else:
@@ -1011,9 +1011,9 @@ func toHex*[T: SomeInteger](x: T): string =
runnableExamples:
doAssert toHex(1984'i64) == "00000000000007C0"
doAssert toHex(1984'i16) == "07C0"
whenJsNoBigInt64:
when jsNoBigInt64:
toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
do:
else:
when T is SomeSignedInt:
toHexImpl(cast[BiggestUInt](BiggestInt(x)), 2*sizeof(T), x < 0)
else:

View File

@@ -215,27 +215,29 @@ when defined(nimPreviewSlimSystem):
when defined(js):
import std/jscore
import std/private/jsutils
# This is really bad, but overflow checks are broken badly for
# ints on the JS backend. See #6752.
{.push overflowChecks: off.}
proc `*`(a, b: int64): int64 =
system.`*`(a, b)
proc `*`(a, b: int): int =
system.`*`(a, b)
proc `+`(a, b: int64): int64 =
system.`+`(a, b)
proc `+`(a, b: int): int =
system.`+`(a, b)
proc `-`(a, b: int64): int64 =
system.`-`(a, b)
proc `-`(a, b: int): int =
system.`-`(a, b)
proc inc(a: var int, b: int) =
system.inc(a, b)
proc inc(a: var int64, b: int) =
system.inc(a, b)
{.pop.}
when jsNoBigInt64:
# This is really bad, but overflow checks are broken badly for
# ints on the JS backend. See #6752.
{.push overflowChecks: off.}
proc `*`(a, b: int64): int64 =
system.`*`(a, b)
proc `*`(a, b: int): int =
system.`*`(a, b)
proc `+`(a, b: int64): int64 =
system.`+`(a, b)
proc `+`(a, b: int): int =
system.`+`(a, b)
proc `-`(a, b: int64): int64 =
system.`-`(a, b)
proc `-`(a, b: int): int =
system.`-`(a, b)
proc inc(a: var int, b: int) =
system.inc(a, b)
proc inc(a: var int64, b: int) =
system.inc(a, b)
{.pop.}
elif defined(posix):
import std/posix

View File

@@ -83,14 +83,21 @@ when defined(js):
assert 9007199254740991.toJs.isSafeInteger
assert not 9007199254740992.toJs.isSafeInteger
template whenJsNoBigInt64*(no64, yes64): untyped =
const jsNoBigInt64* =
when defined(js):
when compiles(compileOption("jsbigint64")):
when compileOption("jsbigint64"):
yes64
else:
no64
not compileOption("jsbigint64")
else:
no64
true
else:
no64
false
const hasWorkingInt64* =
# equal to `not jsNoBigInt64`, but define it by itself anyway
when defined(js):
when compiles(compileOption("jsbigint64")):
compileOption("jsbigint64")
else:
false
else:
true

View File

@@ -75,3 +75,31 @@ func `[]=`*[T](t: var set[T], key: T, val: bool) {.inline.} =
s[a3] = true
assert s == {a2, a3}
if val: t.incl key else: t.excl key
when defined(nimHasXorSet):
func symmetricDifference*[T](x, y: set[T]): set[T] {.magic: "XorSet".} =
## This operator computes the symmetric difference of two sets,
## equivalent to but more efficient than `x + y - x * y` or
## `(x - y) + (y - x)`.
runnableExamples:
assert symmetricDifference({1, 2, 3}, {2, 3, 4}) == {1, 4}
else:
func symmetricDifference*[T](x, y: set[T]): set[T] {.inline.} =
result = x + y - (x * y)
proc `-+-`*[T](x, y: set[T]): set[T] {.inline.} =
## Operator alias for `symmetricDifference`.
runnableExamples:
assert {1, 2, 3} -+- {2, 3, 4} == {1, 4}
result = symmetricDifference(x, y)
proc toggle*[T](x: var set[T], y: set[T]) {.inline.} =
## Toggles the existence of each value of `y` in `x`.
## If any element in `y` is also in `x`, it is excluded from `x`;
## otherwise it is included.
## Equivalent to `x = symmetricDifference(x, y)`.
runnableExamples:
var x = {1, 2, 3}
x.toggle({2, 3, 4})
assert x == {1, 4}
x = symmetricDifference(x, y)

View File

@@ -337,6 +337,18 @@ proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
return result;
""".}
proc SetXor(a, b: int): int {.compilerproc, asmNoStackFrame.} =
{.emit: """
var result = {};
for (var elem in `a`) {
if (!`b`[elem]) { result[elem] = true; }
}
for (var elem in `b`) {
if (!`a`[elem]) { result[elem] = true; }
}
return result;
""".}
proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} =
{.emit: """
if (`a` == `b`) return 0;

View File

@@ -2,10 +2,17 @@ discard """
cmd: "nim check $options --hints:off $file"
action: "reject"
nimout:'''
tpointerprocs.nim(15, 11) Error: 'foo' doesn't have a concrete type, due to unspecified generic parameters.
tpointerprocs.nim(27, 11) Error: cannot instantiate: 'foo[int]'; got 1 typeof(s) but expected 2
tpointerprocs.nim(27, 14) Error: expression 'foo[int]' has no type (or is ambiguous)
tpointerprocs.nim(28, 11) Error: expression 'bar' has no type (or is ambiguous)
tpointerprocs.nim(22, 11) Error: 'foo' doesn't have a concrete type, due to unspecified generic parameters.
tpointerprocs.nim(34, 14) Error: type mismatch: got <int>
but expected one of:
proc foo(x: int | float; y: int or string): float
first type mismatch at position: 2 in generic parameters
missing generic parameter: y:type
expression: foo[int]
tpointerprocs.nim(34, 14) Error: cannot instantiate: 'foo[int]'
tpointerprocs.nim(34, 14) Error: expression 'foo[int]' has no type (or is ambiguous)
tpointerprocs.nim(35, 11) Error: expression 'bar' has no type (or is ambiguous)
'''
"""
@@ -25,4 +32,4 @@ block:
proc foo(x: int | float, y: int or string): float = result = 1.0
let
bar = foo[int]
baz = bar
baz = bar

View File

@@ -27,8 +27,7 @@ template test(opr, a, b, c: untyped): untyped =
test(`+`, 12'i8, -13'i16, -1'i16)
test(`shl`, 0b11, 0b100, 0b110000)
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test(`shl`, 0b11'i64, 0b100'i64, 0b110000'i64)
when not defined(js):
# mixed type shr needlessly complicates codegen with bigint
@@ -39,25 +38,21 @@ test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64)
test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16)
test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8)
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32)
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)

View File

@@ -10,8 +10,7 @@ proc main()=
doAssert fn(array[2, uint8].default) == "Uint8Array"
doAssert fn(array[2, byte].default) == "Uint8Array"
doAssert fn(array[2, char].default) == "Uint8Array"
whenJsNoBigInt64: discard
do:
when not jsNoBigInt64:
doAssert fn(array[2, uint64].default) == "BigUint64Array"
doAssert fn([1'u8]) == "Uint8Array"
doAssert fn([1'u16]) == "Uint16Array"

View File

@@ -61,8 +61,7 @@ template main =
doAssert -2147483648'i32 == int32.low
when int.sizeof > 4:
doAssert -9223372036854775808 == int.low
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
doAssert -9223372036854775808 == int64.low
block: # check when a minus (-) is an unary op

View File

@@ -0,0 +1,6 @@
# related to issue #8064
import tables
let x = values[int] #[tt.Error
^ ambiguous identifier: 'values' -- use one of the following:]#

View File

@@ -0,0 +1,7 @@
# issue #8064
import tables
values[int] #[tt.Error
^ ambiguous identifier: 'values' -- use one of the following:]#
# this happens before discard check, so no discard error

View File

@@ -3,7 +3,7 @@ discard """
matrix: "--hint:processing"
nimout: '''
compile start
..
...
warn_module.nim(6, 6) Hint: 'test' is declared but not used [XDeclaredButNotUsed]
compile end
'''

View File

@@ -314,8 +314,7 @@ block: # bug #17383
else:
testRoundtrip(int.high): "9223372036854775807"
testRoundtrip(uint.high): "18446744073709551615"
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
testRoundtrip(int64.high): "9223372036854775807"
testRoundtrip(uint64.high): "18446744073709551615"

View File

@@ -225,8 +225,9 @@ block: # same as above but use slice overload
doAssert a3.type is a2.type
test cast[uint](int.high)
test cast[uint](int.high) + 1
whenJsNoBigInt64: discard
do:
when hasWorkingInt64 and defined(js):
# weirdly this has to run only in JS for the final int32.high test
# to be the same between C/C++ and --jsbigint64:on
test uint64.high
test uint64.high - 1
test uint.high - 2

View File

@@ -44,6 +44,26 @@ template main =
s[a2] = true
s[a3] = true
doAssert s == {a2, a3}
block: # set symmetric difference (xor), https://github.com/nim-lang/RFCs/issues/554
type T = set[range[0..15]]
let x: T = {1, 4, 5, 8, 9}
let y: T = {0, 2..6, 9}
let res = symmetricDifference(x, y)
doAssert res == {0, 1, 2, 3, 6, 8}
doAssert res == (x + y - x * y)
doAssert res == ((x - y) + (y - x))
var z = x
doAssert z == {1, 4, 5, 8, 9}
doAssert z == x
z.toggle(y)
doAssert z == res
z.toggle(y)
doAssert z == x
z.toggle({1, 5})
doAssert z == {4, 8, 9}
z.toggle({3, 8})
doAssert z == {3, 4, 9}
main()
static: main()

View File

@@ -527,8 +527,7 @@ template main() =
block: # toHex
doAssert(toHex(100i16, 32) == "00000000000000000000000000000064")
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
@@ -550,9 +549,8 @@ template main() =
doAssert(spaces(0) == "")
block: # toBin, toOct
whenJsNoBigInt64: # bug #11369
discard
do:
when hasWorkingInt64:
# bug #11369
var num: int64 = -1
doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
doAssert num.toOct(24) == "001777777777777777777777"
@@ -773,8 +771,7 @@ bar
block: # formatSize
disableVm:
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
doAssert formatSize(4096) == "4KiB"

View File

@@ -66,8 +66,7 @@ block: # `$`(SomeInteger)
testType int
testType bool
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
testType uint64
testType int64
testType BiggestInt
@@ -177,8 +176,7 @@ proc main()=
res.addInt int64(i)
doAssert res == "-9-8-7-6-5-4-3-2-10"
whenJsNoBigInt64: discard
do:
when hasWorkingInt64:
test2 high(int64), "9223372036854775807"
test2 low(int64), "-9223372036854775808"
test2 high(int32), "2147483647"

16
tests/tools/tctags.nim Normal file
View File

@@ -0,0 +1,16 @@
discard """
cmd: '''nim ctags --stdout $file'''
nimout: '''
Foo
hello
`$$`
'''
action: "compile"
"""
type
Foo = object
proc hello() = discard
proc `$`(x: Foo): string = "foo"