Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
8683c8a389
15 changed files with 258 additions and 104 deletions
|
|
@ -22,6 +22,14 @@
|
||||||
|
|
||||||
### Tool changes
|
### Tool changes
|
||||||
|
|
||||||
|
- ``jsondoc2`` has been renamed ``jsondoc``, similar to how ``doc2`` was renamed
|
||||||
|
``doc``. The old ``jsondoc`` can still be invoked with ``jsondoc0``.
|
||||||
|
|
||||||
### Compiler changes
|
### Compiler changes
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
- The `importcpp` pragma now allows importing the listed fields of generic
|
||||||
|
C++ types. Support for numeric parameters have also been added through
|
||||||
|
the use of `static[T]` types.
|
||||||
|
(#6415)
|
||||||
|
|
|
||||||
|
|
@ -617,8 +617,10 @@ proc scanCppGenericSlot(pat: string, cursor, outIdx, outStars: var int): bool =
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
|
||||||
# XXX: we should catch this earlier and report it as a semantic error
|
# Make sure the index refers to one of the generic params of the type.
|
||||||
if idx >= typ.len: internalError "invalid apostrophe type parameter index"
|
# XXX: we should catch this earlier and report it as a semantic error.
|
||||||
|
if idx >= typ.len:
|
||||||
|
internalError "invalid apostrophe type parameter index"
|
||||||
|
|
||||||
result = typ.sons[idx]
|
result = typ.sons[idx]
|
||||||
for i in 1..stars:
|
for i in 1..stars:
|
||||||
|
|
@ -820,6 +822,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
|
||||||
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
let typeInSlot = resolveStarsInCppType(origTyp, idx + 1, stars)
|
||||||
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
if typeInSlot == nil or typeInSlot.kind == tyVoid:
|
||||||
result.add(~"void")
|
result.add(~"void")
|
||||||
|
elif typeInSlot.kind == tyStatic:
|
||||||
|
internalAssert typeInSlot.n != nil
|
||||||
|
result.add typeInSlot.n.renderTree
|
||||||
else:
|
else:
|
||||||
result.add getTypeDescAux(m, typeInSlot, check)
|
result.add getTypeDescAux(m, typeInSlot, check)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -210,14 +210,14 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
|
||||||
gCmd = cmdRst2tex
|
gCmd = cmdRst2tex
|
||||||
loadConfigs(DocTexConfig, cache)
|
loadConfigs(DocTexConfig, cache)
|
||||||
commandRst2TeX()
|
commandRst2TeX()
|
||||||
of "jsondoc":
|
of "jsondoc0":
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
gCmd = cmdDoc
|
gCmd = cmdDoc
|
||||||
loadConfigs(DocConfig, cache)
|
loadConfigs(DocConfig, cache)
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
defineSymbol("nimdoc")
|
defineSymbol("nimdoc")
|
||||||
commandJson()
|
commandJson()
|
||||||
of "jsondoc2":
|
of "jsondoc2", "jsondoc":
|
||||||
gCmd = cmdDoc
|
gCmd = cmdDoc
|
||||||
loadConfigs(DocConfig, cache)
|
loadConfigs(DocConfig, cache)
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
|
|
|
||||||
|
|
@ -255,69 +255,61 @@ proc semCase(c: PContext, n: PNode): PNode =
|
||||||
result.typ = typ
|
result.typ = typ
|
||||||
|
|
||||||
proc semTry(c: PContext, n: PNode): PNode =
|
proc semTry(c: PContext, n: PNode): PNode =
|
||||||
|
|
||||||
|
var check = initIntSet()
|
||||||
|
template semExceptBranchType(typeNode: PNode): PNode =
|
||||||
|
let typ = semTypeNode(c, typeNode, nil).toObject()
|
||||||
|
if typ.kind != tyObject:
|
||||||
|
localError(typeNode.info, errExprCannotBeRaised)
|
||||||
|
if containsOrIncl(check, typ.id):
|
||||||
|
localError(typeNode.info, errExceptionAlreadyHandled)
|
||||||
|
newNodeIT(nkType, typeNode.info, typ)
|
||||||
|
|
||||||
result = n
|
result = n
|
||||||
inc c.p.inTryStmt
|
inc c.p.inTryStmt
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
|
|
||||||
var typ = commonTypeBegin
|
var typ = commonTypeBegin
|
||||||
n.sons[0] = semExprBranchScope(c, n.sons[0])
|
n[0] = semExprBranchScope(c, n[0])
|
||||||
typ = commonType(typ, n.sons[0].typ)
|
typ = commonType(typ, n[0].typ)
|
||||||
|
|
||||||
var check = initIntSet()
|
|
||||||
var last = sonsLen(n) - 1
|
var last = sonsLen(n) - 1
|
||||||
for i in countup(1, last):
|
for i in countup(1, last):
|
||||||
var a = n.sons[i]
|
let a = n.sons[i]
|
||||||
checkMinSonsLen(a, 1)
|
checkMinSonsLen(a, 1)
|
||||||
var length = sonsLen(a)
|
|
||||||
openScope(c)
|
openScope(c)
|
||||||
if a.kind == nkExceptBranch:
|
if a.kind == nkExceptBranch:
|
||||||
# so that ``except [a, b, c]`` is supported:
|
|
||||||
if length == 2 and a.sons[0].kind == nkBracket:
|
|
||||||
a.sons[0..0] = a.sons[0].sons
|
|
||||||
length = a.sonsLen
|
|
||||||
|
|
||||||
# Iterate through each exception type in the except branch.
|
if a.len == 2 and a[0].kind == nkBracket:
|
||||||
for j in countup(0, length-2):
|
# rewrite ``except [a, b, c]: body`` -> ```except a, b, c: body```
|
||||||
var typeNode = a.sons[j] # e.g. `Exception`
|
a.sons[0..0] = a[0].sons
|
||||||
var symbolNode: PNode = nil # e.g. `foobar`
|
|
||||||
# Handle the case where the `Exception as foobar` syntax is used.
|
if a.len == 2 and a[0].isInfixAs():
|
||||||
if typeNode.isInfixAs():
|
# support ``except Exception as ex: body``
|
||||||
typeNode = a.sons[j].sons[1]
|
a[0][1] = semExceptBranchType(a[0][1])
|
||||||
symbolNode = a.sons[j].sons[2]
|
|
||||||
|
|
||||||
# Resolve the type ident into a PType.
|
let symbol = newSymG(skLet, a[0][2], c)
|
||||||
var typ = semTypeNode(c, typeNode, nil).toObject()
|
symbol.typ = a[0][1].typ.toRef()
|
||||||
if typ.kind != tyObject:
|
addDecl(c, symbol)
|
||||||
localError(a.sons[j].info, errExprCannotBeRaised)
|
# Overwrite symbol in AST with the symbol in the symbol table.
|
||||||
|
a[0][2] = newSymNode(symbol, a[0][2].info)
|
||||||
|
|
||||||
let newTypeNode = newNodeI(nkType, typeNode.info)
|
else:
|
||||||
newTypeNode.typ = typ
|
# support ``except KeyError, ValueError, ... : body``
|
||||||
if symbolNode.isNil:
|
for j in 0..a.len-2:
|
||||||
a.sons[j] = newTypeNode
|
a[j] = semExceptBranchType(a[j])
|
||||||
else:
|
|
||||||
a.sons[j].sons[1] = newTypeNode
|
|
||||||
# Add the exception ident to the symbol table.
|
|
||||||
let symbol = newSymG(skLet, symbolNode, c)
|
|
||||||
symbol.typ = typ.toRef()
|
|
||||||
addDecl(c, symbol)
|
|
||||||
# Overwrite symbol in AST with the symbol in the symbol table.
|
|
||||||
let symNode = newNodeI(nkSym, typeNode.info)
|
|
||||||
symNode.sym = symbol
|
|
||||||
a.sons[j].sons[2] = symNode
|
|
||||||
|
|
||||||
if containsOrIncl(check, typ.id):
|
|
||||||
localError(a.sons[j].info, errExceptionAlreadyHandled)
|
|
||||||
elif a.kind != nkFinally:
|
elif a.kind != nkFinally:
|
||||||
illFormedAst(n)
|
illFormedAst(n)
|
||||||
|
|
||||||
# last child of an nkExcept/nkFinally branch is a statement:
|
# last child of an nkExcept/nkFinally branch is a statement:
|
||||||
a.sons[length-1] = semExprBranchScope(c, a.sons[length-1])
|
a[^1] = semExprBranchScope(c, a[^1])
|
||||||
if a.kind != nkFinally: typ = commonType(typ, a.sons[length-1].typ)
|
if a.kind != nkFinally: typ = commonType(typ, a[^1])
|
||||||
else: dec last
|
else: dec last
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
|
||||||
dec c.p.inTryStmt
|
dec c.p.inTryStmt
|
||||||
if isEmptyType(typ) or typ.kind == tyNil:
|
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}:
|
||||||
discardCheck(c, n.sons[0])
|
discardCheck(c, n.sons[0])
|
||||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
|
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
|
||||||
if typ == enforceVoidContext:
|
if typ == enforceVoidContext:
|
||||||
|
|
|
||||||
|
|
@ -632,16 +632,18 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
else:
|
else:
|
||||||
typ = semTypeNode(c, n.sons[length-2], nil)
|
typ = semTypeNode(c, n.sons[length-2], nil)
|
||||||
propagateToOwner(rectype, typ)
|
propagateToOwner(rectype, typ)
|
||||||
let rec = rectype.sym
|
var fieldOwner = if c.inGenericContext > 0: c.getCurrOwner
|
||||||
|
else: rectype.sym
|
||||||
for i in countup(0, sonsLen(n)-3):
|
for i in countup(0, sonsLen(n)-3):
|
||||||
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
|
||||||
suggestSym(n.sons[i].info, f, c.graph.usageSym)
|
suggestSym(n.sons[i].info, f, c.graph.usageSym)
|
||||||
f.typ = typ
|
f.typ = typ
|
||||||
f.position = pos
|
f.position = pos
|
||||||
if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and
|
if fieldOwner != nil and
|
||||||
(f.loc.r == nil):
|
{sfImportc, sfExportc} * fieldOwner.flags != {} and
|
||||||
|
f.loc.r == nil:
|
||||||
f.loc.r = rope(f.name.s)
|
f.loc.r = rope(f.name.s)
|
||||||
f.flags = f.flags + ({sfImportc, sfExportc} * rec.flags)
|
f.flags = f.flags + ({sfImportc, sfExportc} * fieldOwner.flags)
|
||||||
inc(pos)
|
inc(pos)
|
||||||
if containsOrIncl(check, f.name.id):
|
if containsOrIncl(check, f.name.id):
|
||||||
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
localError(n.sons[i].info, errAttemptToRedefine, f.name.s)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ Advanced commands:
|
||||||
//rst2html convert a reStructuredText file to HTML
|
//rst2html convert a reStructuredText file to HTML
|
||||||
//rst2tex convert a reStructuredText file to TeX
|
//rst2tex convert a reStructuredText file to TeX
|
||||||
//jsondoc extract the documentation to a json file
|
//jsondoc extract the documentation to a json file
|
||||||
//jsondoc2 extract the documentation to a json file (uses doc2)
|
|
||||||
//ctags create a tags file
|
//ctags create a tags file
|
||||||
//buildIndex build an index for the whole documentation
|
//buildIndex build an index for the whole documentation
|
||||||
//run run the project (with Tiny C backend; buggy!)
|
//run run the project (with Tiny C backend; buggy!)
|
||||||
|
|
|
||||||
|
|
@ -84,51 +84,72 @@ Document Types
|
||||||
HTML
|
HTML
|
||||||
----
|
----
|
||||||
|
|
||||||
Generation of HTML documents is done via both the ``doc`` and ``doc2``
|
Generation of HTML documents is done via the ``doc`` command. This command
|
||||||
commands. These command take either a single .nim file, outputting a single
|
takes either a single .nim file, outputting a single .html file with the same
|
||||||
.html file with the same base filename, or multiple .nim files, outputting
|
base filename, or multiple .nim files, outputting multiple .html files and,
|
||||||
multiple .html files and, optionally, an index file.
|
optionally, an index file.
|
||||||
|
|
||||||
The ``doc`` command::
|
The ``doc`` command::
|
||||||
nim doc sample
|
nim doc sample
|
||||||
|
|
||||||
Partial Output::
|
|
||||||
...
|
|
||||||
proc helloWorld*(times: int)
|
|
||||||
...
|
|
||||||
|
|
||||||
Output can be viewed in full here: `docgen_sample.html <docgen_sample.html>`_.
|
|
||||||
The next command, called ``doc2``, is very similar to the ``doc`` command, but
|
|
||||||
will be run after the compiler performs semantic checking on the input nim
|
|
||||||
module(s), which allows it to process macros.
|
|
||||||
|
|
||||||
The ``doc2`` command::
|
|
||||||
nim doc2 sample
|
|
||||||
|
|
||||||
Partial Output::
|
Partial Output::
|
||||||
...
|
...
|
||||||
proc helloWorld(times: int) {.raises: [], tags: [].}
|
proc helloWorld(times: int) {.raises: [], tags: [].}
|
||||||
...
|
...
|
||||||
|
|
||||||
The full output can be seen here: `docgen_sample2.html <docgen_sample2.html>`_.
|
The full output can be seen here: `docgen_sample2.html <docgen_sample2.html>`_.
|
||||||
As you can see, the tool has extracted additional information provided to it by
|
|
||||||
the compiler beyond what the ``doc`` command provides, such as pragmas attached
|
The older version of the ``doc`` command, now renamed ``doc0`` runs before
|
||||||
implicitly by the compiler. This type of information is not available from
|
semantic checking which means it lacks some of the things ``doc`` will output.
|
||||||
looking at the AST (Abstract Syntax Tree) prior to semantic checking, as the
|
|
||||||
``doc`` command does.
|
The ``doc0`` command::
|
||||||
|
nim doc0 sample
|
||||||
|
|
||||||
|
Partial Output::
|
||||||
|
...
|
||||||
|
proc helloWorld*(times: int)
|
||||||
|
...
|
||||||
|
|
||||||
|
Output can be viewed in full here: `docgen_sample.html <docgen_sample.html>`_.
|
||||||
|
As you can see, the tool has extracted less information than what the ``doc``
|
||||||
|
command provides, such as pragmas attached implicitly by the compiler. This type
|
||||||
|
of information is not available from looking at the AST (Abstract Syntax Tree)
|
||||||
|
prior to semantic checking, which is why ``doc0`` doesn't show it.
|
||||||
|
|
||||||
|
|
||||||
JSON
|
JSON
|
||||||
----
|
----
|
||||||
|
|
||||||
Generation of JSON documents is done via the ``jsondoc`` command. This command
|
Generation of JSON documents is done via the ``jsondoc`` command. This command
|
||||||
takes in a .nim file, and outputs a .json file with the same base filename.
|
takes in a .nim file, and outputs a .json file with the same base filename. Note
|
||||||
Note that this tool is built off of the ``doc`` command, and therefore is
|
that this tool is built off of the ``doc`` command (previously ``doc2``), and
|
||||||
performed before semantic checking.
|
contains the same information.
|
||||||
|
|
||||||
The ``jsondoc`` command::
|
The ``jsondoc`` command::
|
||||||
nim jsondoc sample
|
nim jsondoc sample
|
||||||
|
|
||||||
|
Output::
|
||||||
|
{
|
||||||
|
"orig": "docgen_sample.nim",
|
||||||
|
"nimble": "",
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"name": "helloWorld",
|
||||||
|
"type": "skProc",
|
||||||
|
"line": 5,
|
||||||
|
"col": 0,
|
||||||
|
"description": "Takes an integer and outputs as many "hello world!"s",
|
||||||
|
"code": "proc helloWorld(times: int) {.raises: [], tags: [].}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Similarly to the old ``doc`` command the old ``jsondoc`` command has been
|
||||||
|
renamed ``jsondoc0``.
|
||||||
|
|
||||||
|
The ``jsondoc0`` command::
|
||||||
|
nim jsondoc0 sample
|
||||||
|
|
||||||
Output::
|
Output::
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|
@ -142,6 +163,8 @@ Output::
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Note that the ``jsondoc`` command outputs it's JSON without pretty-printing it,
|
||||||
|
while ``jsondoc0`` outputs pretty-printed JSON.
|
||||||
|
|
||||||
Related Options
|
Related Options
|
||||||
===============
|
===============
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,23 @@
|
||||||
## It supports one convenience iterator over all command line options and some
|
## It supports one convenience iterator over all command line options and some
|
||||||
## lower-level features.
|
## lower-level features.
|
||||||
##
|
##
|
||||||
## Supported syntax:
|
## Supported syntax with default empty ``shortNoVal``/``longNoVal``:
|
||||||
##
|
##
|
||||||
## 1. short options - ``-abcd``, where a, b, c, d are names
|
## 1. short options - ``-abcd``, where a, b, c, d are names
|
||||||
## 2. long option - ``--foo:bar``, ``--foo=bar`` or ``--foo``
|
## 2. long option - ``--foo:bar``, ``--foo=bar`` or ``--foo``
|
||||||
## 3. argument - everything else
|
## 3. argument - everything else
|
||||||
|
##
|
||||||
|
## When ``shortNoVal``/``longNoVal`` are non-empty then the ':' and '=' above
|
||||||
|
## are still accepted, but become optional. Note that these option key sets
|
||||||
|
## must be updated along with the set of option keys taking no value, but
|
||||||
|
## keys which do take values need no special updates as their set evolves.
|
||||||
|
##
|
||||||
|
## When option values begin with ':' or '=' they need to be doubled up (as in
|
||||||
|
## ``--delim::``) or alternated (as in ``--delim=:``).
|
||||||
|
##
|
||||||
|
## The common ``--`` non-option argument delimiter appears as an empty string
|
||||||
|
## long option key. ``OptParser.cmd``, ``OptParser.pos``, and
|
||||||
|
## ``os.parseCmdLine`` may be used to complete parsing in that case.
|
||||||
|
|
||||||
{.push debugger: off.}
|
{.push debugger: off.}
|
||||||
|
|
||||||
|
|
@ -32,9 +44,11 @@ type
|
||||||
cmdShortOption ## a short option ``-c`` detected
|
cmdShortOption ## a short option ``-c`` detected
|
||||||
OptParser* =
|
OptParser* =
|
||||||
object of RootObj ## this object implements the command line parser
|
object of RootObj ## this object implements the command line parser
|
||||||
cmd: string
|
cmd*: string # cmd,pos exported so caller can catch "--" as..
|
||||||
pos: int
|
pos*: int # ..empty key or subcmd cmdArg & handle specially
|
||||||
inShortState: bool
|
inShortState: bool
|
||||||
|
shortNoVal: set[char]
|
||||||
|
longNoVal: seq[string]
|
||||||
kind*: CmdLineKind ## the dected command line token
|
kind*: CmdLineKind ## the dected command line token
|
||||||
key*, val*: TaintedString ## key and value pair; ``key`` is the option
|
key*, val*: TaintedString ## key and value pair; ``key`` is the option
|
||||||
## or the argument, ``value`` is not "" if
|
## or the argument, ``value`` is not "" if
|
||||||
|
|
@ -78,11 +92,19 @@ when declared(os.paramCount):
|
||||||
# we cannot provide this for NimRtl creation on Posix, because we can't
|
# we cannot provide this for NimRtl creation on Posix, because we can't
|
||||||
# access the command line arguments then!
|
# access the command line arguments then!
|
||||||
|
|
||||||
proc initOptParser*(cmdline = ""): OptParser =
|
proc initOptParser*(cmdline = "", shortNoVal: set[char]={},
|
||||||
|
longNoVal: seq[string] = @[]): OptParser =
|
||||||
## inits the option parser. If ``cmdline == ""``, the real command line
|
## inits the option parser. If ``cmdline == ""``, the real command line
|
||||||
## (as provided by the ``OS`` module) is taken.
|
## (as provided by the ``OS`` module) is taken. If ``shortNoVal`` is
|
||||||
|
## provided command users do not need to delimit short option keys and
|
||||||
|
## values with a ':' or '='. If ``longNoVal`` is provided command users do
|
||||||
|
## not need to delimit long option keys and values with a ':' or '='
|
||||||
|
## (though they still need at least a space). In both cases, ':' or '='
|
||||||
|
## may still be used if desired. They just become optional.
|
||||||
result.pos = 0
|
result.pos = 0
|
||||||
result.inShortState = false
|
result.inShortState = false
|
||||||
|
result.shortNoVal = shortNoVal
|
||||||
|
result.longNoVal = longNoVal
|
||||||
if cmdline != "":
|
if cmdline != "":
|
||||||
result.cmd = cmdline
|
result.cmd = cmdline
|
||||||
else:
|
else:
|
||||||
|
|
@ -94,15 +116,19 @@ when declared(os.paramCount):
|
||||||
result.key = TaintedString""
|
result.key = TaintedString""
|
||||||
result.val = TaintedString""
|
result.val = TaintedString""
|
||||||
|
|
||||||
proc initOptParser*(cmdline: seq[string]): OptParser =
|
proc initOptParser*(cmdline: seq[TaintedString], shortNoVal: set[char]={},
|
||||||
|
longNoVal: seq[string] = @[]): OptParser =
|
||||||
## inits the option parser. If ``cmdline.len == 0``, the real command line
|
## inits the option parser. If ``cmdline.len == 0``, the real command line
|
||||||
## (as provided by the ``OS`` module) is taken.
|
## (as provided by the ``OS`` module) is taken. ``shortNoVal`` and
|
||||||
|
## ``longNoVal`` behavior is the same as for ``initOptParser(string,...)``.
|
||||||
result.pos = 0
|
result.pos = 0
|
||||||
result.inShortState = false
|
result.inShortState = false
|
||||||
|
result.shortNoVal = shortNoVal
|
||||||
|
result.longNoVal = longNoVal
|
||||||
result.cmd = ""
|
result.cmd = ""
|
||||||
if cmdline.len != 0:
|
if cmdline.len != 0:
|
||||||
for i in 0..<cmdline.len:
|
for i in 0..<cmdline.len:
|
||||||
result.cmd.add quote(cmdline[i])
|
result.cmd.add quote(cmdline[i].string)
|
||||||
result.cmd.add ' '
|
result.cmd.add ' '
|
||||||
else:
|
else:
|
||||||
for i in countup(1, paramCount()):
|
for i in countup(1, paramCount()):
|
||||||
|
|
@ -121,8 +147,9 @@ proc handleShortOption(p: var OptParser) =
|
||||||
while p.cmd[i] in {'\x09', ' '}:
|
while p.cmd[i] in {'\x09', ' '}:
|
||||||
inc(i)
|
inc(i)
|
||||||
p.inShortState = false
|
p.inShortState = false
|
||||||
if p.cmd[i] in {':', '='}:
|
if p.cmd[i] in {':', '='} or card(p.shortNoVal) > 0 and p.key.string[0] notin p.shortNoVal:
|
||||||
inc(i)
|
if p.cmd[i] in {':', '='}:
|
||||||
|
inc(i)
|
||||||
p.inShortState = false
|
p.inShortState = false
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
i = parseWord(p.cmd, i, p.val.string)
|
i = parseWord(p.cmd, i, p.val.string)
|
||||||
|
|
@ -146,12 +173,13 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
|
||||||
of '-':
|
of '-':
|
||||||
inc(i)
|
inc(i)
|
||||||
if p.cmd[i] == '-':
|
if p.cmd[i] == '-':
|
||||||
p.kind = cmdLongoption
|
p.kind = cmdLongOption
|
||||||
inc(i)
|
inc(i)
|
||||||
i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='})
|
i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='})
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
if p.cmd[i] in {':', '='}:
|
if p.cmd[i] in {':', '='} or len(p.longNoVal) > 0 and p.key.string notin p.longNoVal:
|
||||||
inc(i)
|
if p.cmd[i] in {':', '='}:
|
||||||
|
inc(i)
|
||||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||||
p.pos = parseWord(p.cmd, i, p.val.string)
|
p.pos = parseWord(p.cmd, i, p.val.string)
|
||||||
else:
|
else:
|
||||||
|
|
@ -172,7 +200,7 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedSt
|
||||||
## Example:
|
## Example:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## var p = initOptParser("--left --debug:3 -l=4 -r:2")
|
## var p = initOptParser("--left --debug:3 -l -r:2")
|
||||||
## for kind, key, val in p.getopt():
|
## for kind, key, val in p.getopt():
|
||||||
## case kind
|
## case kind
|
||||||
## of cmdArgument:
|
## of cmdArgument:
|
||||||
|
|
@ -192,17 +220,30 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key, val: TaintedSt
|
||||||
yield (p.kind, p.key, p.val)
|
yield (p.kind, p.key, p.val)
|
||||||
|
|
||||||
when declared(initOptParser):
|
when declared(initOptParser):
|
||||||
iterator getopt*(): tuple[kind: CmdLineKind, key, val: TaintedString] =
|
iterator getopt*(cmdline: seq[TaintedString] = commandLineParams(),
|
||||||
## This is an convenience iterator for iterating over the command line arguments.
|
shortNoVal: set[char]={}, longNoVal: seq[string] = @[]):
|
||||||
## This create a new OptParser object.
|
tuple[kind: CmdLineKind, key, val: TaintedString] =
|
||||||
## See above for a more detailed example
|
## This is an convenience iterator for iterating over command line arguments.
|
||||||
|
## This creates a new OptParser. See the above ``getopt(var OptParser)``
|
||||||
|
## example for using default empty ``NoVal`` parameters. This example is
|
||||||
|
## for the same option keys as that example but here option key-value
|
||||||
|
## separators become optional for command users:
|
||||||
##
|
##
|
||||||
## .. code-block:: nim
|
## .. code-block:: nim
|
||||||
## for kind, key, val in getopt():
|
## for kind, key, val in getopt(shortNoVal = { 'l' },
|
||||||
## # this will iterate over all arguments passed to the cmdline.
|
## longNoVal = @[ "left" ]):
|
||||||
## continue
|
## case kind
|
||||||
|
## of cmdArgument:
|
||||||
|
## filename = key
|
||||||
|
## of cmdLongOption, cmdShortOption:
|
||||||
|
## case key
|
||||||
|
## of "help", "h": writeHelp()
|
||||||
|
## of "version", "v": writeVersion()
|
||||||
|
## of cmdEnd: assert(false) # cannot happen
|
||||||
|
## if filename == "":
|
||||||
|
## writeHelp()
|
||||||
##
|
##
|
||||||
var p = initOptParser()
|
var p = initOptParser(cmdline, shortNoVal=shortNoVal, longNoVal=longNoVal)
|
||||||
while true:
|
while true:
|
||||||
next(p)
|
next(p)
|
||||||
if p.kind == cmdEnd: break
|
if p.kind == cmdEnd: break
|
||||||
|
|
|
||||||
|
|
@ -1250,7 +1250,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
if len(word) > spaceLeft:
|
if len(word) > spaceLeft:
|
||||||
if splitLongWords and len(word) > maxLineWidth:
|
if splitLongWords and len(word) > maxLineWidth:
|
||||||
result.add(substr(word, 0, spaceLeft-1))
|
result.add(substr(word, 0, spaceLeft-1))
|
||||||
var w = spaceLeft+1
|
var w = spaceLeft
|
||||||
var wordLeft = len(word) - spaceLeft
|
var wordLeft = len(word) - spaceLeft
|
||||||
while wordLeft > 0:
|
while wordLeft > 0:
|
||||||
result.add(newLine)
|
result.add(newLine)
|
||||||
|
|
@ -2514,6 +2514,11 @@ when isMainModule:
|
||||||
outp = " this is a\nlong text\n--\nmuchlongerthan10chars\nand here\nit goes"
|
outp = " this is a\nlong text\n--\nmuchlongerthan10chars\nand here\nit goes"
|
||||||
doAssert wordWrap(inp, 10, false) == outp
|
doAssert wordWrap(inp, 10, false) == outp
|
||||||
|
|
||||||
|
let
|
||||||
|
longInp = """ThisIsOneVeryLongStringWhichWeWillSplitIntoEightSeparatePartsNow"""
|
||||||
|
longOutp = "ThisIsOn\neVeryLon\ngStringW\nhichWeWi\nllSplitI\nntoEight\nSeparate\nPartsNow"
|
||||||
|
doAssert wordWrap(longInp, 8, true) == longOutp
|
||||||
|
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235."
|
doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235."
|
||||||
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
|
doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
|
||||||
|
|
|
||||||
|
|
@ -1461,9 +1461,9 @@ when defined(nodejs):
|
||||||
programResult = 0
|
programResult = 0
|
||||||
else:
|
else:
|
||||||
var programResult* {.exportc: "nim_program_result".}: int
|
var programResult* {.exportc: "nim_program_result".}: int
|
||||||
## modify this variable to specify the exit code of the program
|
## modify this variable to specify the exit code of the program
|
||||||
## under normal circumstances. When the program is terminated
|
## under normal circumstances. When the program is terminated
|
||||||
## prematurely using ``quit``, this value is ignored.
|
## prematurely using ``quit``, this value is ignored.
|
||||||
|
|
||||||
when defined(nimdoc):
|
when defined(nimdoc):
|
||||||
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
|
||||||
|
|
|
||||||
|
|
@ -32,3 +32,11 @@ proc testTryAsExpr(i: int) =
|
||||||
test[Exception]()
|
test[Exception]()
|
||||||
test2()
|
test2()
|
||||||
testTryAsExpr(5)
|
testTryAsExpr(5)
|
||||||
|
|
||||||
|
# see bug #7115
|
||||||
|
doAssert(not compiles(
|
||||||
|
try:
|
||||||
|
echo 1
|
||||||
|
except [KeyError as ex1, ValueError as ex2]:
|
||||||
|
echo 2
|
||||||
|
))
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,17 @@ kind: cmdLongOption key:val -- left:
|
||||||
kind: cmdLongOption key:val -- debug:3
|
kind: cmdLongOption key:val -- debug:3
|
||||||
kind: cmdShortOption key:val -- l:4
|
kind: cmdShortOption key:val -- l:4
|
||||||
kind: cmdShortOption key:val -- r:2
|
kind: cmdShortOption key:val -- r:2
|
||||||
|
parseoptNoVal
|
||||||
|
kind: cmdLongOption key:val -- left:
|
||||||
|
kind: cmdLongOption key:val -- debug:3
|
||||||
|
kind: cmdShortOption key:val -- l:
|
||||||
|
kind: cmdShortOption key:val -- r:2
|
||||||
|
kind: cmdLongOption key:val -- debug:2
|
||||||
|
kind: cmdLongOption key:val -- debug:1
|
||||||
|
kind: cmdShortOption key:val -- r:1
|
||||||
|
kind: cmdShortOption key:val -- r:0
|
||||||
|
kind: cmdShortOption key:val -- l:
|
||||||
|
kind: cmdShortOption key:val -- r:4
|
||||||
parseopt2
|
parseopt2
|
||||||
first round
|
first round
|
||||||
kind: cmdLongOption key:val -- left:
|
kind: cmdLongOption key:val -- left:
|
||||||
|
|
@ -39,6 +50,15 @@ block:
|
||||||
for kind, key, val in parseopt.getopt(p):
|
for kind, key, val in parseopt.getopt(p):
|
||||||
echo "kind: ", kind, "\tkey:val -- ", key, ":", val
|
echo "kind: ", kind, "\tkey:val -- ", key, ":", val
|
||||||
|
|
||||||
|
block:
|
||||||
|
echo "parseoptNoVal"
|
||||||
|
# test NoVal mode with custom cmdline arguments
|
||||||
|
var argv = "--left --debug:3 -l -r:2 --debug 2 --debug=1 -r1 -r=0 -lr4"
|
||||||
|
var p = parseopt.initOptParser(argv,
|
||||||
|
shortNoVal = {'l'}, longNoVal = @["left"])
|
||||||
|
for kind, key, val in parseopt.getopt(p):
|
||||||
|
echo "kind: ", kind, "\tkey:val -- ", key, ":", val
|
||||||
|
|
||||||
block:
|
block:
|
||||||
echo "parseopt2"
|
echo "parseopt2"
|
||||||
for kind, key, val in parseopt2.getopt():
|
for kind, key, val in parseopt2.getopt():
|
||||||
|
|
|
||||||
53
tests/statictypes/tstaticimportcpp.nim
Normal file
53
tests/statictypes/tstaticimportcpp.nim
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
discard """
|
||||||
|
targets: "cpp"
|
||||||
|
output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest"
|
||||||
|
"""
|
||||||
|
|
||||||
|
{.emit: """
|
||||||
|
|
||||||
|
template <int N, class T>
|
||||||
|
struct GenericIntType {
|
||||||
|
T data[N];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct GenericTType {
|
||||||
|
T field;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SimpleStruct {
|
||||||
|
int field;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
""" .}
|
||||||
|
|
||||||
|
type
|
||||||
|
GenericIntType {.importcpp: "GenericIntType<'0, '1>".} [N: static[int]; T] = object
|
||||||
|
data: array[N, T]
|
||||||
|
|
||||||
|
GenericTType {.importcpp: "GenericTType<'0>".} [T] = object
|
||||||
|
field: T
|
||||||
|
|
||||||
|
GenInt4 = GenericIntType[4, int]
|
||||||
|
|
||||||
|
SimpleStruct {.importcpp: "SimpleStruct"} = object
|
||||||
|
field: int
|
||||||
|
|
||||||
|
var
|
||||||
|
a = GenInt4()
|
||||||
|
b = SimpleStruct()
|
||||||
|
c = GenericTType[float]()
|
||||||
|
d = SimpleStruct(field: 15)
|
||||||
|
e = GenericTType[string](field: "test")
|
||||||
|
|
||||||
|
a.data[2] = 10
|
||||||
|
b.field = 5
|
||||||
|
c.field = 1.2
|
||||||
|
|
||||||
|
echo a.data
|
||||||
|
echo b.field
|
||||||
|
echo c.field
|
||||||
|
echo d.field
|
||||||
|
echo e.field
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ _nim()
|
||||||
|
|
||||||
if [ $COMP_CWORD -eq 1 ] ; then
|
if [ $COMP_CWORD -eq 1 ] ; then
|
||||||
# first item - suggest commands
|
# first item - suggest commands
|
||||||
kw="compile c doc doc2 compileToC cc compileToCpp cpp compileToOC objc js e rst2html rst2tex jsondoc jsondoc2 buildIndex genDepend dump check"
|
kw="compile c doc compileToC cc compileToCpp cpp compileToOC objc js e rst2html rst2tex jsondoc buildIndex genDepend dump check"
|
||||||
COMPREPLY=( $( compgen -W "${kw}" -- $cur ) )
|
COMPREPLY=( $( compgen -W "${kw}" -- $cur ) )
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ _nim() {
|
||||||
':command:((
|
':command:((
|
||||||
{compile,c}\:compile\ project\ with\ default\ code\ generator\ C
|
{compile,c}\:compile\ project\ with\ default\ code\ generator\ C
|
||||||
doc\:generate\ the\ documentation\ for\ inputfile
|
doc\:generate\ the\ documentation\ for\ inputfile
|
||||||
doc2\:generate\ the\ documentation\ for\ inputfile
|
|
||||||
{compileToC,cc}\:compile\ project\ with\ C\ code\ generator
|
{compileToC,cc}\:compile\ project\ with\ C\ code\ generator
|
||||||
{compileToCpp,cpp}\:compile\ project\ to\ C++\ code
|
{compileToCpp,cpp}\:compile\ project\ to\ C++\ code
|
||||||
{compileToOC,objc}\:compile\ project\ to\ Objective\ C\ code
|
{compileToOC,objc}\:compile\ project\ to\ Objective\ C\ code
|
||||||
|
|
@ -14,7 +13,6 @@ _nim() {
|
||||||
rst2html\:convert\ a\ reStructuredText\ file\ to\ HTML
|
rst2html\:convert\ a\ reStructuredText\ file\ to\ HTML
|
||||||
rst2tex\:convert\ a\ reStructuredText\ file\ to\ TeX
|
rst2tex\:convert\ a\ reStructuredText\ file\ to\ TeX
|
||||||
jsondoc\:extract\ the\ documentation\ to\ a\ json\ file
|
jsondoc\:extract\ the\ documentation\ to\ a\ json\ file
|
||||||
jsondoc2\:extract\ documentation\ to\ a\ json\ file\ using\ doc2
|
|
||||||
buildIndex\:build\ an\ index\ for\ the\ whole\ documentation
|
buildIndex\:build\ an\ index\ for\ the\ whole\ documentation
|
||||||
genDepend\:generate\ a\ DOT\ file\ containing\ the\ module\ dependency\ graph
|
genDepend\:generate\ a\ DOT\ file\ containing\ the\ module\ dependency\ graph
|
||||||
dump\:dump\ all\ defined\ conditionals\ and\ search\ paths
|
dump\:dump\ all\ defined\ conditionals\ and\ search\ paths
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue