mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
43 Commits
pr_object
...
pr_refc_co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c4a5421b5 | ||
|
|
16f42084d3 | ||
|
|
3f51b6f73d | ||
|
|
c33ab0ba38 | ||
|
|
1ed54b7718 | ||
|
|
f05387045d | ||
|
|
be06446ffe | ||
|
|
1bb117cd7a | ||
|
|
420b0c14eb | ||
|
|
4c073cffbe | ||
|
|
5e016e4466 | ||
|
|
75205fee93 | ||
|
|
4d683fc689 | ||
|
|
16bc546aea | ||
|
|
686c75cef0 | ||
|
|
a37a83cbff | ||
|
|
814d3e6818 | ||
|
|
4898b054ce | ||
|
|
baa577e9e8 | ||
|
|
c71192043b | ||
|
|
3575f2bf9c | ||
|
|
ebb931f9f4 | ||
|
|
273d5ddf17 | ||
|
|
31d3606fe8 | ||
|
|
6ec9c7f683 | ||
|
|
63b4b3c5b8 | ||
|
|
0c6f14af04 | ||
|
|
a80f1a324f | ||
|
|
1c7fd71720 | ||
|
|
d5719c47dc | ||
|
|
2e4ba4ad93 | ||
|
|
b865f6a5f0 | ||
|
|
72ca444122 | ||
|
|
ecf9efa397 | ||
|
|
51ced0d684 | ||
|
|
c06623bf8c | ||
|
|
2315b01ae6 | ||
|
|
4fc9f0c3a3 | ||
|
|
115cec1745 | ||
|
|
0630c649c6 | ||
|
|
ff5ed1dbb1 | ||
|
|
7d83dfd0d1 | ||
|
|
3936071772 |
@@ -23,11 +23,11 @@ jobs:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
CPU: amd64
|
||||
# regularly breaks, refs bug #17325
|
||||
Linux_i386:
|
||||
# on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
|
||||
# g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
|
||||
vmImage: 'ubuntu-18.04'
|
||||
CPU: i386
|
||||
# Linux_i386:
|
||||
# # on 'ubuntu-16.04' (not supported anymore anyways) it errored with:
|
||||
# # g++-multilib : Depends: gcc-multilib (>= 4:5.3.1-1ubuntu1) but it is not going to be installed
|
||||
# vmImage: 'ubuntu-18.04'
|
||||
# CPU: i386
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-11'
|
||||
CPU: amd64
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
|
||||
[//]: # "Additions:"
|
||||
- Added `parseutils.parseSize` - inverse to `strutils.formatSize` - to parse human readable sizes.
|
||||
|
||||
[//]: # "Deprecations:"
|
||||
|
||||
|
||||
@@ -135,30 +135,90 @@
|
||||
|
||||
- The experimental strictFuncs feature now disallows a store to the heap via a `ref` or `ptr` indirection.
|
||||
|
||||
- Underscores (`_`) as routine parameters are now ignored and cannot be used in the routine body.
|
||||
The following code now does not compile:
|
||||
- The underscore identifier (`_`) is now generally not added to scope when
|
||||
used as the name of a definition. While this was already the case for
|
||||
variables, it is now also the case for routine parameters, generic
|
||||
parameters, routine declarations, type declarations, etc. This means that the following code now does not compile:
|
||||
|
||||
```nim
|
||||
proc foo(_: int): int = _ + 1
|
||||
echo foo(1)
|
||||
|
||||
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
|
||||
echo foo[int]()
|
||||
|
||||
proc _() = echo "_"
|
||||
_()
|
||||
|
||||
type _ = int
|
||||
let x: _ = 3
|
||||
```
|
||||
|
||||
Instead, the following code now compiles:
|
||||
Whereas the following code now compiles:
|
||||
|
||||
```nim
|
||||
proc foo(_, _: int): int = 123
|
||||
echo foo(1, 2)
|
||||
```
|
||||
- Underscores (`_`) as generic parameters are not supported and cannot be used.
|
||||
Generics that use `_` as parameters will no longer compile requires you to replace `_` with something else:
|
||||
|
||||
```nim
|
||||
proc foo[_](t: typedesc[_]): string = "BAR" # Can not compile
|
||||
proc foo[T](t: typedesc[T]): string = "BAR" # Can compile
|
||||
|
||||
proc foo[_, _](): int = 123
|
||||
echo foo[int, bool]()
|
||||
|
||||
proc foo[T, U](_: typedesc[T], _: typedesc[U]): (T, U) = (default(T), default(U))
|
||||
echo foo(int, bool)
|
||||
|
||||
proc _() = echo "one"
|
||||
proc _() = echo "two"
|
||||
|
||||
type _ = int
|
||||
type _ = float
|
||||
```
|
||||
|
||||
- - Added the `--legacy:verboseTypeMismatch` switch to get legacy type mismatch error messages.
|
||||
|
||||
- The JavaScript backend now uses [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
|
||||
for 64-bit integer types (`int64` and `uint64`) by default. As this affects
|
||||
JS code generation, code using these types to interface with the JS backend
|
||||
may need to be updated. Note that `int` and `uint` are not affected.
|
||||
|
||||
For compatibility with [platforms that do not support BigInt](https://caniuse.com/bigint)
|
||||
and in the case of potential bugs with the new implementation, the
|
||||
old behavior is currently still supported with the command line option
|
||||
`--jsbigint64:off`.
|
||||
|
||||
- The `proc` and `iterator` type classes now respectively only match
|
||||
procs and iterators. Previously both type classes matched any of
|
||||
procs or iterators.
|
||||
|
||||
```nim
|
||||
proc prc(): int =
|
||||
123
|
||||
|
||||
iterator iter(): int =
|
||||
yield 123
|
||||
|
||||
proc takesProc[T: proc](x: T) = discard
|
||||
proc takesIter[T: iterator](x: T) = discard
|
||||
|
||||
# always compiled:
|
||||
takesProc(prc)
|
||||
takesIter(iter)
|
||||
# no longer compiles:
|
||||
takesProc(iter)
|
||||
takesIter(prc)
|
||||
```
|
||||
|
||||
- The `proc` and `iterator` type classes now accept a calling convention pragma
|
||||
(i.e. `proc {.closure.}`) that must be shared by matching proc or iterator
|
||||
types. Previously pragmas were parsed but discarded if no parameter list
|
||||
was given.
|
||||
|
||||
This is represented in the AST by an `nnkProcTy`/`nnkIteratorTy` node with
|
||||
an `nnkEmpty` node in the place of the `nnkFormalParams` node, and the pragma
|
||||
node in the same place as in a concrete `proc` or `iterator` type node. This
|
||||
state of the AST may be unexpected to existing code, both due to the
|
||||
replacement of the `nnkFormalParams` node as well as having child nodes
|
||||
unlike other type class AST.
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
@@ -231,6 +291,7 @@
|
||||
- Added `openArray[char]` overloads for `std/parseutils` allowing more code reuse.
|
||||
- Added `openArray[char]` overloads for `std/unicode` allowing more code reuse.
|
||||
- Added `safe` parameter to `base64.encodeMime`.
|
||||
- Added `parseutils.parseSize` - inverse to `strutils.formatSize` - to parse human readable sizes.
|
||||
|
||||
[//]: # "Deprecations:"
|
||||
- Deprecated `selfExe` for Nimscript.
|
||||
@@ -343,6 +404,26 @@
|
||||
|
||||
- `=wasMoved` can be overridden by users.
|
||||
|
||||
- Tuple unpacking for variables is now treated as syntax sugar that directly
|
||||
expands into multiple assignments. Along with this, tuple unpacking for
|
||||
variables can now be nested.
|
||||
|
||||
```nim
|
||||
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
|
||||
|
||||
let (x, (_, y), _, z) = returnsNestedTuple()
|
||||
# roughly becomes
|
||||
let
|
||||
tmpTup1 = returnsNestedTuple()
|
||||
x = tmpTup1[0]
|
||||
tmpTup2 = tmpTup1[1]
|
||||
y = tmpTup2[1]
|
||||
z = tmpTup1[3]
|
||||
```
|
||||
|
||||
As a result `nnkVarTuple` nodes in variable sections will no longer be
|
||||
reflected in `typed` AST.
|
||||
|
||||
## Compiler changes
|
||||
|
||||
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the
|
||||
@@ -364,4 +445,4 @@
|
||||
|
||||
## Tool changes
|
||||
|
||||
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs`).
|
||||
- Nim now ships Nimble version 0.14 which added support for lock-files. Libraries are stored in `$nimbleDir/pkgs2` (it was `$nimbleDir/pkgs`). Use `nimble develop --global` to create an old style link file in the special links directory documented at https://github.com/nim-lang/nimble#nimble-develop.
|
||||
|
||||
@@ -1947,7 +1947,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||
|
||||
initLoc(call, locCall, e, OnHeap)
|
||||
if not p.module.compileToCpp:
|
||||
const setLenPattern = "($3) #setLengthSeqV2(&($1)->Sup, $4, $2)"
|
||||
const setLenPattern = "($3) #setLengthSeqV2(($1)?&($1)->Sup:NIM_NIL, $4, $2)"
|
||||
call.r = ropecg(p.module, setLenPattern, [
|
||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||
genTypeInfoV1(p.module, t.skipTypes(abstractInst), e.info)])
|
||||
@@ -2339,7 +2339,7 @@ proc genWasMoved(p: BProc; n: PNode) =
|
||||
if p.withinBlockLeaveActions > 0 and notYetAlive(n1):
|
||||
discard
|
||||
else:
|
||||
initLocExpr(p, n1, a)
|
||||
initLocExpr(p, n1, a, {lfEnforceDeref})
|
||||
resetLoc(p, a)
|
||||
#linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
|
||||
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
|
||||
|
||||
@@ -200,6 +200,9 @@ proc isImportedCppType(t: PType): bool =
|
||||
result = (t.sym != nil and sfInfixCall in t.sym.flags) or
|
||||
(x.sym != nil and sfInfixCall in x.sym.flags)
|
||||
|
||||
proc isOrHasImportedCppType(typ: PType): bool =
|
||||
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
|
||||
|
||||
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKind): Rope
|
||||
|
||||
proc isObjLackingTypeField(typ: PType): bool {.inline.} =
|
||||
@@ -553,7 +556,10 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||
else:
|
||||
# don't use fieldType here because we need the
|
||||
# tyGenericInst for C++ template support
|
||||
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
if fieldType.isOrHasImportedCppType():
|
||||
result.addf("$1$3 $2{};$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
else:
|
||||
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
||||
|
||||
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||
|
||||
@@ -61,12 +61,12 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
var ms = getModule(s)
|
||||
result = m.g.modules[ms.position]
|
||||
|
||||
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
|
||||
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}) =
|
||||
result.k = k
|
||||
result.storage = s
|
||||
result.lode = lode
|
||||
result.r = ""
|
||||
result.flags = {}
|
||||
result.flags = flags
|
||||
|
||||
proc fillLoc(a: var TLoc, k: TLocKind, lode: PNode, r: Rope, s: TStorageLoc) {.inline.} =
|
||||
# fills the loc if it is not already initialized
|
||||
@@ -487,9 +487,6 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
# on the bytes following the m_type field?
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
|
||||
|
||||
proc isOrHasImportedCppType(typ: PType): bool =
|
||||
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
|
||||
|
||||
proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
|
||||
let typ = loc.t
|
||||
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
|
||||
@@ -644,7 +641,23 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||
if sfVolatile in s.flags: decl.add(" volatile")
|
||||
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
|
||||
if value != "":
|
||||
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||
if p.module.compileToCpp and value.startsWith "{{}":
|
||||
# TODO: taking this branch, re"\{\{\}(,\s\{\})*\}" might be emitted, resulting in
|
||||
# either warnings (GCC 12.2+) or errors (Clang 15, MSVC 19.3+) of C++11+ compilers **when
|
||||
# explicit constructors are around** due to overload resolution rules in place [^0][^1][^2]
|
||||
# *Workaround* here: have C++'s static initialization mechanism do the default init work,
|
||||
# for us lacking a deeper knowledge of an imported object's constructors' ex-/implicitness
|
||||
# (so far) *and yet* trying to achieve default initialization.
|
||||
# Still, generating {}s in genConstObjConstr() just to omit them here is faaaar from ideal;
|
||||
# need to figure out a better way, possibly by keeping around more data about the
|
||||
# imported objects' contructors?
|
||||
#
|
||||
# [^0]: https://en.cppreference.com/w/cpp/language/aggregate_initialization
|
||||
# [^1]: https://cplusplus.github.io/CWG/issues/1518.html
|
||||
# [^2]: https://eel.is/c++draft/over.match.ctor
|
||||
decl.addf(" $1;$n", [s.loc.r])
|
||||
else:
|
||||
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||
else:
|
||||
decl.addf(" $1;$n", [s.loc.r])
|
||||
else:
|
||||
@@ -685,8 +698,8 @@ proc genLiteral(p: BProc, n: PNode; result: var Rope)
|
||||
proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Rope; argsCounter: var int)
|
||||
proc raiseExit(p: BProc)
|
||||
|
||||
proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
|
||||
initLoc(result, locNone, e, OnUnknown)
|
||||
proc initLocExpr(p: BProc, e: PNode, result: var TLoc, flags: TLocFlags = {}) =
|
||||
initLoc(result, locNone, e, OnUnknown, flags)
|
||||
expr(p, e, result)
|
||||
|
||||
proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
|
||||
@@ -1086,7 +1099,7 @@ proc genProcBody(p: BProc; procBody: PNode) =
|
||||
proc isNoReturn(m: BModule; s: PSym): bool {.inline.} =
|
||||
sfNoReturn in s.flags and m.config.exc != excGoto
|
||||
|
||||
proc genProcAux(m: BModule, prc: PSym) =
|
||||
proc genProcAux*(m: BModule, prc: PSym) =
|
||||
var p = newProc(prc, m)
|
||||
var header = newRopeAppender()
|
||||
genProcHeader(m, prc, header)
|
||||
@@ -2094,7 +2107,7 @@ proc updateCachedModule(m: BModule) =
|
||||
cf.flags = {CfileFlag.Cached}
|
||||
addFileToCompile(m.config, cf)
|
||||
|
||||
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||
proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode): PNode =
|
||||
## Also called from IC.
|
||||
if sfMainModule in m.module.flags:
|
||||
# phase ordering problem here: We need to announce this
|
||||
@@ -2140,8 +2153,7 @@ proc finalCodegenActions*(graph: ModuleGraph; m: BModule; n: PNode) =
|
||||
|
||||
if m.g.forwardedProcs.len == 0:
|
||||
incl m.flags, objHasKidsValid
|
||||
let disp = generateMethodDispatchers(graph)
|
||||
for x in disp: genProcAux(m, x.sym)
|
||||
result = generateMethodDispatchers(graph, m.idgen)
|
||||
|
||||
let mm = m
|
||||
m.g.modulesClosed.add mm
|
||||
|
||||
@@ -213,7 +213,7 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
|
||||
a[j] = v
|
||||
if h == 1: break
|
||||
|
||||
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
|
||||
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet; idgen: IdGenerator): PSym =
|
||||
var base = methods[0].ast[dispatcherPos].sym
|
||||
result = base
|
||||
var paramLen = base.typ.len
|
||||
@@ -272,7 +272,7 @@ proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PS
|
||||
nilchecks.flags.incl nfTransf # should not be further transformed
|
||||
result.ast[bodyPos] = nilchecks
|
||||
|
||||
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
|
||||
proc generateMethodDispatchers*(g: ModuleGraph, idgen: IdGenerator): PNode =
|
||||
result = newNode(nkStmtList)
|
||||
for bucket in 0..<g.methods.len:
|
||||
var relevantCols = initIntSet()
|
||||
@@ -282,4 +282,4 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode =
|
||||
# if multi-methods are not enabled, we are interested only in the first field
|
||||
break
|
||||
sortBucket(g.methods[bucket].methods, relevantCols)
|
||||
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))
|
||||
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols, idgen))
|
||||
|
||||
@@ -336,6 +336,7 @@ proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool
|
||||
of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace)
|
||||
of "nilseqs", "nilchecks", "taintmode": warningOptionNoop(switch)
|
||||
of "panics": result = contains(conf.globalOptions, optPanics)
|
||||
of "jsbigint64": result = contains(conf.globalOptions, optJsBigInt64)
|
||||
else: invalidCmdLineOption(conf, passCmd1, switch, info)
|
||||
|
||||
proc processPath(conf: ConfigRef; path: string, info: TLineInfo,
|
||||
@@ -1065,29 +1066,6 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
of "expandarc":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
conf.arcToExpand[arg] = "T"
|
||||
of "useversion":
|
||||
expectArg(conf, switch, arg, pass, info)
|
||||
case arg
|
||||
of "1.0":
|
||||
defineSymbol(conf.symbols, "NimMajor", "1")
|
||||
defineSymbol(conf.symbols, "NimMinor", "0")
|
||||
# old behaviors go here:
|
||||
defineSymbol(conf.symbols, "nimOldRelativePathBehavior")
|
||||
undefSymbol(conf.symbols, "nimDoesntTrackDefects")
|
||||
ast.eqTypeFlags.excl {tfGcSafe, tfNoSideEffect}
|
||||
conf.globalOptions.incl optNimV1Emulation
|
||||
of "1.2":
|
||||
defineSymbol(conf.symbols, "NimMajor", "1")
|
||||
defineSymbol(conf.symbols, "NimMinor", "2")
|
||||
conf.globalOptions.incl optNimV12Emulation
|
||||
of "1.6":
|
||||
defineSymbol(conf.symbols, "NimMajor", "1")
|
||||
defineSymbol(conf.symbols, "NimMinor", "6")
|
||||
conf.globalOptions.incl optNimV16Emulation
|
||||
else:
|
||||
localError(conf, info, "unknown Nim version; currently supported values are: `1.0`, `1.2`")
|
||||
# always be compatible with 1.x.100:
|
||||
defineSymbol(conf.symbols, "NimPatch", "100")
|
||||
of "benchmarkvm":
|
||||
processOnOffSwitchG(conf, {optBenchmarkVM}, arg, pass, info)
|
||||
of "profilevm":
|
||||
@@ -1101,6 +1079,8 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
|
||||
processOnOffSwitchG(conf, {optPanics}, arg, pass, info)
|
||||
if optPanics in conf.globalOptions:
|
||||
defineSymbol(conf.symbols, "nimPanics")
|
||||
of "jsbigint64":
|
||||
processOnOffSwitchG(conf, {optJsBigInt64}, arg, pass, info)
|
||||
of "sourcemap": # xxx document in --fullhelp
|
||||
conf.globalOptions.incl optSourcemap
|
||||
conf.options.incl optLineDir
|
||||
|
||||
@@ -154,3 +154,4 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasGenericDefine")
|
||||
defineSymbol("nimHasDefineAliases")
|
||||
defineSymbol("nimHasWarnBareExcept")
|
||||
defineSymbol("nimHasWarnCopyHookForRefc")
|
||||
|
||||
@@ -112,13 +112,16 @@ type
|
||||
proc add(dest: var ItemPre, rst: PRstNode) = dest.add ItemFragment(isRst: true, rst: rst)
|
||||
proc add(dest: var ItemPre, str: string) = dest.add ItemFragment(isRst: false, str: str)
|
||||
|
||||
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
|
||||
proc addRstFileIndex(d: PDoc, fileIndex: lineinfos.FileIndex): rstast.FileIndex =
|
||||
let invalid = rstast.FileIndex(-1)
|
||||
result = d.nimToRstFid.getOrDefault(info.fileIndex, default = invalid)
|
||||
result = d.nimToRstFid.getOrDefault(fileIndex, default = invalid)
|
||||
if result == invalid:
|
||||
let fname = toFullPath(d.conf, info)
|
||||
let fname = toFullPath(d.conf, fileIndex)
|
||||
result = addFilename(d.sharedState, fname)
|
||||
d.nimToRstFid[info.fileIndex] = result
|
||||
d.nimToRstFid[fileIndex] = result
|
||||
|
||||
proc addRstFileIndex(d: PDoc, info: lineinfos.TLineInfo): rstast.FileIndex =
|
||||
addRstFileIndex(d, info.fileIndex)
|
||||
|
||||
proc cmpDecimalsIgnoreCase(a, b: string): int =
|
||||
## For sorting with correct handling of cases like 'uint8' and 'uint16'.
|
||||
@@ -1060,7 +1063,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind, docFlags: DocFlags, nonEx
|
||||
fileIndex: addRstFileIndex(d, nameNode.info))
|
||||
addAnchorNim(d.sharedState, external = false, refn = symbolOrId,
|
||||
tooltip = detailedName, langSym = rstLangSymbol,
|
||||
priority = symbolPriority(k), info = lineinfo)
|
||||
priority = symbolPriority(k), info = lineinfo,
|
||||
module = addRstFileIndex(d, FileIndex d.module.position))
|
||||
|
||||
let renderFlags =
|
||||
if nonExports: {renderNoBody, renderNoComments, renderDocComments, renderSyms,
|
||||
@@ -1451,7 +1455,8 @@ proc finishGenerateDoc*(d: var PDoc) =
|
||||
isGroup: true),
|
||||
priority = symbolPriority(k),
|
||||
# select index `0` just to have any meaningful warning:
|
||||
info = overloadChoices[0].info)
|
||||
info = overloadChoices[0].info,
|
||||
module = addRstFileIndex(d, FileIndex d.module.position))
|
||||
|
||||
if optGenIndexOnly in d.conf.globalOptions:
|
||||
return
|
||||
|
||||
@@ -50,7 +50,10 @@ proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var Alive
|
||||
let n = unpackTree(g, m.module.position, m.fromDisk.topLevel, p)
|
||||
cgen.genTopLevelStmt(bmod, n)
|
||||
|
||||
finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
|
||||
let disps = finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
|
||||
if disps != nil:
|
||||
for disp in disps:
|
||||
genProcAux(bmod, disp.sym)
|
||||
m.fromDisk.backendFlags = cgen.whichInitProcs(bmod)
|
||||
|
||||
proc replayTypeInfo(g: ModuleGraph; m: var LoadedModule; origin: FileIndex) =
|
||||
|
||||
@@ -249,7 +249,17 @@ proc canBeMoved(c: Con; t: PType): bool {.inline.} =
|
||||
proc isNoInit(dest: PNode): bool {.inline.} =
|
||||
result = dest.kind == nkSym and sfNoInit in dest.sym.flags
|
||||
|
||||
proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
proc deepAliases(dest, ri: PNode): bool =
|
||||
case ri.kind
|
||||
of nkCallKinds, nkStmtListExpr, nkBracket, nkTupleConstr, nkObjConstr,
|
||||
nkCast, nkConv, nkObjUpConv, nkObjDownConv:
|
||||
for r in ri:
|
||||
if deepAliases(dest, r): return true
|
||||
return false
|
||||
else:
|
||||
return aliases(dest, ri) != no
|
||||
|
||||
proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or
|
||||
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
|
||||
isNoInit(dest):
|
||||
@@ -263,7 +273,14 @@ proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNod
|
||||
else:
|
||||
# the default is to use combination of `=destroy(dest)` and
|
||||
# and copyMem(dest, source). This is efficient.
|
||||
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
|
||||
if deepAliases(dest, ri):
|
||||
# consider: x = x + y, it is wrong to destroy the destination first!
|
||||
# tmp to support self assignments
|
||||
let tmp = c.getTemp(s, dest.typ, dest.info)
|
||||
result = newTree(nkStmtList, newTree(nkFastAsgn, tmp, dest), newTree(nkFastAsgn, dest, ri),
|
||||
c.genDestroy(tmp))
|
||||
else:
|
||||
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
|
||||
|
||||
proc isCriticalLink(dest: PNode): bool {.inline.} =
|
||||
#[
|
||||
@@ -454,7 +471,7 @@ proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
|
||||
# This was already done in the sink parameter handling logic.
|
||||
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
|
||||
let tmp = c.getTemp(s, arg.typ, arg.info)
|
||||
result.add c.genSink(tmp, arg, {IsDecl})
|
||||
result.add c.genSink(s, tmp, arg, {IsDecl})
|
||||
result.add tmp
|
||||
s.final.add c.genDestroy(tmp)
|
||||
else:
|
||||
@@ -1004,7 +1021,7 @@ proc sameLocation*(a, b: PNode): bool =
|
||||
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b)
|
||||
else: false
|
||||
|
||||
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
proc genFieldAccessSideEffects(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
# with side effects
|
||||
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), nextSymId c.idgen, c.owner, ri[1].info)
|
||||
temp.typ = ri[1].typ
|
||||
@@ -1021,7 +1038,7 @@ proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCop
|
||||
newAccess.add ri[0]
|
||||
newAccess.add tempAsNode
|
||||
|
||||
var snk = c.genSink(dest, newAccess, flags)
|
||||
var snk = c.genSink(s, dest, newAccess, flags)
|
||||
result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess))
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
@@ -1039,21 +1056,21 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
|
||||
else:
|
||||
case ri.kind
|
||||
of nkCallKinds:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
|
||||
of nkBracketExpr:
|
||||
if isUnpackedTuple(ri[0]):
|
||||
# unpacking of tuple: take over the elements
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
|
||||
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s):
|
||||
if aliases(dest, ri) == no:
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
if isAtom(ri[1]):
|
||||
var snk = c.genSink(dest, ri, flags)
|
||||
var snk = c.genSink(s, dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = genFieldAccessSideEffects(c, dest, ri, flags)
|
||||
result = genFieldAccessSideEffects(c, s, dest, ri, flags)
|
||||
else:
|
||||
result = c.genSink(dest, destructiveMoveVar(ri, c, s), flags)
|
||||
result = c.genSink(s, dest, destructiveMoveVar(ri, c, s), flags)
|
||||
else:
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
@@ -1065,25 +1082,25 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
else:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
|
||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
result = c.genSink(s, dest, p(ri, c, s, consumed), flags)
|
||||
of nkSym:
|
||||
if isSinkParam(ri.sym) and isLastRead(ri, c, s):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
let snk = c.genSink(s, dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
|
||||
isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
let snk = c.genSink(s, dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
of nkHiddenSubConv, nkHiddenStdConv, nkConv, nkObjDownConv, nkObjUpConv, nkCast:
|
||||
result = c.genSink(dest, p(ri, c, s, sinkArg), flags)
|
||||
result = c.genSink(s, dest, p(ri, c, s, sinkArg), flags)
|
||||
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
|
||||
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
|
||||
# We know the result will be a stmt so we use that fact to optimize
|
||||
@@ -1094,7 +1111,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopy
|
||||
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s) and
|
||||
canBeMoved(c, dest.typ):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
let snk = c.genSink(s, dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
|
||||
@@ -571,12 +571,20 @@ proc binaryUintExpr(p: PProc, n: PNode, r: var TCompRes, op: string,
|
||||
var x, y: TCompRes
|
||||
gen(p, n[1], x)
|
||||
gen(p, n[2], y)
|
||||
let trimmer = unsignedTrimmer(n[1].typ.skipTypes(abstractRange).size)
|
||||
let size = n[1].typ.skipTypes(abstractRange).size
|
||||
when reassign:
|
||||
let (a, tmp) = maybeMakeTempAssignable(p, n[1], x)
|
||||
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
|
||||
if size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "$1 = BigInt.asUintN(64, ($4 $2 $3))" % [a, rope op, y.rdLoc, tmp]
|
||||
else:
|
||||
let trimmer = unsignedTrimmer(size)
|
||||
r.res = "$1 = (($5 $2 $3) $4)" % [a, rope op, y.rdLoc, trimmer, tmp]
|
||||
else:
|
||||
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
|
||||
if size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "BigInt.asUintN(64, ($1 $2 $3))" % [x.rdLoc, rope op, y.rdLoc]
|
||||
else:
|
||||
let trimmer = unsignedTrimmer(size)
|
||||
r.res = "(($1 $2 $3) $4)" % [x.rdLoc, rope op, y.rdLoc, trimmer]
|
||||
r.kind = resExpr
|
||||
|
||||
template ternaryExpr(p: PProc, n: PNode, r: var TCompRes, magic, frmt: string) =
|
||||
@@ -618,11 +626,45 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
if i == 0: applyFormat(frmtA) else: applyFormat(frmtB)
|
||||
|
||||
case op
|
||||
of mAddI: applyFormat("addInt($1, $2)", "($1 + $2)")
|
||||
of mSubI: applyFormat("subInt($1, $2)", "($1 - $2)")
|
||||
of mMulI: applyFormat("mulInt($1, $2)", "($1 * $2)")
|
||||
of mDivI: applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
|
||||
of mModI: applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
|
||||
of mAddI:
|
||||
if i == 0:
|
||||
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
useMagic(p, "addInt64")
|
||||
applyFormat("addInt64($1, $2)")
|
||||
else:
|
||||
applyFormat("addInt($1, $2)")
|
||||
else:
|
||||
applyFormat("($1 + $2)")
|
||||
of mSubI:
|
||||
if i == 0:
|
||||
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
useMagic(p, "subInt64")
|
||||
applyFormat("subInt64($1, $2)")
|
||||
else:
|
||||
applyFormat("subInt($1, $2)")
|
||||
else:
|
||||
applyFormat("($1 - $2)")
|
||||
of mMulI:
|
||||
if i == 0:
|
||||
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
useMagic(p, "mulInt64")
|
||||
applyFormat("mulInt64($1, $2)")
|
||||
else:
|
||||
applyFormat("mulInt($1, $2)")
|
||||
else:
|
||||
applyFormat("($1 * $2)")
|
||||
of mDivI:
|
||||
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
useMagic(p, "divInt64")
|
||||
applyFormat("divInt64($1, $2)", "$1 / $2")
|
||||
else:
|
||||
applyFormat("divInt($1, $2)", "Math.trunc($1 / $2)")
|
||||
of mModI:
|
||||
if n[1].typ.size == 8 and optJsBigInt64 in p.config.globalOptions:
|
||||
useMagic(p, "modInt64")
|
||||
applyFormat("modInt64($1, $2)", "$1 % $2")
|
||||
else:
|
||||
applyFormat("modInt($1, $2)", "Math.trunc($1 % $2)")
|
||||
of mSucc: applyFormat("addInt($1, $2)", "($1 + $2)")
|
||||
of mPred: applyFormat("subInt($1, $2)", "($1 - $2)")
|
||||
of mAddF64: applyFormat("($1 + $2)", "($1 + $2)")
|
||||
@@ -631,15 +673,27 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
|
||||
of mShrI: applyFormat("", "")
|
||||
of mShlI:
|
||||
if n[1].typ.size <= 4:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.size == 8:
|
||||
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asIntN(64, $1 << BigInt($2))")
|
||||
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asUintN(64, $1 << BigInt($2))")
|
||||
else:
|
||||
applyFormat("($1 * Math.pow(2, $2))")
|
||||
else:
|
||||
applyFormat("($1 << $2)", "($1 << $2)")
|
||||
else:
|
||||
applyFormat("($1 * Math.pow(2, $2))", "($1 * Math.pow(2, $2))")
|
||||
of mAshrI:
|
||||
if n[1].typ.size <= 4:
|
||||
applyFormat("($1 >> $2)", "($1 >> $2)")
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.size == 8:
|
||||
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asIntN(64, $1 >> BigInt($2))")
|
||||
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
applyFormat("BigInt.asUintN(64, $1 >> BigInt($2))")
|
||||
else:
|
||||
applyFormat("Math.floor($1 / Math.pow(2, $2))")
|
||||
else:
|
||||
applyFormat("Math.floor($1 / Math.pow(2, $2))", "Math.floor($1 / Math.pow(2, $2))")
|
||||
applyFormat("($1 >> $2)", "($1 >> $2)")
|
||||
of mBitandI: applyFormat("($1 & $2)", "($1 & $2)")
|
||||
of mBitorI: applyFormat("($1 | $2)", "($1 | $2)")
|
||||
of mBitxorI: applyFormat("($1 ^ $2)", "($1 ^ $2)")
|
||||
@@ -697,7 +751,9 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
of mMulU: binaryUintExpr(p, n, r, "*")
|
||||
of mDivU:
|
||||
binaryUintExpr(p, n, r, "/")
|
||||
if n[1].typ.skipTypes(abstractRange).size == 8:
|
||||
if optJsBigInt64 notin p.config.globalOptions and
|
||||
n[1].typ.skipTypes(abstractRange).size == 8:
|
||||
# bigint / already truncates
|
||||
r.res = "Math.trunc($1)" % [r.res]
|
||||
of mDivI:
|
||||
arithAux(p, n, r, op)
|
||||
@@ -707,7 +763,13 @@ proc arith(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
|
||||
var x, y: TCompRes
|
||||
gen(p, n[1], x)
|
||||
gen(p, n[2], y)
|
||||
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
if typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "BigInt.asIntN(64, BigInt.asUintN(64, $1) >> BigInt($2))" % [x.rdLoc, y.rdLoc]
|
||||
elif typ.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "($1 >> BigInt($2))" % [x.rdLoc, y.rdLoc]
|
||||
else:
|
||||
r.res = "($1 >>> $2)" % [x.rdLoc, y.rdLoc]
|
||||
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mCStrToStr, mStrToStr, mEnumToStr:
|
||||
arithAux(p, n, r, op)
|
||||
of mEqRef:
|
||||
@@ -1764,15 +1826,25 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
|
||||
createRecordVarAux(p, t.n, excludedFieldIDs, output)
|
||||
t = t[0]
|
||||
|
||||
proc arrayTypeForElemType(typ: PType): string =
|
||||
proc arrayTypeForElemType(conf: ConfigRef; typ: PType): string =
|
||||
let typ = typ.skipTypes(abstractRange)
|
||||
case typ.kind
|
||||
of tyInt, tyInt32: "Int32Array"
|
||||
of tyInt16: "Int16Array"
|
||||
of tyInt8: "Int8Array"
|
||||
of tyInt64:
|
||||
if optJsBigInt64 in conf.globalOptions:
|
||||
"BigInt64Array"
|
||||
else:
|
||||
""
|
||||
of tyUInt, tyUInt32: "Uint32Array"
|
||||
of tyUInt16: "Uint16Array"
|
||||
of tyUInt8, tyChar, tyBool: "Uint8Array"
|
||||
of tyUInt64:
|
||||
if optJsBigInt64 in conf.globalOptions:
|
||||
"BigUint64Array"
|
||||
else:
|
||||
""
|
||||
of tyFloat32: "Float32Array"
|
||||
of tyFloat64, tyFloat: "Float64Array"
|
||||
of tyEnum:
|
||||
@@ -1786,11 +1858,18 @@ proc arrayTypeForElemType(typ: PType): string =
|
||||
proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
var t = skipTypes(typ, abstractInst)
|
||||
case t.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar:
|
||||
of tyInt8..tyInt32, tyUInt8..tyUInt32, tyEnum, tyChar:
|
||||
result = putToSeq("0", indirect)
|
||||
of tyInt, tyUInt:
|
||||
if $t.sym.loc.r == "bigint":
|
||||
result = putToSeq("0n", indirect)
|
||||
else:
|
||||
result = putToSeq("0", indirect)
|
||||
of tyInt64, tyUInt64:
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
result = putToSeq("0n", indirect)
|
||||
else:
|
||||
result = putToSeq("0", indirect)
|
||||
of tyFloat..tyFloat128:
|
||||
result = putToSeq("0.0", indirect)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
|
||||
@@ -1804,7 +1883,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
of tyArray:
|
||||
let length = toInt(lengthOrd(p.config, t))
|
||||
let e = elemType(t)
|
||||
let jsTyp = arrayTypeForElemType(e)
|
||||
let jsTyp = arrayTypeForElemType(p.config, e)
|
||||
if jsTyp.len > 0:
|
||||
result = "new $1($2)" % [rope(jsTyp), rope(length)]
|
||||
elif length > 32:
|
||||
@@ -1979,7 +2058,11 @@ proc genNewSeq(p: PProc, n: PNode) =
|
||||
|
||||
proc genOrd(p: PProc, n: PNode, r: var TCompRes) =
|
||||
case skipTypes(n[1].typ, abstractVar + abstractRange).kind
|
||||
of tyEnum, tyInt..tyUInt64, tyChar: gen(p, n[1], r)
|
||||
of tyEnum, tyInt..tyInt32, tyUInt..tyUInt32, tyChar: gen(p, n[1], r)
|
||||
of tyInt64, tyUInt64:
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
unaryExpr(p, n, r, "", "Number($1)")
|
||||
else: gen(p, n[1], r)
|
||||
of tyBool: unaryExpr(p, n, r, "", "($1 ? 1 : 0)")
|
||||
else: internalError(p.config, n.info, "genOrd")
|
||||
|
||||
@@ -2202,14 +2285,34 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.res = "($1).length - 1" % [x.rdLoc]
|
||||
r.kind = resExpr
|
||||
of mInc:
|
||||
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
case typ.kind
|
||||
of tyUInt..tyUInt32:
|
||||
binaryUintExpr(p, n, r, "+", true)
|
||||
of tyUInt64:
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 + BigInt($2))", true)
|
||||
else: binaryUintExpr(p, n, r, "+", true)
|
||||
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if optOverflowCheck notin p.options:
|
||||
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 + BigInt($2))", true)
|
||||
else: binaryExpr(p, n, r, "addInt64", "$1 = addInt64($3, BigInt($2))", true)
|
||||
else:
|
||||
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 += $2")
|
||||
else: binaryExpr(p, n, r, "addInt", "$1 = addInt($3, $2)", true)
|
||||
of ast.mDec:
|
||||
if n[1].typ.skipTypes(abstractRange).kind in {tyUInt..tyUInt64}:
|
||||
let typ = n[1].typ.skipTypes(abstractVarRange)
|
||||
case typ.kind
|
||||
of tyUInt..tyUInt32:
|
||||
binaryUintExpr(p, n, r, "-", true)
|
||||
of tyUInt64:
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
binaryExpr(p, n, r, "", "$1 = BigInt.asUintN(64, $3 - BigInt($2))", true)
|
||||
else: binaryUintExpr(p, n, r, "+", true)
|
||||
elif typ.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if optOverflowCheck notin p.options:
|
||||
binaryExpr(p, n, r, "", "$1 = BigInt.asIntN(64, $3 - BigInt($2))", true)
|
||||
else: binaryExpr(p, n, r, "subInt64", "$1 = subInt64($3, BigInt($2))", true)
|
||||
else:
|
||||
if optOverflowCheck notin p.options: binaryExpr(p, n, r, "", "$1 -= $2")
|
||||
else: binaryExpr(p, n, r, "subInt", "$1 = subInt($3, $2)", true)
|
||||
@@ -2303,7 +2406,7 @@ proc genArrayConstr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
## Nim sequence maps to JS array.
|
||||
var t = skipTypes(n.typ, abstractInst)
|
||||
let e = elemType(t)
|
||||
let jsTyp = arrayTypeForElemType(e)
|
||||
let jsTyp = arrayTypeForElemType(p.config, e)
|
||||
if skipTypes(n.typ, abstractVarRange).kind != tySequence and jsTyp.len > 0:
|
||||
# generate typed array
|
||||
# for example Nim generates `new Uint8Array([1, 2, 3])` for `[byte(1), 2, 3]`
|
||||
@@ -2384,7 +2487,27 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||
r.res = "(!!($1))" % [r.res]
|
||||
r.kind = resExpr
|
||||
elif toInt:
|
||||
r.res = "(($1) | 0)" % [r.res]
|
||||
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number($1)" % [r.res]
|
||||
else:
|
||||
r.res = "(($1) | 0)" % [r.res]
|
||||
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
|
||||
r.res = "BigInt($1)" % [r.res]
|
||||
elif src.kind in {tyFloat..tyFloat64}:
|
||||
r.res = "BigInt(Math.trunc($1))" % [r.res]
|
||||
elif src.kind == tyUInt64:
|
||||
r.res = "BigInt.asIntN(64, $1)" % [r.res]
|
||||
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if fromInt or fromUint:
|
||||
r.res = "BigInt($1)" % [r.res]
|
||||
elif src.kind in {tyFloat..tyFloat64}:
|
||||
r.res = "BigInt(Math.trunc($1))" % [r.res]
|
||||
elif src.kind == tyInt64:
|
||||
r.res = "BigInt.asUintN(64, $1)" % [r.res]
|
||||
elif toUint or dest.kind in tyFloat..tyFloat64:
|
||||
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number($1)" % [r.res]
|
||||
else:
|
||||
# TODO: What types must we handle here?
|
||||
discard
|
||||
@@ -2395,7 +2518,11 @@ proc upConv(p: PProc, n: PNode, r: var TCompRes) =
|
||||
proc genRangeChck(p: PProc, n: PNode, r: var TCompRes, magic: string) =
|
||||
var a, b: TCompRes
|
||||
gen(p, n[0], r)
|
||||
if optRangeCheck notin p.options or (skipTypes(n.typ, abstractVar).kind in {tyUInt..tyUInt64} and
|
||||
let src = skipTypes(n[0].typ, abstractVarRange)
|
||||
let dest = skipTypes(n.typ, abstractVarRange)
|
||||
if src.kind in {tyInt64, tyUInt64} and dest.kind notin {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number($1)" % [r.res]
|
||||
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
|
||||
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||
discard "XXX maybe emit masking instructions here"
|
||||
else:
|
||||
@@ -2587,6 +2714,8 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if toUint and (fromInt or fromUint):
|
||||
let trimmer = unsignedTrimmer(dest.size)
|
||||
r.res = "($1 $2)" % [r.res, trimmer]
|
||||
elif toUint and src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number(BigInt.asUintN($1, $2))" % [$(dest.size * 8), r.res]
|
||||
elif toInt:
|
||||
if fromInt:
|
||||
return
|
||||
@@ -2602,6 +2731,25 @@ proc genCast(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of 4: "0xfffffffe"
|
||||
else: ""
|
||||
r.res = "($1 - ($2 $3))" % [rope minuend, r.res, trimmer]
|
||||
elif src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number(BigInt.asIntN($1, $2))" % [$(dest.size * 8), r.res]
|
||||
elif dest.kind == tyInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if fromInt or fromUint or src.kind in {tyBool, tyChar, tyEnum}:
|
||||
r.res = "BigInt($1)" % [r.res]
|
||||
elif src.kind in {tyFloat..tyFloat64}:
|
||||
r.res = "BigInt(Math.trunc($1))" % [r.res]
|
||||
elif src.kind == tyUInt64:
|
||||
r.res = "BigInt.asIntN(64, $1)" % [r.res]
|
||||
elif dest.kind == tyUInt64 and optJsBigInt64 in p.config.globalOptions:
|
||||
if fromInt or fromUint:
|
||||
r.res = "BigInt($1)" % [r.res]
|
||||
elif src.kind in {tyFloat..tyFloat64}:
|
||||
r.res = "BigInt(Math.trunc($1))" % [r.res]
|
||||
elif src.kind == tyInt64:
|
||||
r.res = "BigInt.asUintN(64, $1)" % [r.res]
|
||||
elif dest.kind in tyFloat..tyFloat64:
|
||||
if src.kind in {tyInt64, tyUInt64} and optJsBigInt64 in p.config.globalOptions:
|
||||
r.res = "Number($1)" % [r.res]
|
||||
elif (src.kind == tyPtr and mapType(p, src) == etyObject) and dest.kind == tyPointer:
|
||||
r.address = r.res
|
||||
r.res = "null"
|
||||
@@ -2620,8 +2768,17 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkSym:
|
||||
genSym(p, n, r)
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if n.typ.kind == tyBool:
|
||||
case n.typ.skipTypes(abstractVarRange).kind
|
||||
of tyBool:
|
||||
r.res = if n.intVal == 0: rope"false" else: rope"true"
|
||||
of tyUInt64:
|
||||
r.res = rope($cast[BiggestUInt](n.intVal))
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
r.res.add('n')
|
||||
of tyInt64:
|
||||
r.res = rope(n.intVal)
|
||||
if optJsBigInt64 in p.config.globalOptions:
|
||||
r.res.add('n')
|
||||
else:
|
||||
r.res = rope(n.intVal)
|
||||
r.kind = resExpr
|
||||
@@ -2855,7 +3012,7 @@ proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
|
||||
var p = newInitProc(globals, m)
|
||||
attachProc(p, prc)
|
||||
|
||||
var disp = generateMethodDispatchers(graph)
|
||||
var disp = generateMethodDispatchers(graph, m.idgen)
|
||||
for i in 0..<disp.len:
|
||||
let prc = disp[i].sym
|
||||
if not globals.generatedSyms.containsOrIncl(prc.id):
|
||||
|
||||
@@ -88,6 +88,8 @@ type
|
||||
warnUnnamedBreak = "UnnamedBreak",
|
||||
warnStmtListLambda = "StmtListLambda",
|
||||
warnBareExcept = "BareExcept",
|
||||
warnCopyHookForRefc = "CopyHookForRefc",
|
||||
warnImplicitDefaultValue = "ImplicitDefaultValue",
|
||||
warnUser = "User",
|
||||
# hints
|
||||
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
||||
@@ -189,6 +191,8 @@ const
|
||||
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
|
||||
warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
|
||||
warnBareExcept: "$1",
|
||||
warnCopyHookForRefc: "Overriding `=copy` hook is not reliable for refc",
|
||||
warnImplicitDefaultValue: "$1",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
# keep in sync with `testament.isSuccess`
|
||||
|
||||
@@ -396,11 +396,12 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) =
|
||||
if fn.kind notin OverloadableSyms:
|
||||
internalError(c.config, fn.info, "addOverloadableSymAt")
|
||||
return
|
||||
let check = strTableGet(scope.symbols, fn.name)
|
||||
if check != nil and check.kind notin OverloadableSyms:
|
||||
wrongRedefinition(c, fn.info, fn.name.s, check.info)
|
||||
else:
|
||||
scope.addSym(fn)
|
||||
if fn.name.s != "_":
|
||||
let check = strTableGet(scope.symbols, fn.name)
|
||||
if check != nil and check.kind notin OverloadableSyms:
|
||||
wrongRedefinition(c, fn.info, fn.name.s, check.info)
|
||||
else:
|
||||
scope.addSym(fn)
|
||||
|
||||
proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
|
||||
## adds an overloadable symbol on the scope and the interface if appropriate
|
||||
@@ -546,12 +547,16 @@ proc errorUseQualifier*(c: PContext; info:TLineInfo; choices: PNode) =
|
||||
errorUseQualifier(c, info, candidates, prefix)
|
||||
|
||||
proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extra = "") =
|
||||
var err = "undeclared identifier: '" & name & "'" & extra
|
||||
if c.recursiveDep.len > 0:
|
||||
err.add "\nThis might be caused by a recursive module dependency:\n"
|
||||
err.add c.recursiveDep
|
||||
# prevent excessive errors for 'nim check'
|
||||
c.recursiveDep = ""
|
||||
var err: string
|
||||
if name == "_":
|
||||
err = "the special identifier '_' is ignored in declarations and cannot be used"
|
||||
else:
|
||||
err = "undeclared identifier: '" & name & "'" & extra
|
||||
if c.recursiveDep.len > 0:
|
||||
err.add "\nThis might be caused by a recursive module dependency:\n"
|
||||
err.add c.recursiveDep
|
||||
# prevent excessive errors for 'nim check'
|
||||
c.recursiveDep = ""
|
||||
localError(c.config, info, errGenerated, err)
|
||||
|
||||
proc errorUndeclaredIdentifierHint*(c: PContext; n: PNode, ident: PIdent): PSym =
|
||||
|
||||
@@ -46,3 +46,7 @@ define:useStdoutAsStdmsg
|
||||
@if nimHasWarnBareExcept:
|
||||
warningAserror[BareExcept]:on
|
||||
@end
|
||||
|
||||
@if nimHasWarnCopyHookForRefc:
|
||||
warningAserror[CopyHookForRefc]:on
|
||||
@end
|
||||
|
||||
@@ -102,13 +102,11 @@ type # please make sure we have under 32 options
|
||||
optBenchmarkVM # Enables cpuTime() in the VM
|
||||
optProduceAsm # produce assembler code
|
||||
optPanics # turn panics (sysFatal) into a process termination
|
||||
optNimV1Emulation # emulate Nim v1.0
|
||||
optNimV12Emulation # emulate Nim v1.2
|
||||
optNimV16Emulation # emulate Nim v1.6
|
||||
optSourcemap
|
||||
optProfileVM # enable VM profiler
|
||||
optEnableDeepCopy # ORC specific: enable 'deepcopy' for all types.
|
||||
optShowNonExportedFields # for documentation: show fields that are not exported
|
||||
optJsBigInt64 # use bigints for 64-bit integers in JS
|
||||
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
|
||||
@@ -479,7 +477,8 @@ const
|
||||
optBoundsCheck, optOverflowCheck, optAssert, optWarns, optRefCheck,
|
||||
optHints, optStackTrace, optLineTrace, # consider adding `optStackTraceMsgs`
|
||||
optTrMacros, optStyleCheck, optCursorInference}
|
||||
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace}
|
||||
DefaultGlobalOptions* = {optThreadAnalysis, optExcessiveStackTrace,
|
||||
optJsBigInt64}
|
||||
|
||||
proc getSrcTimestamp(): DateTime =
|
||||
try:
|
||||
|
||||
@@ -1197,14 +1197,18 @@ proc parseProcExpr(p: var Parser; isExpr: bool; kind: TNodeKind): PNode =
|
||||
let pragmas = optPragmas(p)
|
||||
if p.tok.tokType == tkEquals and isExpr:
|
||||
getTok(p)
|
||||
skipComment(p, result)
|
||||
result = newProcNode(kind, info, body = parseStmt(p),
|
||||
result = newProcNode(kind, info, body = p.emptyNode,
|
||||
params = params, name = p.emptyNode, pattern = p.emptyNode,
|
||||
genericParams = p.emptyNode, pragmas = pragmas, exceptions = p.emptyNode)
|
||||
skipComment(p, result)
|
||||
result[bodyPos] = parseStmt(p)
|
||||
else:
|
||||
result = newNodeI(if kind == nkIteratorDef: nkIteratorTy else: nkProcTy, info)
|
||||
if hasSignature:
|
||||
result.add(params)
|
||||
if hasSignature or pragmas.kind != nkEmpty:
|
||||
if hasSignature:
|
||||
result.add(params)
|
||||
else: # pragmas but no param list, implies typeclass with pragmas
|
||||
result.add(p.emptyNode)
|
||||
if kind == nkFuncDef:
|
||||
parMessage(p, "func keyword is not allowed in type descriptions, use proc with {.noSideEffect.} pragma instead")
|
||||
result.add(pragmas)
|
||||
@@ -2277,13 +2281,19 @@ proc parseTypeDef(p: var Parser): PNode =
|
||||
setEndInfo()
|
||||
|
||||
proc parseVarTuple(p: var Parser): PNode =
|
||||
#| varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||
#| varTupleLhs = '(' optInd (identWithPragma / varTupleLhs) ^+ comma optPar ')'
|
||||
#| varTuple = varTupleLhs '=' optInd expr
|
||||
result = newNodeP(nkVarTuple, p)
|
||||
getTok(p) # skip '('
|
||||
optInd(p, result)
|
||||
# progress guaranteed
|
||||
while p.tok.tokType in {tkSymbol, tkAccent}:
|
||||
var a = identWithPragma(p, allowDot=true)
|
||||
while p.tok.tokType in {tkSymbol, tkAccent, tkParLe}:
|
||||
var a: PNode
|
||||
if p.tok.tokType == tkParLe:
|
||||
a = parseVarTuple(p)
|
||||
a.add(p.emptyNode)
|
||||
else:
|
||||
a = identWithPragma(p, allowDot=true)
|
||||
result.add(a)
|
||||
if p.tok.tokType != tkComma: break
|
||||
getTok(p)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import sem, cgen, modulegraphs, ast, llstream, parser, msgs,
|
||||
lineinfos, reorder, options, semdata, cgendata, modules, pathutils,
|
||||
packages, syntaxes, depends, vm, pragmas, idents, lookups
|
||||
packages, syntaxes, depends, vm, pragmas, idents, lookups, wordrecg,
|
||||
liftdestructors
|
||||
|
||||
import pipelineutils
|
||||
|
||||
@@ -176,7 +177,16 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator
|
||||
case graph.pipelinePass
|
||||
of CgenPass:
|
||||
if bModule != nil:
|
||||
finalCodegenActions(graph, BModule(bModule), finalNode)
|
||||
let disps = finalCodegenActions(graph, BModule(bModule), finalNode)
|
||||
if disps != nil:
|
||||
let ctx = preparePContext(graph, module, idgen)
|
||||
for disp in disps:
|
||||
let retTyp = disp.sym.typ[0]
|
||||
if retTyp != nil:
|
||||
# todo properly semcheck the code of dispatcher?
|
||||
createTypeBoundOps(graph, ctx, retTyp, disp.info, idgen)
|
||||
genProcAux(BModule(bModule), disp.sym)
|
||||
discard closePContext(graph, ctx, nil)
|
||||
of JSgenPass:
|
||||
when not defined(leanCompiler):
|
||||
discard finalJSCodeGen(graph, bModule, finalNode)
|
||||
|
||||
@@ -132,7 +132,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||
# just in case, should be impossible though
|
||||
if syms.len == 0:
|
||||
break
|
||||
|
||||
|
||||
if nextSymIndex > high(syms):
|
||||
# we have reached the end
|
||||
break
|
||||
@@ -293,7 +293,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
const
|
||||
errTypeMismatch = "type mismatch: got <"
|
||||
errButExpected = "but expected one of:"
|
||||
errExpectedPosition = "Expected one of (first mismatch at position [#]):"
|
||||
errExpectedPosition = "Expected one of (first mismatch at [position]):"
|
||||
errUndeclaredField = "undeclared field: '$1'"
|
||||
errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
|
||||
errBadRoutine = "attempting to call routine: '$1'$2"
|
||||
|
||||
@@ -469,6 +469,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
res = t.kind == tyProc and
|
||||
t.callConv == ccClosure
|
||||
of "iterator":
|
||||
# holdover from when `is iterator` didn't work
|
||||
let t = skipTypes(t1, abstractRange)
|
||||
res = t.kind == tyProc and
|
||||
t.callConv == ccClosure and
|
||||
@@ -1352,6 +1353,12 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
of skModule:
|
||||
# make sure type is None and not nil for discard checking
|
||||
if efWantStmt in flags: s.typ = newTypeS(tyNone, c)
|
||||
markUsed(c, n.info, s)
|
||||
onUse(n.info, s)
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
let info = getCallLineInfo(n)
|
||||
#if efInCall notin flags:
|
||||
@@ -1824,7 +1831,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
result.add(n[1])
|
||||
return semExprNoType(c, result)
|
||||
of nkPar, nkTupleConstr:
|
||||
if a.len >= 2:
|
||||
if a.len >= 2 or a.kind == nkTupleConstr:
|
||||
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so
|
||||
# that overloading of the assignment operator still works. Usually we
|
||||
# prefer to do these rewritings in transf.nim:
|
||||
@@ -3078,7 +3085,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
result = semConv(c, n, expectedType)
|
||||
elif ambig and n.len == 1:
|
||||
errorUseQualifier(c, n.info, s)
|
||||
elif n.len == 1 or (n.kind == nkCall and useObjConstr(c, n, flags, expectedType)):
|
||||
elif n.len == 1:
|
||||
result = semObjConstr(c, n, flags, expectedType)
|
||||
elif s.magic == mNone: result = semDirectOp(c, n, flags, expectedType)
|
||||
else: result = semMagic(c, n, s, flags, expectedType)
|
||||
|
||||
@@ -506,12 +506,12 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result[i] = semGenericStmt(c, n[i], flags, ctx)
|
||||
if result[0].kind == nkSym:
|
||||
let fmoduleId = getModule(result[0].sym).id
|
||||
var isVisible = false
|
||||
var isVisable = false
|
||||
for module in c.friendModules:
|
||||
if module.id == fmoduleId:
|
||||
isVisible = true
|
||||
isVisable = true
|
||||
break
|
||||
if isVisible:
|
||||
if isVisable:
|
||||
for i in 1..<result.len:
|
||||
if result[i].kind == nkExprColonExpr:
|
||||
result[i][1].flags.incl nfSkipFieldChecking
|
||||
|
||||
@@ -86,6 +86,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
|
||||
var initValue = semExprFlagDispatched(c, assignment[1], flags, field.typ)
|
||||
if initValue != nil:
|
||||
initValue = fitNodeConsiderViewType(c, field.typ, initValue, assignment.info)
|
||||
initValue.flags.incl nfSkipFieldChecking
|
||||
assignment[0] = newSymNode(field)
|
||||
assignment[1] = initValue
|
||||
assignment.flags.incl nfSem
|
||||
@@ -412,113 +413,15 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
|
||||
else:
|
||||
assert false, "Must not enter here."
|
||||
|
||||
type
|
||||
ObjConstrError = enum
|
||||
none
|
||||
discriminatorError = "The discriminator can only be initialized with unnamed fields known at the compile time"
|
||||
mixingError = "When mixing named fields and unnamed fields, every field needs to be initialized in order"
|
||||
lackingError = "The object construction is given more fields than required"
|
||||
|
||||
proc filterObjConstr(c: PContext; field: PNode, n: PNode, iterField: var int, flags: TExprFlags, write: bool): ObjConstrError =
|
||||
result = none
|
||||
if iterField >= n.len:
|
||||
return mixingError
|
||||
case field.kind
|
||||
of nkRecCase:
|
||||
# handle defaults if the ast of the field is known
|
||||
var discriminatorVal =
|
||||
case n[iterField].kind
|
||||
of nkExprColonExpr:
|
||||
semExprFlagDispatched(c, n[iterField][1], flags + {efPreferStatic})
|
||||
else:
|
||||
semExprFlagDispatched(c, n[iterField], flags + {efPreferStatic})
|
||||
|
||||
let ret = filterObjConstr(c, field[0], n, iterField, flags, write)
|
||||
if ret != none:
|
||||
return ret
|
||||
|
||||
if discriminatorVal == nil or discriminatorVal.kind != nkIntLit:
|
||||
return discriminatorError
|
||||
|
||||
let matchedBranch = field.pickCaseBranch discriminatorVal
|
||||
if matchedBranch != nil:
|
||||
result = filterObjConstr(c, matchedBranch.lastSon, n, iterField, flags, write)
|
||||
else:
|
||||
result = none
|
||||
|
||||
of nkSym:
|
||||
if n[iterField].kind == nkExprColonExpr and field.sym.name.id == considerQuotedIdent(c, n[iterField][0]).id:
|
||||
inc iterField
|
||||
elif not fieldVisible(c, field.sym):
|
||||
discard
|
||||
elif n[iterField].kind != nkExprColonExpr:
|
||||
if write:
|
||||
n[iterField] = newTree(nkExprColonExpr, field, n[iterField])
|
||||
inc iterField
|
||||
else:
|
||||
result = mixingError
|
||||
of nkRecList:
|
||||
for f in field:
|
||||
let ret = filterObjConstr(c, f, n, iterField, flags, write)
|
||||
if ret != none:
|
||||
result = ret
|
||||
break
|
||||
else:
|
||||
assert false
|
||||
|
||||
proc expandObjConstr(c: PContext, n: PNode, t: PType, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
var hasValue = false
|
||||
for i in 1..<n.len:
|
||||
if n[i].kind != nkExprColonExpr:
|
||||
hasValue = true
|
||||
break
|
||||
if hasValue:
|
||||
var iterField = 1
|
||||
let ret = filterObjConstr(c, t.n, result, iterField, flags, write = true)
|
||||
if ret != none:
|
||||
localError(c.config, result.info, $ret)
|
||||
else:
|
||||
if iterField > result.len:
|
||||
localError(c.config, result.info, $mixingError)
|
||||
elif iterField < result.len:
|
||||
localError(c.config, result.info, $lackingError)
|
||||
|
||||
proc useObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): bool =
|
||||
var n = copyTree(n)
|
||||
var t = semTypeNode(c, n[0], nil)
|
||||
if t == nil:
|
||||
return false
|
||||
|
||||
if t.skipTypes({tyGenericInst,
|
||||
tyAlias, tySink, tyOwned, tyRef}).kind != tyObject and
|
||||
expectedType != nil and expectedType.skipTypes({tyGenericInst,
|
||||
tyAlias, tySink, tyOwned, tyRef}).kind == tyObject:
|
||||
t = expectedType
|
||||
|
||||
t = skipTypes(t, {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
if t.kind == tyRef:
|
||||
t = skipTypes(t[0], {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
|
||||
if t.kind != tyObject:
|
||||
return false
|
||||
|
||||
for i in 1..<n.len:
|
||||
if n[i].kind == nkExprColonExpr:
|
||||
return true
|
||||
|
||||
var iterField = 1
|
||||
result = filterObjConstr(c, t.n, n, iterField, flags, write = false) == none
|
||||
if iterField != n.len:
|
||||
return false
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
var t = semTypeNode(c, n[0], nil)
|
||||
result = newNodeIT(nkObjConstr, n.info, t)
|
||||
for i in 0..<n.len:
|
||||
result.add n[i]
|
||||
|
||||
if t == nil:
|
||||
return localErrorNode(c, result, "object constructor needs an object type")
|
||||
|
||||
|
||||
if t.skipTypes({tyGenericInst,
|
||||
tyAlias, tySink, tyOwned, tyRef}).kind != tyObject and
|
||||
expectedType != nil and expectedType.skipTypes({tyGenericInst,
|
||||
@@ -541,10 +444,6 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
"'; the object's generic parameters cannot be inferred and must be explicitly given"
|
||||
)
|
||||
|
||||
let expanded = expandObjConstr(c, n, t, flags)
|
||||
for i in 0..<expanded.len:
|
||||
result.add expanded[i]
|
||||
|
||||
# Check if the object is fully initialized by recursively testing each
|
||||
# field (if this is a case object, initialized fields in two different
|
||||
# branches will be reported as an error):
|
||||
|
||||
@@ -396,7 +396,7 @@ proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) =
|
||||
if sameType(a.graph.excType(aa[i]), a.graph.excType(e)): return
|
||||
|
||||
if e.typ != nil:
|
||||
if optNimV1Emulation in a.config.globalOptions or not isDefectException(e.typ):
|
||||
if not isDefectException(e.typ):
|
||||
throws(a.exc, e, comesFrom)
|
||||
|
||||
proc addTag(a: PEffects, e, comesFrom: PNode) =
|
||||
|
||||
@@ -161,18 +161,19 @@ proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
|
||||
if result.typ.kind == tyNone:
|
||||
localError(c.config, result.info, "expression has no type: " &
|
||||
renderTree(result, {renderNoComments}))
|
||||
var n = result
|
||||
while n.kind in skipForDiscardable:
|
||||
if n.kind == nkTryStmt: n = n[0]
|
||||
else: n = n.lastSon
|
||||
var s = "expression '" & $n & "' is of type '" &
|
||||
result.typ.typeToString & "' and has to be used (or discarded)"
|
||||
if result.info.line != n.info.line or
|
||||
result.info.fileIndex != n.info.fileIndex:
|
||||
s.add "; start of expression here: " & c.config$result.info
|
||||
if result.typ.kind == tyProc:
|
||||
s.add "; for a function call use ()"
|
||||
localError(c.config, n.info, s)
|
||||
else:
|
||||
var n = result
|
||||
while n.kind in skipForDiscardable:
|
||||
if n.kind == nkTryStmt: n = n[0]
|
||||
else: n = n.lastSon
|
||||
var s = "expression '" & $n & "' is of type '" &
|
||||
result.typ.typeToString & "' and has to be used (or discarded)"
|
||||
if result.info.line != n.info.line or
|
||||
result.info.fileIndex != n.info.fileIndex:
|
||||
s.add "; start of expression here: " & c.config$result.info
|
||||
if result.typ.kind == tyProc:
|
||||
s.add "; for a function call use ()"
|
||||
localError(c.config, n.info, s)
|
||||
|
||||
proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n
|
||||
@@ -583,6 +584,57 @@ proc globalVarInitCheck(c: PContext, n: PNode) =
|
||||
if n.isLocalVarSym or n.kind in nkCallKinds and usesLocalVar(n):
|
||||
localError(c.config, n.info, errCannotAssignToGlobal)
|
||||
|
||||
proc makeVarTupleSection(c: PContext, n, a, def: PNode, typ: PType, symkind: TSymKind, origResult: var PNode): PNode =
|
||||
## expand tuple unpacking assignments into new var/let/const section
|
||||
if typ.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif a.len-2 != typ.len:
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
var
|
||||
tmpTuple: PSym
|
||||
lastDef: PNode
|
||||
let defkind = if symkind == skConst: nkConstDef else: nkIdentDefs
|
||||
# temporary not needed if not const and RHS is tuple literal
|
||||
# const breaks with seqs without temporary
|
||||
let useTemp = def.kind notin {nkPar, nkTupleConstr} or symkind == skConst
|
||||
if useTemp:
|
||||
# use same symkind for compatibility with original section
|
||||
tmpTuple = newSym(symkind, getIdent(c.cache, "tmpTuple"), nextSymId c.idgen, getCurrOwner(c), n.info)
|
||||
tmpTuple.typ = typ
|
||||
tmpTuple.flags.incl(sfGenSym)
|
||||
lastDef = newNodeI(defkind, a.info)
|
||||
newSons(lastDef, 3)
|
||||
lastDef[0] = newSymNode(tmpTuple)
|
||||
# NOTE: at the moment this is always ast.emptyNode, see parser.nim
|
||||
lastDef[1] = a[^2]
|
||||
lastDef[2] = def
|
||||
tmpTuple.ast = lastDef
|
||||
addToVarSection(c, origResult, n, lastDef)
|
||||
result = newNodeI(n.kind, a.info)
|
||||
for j in 0..<a.len-2:
|
||||
let name = a[j]
|
||||
if useTemp and name.kind == nkIdent and name.ident.s == "_":
|
||||
# skip _ assignments if we are using a temp as they are already evaluated
|
||||
continue
|
||||
if name.kind == nkVarTuple:
|
||||
# nested tuple
|
||||
lastDef = newNodeI(nkVarTuple, name.info)
|
||||
newSons(lastDef, name.len)
|
||||
for k in 0..<name.len-2:
|
||||
lastDef[k] = name[k]
|
||||
else:
|
||||
lastDef = newNodeI(defkind, name.info)
|
||||
newSons(lastDef, 3)
|
||||
lastDef[0] = name
|
||||
lastDef[^2] = c.graph.emptyNode
|
||||
if useTemp:
|
||||
lastDef[^1] = newTreeIT(nkBracketExpr, name.info, typ[j], newSymNode(tmpTuple), newIntNode(nkIntLit, j))
|
||||
else:
|
||||
var val = def[j]
|
||||
if val.kind == nkExprColonExpr: val = val[1]
|
||||
lastDef[^1] = val
|
||||
result.add(lastDef)
|
||||
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
@@ -649,43 +701,37 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
|
||||
var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
|
||||
if a.kind == nkVarTuple:
|
||||
if tup.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif a.len-2 != tup.len:
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkVarTuple, a.info)
|
||||
newSons(b, a.len)
|
||||
# keep type desc for doc generator
|
||||
# NOTE: at the moment this is always ast.emptyNode, see parser.nim
|
||||
b[^2] = a[^2]
|
||||
b[^1] = def
|
||||
addToVarSection(c, result, n, b)
|
||||
elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
|
||||
a.kind == nkIdentDefs and a.len > 3:
|
||||
message(c.config, a.info, warnEachIdentIsTuple)
|
||||
# generate new section from tuple unpacking and embed it into this one
|
||||
let assignments = makeVarTupleSection(c, n, a, def, tup, symkind, result)
|
||||
let resSection = semVarOrLet(c, assignments, symkind)
|
||||
for resDef in resSection:
|
||||
addToVarSection(c, result, n, resDef)
|
||||
else:
|
||||
if tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and
|
||||
a.len > 3:
|
||||
# var a, b = (1, 2)
|
||||
message(c.config, a.info, warnEachIdentIsTuple)
|
||||
|
||||
for j in 0..<a.len-2:
|
||||
if a[j].kind == nkDotExpr:
|
||||
fillPartialObject(c, a[j],
|
||||
if a.kind != nkVarTuple: typ else: tup[j])
|
||||
addToVarSection(c, result, n, a)
|
||||
continue
|
||||
var v = semIdentDef(c, a[j], symkind, false)
|
||||
styleCheckDef(c, v)
|
||||
onDef(a[j].info, v)
|
||||
if sfGenSym notin v.flags:
|
||||
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
|
||||
else:
|
||||
if v.owner == nil: v.owner = c.p.owner
|
||||
when oKeepVariableNames:
|
||||
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
||||
for j in 0..<a.len-2:
|
||||
if a[j].kind == nkDotExpr:
|
||||
fillPartialObject(c, a[j], typ)
|
||||
addToVarSection(c, result, n, a)
|
||||
continue
|
||||
var v = semIdentDef(c, a[j], symkind, false)
|
||||
styleCheckDef(c, v)
|
||||
onDef(a[j].info, v)
|
||||
if sfGenSym notin v.flags:
|
||||
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
|
||||
else:
|
||||
let shadowed = findShadowedVar(c, v)
|
||||
if shadowed != nil:
|
||||
shadowed.flags.incl(sfShadowed)
|
||||
if shadowed.kind == skResult and sfGenSym notin v.flags:
|
||||
message(c.config, a.info, warnResultShadowed)
|
||||
if a.kind != nkVarTuple:
|
||||
if v.owner == nil: v.owner = c.p.owner
|
||||
when oKeepVariableNames:
|
||||
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
||||
else:
|
||||
let shadowed = findShadowedVar(c, v)
|
||||
if shadowed != nil:
|
||||
shadowed.flags.incl(sfShadowed)
|
||||
if shadowed.kind == skResult and sfGenSym notin v.flags:
|
||||
message(c.config, a.info, warnResultShadowed)
|
||||
if def.kind != nkEmpty:
|
||||
if sfThread in v.flags: localError(c.config, def.info, errThreadvarCannotInit)
|
||||
setVarType(c, v, typ)
|
||||
@@ -708,35 +754,26 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
b.add copyTree(def)
|
||||
addToVarSection(c, result, n, b)
|
||||
v.ast = b
|
||||
else:
|
||||
if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
|
||||
# bug #7663, for 'nim check' this can be a non-tuple:
|
||||
if tup.kind == tyTuple: setVarType(c, v, tup[j])
|
||||
else: v.typ = tup
|
||||
b[j] = newSymNode(v)
|
||||
if def.kind == nkEmpty:
|
||||
let actualType = v.typ.skipTypes({tyGenericInst, tyAlias,
|
||||
tyUserTypeClassInst})
|
||||
if actualType.kind in {tyObject, tyDistinct} and
|
||||
actualType.requiresInit:
|
||||
defaultConstructionError(c, v.typ, v.info)
|
||||
else:
|
||||
checkNilable(c, v)
|
||||
# allow let to not be initialised if imported from C:
|
||||
if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
|
||||
localError(c.config, a.info, errLetNeedsInit)
|
||||
if sfCompileTime in v.flags:
|
||||
if a.kind != nkVarTuple:
|
||||
if def.kind == nkEmpty:
|
||||
let actualType = v.typ.skipTypes({tyGenericInst, tyAlias,
|
||||
tyUserTypeClassInst})
|
||||
if actualType.kind in {tyObject, tyDistinct} and
|
||||
actualType.requiresInit:
|
||||
defaultConstructionError(c, v.typ, v.info)
|
||||
else:
|
||||
checkNilable(c, v)
|
||||
# allow let to not be initialised if imported from C:
|
||||
if v.kind == skLet and sfImportc notin v.flags and (strictDefs notin c.features or not isLocalSym(v)):
|
||||
localError(c.config, a.info, errLetNeedsInit)
|
||||
if sfCompileTime in v.flags:
|
||||
var x = newNodeI(result.kind, v.info)
|
||||
x.add result[i]
|
||||
vm.setupCompileTimeVar(c.module, c.idgen, c.graph, x)
|
||||
else:
|
||||
localError(c.config, a.info, "cannot destructure to compile time variable")
|
||||
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
|
||||
message(c.config, v.info, hintGlobalVar)
|
||||
if {sfGlobal, sfPure} <= v.flags:
|
||||
globalVarInitCheck(c, def)
|
||||
suggestSym(c.graph, v.info, v, c.graph.usageSym)
|
||||
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
|
||||
message(c.config, v.info, hintGlobalVar)
|
||||
if {sfGlobal, sfPure} <= v.flags:
|
||||
globalVarInitCheck(c, def)
|
||||
suggestSym(c.graph, v.info, v, c.graph.usageSym)
|
||||
|
||||
proc semConst(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
@@ -789,23 +826,19 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
typeAllowedCheck(c, a.info, typ, skConst, typFlags)
|
||||
|
||||
if a.kind == nkVarTuple:
|
||||
if typ.kind != tyTuple:
|
||||
localError(c.config, a.info, errXExpected, "tuple")
|
||||
elif a.len-2 != typ.len:
|
||||
localError(c.config, a.info, errWrongNumberOfVariables)
|
||||
b = newNodeI(nkVarTuple, a.info)
|
||||
newSons(b, a.len)
|
||||
b[^2] = a[^2]
|
||||
b[^1] = def
|
||||
# generate new section from tuple unpacking and embed it into this one
|
||||
let assignments = makeVarTupleSection(c, n, a, def, typ, skConst, result)
|
||||
let resSection = semConst(c, assignments)
|
||||
for resDef in resSection:
|
||||
addToVarSection(c, result, n, resDef)
|
||||
else:
|
||||
for j in 0..<a.len-2:
|
||||
var v = semIdentDef(c, a[j], skConst)
|
||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
styleCheckDef(c, v)
|
||||
onDef(a[j].info, v)
|
||||
|
||||
for j in 0..<a.len-2:
|
||||
var v = semIdentDef(c, a[j], skConst)
|
||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
styleCheckDef(c, v)
|
||||
onDef(a[j].info, v)
|
||||
|
||||
if a.kind != nkVarTuple:
|
||||
setVarType(c, v, typ)
|
||||
when false:
|
||||
v.ast = def # no need to copy
|
||||
@@ -822,12 +855,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
b.add a[1]
|
||||
b.add copyTree(def)
|
||||
v.ast = b
|
||||
else:
|
||||
setVarType(c, v, typ[j])
|
||||
v.ast = if def[j].kind != nkExprColonExpr: def[j]
|
||||
else: def[j][1]
|
||||
b[j] = newSymNode(v)
|
||||
addToVarSection(c, result, n, b)
|
||||
addToVarSection(c, result, n, b)
|
||||
dec c.inStaticContext
|
||||
|
||||
include semfields
|
||||
@@ -1034,7 +1062,8 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
result = n
|
||||
n[^2] = semExprNoDeref(c, n[^2], {efWantIterator})
|
||||
var call = n[^2]
|
||||
if call.kind == nkStmtListExpr and isTrivalStmtExpr(call):
|
||||
|
||||
if call.kind == nkStmtListExpr and (isTrivalStmtExpr(call) or (call.lastSon.kind in nkCallKinds and call.lastSon[0].sym.kind == skIterator)):
|
||||
call = call.lastSon
|
||||
n[^2] = call
|
||||
let isCallExpr = call.kind in nkCallKinds
|
||||
@@ -1857,6 +1886,8 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
incl(s.flags, sfOverriden)
|
||||
if name == "=":
|
||||
message(c.config, n.info, warnDeprecated, "Overriding `=` hook is deprecated; Override `=copy` hook instead")
|
||||
elif c.config.selectedGC == gcRefc and name == "=copy":
|
||||
message(c.config, n.info, warnCopyHookForRefc)
|
||||
let t = s.typ
|
||||
if t.len == 3 and t[0] == nil and t[1].kind == tyVar:
|
||||
var obj = t[1][0]
|
||||
@@ -2275,7 +2306,6 @@ proc semMethod(c: PContext, n: PNode): PNode =
|
||||
|
||||
proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||
if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "converter")
|
||||
checkSonsLen(n, bodyPos + 1, c.config)
|
||||
result = semProcAux(c, n, skConverter, converterPragmas)
|
||||
# macros can transform converters to nothing:
|
||||
if namePos >= result.safeLen: return result
|
||||
@@ -2290,7 +2320,6 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
|
||||
addConverterDef(c, LazySym(sym: s))
|
||||
|
||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, bodyPos + 1, c.config)
|
||||
result = semProcAux(c, n, skMacro, macroPragmas)
|
||||
# macros can transform macros to nothing:
|
||||
if namePos >= result.safeLen: return result
|
||||
|
||||
@@ -130,8 +130,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
|
||||
e.typ = result
|
||||
e.position = int(counter)
|
||||
let symNode = newSymNode(e)
|
||||
if optNimV1Emulation notin c.config.globalOptions and identToReplace != nil and
|
||||
c.config.cmd notin cmdDocLike: # A hack to produce documentation for enum fields.
|
||||
if identToReplace != nil and c.config.cmd notin cmdDocLike:
|
||||
# A hack to produce documentation for enum fields.
|
||||
identToReplace[] = symNode
|
||||
if e.position == 0: hasNull = true
|
||||
if result.sym != nil and sfExported in result.sym.flags:
|
||||
@@ -803,8 +803,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||
else: illFormedAst(n, c.config)
|
||||
if c.inGenericContext > 0:
|
||||
# use a new check intset here for each branch:
|
||||
var newCheck: IntSet
|
||||
assign(newCheck, check)
|
||||
var newCheck: IntSet = check
|
||||
var newPos = pos
|
||||
var newf = newNodeI(nkRecList, n.info)
|
||||
semRecordNodeAux(c, it[idx], newCheck, newPos, newf, rectype, hasCaseFields)
|
||||
@@ -1311,6 +1310,16 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
|
||||
if hasDefault:
|
||||
def = a[^1]
|
||||
if a.len > 3:
|
||||
var msg = ""
|
||||
for j in 0 ..< a.len - 2:
|
||||
if msg.len != 0: msg.add(", ")
|
||||
msg.add($a[j])
|
||||
msg.add(" all have default value '")
|
||||
msg.add(def.renderTree)
|
||||
msg.add("', this may be unintentional, " &
|
||||
"either use ';' (semicolon) or explicitly write each default value")
|
||||
message(c.config, a.info, warnImplicitDefaultValue, msg)
|
||||
block determineType:
|
||||
var defTyp = typ
|
||||
if genericParams != nil and genericParams.len > 0:
|
||||
@@ -1359,6 +1368,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
|
||||
for j in 0..<a.len-2:
|
||||
var arg = newSymG(skParam, if a[j].kind == nkPragmaExpr: a[j][0] else: a[j], c)
|
||||
if arg.name.s == "_":
|
||||
arg.flags.incl(sfGenSym)
|
||||
elif containsOrIncl(check, arg.name.id):
|
||||
localError(c.config, a[j].info, "attempt to redefine: '" & arg.name.s & "'")
|
||||
if a[j].kind == nkPragmaExpr:
|
||||
pragma(c, arg, a[j][1], paramPragmas)
|
||||
if not hasType and not hasDefault and kind notin {skTemplate, skMacro}:
|
||||
@@ -1367,8 +1380,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
else:
|
||||
localError(c.config, a.info, "parameter '$1' requires a type" % arg.name.s)
|
||||
typ = errorType(c)
|
||||
var nameForLift = arg.name.s
|
||||
if sfGenSym in arg.flags:
|
||||
nameForLift.add("`gensym" & $arg.id)
|
||||
let lifted = liftParamType(c, kind, genericParams, typ,
|
||||
arg.name.s, arg.info)
|
||||
nameForLift, arg.info)
|
||||
let finalType = if lifted != nil: lifted else: typ.skipIntLit(c.idgen)
|
||||
arg.typ = finalType
|
||||
arg.position = counter
|
||||
@@ -1376,17 +1392,12 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
inc(counter)
|
||||
if def != nil and def.kind != nkEmpty:
|
||||
arg.ast = copyTree(def)
|
||||
if arg.name.s == "_":
|
||||
arg.flags.incl(sfGenSym)
|
||||
elif containsOrIncl(check, arg.name.id):
|
||||
localError(c.config, a[j].info, "attempt to redefine: '" & arg.name.s & "'")
|
||||
result.n.add newSymNode(arg)
|
||||
rawAddSon(result, finalType)
|
||||
addParamOrResult(c, arg, kind)
|
||||
styleCheckDef(c, a[j].info, arg)
|
||||
onDef(a[j].info, arg)
|
||||
if {optNimV1Emulation, optNimV12Emulation} * c.config.globalOptions == {}:
|
||||
a[j] = newSymNode(arg)
|
||||
a[j] = newSymNode(arg)
|
||||
|
||||
var r: PType
|
||||
if n[0].kind != nkEmpty:
|
||||
@@ -1748,7 +1759,7 @@ proc semProcTypeWithScope(c: PContext, n: PNode,
|
||||
if n[1].kind != nkEmpty and n[1].len > 0:
|
||||
pragma(c, s, n[1], procTypePragmas)
|
||||
when useEffectSystem: setEffectsForProcType(c.graph, result, n[1])
|
||||
elif c.optionStack.len > 0 and optNimV1Emulation notin c.config.globalOptions:
|
||||
elif c.optionStack.len > 0:
|
||||
# we construct a fake 'nkProcDef' for the 'mergePragmas' inside 'implicitPragmas'...
|
||||
s.ast = newTree(nkProcDef, newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info),
|
||||
newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info), newNodeI(nkEmpty, n.info))
|
||||
@@ -2043,25 +2054,27 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkOutTy: result = semVarOutType(c, n, prev, {tfIsOutParam})
|
||||
of nkDistinctTy: result = semDistinct(c, n, prev)
|
||||
of nkStaticTy: result = semStaticType(c, n[0], prev)
|
||||
of nkIteratorTy:
|
||||
if n.len == 0:
|
||||
of nkProcTy, nkIteratorTy:
|
||||
if n.len == 0 or n[0].kind == nkEmpty:
|
||||
# 0 length or empty param list with possible pragmas imply typeclass
|
||||
result = newTypeS(tyBuiltInTypeClass, c)
|
||||
let child = newTypeS(tyProc, c)
|
||||
child.flags.incl tfIterator
|
||||
var symKind: TSymKind
|
||||
if n.kind == nkIteratorTy:
|
||||
child.flags.incl tfIterator
|
||||
if n.len > 0 and n[1].kind != nkEmpty and n[1].len > 0:
|
||||
# typeclass with pragma
|
||||
let symKind = if n.kind == nkIteratorTy: skIterator else: skProc
|
||||
# dummy symbol for `pragma`:
|
||||
var s = newSymS(symKind, newIdentNode(getIdent(c.cache, "dummy"), n.info), c)
|
||||
s.typ = child
|
||||
# for now only call convention pragmas supported in proc typeclass
|
||||
pragma(c, s, n[1], {FirstCallConv..LastCallConv})
|
||||
result.addSonSkipIntLit(child, c.idgen)
|
||||
else:
|
||||
result = semProcTypeWithScope(c, n, prev, skIterator)
|
||||
if result.kind == tyProc:
|
||||
result.flags.incl(tfIterator)
|
||||
if n.lastSon.kind == nkPragma and hasPragma(n.lastSon, wInline):
|
||||
result.callConv = ccInline
|
||||
else:
|
||||
result.callConv = ccClosure
|
||||
of nkProcTy:
|
||||
if n.len == 0:
|
||||
result = newConstraint(c, tyProc)
|
||||
else:
|
||||
result = semProcTypeWithScope(c, n, prev, skProc)
|
||||
if n.kind == nkIteratorTy and result.kind == tyProc:
|
||||
result.flags.incl(tfIterator)
|
||||
of nkEnumTy: result = semEnum(c, n, prev)
|
||||
of nkType: result = n.typ
|
||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||
|
||||
@@ -204,7 +204,7 @@ proc hasValuelessStatics(n: PNode): bool =
|
||||
proc doThing(_: MyThing)
|
||||
]#
|
||||
if n.safeLen == 0:
|
||||
n.typ.kind == tyStatic
|
||||
n.typ == nil or n.typ.kind == tyStatic
|
||||
else:
|
||||
for x in n:
|
||||
if hasValuelessStatics(x):
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
## Computes hash values for routine (proc, method etc) signatures.
|
||||
|
||||
import ast, tables, ropes, md5, modulegraphs, options, msgs, packages, pathutils
|
||||
import ast, tables, ropes, md5, modulegraphs, options, msgs, pathutils
|
||||
from hashes import Hash
|
||||
import types
|
||||
|
||||
import std/os
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/assertions
|
||||
|
||||
@@ -624,6 +624,9 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||
if f.len != a.len: return
|
||||
result = isEqual # start with maximum; also correct for no
|
||||
# params at all
|
||||
|
||||
if f.flags * {tfIterator} != a.flags * {tfIterator}:
|
||||
return isNone
|
||||
|
||||
template checkParam(f, a) =
|
||||
result = minRel(result, procParamTypeRel(c, f, a))
|
||||
@@ -1295,7 +1298,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
of tyNil: result = isNone
|
||||
else: discard
|
||||
of tyOrdinal:
|
||||
if isOrdinalType(a, allowEnumWithHoles = optNimV1Emulation in c.c.config.globalOptions):
|
||||
if isOrdinalType(a):
|
||||
var x = if a.kind == tyOrdinal: a[0] else: a
|
||||
if f[0].kind == tyNone:
|
||||
result = isGeneric
|
||||
@@ -1636,13 +1639,19 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
|
||||
of tyBuiltInTypeClass:
|
||||
considerPreviousT:
|
||||
let targetKind = f[0].kind
|
||||
let target = f[0]
|
||||
let targetKind = target.kind
|
||||
let effectiveArgType = a.skipTypes({tyRange, tyGenericInst,
|
||||
tyBuiltInTypeClass, tyAlias, tySink, tyOwned})
|
||||
let typeClassMatches = targetKind == effectiveArgType.kind and
|
||||
not effectiveArgType.isEmptyContainer
|
||||
if typeClassMatches or
|
||||
(targetKind in {tyProc, tyPointer} and effectiveArgType.kind == tyNil):
|
||||
if targetKind == effectiveArgType.kind:
|
||||
if effectiveArgType.isEmptyContainer:
|
||||
return isNone
|
||||
if targetKind == tyProc:
|
||||
if target.flags * {tfIterator} != effectiveArgType.flags * {tfIterator}:
|
||||
return isNone
|
||||
if tfExplicitCallConv in target.flags and
|
||||
target.callConv != effectiveArgType.callConv:
|
||||
return isNone
|
||||
put(c, f, a)
|
||||
return isGeneric
|
||||
else:
|
||||
|
||||
@@ -1686,7 +1686,7 @@ proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool =
|
||||
of tyTuple:
|
||||
var cycleDetectorCopy: IntSet
|
||||
for i in 0..<t.len:
|
||||
assign(cycleDetectorCopy, cycleDetector)
|
||||
cycleDetectorCopy = cycleDetector
|
||||
if isTupleRecursive(t[i], cycleDetectorCopy):
|
||||
return true
|
||||
of tyAlias, tyRef, tyPtr, tyGenericInst, tyVar, tyLent, tySink,
|
||||
|
||||
@@ -64,9 +64,8 @@ proc renderType(n: PNode, toNormalize: bool): string =
|
||||
result = "ptr"
|
||||
of nkProcTy:
|
||||
assert n.len != 1
|
||||
if n.len > 1:
|
||||
if n.len > 1 and n[0].kind == nkFormalParams:
|
||||
let params = n[0]
|
||||
assert params.kind == nkFormalParams
|
||||
assert params.len > 0
|
||||
result = "proc("
|
||||
for i in 1..<params.len: result.add(renderType(params[i], toNormalize) & ',')
|
||||
|
||||
@@ -38,7 +38,6 @@ when defined(nimPreviewSlimSystem):
|
||||
else:
|
||||
from std/formatfloat import addFloatRoundtrip, addFloatSprintf
|
||||
|
||||
from std/strutils import formatBiggestFloat, FloatFormatMode
|
||||
|
||||
# There are some useful procs in vmconv.
|
||||
import vmconv, vmmarshal
|
||||
|
||||
@@ -169,9 +169,10 @@ Advanced options:
|
||||
enable experimental language feature
|
||||
--legacy:$2
|
||||
enable obsolete/legacy language feature
|
||||
--useVersion:1.0|1.2|1.6 emulate Nim version X of the Nim compiler, for testing
|
||||
--benchmarkVM:on|off turn benchmarking of VM code with cpuTime() on|off
|
||||
--profileVM:on|off turn compile time VM profiler on|off
|
||||
--sinkInference:on|off turn sink parameter inference on|off (default: off)
|
||||
--panics:on|off turn panics into process terminations (default: off)
|
||||
--deepcopy:on|off enable 'system.deepCopy' for ``--mm:arc|orc``
|
||||
--jsbigint64:on|off toggle the use of [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
|
||||
for 64-bit integers on the JavaScript backend (default: on)
|
||||
|
||||
@@ -1348,7 +1348,7 @@ Generic parameters are treated in the type, not the ``proc`` itself.
|
||||
Concrete syntax:
|
||||
|
||||
```nim
|
||||
type MyProc[T] = proc(x: T)
|
||||
type MyProc[T] = proc(x: T) {.nimcall.}
|
||||
```
|
||||
|
||||
AST:
|
||||
@@ -1363,7 +1363,8 @@ AST:
|
||||
nnkProcTy( # behaves like a procedure declaration from here on
|
||||
nnkFormalParams(
|
||||
# ...
|
||||
)
|
||||
),
|
||||
nnkPragma(nnkIdent("nimcall"))
|
||||
)
|
||||
)
|
||||
```
|
||||
@@ -1371,6 +1372,37 @@ AST:
|
||||
The same syntax applies to ``iterator`` (with ``nnkIteratorTy``), but
|
||||
*does not* apply to ``converter`` or ``template``.
|
||||
|
||||
Type class versions of these nodes generally share the same node kind but
|
||||
without any child nodes. The ``tuple`` type class is represented by
|
||||
``nnkTupleClassTy``, while a ``proc`` or ``iterator`` type class with pragmas
|
||||
has an ``nnkEmpty`` node in place of the ``nnkFormalParams`` node of a
|
||||
concrete ``proc`` or ``iterator`` type node.
|
||||
|
||||
```nim
|
||||
type TypeClass = proc {.nimcall.} | ref | tuple
|
||||
```
|
||||
|
||||
AST:
|
||||
|
||||
```nim
|
||||
nnkTypeDef(
|
||||
nnkIdent("TypeClass"),
|
||||
nnkEmpty(),
|
||||
nnkInfix(
|
||||
nnkIdent("|"),
|
||||
nnkProcTy(
|
||||
nnkEmpty(),
|
||||
nnkPragma(nnkIdent("nimcall"))
|
||||
),
|
||||
nnkInfix(
|
||||
nnkIdent("|"),
|
||||
nnkRefTy(),
|
||||
nnkTupleClassTy()
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
Mixin statement
|
||||
---------------
|
||||
|
||||
|
||||
@@ -187,7 +187,8 @@ conceptDecl = 'concept' conceptParam ^* ',' (pragma)? ('of' typeDesc ^* ',')?
|
||||
&IND{>} stmt
|
||||
typeDef = identVisDot genericParamList? pragma '=' optInd typeDefValue
|
||||
indAndComment?
|
||||
varTuple = '(' optInd identWithPragma ^+ comma optPar ')' '=' optInd expr
|
||||
varTupleLhs = '(' optInd (identWithPragma / varTupleLhs) ^+ comma optPar ')'
|
||||
varTuple = varTupleLhs '=' optInd expr
|
||||
colonBody = colcom stmt postExprBlocks?
|
||||
variable = (varTuple / identColonEquals) colonBody? indAndComment
|
||||
constant = (varTuple / identWithPragma) (colon typeDesc)? '=' optInd expr indAndComment
|
||||
|
||||
208
doc/lib.md
208
doc/lib.md
@@ -47,17 +47,17 @@ Core
|
||||
Provides a series of low-level methods for bit manipulation.
|
||||
|
||||
* [compilesettings](compilesettings.html)
|
||||
This module allows querying the compiler about diverse configuration settings.
|
||||
Querying the compiler about diverse configuration settings from code.
|
||||
|
||||
* [cpuinfo](cpuinfo.html)
|
||||
This module implements procs to determine the number of CPUs / cores.
|
||||
Procs to determine the number of CPUs / cores.
|
||||
|
||||
* [effecttraits](effecttraits.html)
|
||||
This module provides access to the inferred .raises effects
|
||||
Access to the inferred .raises effects
|
||||
for Nim's macro system.
|
||||
|
||||
* [endians](endians.html)
|
||||
This module contains helpers that deal with different byte orders.
|
||||
Helpers that deal with different byte orders.
|
||||
|
||||
* [locks](locks.html)
|
||||
Locks and condition variables for Nim.
|
||||
@@ -75,10 +75,10 @@ Core
|
||||
Provides (unsafe) access to Nim's run-time type information.
|
||||
|
||||
* [typetraits](typetraits.html)
|
||||
This module defines compile-time reflection procs for working with types.
|
||||
Compile-time reflection procs for working with types.
|
||||
|
||||
* [volatile](volatile.html)
|
||||
This module contains code for generating volatile loads and stores,
|
||||
Code for generating volatile loads and stores,
|
||||
which are useful in embedded and systems programming.
|
||||
|
||||
|
||||
@@ -86,24 +86,24 @@ Algorithms
|
||||
----------
|
||||
|
||||
* [algorithm](algorithm.html)
|
||||
This module implements some common generic algorithms like sort or binary search.
|
||||
Some common generic algorithms like sort or binary search.
|
||||
|
||||
* [enumutils](enumutils.html)
|
||||
This module adds functionality for the built-in `enum` type.
|
||||
Additional functionality for the built-in `enum` type.
|
||||
|
||||
* [sequtils](sequtils.html)
|
||||
This module implements operations for the built-in `seq` type
|
||||
Operations for the built-in `seq` type
|
||||
which were inspired by functional programming languages.
|
||||
|
||||
* [setutils](setutils.html)
|
||||
This module adds functionality for the built-in `set` type.
|
||||
Additional functionality for the built-in `set` type.
|
||||
|
||||
|
||||
Collections
|
||||
-----------
|
||||
|
||||
* [critbits](critbits.html)
|
||||
This module implements a *crit bit tree* which is an efficient
|
||||
A *crit bit tree* which is an efficient
|
||||
container for a sorted set of strings, or a sorted mapping of strings.
|
||||
|
||||
* [deques](deques.html)
|
||||
@@ -127,7 +127,7 @@ Collections
|
||||
Efficient implementation of a set of ordinals as a sparse bit set.
|
||||
|
||||
* [ropes](ropes.html)
|
||||
This module contains support for a *rope* data type.
|
||||
A *rope* data type.
|
||||
Ropes can represent very long strings efficiently;
|
||||
in particular, concatenation is done in O(1) instead of O(n).
|
||||
|
||||
@@ -150,7 +150,7 @@ String handling
|
||||
Utilities for `cstring` handling.
|
||||
|
||||
* [editdistance](editdistance.html)
|
||||
This module contains an algorithm to compute the edit distance between two
|
||||
An algorithm to compute the edit distance between two
|
||||
Unicode strings.
|
||||
|
||||
* [encodings](encodings.html)
|
||||
@@ -158,35 +158,37 @@ String handling
|
||||
the `iconv` library, on Windows the Windows API.
|
||||
|
||||
* [formatfloat](formatfloat.html)
|
||||
This module implements formatting floats as strings.
|
||||
Formatting floats as strings.
|
||||
|
||||
* [objectdollar](objectdollar.html)
|
||||
This module implements a generic `$` operator to convert objects to strings.
|
||||
A generic `$` operator to convert objects to strings.
|
||||
|
||||
* [punycode](punycode.html)
|
||||
Implements a representation of Unicode with the limited ASCII character subset.
|
||||
|
||||
* [strbasics](strbasics.html)
|
||||
This module provides some high performance string operations.
|
||||
Some high performance string operations.
|
||||
|
||||
* [strformat](strformat.html)
|
||||
Macro based standard string interpolation/formatting. Inspired by
|
||||
Python's f-strings.
|
||||
Python's f-strings.\
|
||||
**Note:** if you need templating, consider using Nim
|
||||
[Source Code Filters (SCF)](filters.html).
|
||||
|
||||
* [strmisc](strmisc.html)
|
||||
This module contains uncommon string handling operations that do not
|
||||
fit with the commonly used operations in strutils.
|
||||
Uncommon string handling operations that do not
|
||||
fit with the commonly used operations in [strutils](strutils.html).
|
||||
|
||||
* [strscans](strscans.html)
|
||||
This module contains a `scanf` macro for convenient parsing of mini languages.
|
||||
A `scanf` macro for convenient parsing of mini languages.
|
||||
|
||||
* [strutils](strutils.html)
|
||||
This module contains common string handling operations like changing
|
||||
Common string handling operations like changing
|
||||
case of a string, splitting a string into substrings, searching for
|
||||
substrings, replacing substrings.
|
||||
|
||||
* [unicode](unicode.html)
|
||||
This module provides support to handle the Unicode UTF-8 encoding.
|
||||
Support for handling the Unicode UTF-8 encoding.
|
||||
|
||||
* [unidecode](unidecode.html)
|
||||
It provides a single proc that does Unicode to ASCII transliterations.
|
||||
@@ -196,7 +198,7 @@ String handling
|
||||
Nim support for C/C++'s wide strings.
|
||||
|
||||
* [wordwrap](wordwrap.html)
|
||||
This module contains an algorithm to wordwrap a Unicode string.
|
||||
An algorithm for word-wrapping Unicode strings.
|
||||
|
||||
|
||||
Time handling
|
||||
@@ -213,17 +215,16 @@ Generic Operating System Services
|
||||
---------------------------------
|
||||
|
||||
* [appdirs](appdirs.html)
|
||||
This module implements helpers for determining special directories used by apps.
|
||||
Helpers for determining special directories used by apps.
|
||||
|
||||
* [cmdline](cmdline.html)
|
||||
This module contains system facilities for reading command
|
||||
line parameters.
|
||||
System facilities for reading command line parameters.
|
||||
|
||||
* [dirs](dirs.html)
|
||||
This module implements directory handling.
|
||||
Directory handling.
|
||||
|
||||
* [distros](distros.html)
|
||||
This module implements the basics for OS distribution ("distro") detection
|
||||
Basics for OS distribution ("distro") detection
|
||||
and the OS's native package manager.
|
||||
Its primary purpose is to produce output for Nimble packages,
|
||||
but it also contains the widely used **Distribution** enum
|
||||
@@ -231,19 +232,19 @@ Generic Operating System Services
|
||||
See [packaging](packaging.html) for hints on distributing Nim using OS packages.
|
||||
|
||||
* [dynlib](dynlib.html)
|
||||
This module implements the ability to access symbols from shared libraries.
|
||||
Accessing symbols from shared libraries.
|
||||
|
||||
* [envvars](envvars.html)
|
||||
This module implements environment variable handling.
|
||||
Environment variable handling.
|
||||
|
||||
* [exitprocs](exitprocs.html)
|
||||
This module allows adding hooks to program exit.
|
||||
Adding hooks to program exit.
|
||||
|
||||
* [files](files.html)
|
||||
This module implements file handling.
|
||||
File handling.
|
||||
|
||||
* [memfiles](memfiles.html)
|
||||
This module provides support for memory-mapped files (Posix's `mmap`)
|
||||
Support for memory-mapped files (Posix's `mmap`)
|
||||
on the different operating systems.
|
||||
|
||||
* [os](os.html)
|
||||
@@ -252,52 +253,50 @@ Generic Operating System Services
|
||||
commands, etc.
|
||||
|
||||
* [oserrors](oserrors.html)
|
||||
This module implements OS error reporting.
|
||||
OS error reporting.
|
||||
|
||||
* [osproc](osproc.html)
|
||||
Module for process communication beyond `os.execShellCmd`.
|
||||
|
||||
* [paths](paths.html)
|
||||
This module implements path handling.
|
||||
Path handling.
|
||||
|
||||
* [reservedmem](reservedmem.html)
|
||||
This module provides utilities for reserving portions of the
|
||||
Utilities for reserving portions of the
|
||||
address space of a program without consuming physical memory.
|
||||
|
||||
* [streams](streams.html)
|
||||
This module provides a stream interface and two implementations thereof:
|
||||
A stream interface and two implementations thereof:
|
||||
the `FileStream` and the `StringStream` which implement the stream
|
||||
interface for Nim file objects (`File`) and strings. Other modules
|
||||
may provide other implementations for this standard stream interface.
|
||||
|
||||
* [symlinks](symlinks.html)
|
||||
This module implements symlink handling.
|
||||
Symlink handling.
|
||||
|
||||
* [syncio](syncio.html)
|
||||
This module implements various synchronized I/O operations.
|
||||
Various synchronized I/O operations.
|
||||
|
||||
* [terminal](terminal.html)
|
||||
This module contains a few procedures to control the *terminal*
|
||||
(also called *console*). The implementation simply uses ANSI escape
|
||||
sequences and does not depend on any other module.
|
||||
A module to control the terminal output (also called *console*).
|
||||
|
||||
* [tempfiles](tempfiles.html)
|
||||
This module provides some utils to generate temporary path names and
|
||||
create temporary files and directories.
|
||||
Some utilities for generating temporary path names and
|
||||
creating temporary files and directories.
|
||||
|
||||
|
||||
Math libraries
|
||||
--------------
|
||||
|
||||
* [complex](complex.html)
|
||||
This module implements complex numbers and relevant mathematical operations.
|
||||
Complex numbers and relevant mathematical operations.
|
||||
|
||||
* [fenv](fenv.html)
|
||||
Floating-point environment. Handling of floating-point rounding and
|
||||
exceptions (overflow, zero-divide, etc.).
|
||||
|
||||
* [lenientops](lenientops.html)
|
||||
Provides binary operators for mixed integer/float expressions for convenience.
|
||||
Binary operators for mixed integer/float expressions for convenience.
|
||||
|
||||
* [math](math.html)
|
||||
Mathematical operations like cosine, square root.
|
||||
@@ -306,7 +305,7 @@ Math libraries
|
||||
Fast and tiny random number generator.
|
||||
|
||||
* [rationals](rationals.html)
|
||||
This module implements rational numbers and relevant mathematical operations.
|
||||
Rational numbers and relevant mathematical operations.
|
||||
|
||||
* [stats](stats.html)
|
||||
Statistical analysis.
|
||||
@@ -322,75 +321,69 @@ Internet Protocols and Support
|
||||
Exports `asyncmacro` and `asyncfutures` for native backends, and `asyncjs` on the JS backend.
|
||||
|
||||
* [asyncdispatch](asyncdispatch.html)
|
||||
This module implements an asynchronous dispatcher for IO operations.
|
||||
An asynchronous dispatcher for IO operations.
|
||||
|
||||
* [asyncfile](asyncfile.html)
|
||||
This module implements asynchronous file reading and writing using
|
||||
`asyncdispatch`.
|
||||
An asynchronous file reading and writing using `asyncdispatch`.
|
||||
|
||||
* [asyncftpclient](asyncftpclient.html)
|
||||
This module implements an asynchronous FTP client using the `asyncnet`
|
||||
module.
|
||||
An asynchronous FTP client using the `asyncnet` module.
|
||||
|
||||
* [asynchttpserver](asynchttpserver.html)
|
||||
This module implements an asynchronous HTTP server using the `asyncnet`
|
||||
module.
|
||||
An asynchronous HTTP server using the `asyncnet` module.
|
||||
|
||||
* [asyncmacro](asyncmacro.html)
|
||||
Implements the `async` and `multisync` macros for `asyncdispatch`.
|
||||
`async` and `multisync` macros for `asyncdispatch`.
|
||||
|
||||
* [asyncnet](asyncnet.html)
|
||||
This module implements asynchronous sockets based on the `asyncdispatch`
|
||||
module.
|
||||
Asynchronous sockets based on the `asyncdispatch` module.
|
||||
|
||||
* [asyncstreams](asyncstreams.html)
|
||||
This module provides `FutureStream` - a future that acts as a queue.
|
||||
`FutureStream` - a future that acts as a queue.
|
||||
|
||||
* [cgi](cgi.html)
|
||||
This module implements helpers for CGI applications.
|
||||
Helpers for CGI applications.
|
||||
|
||||
* [cookies](cookies.html)
|
||||
This module contains helper procs for parsing and generating cookies.
|
||||
Helper procs for parsing and generating cookies.
|
||||
|
||||
* [httpclient](httpclient.html)
|
||||
This module implements a simple HTTP client which supports both synchronous
|
||||
A simple HTTP client with support for both synchronous
|
||||
and asynchronous retrieval of web pages.
|
||||
|
||||
* [mimetypes](mimetypes.html)
|
||||
This module implements a mimetypes database.
|
||||
A mimetypes database.
|
||||
|
||||
* [nativesockets](nativesockets.html)
|
||||
This module implements a low-level sockets API.
|
||||
A low-level sockets API.
|
||||
|
||||
* [net](net.html)
|
||||
This module implements a high-level sockets API. It replaces the
|
||||
`sockets` module.
|
||||
A high-level sockets API.
|
||||
|
||||
* [selectors](selectors.html)
|
||||
This module implements a selector API with backends specific to each OS.
|
||||
Currently, epoll on Linux and select on other operating systems.
|
||||
A selector API with backends specific to each OS.
|
||||
Supported OS primitives: `epoll`, `kqueue`, `poll`, and `select` on Windows.
|
||||
|
||||
* [smtp](smtp.html)
|
||||
This module implements a simple SMTP client.
|
||||
A simple SMTP client with support for both synchronous and asynchronous operation.
|
||||
|
||||
* [socketstreams](socketstreams.html)
|
||||
This module provides an implementation of the streams interface for sockets.
|
||||
|
||||
An implementation of the streams interface for sockets.
|
||||
|
||||
* [uri](uri.html)
|
||||
This module provides functions for working with URIs.
|
||||
Functions for working with URIs and URLs.
|
||||
|
||||
|
||||
Threading
|
||||
---------
|
||||
|
||||
* [isolation](isolation.html)
|
||||
This module implements the `Isolated[T]` type for
|
||||
The `Isolated[T]` type for
|
||||
safe construction of isolated subgraphs that can be
|
||||
passed efficiently to different channels and threads.
|
||||
|
||||
* [tasks](tasks.html)
|
||||
This module provides basic primitives for creating parallel programs.
|
||||
Basic primitives for creating parallel programs.
|
||||
|
||||
* [threadpool](threadpool.html)
|
||||
Implements Nim's [spawn](manual_experimental.html#parallel-amp-spawn).
|
||||
@@ -403,13 +396,13 @@ Parsers
|
||||
-------
|
||||
|
||||
* [htmlparser](htmlparser.html)
|
||||
This module parses an HTML document and creates its XML tree representation.
|
||||
HTML document parser that creates a XML tree representation.
|
||||
|
||||
* [json](json.html)
|
||||
High-performance JSON parser.
|
||||
|
||||
* [lexbase](lexbase.html)
|
||||
This is a low-level module that implements an extremely efficient buffering
|
||||
A low-level module that implements an extremely efficient buffering
|
||||
scheme for lexers and parsers. This is used by the diverse parsing modules.
|
||||
|
||||
* [parsecfg](parsecfg.html)
|
||||
@@ -423,7 +416,7 @@ Parsers
|
||||
The `parsecsv` module implements a simple high-performance CSV parser.
|
||||
|
||||
* [parsejson](parsejson.html)
|
||||
This module implements a JSON parser. It is used and exported by the [json](json.html) module, but can also be used in its own right.
|
||||
A JSON parser. It is used and exported by the [json](json.html) module, but can also be used in its own right.
|
||||
|
||||
* [parseopt](parseopt.html)
|
||||
The `parseopt` module implements a command line option parser.
|
||||
@@ -432,7 +425,7 @@ Parsers
|
||||
The `parsesql` module implements a simple high-performance SQL parser.
|
||||
|
||||
* [parseutils](parseutils.html)
|
||||
This module contains helpers for parsing tokens, numbers, identifiers, etc.
|
||||
Helpers for parsing tokens, numbers, identifiers, etc.
|
||||
|
||||
* [parsexml](parsexml.html)
|
||||
The `parsexml` module implements a simple high performance XML/HTML parser.
|
||||
@@ -441,7 +434,7 @@ Parsers
|
||||
web can be parsed with it.
|
||||
|
||||
* [pegs](pegs.html)
|
||||
This module contains procedures and operators for handling PEGs.
|
||||
Procedures and operators for handling PEGs.
|
||||
|
||||
|
||||
Docutils
|
||||
@@ -453,14 +446,14 @@ Docutils
|
||||
The interface supports one language nested in another.
|
||||
|
||||
* [packages/docutils/rst](rst.html)
|
||||
This module implements a reStructuredText parser. A large subset
|
||||
A reStructuredText parser. A large subset
|
||||
is implemented. Some features of the markdown wiki syntax are also supported.
|
||||
|
||||
* [packages/docutils/rstast](rstast.html)
|
||||
This module implements an AST for the reStructuredText parser.
|
||||
An AST for the reStructuredText parser.
|
||||
|
||||
* [packages/docutils/rstgen](rstgen.html)
|
||||
This module implements a generator of HTML/Latex from reStructuredText.
|
||||
A generator of HTML/Latex from reStructuredText.
|
||||
|
||||
|
||||
XML Processing
|
||||
@@ -471,17 +464,17 @@ XML Processing
|
||||
contains a macro for XML/HTML code generation.
|
||||
|
||||
* [xmlparser](xmlparser.html)
|
||||
This module parses an XML document and creates its XML tree representation.
|
||||
XML document parser that creates a XML tree representation.
|
||||
|
||||
|
||||
Generators
|
||||
----------
|
||||
|
||||
* [genasts](genasts.html)
|
||||
This module implements AST generation using captured variables for macros.
|
||||
AST generation using captured variables for macros.
|
||||
|
||||
* [htmlgen](htmlgen.html)
|
||||
This module implements a simple XML and HTML code
|
||||
A simple XML and HTML code
|
||||
generator. Each commonly used HTML tag has a corresponding macro
|
||||
that generates a string with its HTML representation.
|
||||
|
||||
@@ -490,14 +483,13 @@ Hashing
|
||||
-------
|
||||
|
||||
* [base64](base64.html)
|
||||
This module implements a Base64 encoder and decoder.
|
||||
A Base64 encoder and decoder.
|
||||
|
||||
* [hashes](hashes.html)
|
||||
This module implements efficient computations of hash values for diverse
|
||||
Nim types.
|
||||
Efficient computations of hash values for diverse Nim types.
|
||||
|
||||
* [md5](md5.html)
|
||||
This module implements the MD5 checksum algorithm.
|
||||
The MD5 checksum algorithm.
|
||||
|
||||
* [oids](oids.html)
|
||||
An OID is a global ID that consists of a timestamp,
|
||||
@@ -505,14 +497,14 @@ Hashing
|
||||
produce a globally distributed unique ID.
|
||||
|
||||
* [sha1](sha1.html)
|
||||
This module implements the SHA-1 checksum algorithm.
|
||||
The SHA-1 checksum algorithm.
|
||||
|
||||
|
||||
Serialization
|
||||
-------------
|
||||
|
||||
* [jsonutils](jsonutils.html)
|
||||
This module implements a hookable (de)serialization for arbitrary types
|
||||
Hookable (de)serialization for arbitrary types
|
||||
using JSON.
|
||||
|
||||
* [marshal](marshal.html)
|
||||
@@ -524,35 +516,35 @@ Miscellaneous
|
||||
-------------
|
||||
|
||||
* [assertions](assertions.html)
|
||||
This module implements assertion handling.
|
||||
Assertion handling.
|
||||
|
||||
* [browsers](browsers.html)
|
||||
This module implements procs for opening URLs with the user's default
|
||||
Procs for opening URLs with the user's default
|
||||
browser.
|
||||
|
||||
* [colors](colors.html)
|
||||
This module implements color handling for Nim.
|
||||
Color handling.
|
||||
|
||||
* [coro](coro.html)
|
||||
This module implements experimental coroutines in Nim.
|
||||
Experimental coroutines in Nim.
|
||||
|
||||
* [decls](decls.html)
|
||||
This module implements syntax sugar for some declarations.
|
||||
Syntax sugar for some declarations.
|
||||
|
||||
* [enumerate](enumerate.html)
|
||||
This module implements `enumerate` syntactic sugar based on Nim's macro system.
|
||||
`enumerate` syntactic sugar based on Nim's macro system.
|
||||
|
||||
* [importutils](importutils.html)
|
||||
Utilities related to import and symbol resolution.
|
||||
|
||||
* [logging](logging.html)
|
||||
This module implements a simple logger.
|
||||
A simple logger.
|
||||
|
||||
* [segfaults](segfaults.html)
|
||||
Turns access violations or segfaults into a `NilAccessDefect` exception.
|
||||
|
||||
* [sugar](sugar.html)
|
||||
This module implements nice syntactic sugar based on Nim's macro system.
|
||||
Nice syntactic sugar based on Nim's macro system.
|
||||
|
||||
* [unittest](unittest.html)
|
||||
Implements a Unit testing DSL.
|
||||
@@ -561,10 +553,10 @@ Miscellaneous
|
||||
Decode variable-length integers that are compatible with SQLite.
|
||||
|
||||
* [with](with.html)
|
||||
This module implements the `with` macro for easy function chaining.
|
||||
The `with` macro for easy function chaining.
|
||||
|
||||
* [wrapnils](wrapnils.html)
|
||||
This module allows evaluating expressions safely against nil dereferences.
|
||||
Allows evaluating expressions safely against nil dereferences.
|
||||
|
||||
|
||||
Modules for the JavaScript backend
|
||||
@@ -603,12 +595,12 @@ Regular expressions
|
||||
-------------------
|
||||
|
||||
* [re](re.html)
|
||||
This module contains procedures and operators for handling regular
|
||||
Procedures and operators for handling regular
|
||||
expressions. The current implementation uses PCRE.
|
||||
|
||||
* [nre](nre.html)
|
||||
|
||||
This module contains many help functions for handling regular expressions.
|
||||
Many help functions for handling regular expressions.
|
||||
The current implementation uses PCRE.
|
||||
|
||||
Database support
|
||||
@@ -635,7 +627,7 @@ Generic Operating System Services
|
||||
---------------------------------
|
||||
|
||||
* [rdstdin](rdstdin.html)
|
||||
This module contains code for reading from stdin.
|
||||
Code for reading user input from stdin.
|
||||
|
||||
|
||||
Wrappers
|
||||
@@ -649,7 +641,7 @@ Windows-specific
|
||||
----------------
|
||||
|
||||
* [winlean](winlean.html)
|
||||
Contains a wrapper for a small subset of the Win32 API.
|
||||
Wrapper for a small subset of the Win32 API.
|
||||
* [registry](registry.html)
|
||||
Windows registry support.
|
||||
|
||||
@@ -658,7 +650,7 @@ UNIX specific
|
||||
-------------
|
||||
|
||||
* [posix](posix.html)
|
||||
Contains a wrapper for the POSIX standard.
|
||||
Wrapper for the POSIX standard.
|
||||
* [posix_utils](posix_utils.html)
|
||||
Contains helpers for the POSIX standard or specialized for Linux and BSDs.
|
||||
|
||||
@@ -674,13 +666,13 @@ Database support
|
||||
----------------
|
||||
|
||||
* [mysql](mysql.html)
|
||||
Contains a wrapper for the mySQL API.
|
||||
Wrapper for the mySQL API.
|
||||
* [odbcsql](odbcsql.html)
|
||||
interface to the ODBC driver.
|
||||
* [postgres](postgres.html)
|
||||
Contains a wrapper for the PostgreSQL API.
|
||||
Wrapper for the PostgreSQL API.
|
||||
* [sqlite3](sqlite3.html)
|
||||
Contains a wrapper for the SQLite 3 API.
|
||||
Wrapper for the SQLite 3 API.
|
||||
|
||||
|
||||
Network Programming and Internet Protocols
|
||||
|
||||
@@ -1828,23 +1828,6 @@ an `object` type or a `ref object` type:
|
||||
Note that, unlike tuples, objects require the field names along with their values.
|
||||
For a `ref object` type `system.new` is invoked implicitly.
|
||||
|
||||
The field names can be omitted if all the values are given in order. It can be mixed with field names along with values.
|
||||
|
||||
```nim
|
||||
var a1 = Student("Anton", 5)
|
||||
var a2 = PStudent("Anton", age: 5)
|
||||
```
|
||||
|
||||
Note that, objects with only one field must use field names along with values. Otherwise, they will be recognized as type conversions.
|
||||
|
||||
```nim
|
||||
type
|
||||
Teacher = object
|
||||
name: string
|
||||
# var t = Teacher("lisa") # Error: type mismatch: got 'string' for '"lisa"'
|
||||
# but expected 'Teacher = object'
|
||||
var t = Teacher(name: "lisa")
|
||||
```
|
||||
|
||||
Object variants
|
||||
---------------
|
||||
@@ -3093,12 +3076,25 @@ when they are declared. The only exception to this is if the `{.importc.}`
|
||||
pragma (or any of the other `importX` pragmas) is applied, in this case the
|
||||
value is expected to come from native code, typically a C/C++ `const`.
|
||||
|
||||
Special identifier `_` (underscore)
|
||||
-----------------------------------
|
||||
|
||||
The identifier `_` has a special meaning in declarations.
|
||||
Any definition with the name `_` will not be added to scope, meaning the
|
||||
definition is evaluated, but cannot be used. As a result the name `_` can be
|
||||
indefinitely redefined.
|
||||
|
||||
```nim
|
||||
let _ = 123
|
||||
echo _ # error
|
||||
let _ = 456 # compiles
|
||||
```
|
||||
|
||||
Tuple unpacking
|
||||
---------------
|
||||
|
||||
In a `var` or `let` statement tuple unpacking can be performed. The special
|
||||
identifier `_` can be used to ignore some parts of the tuple:
|
||||
In a `var`, `let` or `const` statement tuple unpacking can be performed.
|
||||
The special identifier `_` can be used to ignore some parts of the tuple:
|
||||
|
||||
```nim
|
||||
proc returnsTuple(): (int, int, int) = (4, 2, 3)
|
||||
@@ -3106,6 +3102,35 @@ identifier `_` can be used to ignore some parts of the tuple:
|
||||
let (x, _, z) = returnsTuple()
|
||||
```
|
||||
|
||||
This is treated as syntax sugar for roughly the following:
|
||||
|
||||
```nim
|
||||
let
|
||||
tmpTuple = returnsTuple()
|
||||
x = tmpTuple[0]
|
||||
z = tmpTuple[2]
|
||||
```
|
||||
|
||||
For `var` or `let` statements, if the value expression is a tuple literal,
|
||||
each expression is directly expanded into an assignment without the use of
|
||||
a temporary variable.
|
||||
|
||||
```nim
|
||||
let (x, y, z) = (1, 2, 3)
|
||||
# becomes
|
||||
let
|
||||
x = 1
|
||||
y = 2
|
||||
z = 3
|
||||
```
|
||||
|
||||
Tuple unpacking can also be nested:
|
||||
|
||||
```nim
|
||||
proc returnsNestedTuple(): (int, (int, int), int, int) = (4, (5, 7), 2, 3)
|
||||
|
||||
let (x, (_, y), _, z) = returnsNestedTuple()
|
||||
```
|
||||
|
||||
|
||||
Const section
|
||||
@@ -3791,15 +3816,6 @@ every time the function is called.
|
||||
proc foo(a: int, b: int = 47): int
|
||||
```
|
||||
|
||||
Just as the comma propagates the types from right to left until the
|
||||
first parameter or until a semicolon is hit, it also propagates the
|
||||
default value starting from the parameter declared with it.
|
||||
|
||||
```nim
|
||||
# Both a and b are optional with 47 as their default values.
|
||||
proc foo(a, b: int = 47): int
|
||||
```
|
||||
|
||||
Parameters can be declared mutable and so allow the proc to modify those
|
||||
arguments, by using the type modifier `var`.
|
||||
|
||||
@@ -5451,9 +5467,9 @@ type class matches
|
||||
================== ===================================================
|
||||
`object` any object type
|
||||
`tuple` any tuple type
|
||||
|
||||
`enum` any enumeration
|
||||
`proc` any proc type
|
||||
`iterator` any iterator type
|
||||
`ref` any `ref` type
|
||||
`ptr` any `ptr` type
|
||||
`var` any `var` type
|
||||
@@ -5513,6 +5529,17 @@ as `type constraints`:idx: of the generic type parameter:
|
||||
onlyIntOrString("xy", 50) # invalid as 'T' cannot be both at the same time
|
||||
```
|
||||
|
||||
`proc` and `iterator` type classes also accept a calling convention pragma
|
||||
to restrict the calling convention of the matching `proc` or `iterator` type.
|
||||
|
||||
```nim
|
||||
proc onlyClosure[T: proc {.closure.}](x: T) = discard
|
||||
|
||||
onlyClosure(proc() = echo "hello") # valid
|
||||
proc foo() {.nimcall.} = discard
|
||||
onlyClosure(foo) # type mismatch
|
||||
```
|
||||
|
||||
|
||||
Implicit generics
|
||||
-----------------
|
||||
|
||||
10
koch.nim
10
koch.nim
@@ -229,6 +229,14 @@ proc buildTools(args: string = "") =
|
||||
nimCompileFold("Compile atlas", "tools/atlas/atlas.nim", options = "-d:release " & args,
|
||||
outputName = "atlas")
|
||||
|
||||
proc testTools(args: string = "") =
|
||||
nimCompileFold("Compile nimgrep", "tools/nimgrep.nim",
|
||||
options = "-d:release " & args)
|
||||
when defined(windows): buildVccTool(args)
|
||||
bundleNimpretty(args)
|
||||
nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release " & args)
|
||||
nimCompileFold("Compile atlas", "tools/atlas/atlas.nim", options = "-d:release " & args,
|
||||
outputName = "atlas")
|
||||
|
||||
proc nsis(latest: bool; args: string) =
|
||||
bundleNimbleExe(latest, args)
|
||||
@@ -546,7 +554,7 @@ proc runCI(cmd: string) =
|
||||
nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release")
|
||||
execFold("Test selected Nimble packages", "testament $# pcat nimble-packages" % batchParam)
|
||||
else:
|
||||
buildTools()
|
||||
testTools()
|
||||
|
||||
for a in "zip opengl sdl1 jester@#head".split:
|
||||
let buildDeps = "build"/"deps" # xxx factor pending https://github.com/timotheecour/Nim/issues/616
|
||||
|
||||
@@ -947,6 +947,8 @@ proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indent
|
||||
discard # same as nil node in this representation
|
||||
of nnkCharLit .. nnkInt64Lit:
|
||||
res.add(" " & $n.intVal)
|
||||
of nnkUIntLit .. nnkUInt64Lit:
|
||||
res.add(" " & $cast[uint64](n.intVal))
|
||||
of nnkFloatLit .. nnkFloat64Lit:
|
||||
res.add(" " & $n.floatVal)
|
||||
of nnkStrLit .. nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## specific requirements and solely targets JavaScript, you should be using
|
||||
## the relevant functions in the `math`, `json`, and `times` stdlib
|
||||
## modules instead.
|
||||
import std/private/since
|
||||
import std/private/[since, jsutils]
|
||||
|
||||
when not defined(js):
|
||||
{.error: "This module only works on the JavaScript platform".}
|
||||
@@ -74,9 +74,16 @@ proc parse*(d: DateLib, s: cstring): int {.importcpp.}
|
||||
proc newDate*(): DateTime {.
|
||||
importcpp: "new Date()".}
|
||||
|
||||
proc newDate*(date: int|int64|string): DateTime {.
|
||||
proc newDate*(date: int|string): DateTime {.
|
||||
importcpp: "new Date(#)".}
|
||||
|
||||
whenJsNoBigInt64:
|
||||
proc newDate*(date: int64): DateTime {.
|
||||
importcpp: "new Date(#)".}
|
||||
do:
|
||||
proc newDate*(date: int64): DateTime {.
|
||||
importcpp: "new Date(Number(#))".}
|
||||
|
||||
proc newDate*(year, month, day, hours, minutes,
|
||||
seconds, milliseconds: int): DateTime {.
|
||||
importcpp: "new Date(#,#,#,#,#,#,#)".}
|
||||
|
||||
@@ -350,7 +350,7 @@ type
|
||||
footnoteAnchor = "footnote anchor",
|
||||
headlineAnchor = "implicitly-generated headline anchor"
|
||||
AnchorSubst = object
|
||||
info: TLineInfo # where the anchor was defined
|
||||
info: TLineInfo # the file where the anchor was defined
|
||||
priority: int
|
||||
case kind: range[arInternalRst .. arNim]
|
||||
of arInternalRst:
|
||||
@@ -360,6 +360,7 @@ type
|
||||
anchorTypeExt: RstAnchorKind
|
||||
refnameExt: string
|
||||
of arNim:
|
||||
module: FileIndex # anchor's module (generally not the same as file)
|
||||
tooltip: string # displayed tooltip for Nim-generated anchors
|
||||
langSym: LangSymbol
|
||||
refname: string # A reference name that will be inserted directly
|
||||
@@ -520,6 +521,9 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string =
|
||||
proc getFilename(s: PRstSharedState, subst: AnchorSubst): string =
|
||||
getFilename(s.filenames, subst.info.fileIndex)
|
||||
|
||||
proc getModule(s: PRstSharedState, subst: AnchorSubst): string =
|
||||
result = getFilename(s.filenames, subst.module)
|
||||
|
||||
proc currFilename(s: PRstSharedState): string =
|
||||
getFilename(s.filenames, s.currFileIdx)
|
||||
|
||||
@@ -830,7 +834,7 @@ proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string,
|
||||
|
||||
proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string,
|
||||
langSym: LangSymbol, priority: int,
|
||||
info: TLineInfo) =
|
||||
info: TLineInfo, module: FileIndex) =
|
||||
## Adds an anchor `refn`, which follows
|
||||
## the rule `arNim` (i.e. a symbol in ``*.nim`` file)
|
||||
s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add(
|
||||
@@ -859,7 +863,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
|
||||
for subst in substitutions:
|
||||
if subst.kind == arNim:
|
||||
if match(subst.langSym, langSym):
|
||||
let key: GroupKey = (subst.langSym.symKind, getFilename(s, subst))
|
||||
let key: GroupKey = (subst.langSym.symKind, getModule(s, subst))
|
||||
found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst
|
||||
for key, sList in found:
|
||||
if sList.len == 1:
|
||||
@@ -880,7 +884,7 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
|
||||
break
|
||||
doAssert(foundGroup,
|
||||
"docgen has not generated the group for $1 (file $2)" % [
|
||||
langSym.name, getFilename(s, sList[0]) ])
|
||||
langSym.name, getModule(s, sList[0]) ])
|
||||
|
||||
proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo):
|
||||
seq[AnchorSubst] =
|
||||
@@ -2443,7 +2447,9 @@ proc parseParagraph(p: var RstParser, result: PRstNode) =
|
||||
result.addIfNotNil(parseLineBlock(p))
|
||||
of rnMarkdownBlockQuote:
|
||||
result.addIfNotNil(parseMarkdownBlockQuote(p))
|
||||
else: break
|
||||
else:
|
||||
dec p.idx # allow subsequent block to be parsed as another section
|
||||
break
|
||||
else:
|
||||
break
|
||||
of tkPunct:
|
||||
@@ -3552,7 +3558,7 @@ proc loadIdxFile(s: var PRstSharedState, origFilename: string) =
|
||||
langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword)
|
||||
addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc,
|
||||
langSym = langSym, priority = -4, # lowest
|
||||
info=info)
|
||||
info = info, module = info.fileIndex)
|
||||
doAssert s.idxImports[origFilename].title != ""
|
||||
|
||||
proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) =
|
||||
|
||||
@@ -63,6 +63,12 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T =
|
||||
type BitsRange*[T] = range[0..sizeof(T)*8-1]
|
||||
## A range with all bit positions for type `T`.
|
||||
|
||||
template typeMasked[T: SomeInteger](x: T): T =
|
||||
when defined(js):
|
||||
x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8)))
|
||||
else:
|
||||
x
|
||||
|
||||
func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||
## Returns an extracted (and shifted) slice of bits from `v`.
|
||||
runnableExamples:
|
||||
@@ -73,7 +79,7 @@ func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1,
|
||||
let
|
||||
upmost = sizeof(T) * 8 - 1
|
||||
uv = v.castToUnsigned
|
||||
(uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
|
||||
((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
|
||||
|
||||
proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
|
||||
## Mutates `v` into an extracted (and shifted) slice of bits from `v`.
|
||||
@@ -85,7 +91,7 @@ proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1,
|
||||
let
|
||||
upmost = sizeof(T) * 8 - 1
|
||||
uv = v.castToUnsigned
|
||||
v = (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
|
||||
v = ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
|
||||
|
||||
func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||
## Creates a bitmask based on a slice of bits.
|
||||
@@ -96,7 +102,7 @@ func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
|
||||
let
|
||||
upmost = sizeof(T) * 8 - 1
|
||||
bitmask = bitnot(0.T).castToUnsigned
|
||||
(bitmask shl (upmost - slice.b + slice.a) shr (upmost - slice.b)).T
|
||||
((bitmask shl (upmost - slice.b + slice.a)).typeMasked shr (upmost - slice.b)).T
|
||||
|
||||
proc masked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
|
||||
## Returns `v`, with only the `1` bits from `mask` matching those of
|
||||
|
||||
@@ -501,7 +501,7 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
|
||||
h = h !& ord(c)
|
||||
result = !$h
|
||||
|
||||
proc hash*[T: tuple | object | proc](x: T): Hash =
|
||||
proc hash*[T: tuple | object | proc | iterator {.closure.}](x: T): Hash =
|
||||
## Efficient `hash` overload.
|
||||
runnableExamples:
|
||||
# for `tuple|object`, `hash` must be defined for each component of `x`.
|
||||
|
||||
@@ -1110,7 +1110,7 @@ proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
|
||||
dst = jsonNode.copy
|
||||
|
||||
proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
|
||||
when T is uint|uint64 or (not defined(js) and int.sizeof == 4):
|
||||
when T is uint|uint64 or int.sizeof == 4:
|
||||
verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
|
||||
case jsonNode.kind
|
||||
of JString:
|
||||
|
||||
@@ -72,7 +72,7 @@ runnableExamples:
|
||||
## in the standard library
|
||||
|
||||
import algorithm, math
|
||||
import std/private/since
|
||||
import std/private/[since, jsutils]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
import std/[assertions]
|
||||
@@ -231,11 +231,14 @@ proc rand[T: uint | uint64](r: var Rand; max: T): T =
|
||||
let max = uint64(max)
|
||||
when T.high.uint64 == uint64.high:
|
||||
if max == uint64.high: return T(next(r))
|
||||
var iters = 0
|
||||
while true:
|
||||
let x = next(r)
|
||||
# avoid `mod` bias
|
||||
if x <= randMax - (randMax mod max):
|
||||
if x <= randMax - (randMax mod max) or iters > 20:
|
||||
return T(x mod (max + 1))
|
||||
else:
|
||||
inc iters
|
||||
|
||||
proc rand*(r: var Rand; max: Natural): int {.benign.} =
|
||||
## Returns a random integer in the range `0..max` using the given state.
|
||||
@@ -337,9 +340,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
|
||||
when defined(js):
|
||||
whenJsNoBigInt64:
|
||||
result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a))
|
||||
else:
|
||||
do:
|
||||
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 =
|
||||
@@ -378,14 +381,14 @@ proc rand*[T: Ordinal](r: var Rand; t: typedesc[T]): T {.since: (1, 7, 1).} =
|
||||
when T is range or T is enum:
|
||||
result = rand(r, low(T)..high(T))
|
||||
elif T is bool:
|
||||
when defined(js):
|
||||
whenJsNoBigInt64:
|
||||
result = (r.next or 0) < 0
|
||||
else:
|
||||
do:
|
||||
result = cast[int64](r.next) < 0
|
||||
else:
|
||||
when defined(js):
|
||||
whenJsNoBigInt64:
|
||||
result = cast[T](r.next shr (sizeof(uint)*8 - sizeof(T)*8))
|
||||
else:
|
||||
do:
|
||||
result = cast[T](r.next shr (sizeof(uint64)*8 - sizeof(T)*8))
|
||||
|
||||
proc rand*[T: Ordinal](t: typedesc[T]): T =
|
||||
|
||||
@@ -79,7 +79,7 @@ from unicode import toLower, toUpper
|
||||
export toLower, toUpper
|
||||
|
||||
include "system/inclrtl"
|
||||
import std/private/since
|
||||
import std/private/[since, jsutils]
|
||||
from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl,
|
||||
startsWithImpl, endsWithImpl
|
||||
|
||||
@@ -944,9 +944,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"
|
||||
when defined(js):
|
||||
whenJsNoBigInt64:
|
||||
toHexImpl(cast[BiggestUInt](x), len, x < 0)
|
||||
else:
|
||||
do:
|
||||
when T is SomeSignedInt:
|
||||
toHexImpl(cast[BiggestUInt](BiggestInt(x)), len, x < 0)
|
||||
else:
|
||||
@@ -957,9 +957,9 @@ func toHex*[T: SomeInteger](x: T): string =
|
||||
runnableExamples:
|
||||
doAssert toHex(1984'i64) == "00000000000007C0"
|
||||
doAssert toHex(1984'i16) == "07C0"
|
||||
when defined(js):
|
||||
whenJsNoBigInt64:
|
||||
toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
|
||||
else:
|
||||
do:
|
||||
when T is SomeSignedInt:
|
||||
toHexImpl(cast[BiggestUInt](BiggestInt(x)), 2*sizeof(T), x < 0)
|
||||
else:
|
||||
|
||||
@@ -291,25 +291,57 @@ else:
|
||||
## Returns some reasonable terminal width from either standard file
|
||||
## descriptors, controlling terminal, environment variables or tradition.
|
||||
|
||||
var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors
|
||||
# POSIX environment variable takes precendence.
|
||||
# _COLUMNS_: This variable shall represent a decimal integer >0 used
|
||||
# to indicate the user's preferred width in column positions for
|
||||
# the terminal screen or window. If this variable is unset or null,
|
||||
# the implementation determines the number of columns, appropriate
|
||||
# for the terminal or window, in an unspecified manner.
|
||||
# When COLUMNS is set, any terminal-width information implied by TERM
|
||||
# is overridden. Users and conforming applications should not set COLUMNS
|
||||
# unless they wish to override the system selection and produce output
|
||||
# unrelated to the terminal characteristics.
|
||||
# See POSIX Base Definitions Section 8.1 Environment Variable Definition
|
||||
|
||||
var w: int
|
||||
var s = getEnv("COLUMNS") # Try standard env var
|
||||
if len(s) > 0 and parseInt(s, w) > 0 and w > 0:
|
||||
return w
|
||||
w = terminalWidthIoctl([0, 1, 2]) # Try standard file descriptors
|
||||
if w > 0: return w
|
||||
var cterm = newString(L_ctermid) #Try controlling tty
|
||||
var cterm = newString(L_ctermid) # Try controlling tty
|
||||
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
|
||||
if fd != -1:
|
||||
w = terminalWidthIoctl([int(fd)])
|
||||
discard close(fd)
|
||||
if w > 0: return w
|
||||
var s = getEnv("COLUMNS") #Try standard env var
|
||||
if len(s) > 0 and parseInt(s, w) > 0 and w > 0:
|
||||
return w
|
||||
return 80 #Finally default to venerable value
|
||||
return 80 # Finally default to venerable value
|
||||
|
||||
proc terminalHeight*(): int =
|
||||
## Returns some reasonable terminal height from either standard file
|
||||
## descriptors, controlling terminal, environment variables or tradition.
|
||||
## Zero is returned if the height could not be determined.
|
||||
|
||||
var h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
|
||||
# POSIX environment variable takes precendence.
|
||||
# _LINES_: This variable shall represent a decimal integer >0 used
|
||||
# to indicate the user's preferred number of lines on a page or
|
||||
# the vertical screen or window size in lines. A line in this case
|
||||
# is a vertical measure large enough to hold the tallest character
|
||||
# in the character set being displayed. If this variable is unset or null,
|
||||
# the implementation determines the number of lines, appropriate
|
||||
# for the terminal or window (size, terminal baud rate, and so on),
|
||||
# in an unspecified manner.
|
||||
# When LINES is set, any terminal-height information implied by TERM
|
||||
# is overridden. Users and conforming applications should not set LINES
|
||||
# unless they wish to override the system selection and produce output
|
||||
# unrelated to the terminal characteristics.
|
||||
# See POSIX Base Definitions Section 8.1 Environment Variable Definition
|
||||
|
||||
var h: int
|
||||
var s = getEnv("LINES") # Try standard env var
|
||||
if len(s) > 0 and parseInt(s, h) > 0 and h > 0:
|
||||
return h
|
||||
h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
|
||||
if h > 0: return h
|
||||
var cterm = newString(L_ctermid) # Try controlling tty
|
||||
var fd = open(ctermid(cstring(cterm)), O_RDONLY)
|
||||
@@ -317,9 +349,6 @@ else:
|
||||
h = terminalHeightIoctl([int(fd)])
|
||||
discard close(fd)
|
||||
if h > 0: return h
|
||||
var s = getEnv("LINES") # Try standard env var
|
||||
if len(s) > 0 and parseInt(s, h) > 0 and h > 0:
|
||||
return h
|
||||
return 0 # Could not determine height
|
||||
|
||||
proc terminalSize*(): tuple[w, h: int] =
|
||||
|
||||
@@ -537,7 +537,7 @@ proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay
|
||||
assertValidDate monthday, month, year
|
||||
# 1970-01-01 is a Thursday, we adjust to the previous Monday
|
||||
let days = toEpochDay(monthday, month, year) - 3
|
||||
let weeks = floorDiv(days, 7)
|
||||
let weeks = floorDiv(days, 7'i64)
|
||||
let wd = days - weeks * 7
|
||||
# The value of d is 0 for a Sunday, 1 for a Monday, 2 for a Tuesday, etc.
|
||||
# so we must correct for the WeekDay type.
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
## This module allows adding hooks to program exit.
|
||||
|
||||
import locks
|
||||
when defined(js) and not defined(nodejs):
|
||||
import std/assertions
|
||||
|
||||
type
|
||||
FunKind = enum kClosure, kNoconv # extend as needed
|
||||
|
||||
@@ -64,10 +64,10 @@ func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs:
|
||||
runnableExamples:
|
||||
doAssert (big("3") + big("2") ** big("66")).wrapToUint(66) == big("3")
|
||||
|
||||
func toNumber*(this: JsBigInt): BiggestInt {.importjs: "Number(#)".} =
|
||||
func toNumber*(this: JsBigInt): int {.importjs: "Number(#)".} =
|
||||
## Does not do any bounds check and may or may not return an inexact representation.
|
||||
runnableExamples:
|
||||
doAssert toNumber(big"2147483647") == 2147483647.BiggestInt
|
||||
doAssert toNumber(big"2147483647") == 2147483647.int
|
||||
|
||||
func `+`*(x, y: JsBigInt): JsBigInt {.importjs: "(# $1 #)".} =
|
||||
runnableExamples:
|
||||
|
||||
@@ -78,19 +78,24 @@ macro getDiscriminants(a: typedesc): seq[string] =
|
||||
let sym = a[1]
|
||||
let t = sym.getTypeImpl
|
||||
let t2 = t[2]
|
||||
doAssert t2.kind == nnkRecList
|
||||
result = newTree(nnkBracket)
|
||||
for ti in t2:
|
||||
if ti.kind == nnkRecCase:
|
||||
let key = ti[0][0]
|
||||
let typ = ti[0][1]
|
||||
result.add newLit key.strVal
|
||||
if result.len > 0:
|
||||
case t2.kind
|
||||
of nnkEmpty: # allow empty objects
|
||||
result = quote do:
|
||||
@`result`
|
||||
seq[string].default
|
||||
of nnkRecList:
|
||||
result = newTree(nnkBracket)
|
||||
for ti in t2:
|
||||
if ti.kind == nnkRecCase:
|
||||
let key = ti[0][0]
|
||||
result.add newLit key.strVal
|
||||
if result.len > 0:
|
||||
result = quote do:
|
||||
@`result`
|
||||
else:
|
||||
result = quote do:
|
||||
seq[string].default
|
||||
else:
|
||||
result = quote do:
|
||||
seq[string].default
|
||||
doAssert false, "unexpected kind: " & $t2.kind
|
||||
|
||||
macro initCaseObject(T: typedesc, fun: untyped): untyped =
|
||||
## does the minimum to construct a valid case object, only initializing
|
||||
|
||||
@@ -79,5 +79,18 @@ when defined(js):
|
||||
assert not "123".toJs.isSafeInteger
|
||||
assert 123.isSafeInteger
|
||||
assert 123.toJs.isSafeInteger
|
||||
assert 9007199254740991.toJs.isSafeInteger
|
||||
assert not 9007199254740992.toJs.isSafeInteger
|
||||
when false:
|
||||
assert 9007199254740991.toJs.isSafeInteger
|
||||
assert not 9007199254740992.toJs.isSafeInteger
|
||||
|
||||
template whenJsNoBigInt64*(no64, yes64): untyped =
|
||||
when defined(js):
|
||||
when compiles(compileOption("jsbigint64")):
|
||||
when compileOption("jsbigint64"):
|
||||
yes64
|
||||
else:
|
||||
no64
|
||||
else:
|
||||
no64
|
||||
else:
|
||||
no64
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
##[
|
||||
`since` is used to emulate older versions of nim stdlib with `--useVersion`,
|
||||
`since` is used to emulate older versions of nim stdlib,
|
||||
see `tuse_version.nim`.
|
||||
|
||||
If a symbol `foo` is added in version `(1,3,5)`, use `{.since: (1.3.5).}`, not
|
||||
|
||||
@@ -62,11 +62,11 @@ proc typeof*(x: untyped; mode = typeOfIter): typedesc {.
|
||||
doAssert type(myFoo()) is string
|
||||
doAssert typeof(myFoo()) is string
|
||||
doAssert typeof(myFoo(), typeOfIter) is string
|
||||
doAssert typeof(myFoo3) is "iterator"
|
||||
doAssert typeof(myFoo3) is iterator
|
||||
|
||||
doAssert typeof(myFoo(), typeOfProc) is float
|
||||
doAssert typeof(0.0, typeOfProc) is float
|
||||
doAssert typeof(myFoo3, typeOfProc) is "iterator"
|
||||
doAssert typeof(myFoo3, typeOfProc) is iterator
|
||||
doAssert not compiles(typeof(myFoo2(), typeOfProc))
|
||||
# this would give: Error: attempting to call routine: 'myFoo2'
|
||||
# since `typeOfProc` expects a typed expression and `myFoo2()` can
|
||||
@@ -1108,6 +1108,11 @@ when defined(nimscript) or not defined(nimSeqsV2):
|
||||
## containers should also call their adding proc `add` for consistency.
|
||||
## Generic code becomes much easier to write if the Nim naming scheme is
|
||||
## respected.
|
||||
## ```
|
||||
## var s: seq[string] = @["test2","test2"]
|
||||
## s.add("test")
|
||||
## assert s == @["test2", "test2", "test"]
|
||||
## ```
|
||||
|
||||
when false: # defined(gcDestructors):
|
||||
proc add*[T](x: var seq[T], y: sink openArray[T]) {.noSideEffect.} =
|
||||
@@ -1142,13 +1147,17 @@ else:
|
||||
## containers should also call their adding proc `add` for consistency.
|
||||
## Generic code becomes much easier to write if the Nim naming scheme is
|
||||
## respected.
|
||||
## ```
|
||||
## var s: seq[string] = @["test2","test2"]
|
||||
## s.add("test") # s <- @[test2, test2, test]
|
||||
## ```
|
||||
##
|
||||
## See also:
|
||||
## * `& proc <#&,seq[T],seq[T]>`_
|
||||
runnableExamples:
|
||||
var a = @["a1", "a2"]
|
||||
a.add(["b1", "b2"])
|
||||
assert a == @["a1", "a2", "b1", "b2"]
|
||||
var c = @["c0", "c1", "c2", "c3"]
|
||||
a.add(c.toOpenArray(1, 2))
|
||||
assert a == @["a1", "a2", "b1", "b2", "c1", "c2"]
|
||||
|
||||
{.noSideEffect.}:
|
||||
let xl = x.len
|
||||
setLen(x, xl + y.len)
|
||||
@@ -2179,39 +2188,30 @@ when notJSnotNims:
|
||||
include "system/profiler"
|
||||
{.pop.}
|
||||
|
||||
proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} =
|
||||
proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
|
||||
## Retrieves the raw proc pointer of the closure `x`. This is
|
||||
## useful for interfacing closures with C/C++, hash compuations, etc.
|
||||
when T is "closure":
|
||||
#[
|
||||
The conversion from function pointer to `void*` is a tricky topic, but this
|
||||
should work at least for c++ >= c++11, e.g. for `dlsym` support.
|
||||
refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
|
||||
https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
|
||||
]#
|
||||
{.emit: """
|
||||
`result` = (void*)`x`.ClP_0;
|
||||
""".}
|
||||
else:
|
||||
{.error: "Only closure function and iterator are allowed!".}
|
||||
#[
|
||||
The conversion from function pointer to `void*` is a tricky topic, but this
|
||||
should work at least for c++ >= c++11, e.g. for `dlsym` support.
|
||||
refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
|
||||
https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
|
||||
]#
|
||||
{.emit: """
|
||||
`result` = (void*)`x`.ClP_0;
|
||||
""".}
|
||||
|
||||
proc rawEnv*[T: proc](x: T): pointer {.noSideEffect, inline.} =
|
||||
proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
|
||||
## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`.
|
||||
when T is "closure":
|
||||
{.emit: """
|
||||
`result` = `x`.ClE_0;
|
||||
""".}
|
||||
else:
|
||||
{.error: "Only closure function and iterator are allowed!".}
|
||||
{.emit: """
|
||||
`result` = `x`.ClE_0;
|
||||
""".}
|
||||
|
||||
proc finished*[T: proc](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
|
||||
proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
|
||||
## It can be used to determine if a first class iterator has finished.
|
||||
when T is "iterator":
|
||||
{.emit: """
|
||||
`result` = ((NI*) `x`.ClE_0)[1] < 0;
|
||||
""".}
|
||||
else:
|
||||
{.error: "Only closure iterator is allowed!".}
|
||||
{.emit: """
|
||||
`result` = ((NI*) `x`.ClE_0)[1] < 0;
|
||||
""".}
|
||||
|
||||
from std/private/digitsutils import addInt
|
||||
export addInt
|
||||
|
||||
@@ -275,10 +275,12 @@ proc genericReset(dest: pointer, mt: PNimType) =
|
||||
|
||||
proc selectBranch(discVal, L: int,
|
||||
a: ptr array[0x7fff, ptr TNimNode]): ptr TNimNode =
|
||||
result = a[L] # a[L] contains the ``else`` part (but may be nil)
|
||||
if discVal <% L:
|
||||
let x = a[discVal]
|
||||
if x != nil: result = x
|
||||
result = a[discVal]
|
||||
if result == nil:
|
||||
result = a[L]
|
||||
else:
|
||||
result = a[L] # a[L] contains the ``else`` part (but may be nil)
|
||||
|
||||
proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
|
||||
a: ptr array[0x7fff, ptr TNimNode],
|
||||
|
||||
@@ -10,7 +10,7 @@ const
|
||||
## is the minor number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 1
|
||||
NimPatch* {.intdefine.}: int = 3
|
||||
## is the patch number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
|
||||
@@ -12,16 +12,10 @@ type
|
||||
## compiler supports. Currently this is `float64`, but it is
|
||||
## platform-dependent in general.
|
||||
|
||||
when defined(js):
|
||||
type BiggestUInt* = uint32
|
||||
BiggestUInt* = uint64
|
||||
## is an alias for the biggest unsigned integer type the Nim compiler
|
||||
## supports. Currently this is `uint32` for JS and `uint64` for other
|
||||
## targets.
|
||||
else:
|
||||
type BiggestUInt* = uint64
|
||||
## is an alias for the biggest unsigned integer type the Nim compiler
|
||||
## supports. Currently this is `uint32` for JS and `uint64` for other
|
||||
## targets.
|
||||
## supports. Currently this is `uint64`, but it is platform-dependent
|
||||
## in general.
|
||||
|
||||
when defined(windows):
|
||||
type
|
||||
|
||||
@@ -448,7 +448,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
|
||||
else:
|
||||
pushCurrentException(e)
|
||||
{.emit: "throw `e`;".}
|
||||
elif defined(nimQuirky) or gotoBasedExceptions:
|
||||
elif quirkyExceptions or gotoBasedExceptions:
|
||||
pushCurrentException(e)
|
||||
when gotoBasedExceptions:
|
||||
inc nimInErrorMode
|
||||
@@ -560,7 +560,7 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
|
||||
when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
|
||||
not defined(js) and not defined(nimscript) and
|
||||
hostOS != "standalone" and hostOS != "any" and not defined(noCppExceptions) and
|
||||
not defined(nimQuirky):
|
||||
not quirkyExceptions:
|
||||
|
||||
type
|
||||
StdException {.importcpp: "std::exception", header: "<exception>".} = object
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
{.push profiler: off.}
|
||||
|
||||
const gotoBasedExceptions = compileOption("exceptions", "goto")
|
||||
const
|
||||
gotoBasedExceptions = compileOption("exceptions", "goto")
|
||||
quirkyExceptions = compileOption("exceptions", "quirky")
|
||||
|
||||
when hostOS == "standalone":
|
||||
include "$projectpath/panicoverride"
|
||||
@@ -21,7 +23,7 @@ when hostOS == "standalone":
|
||||
rawoutput(message)
|
||||
panic(arg)
|
||||
|
||||
elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript):
|
||||
elif (quirkyExceptions or defined(nimPanics)) and not defined(nimscript):
|
||||
import ansi_c
|
||||
|
||||
func name(t: typedesc): string {.magic: "TypeTrait".}
|
||||
|
||||
@@ -451,44 +451,44 @@ proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
return Math.trunc(`a` % `b`);
|
||||
"""
|
||||
|
||||
proc checkOverflowInt64(a: int) {.asmNoStackFrame, compilerproc.} =
|
||||
proc checkOverflowInt64(a: int64) {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
if (`a` > 9223372036854775807 || `a` < -9223372036854775808) `raiseOverflow`();
|
||||
if (`a` > 9223372036854775807n || `a` < -9223372036854775808n) `raiseOverflow`();
|
||||
"""
|
||||
|
||||
proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
proc addInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` + `b`;
|
||||
`checkOverflowInt64`(result);
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
proc subInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` - `b`;
|
||||
`checkOverflowInt64`(result);
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
proc mulInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
var result = `a` * `b`;
|
||||
`checkOverflowInt64`(result);
|
||||
return result;
|
||||
"""
|
||||
|
||||
proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
proc divInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) `raiseDivByZero`();
|
||||
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
|
||||
return Math.trunc(`a` / `b`);
|
||||
if (`b` == 0n) `raiseDivByZero`();
|
||||
if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
|
||||
return `a` / `b`;
|
||||
"""
|
||||
|
||||
proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
|
||||
proc modInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
|
||||
asm """
|
||||
if (`b` == 0) `raiseDivByZero`();
|
||||
if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
|
||||
return Math.trunc(`a` % `b`);
|
||||
if (`b` == 0n) `raiseDivByZero`();
|
||||
if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
|
||||
return `a` % `b`;
|
||||
"""
|
||||
|
||||
proc negInt(a: int): int {.compilerproc.} =
|
||||
|
||||
@@ -12,6 +12,8 @@ when defined(nimPreviewSlimSystem):
|
||||
import std/formatfloat
|
||||
|
||||
proc reprInt(x: int64): string {.compilerproc.} = $x
|
||||
proc reprInt(x: uint64): string {.compilerproc.} = $x
|
||||
proc reprInt(x: int): string {.compilerproc.} = $x
|
||||
proc reprFloat(x: float): string {.compilerproc.} = $x
|
||||
|
||||
proc reprPointer(p: pointer): string {.compilerproc.} =
|
||||
@@ -192,8 +194,12 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
|
||||
return
|
||||
dec(cl.recDepth)
|
||||
case typ.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
of tyInt..tyInt32, tyUInt..tyUInt32:
|
||||
add(result, reprInt(cast[int](p)))
|
||||
of tyInt64:
|
||||
add(result, reprInt(cast[int64](p)))
|
||||
of tyUInt64:
|
||||
add(result, reprInt(cast[uint64](p)))
|
||||
of tyChar:
|
||||
add(result, reprChar(cast[char](p)))
|
||||
of tyBool:
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
<li><a class="reference" href="#fn2" title="fn2()">fn2()</a></li>
|
||||
<li><a class="reference" href="#fn2%2Cint" title="fn2(x: int)">fn2(x: int)</a></li>
|
||||
<li><a class="reference" href="#fn2%2Cint%2Cfloat" title="fn2(x: int; y: float)">fn2(x: int; y: float)</a></li>
|
||||
<li><a class="reference" href="#fn2%2Cint%2Cfloat%2Cfloat" title="fn2(x: int; y: float; z: float)">fn2(x: int; y: float; z: float)</a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="simple nested-toc-section">fn3
|
||||
@@ -215,7 +216,7 @@
|
||||
<ol class="simple"><li>Other case value</li>
|
||||
<li>Second case.</li>
|
||||
</ol>
|
||||
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
|
||||
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
|
||||
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
@@ -229,7 +230,7 @@
|
||||
<p>Group ref. with capital letters works: <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fN11</a> or <a class="reference internal nimdoc" title="proc fN11 (2 overloads)" href="#fN11-procs-all">fn11</a> </p>
|
||||
Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">[]</a> is the same as <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`(G[T])</a> because there are no overloads. The full form: <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href="#[],G[T]">proc `[]`*[T](x: G[T]): T</a>Ref. <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">[]=</a> aka <a class="reference internal nimdoc" title="proc `[]=`[T](a: var G[T]; index: int; value: T)" href="#[]=,G[T],int,T">`[]=`(G[T], int, T)</a>.Ref. <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">$</a> aka <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc $</a> or <a class="reference internal nimdoc" title="proc $ (2 overloads)" href="#$-procs-all">proc `$`</a>.Ref. <a class="reference internal nimdoc" title="proc `$`[T](a: ref SomeType): string" href="#$,ref.SomeType">$(a: ref SomeType)</a>.Ref. <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">foo_bar</a> aka <a class="reference internal nimdoc" title="iterator fooBar(a: seq[SomeType]): int" href="#fooBar.i,seq[SomeType]">iterator foo_bar_</a>.Ref. <a class="reference internal nimdoc" title="proc fn[T; U, V: SomeFloat]()" href="#fn">fn[T; U,V: SomeFloat]()</a>.Ref. <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">'big</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">func `'big`</a> or <a class="reference internal nimdoc" title="proc `'big`(a: string): SomeType" href="#'big,string">`'big`(string)</a>.
|
||||
<h1><a class="toc-backref" id="pandoc-markdown" href="#pandoc-markdown">Pandoc Markdown</a></h1><p>Now repeat all the auto links of above in Pandoc Markdown Syntax.</p>
|
||||
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (3 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
|
||||
<p>Ref group <a class="reference internal nimdoc" title="proc fn2 (4 overloads)" href="#fn2-procs-all">fn2</a> or specific function like <a class="reference internal nimdoc" title="proc fn2()" href="#fn2">fn2()</a> or <a class="reference internal nimdoc" title="proc fn2(x: int)" href="#fn2,int">fn2( int )</a> or <a class="reference internal nimdoc" title="proc fn2(x: int; y: float)" href="#fn2,int,float">fn2(int, float)</a>.</p>
|
||||
<p>Ref generics like this: <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
cmp: proc (x: T; y: K): int {.closure.}): int" href="#binarySearch,openArray[T],K,proc(T,K)">binarySearch(openArray[T], K, proc (T, K))</a> or <a class="reference internal nimdoc" title="proc binarySearch[T, K](a: openArray[T]; key: K;
|
||||
@@ -392,6 +393,14 @@ Ref. <a class="reference internal nimdoc" title="proc `[]`[T](x: G[T]): T" href=
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</div>
|
||||
<div id="fn2,int,float,float">
|
||||
<dt><pre><span class="Keyword">proc</span> <a href="#fn2%2Cint%2Cfloat%2Cfloat"><span class="Identifier">fn2</span></a><span class="Other">(</span><span class="Identifier">x</span><span class="Other">:</span> <span class="Identifier">int</span><span class="Other">;</span> <span class="Identifier">y</span><span class="Other">:</span> <span class="Identifier">float</span><span class="Other">;</span> <span class="Identifier">z</span><span class="Other">:</span> <span class="Identifier">float</span><span class="Other">)</span> {.<span><span class="Other pragmadots">...</span></span><span class="pragmawrap"><span class="Identifier">raises</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">tags</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span><span class="Other">,</span> <span class="Identifier">forbids</span><span class="Other">:</span> <span class="Other">[</span><span class="Other">]</span></span>.}</pre></dt>
|
||||
<dd>
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
nimTitle utils subdir/subdir_b/utils.html module subdir/subdir_b/utils 0
|
||||
nim funWithGenerics subdir/subdir_b/utils.html#funWithGenerics,T,U proc funWithGenerics[T, U: SomeFloat](a: T; b: U) 1
|
||||
nim fn2 subdir/subdir_b/utils.html#fn2,int,float,float proc fn2(x: int; y: float; z: float) 5
|
||||
nim enumValueA subdir/subdir_b/utils.html#enumValueA SomeType.enumValueA 45
|
||||
nim enumValueB subdir/subdir_b/utils.html#enumValueB SomeType.enumValueB 45
|
||||
nim enumValueC subdir/subdir_b/utils.html#enumValueC SomeType.enumValueC 45
|
||||
@@ -34,7 +35,7 @@ nim fn subdir/subdir_b/utils.html#fn proc fn[T; U, V: SomeFloat]() 160
|
||||
nim `'big` subdir/subdir_b/utils.html#'big,string proc `'big`(a: string): SomeType 164
|
||||
nimgrp $ subdir/subdir_b/utils.html#$-procs-all proc 148
|
||||
nimgrp fn11 subdir/subdir_b/utils.html#fN11-procs-all proc 85
|
||||
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 57
|
||||
nimgrp fn2 subdir/subdir_b/utils.html#fn2-procs-all proc 5
|
||||
nimgrp f subdir/subdir_b/utils.html#f-procs-all proc 130
|
||||
heading This is now a header subdir/subdir_b/utils.html#this-is-now-a-header This is now a header 0
|
||||
heading Next header subdir/subdir_b/utils.html#this-is-now-a-header-next-header Next header 0
|
||||
|
||||
@@ -175,6 +175,8 @@
|
||||
data-doc-search-tag="utils: proc fn2(x: int)" href="subdir/subdir_b/utils.html#fn2%2Cint">utils: proc fn2(x: int)</a></li>
|
||||
<li><a class="reference external"
|
||||
data-doc-search-tag="utils: proc fn2(x: int; y: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat">utils: proc fn2(x: int; y: float)</a></li>
|
||||
<li><a class="reference external"
|
||||
data-doc-search-tag="utils: proc fn2(x: int; y: float; z: float)" href="subdir/subdir_b/utils.html#fn2%2Cint%2Cfloat%2Cfloat">utils: proc fn2(x: int; y: float; z: float)</a></li>
|
||||
</ul></dd>
|
||||
<dt><a name="fn3" href="#fn3"><span>fn3:</span></a></dt><dd><ul class="simple">
|
||||
<li><a class="reference external"
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
proc funWithGenerics*[T, U: SomeFloat](a: T, b: U) = discard
|
||||
|
||||
# We check that presence of overloaded `fn2` here does not break
|
||||
# referencing in the "parent" file (the one that includes this one)
|
||||
proc fn2*(x: int, y: float, z: float) =
|
||||
discard
|
||||
|
||||
@@ -135,7 +135,7 @@ pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim"
|
||||
pkg "pylib"
|
||||
pkg "rbtree"
|
||||
pkg "react", "nimble example"
|
||||
pkg "regex", "nim c src/regex", url = "https://github.com/nim-lang/nim-regex"
|
||||
pkg "regex", "nim c src/regex"
|
||||
pkg "result", "nim c -r result.nim"
|
||||
pkg "RollingHash", "nim c -r tests/test_cyclichash.nim"
|
||||
pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim"
|
||||
|
||||
@@ -222,7 +222,10 @@ proc extractErrorMsg(s: string; i: int; line: var int; col: var int; spec: var T
|
||||
|
||||
while result < s.len-1:
|
||||
if s[result] == '\n':
|
||||
msg.add '\n'
|
||||
if result > 0 and s[result - 1] == '\r':
|
||||
msg[^1] = '\n'
|
||||
else:
|
||||
msg.add '\n'
|
||||
inc result
|
||||
inc line
|
||||
col = 1
|
||||
|
||||
30
tests/arc/t19364.nim
Normal file
30
tests/arc/t19364.nim
Normal file
@@ -0,0 +1,30 @@
|
||||
discard """
|
||||
cmd: '''nim c --gc:arc --expandArc:fooLeaks $file'''
|
||||
nimout: '''
|
||||
--expandArc: fooLeaks
|
||||
|
||||
var
|
||||
tmpTuple_cursor
|
||||
a_cursor
|
||||
b_cursor
|
||||
c_cursor
|
||||
tmpTuple_cursor = refTuple
|
||||
a_cursor = tmpTuple_cursor[0]
|
||||
b_cursor = tmpTuple_cursor[1]
|
||||
c_cursor = tmpTuple_cursor[2]
|
||||
-- end of expandArc ------------------------
|
||||
'''
|
||||
"""
|
||||
|
||||
func fooLeaks(refTuple: tuple[a,
|
||||
b,
|
||||
c: seq[float]]): float =
|
||||
let (a, b, c) = refTuple
|
||||
|
||||
let refset = (a: newSeq[float](25_000_000),
|
||||
b: newSeq[float](25_000_000),
|
||||
c: newSeq[float](25_000_000))
|
||||
|
||||
var res = newSeq[float](1_000_000)
|
||||
for i in 0 .. res.high:
|
||||
res[i] = fooLeaks(refset)
|
||||
41
tests/arc/taliased_reassign.nim
Normal file
41
tests/arc/taliased_reassign.nim
Normal file
@@ -0,0 +1,41 @@
|
||||
discard """
|
||||
matrix: "--mm:orc"
|
||||
"""
|
||||
|
||||
# bug #20993
|
||||
|
||||
type
|
||||
Dual[int] = object # must be generic (even if fully specified)
|
||||
p: int
|
||||
proc D(p: int): Dual[int] = Dual[int](p: p)
|
||||
proc `+`(x: Dual[int], y: Dual[int]): Dual[int] = D(x.p + y.p)
|
||||
|
||||
type
|
||||
Tensor[T] = object
|
||||
buf: seq[T]
|
||||
proc newTensor*[T](s: int): Tensor[T] = Tensor[T](buf: newSeq[T](s))
|
||||
proc `[]`*[T](t: Tensor[T], idx: int): T = t.buf[idx]
|
||||
proc `[]=`*[T](t: var Tensor[T], idx: int, val: T) = t.buf[idx] = val
|
||||
|
||||
proc `+.`[T](t1, t2: Tensor[T]): Tensor[T] =
|
||||
let n = t1.buf.len
|
||||
result = newTensor[T](n)
|
||||
for i in 0 ..< n:
|
||||
result[i] = t1[i] + t2[i]
|
||||
|
||||
proc toTensor*[T](a: sink seq[T]): Tensor[T] =
|
||||
## This breaks it: Using `T` instead makes it work
|
||||
type U = typeof(a[0])
|
||||
var t: Tensor[U] # Tensor[T] works
|
||||
t.buf = a
|
||||
result = t
|
||||
|
||||
proc loss() =
|
||||
var B = toTensor(@[D(123)])
|
||||
let a = toTensor(@[D(-10)])
|
||||
B = B +. a
|
||||
doAssert B[0].p == 113, "I want to be 113, but I am " & $B[0].p
|
||||
|
||||
loss()
|
||||
|
||||
|
||||
@@ -597,3 +597,20 @@ block: # bug #19857
|
||||
let res = v.toF()
|
||||
|
||||
foo()
|
||||
|
||||
import std/options
|
||||
|
||||
# bug #21592
|
||||
type Event* = object
|
||||
code*: string
|
||||
|
||||
type App* = ref object of RootObj
|
||||
id*: string
|
||||
|
||||
method process*(self: App): Option[Event] {.base.} =
|
||||
raise Exception.new_exception("not impl")
|
||||
|
||||
# bug #21617
|
||||
type Test2 = ref object of RootObj
|
||||
|
||||
method bug(t: Test2): seq[float] {.base.} = discard
|
||||
|
||||
39
tests/ccgbugs/tbug21505.nim
Normal file
39
tests/ccgbugs/tbug21505.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
discard """
|
||||
action: "compile"
|
||||
targets: "cpp"
|
||||
cmd: "nim cpp $file"
|
||||
"""
|
||||
|
||||
# see #21505: ensure compilation of imported C++ objects with explicit constructors while retaining default initialization through codegen changes due to #21279
|
||||
|
||||
{.emit:"""/*TYPESECTION*/
|
||||
|
||||
struct ExplObj
|
||||
{
|
||||
explicit ExplObj(int bar = 0) {}
|
||||
};
|
||||
|
||||
struct BareObj
|
||||
{
|
||||
BareObj() {}
|
||||
};
|
||||
|
||||
""".}
|
||||
|
||||
type
|
||||
ExplObj {.importcpp.} = object
|
||||
BareObj {.importcpp.} = object
|
||||
|
||||
type
|
||||
Composer = object
|
||||
explObj: ExplObj
|
||||
bareObj: BareObj
|
||||
|
||||
proc foo =
|
||||
var composer1 {.used.}: Composer
|
||||
let composer2 {.used.} = Composer()
|
||||
|
||||
var composer1 {.used.}: Composer
|
||||
let composer2 {.used.} = Composer()
|
||||
|
||||
foo()
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "When mixing named fields and unnamed fields, every field needs to be initialized in order"
|
||||
errormsg: "incorrect object construction syntax"
|
||||
file: "t5965_1.nim"
|
||||
line: 10
|
||||
"""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
errormsg: "The object construction is given more fields than required"
|
||||
errormsg: "incorrect object construction syntax"
|
||||
file: "t5965_2.nim"
|
||||
line: 10
|
||||
"""
|
||||
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
exitcode: "1"
|
||||
output: '''
|
||||
t14444.nim(13) t14444
|
||||
fatal.nim(51) sysFatal
|
||||
fatal.nim(53) sysFatal
|
||||
Error: unhandled exception: index out of bounds, the container is empty [IndexDefect]
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ Expression: int(inNanoseconds(t2 - t1)) / 100.5
|
||||
[1] int(inNanoseconds(t2 - t1)): int
|
||||
[2] 100.5: float64
|
||||
|
||||
Expected one of (first mismatch at position [#]):
|
||||
Expected one of (first mismatch at [position]):
|
||||
[1] proc `/`(x, y: float): float
|
||||
[1] proc `/`(x, y: float32): float32
|
||||
[2] proc `/`(x, y: int): float
|
||||
@@ -20,4 +20,4 @@ from times import inNanoseconds
|
||||
let t1 = getMonotime()
|
||||
let result = 1 + 2
|
||||
let t2 = getMonotime()
|
||||
echo "Elapsed: ", (t2 - t1).inNanoseconds.int / 100.5
|
||||
echo "Elapsed: ", (t2 - t1).inNanoseconds.int / 100.5
|
||||
|
||||
@@ -2,24 +2,10 @@ type
|
||||
Noice* = object
|
||||
hidden: int
|
||||
|
||||
Ciao* = object
|
||||
hidden1: int
|
||||
hidden2: int
|
||||
|
||||
Gull* = ref object
|
||||
hidden1: int
|
||||
field*: int
|
||||
hidden2: int
|
||||
field2*: int
|
||||
|
||||
|
||||
template jjj*(): Noice =
|
||||
var x = 7
|
||||
template jjj*: Noice =
|
||||
Noice(hidden: 15)
|
||||
|
||||
template said*(): Ciao =
|
||||
var x = 7
|
||||
Ciao(hidden1: 15 + x, 1)
|
||||
type Opt* = object
|
||||
o: int
|
||||
|
||||
proc foo*: Gull =
|
||||
result = Gull(1, 2, 3, 4)
|
||||
template none*(O: type Opt): Opt = Opt(o: 0)
|
||||
|
||||
@@ -3,19 +3,11 @@ import m3770
|
||||
|
||||
doAssert $jjj() == "(hidden: 15)" # works
|
||||
|
||||
doAssert $said() == "(hidden1: 22, hidden2: 1)"
|
||||
|
||||
proc someGeneric(_: type) =
|
||||
doAssert $jjj() == "(hidden: 15)" # fails: "Error: the field 'hidden' is not accessible."
|
||||
when false: # todo somehow make it work?
|
||||
doAssert $said() == "(hidden1: 22, hidden2: 1)"
|
||||
|
||||
someGeneric(int)
|
||||
|
||||
doAssert $(foo()[]) == "(hidden1: 1, field: 2, hidden2: 3, field2: 4)"
|
||||
|
||||
proc bar() =
|
||||
var s = Gull(13, 14)
|
||||
doAssert $(s[]) == "(hidden1: 0, field: 13, hidden2: 0, field2: 14)"
|
||||
|
||||
bar()
|
||||
# bug #20900
|
||||
proc c(y: int | int, w: Opt = Opt.none) = discard
|
||||
c(0)
|
||||
|
||||
54
tests/iter/tgeniteratorinblock.nim
Normal file
54
tests/iter/tgeniteratorinblock.nim
Normal file
@@ -0,0 +1,54 @@
|
||||
discard """
|
||||
output: '''30
|
||||
60
|
||||
90
|
||||
150
|
||||
180
|
||||
210
|
||||
240
|
||||
60
|
||||
180
|
||||
240
|
||||
[60, 180, 240]
|
||||
[60, 180]'''
|
||||
"""
|
||||
import std/enumerate
|
||||
|
||||
template map[T; Y](i: iterable[T], fn: proc(x: T): Y): untyped =
|
||||
iterator internal(): Y {.gensym.} =
|
||||
for it in i:
|
||||
yield fn(it)
|
||||
internal()
|
||||
|
||||
template filter[T](i: iterable[T], fn: proc(x: T): bool): untyped =
|
||||
iterator internal(): T {.gensym.} =
|
||||
for it in i:
|
||||
if fn(it):
|
||||
yield it
|
||||
internal()
|
||||
|
||||
template group[T](i: iterable[T], amount: static int): untyped =
|
||||
iterator internal(): array[amount, T] {.gensym.} =
|
||||
var val: array[amount, T]
|
||||
for ind, it in enumerate i:
|
||||
val[ind mod amount] = it
|
||||
if ind mod amount == amount - 1:
|
||||
yield val
|
||||
internal()
|
||||
|
||||
var a = [10, 20, 30, 50, 60, 70, 80]
|
||||
|
||||
proc mapFn(x: int): int = x * 3
|
||||
proc filterFn(x: int): bool = x mod 20 == 0
|
||||
|
||||
for x in a.items.map(mapFn):
|
||||
echo x
|
||||
|
||||
for y in a.items.map(mapFn).filter(filterFn):
|
||||
echo y
|
||||
|
||||
for y in a.items.map(mapFn).filter(filterFn).group(3):
|
||||
echo y
|
||||
|
||||
for y in a.items.map(mapFn).filter(filterFn).group(2):
|
||||
echo y
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
matrix: "--jsbigint64:off; --jsbigint64:on"
|
||||
"""
|
||||
|
||||
import std/private/jsutils
|
||||
|
||||
proc main()=
|
||||
@@ -5,9 +9,10 @@ proc main()=
|
||||
doAssert fn(array[2, int8].default) == "Int8Array"
|
||||
doAssert fn(array[2, uint8].default) == "Uint8Array"
|
||||
doAssert fn(array[2, byte].default) == "Uint8Array"
|
||||
# doAssert fn(array[2, char].default) == "Uint8Array" # xxx fails; bug?
|
||||
doAssert fn(array[2, uint64].default) == "Array"
|
||||
# pending https://github.com/nim-lang/RFCs/issues/187 maybe use `BigUint64Array`
|
||||
doAssert fn(array[2, char].default) == "Uint8Array"
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
doAssert fn(array[2, uint64].default) == "BigUint64Array"
|
||||
doAssert fn([1'u8]) == "Uint8Array"
|
||||
doAssert fn([1'u16]) == "Uint16Array"
|
||||
doAssert fn([byte(1)]) == "Uint8Array"
|
||||
|
||||
@@ -5,6 +5,7 @@ discard """
|
||||
# Test numeric literals and handling of minus symbol
|
||||
|
||||
import std/[macros, strutils]
|
||||
import std/private/jsutils
|
||||
|
||||
import mlexerutils
|
||||
|
||||
@@ -60,7 +61,8 @@ template main =
|
||||
doAssert -2147483648'i32 == int32.low
|
||||
when int.sizeof > 4:
|
||||
doAssert -9223372036854775808 == int.low
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
doAssert -9223372036854775808 == int64.low
|
||||
|
||||
block: # check when a minus (-) is an unary op
|
||||
|
||||
22
tests/macros/t15691.nim
Normal file
22
tests/macros/t15691.nim
Normal file
@@ -0,0 +1,22 @@
|
||||
discard """
|
||||
action: compile
|
||||
"""
|
||||
|
||||
import std/macros
|
||||
|
||||
macro simplifiedExpandMacros(body: typed): untyped =
|
||||
result = body
|
||||
|
||||
simplifiedExpandMacros:
|
||||
proc testProc() = discard
|
||||
|
||||
simplifiedExpandMacros:
|
||||
template testTemplate(): untyped = discard
|
||||
|
||||
# Error: illformed AST: macro testMacro(): untyped =
|
||||
simplifiedExpandMacros:
|
||||
macro testMacro(): untyped = discard
|
||||
|
||||
# Error: illformed AST: converter testConverter(x: int): float =
|
||||
simplifiedExpandMacros:
|
||||
converter testConverter(x: int): float = discard
|
||||
13
tests/macros/t21593.nim
Normal file
13
tests/macros/t21593.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
discard """
|
||||
nimout: '''
|
||||
StmtList
|
||||
UIntLit 18446744073709551615
|
||||
IntLit -1'''
|
||||
"""
|
||||
|
||||
import macros
|
||||
|
||||
dumpTree:
|
||||
0xFFFFFFFF_FFFFFFFF'u
|
||||
0xFFFFFFFF_FFFFFFFF
|
||||
|
||||
@@ -8,7 +8,9 @@ for i, d in pairs(data):
|
||||
discard
|
||||
for i, (x, y) in pairs(data):
|
||||
discard
|
||||
var (a, b) = (1, 2)
|
||||
var
|
||||
a = 1
|
||||
b = 2
|
||||
|
||||
var data = @[(1, "one"), (2, "two")]
|
||||
for (i, d) in pairs(data):
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
discard """
|
||||
action: reject
|
||||
nimout: '''
|
||||
t11634.nim(20, 7) Error: cannot destructure to compile time variable
|
||||
'''
|
||||
"""
|
||||
|
||||
type Foo = ref object
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
discard """
|
||||
matrix: "; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
|
||||
output: '''
|
||||
0 0
|
||||
0 0
|
||||
@@ -6,6 +7,8 @@ Success'''
|
||||
"""
|
||||
# Test the different integer operations
|
||||
|
||||
import std/private/jsutils
|
||||
|
||||
var testNumber = 0
|
||||
|
||||
template test(opr, a, b, c: untyped): untyped =
|
||||
@@ -23,28 +26,37 @@ template test(opr, a, b, c: untyped): untyped =
|
||||
|
||||
test(`+`, 12'i8, -13'i16, -1'i16)
|
||||
test(`shl`, 0b11, 0b100, 0b110000)
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
test(`shl`, 0b11'i64, 0b100'i64, 0b110000'i64)
|
||||
when not defined(js):
|
||||
# mixed type shr needlessly complicates codegen with bigint
|
||||
# and thus is not yet supported in JS for 64 bit ints
|
||||
test(`shl`, 0b11'i32, 0b100'i64, 0b110000'i64)
|
||||
test(`shl`, 0b11'i32, 0b100'i32, 0b110000'i32)
|
||||
|
||||
test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
|
||||
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
|
||||
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64)
|
||||
test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16)
|
||||
test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8)
|
||||
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
|
||||
test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32)
|
||||
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
|
||||
test(`shl`, 0xffff'i16, 0x4'i16, 0xfff0'i16)
|
||||
test(`shl`, 0xff'i8, 0x4'i8, 0xf0'i8)
|
||||
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
test(`shl`, 0xffffffff'i64, 0x4'i64, 0xffffffff0'i64)
|
||||
test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32)
|
||||
|
||||
|
||||
15
tests/modules/tmodulesymtype.nim
Normal file
15
tests/modules/tmodulesymtype.nim
Normal file
@@ -0,0 +1,15 @@
|
||||
discard """
|
||||
cmd: "nim check $file"
|
||||
"""
|
||||
|
||||
# bug #19225
|
||||
import std/sequtils
|
||||
sequtils #[tt.Error
|
||||
^ expression has no type: sequtils]#
|
||||
proc foo() =
|
||||
block: #[tt.Error
|
||||
^ expression has no type: block:
|
||||
sequtils]#
|
||||
sequtils
|
||||
|
||||
foo()
|
||||
@@ -1,3 +1,15 @@
|
||||
discard """
|
||||
cmd: "nim check $file"
|
||||
errormsg: ""
|
||||
nimout: '''
|
||||
t17437.nim(20, 16) Error: undeclared identifier: 'x'
|
||||
t17437.nim(20, 16) Error: expression 'x' has no type (or is ambiguous)
|
||||
t17437.nim(20, 19) Error: incorrect object construction syntax
|
||||
t17437.nim(20, 19) Error: incorrect object construction syntax
|
||||
t17437.nim(20, 12) Error: expression '' has no type (or is ambiguous)
|
||||
'''
|
||||
"""
|
||||
|
||||
# bug #17437 invalid object construction should result in error
|
||||
|
||||
type
|
||||
@@ -5,8 +17,6 @@ type
|
||||
x, y: int
|
||||
|
||||
proc m =
|
||||
var x = 12
|
||||
var y = 1
|
||||
var v = V(x: x, y)
|
||||
|
||||
m()
|
||||
|
||||
15
tests/objects/t20972.nim
Normal file
15
tests/objects/t20972.nim
Normal file
@@ -0,0 +1,15 @@
|
||||
discard """
|
||||
matrix: "--mm:refc -d:release; --mm:orc -d:release"
|
||||
"""
|
||||
|
||||
{.passC: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -Wall -Wextra -pedantic -flto".}
|
||||
{.passL: "-fsanitize=undefined -fsanitize-undefined-trap-on-error -flto".}
|
||||
|
||||
# bug #20972
|
||||
type ForkedEpochInfo = object
|
||||
case kind: bool
|
||||
of true, false: discard
|
||||
var info = ForkedEpochInfo(kind: true)
|
||||
doAssert info.kind
|
||||
info.kind = false
|
||||
doAssert not info.kind
|
||||
3
tests/parser/t19430.nim
Normal file
3
tests/parser/t19430.nim
Normal file
@@ -0,0 +1,3 @@
|
||||
let x = proc() = ## abc
|
||||
let y = 3 #[tt.Error
|
||||
^ invalid indentation]#
|
||||
@@ -27,3 +27,51 @@ proc main() =
|
||||
|
||||
main()
|
||||
main2()
|
||||
|
||||
block: # nested unpacking
|
||||
block: # simple let
|
||||
let (a, (b, c), d) = (1, (2, 3), 4)
|
||||
doAssert (a, b, c, d) == (1, 2, 3, 4)
|
||||
let foo = (a, (b, c), d)
|
||||
let (a2, (b2, c2), d2) = foo
|
||||
doAssert (a, b, c, d) == (a2, b2, c2, d2)
|
||||
|
||||
block: # var and assignment
|
||||
var (x, (y, z), t) = ('a', (true, @[123]), "abc")
|
||||
doAssert (x, y, z, t) == ('a', true, @[123], "abc")
|
||||
(x, (y, z), t) = ('b', (false, @[456]), "def")
|
||||
doAssert (x, y, z, t) == ('b', false, @[456], "def")
|
||||
|
||||
block: # very nested
|
||||
let (_, (_, (_, (_, (_, a))))) = (1, (2, (3, (4, (5, 6)))))
|
||||
doAssert a == 6
|
||||
|
||||
block: # const
|
||||
const (a, (b, c), d) = (1, (2, 3), 4)
|
||||
doAssert (a, b, c, d) == (1, 2, 3, 4)
|
||||
const foo = (a, (b, c), d)
|
||||
const (a2, (b2, c2), d2) = foo
|
||||
doAssert (a, b, c, d) == (a2, b2, c2, d2)
|
||||
|
||||
block: # evaluation semantics preserved between literal and not literal
|
||||
var s: seq[string]
|
||||
block: # literal
|
||||
let (a, (b, c), d) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
|
||||
doAssert (a, b, c, d) == (1, 2, 3, 4)
|
||||
doAssert s == @["a", "b", "c", "d"]
|
||||
block: # underscore
|
||||
s = @[]
|
||||
let (a, (_, c), _) = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
|
||||
doAssert (a, c) == (1, 3)
|
||||
doAssert s == @["a", "b", "c", "d"]
|
||||
block: # temp
|
||||
s = @[]
|
||||
let foo = ((s.add("a"); 1), ((s.add("b"); 2), (s.add("c"); 3)), (s.add("d"); 4))
|
||||
let (a, (b, c), d) = foo
|
||||
doAssert (a, b, c, d) == (1, 2, 3, 4)
|
||||
doAssert s == @["a", "b", "c", "d"]
|
||||
|
||||
block: # unary assignment unpacking
|
||||
var a: int
|
||||
(a,) = (1,)
|
||||
doAssert a == 1
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
# bug #15949
|
||||
# bug #15949 and RFC #480
|
||||
|
||||
discard """
|
||||
errormsg: "parameter 'a' requires a type"
|
||||
nimout: '''
|
||||
t15949.nim(20, 14) Error: parameter 'a' requires a type'''
|
||||
"""
|
||||
proc procWarn(a, b = 1): (int, int) = (a, b) #[tt.Warning
|
||||
^ a, b all have default value '1', this may be unintentional, either use ';' (semicolon) or explicitly write each default value [ImplicitDefaultValue]]#
|
||||
|
||||
|
||||
# line 10
|
||||
proc procGood(a, b = 1): (int, int) = (a, b)
|
||||
proc procGood(a = 1, b = 1): (int, int) = (a, b)
|
||||
|
||||
doAssert procGood() == (1, 1)
|
||||
doAssert procGood(b = 3) == (1, 3)
|
||||
@@ -17,4 +12,5 @@ doAssert procGood(a = 5, b = 6) == (5, 6)
|
||||
|
||||
# The type (and default value propagation breaks in the below example
|
||||
# as semicolon is used instead of comma.
|
||||
proc procBad(a; b = 1): (int, int) = (a, b)
|
||||
proc procBad(a; b = 1): (int, int) = (a, b) #[tt.Error
|
||||
^ parameter 'a' requires a type]#
|
||||
|
||||
@@ -79,6 +79,19 @@ proc test() =
|
||||
proc foo(_: int) =
|
||||
let a = _
|
||||
doAssert not compiles(main())
|
||||
|
||||
block: # generic params
|
||||
doAssert not (compiles do:
|
||||
proc foo[_](t: typedesc[_]): seq[_] = @[default(_)]
|
||||
doAssert foo[int]() == 0)
|
||||
|
||||
block:
|
||||
proc foo[_, _](): int = 123
|
||||
doAssert foo[int, bool]() == 123
|
||||
|
||||
block:
|
||||
proc foo[T; U](_: typedesc[T]; _: typedesc[U]): (T, U) = (default(T), default(U))
|
||||
doAssert foo(int, bool) == (0, false)
|
||||
|
||||
proc closureTest() =
|
||||
var x = 0
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
type
|
||||
Standard* = object
|
||||
name: string
|
||||
id*: int
|
||||
owner*: string
|
||||
|
||||
Color1* = enum
|
||||
Red, Blue, Green
|
||||
|
||||
Case1* = object
|
||||
name*: string
|
||||
id*: int
|
||||
color*: Color1
|
||||
owner: string
|
||||
|
||||
|
||||
## inplace object construction works
|
||||
doAssert Standard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
|
||||
|
||||
proc initStandard*(name: string, id: int, owner: string): Standard =
|
||||
Standard(name, id, owner)
|
||||
|
||||
## It works in the procs
|
||||
doAssert initStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
|
||||
static: doAssert initStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
|
||||
|
||||
template toStandard*(name: string, id: int, owner: string): Standard =
|
||||
Standard(name, id, owner)
|
||||
|
||||
## It works in the procs
|
||||
doAssert toStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
|
||||
static: doAssert toStandard("Tree", 1, "sky") == Standard(name: "Tree", id: 1, owner: "sky")
|
||||
|
||||
proc initColorRed*(name: string = "red", id: int = 1314, owner: string): Case1 =
|
||||
result = Case1(name, id, Red, owner)
|
||||
|
||||
doAssert Case1("red", 1314, color: Red, owner: "unknown") == Case1("red", 1314, color: Red, "unknown")
|
||||
doAssert Case1("red", 1314, Red, owner: "unknown") == Case1("red", 1314, Red, "unknown")
|
||||
doAssert initColorRed(owner = "unknown") == Case1("red", id: 1314, Red, "unknown")
|
||||
@@ -1,90 +0,0 @@
|
||||
import mobjectconstr_unnamed
|
||||
|
||||
type
|
||||
Vector = object
|
||||
a: int = 999
|
||||
b, c: int
|
||||
|
||||
block: # positional construction
|
||||
## It specifies all the unnamed fields
|
||||
var x = Vector(1, 2, 3)
|
||||
doAssert x.b == 2
|
||||
|
||||
block:
|
||||
## unnamed fields can be mixed with named fields
|
||||
block:
|
||||
var x = Vector(a: 1, 2, 3)
|
||||
doAssert x.c == 3
|
||||
|
||||
block:
|
||||
var x = Vector(1, b: 2, 3)
|
||||
doAssert x.c == 3
|
||||
|
||||
block:
|
||||
var x = Vector(1, 2, c: 3)
|
||||
doAssert x.c == 3
|
||||
|
||||
block:
|
||||
## Object variants support unnamed fields for tags, which should be known at the compile time.
|
||||
type
|
||||
Color = enum
|
||||
Red, Blue, Yellow
|
||||
Factor = object
|
||||
id: int
|
||||
case flag: Color
|
||||
of Red:
|
||||
num: int
|
||||
of Blue, Yellow:
|
||||
done: bool
|
||||
name: string
|
||||
|
||||
block:
|
||||
var x = Factor(1, Red, 2, "1314")
|
||||
doAssert x.num == 2
|
||||
|
||||
block:
|
||||
var x = Factor(1, Blue, true, "1314")
|
||||
doAssert x.done == true
|
||||
|
||||
block:
|
||||
var x = Factor(1, Yellow, false, "1314")
|
||||
doAssert x.done == false
|
||||
|
||||
|
||||
type
|
||||
Ciao = object
|
||||
id: int
|
||||
case flag: bool = false
|
||||
of true:
|
||||
num: int
|
||||
of false:
|
||||
done: bool
|
||||
name: string
|
||||
|
||||
block:
|
||||
var x = Ciao(12, false, false, "123")
|
||||
doAssert x.done == false
|
||||
|
||||
block:
|
||||
var x = Ciao(12, flag: true, 1, "123")
|
||||
doAssert x.num == 1
|
||||
|
||||
## It works in the third module
|
||||
block:
|
||||
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
|
||||
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
|
||||
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
|
||||
|
||||
proc foo() =
|
||||
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
|
||||
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
|
||||
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
|
||||
|
||||
foo()
|
||||
|
||||
template bar() =
|
||||
doAssert initStandard("", 1, "sky") == Standard(id: 1, owner: "sky")
|
||||
doAssert initStandard("", 1, "sky") == Standard(1, "sky")
|
||||
doAssert toStandard("", 1, "sky") == Standard(1, "sky")
|
||||
|
||||
bar()
|
||||
@@ -391,3 +391,23 @@ var sorted = newSeq[int](1000)
|
||||
for i in 0..<sorted.len: sorted[i] = i*2
|
||||
doAssert isSorted2(sorted, compare)
|
||||
doAssert isSorted2(sorted, proc (a, b: int): bool {.inline.} = a < b)
|
||||
|
||||
|
||||
block: # Ensure static descriminated objects compile
|
||||
type
|
||||
ObjKind = enum
|
||||
KindA, KindB, KindC
|
||||
|
||||
MyObject[kind: static[ObjKind]] = object of RootObj
|
||||
myNumber: int
|
||||
when kind != KindA:
|
||||
driverType: int
|
||||
otherField: int
|
||||
elif kind == KindC:
|
||||
driverType: uint
|
||||
otherField: int
|
||||
|
||||
var instance: MyObject[KindA]
|
||||
discard instance
|
||||
discard MyObject[KindC]()
|
||||
|
||||
|
||||
28
tests/stdlib/t21564.nim
Normal file
28
tests/stdlib/t21564.nim
Normal file
@@ -0,0 +1,28 @@
|
||||
discard """
|
||||
targets: "c js"
|
||||
"""
|
||||
|
||||
import bitops
|
||||
import std/assertions
|
||||
|
||||
proc main() =
|
||||
block: # bug #21564
|
||||
# tesk `bitops.bitsliced` patch
|
||||
doAssert(0x17.bitsliced(4..7) == 0x01)
|
||||
doAssert(0x17.bitsliced(0..3) == 0x07)
|
||||
|
||||
block:
|
||||
# test in-place `bitops.bitslice`
|
||||
var t = 0x12F4
|
||||
t.bitslice(4..7)
|
||||
|
||||
doAssert(t == 0xF)
|
||||
|
||||
block:
|
||||
# test `bitops.toMask` patch via bitops.masked
|
||||
doAssert(0x12FFFF34.masked(8..23) == 0x00FFFF00)
|
||||
|
||||
main()
|
||||
|
||||
static:
|
||||
main()
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
targets: "c cpp js"
|
||||
matrix: "; --backend:cpp; --backend:js --jsbigint64:on; --backend:js --jsbigint64:off"
|
||||
"""
|
||||
|
||||
import std/hashes
|
||||
|
||||
@@ -57,8 +57,9 @@ proc asyncTest() {.async.} =
|
||||
doAssert(resp.code == Http404)
|
||||
doAssert(resp.status == $Http404)
|
||||
|
||||
resp = await client.request("https://google.com/")
|
||||
doAssert(resp.code.is2xx or resp.code.is3xx)
|
||||
when false: # occasionally does not give success code
|
||||
resp = await client.request("https://google.com/")
|
||||
doAssert(resp.code.is2xx or resp.code.is3xx)
|
||||
|
||||
# getContent
|
||||
try:
|
||||
@@ -118,8 +119,9 @@ proc syncTest() =
|
||||
doAssert(resp.code == Http404)
|
||||
doAssert(resp.status == $Http404)
|
||||
|
||||
resp = client.request("https://google.com/")
|
||||
doAssert(resp.code.is2xx or resp.code.is3xx)
|
||||
when false: # occasionally does not give success code
|
||||
resp = client.request("https://google.com/")
|
||||
doAssert(resp.code.is2xx or resp.code.is3xx)
|
||||
|
||||
# getContent
|
||||
try:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
discard """
|
||||
matrix: "--mm:refc"
|
||||
targets: "c cpp js"
|
||||
matrix: "--mm:refc; --backend:cpp --mm:refc; --backend:js --jsbigint64:off; --backend:js --jsbigint64:on"
|
||||
"""
|
||||
|
||||
|
||||
@@ -9,6 +8,7 @@ Note: Macro tests are in tests/stdlib/tjsonmacro.nim
|
||||
]#
|
||||
|
||||
import std/[json,parsejson,strutils]
|
||||
import std/private/jsutils
|
||||
from std/math import isNaN
|
||||
when not defined(js):
|
||||
import std/streams
|
||||
@@ -314,7 +314,8 @@ block: # bug #17383
|
||||
else:
|
||||
testRoundtrip(int.high): "9223372036854775807"
|
||||
testRoundtrip(uint.high): "18446744073709551615"
|
||||
when not defined(js):
|
||||
whenJsNoBigInt64: discard
|
||||
do:
|
||||
testRoundtrip(int64.high): "9223372036854775807"
|
||||
testRoundtrip(uint64.high): "18446744073709551615"
|
||||
|
||||
|
||||
@@ -436,11 +436,7 @@ proc testJson() =
|
||||
block:
|
||||
let s = """{"a": 1, "b": 2}"""
|
||||
let t = parseJson(s).to(Table[string, int])
|
||||
when not defined(js):
|
||||
# For some reason on the JS backend `{"b": 2, "a": 0}` is
|
||||
# sometimes the value of `t`. This needs investigation. I can't
|
||||
# reproduce it right now in an isolated test.
|
||||
doAssert t["a"] == 1
|
||||
doAssert t["a"] == 1
|
||||
doAssert t["b"] == 2
|
||||
|
||||
block:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user