From 0a058a6b8f32749ebb19bfcd824b9f219d317f68 Mon Sep 17 00:00:00 2001 From: metagn Date: Fri, 18 Oct 2024 20:06:42 +0300 Subject: [PATCH 1/6] better errors for standalone explicit generic instantiations (#24276) refs #8064, refs #24010 Error messages for standalone explicit generic instantiations are revamped. Failing standalone explicit generic instantiations now only error after overloading has finished and resolved to the default `[]` magic (this means `[]` can now be overloaded for procs but this isn't necessarily intentional, in #24010 it was documented that it isn't possible). The error messages for failed instantiations are also no longer a simple `cannot instantiate: foo` message, instead they now give the same type mismatch error message as overloads with mismatching explicit generic parameters. This is now possible due to the changes in #24010 that delegate all explicit generic proc instantiations to overload resolution. Old code that worked around this is now removed. `maybeInstantiateGeneric` could maybe also be removed in favor of just `explicitGenericSym`, the `result == n` case is due to `explicitGenericInstError` which is only for niche cases. Also, to cause "ambiguous identifier" error messages when the explicit instantiation is a symchoice and the expression context doesn't allow symchoices, we semcheck the sym/symchoice created by `explicitGenericSym` with the given expression flags. #8064 isn't entirely fixed because the error message is still misleading for the original case which does `values[1]`, as a consequence of #12664. --- compiler/semcall.nim | 44 ++++++++++---------- compiler/semexprs.nim | 35 ++++++---------- compiler/semmagic.nim | 21 +++++++--- compiler/sigmatch.nim | 3 ++ tests/generics/tpointerprocs.nim | 17 +++++--- tests/overload/tambiguousexplicitgeneric.nim | 6 +++ tests/overload/texplicitgenericdiscard.nim | 7 ++++ 7 files changed, 80 insertions(+), 53 deletions(-) create mode 100644 tests/overload/tambiguousexplicitgeneric.nim create mode 100644 tests/overload/texplicitgenericdiscard.nim diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 89d1b6a7b4..a195e9857f 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -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.. 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``. diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b76696230d..3538ea83cd 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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 diff --git a/tests/generics/tpointerprocs.nim b/tests/generics/tpointerprocs.nim index 2bcaf15b36..29c4f2954f 100644 --- a/tests/generics/tpointerprocs.nim +++ b/tests/generics/tpointerprocs.nim @@ -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 +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 \ No newline at end of file + baz = bar diff --git a/tests/overload/tambiguousexplicitgeneric.nim b/tests/overload/tambiguousexplicitgeneric.nim new file mode 100644 index 0000000000..cc6e3dbe40 --- /dev/null +++ b/tests/overload/tambiguousexplicitgeneric.nim @@ -0,0 +1,6 @@ +# related to issue #8064 + +import tables + +let x = values[int] #[tt.Error + ^ ambiguous identifier: 'values' -- use one of the following:]# diff --git a/tests/overload/texplicitgenericdiscard.nim b/tests/overload/texplicitgenericdiscard.nim new file mode 100644 index 0000000000..1a207849b6 --- /dev/null +++ b/tests/overload/texplicitgenericdiscard.nim @@ -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 From ae9287c4f3a70ce92ed47db71bcb0e1832e3b84c Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 19 Oct 2024 11:07:00 +0300 Subject: [PATCH 2/6] symmetric difference operation for sets via `xor` (#24286) closes https://github.com/nim-lang/RFCs/issues/554 Adds a symmetric difference operation to the language bitset type. This maps to a simple `xor` operation on the backend and thus is likely faster than the current alternatives, namely `(a - b) + (b - a)` or `a + b - a * b`. The compiler VM implementation of bitsets already implemented this via `symdiffSets` but it was never used. The standalone binary operation is added to `setutils`, named `symmetricDifference` in line with [hash sets](https://nim-lang.org/docs/sets.html#symmetricDifference%2CHashSet%5BA%5D%2CHashSet%5BA%5D). An operator version `-+-` and an in-place version like `toggle` as described in the RFC are also added, implemented as trivial sugar. --- changelog.md | 5 +++++ compiler/ast.nim | 4 ++-- compiler/ccgexprs.nim | 10 ++++++---- compiler/condsyms.nim | 1 + compiler/jsgen.nim | 1 + compiler/semfold.nim | 3 +++ compiler/vm.nim | 5 +++++ compiler/vmdef.nim | 2 +- compiler/vmgen.nim | 1 + lib/std/setutils.nim | 28 ++++++++++++++++++++++++++++ lib/system/jssys.nim | 12 ++++++++++++ tests/stdlib/tsetutils.nim | 20 ++++++++++++++++++++ 12 files changed, 85 insertions(+), 7 deletions(-) diff --git a/changelog.md b/changelog.md index e17b24b428..1310b6ae3f 100644 --- a/changelog.md +++ b/changelog.md @@ -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. diff --git a/compiler/ast.nim b/compiler/ast.nim index 9708252f0e..5ff986776c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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} diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 3f4e4ff763..c954e6057b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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 diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 4523081a63..81cc40f3f6 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -170,3 +170,4 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasGenericsOpenSym3") defineSymbol("nimHasJsNoLambdaLifting") defineSymbol("nimHasDefaultFloatRoundtrip") + defineSymbol("nimHasXorSet") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 6b882a4727..21781efde0 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -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: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 8acb312c63..eb5db88fc9 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -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: diff --git a/compiler/vm.nim b/compiler/vm.nim index 1be04a922d..f26d41324f 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -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] diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 42e58c63b8..bfa589402a 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -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, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index a40f0afe47..59b8bf17f7 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -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) diff --git a/lib/std/setutils.nim b/lib/std/setutils.nim index 8e7bc6a92d..32a2e88f2c 100644 --- a/lib/std/setutils.nim +++ b/lib/std/setutils.nim @@ -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) diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 5599240fdb..ec1af2ea57 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -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; diff --git a/tests/stdlib/tsetutils.nim b/tests/stdlib/tsetutils.nim index c8498f23e0..c3338a3a27 100644 --- a/tests/stdlib/tsetutils.nim +++ b/tests/stdlib/tsetutils.nim @@ -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() From 93c24fe1c5ca998f112cf77834b9bb02c4fc47c0 Mon Sep 17 00:00:00 2001 From: Jake Leahy Date: Sun, 20 Oct 2024 01:39:15 +1100 Subject: [PATCH 3/6] Fix quoted idents in ctags (#24317) Running `ctags` on files with quoted symbols (e.g. `$`) would list \` instead of the full ident. Issue was the result getting reassigned at the end to a \` instead of appending --- compiler/docgen.nim | 2 +- tests/tools/tctags.nim | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 tests/tools/tctags.nim diff --git a/compiler/docgen.nim b/compiler/docgen.nim index d457528217..2b25ded7df 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -830,7 +830,7 @@ proc getName(n: PNode): string = of nkAccQuoted: result = "`" for i in 0.. Date: Sat, 19 Oct 2024 17:40:28 +0300 Subject: [PATCH 4/6] clean up stdlib with --jsbigint64 (#24255) refs #6978, refs #6752, refs #21613, refs #24234 The `jsNoInt64`, `whenHasBigInt64`, `whenJsNoBigInt64` templates are replaced with bool constants to use with `when`. Weird that I didn't do this in the first place. The `whenJsNoBigInt64` template was also slightly misleading. The first branch was compiled for both no bigint64 on JS as well as on C/C++. It seems only `trandom` depended on this by mistake. The workaround for #6752 added in #6978 to `times` is also removed with `--jsbigint64:on`, but #24233 was also encountered with this, so this PR depends on #24234. --- lib/js/jscore.nim | 4 +-- lib/pure/hashes.nim | 13 +++------- lib/pure/random.nim | 31 ++++++++--------------- lib/pure/strutils.nim | 8 +++--- lib/pure/times.nim | 42 ++++++++++++++++--------------- lib/std/private/jsutils.nim | 21 ++++++++++------ tests/int/tints.nim | 15 ++++------- tests/js/ttypedarray.nim | 3 +-- tests/lexer/tunary_minus.nim | 3 +-- tests/pragmas/thintprocessing.nim | 2 +- tests/stdlib/tjson.nim | 3 +-- tests/stdlib/trandom.nim | 5 ++-- tests/stdlib/tstrutils.nim | 11 +++----- tests/system/tdollars.nim | 6 ++--- 14 files changed, 73 insertions(+), 94 deletions(-) diff --git a/lib/js/jscore.nim b/lib/js/jscore.nim index be353875c8..f8c201ad90 100644 --- a/lib/js/jscore.nim +++ b/lib/js/jscore.nim @@ -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(#))".} diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 1038d55a1e..cce8d2dbf6 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -65,7 +65,7 @@ runnableExamples: ## * `sha1 module `_ for the SHA-1 checksum algorithm ## * `tables module `_ 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 = diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 0ff5878a5c..35c3f4364c 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -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 = diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 81be7db179..818e23b15b 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -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: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 1d498e8739..b2f30b7a30 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -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 diff --git a/lib/std/private/jsutils.nim b/lib/std/private/jsutils.nim index 5f79eab278..9ba36d1a1b 100644 --- a/lib/std/private/jsutils.nim +++ b/lib/std/private/jsutils.nim @@ -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 diff --git a/tests/int/tints.nim b/tests/int/tints.nim index 773e8ccad6..b85a66b01b 100644 --- a/tests/int/tints.nim +++ b/tests/int/tints.nim @@ -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) diff --git a/tests/js/ttypedarray.nim b/tests/js/ttypedarray.nim index 4807cb1033..ec10170f61 100644 --- a/tests/js/ttypedarray.nim +++ b/tests/js/ttypedarray.nim @@ -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" diff --git a/tests/lexer/tunary_minus.nim b/tests/lexer/tunary_minus.nim index 5ec2b5c70e..48e8c0375a 100644 --- a/tests/lexer/tunary_minus.nim +++ b/tests/lexer/tunary_minus.nim @@ -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 diff --git a/tests/pragmas/thintprocessing.nim b/tests/pragmas/thintprocessing.nim index c608bc6e42..943d921669 100644 --- a/tests/pragmas/thintprocessing.nim +++ b/tests/pragmas/thintprocessing.nim @@ -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 ''' diff --git a/tests/stdlib/tjson.nim b/tests/stdlib/tjson.nim index e425501f69..c881bbe7e7 100644 --- a/tests/stdlib/tjson.nim +++ b/tests/stdlib/tjson.nim @@ -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" diff --git a/tests/stdlib/trandom.nim b/tests/stdlib/trandom.nim index eb32f77575..272e2e6ee2 100644 --- a/tests/stdlib/trandom.nim +++ b/tests/stdlib/trandom.nim @@ -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 diff --git a/tests/stdlib/tstrutils.nim b/tests/stdlib/tstrutils.nim index 35f6bc669b..0cabff8335 100644 --- a/tests/stdlib/tstrutils.nim +++ b/tests/stdlib/tstrutils.nim @@ -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" diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim index eabee81b38..1135694f8b 100644 --- a/tests/system/tdollars.nim +++ b/tests/system/tdollars.nim @@ -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" From e69eb99a159859338dbcd9606cf31a6c4700d90b Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 19 Oct 2024 21:54:17 +0300 Subject: [PATCH 5/6] use cbuilder for typedefs, add array typedef (#24330) The only remaining explicit use of `typedef` in the codegen (from my search) is in `addForwardStructFormat` which from what I understand won't do anything in NIFC. --- compiler/cbuilderdecls.nim | 11 ++++++++++ compiler/cbuilderexprs.nim | 1 + compiler/ccgtypes.nim | 45 ++++++++++++++++++++++++++++---------- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/compiler/cbuilderdecls.nim b/compiler/cbuilderdecls.nim index 1c54a85eb3..d17869ac80 100644 --- a/compiler/cbuilderdecls.nim +++ b/compiler/cbuilderdecls.nim @@ -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 diff --git a/compiler/cbuilderexprs.nim b/compiler/cbuilderexprs.nim index f381944ecc..0fda722ce5 100644 --- a/compiler/cbuilderexprs.nim +++ b/compiler/cbuilderexprs.nim @@ -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 & "*" diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 2337c70e63..361475e55e 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -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) From 67442471ae4504bc074c8bb02308613fadc199f8 Mon Sep 17 00:00:00 2001 From: bptato <60043228+bptato@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:15:39 +0200 Subject: [PATCH 6/6] Fix broken poll and nfds_t bindings (#24331) This fixes several cases of the Nim binding of nfds_t being inconsistent with the target platform signedness and/or size. Additionally, it fixes poll's third argument (timeout) being set to Nim "int" when it should have been "cint". The former is the same issue that #23045 had attempted to fix, but failed because it only considered Linux. (Also, it was only applied to version 2.0, so the two branches now have incompatible versions of the same bug.) Notes: * SVR4's original "unsigned long" definition is cloned by Linux and Haiku. Nim got this right for Haiku and Linux-amd64, but it was wrong on non-amd64 Linux. * Zephyr does not have nfds_t, but simply uses (signed) "int". This was already correctly reflected by Nim. * OpenBSD poll.h uses "unsigned int", and other BSD derivatives follow suit. This being the most commonly copied definition, the fallback case now returns cuint. (This also seems to be correct for the OS X headers I could find on the web.) * This changes Nintendo Switch nfds_t to cuint from culong. It is purportedly a FreeBSD derivative, so I *think* this is correct, but I can't tell because I don't have access to the Nintendo Switch headers. I have also moved the platform-specific Tnfds to posix.nim so that we can reuse the fallback logic on all platforms. (e.g. specifying the size in posix_linux_amd64 only to then use when defined(linux) in posix_other seems redundant.) --- lib/posix/posix.nim | 16 +++++++++++++++- lib/posix/posix_haiku.nim | 2 -- lib/posix/posix_linux_amd64.nim | 2 -- lib/posix/posix_macos_amd64.nim | 2 -- lib/posix/posix_nintendoswitch.nim | 2 -- lib/posix/posix_openbsd_amd64.nim | 2 -- lib/posix/posix_other.nim | 7 ------- lib/pure/ioselects/ioselectors_poll.nim | 2 +- lib/pure/net.nim | 6 +++--- 9 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index d85c84a486..ca3ca12757 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -1095,7 +1095,21 @@ proc setprotoent*(a1: cint) {.importc, header: "".} proc setservent*(a1: cint) {.importc, header: "".} 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: "".} = culong + elif defined(zephyr): + type + Tnfds* = distinct cint + else: + type + Tnfds* {.importc: "nfds_t", header: "".} = cuint + + proc poll*(a1: ptr TPollfd, a2: Tnfds, a3: cint): cint {. importc, header: "", sideEffect.} proc realpath*(name, resolved: cstring): cstring {. diff --git a/lib/posix/posix_haiku.nim b/lib/posix/posix_haiku.nim index ba579778fa..6e325cb659 100644 --- a/lib/posix/posix_haiku.nim +++ b/lib/posix/posix_haiku.nim @@ -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: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_linux_amd64.nim b/lib/posix/posix_linux_amd64.nim index 8d11c507d7..7a9126abed 100644 --- a/lib/posix/posix_linux_amd64.nim +++ b/lib/posix/posix_linux_amd64.nim @@ -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: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_macos_amd64.nim b/lib/posix/posix_macos_amd64.nim index 59c4c65509..2b5dea69f4 100644 --- a/lib/posix/posix_macos_amd64.nim +++ b/lib/posix/posix_macos_amd64.nim @@ -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: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index b66563695c..fdc4e590e4 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -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: "".} = culong - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_openbsd_amd64.nim b/lib/posix/posix_openbsd_amd64.nim index 555980ed78..9244ce78cc 100644 --- a/lib/posix/posix_openbsd_amd64.nim +++ b/lib/posix/posix_openbsd_amd64.nim @@ -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: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index 9804ab0ba6..6301216d4c 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -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: "".} = cint - var errno* {.importc, header: "".}: cint ## error variable h_errno* {.importc, header: "".}: cint diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim index 7c53471563..6f50a5234d 100644 --- a/lib/pure/ioselects/ioselectors_poll.nim +++ b/lib/pure/ioselects/ioselectors_poll.nim @@ -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() diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 8ca1ab8259..6fecb8b8ef 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -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,