mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 10:53:40 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7994556f38 | ||
|
|
8c9e88f520 | ||
|
|
7e52a57121 | ||
|
|
35c812fda1 | ||
|
|
47888c18f7 | ||
|
|
a8e040ec30 | ||
|
|
2fb1c80f42 | ||
|
|
e1f3c74bdc | ||
|
|
52d2ff601b | ||
|
|
41b71487af | ||
|
|
3d3b34473b | ||
|
|
fc0aec6f1b | ||
|
|
7cafd22377 | ||
|
|
9aff19f51a | ||
|
|
bc823b6487 | ||
|
|
3d3d790c63 | ||
|
|
a90cabbe40 | ||
|
|
2539d7a862 | ||
|
|
30737b3e7f | ||
|
|
984691bb67 | ||
|
|
5f70b1ab53 | ||
|
|
afa4bc34b4 | ||
|
|
0648cde117 | ||
|
|
980ec713da | ||
|
|
26ed4e5413 | ||
|
|
161736ceb3 | ||
|
|
ce6fa79858 | ||
|
|
f2e7e5d899 | ||
|
|
d4de5d32bc | ||
|
|
efdb180f62 | ||
|
|
095202e218 | ||
|
|
f4e41e6c4f | ||
|
|
8aec198abc |
@@ -11,6 +11,10 @@
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
- `macros.parseExpr` and `macros.parseStmt` now accept an optional
|
||||
filename argument for more informative errors.
|
||||
- Module `colors` expanded with missing colors from the CSS color standard.
|
||||
- Fixed `lists.SinglyLinkedList` being broken after removing the last node ([#19353](https://github.com/nim-lang/Nim/pull/19353)).
|
||||
|
||||
|
||||
## Language changes
|
||||
|
||||
@@ -501,7 +501,7 @@ type
|
||||
nfHasComment # node has a comment
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 43)
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45)
|
||||
tfVarargs, # procedure has C styled varargs
|
||||
# tyArray type represeting a varargs list
|
||||
tfNoSideEffect, # procedure type does not allow side effects
|
||||
|
||||
@@ -76,7 +76,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
if params != nil: pl.add(~", ")
|
||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
|
||||
@@ -376,8 +376,8 @@ proc genParams(p: BProc, ri: PNode, typ: PType): Rope =
|
||||
if not needTmp[i - 1]:
|
||||
needTmp[i - 1] = potentialAlias(n, potentialWrites)
|
||||
getPotentialWrites(ri[i], false, potentialWrites)
|
||||
if ri[i].kind == nkHiddenAddr:
|
||||
# Optimization: don't use a temp, if we would only take the adress anyway
|
||||
if ri[i].kind in {nkHiddenAddr, nkAddr}:
|
||||
# Optimization: don't use a temp, if we would only take the address anyway
|
||||
needTmp[i - 1] = false
|
||||
|
||||
for i in 1..<ri.len:
|
||||
@@ -439,7 +439,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
let rawProc = getClosureType(p.module, typ, clHalf)
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
if ri.len > 1: pl.add(~", ")
|
||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
|
||||
@@ -737,7 +737,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
pl.add(~": ")
|
||||
pl.add(genArg(p, ri[i], param, ri))
|
||||
if typ[0] != nil:
|
||||
if isInvalidReturnType(p.config, typ[0]):
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
if ri.len > 1: pl.add(~" ")
|
||||
# beware of 'result = p(result)'. We always allocate a temporary:
|
||||
if d.k in {locTemp, locNone}:
|
||||
|
||||
@@ -32,13 +32,20 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) =
|
||||
"$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc])
|
||||
|
||||
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
||||
if n.kind == nkEmpty: return false
|
||||
if isInvalidReturnType(conf, n.typ):
|
||||
# var v = f()
|
||||
# is transformed into: var v; f(addr v)
|
||||
# where 'f' **does not** initialize the result!
|
||||
return false
|
||||
result = true
|
||||
if n.kind == nkEmpty:
|
||||
result = false
|
||||
elif n.kind in nkCallKinds and n[0] != nil and n[0].typ != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc:
|
||||
if isInvalidReturnType(conf, n[0].typ, true):
|
||||
# var v = f()
|
||||
# is transformed into: var v; f(addr v)
|
||||
# where 'f' **does not** initialize the result!
|
||||
result = false
|
||||
else:
|
||||
result = true
|
||||
elif isInvalidReturnType(conf, n.typ, false):
|
||||
result = false
|
||||
else:
|
||||
result = true
|
||||
|
||||
proc inExceptBlockLen(p: BProc): int =
|
||||
for x in p.nestedTryStmts:
|
||||
|
||||
@@ -215,12 +215,18 @@ proc isObjLackingTypeField(typ: PType): bool {.inline.} =
|
||||
result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and
|
||||
(typ[0] == nil) or isPureObject(typ))
|
||||
|
||||
proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
|
||||
proc isInvalidReturnType(conf: ConfigRef; typ: PType, isProc = true): bool =
|
||||
# Arrays and sets cannot be returned by a C procedure, because C is
|
||||
# such a poor programming language.
|
||||
# We exclude records with refs too. This enhances efficiency and
|
||||
# is necessary for proper code generation of assignments.
|
||||
if rettype == nil or getSize(conf, rettype) > conf.target.floatSize*3:
|
||||
var rettype = typ
|
||||
var isAllowedCall = true
|
||||
if isProc:
|
||||
rettype = rettype[0]
|
||||
isAllowedCall = typ.callConv in {ccClosure, ccInline, ccNimCall}
|
||||
if rettype == nil or (isAllowedCall and
|
||||
getSize(conf, rettype) > conf.target.floatSize*3):
|
||||
result = true
|
||||
else:
|
||||
case mapType(conf, rettype, skResult)
|
||||
@@ -257,11 +263,11 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) =
|
||||
# see `testCodegenABICheck` for example error message it generates
|
||||
|
||||
|
||||
proc fillResult(conf: ConfigRef; param: PNode) =
|
||||
proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) =
|
||||
fillLoc(param.sym.loc, locParam, param, ~"Result",
|
||||
OnStack)
|
||||
let t = param.sym.typ
|
||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, t):
|
||||
if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype):
|
||||
incl(param.sym.loc.flags, lfIndirect)
|
||||
param.sym.loc.storage = OnUnknown
|
||||
|
||||
@@ -426,7 +432,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
check: var IntSet, declareEnvironment=true;
|
||||
weakDep=false) =
|
||||
params = nil
|
||||
if t[0] == nil or isInvalidReturnType(m.config, t[0]):
|
||||
if t[0] == nil or isInvalidReturnType(m.config, t):
|
||||
rettype = ~"void"
|
||||
else:
|
||||
rettype = getTypeDescAux(m, t[0], check, skResult)
|
||||
@@ -461,7 +467,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||
params.addf(", NI $1Len_$2", [param.loc.r, j.rope])
|
||||
inc(j)
|
||||
arr = arr[0].skipTypes({tySink})
|
||||
if t[0] != nil and isInvalidReturnType(m.config, t[0]):
|
||||
if t[0] != nil and isInvalidReturnType(m.config, t):
|
||||
var arr = t[0]
|
||||
if params != nil: params.add(", ")
|
||||
if mapReturnType(m.config, t[0]) != ctArray:
|
||||
|
||||
@@ -48,8 +48,13 @@ proc addForwardedProc(m: BModule, prc: PSym) =
|
||||
m.g.forwardedProcs.add(prc)
|
||||
|
||||
proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
# TODO fixme
|
||||
if m.config.symbolFiles == v2Sf:
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
else:
|
||||
var ms = getModule(s)
|
||||
result = m.g.modules[ms.position]
|
||||
|
||||
proc initLoc(result: var TLoc, k: TLocKind, lode: PNode, s: TStorageLoc) =
|
||||
result.k = k
|
||||
@@ -1034,7 +1039,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
internalError(m.config, prc.info, "proc has no result symbol")
|
||||
let resNode = prc.ast[resultPos]
|
||||
let res = resNode.sym # get result symbol
|
||||
if not isInvalidReturnType(m.config, prc.typ[0]):
|
||||
if not isInvalidReturnType(m.config, prc.typ):
|
||||
if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
|
||||
if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil):
|
||||
var decl = localVarDecl(p, resNode)
|
||||
@@ -1048,7 +1053,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||
initLocalVar(p, res, immediateAsgn=false)
|
||||
returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
|
||||
else:
|
||||
fillResult(p.config, resNode)
|
||||
fillResult(p.config, resNode, prc.typ)
|
||||
assignParam(p, res, prc.typ[0])
|
||||
# We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)'
|
||||
# to 'unsureAsgn(result, x)'
|
||||
|
||||
@@ -178,7 +178,7 @@ const
|
||||
proc mapType(typ: PType): TJSTypeKind =
|
||||
let t = skipTypes(typ, abstractInst)
|
||||
case t.kind
|
||||
of tyVar, tyRef, tyPtr, tyLent:
|
||||
of tyVar, tyRef, tyPtr:
|
||||
if skipTypes(t.lastSon, abstractInst).kind in MappedToObject:
|
||||
result = etyObject
|
||||
else:
|
||||
@@ -186,7 +186,8 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
of tyPointer:
|
||||
# treat a tyPointer like a typed pointer to an array of bytes
|
||||
result = etyBaseIndex
|
||||
of tyRange, tyDistinct, tyOrdinal, tyProxy:
|
||||
of tyRange, tyDistinct, tyOrdinal, tyProxy, tyLent:
|
||||
# tyLent is no-op as JS has pass-by-reference semantics
|
||||
result = mapType(t[0])
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
||||
of tyBool: result = etyBool
|
||||
@@ -1060,14 +1061,14 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||
xtyp = etySeq
|
||||
case xtyp
|
||||
of etySeq:
|
||||
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
else:
|
||||
useMagic(p, "nimCopy")
|
||||
lineF(p, "$1 = nimCopy(null, $2, $3);$n",
|
||||
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
|
||||
of etyObject:
|
||||
if x.typ.kind in {tyVar} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
if x.typ.kind in {tyVar, tyLent} or (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
else:
|
||||
useMagic(p, "nimCopy")
|
||||
@@ -1092,10 +1093,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||
lineF(p, "$# = [$#, $#];$n", [a.res, b.address, b.res])
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
elif a.typ == etyBaseIndex:
|
||||
# array indexing may not map to var type
|
||||
if b.address != nil:
|
||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
else:
|
||||
internalError(p.config, x.info, $("genAsgn", b.typ, a.typ))
|
||||
else:
|
||||
elif b.address != nil:
|
||||
lineF(p, "$1 = $2; $3 = $4;$n", [a.address, b.address, a.res, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.address, b.res])
|
||||
else:
|
||||
lineF(p, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
||||
|
||||
@@ -1442,13 +1451,17 @@ proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||
else:
|
||||
if s.loc.r == nil:
|
||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||
r.res = s.loc.r
|
||||
if mapType(p, s.typ) == etyBaseIndex:
|
||||
r.address = s.loc.r
|
||||
r.res = s.loc.r & "_Idx"
|
||||
else:
|
||||
r.res = s.loc.r
|
||||
r.kind = resVal
|
||||
|
||||
proc genDeref(p: PProc, n: PNode, r: var TCompRes) =
|
||||
let it = n[0]
|
||||
let t = mapType(p, it.typ)
|
||||
if t == etyObject:
|
||||
if t == etyObject or it.typ.kind == tyLent:
|
||||
gen(p, it, r)
|
||||
else:
|
||||
var a: TCompRes
|
||||
@@ -1689,7 +1702,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
result = putToSeq("0", indirect)
|
||||
of tyFloat..tyFloat128:
|
||||
result = putToSeq("0.0", indirect)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned:
|
||||
of tyRange, tyGenericInst, tyAlias, tySink, tyOwned, tyLent:
|
||||
result = createVar(p, lastSon(typ), indirect)
|
||||
of tySet:
|
||||
result = putToSeq("{}", indirect)
|
||||
@@ -1731,7 +1744,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
|
||||
createObjInitList(p, t, initIntSet(), initList)
|
||||
result = ("({$1})") % [initList]
|
||||
if indirect: result = "[$1]" % [result]
|
||||
of tyVar, tyPtr, tyLent, tyRef, tyPointer:
|
||||
of tyVar, tyPtr, tyRef, tyPointer:
|
||||
if mapType(p, t) == etyBaseIndex:
|
||||
result = putToSeq("[null, 0]", indirect)
|
||||
else:
|
||||
@@ -2380,16 +2393,17 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
|
||||
if prc.typ[0] != nil and sfPure notin prc.flags:
|
||||
resultSym = prc.ast[resultPos].sym
|
||||
let mname = mangleName(p.module, resultSym)
|
||||
if not isIndirect(resultSym) and
|
||||
let returnAddress = not isIndirect(resultSym) and
|
||||
resultSym.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and
|
||||
mapType(p, resultSym.typ) == etyBaseIndex:
|
||||
mapType(p, resultSym.typ) == etyBaseIndex
|
||||
if returnAddress:
|
||||
resultAsgn = p.indentLine(("var $# = null;$n") % [mname])
|
||||
resultAsgn.add p.indentLine("var $#_Idx = 0;$n" % [mname])
|
||||
else:
|
||||
let resVar = createVar(p, resultSym.typ, isIndirect(resultSym))
|
||||
resultAsgn = p.indentLine(("var $# = $#;$n") % [mname, resVar])
|
||||
gen(p, prc.ast[resultPos], a)
|
||||
if mapType(p, resultSym.typ) == etyBaseIndex:
|
||||
if returnAddress:
|
||||
returnStmt = "return [$#, $#];$n" % [a.address, a.res]
|
||||
else:
|
||||
returnStmt = "return $#;$n" % [a.res]
|
||||
@@ -2565,8 +2579,15 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkObjConstr: genObjConstr(p, n, r)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r)
|
||||
of nkAddr, nkHiddenAddr:
|
||||
genAddr(p, n, r)
|
||||
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, r)
|
||||
if n.typ.kind in {tyLent}:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
genAddr(p, n, r)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
if n.typ.kind in {tyLent}:
|
||||
gen(p, n[0], r)
|
||||
else:
|
||||
genDeref(p, n, r)
|
||||
of nkBracketExpr: genArrayAccess(p, n, r)
|
||||
of nkDotExpr: genFieldAccess(p, n, r)
|
||||
of nkCheckedFieldExpr: genCheckedFieldOp(p, n, nil, r)
|
||||
|
||||
@@ -582,10 +582,10 @@ proc parsePar(p: var Parser): PNode =
|
||||
#| | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
|
||||
#| | 'when' | 'var' | 'mixin'
|
||||
#| par = '(' optInd
|
||||
#| ( &parKeyw (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
#| | ';' (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
#| ( &parKeyw (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
#| | ';' (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
#| | pragmaStmt
|
||||
#| | simpleExpr ( ('=' expr (';' (ifExpr \ complexOrSimpleStmt) ^+ ';' )? )
|
||||
#| | simpleExpr ( ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
|
||||
#| | (':' expr (',' exprColonEqExpr ^+ ',' )? ) ) )
|
||||
#| optPar ')'
|
||||
#
|
||||
|
||||
@@ -1414,7 +1414,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
|
||||
ty = ty.lastSon
|
||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink})
|
||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink, tyStatic})
|
||||
while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct, tyGenericInst, tyAlias})
|
||||
var check: PNode = nil
|
||||
if ty.kind == tyObject:
|
||||
|
||||
@@ -2075,6 +2075,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
incl(s.flags, sfWasForwarded)
|
||||
elif sfBorrow in s.flags: semBorrow(c, n, s)
|
||||
sideEffectsCheck(c, s)
|
||||
|
||||
closeScope(c) # close scope for parameters
|
||||
# c.currentScope = oldScope
|
||||
popOwner(c)
|
||||
|
||||
@@ -57,6 +57,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
of tyVar, tyLent:
|
||||
if kind in {skProc, skFunc, skConst} and (views notin c.features):
|
||||
result = t
|
||||
elif taIsOpenArray in flags:
|
||||
result = t
|
||||
elif t.kind == tyLent and ((kind != skResult and views notin c.features) or
|
||||
kind == skParam): # lent can't be used as parameters.
|
||||
result = t
|
||||
@@ -231,7 +233,7 @@ proc classifyViewTypeAux(marker: var IntSet, t: PType): ViewTypeKind =
|
||||
case t.kind
|
||||
of tyVar:
|
||||
result = mutableView
|
||||
of tyLent, tyOpenArray:
|
||||
of tyLent, tyOpenArray, tyVarargs:
|
||||
result = immutableView
|
||||
of tyGenericInst, tyDistinct, tyAlias, tyInferred, tySink, tyOwned,
|
||||
tyUncheckedArray, tySequence, tyArray, tyRef, tyStatic:
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
cppDefine "errno"
|
||||
cppDefine "unix"
|
||||
|
||||
# mangle the macro names in nimbase.h
|
||||
cppDefine "NAN_INFINITY"
|
||||
cppDefine "INF"
|
||||
cppDefine "NAN"
|
||||
|
||||
when defined(nimStrictMode):
|
||||
# xxx add more flags here, and use `-d:nimStrictMode` in more contexts in CI.
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
|
||||
| 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
|
||||
| 'when' | 'var' | 'mixin'
|
||||
par = '(' optInd
|
||||
( &parKeyw (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
| ';' (ifExpr \ complexOrSimpleStmt) ^+ ';'
|
||||
( &parKeyw (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
| ';' (ifExpr / complexOrSimpleStmt) ^+ ';'
|
||||
| pragmaStmt
|
||||
| simpleExpr ( ('=' expr (';' (ifExpr \ complexOrSimpleStmt) ^+ ';' )? )
|
||||
| simpleExpr ( ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
|
||||
| (':' expr (',' exprColonEqExpr ^+ ',' )? ) ) )
|
||||
optPar ')'
|
||||
literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
|
||||
|
||||
@@ -1899,7 +1899,7 @@ A small example:
|
||||
cast uncheckedAssign
|
||||
--------------------
|
||||
|
||||
Some restrictions for case objects can be disabled via a `{.cast(unsafeAssign).}` section:
|
||||
Some restrictions for case objects can be disabled via a `{.cast(uncheckedAssign).}` section:
|
||||
|
||||
.. code-block:: nim
|
||||
:test: "nim c $1"
|
||||
@@ -5002,7 +5002,7 @@ be used:
|
||||
|
||||
See also:
|
||||
|
||||
- `Shared heap memory management <gc.html>`_.
|
||||
- `Shared heap memory management <mm.html>`_.
|
||||
|
||||
|
||||
|
||||
|
||||
3
koch.nim
3
koch.nim
@@ -559,7 +559,8 @@ proc runCI(cmd: string) =
|
||||
|
||||
let batchParam = "--batch:$1" % "NIM_TESTAMENT_BATCH".getEnv("_")
|
||||
if getEnv("NIM_TEST_PACKAGES", "0") == "1":
|
||||
execFold("Test selected Nimble packages", "nim r testament/testament $# pcat nimble-packages" % batchParam)
|
||||
nimCompileFold("Compile testament", "testament/testament.nim", options = "-d:release")
|
||||
execFold("Test selected Nimble packages", "testament $# pcat nimble-packages" % batchParam)
|
||||
else:
|
||||
buildTools()
|
||||
|
||||
|
||||
@@ -1718,8 +1718,8 @@ proc extractDocCommentsAndRunnables*(n: NimNode): NimNode =
|
||||
case ni.kind
|
||||
of nnkCommentStmt:
|
||||
result.add ni
|
||||
of nnkCall:
|
||||
if ni[0].kind == nnkIdent and ni[0].strVal == "runnableExamples":
|
||||
of nnkCall, nnkCommand:
|
||||
if ni[0].kind == nnkIdent and ni[0].eqIdent "runnableExamples":
|
||||
result.add ni
|
||||
else: break
|
||||
else: break
|
||||
|
||||
@@ -522,19 +522,22 @@ iterator split*(s: string, sep: Regex; maxsplit = -1): string =
|
||||
@["", "this", "is", "an", "example", ""]
|
||||
var last = 0
|
||||
var splits = maxsplit
|
||||
var x: int
|
||||
var x = -1
|
||||
if len(s) == 0:
|
||||
last = 1
|
||||
if matchLen(s, sep, 0) == 0:
|
||||
x = 0
|
||||
while last <= len(s):
|
||||
var first = last
|
||||
var sepLen = 1
|
||||
if x == 0:
|
||||
inc(last)
|
||||
while last < len(s):
|
||||
x = matchLen(s, sep, last)
|
||||
if x >= 0:
|
||||
sepLen = x
|
||||
break
|
||||
inc(last)
|
||||
if x == 0:
|
||||
if last >= len(s): break
|
||||
inc last
|
||||
if splits == 0: last = len(s)
|
||||
yield substr(s, first, last-1)
|
||||
if splits == 0: break
|
||||
|
||||
@@ -927,7 +927,8 @@ proc getField1Int(d: PDoc, n: PRstNode, fieldName: string): int =
|
||||
let nChars = parseInt(value, number)
|
||||
if nChars == 0:
|
||||
if value.len == 0:
|
||||
err("field $1 requires an argument" % [fieldName])
|
||||
# use a good default value:
|
||||
result = 1
|
||||
else:
|
||||
err("field $1 requires an integer, but '$2' was given" %
|
||||
[fieldName, value])
|
||||
|
||||
@@ -531,11 +531,12 @@ proc addMoved*[T](a, b: var SinglyLinkedList[T]) {.since: (1, 5, 1).} =
|
||||
ci
|
||||
assert s == [0, 1, 0, 1, 0, 1]
|
||||
|
||||
if a.tail != nil:
|
||||
a.tail.next = b.head
|
||||
a.tail = b.tail
|
||||
if a.head == nil:
|
||||
a.head = b.head
|
||||
if b.head != nil:
|
||||
if a.head == nil:
|
||||
a.head = b.head
|
||||
else:
|
||||
a.tail.next = b.head
|
||||
a.tail = b.tail
|
||||
if a.addr != b.addr:
|
||||
b.head = nil
|
||||
b.tail = nil
|
||||
@@ -675,12 +676,12 @@ proc addMoved*[T](a, b: var DoublyLinkedList[T]) {.since: (1, 5, 1).} =
|
||||
assert s == [0, 1, 0, 1, 0, 1]
|
||||
|
||||
if b.head != nil:
|
||||
b.head.prev = a.tail
|
||||
if a.tail != nil:
|
||||
a.tail.next = b.head
|
||||
a.tail = b.tail
|
||||
if a.head == nil:
|
||||
a.head = b.head
|
||||
if a.head == nil:
|
||||
a.head = b.head
|
||||
else:
|
||||
b.head.prev = a.tail
|
||||
a.tail.next = b.head
|
||||
a.tail = b.tail
|
||||
if a.addr != b.addr:
|
||||
b.head = nil
|
||||
b.tail = nil
|
||||
@@ -739,6 +740,8 @@ proc remove*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]): bool {.disc
|
||||
if prev.next == nil:
|
||||
return false
|
||||
prev.next = n.next
|
||||
if L.tail == n:
|
||||
L.tail = prev # update tail if we removed the last node
|
||||
true
|
||||
|
||||
proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) =
|
||||
|
||||
@@ -293,19 +293,16 @@ else:
|
||||
AtomicInt32 {.importc: "_Atomic NI32".} = int32
|
||||
AtomicInt64 {.importc: "_Atomic NI64".} = int64
|
||||
|
||||
template atomicType*(T: typedesc[Trivial]): untyped =
|
||||
# Maps the size of a trivial type to it's internal atomic type
|
||||
when sizeof(T) == 1: AtomicInt8
|
||||
elif sizeof(T) == 2: AtomicInt16
|
||||
elif sizeof(T) == 4: AtomicInt32
|
||||
elif sizeof(T) == 8: AtomicInt64
|
||||
|
||||
type
|
||||
AtomicFlag* {.importc: "atomic_flag", size: 1.} = object
|
||||
|
||||
Atomic*[T] = object
|
||||
when T is Trivial:
|
||||
value: T.atomicType
|
||||
# Maps the size of a trivial type to it's internal atomic type
|
||||
when sizeof(T) == 1: value: AtomicInt8
|
||||
elif sizeof(T) == 2: value: AtomicInt16
|
||||
elif sizeof(T) == 4: value: AtomicInt32
|
||||
elif sizeof(T) == 8: value: AtomicInt64
|
||||
else:
|
||||
nonAtomicValue: T
|
||||
guard: AtomicFlag
|
||||
@@ -364,11 +361,11 @@ else:
|
||||
cast[T](atomic_fetch_xor_explicit(addr(location.value), cast[nonAtomicType(T)](value), order))
|
||||
|
||||
template withLock[T: not Trivial](location: var Atomic[T]; order: MemoryOrder; body: untyped): untyped =
|
||||
while location.guard.testAndSet(moAcquire): discard
|
||||
while testAndSet(location.guard, moAcquire): discard
|
||||
try:
|
||||
body
|
||||
finally:
|
||||
location.guard.clear(moRelease)
|
||||
clear(location.guard, moRelease)
|
||||
|
||||
proc load*[T: not Trivial](location: var Atomic[T]; order: MemoryOrder = moSequentiallyConsistent): T {.inline.} =
|
||||
withLock(location, order):
|
||||
|
||||
@@ -523,7 +523,7 @@ proc generateHeaders(requestUrl: Uri, httpMethod: HttpMethod, headers: HttpHeade
|
||||
# Proxy auth header.
|
||||
if not proxy.isNil and proxy.auth != "":
|
||||
let auth = base64.encode(proxy.auth)
|
||||
add(result, "Proxy-Authorization: basic " & auth & httpNewLine)
|
||||
add(result, "Proxy-Authorization: Basic " & auth & httpNewLine)
|
||||
|
||||
for key, val in headers:
|
||||
add(result, key & ": " & val & httpNewLine)
|
||||
@@ -673,7 +673,7 @@ proc reportProgress(client: HttpClient | AsyncHttpClient,
|
||||
progress: BiggestInt) {.multisync.} =
|
||||
client.contentProgress += progress
|
||||
client.oneSecondProgress += progress
|
||||
if (getMonoTime() - client.lastProgressReport).inSeconds > 1:
|
||||
if (getMonoTime() - client.lastProgressReport).inSeconds >= 1:
|
||||
if not client.onProgressChanged.isNil:
|
||||
await client.onProgressChanged(client.contentTotal,
|
||||
client.contentProgress,
|
||||
|
||||
@@ -1618,7 +1618,7 @@ proc recvFrom*(socket: Socket, data: var string, length: int,
|
||||
## used. Therefore if `socket` contains something in its buffer this
|
||||
## function will make no effort to return it.
|
||||
template adaptRecvFromToDomain(domain: Domain) =
|
||||
var addrLen = sizeof(sockAddress).SockLen
|
||||
var addrLen = SockLen(sizeof(sockAddress))
|
||||
result = recvfrom(socket.fd, cstring(data), length.cint, flags.cint,
|
||||
cast[ptr SockAddr](addr(sockAddress)), addr(addrLen))
|
||||
|
||||
|
||||
@@ -574,6 +574,9 @@ template formatValue(result: var string; value: cstring; specifier: string) =
|
||||
result.add value
|
||||
|
||||
proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
|
||||
template missingCloseChar =
|
||||
error("invalid format string: missing closing character '" & closeChar & "'")
|
||||
|
||||
if openChar == ':' or closeChar == ':':
|
||||
error "openChar and closeChar must not be ':'"
|
||||
var i = 0
|
||||
@@ -618,6 +621,8 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
|
||||
let start = i
|
||||
inc i
|
||||
i += f.skipWhitespace(i)
|
||||
if i == f.len:
|
||||
missingCloseChar
|
||||
if f[i] == closeChar or f[i] == ':':
|
||||
result.add newCall(bindSym"add", res, newLit(subexpr & f[start ..< i]))
|
||||
else:
|
||||
@@ -627,6 +632,9 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
|
||||
subexpr.add f[i]
|
||||
inc i
|
||||
|
||||
if i == f.len:
|
||||
missingCloseChar
|
||||
|
||||
var x: NimNode
|
||||
try:
|
||||
x = parseExpr(subexpr)
|
||||
@@ -639,10 +647,10 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
|
||||
while i < f.len and f[i] != closeChar:
|
||||
options.add f[i]
|
||||
inc i
|
||||
if i == f.len:
|
||||
missingCloseChar
|
||||
if f[i] == closeChar:
|
||||
inc i
|
||||
else:
|
||||
doAssert false, "invalid format string: missing '}'"
|
||||
result.add newCall(formatSym, res, x, newLit(options))
|
||||
elif f[i] == closeChar:
|
||||
if i<f.len-1 and f[i+1] == closeChar:
|
||||
|
||||
@@ -1859,7 +1859,7 @@ func find*(s: string, sub: char, start: Natural = 0, last = 0): int {.rtl,
|
||||
## Use `s[start..last].rfind` for a `start`-origin index.
|
||||
##
|
||||
## See also:
|
||||
## * `rfind func<#rfind,string,char,Natural>`_
|
||||
## * `rfind func<#rfind,string,char,Natural,int>`_
|
||||
## * `replace func<#replace,string,char,char>`_
|
||||
let last = if last == 0: s.high else: last
|
||||
when nimvm:
|
||||
@@ -1887,7 +1887,7 @@ func find*(s: string, chars: set[char], start: Natural = 0, last = 0): int {.
|
||||
## Use `s[start..last].find` for a `start`-origin index.
|
||||
##
|
||||
## See also:
|
||||
## * `rfind func<#rfind,string,set[char],Natural>`_
|
||||
## * `rfind func<#rfind,string,set[char],Natural,int>`_
|
||||
## * `multiReplace func<#multiReplace,string,varargs[]>`_
|
||||
let last = if last == 0: s.high else: last
|
||||
for i in int(start)..last:
|
||||
@@ -1904,7 +1904,7 @@ func find*(s, sub: string, start: Natural = 0, last = 0): int {.rtl,
|
||||
## Use `s[start..last].find` for a `start`-origin index.
|
||||
##
|
||||
## See also:
|
||||
## * `rfind func<#rfind,string,string,Natural>`_
|
||||
## * `rfind func<#rfind,string,string,Natural,int>`_
|
||||
## * `replace func<#replace,string,string,string>`_
|
||||
if sub.len > s.len - start: return -1
|
||||
if sub.len == 1: return find(s, sub[0], start, last)
|
||||
|
||||
@@ -216,8 +216,6 @@ func parseAuthority(authority: string, result: var Uri) =
|
||||
result.isIpv6 = true
|
||||
of ']':
|
||||
inIPv6 = false
|
||||
of '\0':
|
||||
break
|
||||
else:
|
||||
if inPort:
|
||||
result.port.add(authority[i])
|
||||
|
||||
@@ -1189,8 +1189,8 @@ proc align(address, alignment: int): int =
|
||||
else:
|
||||
result = (address + (alignment - 1)) and not (alignment - 1)
|
||||
|
||||
when defined(nimdoc):
|
||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||
when defined(nimNoQuit):
|
||||
proc quit*(errorcode: int = QuitSuccess) = discard "ignoring quit"
|
||||
## Stops the program immediately with an exit code.
|
||||
##
|
||||
## Before stopping the program the "exit procedures" are called in the
|
||||
@@ -1214,6 +1214,9 @@ when defined(nimdoc):
|
||||
## It does *not* call the garbage collector to free all the memory,
|
||||
## unless an `addExitProc` proc calls `GC_fullCollect <#GC_fullCollect>`_.
|
||||
|
||||
elif defined(nimdoc):
|
||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||
|
||||
elif defined(genode):
|
||||
include genode/env
|
||||
|
||||
@@ -2125,7 +2128,7 @@ const
|
||||
## is the minor number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 2
|
||||
NimPatch* {.intdefine.}: int = 4
|
||||
## is the patch number of Nim's version.
|
||||
## Odd for devel, even for releases.
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ proc pkg(name: string; cmd = "nimble test"; url = "", useHead = true, allowFailu
|
||||
|
||||
pkg "alea", allowFailure = true
|
||||
pkg "argparse"
|
||||
pkg "arraymancer", "nim c tests/tests_cpu.nim", allowFailure = true
|
||||
pkg "arraymancer", "nim c tests/tests_cpu.nim"
|
||||
pkg "ast_pattern_matching", "nim c -r --oldgensym:on tests/test1.nim", allowFailure = true
|
||||
pkg "asyncthreadpool"
|
||||
pkg "awk"
|
||||
@@ -55,7 +55,7 @@ pkg "chronos", "nim c -r -d:release tests/testall"
|
||||
pkg "cligen", "nim c --path:. -r cligen.nim"
|
||||
pkg "combparser", "nimble test --gc:orc"
|
||||
pkg "compactdict"
|
||||
pkg "comprehension", "nimble test", "https://github.com/alehander42/comprehension"
|
||||
pkg "comprehension", "nimble test", "https://github.com/alehander92/comprehension"
|
||||
pkg "criterion", allowFailure = true # pending https://github.com/disruptek/criterion/issues/3 (wrongly closed)
|
||||
pkg "datamancer"
|
||||
pkg "dashing", "nim c tests/functional.nim"
|
||||
@@ -63,8 +63,8 @@ pkg "delaunay"
|
||||
pkg "docopt"
|
||||
pkg "easygl", "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl"
|
||||
pkg "elvis"
|
||||
pkg "fidget", allowFailure = true
|
||||
pkg "fragments", "nim c -r fragments/dsl.nim"
|
||||
pkg "fidget"
|
||||
pkg "fragments", "nim c -r fragments/dsl.nim", allowFailure = true # pending https://github.com/nim-lang/packages/issues/2115
|
||||
pkg "fusion"
|
||||
pkg "gara"
|
||||
pkg "glob"
|
||||
@@ -91,7 +91,7 @@ pkg "memo"
|
||||
pkg "msgpack4nim", "nim c -r tests/test_spec.nim"
|
||||
pkg "nake", "nim c nakefile.nim"
|
||||
pkg "neo", "nim c -d:blas=openblas tests/all.nim"
|
||||
pkg "nesm", "nimble tests", allowFailure = true # notice plural 'tests'
|
||||
pkg "nesm", "nimble tests" # notice plural 'tests'
|
||||
pkg "netty"
|
||||
pkg "nico", allowFailure = true
|
||||
pkg "nicy", "nim c -r src/nicy.nim"
|
||||
@@ -103,7 +103,7 @@ pkg "nimfp", "nim c -o:nfp -r src/fp.nim"
|
||||
pkg "nimgame2", "nim c -d:nimLegacyConvEnumEnum nimgame2/nimgame.nim"
|
||||
# XXX Doesn't work with deprecated 'randomize', will create a PR.
|
||||
pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim"
|
||||
pkg "nimlsp"
|
||||
pkg "nimlsp", allowFailure = true
|
||||
pkg "nimly", "nim c -r tests/test_readme_example.nim"
|
||||
pkg "nimongo", "nimble test_ci", allowFailure = true
|
||||
pkg "nimph", "nimble test", "https://github.com/disruptek/nimph", allowFailure = true
|
||||
@@ -115,9 +115,9 @@ pkg "nimterop", "nimble minitest"
|
||||
pkg "nimwc", "nim c nimwc.nim"
|
||||
pkg "nimx", "nim c --threads:on test/main.nim", allowFailure = true
|
||||
pkg "nitter", "nim c src/nitter.nim", "https://github.com/zedeus/nitter"
|
||||
pkg "norm", "nim c -r tests/sqlite/trows.nim"
|
||||
pkg "norm", "testament r tests/sqlite/trows.nim"
|
||||
pkg "npeg", "nimble testarc"
|
||||
pkg "numericalnim", "nim c -r tests/test_integrate.nim"
|
||||
pkg "numericalnim", "nimble nimCI"
|
||||
pkg "optionsutils"
|
||||
pkg "ormin", "nim c -o:orminn ormin.nim"
|
||||
pkg "parsetoml"
|
||||
@@ -157,7 +157,7 @@ pkg "tiny_sqlite"
|
||||
pkg "unicodedb", "nim c -d:release -r tests/tests.nim"
|
||||
pkg "unicodeplus", "nim c -d:release -r tests/tests.nim"
|
||||
pkg "unpack"
|
||||
pkg "weave", "nimble test_gc_arc", allowFailure = true
|
||||
pkg "weave", "nimble test_gc_arc"
|
||||
pkg "websocket", "nim c websocket.nim"
|
||||
pkg "winim", "nim c winim.nim"
|
||||
pkg "with"
|
||||
|
||||
@@ -103,7 +103,7 @@ type
|
||||
|
||||
proc getCmd*(s: TSpec): string =
|
||||
if s.cmd.len == 0:
|
||||
result = compilerPrefix & " $target --hints:on -d:testing --clearNimblePath --nimblePath:build/deps/pkgs $options $file"
|
||||
result = compilerPrefix & " $target --hints:on -d:testing --nimblePath:build/deps/pkgs $options $file"
|
||||
else:
|
||||
result = s.cmd
|
||||
|
||||
|
||||
22
tests/arc/tarc_orc.nim
Normal file
22
tests/arc/tarc_orc.nim
Normal file
@@ -0,0 +1,22 @@
|
||||
discard """
|
||||
matrix: "--mm:arc; --mm:orc"
|
||||
"""
|
||||
|
||||
block:
|
||||
type
|
||||
PublicKey = array[32, uint8]
|
||||
PrivateKey = array[64, uint8]
|
||||
|
||||
proc ed25519_create_keypair(publicKey: ptr PublicKey; privateKey: ptr PrivateKey) =
|
||||
publicKey[][0] = uint8(88)
|
||||
|
||||
type
|
||||
KeyPair = object
|
||||
public: PublicKey
|
||||
private: PrivateKey
|
||||
|
||||
proc initKeyPair(): KeyPair =
|
||||
ed25519_create_keypair(result.public.addr, result.private.addr)
|
||||
|
||||
let keys = initKeyPair()
|
||||
doAssert keys.public[0] == 88
|
||||
16
tests/ccgbugs/tmangle.nim
Normal file
16
tests/ccgbugs/tmangle.nim
Normal file
@@ -0,0 +1,16 @@
|
||||
block:
|
||||
proc hello() =
|
||||
let NAN_INFINITY = 12
|
||||
doAssert NAN_INFINITY == 12
|
||||
let INF = "2.0"
|
||||
doAssert INF == "2.0"
|
||||
let NAN = 2.3
|
||||
doAssert NAN == 2.3
|
||||
|
||||
hello()
|
||||
|
||||
block:
|
||||
proc hello(NAN: float) =
|
||||
doAssert NAN == 2.0
|
||||
|
||||
hello(2.0)
|
||||
33
tests/js/tlent.nim
Normal file
33
tests/js/tlent.nim
Normal file
@@ -0,0 +1,33 @@
|
||||
discard """
|
||||
output: '''
|
||||
hmm
|
||||
100
|
||||
hmm
|
||||
100
|
||||
'''
|
||||
"""
|
||||
|
||||
# #16800
|
||||
|
||||
type A = object
|
||||
b: int
|
||||
var t = A(b: 100)
|
||||
block:
|
||||
proc getValues: lent int =
|
||||
echo "hmm"
|
||||
result = t.b
|
||||
echo getValues()
|
||||
block:
|
||||
proc getValues: lent int =
|
||||
echo "hmm"
|
||||
t.b
|
||||
echo getValues()
|
||||
|
||||
when false: # still an issue, #16908
|
||||
template main =
|
||||
iterator fn[T](a:T): lent T = yield a
|
||||
let a = @[10]
|
||||
for b in fn(a): echo b
|
||||
|
||||
static: main()
|
||||
main()
|
||||
@@ -17,22 +17,26 @@ proc main =
|
||||
main()
|
||||
|
||||
template main2 = # bug #15958
|
||||
when defined(js):
|
||||
proc sameAddress[T](a, b: T): bool {.importjs: "(# === #)".}
|
||||
else:
|
||||
template sameAddress(a, b): bool = a.unsafeAddr == b.unsafeAddr
|
||||
proc byLent[T](a: T): lent T = a
|
||||
let a = [11,12]
|
||||
let b = @[21,23]
|
||||
let ss = {1, 2, 3, 5}
|
||||
doAssert byLent(a) == [11,12]
|
||||
doAssert byLent(a).unsafeAddr == a.unsafeAddr
|
||||
doAssert sameAddress(byLent(a), a)
|
||||
doAssert byLent(b) == @[21,23]
|
||||
when not defined(js): # pending bug #16073
|
||||
doAssert byLent(b).unsafeAddr == b.unsafeAddr
|
||||
# bug #16073
|
||||
doAssert sameAddress(byLent(b), b)
|
||||
doAssert byLent(ss) == {1, 2, 3, 5}
|
||||
doAssert byLent(ss).unsafeAddr == ss.unsafeAddr
|
||||
doAssert sameAddress(byLent(ss), ss)
|
||||
|
||||
let r = new(float)
|
||||
r[] = 10.0
|
||||
when not defined(js): # pending bug #16073
|
||||
doAssert byLent(r)[] == 10.0
|
||||
# bug #16073
|
||||
doAssert byLent(r)[] == 10.0
|
||||
|
||||
when not defined(js): # pending bug https://github.com/timotheecour/Nim/issues/372
|
||||
let p = create(float)
|
||||
@@ -41,9 +45,9 @@ template main2 = # bug #15958
|
||||
|
||||
proc byLent2[T](a: openarray[T]): lent T = a[0]
|
||||
doAssert byLent2(a) == 11
|
||||
doAssert byLent2(a).unsafeAddr == a[0].unsafeAddr
|
||||
doAssert sameAddress(byLent2(a), a[0])
|
||||
doAssert byLent2(b) == 21
|
||||
doAssert byLent2(b).unsafeAddr == b[0].unsafeAddr
|
||||
doAssert sameAddress(byLent2(b), b[0])
|
||||
|
||||
proc byLent3[T](a: varargs[T]): lent T = a[1]
|
||||
let
|
||||
|
||||
12
tests/objects/m19342.c
Normal file
12
tests/objects/m19342.c
Normal file
@@ -0,0 +1,12 @@
|
||||
struct Node
|
||||
{
|
||||
int data[25];
|
||||
};
|
||||
|
||||
|
||||
struct Node hello(int name) {
|
||||
struct Node x = {999, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7 ,8, 9,
|
||||
1, 2, 3, 4, 5};
|
||||
return x;
|
||||
}
|
||||
18
tests/objects/t19342.nim
Normal file
18
tests/objects/t19342.nim
Normal file
@@ -0,0 +1,18 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
"""
|
||||
|
||||
{.compile: "m19342.c".}
|
||||
|
||||
# bug #19342
|
||||
type
|
||||
Node* {.bycopy.} = object
|
||||
data: array[25, cint]
|
||||
|
||||
proc myproc(name: cint): Node {.importc: "hello", cdecl.}
|
||||
|
||||
proc parse =
|
||||
let node = myproc(10)
|
||||
doAssert node.data[0] == 999
|
||||
|
||||
parse()
|
||||
18
tests/objects/t19342_2.nim
Normal file
18
tests/objects/t19342_2.nim
Normal file
@@ -0,0 +1,18 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
"""
|
||||
|
||||
{.compile: "m19342.c".}
|
||||
|
||||
# bug #19342
|
||||
type
|
||||
Node* {.byRef.} = object
|
||||
data: array[25, cint]
|
||||
|
||||
proc myproc(name: cint): Node {.importc: "hello", cdecl.}
|
||||
|
||||
proc parse =
|
||||
let node = myproc(10)
|
||||
doAssert node.data[0] == 999
|
||||
|
||||
parse()
|
||||
9
tests/stdlib/concurrency/atomicSample.nim
Normal file
9
tests/stdlib/concurrency/atomicSample.nim
Normal file
@@ -0,0 +1,9 @@
|
||||
import atomics
|
||||
|
||||
type
|
||||
AtomicWithGeneric*[T] = object
|
||||
value: Atomic[T]
|
||||
|
||||
proc initAtomicWithGeneric*[T](value: T): AtomicWithGeneric[T] =
|
||||
result.value.store(value)
|
||||
|
||||
11
tests/stdlib/concurrency/tatomic_import.nim
Normal file
11
tests/stdlib/concurrency/tatomic_import.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
import atomicSample
|
||||
|
||||
block crossFileObjectContainingAGenericWithAComplexObject:
|
||||
discard initAtomicWithGeneric[string]("foo")
|
||||
|
||||
block crossFileObjectContainingAGenericWithAnInteger:
|
||||
discard initAtomicWithGeneric[int](1)
|
||||
discard initAtomicWithGeneric[int8](1)
|
||||
discard initAtomicWithGeneric[int16](1)
|
||||
discard initAtomicWithGeneric[int32](1)
|
||||
discard initAtomicWithGeneric[int64](1)
|
||||
@@ -233,6 +233,43 @@ template main =
|
||||
doAssert l.toSeq == [1]
|
||||
doAssert l.remove(l.head) == true
|
||||
doAssert l.toSeq == []
|
||||
|
||||
block issue19297: # add (appends a shallow copy)
|
||||
var a: SinglyLinkedList[int]
|
||||
var b: SinglyLinkedList[int]
|
||||
|
||||
doAssert a.toSeq == @[]
|
||||
a.add(1)
|
||||
doAssert a.toSeq == @[1]
|
||||
a.add(b)
|
||||
doAssert a.toSeq == @[1]
|
||||
a.add(2)
|
||||
doAssert a.toSeq == @[1, 2]
|
||||
|
||||
block issue19314: # add (appends a shallow copy)
|
||||
var a: DoublyLinkedList[int]
|
||||
var b: DoublyLinkedList[int]
|
||||
|
||||
doAssert a.toSeq == @[]
|
||||
a.add(1)
|
||||
doAssert a.toSeq == @[1]
|
||||
a.add(b)
|
||||
doAssert a.toSeq == @[1]
|
||||
a.add(2)
|
||||
doAssert a.toSeq == @[1, 2]
|
||||
|
||||
block RemoveLastNodeFromSinglyLinkedList:
|
||||
var list = initSinglyLinkedList[string]()
|
||||
let n1 = newSinglyLinkedNode("sonic")
|
||||
let n2 = newSinglyLinkedNode("the")
|
||||
let n3 = newSinglyLinkedNode("tiger")
|
||||
let n4 = newSinglyLinkedNode("hedgehog")
|
||||
list.add(n1)
|
||||
list.add(n2)
|
||||
list.add(n3)
|
||||
list.remove(n3)
|
||||
list.add(n4)
|
||||
doAssert list.toSeq == @["sonic", "the", "hedgehog"]
|
||||
|
||||
static: main()
|
||||
main()
|
||||
|
||||
@@ -66,3 +66,23 @@ block: # unpackVarargs
|
||||
doAssert call1(toString) == ""
|
||||
doAssert call1(toString, 10) == "10"
|
||||
doAssert call1(toString, 10, 11) == "1011"
|
||||
|
||||
block: # extractDocCommentsAndRunnables
|
||||
macro checkRunnables(prc: untyped) =
|
||||
let runnables = prc.body.extractDocCommentsAndRunnables()
|
||||
doAssert runnables[0][0].eqIdent("runnableExamples")
|
||||
|
||||
macro checkComments(comment: static[string], prc: untyped) =
|
||||
let comments = prc.body.extractDocCommentsAndRunnables()
|
||||
doAssert comments[0].strVal == comment
|
||||
|
||||
proc a() {.checkRunnables.} =
|
||||
runnableExamples: discard
|
||||
discard
|
||||
|
||||
proc b() {.checkRunnables.} =
|
||||
runnableExamples "-d:ssl": discard
|
||||
discard
|
||||
|
||||
proc c() {.checkComments("Hello world").} =
|
||||
## Hello world
|
||||
|
||||
@@ -108,4 +108,10 @@ proc testAll() =
|
||||
doAssert replace("foo", re"", "-") == "-f-o-o-"
|
||||
doAssert replace("ooo", re"o", "-") == "---"
|
||||
|
||||
block: # bug #14468
|
||||
accum = @[]
|
||||
for word in split("this is an example", re"\b"):
|
||||
accum.add(word)
|
||||
doAssert(accum == @["this", " ", "is", " ", "an", " ", "example"])
|
||||
|
||||
testAll()
|
||||
|
||||
@@ -44,6 +44,14 @@ template main() =
|
||||
proc parseInt(f: static[bool]): int {.used.} = discard
|
||||
|
||||
doAssert "123".parseInt == 123
|
||||
block:
|
||||
type
|
||||
MyType = object
|
||||
field: float32
|
||||
AType[T: static MyType] = distinct range[0f32 .. T.field]
|
||||
var a: AType[MyType(field: 5f32)]
|
||||
proc n(S: static Slice[int]): range[S.a..S.b] = discard
|
||||
assert typeof(n 1..2) is range[1..2]
|
||||
|
||||
|
||||
static: main()
|
||||
|
||||
Reference in New Issue
Block a user