diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 4ba6643ec..6dfd7b52c 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -99,7 +99,10 @@ proc getUniqueType*(key: PType): PType = gCanonicalTypes[k] = key result = key of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor: - internalError("getUniqueType") + if key.sym != nil: + internalError(key.sym.info, "metatype not eliminated") + else: + internalError("metatype not eliminated") of tyDistinct: if key.deepCopy != nil: result = key else: result = getUniqueType(lastSon(key)) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 9c9281da0..48d725ea8 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -234,7 +234,7 @@ proc semGenericStmt(c: PContext, n: PNode, discard of skProc, skMethod, skIterators, skConverter, skModule: result.sons[0] = symChoice(c, fn, s, scOption) - # do check of 's.magic==mRoof' here because it might be some + # do not check of 's.magic==mRoof' here because it might be some # other '^' but after overload resolution the proper one: if ctx.bracketExpr != nil and n.len == 2 and s.name.s == "^": result.add ctx.bracketExpr diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 64e3e8cb8..1c1d71a2f 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -164,7 +164,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable, addDecl(c, prc) pushInfoContext(info) - var cl = initTypeVars(c, pt, info) + var cl = initTypeVars(c, pt, info, nil) var result = instCopyType(cl, prc.typ) let originalParams = result.n result.n = originalParams.shallowCopy diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f67ee2822..adb1c81c1 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -957,27 +957,35 @@ proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode = var n = n - n = replaceTypesInBody(c, pt, n) + let original = n.sons[namePos].sym + let s = copySym(original, false) + incl(s.flags, sfFromGeneric) + + n = replaceTypesInBody(c, pt, n, original) result = n - + s.ast = result + n.sons[namePos].sym = s n.sons[genericParamsPos] = emptyNode - n.sons[paramsPos] = n.typ.n - + let params = n.typ.n + n.sons[paramsPos] = params + s.typ = n.typ + for i in 1.. 20: + localError(body.n[3].info, $body.n[3] & " too nested for type matching") + return isNone openScope(c) inc c.inTypeClass @@ -590,7 +593,7 @@ proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode = # Here, N-1 will be initially nkStaticExpr that can be evaluated only after # N is bound to a concrete value during the matching of the first param. # This proc is used to evaluate such static expressions. - let instantiated = replaceTypesInBody(c.c, c.bindings, n) + let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil) result = c.c.semExpr(c.c, instantiated) proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg index 4773258cf..23151b275 100644 --- a/config/nimdoc.cfg +++ b/config/nimdoc.cfg @@ -145,7 +145,7 @@ body { font-weight: 400; font-size: 14px; line-height: 20px; - color: #2d2d2d; + color: #666; background-color: rgba(252, 248, 244, 0.75); } /* Skeleton grid */ diff --git a/lib/pure/asyncftpclient.nim b/lib/pure/asyncftpclient.nim index fe4577ed9..b806f4235 100644 --- a/lib/pure/asyncftpclient.nim +++ b/lib/pure/asyncftpclient.nim @@ -6,23 +6,74 @@ # distribution, for details about the copyright. # -## This module implement an asynchronous FTP client. +## This module implements an asynchronous FTP client. It allows you to connect +## to an FTP server and perform operations on it such as for example: ## -## Examples -## -------- +## * The upload of new files. +## * The removal of existing files. +## * Download of files. +## * Changing of files' permissions. +## * Navigation through the FTP server's directories. ## -## .. code-block::nim +## Connecting to an FTP server +## ------------------------ ## -## var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") -## proc main(ftp: AsyncFtpClient) {.async.} = +## In order to begin any sort of transfer of files you must first +## connect to an FTP server. You can do so with the ``connect`` procedure. +## +## .. code-block::nim +## import asyncdispatch, asyncftpclient +## proc main() {.async.} = +## var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") ## await ftp.connect() -## echo await ftp.pwd() -## echo await ftp.listDirs() -## await ftp.store("payload.jpg", "payload.jpg") -## await ftp.retrFile("payload.jpg", "payload2.jpg") -## echo("Finished") +## echo("Connected") +## waitFor(main()) ## -## waitFor main(ftp) +## A new ``main`` async procedure must be declared to allow the use of the +## ``await`` keyword. The connection will complete asynchronously and the +## client will be connected after the ``await ftp.connect()`` call. +## +## Uploading a new file +## -------------------- +## +## After a connection is made you can use the ``store`` procedure to upload +## a new file to the FTP server. Make sure to check you are in the correct +## working directory before you do so with the ``pwd`` procedure, you can also +## instead specify an absolute path. +## +## .. code-block::nim +## import asyncdispatch, asyncftpclient +## proc main() {.async.} = +## var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") +## await ftp.connect() +## let currentDir = await ftp.pwd() +## assert currentDir == "/home/user/" +## await ftp.store("file.txt", "file.txt") +## echo("File finished uploading") +## waitFor(main()) +## +## Checking the progress of a file transfer +## ---------------------------------------- +## +## The progress of either a file upload or a file download can be checked +## by specifying a ``onProgressChanged`` procedure to the ``store`` or +## ``retrFile`` procedures. +## +## .. code-block::nim +## import asyncdispatch, asyncftpclient +## +## proc onProgressChanged(total, progress: BiggestInt, +## speed: float): Future[void] = +## echo("Uploaded ", progress, " of ", total, " bytes") +## echo("Current speed: ", speed, " kb/s") +## +## proc main() {.async.} = +## var ftp = newAsyncFtpClient("example.com", user = "test", pass = "test") +## await ftp.connect() +## await ftp.store("file.txt", "/home/user/file.txt", onProgressChanged) +## echo("File finished uploading") +## waitFor(main()) + import asyncdispatch, asyncnet, strutils, parseutils, os, times diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index aa7d458b3..5d74896bf 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -67,6 +67,12 @@ type Http409 = "409 Conflict", Http410 = "410 Gone", Http411 = "411 Length Required", + Http412 = "412 Precondition Failed", + Http413 = "413 Request Entity Too Large", + Http414 = "414 Request-URI Too Long", + Http415 = "415 Unsupported Media Type", + Http416 = "416 Requested Range Not Satisfiable", + Http417 = "417 Expectation Failed", Http418 = "418 I'm a teapot", Http500 = "500 Internal Server Error", Http501 = "501 Not Implemented", diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index deab39c7c..32d37ce02 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -8,6 +8,38 @@ # ## This module implements a base64 encoder and decoder. +## +## Encoding data +## ------------- +## +## In order to encode some text simply call the ``encode`` procedure: +## +## .. code-block::nim +## import base64 +## let encoded = encode("Hello World") +## echo(encoded) # SGVsbG8gV29ybGQ= +## +## Apart from strings you can also encode lists of integers or characters: +## +## .. code-block::nim +## import base64 +## let encodedInts = encode([1,2,3]) +## echo(encodedInts) # AQID +## let encodedChars = encode(['h','e','y']) +## echo(encodedChars) # aGV5 +## +## The ``encode`` procedure takes an ``openarray`` so both arrays and sequences +## can be passed as parameters. +## +## Decoding data +## ------------- +## +## To decode a base64 encoded data string simply call the ``decode`` +## procedure: +## +## .. code-block::nim +## import base64 +## echo(decode("SGVsbG8gV29ybGQ=")) # Hello World const cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" @@ -64,11 +96,16 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. + ## + ## This procedure encodes an openarray (array or sequence) of either integers + ## or characters. encodeInternal(s, lineLen, newLine) proc encode*(s: string, lineLen = 75, newLine="\13\10"): string = ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. + ## + ## This procedure encodes a string. encodeInternal(s, lineLen, newLine) proc decodeByte(b: char): int {.inline.} = diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index 778ba6857..229fe4b51 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -13,7 +13,12 @@ import sockets, strutils, parseutils, times, os, asyncio from asyncnet import nil from rawsockets import nil from asyncdispatch import PFuture - +## **Note**: This module is deprecated since version 0.11.3. +## You should use the async version of this module +## `asyncftpclient `_. +## +## ---- +## ## This module **partially** implements an FTP client as specified ## by `RFC 959 `_. ## @@ -36,6 +41,8 @@ from asyncdispatch import PFuture ## **Warning:** The API of this module is unstable, and therefore is subject ## to change. +{.deprecated.} + type FtpBase*[SockType] = ref FtpBaseObj[SockType] FtpBaseObj*[SockType] = object diff --git a/lib/pure/json.nim b/lib/pure/json.nim index abf6305f2..06d5a13e2 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -622,9 +622,12 @@ proc getNum*(n: JsonNode, default: BiggestInt = 0): BiggestInt = proc getFNum*(n: JsonNode, default: float = 0.0): float = ## Retrieves the float value of a `JFloat JsonNode`. ## - ## Returns ``default`` if ``n`` is not a ``JFloat``, or if ``n`` is nil. - if n.isNil or n.kind != JFloat: return default - else: return n.fnum + ## Returns ``default`` if ``n`` is not a ``JFloat`` or ``JInt``, or if ``n`` is nil. + if n.isNil: return default + case n.kind + of JFloat: return n.fnum + of JInt: return float(n.num) + else: return default proc getBVal*(n: JsonNode, default: bool = false): bool = ## Retrieves the bool value of a `JBool JsonNode`. diff --git a/lib/pure/math.nim b/lib/pure/math.nim index c1d5c9439..06a018d9f 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -21,6 +21,20 @@ include "system/inclrtl" {.push debugger:off .} # the user does not want to trace a part # of the standard library! +proc binom*(n, k: int): int {.noSideEffect.} = + ## Computes the binomial coefficient + if k <= 0: return 1 + if 2*k > n: return binom(n, n-k) + result = n + for i in countup(2, k): + result = (result * (n + 1 - i)) div i + +proc fac*(n: int): int {.noSideEffect.} = + ## Computes the faculty/factorial function. + result = 1 + for i in countup(2, n): + result = result * i + {.push checks:off, line_dir:off, stack_trace:off.} when defined(Posix) and not defined(haiku): @@ -72,21 +86,6 @@ proc classify*(x: float): FloatClass = return fcNormal # XXX: fcSubnormal is not detected! - -proc binom*(n, k: int): int {.noSideEffect.} = - ## Computes the binomial coefficient - if k <= 0: return 1 - if 2*k > n: return binom(n, n-k) - result = n - for i in countup(2, k): - result = (result * (n + 1 - i)) div i - -proc fac*(n: int): int {.noSideEffect.} = - ## Computes the faculty/factorial function. - result = 1 - for i in countup(2, n): - result = result * i - proc isPowerOfTwo*(x: int): bool {.noSideEffect.} = ## Returns true, if `x` is a power of two, false otherwise. ## Zero and negative numbers are not a power of two. diff --git a/tests/typerel/t2plus.nim b/tests/typerel/t2plus.nim new file mode 100644 index 000000000..08378b804 --- /dev/null +++ b/tests/typerel/t2plus.nim @@ -0,0 +1,22 @@ +discard """ + output: "2.0" +""" + +{.warning[TypelessParam]: off.} + +import future + +# bug #3329 + +proc foldRight[T,U](lst: seq[T], v: U, f: (T, U) -> U): U = + result = v + for x in lst: + result = f(x, result) + +proc mean[T: SomeNumber](xs: seq[T]): T = + xs.foldRight(0.T, (xBAZ: auto, yBAZ: auto) => xBAZ + yBAZ) / T(xs.len) + +when isMainModule: + let x = mean(@[1.float, 2, 3]) + echo x + diff --git a/web/news.txt b/web/news.txt index aaa27cfee..c70824b87 100644 --- a/web/news.txt +++ b/web/news.txt @@ -82,6 +82,8 @@ News result = $x & y echo f(0, "abc") + - The ``ftpclient`` module is now deprecated in favour of the + ``asyncdispatch`` module. Library Additions diff --git a/web/question.txt b/web/question.txt index 46ea7161c..da38760f5 100644 --- a/web/question.txt +++ b/web/question.txt @@ -94,9 +94,9 @@ General FAQ What about JVM/CLR backends? ---------------------------- - A JVM backend is almost impossible. The JVM is not expressive enough. It has - never been designed as a general purpose VM anyway. A CLR backend is possible - but would require much work. + JVM/CLR support is not in the nearest plans. However, since these VMs support FFI to C + it should be possible to create native Nim bridges, that transparenlty generate all the + glue code thanks to powerful metaprogramming capabilities of Nim. .. container:: standout