mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-05 11:24:08 +00:00
Merge branch 'bigbreak' of github.com:Araq/Nimrod into bigbreak
This commit is contained in:
@@ -949,7 +949,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
|
||||
discard transformOuterProcBody(o, body, initIter(fn))
|
||||
result = ex
|
||||
finishEnvironments(o)
|
||||
#if fn.name.s == "cbOuter":
|
||||
#if fn.name.s == "parseLong":
|
||||
# echo rendertree(result, {renderIds})
|
||||
|
||||
proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
|
||||
|
||||
@@ -56,6 +56,7 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
|
||||
|
||||
result.add newAsgnStmt(newSymNode(temp), value)
|
||||
for i in 0 .. n.len-3:
|
||||
if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
|
||||
result.add newAsgnStmt(n.sons[i], newTupleAccess(value, i))
|
||||
|
||||
proc createObj*(owner: PSym, info: TLineInfo): PType =
|
||||
|
||||
@@ -442,7 +442,7 @@ type
|
||||
TNoteKinds* = set[TNoteKind]
|
||||
|
||||
TFileInfo*{.final.} = object
|
||||
fullPath*: string # This is a canonical full filesystem path
|
||||
fullPath: string # This is a canonical full filesystem path
|
||||
projPath*: string # This is relative to the project's root
|
||||
shortName*: string # short name of the module
|
||||
quotedName*: PRope # cached quoted short name for codegen
|
||||
|
||||
@@ -188,8 +188,9 @@ proc getPrefixDir*(): string =
|
||||
result = splitPath(getAppDir()).head
|
||||
|
||||
proc canonicalizePath*(path: string): string =
|
||||
result = path.expandFilename
|
||||
when not FileSystemCaseSensitive: result = result.toLower
|
||||
#result = path.expandFilename
|
||||
when not FileSystemCaseSensitive: result = path.toLower
|
||||
else: result = path
|
||||
|
||||
proc shortenDir*(dir: string): string =
|
||||
## returns the interesting part of a dir
|
||||
|
||||
@@ -110,7 +110,7 @@ template styleCheckDef*(info: TLineInfo; s: PSym) =
|
||||
template styleCheckDef*(s: PSym) =
|
||||
styleCheckDef(s.info, s, s.kind)
|
||||
|
||||
proc styleCheckUse*(info: TLineInfo; s: PSym) =
|
||||
proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
|
||||
if info.fileIndex < 0: return
|
||||
# we simply convert it to what it looks like in the definition
|
||||
# for consistency
|
||||
@@ -138,3 +138,7 @@ proc styleCheckUse*(info: TLineInfo; s: PSym) =
|
||||
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
||||
gSourceFiles[info.fileIndex].dirty = true
|
||||
#if newName == "File": writeStackTrace()
|
||||
|
||||
template styleCheckUse*(info: TLineInfo; s: PSym) =
|
||||
when defined(nimfix):
|
||||
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s)
|
||||
|
||||
@@ -354,7 +354,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
|
||||
if typ != nil:
|
||||
if typ.isMetaType:
|
||||
def = inferWithMetaType(c, typ, def)
|
||||
def = inferWithMetatype(c, typ, def)
|
||||
typ = def.typ
|
||||
else:
|
||||
# BUGFIX: ``fitNode`` is needed here!
|
||||
|
||||
@@ -1135,14 +1135,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
of opcParseExprToAst:
|
||||
decodeB(rkNode)
|
||||
# c.debug[pc].line.int - countLines(regs[rb].strVal) ?
|
||||
let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
|
||||
let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
|
||||
c.debug[pc].line.int)
|
||||
if sonsLen(ast) != 1:
|
||||
globalError(c.debug[pc], errExprExpected, "multiple statements")
|
||||
regs[ra].node = ast.sons[0]
|
||||
of opcParseStmtToAst:
|
||||
decodeB(rkNode)
|
||||
let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFilename,
|
||||
let ast = parseString(regs[rb].node.strVal, c.debug[pc].toFullPath,
|
||||
c.debug[pc].line.int)
|
||||
regs[ra].node = ast
|
||||
of opcCallSite:
|
||||
|
||||
@@ -12,11 +12,11 @@ import ast, types, msgs, osproc, streams, options
|
||||
proc readOutput(p: Process): string =
|
||||
result = ""
|
||||
var output = p.outputStream
|
||||
discard p.waitForExit
|
||||
while not output.atEnd:
|
||||
result.add(output.readLine)
|
||||
result.add("\n")
|
||||
result.setLen(result.len - "\n".len)
|
||||
discard p.waitForExit
|
||||
|
||||
proc opGorge*(cmd, input: string): string =
|
||||
var p = startCmd(cmd)
|
||||
|
||||
@@ -46,7 +46,6 @@ proc debugInfo(info: TLineInfo): string =
|
||||
proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
|
||||
# first iteration: compute all necessary labels:
|
||||
var jumpTargets = initIntSet()
|
||||
|
||||
let last = if last < 0: c.code.len-1 else: min(last, c.code.len-1)
|
||||
for i in start..last:
|
||||
let x = c.code[i]
|
||||
|
||||
@@ -35,3 +35,5 @@ Options:
|
||||
-r, --run run the compiled program with given arguments
|
||||
--advanced show advanced command line switches
|
||||
-h, --help show this help
|
||||
|
||||
Note: Even single letter options require the colon: -p:PATH.
|
||||
|
||||
@@ -138,6 +138,13 @@ from rst to HTML. It also repeats the same operation but places the result in
|
||||
the ``web/upload`` which can be used to update the website at
|
||||
http://nim-lang.org.
|
||||
|
||||
By default the documentation will be built in parallel using the number of
|
||||
available CPU cores. If any documentation build sub commands fail, they will
|
||||
be rerun in serial fashion so that meaninful error output can be gathered for
|
||||
inspection. The ``--parallelBuild:n`` switch or configuration option can be
|
||||
used to force a specific number of parallel jobs or run everything serially
|
||||
from the start (``n == 1``).
|
||||
|
||||
zip command
|
||||
-----------
|
||||
|
||||
|
||||
@@ -596,7 +596,7 @@ Ordinal types
|
||||
Ordinal types have the following characteristics:
|
||||
|
||||
- Ordinal types are countable and ordered. This property allows
|
||||
the operation of functions as ``Inc``, ``Ord``, ``Dec`` on ordinal types to
|
||||
the operation of functions as ``inc``, ``ord``, ``dec`` on ordinal types to
|
||||
be defined.
|
||||
- Ordinal values have a smallest possible value. Trying to count further
|
||||
down than the smallest value gives a checked runtime or static error.
|
||||
@@ -699,11 +699,11 @@ lowest and highest value of the type:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
TSubrange = range[0..5]
|
||||
Subrange = range[0..5]
|
||||
|
||||
|
||||
``TSubrange`` is a subrange of an integer which can only hold the values 0
|
||||
to 5. Assigning any other value to a variable of type ``TSubrange`` is a
|
||||
``Subrange`` is a subrange of an integer which can only hold the values 0
|
||||
to 5. Assigning any other value to a variable of type ``Subrange`` is a
|
||||
checked runtime error (or static error if it can be statically
|
||||
determined). Assignments from the base type to one of its subrange types
|
||||
(and vice versa) are allowed.
|
||||
@@ -791,6 +791,10 @@ turned off as default.
|
||||
The only operations that are affected by the ``floatChecks`` pragma are
|
||||
the ``+``, ``-``, ``*``, ``/`` operators for floating point types.
|
||||
|
||||
An implementation should always use the maximum precision available to evaluate
|
||||
floating pointer values at compile time; this means expressions like
|
||||
``0.09'f32 + 0.01'f32 == 0.09'f64 + 0.01'f64`` are true.
|
||||
|
||||
|
||||
Boolean type
|
||||
------------
|
||||
@@ -3675,10 +3679,11 @@ Future versions of Nim may also support overloading based on the return type
|
||||
of the overloads. In such settings, the expected result type at call sites may
|
||||
also influence the inferred return type.
|
||||
|
||||
Likewise, if a type class is used in another position where Nim expects a
|
||||
concrete type (e.g. a variable declaration or a type coercion), Nim will try to
|
||||
infer the concrete type by applying the sane matching algorithm also used in
|
||||
overload resolution.
|
||||
..
|
||||
Likewise, if a type class is used in another position where Nim expects a
|
||||
concrete type (e.g. a variable declaration or a type coercion), Nim will try
|
||||
to infer the concrete type by applying the matching algorithm that also used
|
||||
in overload resolution.
|
||||
|
||||
|
||||
Symbol lookup in generics
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import zmq
|
||||
|
||||
var connection = zmq.open("tcp://localhost:5555", server=false)
|
||||
|
||||
echo("Connecting...")
|
||||
|
||||
for i in 0..10:
|
||||
echo("Sending hello...", i)
|
||||
send(connection, "Hello")
|
||||
|
||||
var reply = receive(connection)
|
||||
echo("Received ...", reply)
|
||||
|
||||
close(connection)
|
||||
@@ -1,11 +0,0 @@
|
||||
import zmq
|
||||
|
||||
var connection = zmq.open("tcp://*:5555", server=true)
|
||||
|
||||
while True:
|
||||
var request = receive(connection)
|
||||
echo("Received: ", request)
|
||||
send(connection, "World")
|
||||
|
||||
close(connection)
|
||||
|
||||
@@ -28,8 +28,9 @@ proc parseCookies*(s: string): StringTableRef =
|
||||
if s[i] == '\0': break
|
||||
inc(i) # skip ';'
|
||||
|
||||
proc setCookie*(key, value: string, domain = "", path = "",
|
||||
expires = "", noName = false): string =
|
||||
proc setCookie*(key, value: string, domain = "", path = "",
|
||||
expires = "", noName = false,
|
||||
secure = false, httpOnly = false): string =
|
||||
## Creates a command in the format of
|
||||
## ``Set-Cookie: key=value; Domain=...; ...``
|
||||
result = ""
|
||||
@@ -38,22 +39,23 @@ proc setCookie*(key, value: string, domain = "", path = "",
|
||||
if domain != "": result.add("; Domain=" & domain)
|
||||
if path != "": result.add("; Path=" & path)
|
||||
if expires != "": result.add("; Expires=" & expires)
|
||||
if secure: result.add("; secure")
|
||||
if httpOnly: result.add("; HttpOnly")
|
||||
|
||||
proc setCookie*(key, value: string, expires: TimeInfo,
|
||||
domain = "", path = "", noName = false): string =
|
||||
domain = "", path = "", noName = false,
|
||||
secure = false, httpOnly = false): string =
|
||||
## Creates a command in the format of
|
||||
## ``Set-Cookie: key=value; Domain=...; ...``
|
||||
##
|
||||
## **Note:** UTC is assumed as the timezone for ``expires``.
|
||||
|
||||
## **Note:** UTC is assumed as the timezone for ``expires``.
|
||||
return setCookie(key, value, domain, path,
|
||||
format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noName)
|
||||
|
||||
format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"),
|
||||
noname, secure, httpOnly)
|
||||
|
||||
when isMainModule:
|
||||
var tim = Time(int(getTime()) + 76 * (60 * 60 * 24))
|
||||
|
||||
echo(setCookie("test", "value", tim.getGMTime()))
|
||||
|
||||
echo parseCookies("uid=1; kp=2")
|
||||
|
||||
|
||||
|
||||
@@ -803,6 +803,36 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} =
|
||||
if result != -1: return
|
||||
return -1
|
||||
|
||||
proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
|
||||
rtl, extern: "nsuCountString".} =
|
||||
## Count the occurences of a substring `sub` in the string `s`.
|
||||
## Overlapping occurences of `sub` only count when `overlapping`
|
||||
## is set to true.
|
||||
var i = 0
|
||||
while true:
|
||||
i = s.find(sub, i)
|
||||
if i < 0:
|
||||
break
|
||||
if overlapping:
|
||||
inc i
|
||||
else:
|
||||
i += sub.len
|
||||
inc result
|
||||
|
||||
proc count*(s: string, sub: char): int {.noSideEffect,
|
||||
rtl, extern: "nsuCountChar".} =
|
||||
## Count the occurences of the character `sub` in the string `s`.
|
||||
for c in s:
|
||||
if c == sub:
|
||||
inc result
|
||||
|
||||
proc count*(s: string, subs: set[char]): int {.noSideEffect,
|
||||
rtl, extern: "nsuCountCharSet".} =
|
||||
## Count the occurences of the group of character `subs` in the string `s`.
|
||||
for c in s:
|
||||
if c in subs:
|
||||
inc result
|
||||
|
||||
proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
|
||||
## Returns ``'"' & s & '"'`` if `s` contains a space and does not
|
||||
## start with a quote, else returns `s`.
|
||||
@@ -1356,3 +1386,8 @@ when isMainModule:
|
||||
doAssert parseEnum[MyEnum]("enu_D") == enuD
|
||||
|
||||
doAssert parseEnum("invalid enum value", enC) == enC
|
||||
|
||||
doAssert count("foofoofoo", "foofoo") == 1
|
||||
doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
|
||||
doAssert count("foofoofoo", 'f') == 3
|
||||
doAssert count("foofoofoobar", {'f','b'}) == 4
|
||||
|
||||
@@ -514,7 +514,7 @@ elif defined(JS):
|
||||
result.setFullYear(timeInfo.year)
|
||||
result.setDate(timeInfo.monthday)
|
||||
|
||||
proc `$`(timeInfo: TimeInfo): string = return $(TimeInfoToTIme(timeInfo))
|
||||
proc `$`(timeInfo: TimeInfo): string = return $(timeInfoToTime(timeInfo))
|
||||
proc `$`(time: Time): string = return $time.toLocaleString()
|
||||
|
||||
proc `-` (a, b: Time): int64 =
|
||||
|
||||
@@ -154,6 +154,8 @@ proc addEscaped*(result: var string, s: string) =
|
||||
of '>': result.add(">")
|
||||
of '&': result.add("&")
|
||||
of '"': result.add(""")
|
||||
of '\'': result.add("'")
|
||||
of '/': result.add("/")
|
||||
else: result.add(c)
|
||||
|
||||
proc escape*(s: string): string =
|
||||
@@ -167,6 +169,8 @@ proc escape*(s: string): string =
|
||||
## ``>`` ``>``
|
||||
## ``&`` ``&``
|
||||
## ``"`` ``"``
|
||||
## ``'`` ``'``
|
||||
## ``/`` ``/``
|
||||
## ------------ -------------------
|
||||
result = newStringOfCap(s.len)
|
||||
addEscaped(result, s)
|
||||
|
||||
@@ -215,13 +215,13 @@ proc open(f: var File, filename: string,
|
||||
mode: FileMode = fmRead,
|
||||
bufSize: int = -1): bool =
|
||||
var p: pointer = fopen(filename, FormatOpen[mode])
|
||||
result = (p != nil)
|
||||
f = cast[File](p)
|
||||
if bufSize > 0 and bufSize <= high(cint).int:
|
||||
if setvbuf(f, nil, IOFBF, bufSize.cint) != 0'i32:
|
||||
sysFatal(OutOfMemError, "out of memory")
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
if p != nil:
|
||||
result = true
|
||||
f = cast[File](p)
|
||||
if bufSize > 0 and bufSize <= high(cint).int:
|
||||
discard setvbuf(f, nil, IOFBF, bufSize.cint)
|
||||
elif bufSize == 0:
|
||||
discard setvbuf(f, nil, IONBF, 0)
|
||||
|
||||
proc reopen(f: File, filename: string, mode: FileMode = fmRead): bool =
|
||||
var p: pointer = freopen(filename, FormatOpen[mode], f)
|
||||
|
||||
@@ -354,7 +354,6 @@ when hostOS == "windows":
|
||||
addr(t), 0'i32, dummyThreadId)
|
||||
if t.sys <= 0:
|
||||
raise newException(ResourceExhaustedError, "cannot create thread")
|
||||
|
||||
else:
|
||||
proc createThread*[TArg](t: var TThread[TArg],
|
||||
tp: proc (arg: TArg) {.thread.},
|
||||
|
||||
@@ -21,6 +21,7 @@ type
|
||||
nimrodArgs: string
|
||||
gitCommit: string
|
||||
quotations: TTable[string, tuple[quote, author: string]]
|
||||
numProcessors: int # Set by parallelBuild:n, only works for values > 0.
|
||||
TRssItem = object
|
||||
year, month, day, title: string
|
||||
|
||||
@@ -42,6 +43,7 @@ proc initConfigData(c: var TConfigData) =
|
||||
c.ticker = ""
|
||||
c.vars = newStringTable(modeStyleInsensitive)
|
||||
c.gitCommit = "master"
|
||||
c.numProcessors = countProcessors()
|
||||
# Attempts to obtain the git current commit.
|
||||
let (output, code) = execCmdEx("git log -n 1 --format=%H")
|
||||
if code == 0 and output.strip.len == 40:
|
||||
@@ -121,6 +123,12 @@ proc parseCmdLine(c: var TConfigData) =
|
||||
stdout.write(version & "\n")
|
||||
quit(0)
|
||||
of "o", "output": c.outdir = val
|
||||
of "parallelbuild":
|
||||
try:
|
||||
let num = parseInt(val)
|
||||
if num != 0: c.numProcessors = num
|
||||
except EInvalidValue:
|
||||
quit("invalid numeric value for --parallelBuild")
|
||||
of "var":
|
||||
var idx = val.find('=')
|
||||
if idx < 0: quit("invalid command line")
|
||||
@@ -187,6 +195,12 @@ proc parseIniFile(c: var TConfigData) =
|
||||
of "srcdoc": addFiles(c.srcdoc, "lib", ".nim", split(v, {';'}))
|
||||
of "srcdoc2": addFiles(c.srcdoc2, "lib", ".nim", split(v, {';'}))
|
||||
of "webdoc": addFiles(c.webdoc, "lib", ".nim", split(v, {';'}))
|
||||
of "parallelbuild":
|
||||
try:
|
||||
let num = parseInt(v)
|
||||
if num != 0: c.numProcessors = num
|
||||
except EInvalidValue:
|
||||
quit("invalid numeric value for --parallelBuild in config")
|
||||
else: quit(errorStr(p, "unknown variable: " & k.key))
|
||||
of "quotations":
|
||||
let vSplit = v.split('-')
|
||||
@@ -215,6 +229,20 @@ proc exec(cmd: string) =
|
||||
echo(cmd)
|
||||
if os.execShellCmd(cmd) != 0: quit("external program failed")
|
||||
|
||||
proc sexec(cmds: openarray[string]) =
|
||||
## Serial queue wrapper around exec.
|
||||
for cmd in cmds: exec(cmd)
|
||||
|
||||
proc mexec(cmds: openarray[string], processors: int) =
|
||||
## Multiprocessor version of exec
|
||||
if processors < 2:
|
||||
sexec(cmds)
|
||||
return
|
||||
|
||||
if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}):
|
||||
echo "external program failed, retrying serial work queue for logs!"
|
||||
sexec(cmds)
|
||||
|
||||
proc buildDocSamples(c: var TConfigData, destPath: string) =
|
||||
## Special case documentation sample proc.
|
||||
##
|
||||
@@ -229,18 +257,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
|
||||
|
||||
proc buildDoc(c: var TConfigData, destPath: string) =
|
||||
# call nim for the documentation:
|
||||
var
|
||||
commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
|
||||
i = 0
|
||||
for d in items(c.doc):
|
||||
exec("nim rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
commands[i] = "nim rst2html $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
[c.nimrodArgs, c.gitCommit,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d])
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
for d in items(c.srcdoc):
|
||||
exec("nim doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
commands[i] = "nim doc $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
[c.nimrodArgs, c.gitCommit,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d])
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
for d in items(c.srcdoc2):
|
||||
exec("nim doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
commands[i] = "nim doc2 $# --docSeeSrcUrl:$# -o:$# --index:on $#" %
|
||||
[c.nimrodArgs, c.gitCommit,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d])
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
|
||||
mexec(commands, c.numProcessors)
|
||||
exec("nim buildIndex -o:$1/theindex.html $1" % [destPath])
|
||||
|
||||
proc buildPdfDoc(c: var TConfigData, destPath: string) =
|
||||
@@ -264,10 +300,17 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
|
||||
|
||||
proc buildAddDoc(c: var TConfigData, destPath: string) =
|
||||
# build additional documentation (without the index):
|
||||
<<<<<<< HEAD
|
||||
var commands = newSeq[string](c.webdoc.len)
|
||||
for i, doc in pairs(c.webdoc):
|
||||
commands[i] = "nimrod doc $# --docSeeSrcUrl:$# -o:$# $#" %
|
||||
=======
|
||||
for d in items(c.webdoc):
|
||||
exec("nim doc $# --docSeeSrcUrl:$# -o:$# $#" %
|
||||
>>>>>>> 0047172274a73c681f619f5cd60aaad7109f694d
|
||||
[c.nimrodArgs, c.gitCommit,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d])
|
||||
destPath / changeFileExt(splitFile(doc).name, "html"), doc]
|
||||
mexec(commands, c.numProcessors)
|
||||
|
||||
proc parseNewsTitles(inputFilename: string): seq[TRssItem] =
|
||||
# parses the file for titles and returns them as TRssItem blocks.
|
||||
|
||||
Reference in New Issue
Block a user