mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 19:03:42 +00:00
Compare commits
39 Commits
v1.2.14
...
version-1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
772b62cdeb | ||
|
|
82e9ec3b5c | ||
|
|
7e3e04c469 | ||
|
|
f2bbff989f | ||
|
|
de715892ac | ||
|
|
24fb72c8ad | ||
|
|
7e5686a828 | ||
|
|
843c479593 | ||
|
|
7b35ce9812 | ||
|
|
0798bd020b | ||
|
|
c956aeae7f | ||
|
|
af3d1342c0 | ||
|
|
aa0dbaf3a1 | ||
|
|
8a5c8d3e22 | ||
|
|
315a286d7c | ||
|
|
1d92e79dac | ||
|
|
01c8262426 | ||
|
|
5e102df04d | ||
|
|
57c9de181a | ||
|
|
eeea72060c | ||
|
|
0b1fee5d66 | ||
|
|
594831620b | ||
|
|
2eb0442a9a | ||
|
|
002621b61d | ||
|
|
8ea5475dd9 | ||
|
|
3e6d708175 | ||
|
|
e3fb2c21d7 | ||
|
|
c4ab020f0f | ||
|
|
6e4fdbc4a9 | ||
|
|
497d061cd1 | ||
|
|
4cb522fb8a | ||
|
|
84c1b1af0e | ||
|
|
a683ca3fac | ||
|
|
f7ea7b3c4f | ||
|
|
a34845b66c | ||
|
|
79f95a2efc | ||
|
|
8a3f542532 | ||
|
|
2009df72cb | ||
|
|
f4216f12b3 |
2
.github/workflows/ci_docs.yml
vendored
2
.github/workflows/ci_docs.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
- target: windows
|
||||
os: windows-2019
|
||||
- target: osx
|
||||
os: macos-10.15
|
||||
os: macos-11
|
||||
|
||||
name: ${{ matrix.target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -15,23 +15,23 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
Linux_amd64:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
vmImage: 'ubuntu-18.04'
|
||||
CPU: amd64
|
||||
Linux_i386:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
vmImage: 'ubuntu-18.04'
|
||||
CPU: i386
|
||||
OSX_amd64:
|
||||
vmImage: 'macOS-10.15'
|
||||
vmImage: 'macOS-11'
|
||||
CPU: amd64
|
||||
OSX_amd64_cpp:
|
||||
vmImage: 'macOS-10.15'
|
||||
vmImage: 'macOS-11'
|
||||
CPU: amd64
|
||||
NIM_COMPILE_TO_CPP: true
|
||||
Windows_amd64:
|
||||
vmImage: 'windows-2019'
|
||||
CPU: amd64
|
||||
Linux_amd64_pkg:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
vmImage: 'ubuntu-18.04'
|
||||
CPU: amd64
|
||||
NIM_TEST_PACKAGES: true
|
||||
OSX_amd64_pkg:
|
||||
|
||||
@@ -2741,6 +2741,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
inc p.splitDecls
|
||||
genGotoState(p, n)
|
||||
of nkBreakState: genBreakState(p, n, d)
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
||||
|
||||
proc genNamedConstExpr(p: BProc, n: PNode; isConst: bool): Rope =
|
||||
|
||||
@@ -1330,8 +1330,19 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimSigSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimBuiltinSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = __builtin_setjmp($1.context);$n", [safePoint])
|
||||
elif isDefined(p.config, "nimRawSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
|
||||
if isDefined(p.config, "mswindows"):
|
||||
# The Windows `_setjmp()` takes two arguments, with the second being an
|
||||
# undocumented buffer used by the SEH mechanism for stack unwinding.
|
||||
# Mingw-w64 has been trying to get it right for years, but it's still
|
||||
# prone to stack corruption during unwinding, so we disable that by setting
|
||||
# it to NULL.
|
||||
# More details: https://github.com/status-im/nimbus-eth2/issues/3121
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context, 0);$n", [safePoint])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
|
||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||
|
||||
@@ -220,7 +220,8 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool =
|
||||
# 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: result = true
|
||||
if rettype == nil or (tfByCopy notin rettype.flags and getSize(conf, rettype) > conf.target.floatSize*3):
|
||||
result = true
|
||||
else:
|
||||
case mapType(conf, rettype)
|
||||
of ctArray:
|
||||
|
||||
@@ -432,8 +432,14 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
|
||||
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
|
||||
linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
|
||||
elif not isComplexValueType(typ):
|
||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
||||
getTypeDesc(p.module, typ)])
|
||||
if containsGarbageCollectedRef(loc.t):
|
||||
var nilLoc: TLoc
|
||||
initLoc(nilLoc, locTemp, loc.lode, OnStack)
|
||||
nilLoc.r = rope("NIM_NIL")
|
||||
genRefAssign(p, loc, nilLoc)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
||||
getTypeDesc(p.module, typ)])
|
||||
else:
|
||||
if not isTemp or containsGarbageCollectedRef(loc.t):
|
||||
# don't use nimZeroMem for temporary values for performance if we can
|
||||
@@ -838,7 +844,8 @@ proc containsResult(n: PNode): bool =
|
||||
for i in 0..<n.safeLen:
|
||||
if containsResult(n[i]): return true
|
||||
|
||||
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef, nkMacroDef} +
|
||||
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef,
|
||||
nkMacroDef, nkMixinStmt, nkBindStmt} +
|
||||
declarativeDefs
|
||||
|
||||
proc easyResultAsgn(n: PNode): PNode =
|
||||
|
||||
@@ -121,7 +121,10 @@
|
||||
# yield 2
|
||||
# if :unrollFinally: # This node is created by `newEndFinallyNode`
|
||||
# if :curExc.isNil:
|
||||
# return :tmpResult
|
||||
# if nearestFinally == 0:
|
||||
# return :tmpResult
|
||||
# else:
|
||||
# :state = nearestFinally # bubble up
|
||||
# else:
|
||||
# closureIterSetupExc(nil)
|
||||
# raise
|
||||
@@ -156,7 +159,7 @@ type
|
||||
|
||||
const
|
||||
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
|
||||
nkCommentStmt} + procDefs
|
||||
nkCommentStmt, nkMixinStmt, nkBindStmt} + procDefs
|
||||
|
||||
proc newStateAccess(ctx: var Ctx): PNode =
|
||||
if ctx.stateVarSym.isNil:
|
||||
@@ -793,7 +796,10 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
# Generate the following code:
|
||||
# if :unrollFinally:
|
||||
# if :curExc.isNil:
|
||||
# return :tmpResult
|
||||
# if nearestFinally == 0:
|
||||
# return :tmpResult
|
||||
# else:
|
||||
# :state = nearestFinally # bubble up
|
||||
# else:
|
||||
# raise
|
||||
let curExc = ctx.newCurExcAccess()
|
||||
@@ -802,11 +808,17 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
let cmp = newTree(nkCall, newSymNode(ctx.g.getSysMagic(info, "==", mEqRef), info), curExc, nilnode)
|
||||
cmp.typ = ctx.g.getSysType(info, tyBool)
|
||||
|
||||
let asgn = newTree(nkFastAsgn,
|
||||
newSymNode(getClosureIterResult(ctx.g, ctx.fn), info),
|
||||
ctx.newTmpResultAccess())
|
||||
let retStmt =
|
||||
if ctx.nearestFinally == 0:
|
||||
# last finally, we can return
|
||||
let asgn = newTree(nkFastAsgn,
|
||||
newSymNode(getClosureIterResult(ctx.g, ctx.fn), info),
|
||||
ctx.newTmpResultAccess())
|
||||
newTree(nkReturnStmt, asgn)
|
||||
else:
|
||||
# bubble up to next finally
|
||||
newTree(nkGotoState, ctx.g.newIntLit(info, ctx.nearestFinally))
|
||||
|
||||
let retStmt = newTree(nkReturnStmt, asgn)
|
||||
let branch = newTree(nkElifBranch, cmp, retStmt)
|
||||
|
||||
let nullifyExc = newTree(nkCall, newSymNode(ctx.g.getCompilerProc("closureIterSetupExc")), nilnode)
|
||||
@@ -850,6 +862,13 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
|
||||
of nkSkip:
|
||||
discard
|
||||
of nkTryStmt:
|
||||
if n.hasYields:
|
||||
# the inner try will handle these transformations
|
||||
discard
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
n[i] = ctx.transformReturnsInTry(n[i])
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
n[i] = ctx.transformReturnsInTry(n[i])
|
||||
|
||||
@@ -225,7 +225,7 @@ const
|
||||
errNoneBoehmRefcExpectedButXFound = "'none', 'boehm' or 'refc' expected, but '$1' found"
|
||||
errNoneSpeedOrSizeExpectedButXFound = "'none', 'speed' or 'size' expected, but '$1' found"
|
||||
errGuiConsoleOrLibExpectedButXFound = "'gui', 'console' or 'lib' expected, but '$1' found"
|
||||
errInvalidExceptionSystem = "'goto', 'setjump', 'cpp' or 'quirky' expected, but '$1' found"
|
||||
errInvalidExceptionSystem = "'goto', 'setjmp', 'cpp' or 'quirky' expected, but '$1' found"
|
||||
|
||||
proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo): bool =
|
||||
case switch.normalize
|
||||
|
||||
@@ -651,6 +651,10 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile,
|
||||
if useCpp(conf, cfile.cname):
|
||||
options.add(' ' & CC[c].cppXsupport)
|
||||
|
||||
if cfile.customArgs != "":
|
||||
options.add ' '
|
||||
options.add cfile.customArgs
|
||||
|
||||
var compilePattern: string
|
||||
# compute include paths:
|
||||
var includeCmd = CC[c].includeCmd & quoteShell(conf.libpath)
|
||||
|
||||
@@ -945,7 +945,8 @@ proc p(n: PNode; c: var Con; mode: ProcessMode): PNode =
|
||||
of nkNone..nkNilLit, nkTypeSection, nkProcDef, nkConverterDef,
|
||||
nkMethodDef, nkIteratorDef, nkMacroDef, nkTemplateDef, nkLambda, nkDo,
|
||||
nkFuncDef, nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState:
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkMixinStmt, nkBindStmt:
|
||||
result = n
|
||||
of nkBreakStmt:
|
||||
inc c.hasUnstructuredCf
|
||||
|
||||
@@ -2479,7 +2479,8 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkRaiseStmt: genRaiseStmt(p, n)
|
||||
of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt,
|
||||
nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt,
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt: discard
|
||||
nkFromStmt, nkTemplateDef, nkMacroDef, nkStaticStmt,
|
||||
nkMixinStmt, nkBindStmt: discard
|
||||
of nkPragma: genPragma(p, n)
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef:
|
||||
var s = n[namePos].sym
|
||||
|
||||
@@ -493,7 +493,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
w = up
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef,
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt, nkTypeOfExpr:
|
||||
nkConverterDef, nkMacroDef, nkFuncDef, nkCommentStmt,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
discard
|
||||
of nkLambdaKinds, nkIteratorDef:
|
||||
if n.typ != nil:
|
||||
@@ -747,7 +748,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||
result = accessViaEnvVar(n, owner, d, c)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
|
||||
nkTemplateDef, nkTypeSection, nkProcDef, nkMethodDef, nkConverterDef,
|
||||
nkMacroDef, nkFuncDef:
|
||||
nkMacroDef, nkFuncDef, nkMixinStmt, nkBindStmt:
|
||||
discard
|
||||
of nkClosure:
|
||||
if n[1].kind == nkNilLit:
|
||||
|
||||
@@ -42,7 +42,7 @@ proc liftLocals(n: PNode; i: int; c: var Ctx) =
|
||||
of nkSym:
|
||||
if interestingVar(it.sym):
|
||||
n[i] = lookupOrAdd(c, it.sym, it.info)
|
||||
of procDefs, nkTypeSection: discard
|
||||
of procDefs, nkTypeSection, nkMixinStmt, nkBindStmt: discard
|
||||
else:
|
||||
for i in 0..<it.safeLen:
|
||||
liftLocals(it, i, c)
|
||||
|
||||
@@ -181,6 +181,7 @@ type
|
||||
nimname*: string
|
||||
cname*, obj*: AbsoluteFile
|
||||
flags*: set[CfileFlag]
|
||||
customArgs*: string
|
||||
CfileList* = seq[Cfile]
|
||||
|
||||
Suggest* = ref object
|
||||
|
||||
@@ -92,11 +92,10 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
|
||||
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords;
|
||||
isStatement: bool = false)
|
||||
|
||||
proc recordPragma(c: PContext; n: PNode; key, val: string; val2 = "") =
|
||||
proc recordPragma(c: PContext; n: PNode; args: varargs[string]) =
|
||||
var recorded = newNodeI(nkCommentStmt, n.info)
|
||||
recorded.add newStrNode(key, n.info)
|
||||
recorded.add newStrNode(val, n.info)
|
||||
if val2.len > 0: recorded.add newStrNode(val2, n.info)
|
||||
for i in 0..args.high:
|
||||
recorded.add newStrNode(args[i], n.info)
|
||||
c.graph.recordStmt(c.graph, c.module, recorded)
|
||||
|
||||
const
|
||||
@@ -496,11 +495,12 @@ proc relativeFile(c: PContext; n: PNode; ext=""): AbsoluteFile =
|
||||
if result.isEmpty: result = AbsoluteFile s
|
||||
|
||||
proc processCompile(c: PContext, n: PNode) =
|
||||
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile) =
|
||||
proc docompile(c: PContext; it: PNode; src, dest: AbsoluteFile; customArgs: string) =
|
||||
var cf = Cfile(nimname: splitFile(src).name,
|
||||
cname: src, obj: dest, flags: {CfileFlag.External})
|
||||
cname: src, obj: dest, flags: {CfileFlag.External},
|
||||
customArgs: customArgs)
|
||||
extccomp.addExternalFileToCompile(c.config, cf)
|
||||
recordPragma(c, it, "compile", src.string, dest.string)
|
||||
recordPragma(c, it, "compile", src.string, dest.string, customArgs)
|
||||
|
||||
proc getStrLit(c: PContext, n: PNode; i: int): string =
|
||||
n[i] = c.semConstExpr(c, n[i])
|
||||
@@ -518,9 +518,19 @@ proc processCompile(c: PContext, n: PNode) =
|
||||
var found = parentDir(toFullPath(c.config, n.info)) / s
|
||||
for f in os.walkFiles(found):
|
||||
let obj = completeCfilePath(c.config, AbsoluteFile(dest % extractFilename(f)))
|
||||
docompile(c, it, AbsoluteFile f, obj)
|
||||
docompile(c, it, AbsoluteFile f, obj, "")
|
||||
else:
|
||||
let s = expectStrLit(c, n)
|
||||
var s = ""
|
||||
var customArgs = ""
|
||||
if n.kind in nkCallKinds:
|
||||
s = getStrLit(c, n, 1)
|
||||
if n.len <= 3:
|
||||
customArgs = getStrLit(c, n, 2)
|
||||
else:
|
||||
localError(c.config, n.info, "'.compile' pragma takes up 2 arguments")
|
||||
else:
|
||||
s = expectStrLit(c, n)
|
||||
|
||||
var found = AbsoluteFile(parentDir(toFullPath(c.config, n.info)) / s)
|
||||
if not fileExists(found):
|
||||
if isAbsolute(s): found = AbsoluteFile s
|
||||
@@ -528,7 +538,7 @@ proc processCompile(c: PContext, n: PNode) =
|
||||
found = findFile(c.config, s)
|
||||
if found.isEmpty: found = AbsoluteFile s
|
||||
let obj = toObjFile(c.config, completeCfilePath(c.config, found, false))
|
||||
docompile(c, it, found, obj)
|
||||
docompile(c, it, found, obj, customArgs)
|
||||
|
||||
proc processLink(c: PContext, n: PNode) =
|
||||
let found = relativeFile(c, n, CC[c.config.cCompiler].objExt)
|
||||
|
||||
@@ -150,6 +150,7 @@ proc putNL(g: var TSrcGen) =
|
||||
proc optNL(g: var TSrcGen, indent: int) =
|
||||
g.pendingNL = indent
|
||||
g.lineLen = indent
|
||||
g.col = g.indent
|
||||
when defined(nimpretty): g.pendingNewlineCount = 0
|
||||
|
||||
proc optNL(g: var TSrcGen) =
|
||||
@@ -158,6 +159,7 @@ proc optNL(g: var TSrcGen) =
|
||||
proc optNL(g: var TSrcGen; a, b: PNode) =
|
||||
g.pendingNL = g.indent
|
||||
g.lineLen = g.indent
|
||||
g.col = g.indent
|
||||
when defined(nimpretty): g.pendingNewlineCount = lineDiff(a, b)
|
||||
|
||||
proc indentNL(g: var TSrcGen) =
|
||||
|
||||
@@ -106,6 +106,7 @@ proc computeDeps(cache: IdentCache; n: PNode, declares, uses: var IntSet; topLev
|
||||
decl(a[1])
|
||||
else:
|
||||
for i in 0..<n.safeLen: deps(n[i])
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else:
|
||||
for i in 0..<n.safeLen: deps(n[i])
|
||||
|
||||
|
||||
@@ -838,11 +838,12 @@ proc replay(g: ModuleGraph; module: PSym; n: PNode) =
|
||||
of "warning": message(g.config, n.info, warnUser, n[1].strVal)
|
||||
of "error": localError(g.config, n.info, errUser, n[1].strVal)
|
||||
of "compile":
|
||||
internalAssert g.config, n.len == 3 and n[2].kind == nkStrLit
|
||||
internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit
|
||||
let cname = AbsoluteFile n[1].strVal
|
||||
var cf = Cfile(nimname: splitFile(cname).name, cname: cname,
|
||||
obj: AbsoluteFile n[2].strVal,
|
||||
flags: {CfileFlag.External})
|
||||
flags: {CfileFlag.External},
|
||||
customArgs: n[3].strVal)
|
||||
extccomp.addExternalFileToCompile(g.config, cf)
|
||||
of "link":
|
||||
extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal)
|
||||
|
||||
@@ -38,6 +38,7 @@ type
|
||||
mappingExists*: bool
|
||||
mapping*: TIdTable
|
||||
caseContext*: seq[tuple[n: PNode, idx: int]]
|
||||
localBindStmts*: seq[PNode]
|
||||
|
||||
TMatchedConcept* = object
|
||||
candidateType*: PType
|
||||
|
||||
@@ -2833,6 +2833,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
for i in 0..<n.len:
|
||||
n[i] = semExpr(c, n[i])
|
||||
of nkComesFrom: discard "ignore the comes from information for now"
|
||||
of nkMixinStmt: discard
|
||||
of nkBindStmt:
|
||||
if c.p != nil:
|
||||
c.p.localBindStmts.add n
|
||||
else:
|
||||
localError(c.config, n.info, "invalid context for 'bind' statement: " &
|
||||
renderTree(n, {renderNoComments}))
|
||||
else:
|
||||
localError(c.config, n.info, "invalid expression: " &
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
@@ -164,7 +164,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, g)
|
||||
of mBitnotI:
|
||||
if n.typ.isUnsigned:
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(n.typ.size)), n, g)
|
||||
result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(getSize(g.config, n.typ))), n, g)
|
||||
else:
|
||||
result = newIntNodeT(bitnot(getInt(a)), n, g)
|
||||
of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
|
||||
@@ -276,23 +276,23 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
||||
of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g)
|
||||
of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, g)
|
||||
of mAddU:
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) + getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mSubU:
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) - getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, g)
|
||||
# echo "subU: ", val, " n: ", n, " result: ", val
|
||||
of mMulU:
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(n.typ.size))
|
||||
let val = maskBytes(getInt(a) * getInt(b), int(getSize(g.config, n.typ)))
|
||||
result = newIntNodeT(val, n, g)
|
||||
of mModU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
|
||||
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA mod argB, n, g)
|
||||
of mDivU:
|
||||
let argA = maskBytes(getInt(a), int(a.typ.size))
|
||||
let argB = maskBytes(getInt(b), int(a.typ.size))
|
||||
let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
|
||||
let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
|
||||
if argB != Zero:
|
||||
result = newIntNodeT(argA div argB, n, g)
|
||||
of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, g)
|
||||
|
||||
@@ -319,6 +319,14 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
|
||||
prc.typ = result
|
||||
popInfoContext(c.config)
|
||||
|
||||
proc fillMixinScope(c: PContext) =
|
||||
var p = c.p
|
||||
while p != nil:
|
||||
for bnd in p.localBindStmts:
|
||||
for n in bnd:
|
||||
addSym(c.currentScope, n.sym)
|
||||
p = p.next
|
||||
|
||||
proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
info: TLineInfo): PSym =
|
||||
## Generates a new instance of a generic procedure.
|
||||
@@ -345,6 +353,10 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
result.ast = n
|
||||
pushOwner(c, result)
|
||||
|
||||
# mixin scope:
|
||||
openScope(c)
|
||||
fillMixinScope(c)
|
||||
|
||||
openScope(c)
|
||||
let gp = n[genericParamsPos]
|
||||
internalAssert c.config, gp.kind != nkEmpty
|
||||
@@ -395,6 +407,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
popProcCon(c)
|
||||
popInfoContext(c.config)
|
||||
closeScope(c) # close scope for parameters
|
||||
closeScope(c) # close scope for 'mixin' declarations
|
||||
popOwner(c)
|
||||
c.currentScope = oldScope
|
||||
discard c.friendModules.pop()
|
||||
|
||||
@@ -359,12 +359,17 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
|
||||
while objType.kind != tyObject:
|
||||
objType = objType.lastSon
|
||||
assert objType != nil
|
||||
var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
|
||||
let initResult = semConstructTypeAux(c, constrCtx, {})
|
||||
assert constrCtx.missingFields.len > 0
|
||||
localError(c.config, info,
|
||||
"The $1 type doesn't have a default value. The following fields must be initialized: $2.",
|
||||
[typeToString(t), listSymbolNames(constrCtx.missingFields)])
|
||||
if objType.kind == tyObject:
|
||||
var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
|
||||
let initResult = semConstructTypeAux(c, constrCtx, {})
|
||||
if constrCtx.missingFields.len > 0:
|
||||
localError(c.config, info,
|
||||
"The $1 type doesn't have a default value. The following fields must be initialized: $2." % [typeToString(t), listSymbolNames(constrCtx.missingFields)])
|
||||
elif objType.kind == tyDistinct:
|
||||
localError(c.config, info,
|
||||
"The $1 distinct type doesn't have a default value." % typeToString(t))
|
||||
else:
|
||||
assert false, "Must not enter here."
|
||||
|
||||
proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var t = semTypeNode(c, n[0], nil)
|
||||
|
||||
@@ -391,7 +391,8 @@ proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
addFactNeg(c.guards, canon(n[0], c.guards.o))
|
||||
dec c.inLoop
|
||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef:
|
||||
nkMacroDef, nkTemplateDef, nkConstSection, nkPragma, nkFuncDef,
|
||||
nkMixinStmt, nkBindStmt, nkExportStmt:
|
||||
discard
|
||||
else:
|
||||
analyseSons(c, n)
|
||||
|
||||
@@ -1828,8 +1828,8 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
|
||||
let t = tt[col]
|
||||
if t != nil and t.kind == tyGenericInvocation:
|
||||
var x = skipTypes(t[0], {tyVar, tyLent, tyPtr, tyRef, tyGenericInst,
|
||||
tyGenericInvocation, tyGenericBody,
|
||||
tyAlias, tySink, tyOwned})
|
||||
tyGenericInvocation, tyGenericBody,
|
||||
tyAlias, tySink, tyOwned})
|
||||
if x.kind == tyObject and t.len-1 == n[genericParamsPos].len:
|
||||
foundObj = true
|
||||
x.methods.add((col,s))
|
||||
|
||||
@@ -86,6 +86,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
|
||||
a = nextOverloadIter(o, c, n)
|
||||
|
||||
proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
var a = n[i]
|
||||
# If 'a' is an overloaded symbol, we used to use the first symbol
|
||||
@@ -99,16 +100,24 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
|
||||
let sc = symChoice(c, n, s, scClosed)
|
||||
if sc.kind == nkSym:
|
||||
toBind.incl(sc.sym.id)
|
||||
result.add sc
|
||||
else:
|
||||
for x in items(sc): toBind.incl(x.sym.id)
|
||||
for x in items(sc):
|
||||
toBind.incl(x.sym.id)
|
||||
result.add x
|
||||
else:
|
||||
illFormedAst(a, c.config)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
|
||||
proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
|
||||
result = copyNode(n)
|
||||
var count = 0
|
||||
for i in 0..<n.len:
|
||||
toMixin.incl(considerQuotedIdent(c, n[i]).id)
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
let x = symChoice(c, n[i], nil, scForceOpen)
|
||||
inc count, x.len
|
||||
result.add x
|
||||
if count == 0:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
|
||||
proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
|
||||
case n.kind
|
||||
|
||||
@@ -993,7 +993,7 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkConstSection:
|
||||
# do not replace ``const c = 3`` with ``const 3 = 3``
|
||||
return transformConstSection(c, n)
|
||||
of nkTypeSection, nkTypeOfExpr:
|
||||
of nkTypeSection, nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
# no need to transform type sections:
|
||||
return n
|
||||
of nkVarSection, nkLetSection:
|
||||
|
||||
@@ -2106,7 +2106,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
else:
|
||||
dest = tmp0
|
||||
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
|
||||
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt:
|
||||
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt, nkExportStmt,
|
||||
nkMixinStmt, nkBindStmt:
|
||||
unused(c, n, dest)
|
||||
of nkStringToCString, nkCStringToString:
|
||||
gen(c, n[0], dest)
|
||||
|
||||
@@ -3,3 +3,13 @@
|
||||
when defined(nimHasCppDefine):
|
||||
cppDefine "errno"
|
||||
cppDefine "unix"
|
||||
|
||||
# mangle the macro names in nimbase.h
|
||||
cppDefine "NAN_INFINITY"
|
||||
cppDefine "INF"
|
||||
cppDefine "NAN"
|
||||
|
||||
when defined(windows) and not defined(booting):
|
||||
# Avoid some rare stack corruption while using exceptions with a SEH-enabled
|
||||
# toolchain: https://github.com/nim-lang/Nim/pull/19197
|
||||
switch("define", "nimRawSetjmp")
|
||||
|
||||
@@ -47,9 +47,11 @@ The commands to compile to either C, C++ or Objective-C are:
|
||||
The most significant difference between these commands is that if you look
|
||||
into the ``nimcache`` directory you will find ``.c``, ``.cpp`` or ``.m``
|
||||
files, other than that all of them will produce a native binary for your
|
||||
project. This allows you to take the generated code and place it directly
|
||||
into a project using any of these languages. Here are some typical command
|
||||
line invocations::
|
||||
project. This allows you to take the generated code and place it directly
|
||||
into a project using any of these languages. Here are some typical command-
|
||||
line invocations:
|
||||
|
||||
.. code:: cmd
|
||||
|
||||
$ nim c hallo.nim
|
||||
$ nim cpp hallo.nim
|
||||
@@ -108,8 +110,8 @@ Nim code calling the backend
|
||||
Nim code can interface with the backend through the `Foreign function
|
||||
interface <manual.html#foreign-function-interface>`_ mainly through the
|
||||
`importc pragma <manual.html#foreign-function-interface-importc-pragma>`_.
|
||||
The ``importc`` pragma is the *generic* way of making backend symbols available
|
||||
in Nim and is available in all the target backends (JavaScript too). The C++
|
||||
The `importc` pragma is the *generic* way of making backend symbols available
|
||||
in Nim and is available in all the target backends (JavaScript too). The C++
|
||||
or Objective-C backends have their respective `ImportCpp
|
||||
<manual.html#implementation-specific-pragmas-importcpp-pragma>`_ and
|
||||
`ImportObjC <manual.html#implementation-specific-pragmas-importobjc-pragma>`_
|
||||
@@ -230,11 +232,6 @@ Also, C code requires you to specify a forward declaration for functions or
|
||||
the compiler will assume certain types for the return value and parameters
|
||||
which will likely make your program crash at runtime.
|
||||
|
||||
The Nim compiler can generate a C interface header through the ``--header``
|
||||
command line switch. The generated header will contain all the exported
|
||||
symbols and the ``NimMain`` proc which you need to call before any other
|
||||
Nim code.
|
||||
|
||||
|
||||
Nim invocation example from C
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -253,9 +250,10 @@ Create a ``maths.c`` file with the following content:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#include "fib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
extern int fib(int a);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
NimMain();
|
||||
@@ -268,13 +266,14 @@ Now you can run the following Unix like commands to first generate C sources
|
||||
form the Nim code, then link them into a static binary along your main C
|
||||
program::
|
||||
|
||||
$ nim c --noMain --noLinking --header:fib.h fib.nim
|
||||
$ gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
|
||||
.. code:: cmd
|
||||
|
||||
nim c --noMain --noLinking fib.nim
|
||||
gcc -o m -I$HOME/.cache/nim/fib_d -Ipath/to/nim/lib $HOME/.cache/nim/fib_d/*.c maths.c
|
||||
|
||||
The first command runs the Nim compiler with three special options to avoid
|
||||
generating a ``main()`` function in the generated files, avoid linking the
|
||||
object files into a final binary, and explicitly generate a header file for C
|
||||
integration. All the generated files are placed into the ``nimcache``
|
||||
generating a `main()`:c: function in the generated files and to avoid linking the
|
||||
object files into a final binary. All the generated files are placed into the ``nimcache``
|
||||
directory. That's why the next command compiles the ``maths.c`` source plus
|
||||
all the ``.c`` files form ``nimcache``. In addition to this path, you also
|
||||
have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
|
||||
@@ -282,12 +281,12 @@ have to tell the C compiler where to find Nim's ``nimbase.h`` header file.
|
||||
Instead of depending on the generation of the individual ``.c`` files you can
|
||||
also ask the Nim compiler to generate a statically linked library::
|
||||
|
||||
$ nim c --app:staticLib --noMain --header fib.nim
|
||||
$ gcc -o m -Inimcache -Ipath/to/nim/lib libfib.nim.a maths.c
|
||||
nim c --app:staticLib --noMain fib.nim
|
||||
gcc -o m -Inimcache -Ipath/to/nim/lib libfib.nim.a maths.c
|
||||
|
||||
The Nim compiler will handle linking the source files generated in the
|
||||
``nimcache`` directory into the ``libfib.nim.a`` static library, which you can
|
||||
then link into your C program. Note that these commands are generic and will
|
||||
then link into your C program. Note that these commands are generic and will
|
||||
vary for each system. For instance, on Linux systems you will likely need to
|
||||
use ``-ldl`` too to link in required dlopen functionality.
|
||||
|
||||
|
||||
@@ -4789,6 +4789,50 @@ scope is the default.
|
||||
``bind`` statements only make sense in templates and generics.
|
||||
|
||||
|
||||
Delegating bind statements
|
||||
--------------------------
|
||||
|
||||
The following example outlines a problem that can arise when generic
|
||||
instantiations cross multiple different modules:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
# module A
|
||||
proc genericA*[T](x: T) =
|
||||
mixin init
|
||||
init(x)
|
||||
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
import C
|
||||
|
||||
# module B
|
||||
proc genericB*[T](x: T) =
|
||||
# Without the `bind init` statement C's init proc is
|
||||
# not available when `genericB` is instantiated:
|
||||
bind init
|
||||
genericA(x)
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
# module C
|
||||
type O = object
|
||||
proc init*(x: var O) = discard
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
# module main
|
||||
import B, C
|
||||
|
||||
genericB O()
|
||||
|
||||
In module B has an `init` proc from module C in its scope that is not
|
||||
taken into account when `genericB` is instantiated which leads to the
|
||||
instantiation of `genericA`. The solution is to `forward`:idx these
|
||||
symbols by a `bind` statement inside `genericB`.
|
||||
|
||||
|
||||
Templates
|
||||
=========
|
||||
|
||||
@@ -6608,6 +6652,14 @@ with the project:
|
||||
has changed. One can use the ``-f`` command line option to force recompilation
|
||||
of the file.
|
||||
|
||||
Since 1.4 the `compile` pragma is also available with this syntax:
|
||||
|
||||
.. code-block:: Nim
|
||||
{.compile("myfile.cpp", "--custom flags here").}
|
||||
|
||||
As can be seen in the example, this new variant allows for custom flags
|
||||
that are passed to the C compiler when the file is recompiled.
|
||||
|
||||
|
||||
Link pragma
|
||||
-----------
|
||||
|
||||
16
doc/nimc.rst
16
doc/nimc.rst
@@ -149,6 +149,22 @@ ignored too. ``--define:FOO`` and ``--define:foo`` are identical.
|
||||
Compile time symbols starting with the ``nim`` prefix are reserved for the
|
||||
implementation and should not be used elsewhere.
|
||||
|
||||
========================== ============================================
|
||||
Name Description
|
||||
========================== ============================================
|
||||
nimStdSetjmp Use the standard `setjmp()/longjmp()` library
|
||||
functions for setjmp-based exceptions. This is
|
||||
the default on most platforms.
|
||||
nimSigSetjmp Use `sigsetjmp()/siglongjmp()` for setjmp-based exceptions.
|
||||
nimRawSetjmp Use `_setjmp()/_longjmp()` on POSIX and `_setjmp()/longjmp()`
|
||||
on Windows, for setjmp-based exceptions. It's the default on
|
||||
BSDs and BSD-like platforms, where it's significantly faster
|
||||
than the standard functions.
|
||||
nimBuiltinSetjmp Use `__builtin_setjmp()/__builtin_longjmp()` for setjmp-based
|
||||
exceptions. This will not work if an exception is being thrown
|
||||
and caught inside the same procedure. Useful for benchmarking.
|
||||
========================== ============================================
|
||||
|
||||
|
||||
Configuration files
|
||||
-------------------
|
||||
|
||||
@@ -181,6 +181,8 @@ type
|
||||
of JArray:
|
||||
elems*: seq[JsonNode]
|
||||
|
||||
const DepthLimit = 1000
|
||||
|
||||
proc newJString*(s: string): JsonNode =
|
||||
## Creates a new `JString JsonNode`.
|
||||
result = JsonNode(kind: JString, str: s)
|
||||
@@ -771,7 +773,7 @@ iterator mpairs*(node: var JsonNode): tuple[key: string, val: var JsonNode] =
|
||||
for key, val in mpairs(node.fields):
|
||||
yield (key, val)
|
||||
|
||||
proc parseJson(p: var JsonParser): JsonNode =
|
||||
proc parseJson(p: var JsonParser, depth=0): JsonNode =
|
||||
## Parses JSON from a JSON Parser `p`.
|
||||
case p.tok
|
||||
of tkString:
|
||||
@@ -795,6 +797,8 @@ proc parseJson(p: var JsonParser): JsonNode =
|
||||
result = newJNull()
|
||||
discard getTok(p)
|
||||
of tkCurlyLe:
|
||||
if depth > DepthLimit:
|
||||
raiseParseErr(p, "}")
|
||||
result = newJObject()
|
||||
discard getTok(p)
|
||||
while p.tok != tkCurlyRi:
|
||||
@@ -803,16 +807,18 @@ proc parseJson(p: var JsonParser): JsonNode =
|
||||
var key = p.a
|
||||
discard getTok(p)
|
||||
eat(p, tkColon)
|
||||
var val = parseJson(p)
|
||||
var val = parseJson(p, depth+1)
|
||||
result[key] = val
|
||||
if p.tok != tkComma: break
|
||||
discard getTok(p)
|
||||
eat(p, tkCurlyRi)
|
||||
of tkBracketLe:
|
||||
if depth > DepthLimit:
|
||||
raiseParseErr(p, "]")
|
||||
result = newJArray()
|
||||
discard getTok(p)
|
||||
while p.tok != tkBracketRi:
|
||||
result.add(parseJson(p))
|
||||
result.add(parseJson(p, depth+1))
|
||||
if p.tok != tkComma: break
|
||||
discard getTok(p)
|
||||
eat(p, tkBracketRi)
|
||||
|
||||
@@ -12,24 +12,24 @@
|
||||
## produce a globally distributed unique ID. This implementation was extracted
|
||||
## from the Mongodb interface and it thus binary compatible with a Mongo OID.
|
||||
##
|
||||
## This implementation calls ``math.randomize()`` for the first call of
|
||||
## This implementation calls `initRand()` for the first call of
|
||||
## ``genOid``.
|
||||
|
||||
import hashes, times, endians
|
||||
import hashes, times, endians, random
|
||||
|
||||
type
|
||||
Oid* = object ## an OID
|
||||
Oid* = object ## An OID.
|
||||
time: int32 ##
|
||||
fuzz: int32 ##
|
||||
count: int32 ##
|
||||
|
||||
proc `==`*(oid1: Oid, oid2: Oid): bool =
|
||||
## Compare two Mongo Object IDs for equality
|
||||
## Compares two Mongo Object IDs for equality.
|
||||
return (oid1.time == oid2.time) and (oid1.fuzz == oid2.fuzz) and
|
||||
(oid1.count == oid2.count)
|
||||
|
||||
proc hash*(oid: Oid): Hash =
|
||||
## Generate hash of Oid for use in hashtables
|
||||
## Generates hash of Oid for use in hashtables.
|
||||
var h: Hash = 0
|
||||
h = h !& hash(oid.time)
|
||||
h = h !& hash(oid.fuzz)
|
||||
@@ -44,7 +44,7 @@ proc hexbyte*(hex: char): int =
|
||||
else: discard
|
||||
|
||||
proc parseOid*(str: cstring): Oid =
|
||||
## parses an OID.
|
||||
## Parses an OID.
|
||||
var bytes = cast[cstring](addr(result.time))
|
||||
var i = 0
|
||||
while i < 12:
|
||||
@@ -52,6 +52,7 @@ proc parseOid*(str: cstring): Oid =
|
||||
inc(i)
|
||||
|
||||
proc oidToString*(oid: Oid, str: cstring) =
|
||||
## Converts an oid to `str` which must have space allocated for 25 elements.
|
||||
const hex = "0123456789abcdef"
|
||||
# work around a compiler bug:
|
||||
var str = str
|
||||
@@ -66,35 +67,33 @@ proc oidToString*(oid: Oid, str: cstring) =
|
||||
str[24] = '\0'
|
||||
|
||||
proc `$`*(oid: Oid): string =
|
||||
## Converts an oid to string.
|
||||
result = newString(24)
|
||||
oidToString(oid, result)
|
||||
|
||||
proc rand(): cint {.importc: "rand", header: "<stdlib.h>", nodecl.}
|
||||
proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>", nodecl.}
|
||||
|
||||
var t = getTime().toUnix.int32
|
||||
srand(t)
|
||||
|
||||
var
|
||||
incr: int = rand()
|
||||
fuzz: int32 = rand()
|
||||
t = getTime().toUnix.int32
|
||||
seed = initRand(t)
|
||||
incr: int = seed.rand(int.high)
|
||||
|
||||
let fuzz = cast[int32](seed.rand(high(int)))
|
||||
|
||||
proc genOid*(): Oid =
|
||||
## generates a new OID.
|
||||
## Generates a new OID.
|
||||
runnableExamples:
|
||||
doAssert ($genOid()).len == 24
|
||||
if false: doAssert $genOid() == "5fc7f546ddbbc84800006aaf"
|
||||
t = getTime().toUnix.int32
|
||||
var i = int32(atomicInc(incr))
|
||||
var i = cast[int32](atomicInc(incr))
|
||||
|
||||
bigEndian32(addr result.time, addr(t))
|
||||
result.fuzz = fuzz
|
||||
bigEndian32(addr result.count, addr(i))
|
||||
|
||||
proc generatedTime*(oid: Oid): Time =
|
||||
## returns the generated timestamp of the OID.
|
||||
## Returns the generated timestamp of the OID.
|
||||
var tmp: int32
|
||||
var dummy = oid.time
|
||||
bigEndian32(addr(tmp), addr(dummy))
|
||||
result = fromUnix(tmp)
|
||||
|
||||
when not defined(testing) and isMainModule:
|
||||
let xo = genOid()
|
||||
echo xo.generatedTime
|
||||
|
||||
@@ -2058,7 +2058,7 @@ const
|
||||
NimMinor* {.intdefine.}: int = 2
|
||||
## is the minor number of Nim's version.
|
||||
|
||||
NimPatch* {.intdefine.}: int = 14
|
||||
NimPatch* {.intdefine.}: int = 19
|
||||
## is the patch number of Nim's version.
|
||||
|
||||
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
|
||||
|
||||
@@ -33,7 +33,10 @@ proc c_abort*() {.
|
||||
importc: "abort", header: "<stdlib.h>", noSideEffect, noreturn.}
|
||||
|
||||
|
||||
when defined(linux) and defined(amd64):
|
||||
when defined(nimBuiltinSetjmp):
|
||||
type
|
||||
C_JmpBuf* = array[5, pointer]
|
||||
elif defined(linux) and defined(amd64):
|
||||
type
|
||||
C_JmpBuf* {.importc: "jmp_buf", header: "<setjmp.h>", bycopy.} = object
|
||||
abi: array[200 div sizeof(clong), clong]
|
||||
@@ -89,18 +92,54 @@ when defined(macosx):
|
||||
elif defined(haiku):
|
||||
const SIGBUS* = cint(30)
|
||||
|
||||
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
|
||||
# "nimRawSetjmp" is defined by default for certain platforms, so we need the
|
||||
# "nimStdSetjmp" escape hatch with it.
|
||||
when defined(nimSigSetjmp):
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "siglongjmp".}
|
||||
template c_setjmp*(jmpb: C_JmpBuf): cint =
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint =
|
||||
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
|
||||
header: "<setjmp.h>", importc: "sigsetjmp".}
|
||||
c_sigsetjmp(jmpb, 0)
|
||||
elif defined(nimBuiltinSetjmp):
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) =
|
||||
# Apple's Clang++ has trouble converting array names to pointers, so we need
|
||||
# to be very explicit here.
|
||||
proc c_builtin_longjmp(jmpb: ptr pointer, retval: cint) {.
|
||||
importc: "__builtin_longjmp", nodecl.}
|
||||
# The second parameter needs to be 1 and sometimes the C/C++ compiler checks it.
|
||||
c_builtin_longjmp(unsafeAddr jmpb[0], 1)
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint =
|
||||
proc c_builtin_setjmp(jmpb: ptr pointer): cint {.
|
||||
importc: "__builtin_setjmp", nodecl.}
|
||||
c_builtin_setjmp(unsafeAddr jmpb[0])
|
||||
|
||||
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "_longjmp".}
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "_setjmp".}
|
||||
when defined(windows) and not defined(vcc):
|
||||
# No `_longjmp()` on Windows.
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
# The Windows `_setjmp()` takes two arguments, with the second being an
|
||||
# undocumented buffer used by the SEH mechanism for stack unwinding.
|
||||
# Mingw-w64 has been trying to get it right for years, but it's still
|
||||
# prone to stack corruption during unwinding, so we disable that by setting
|
||||
# it to NULL.
|
||||
# More details: https://github.com/status-im/nimbus-eth2/issues/3121
|
||||
when defined(nimHasStyleChecks):
|
||||
{.push styleChecks: off.}
|
||||
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint =
|
||||
proc c_setjmp_win(jmpb: C_JmpBuf, ctx: pointer): cint {.
|
||||
header: "<setjmp.h>", importc: "_setjmp".}
|
||||
c_setjmp_win(jmpb, nil)
|
||||
|
||||
when defined(nimHasStyleChecks):
|
||||
{.pop.}
|
||||
else:
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "_longjmp".}
|
||||
proc c_setjmp*(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "_setjmp".}
|
||||
else:
|
||||
proc c_longjmp*(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
|
||||
@@ -381,7 +381,6 @@ else:
|
||||
let regEnd = sp +% sizeof(registers)
|
||||
while sp <% regEnd:
|
||||
gcMark(gch, cast[PPointer](sp)[])
|
||||
gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
|
||||
sp = sp +% sizeof(pointer)
|
||||
# Make sure sp is word-aligned
|
||||
sp = sp and not (sizeof(pointer) - 1)
|
||||
|
||||
@@ -9,16 +9,14 @@ pkg "argparse"
|
||||
pkg "arraymancer", true, "nim c tests/tests_cpu.nim"
|
||||
pkg "ast_pattern_matching", false, "nim c -r --oldgensym:on tests/test1.nim"
|
||||
pkg "asyncmysql", true
|
||||
pkg "bigints"
|
||||
pkg "binaryheap", false, "nim c -r binaryheap.nim"
|
||||
# pkg "blscurve", true # pending https://github.com/status-im/nim-blscurve/issues/39
|
||||
pkg "bncurve", true
|
||||
pkg "c2nim", false, "nim c testsuite/tester.nim"
|
||||
pkg "cascade"
|
||||
pkg "chroma"
|
||||
pkg "chronicles", true, "nim c -o:chr -r chronicles.nim"
|
||||
# disable until my chronos fix was merged
|
||||
#pkg "chronos", true
|
||||
pkg "chronicles", true, "nim c --stylecheck:hint -o:chr -r chronicles.nim"
|
||||
pkg "chronos", true, "nim c -r -d:release tests/testall"
|
||||
pkg "cligen", false, "nim c -o:cligenn -r cligen.nim"
|
||||
pkg "coco", true
|
||||
pkg "combparser"
|
||||
@@ -28,8 +26,8 @@ pkg "comprehension", false, "nimble test", "https://github.com/alehander42/compr
|
||||
pkg "dashing", false, "nim c tests/functional.nim"
|
||||
pkg "docopt"
|
||||
pkg "easygl", true, "nim c -o:egl -r src/easygl.nim", "https://github.com/jackmott/easygl"
|
||||
pkg "elvis"
|
||||
pkg "fragments", false, "nim c -r fragments/dsl.nim"
|
||||
# pkg "elvis"
|
||||
# pkg "fragments", false, "nim c -r fragments/dsl.nim"
|
||||
pkg "gara"
|
||||
# pkg "ggplotnim", true, "nimble testCI"
|
||||
pkg "glob"
|
||||
@@ -57,7 +55,7 @@ pkg "nimfp", true, "nim c -o:nfp -r src/fp.nim"
|
||||
# pkg "nimlsp", true
|
||||
# pkg "nimly", true
|
||||
# pkg "nimongo", true, "nimble test_ci"
|
||||
pkg "nimpy", false, "nim c -r tests/nimfrompy.nim"
|
||||
# pkg "nimpy", false, "nim c -r tests/nimfrompy.nim"
|
||||
# pkg "nimquery"
|
||||
pkg "nimsl", true
|
||||
pkg "nimsvg"
|
||||
@@ -70,7 +68,7 @@ pkg "ormin", true, "nim c -o:orminn ormin.nim"
|
||||
pkg "patty"
|
||||
pkg "plotly", true, "nim c --oldgensym:on examples/all.nim"
|
||||
pkg "pnm"
|
||||
pkg "polypbren"
|
||||
# pkg "polypbren"
|
||||
pkg "protobuf", true, "nim c -o:protobuff -r src/protobuf.nim"
|
||||
pkg "rbtree"
|
||||
pkg "react", false, "nimble example"
|
||||
@@ -82,10 +80,10 @@ pkg "sdl2_nim", false, "nim c -r sdl2/sdl.nim"
|
||||
pkg "snip", false, "nimble test", "https://github.com/genotrance/snip"
|
||||
pkg "stint", false, "nim c -o:stintt -r stint.nim"
|
||||
pkg "strunicode", true, "nim c -r src/strunicode.nim"
|
||||
pkg "telebot", true, "nim c -o:tbot -r src/telebot.nim"
|
||||
# pkg "telebot", true, "nim c -o:tbot -r src/telebot.nim"
|
||||
pkg "tempdir"
|
||||
pkg "tensordsl", false, "nim c -r tests/tests.nim", "https://krux02@bitbucket.org/krux02/tensordslnim.git"
|
||||
pkg "tiny_sqlite"
|
||||
# pkg "tiny_sqlite"
|
||||
pkg "unicodedb"
|
||||
pkg "unicodeplus", true
|
||||
pkg "unpack"
|
||||
@@ -93,4 +91,4 @@ pkg "unpack"
|
||||
pkg "with"
|
||||
# pkg "ws"
|
||||
pkg "yaml"
|
||||
pkg "zero_functional", false, "nim c -r test.nim"
|
||||
# pkg "zero_functional", false, "nim c -r test.nim"
|
||||
|
||||
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)
|
||||
@@ -1,4 +1,6 @@
|
||||
discard """
|
||||
disabled: "windows" # no sigsetjmp() there
|
||||
matrix: "-d:nimStdSetjmp; -d:nimSigSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
|
||||
output: '''
|
||||
BEFORE
|
||||
FINALLY
|
||||
@@ -16,7 +18,7 @@ FINALLY
|
||||
|
||||
echo ""
|
||||
|
||||
proc no_expcetion =
|
||||
proc no_exception =
|
||||
try:
|
||||
echo "BEFORE"
|
||||
|
||||
@@ -27,7 +29,7 @@ proc no_expcetion =
|
||||
finally:
|
||||
echo "FINALLY"
|
||||
|
||||
try: no_expcetion()
|
||||
try: no_exception()
|
||||
except: echo "RECOVER"
|
||||
|
||||
echo ""
|
||||
|
||||
130
tests/exception/texceptions2.nim
Normal file
130
tests/exception/texceptions2.nim
Normal file
@@ -0,0 +1,130 @@
|
||||
discard """
|
||||
disabled: "posix" # already covered by texceptions.nim
|
||||
matrix: "-d:nimStdSetjmp; -d:nimRawSetjmp; -d:nimBuiltinSetjmp"
|
||||
output: '''
|
||||
|
||||
BEFORE
|
||||
FINALLY
|
||||
|
||||
BEFORE
|
||||
EXCEPT
|
||||
FINALLY
|
||||
RECOVER
|
||||
|
||||
BEFORE
|
||||
EXCEPT: IOError: hi
|
||||
FINALLY
|
||||
'''
|
||||
"""
|
||||
|
||||
echo ""
|
||||
|
||||
proc no_exception =
|
||||
try:
|
||||
echo "BEFORE"
|
||||
|
||||
except:
|
||||
echo "EXCEPT"
|
||||
raise
|
||||
|
||||
finally:
|
||||
echo "FINALLY"
|
||||
|
||||
try: no_exception()
|
||||
except: echo "RECOVER"
|
||||
|
||||
echo ""
|
||||
|
||||
proc reraise_in_except =
|
||||
try:
|
||||
echo "BEFORE"
|
||||
raise newException(IOError, "")
|
||||
|
||||
except IOError:
|
||||
echo "EXCEPT"
|
||||
raise
|
||||
|
||||
finally:
|
||||
echo "FINALLY"
|
||||
|
||||
try: reraise_in_except()
|
||||
except: echo "RECOVER"
|
||||
|
||||
echo ""
|
||||
|
||||
proc return_in_except =
|
||||
try:
|
||||
echo "BEFORE"
|
||||
raise newException(IOError, "hi")
|
||||
|
||||
except:
|
||||
echo "EXCEPT: ", getCurrentException().name, ": ", getCurrentExceptionMsg()
|
||||
return
|
||||
|
||||
finally:
|
||||
echo "FINALLY"
|
||||
|
||||
try: return_in_except()
|
||||
except: echo "RECOVER"
|
||||
|
||||
block: #10417
|
||||
proc moo() {.noreturn.} = discard
|
||||
|
||||
let bar =
|
||||
try:
|
||||
1
|
||||
except:
|
||||
moo()
|
||||
|
||||
doAssert(bar == 1)
|
||||
|
||||
# Make sure the VM handles the exceptions correctly
|
||||
block:
|
||||
proc fun1(): seq[int] =
|
||||
try:
|
||||
try:
|
||||
raise newException(ValueError, "xx")
|
||||
except:
|
||||
doAssert("xx" == getCurrentExceptionMsg())
|
||||
raise newException(KeyError, "yy")
|
||||
except:
|
||||
doAssert("yy" == getCurrentExceptionMsg())
|
||||
result.add(1212)
|
||||
try:
|
||||
try:
|
||||
raise newException(AssertionError, "a")
|
||||
finally:
|
||||
result.add(42)
|
||||
except AssertionError:
|
||||
result.add(99)
|
||||
finally:
|
||||
result.add(10)
|
||||
result.add(4)
|
||||
result.add(0)
|
||||
try:
|
||||
result.add(1)
|
||||
except KeyError:
|
||||
result.add(-1)
|
||||
except ValueError:
|
||||
result.add(-1)
|
||||
except IndexError:
|
||||
result.add(2)
|
||||
except:
|
||||
result.add(3)
|
||||
|
||||
try:
|
||||
try:
|
||||
result.add(1)
|
||||
return
|
||||
except:
|
||||
result.add(-1)
|
||||
finally:
|
||||
result.add(2)
|
||||
except KeyError:
|
||||
doAssert(false)
|
||||
finally:
|
||||
result.add(3)
|
||||
|
||||
let x1 = fun1()
|
||||
const x2 = fun1()
|
||||
doAssert(x1 == x2)
|
||||
@@ -18,6 +18,14 @@ end
|
||||
1
|
||||
2
|
||||
7
|
||||
nested finally
|
||||
outer finally
|
||||
nested finally
|
||||
outer finally
|
||||
nested finally
|
||||
outer finally
|
||||
nested finally
|
||||
outer finally
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -213,3 +221,71 @@ block t2023_objiter:
|
||||
|
||||
var o = init()
|
||||
echo(o.iter())
|
||||
|
||||
|
||||
block:
|
||||
# bug #19911 (return in nested try)
|
||||
|
||||
# try yield -> try
|
||||
iterator p1: int {.closure.} =
|
||||
try:
|
||||
yield 0
|
||||
try:
|
||||
return
|
||||
finally:
|
||||
echo "nested finally"
|
||||
echo "shouldn't run"
|
||||
finally:
|
||||
echo "outer finally"
|
||||
echo "shouldn't run"
|
||||
|
||||
for _ in p1():
|
||||
discard
|
||||
|
||||
# try -> try yield
|
||||
iterator p2: int {.closure.} =
|
||||
try:
|
||||
try:
|
||||
yield 0
|
||||
return
|
||||
finally:
|
||||
echo "nested finally"
|
||||
echo "shouldn't run"
|
||||
finally:
|
||||
echo "outer finally"
|
||||
echo "shouldn't run"
|
||||
|
||||
for _ in p2():
|
||||
discard
|
||||
|
||||
# try yield -> try yield
|
||||
iterator p3: int {.closure.} =
|
||||
try:
|
||||
yield 0
|
||||
try:
|
||||
yield 0
|
||||
return
|
||||
finally:
|
||||
echo "nested finally"
|
||||
echo "shouldn't run"
|
||||
finally:
|
||||
echo "outer finally"
|
||||
echo "shouldn't run"
|
||||
|
||||
for _ in p3():
|
||||
discard
|
||||
|
||||
# try -> try
|
||||
iterator p4: int {.closure.} =
|
||||
try:
|
||||
try:
|
||||
return
|
||||
finally:
|
||||
echo "nested finally"
|
||||
echo "shouldn't run"
|
||||
finally:
|
||||
echo "outer finally"
|
||||
echo "shouldn't run"
|
||||
|
||||
for _ in p4():
|
||||
discard
|
||||
|
||||
@@ -60,3 +60,22 @@ macro foo(t: static Tuple): untyped =
|
||||
doAssert t.b == 12345
|
||||
|
||||
foo((a: "foo", b: 12345))
|
||||
|
||||
|
||||
# bug #16307
|
||||
|
||||
macro bug(x: untyped): string =
|
||||
newLit repr(x)
|
||||
|
||||
let res = bug:
|
||||
block:
|
||||
## one
|
||||
## two
|
||||
## three
|
||||
|
||||
doAssert res == """
|
||||
|
||||
block:
|
||||
## one
|
||||
## two
|
||||
## three"""
|
||||
|
||||
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()
|
||||
4
tests/pragmas/cfunction.c
Normal file
4
tests/pragmas/cfunction.c
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
int cfunction(void) {
|
||||
return NUMBER_HERE;
|
||||
}
|
||||
9
tests/pragmas/tcompile_pragma.nim
Normal file
9
tests/pragmas/tcompile_pragma.nim
Normal file
@@ -0,0 +1,9 @@
|
||||
discard """
|
||||
output: '''34'''
|
||||
"""
|
||||
|
||||
{.compile("cfunction.c", "-DNUMBER_HERE=34").}
|
||||
|
||||
proc cfunction(): cint {.importc.}
|
||||
|
||||
echo cfunction()
|
||||
6
tests/sandwich/generic_library.nim
Normal file
6
tests/sandwich/generic_library.nim
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
proc libraryFunc*[T](x: T) =
|
||||
mixin mixedIn, indirectlyMixedIn
|
||||
echo mixedIn()
|
||||
echo indirectlyMixedIn()
|
||||
|
||||
3
tests/sandwich/helper_module.nim
Normal file
3
tests/sandwich/helper_module.nim
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
proc indirectlyMixedIn*: int =
|
||||
200
|
||||
12
tests/sandwich/module_using_generic_library.nim
Normal file
12
tests/sandwich/module_using_generic_library.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
import
|
||||
generic_library, helper_module
|
||||
|
||||
proc mixedIn: int = 100
|
||||
|
||||
proc makeUseOfLibrary*[T](x: T) =
|
||||
bind mixedIn, indirectlyMixedIn
|
||||
libraryFunc(x)
|
||||
|
||||
when isMainModule:
|
||||
makeUseOfLibrary "test"
|
||||
9
tests/sandwich/tmain.nim
Normal file
9
tests/sandwich/tmain.nim
Normal file
@@ -0,0 +1,9 @@
|
||||
discard """
|
||||
output: '''100
|
||||
200'''
|
||||
"""
|
||||
|
||||
import
|
||||
module_using_generic_library
|
||||
|
||||
makeUseOfLibrary "test"
|
||||
2
tests/slice/tdistinctslice.nim
Normal file
2
tests/slice/tdistinctslice.nim
Normal file
@@ -0,0 +1,2 @@
|
||||
type Foo = distinct uint64
|
||||
const slice = 0 ..< 42.Foo
|
||||
6
tests/stdlib/toids.nim
Normal file
6
tests/stdlib/toids.nim
Normal file
@@ -0,0 +1,6 @@
|
||||
import std/oids
|
||||
|
||||
|
||||
block: # genOid
|
||||
let x = genOid()
|
||||
doAssert ($x).len == 24
|
||||
Reference in New Issue
Block a user