diff options
-rw-r--r-- | compiler/renderer.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semfold.nim | 8 | ||||
-rw-r--r-- | compiler/semtypes.nim | 24 | ||||
-rw-r--r-- | compiler/vm.nim | 11 | ||||
-rw-r--r-- | compiler/vmgen.nim | 12 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 32 | ||||
-rw-r--r-- | lib/pure/sockets.nim | 5 | ||||
-rw-r--r-- | lib/pure/subexes.nim | 6 | ||||
-rw-r--r-- | lib/system/ansi_c.nim | 9 | ||||
-rw-r--r-- | tests/js/tbyvar.nim | 7 | ||||
-rw-r--r-- | tests/js/test1.nim | 4 | ||||
-rw-r--r-- | tests/metatype/tautonotgeneric.nim | 15 | ||||
-rw-r--r-- | tests/misc/teventemitter.nim | 8 | ||||
-rw-r--r-- | tests/misc/tunsigned64mod.nim | 12 | ||||
-rw-r--r-- | tests/testament/categories.nim | 4 | ||||
-rw-r--r-- | tests/vm/tstringnil.nim | 50 |
17 files changed, 155 insertions, 58 deletions
diff --git a/compiler/renderer.nim b/compiler/renderer.nim index b0d328f9e..3f7b0e657 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -620,7 +620,7 @@ proc gpattern(g: var TSrcGen, n: PNode) = if longMode(n) or (lsub(n.sons[0]) + g.lineLen > MaxLineLen): incl(c.flags, rfLongMode) gcoms(g) # a good place for comments - gstmts(g, n.sons[0], c) + gstmts(g, n, c) put(g, tkCurlyRi, "}") proc gpragmaBlock(g: var TSrcGen, n: PNode) = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ac82e9fed..ce06c2e77 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1249,8 +1249,8 @@ proc semAsgn(c: PContext, n: PNode): PNode = proc semReturn(c: PContext, n: PNode): PNode = result = n checkSonsLen(n, 1) - if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or - c.p.owner.kind == skClosureIterator: + if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro, + skClosureIterator}: if n.sons[0].kind != nkEmpty: # transform ``return expr`` to ``result = expr; return`` if c.p.resultSym != nil: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index c7ae42548..220abcad7 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -197,18 +197,20 @@ proc getIntervalType*(m: TMagic, n: PNode): PType = of mSubI, mSubI64, mSubU: binaryOp(`|-|`) of mBitandI, mBitandI64: + # since uint64 is still not even valid for 'range' (since it's no ordinal + # yet), we exclude it from the list (see bug #1638) for now: var a = n.sons[1] var b = n.sons[2] # symmetrical: - if b.kind notin {nkIntLit..nkUInt64Lit}: swap(a, b) - if b.kind in {nkIntLit..nkUInt64Lit}: + if b.kind notin {nkIntLit..nkUInt32Lit}: swap(a, b) + if b.kind in {nkIntLit..nkUInt32Lit}: let x = b.intVal|+|1 if (x and -x) == x and x >= 0: result = makeRange(a.typ, 0, b.intVal) of mModU: let a = n.sons[1] let b = n.sons[2] - if b.kind in {nkIntLit..nkUInt64Lit}: + if b.kind in {nkIntLit..nkUInt32Lit}: if b.intVal >= 0: result = makeRange(a.typ, 0, b.intVal-1) else: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 1d0bba6f0..e33df75ff 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -939,17 +939,19 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # turn explicit 'void' return type into 'nil' because the rest of the # compiler only checks for 'nil': if skipTypes(r, {tyGenericInst}).kind != tyEmpty: - if r.sym == nil or sfAnon notin r.sym.flags: - let lifted = liftParamType(c, kind, genericParams, r, "result", - n.sons[0].info) - if lifted != nil: r = lifted - r.flags.incl tfRetType - r = skipIntLit(r) - if kind == skIterator: - # see tchainediterators - # in cases like iterator foo(it: iterator): type(it) - # we don't need to change the return type to iter[T] - if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r]) + # 'auto' as a return type does not imply a generic: + if r.kind != tyExpr: + if r.sym == nil or sfAnon notin r.sym.flags: + let lifted = liftParamType(c, kind, genericParams, r, "result", + n.sons[0].info) + if lifted != nil: r = lifted + r.flags.incl tfRetType + r = skipIntLit(r) + if kind == skIterator: + # see tchainediterators + # in cases like iterator foo(it: iterator): type(it) + # we don't need to change the return type to iter[T] + if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r]) result.sons[0] = r res.typ = r diff --git a/compiler/vm.nim b/compiler/vm.nim index 2da242771..ad0d3b0a1 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -454,8 +454,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcLdStrIdx: decodeBC(rkInt) let idx = regs[rc].intVal.int - if idx <=% regs[rb].node.strVal.len: - regs[ra].intVal = regs[rb].node.strVal[idx].ord + let s = regs[rb].node.strVal + if s.isNil: + stackTrace(c, tos, pc, errNilAccess) + elif idx <=% s.len: + regs[ra].intVal = s[idx].ord else: stackTrace(c, tos, pc, errIndexOutOfBounds) of opcWrArr: @@ -1058,7 +1061,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].intVal = regs[ra].intVal and ((1'i64 shl rb)-1) of opcIsNil: decodeB(rkInt) - regs[ra].intVal = ord(regs[rb].node.kind == nkNilLit) + let node = regs[rb].node + regs[ra].intVal = ord(node.kind == nkNilLit or + (node.kind in {nkStrLit..nkTripleStrLit} and node.strVal.isNil)) of opcNBindSym: decodeBx(rkNode) regs[ra].node = copyTree(c.constants.sons[rbx]) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index fe909b887..7397a562c 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -370,8 +370,8 @@ proc sameConstant*(a, b: PNode): bool = of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal - of nkType: result = a.typ == b.typ - of nkEmpty, nkNilLit: result = true + of nkType, nkNilLit: result = a.typ == b.typ + of nkEmpty: result = true else: if sonsLen(a) == sonsLen(b): for i in countup(0, sonsLen(a) - 1): @@ -1350,7 +1350,9 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = result = newNodeIT(nkUIntLit, info, t) of tyFloat..tyFloat128: result = newNodeIT(nkFloatLit, info, t) - of tyVar, tyPointer, tyPtr, tyCString, tySequence, tyString, tyExpr, + of tyCString, tyString: + result = newNodeIT(nkStrLit, info, t) + of tyVar, tyPointer, tyPtr, tySequence, tyExpr, tyStmt, tyTypeDesc, tyStatic, tyRef: result = newNodeIT(nkNilLit, info, t) of tyProc: @@ -1570,7 +1572,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = genLit(c, n, dest) of nkUIntLit..pred(nkNilLit): genLit(c, n, dest) of nkNilLit: - if not n.typ.isEmptyType: genLit(c, n, dest) + if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest) else: unused(n, dest) of nkAsgn, nkFastAsgn: unused(n, dest) @@ -1647,7 +1649,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = if allowCast in c.features: genConv(c, n, n.sons[1], dest, opcCast) else: - localError(n.info, errGenerated, "VM is not allowed to 'cast'") + globalError(n.info, errGenerated, "VM is not allowed to 'cast'") else: internalError n.info, "cannot generate VM code for " & n.renderTree diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 2b161778c..a7e1aeab2 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -88,10 +88,9 @@ ## constructor should be used for this purpose. However, ## currently only basic authentication is supported. -import sockets, strutils, parseurl, parseutils, strtabs, base64, os +import net, strutils, uri, parseutils, strtabs, base64, os import asyncnet, asyncdispatch import rawsockets -from net import nil type Response* = tuple[ @@ -101,7 +100,7 @@ type body: string] Proxy* = ref object - url*: Url + url*: Uri auth*: string ProtocolError* = object of IOError ## exception that is raised when server @@ -279,7 +278,7 @@ else: proc newProxy*(url: string, auth = ""): Proxy = ## Constructs a new ``TProxy`` object. - result = Proxy(url: parseUrl(url), auth: auth) + result = Proxy(url: parseUri(url), auth: auth) proc request*(url: string, httpMethod = httpGET, extraHeaders = "", body = "", @@ -290,7 +289,7 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", ## | Extra headers can be specified and must be seperated by ``\c\L`` ## | An optional timeout can be specified in miliseconds, if reading from the ## server takes longer than specified an ETimeout exception will be raised. - var r = if proxy == nil: parseUrl(url) else: proxy.url + var r = if proxy == nil: parseUri(url) else: proxy.url var headers = substr($httpMethod, len("http")) if proxy == nil: headers.add(" /" & r.path & r.query) @@ -308,18 +307,18 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "", add(headers, extraHeaders) add(headers, "\c\L") - var s = socket() - if s == invalidSocket: raiseOSError(osLastError()) - var port = sockets.Port(80) + var s = newSocket() + if s == nil: raiseOSError(osLastError()) + var port = net.Port(80) if r.scheme == "https": when defined(ssl): sslContext.wrapSocket(s) - port = sockets.Port(443) + port = net.Port(443) else: raise newException(HttpRequestError, "SSL support is not available. Cannot connect over SSL.") if r.port != "": - port = sockets.Port(r.port.parseInt) + port = net.Port(r.port.parseInt) if timeout == -1: s.connect(r.hostname, port) @@ -342,9 +341,9 @@ proc getNewLocation(lastUrl: string, headers: StringTableRef): string = result = headers["Location"] if result == "": httpError("location header expected") # Relative URLs. (Not part of the spec, but soon will be.) - let r = parseURL(result) + let r = parseUri(result) if r.hostname == "" and r.path != "": - let origParsed = parseURL(lastUrl) + let origParsed = parseUri(lastUrl) result = origParsed.hostname & "/" & r.path proc get*(url: string, extraHeaders = "", maxRedirects = 5, @@ -437,7 +436,7 @@ proc downloadFile*(url: string, outputFilename: string, else: fileError("Unable to open file") -proc generateHeaders(r: Url, httpMethod: HttpMethod, +proc generateHeaders(r: Uri, httpMethod: HttpMethod, headers: StringTableRef): string = result = substr($httpMethod, len("http")) # TODO: Proxies @@ -455,7 +454,7 @@ type AsyncHttpClient* = ref object socket: AsyncSocket connected: bool - currentURL: Url ## Where we are currently connected. + currentURL: Uri ## Where we are currently connected. headers*: StringTableRef maxRedirects: int userAgent: string @@ -499,7 +498,6 @@ proc recvFull(socket: AsyncSocket, size: int): Future[string] {.async.} = proc parseChunks(client: AsyncHttpClient): Future[string] {.async.} = result = "" - var ri = 0 while true: var chunkSize = 0 var chunkSizeStr = await client.socket.recvLine() @@ -607,7 +605,7 @@ proc parseResponse(client: AsyncHttpClient, else: result.body = "" -proc newConnection(client: AsyncHttpClient, url: Url) {.async.} = +proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} = if client.currentURL.hostname != url.hostname or client.currentURL.scheme != url.scheme: if client.connected: client.close() @@ -643,7 +641,7 @@ proc request*(client: AsyncHttpClient, url: string, httpMethod = httpGET, ## connection can be closed by using the ``close`` procedure. ## ## The returned future will complete once the request is completed. - let r = parseUrl(url) + let r = parseUri(url) await newConnection(client, r) if not client.headers.hasKey("user-agent") and client.userAgent != "": diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index e3c32e806..e67321a59 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -23,6 +23,11 @@ ## ## Asynchronous sockets are supported, however a better alternative is to use ## the `asyncio <asyncio.html>`_ module. +## +## Since version 0.10.2 this module is deprecated. Use the `net <net.html>`_ +## or the ``rawsockets <rawsockets.html>`_ module instead. + +{.deprecated.} include "system/inclrtl" diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index c87823926..adcfdd288 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -38,7 +38,11 @@ proc raiseInvalidFormat(msg: string) {.noinline.} = type TFormatParser = object {.pure, final.} - f: cstring + when defined(js): + f: string # we rely on the '\0' terminator + # which JS's native string doesn't have + else: + f: cstring num, i, lineLen: int template call(x: stmt) {.immediate.} = diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 6bc44719f..9406f26c9 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -33,10 +33,11 @@ type C_JmpBuf {.importc: "jmp_buf", header: "<setjmp.h>".} = object -var - c_stdin {.importc: "stdin", nodecl.}: C_TextFileStar - c_stdout {.importc: "stdout", nodecl.}: C_TextFileStar - c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar +when not defined(vm): + var + c_stdin {.importc: "stdin", nodecl.}: C_TextFileStar + c_stdout {.importc: "stdout", nodecl.}: C_TextFileStar + c_stderr {.importc: "stderr", nodecl.}: C_TextFileStar # constants faked as variables: when not declared(SIGINT): diff --git a/tests/js/tbyvar.nim b/tests/js/tbyvar.nim index 5ed2de1da..1269e6f66 100644 --- a/tests/js/tbyvar.nim +++ b/tests/js/tbyvar.nim @@ -4,12 +4,13 @@ bar 12 2 foo 12 bar 12 -2''' +2 +''' """ # bug #1489 -proc foo(x: int) = echo "foo: ", x -proc bar(y: var int) = echo "bar: ", y +proc foo(x: int) = echo "foo ", x +proc bar(y: var int) = echo "bar ", y var x = 12 foo(x) diff --git a/tests/js/test1.nim b/tests/js/test1.nim index 09ba30676..7f1d346f0 100644 --- a/tests/js/test1.nim +++ b/tests/js/test1.nim @@ -10,9 +10,9 @@ import var inputElement = "1123" -proc OnButtonClick(inputElement: string) {.exportc.} = +proc onButtonClick(inputElement: string) {.exportc.} = let v = $inputElement - if v.allCharsInSet(whiteSpace): + if v.allCharsInSet(WhiteSpace): echo "only whitespace, hu?" else: var x = parseInt(v) diff --git a/tests/metatype/tautonotgeneric.nim b/tests/metatype/tautonotgeneric.nim new file mode 100644 index 000000000..a55ae488e --- /dev/null +++ b/tests/metatype/tautonotgeneric.nim @@ -0,0 +1,15 @@ +discard """ + output: "wof!" +""" + +# bug #1659 +type Animal = ref object {.inheritable.} +type Dog = ref object of Animal + +method say(a: Animal): auto = "wat!" +method say(a: Dog): auto = "wof!" + +proc saySomething(a: Animal): auto = a.say() + +var a = Dog() +echo saySomething(a) diff --git a/tests/misc/teventemitter.nim b/tests/misc/teventemitter.nim index bfcf95701..c1cc3d3a9 100644 --- a/tests/misc/teventemitter.nim +++ b/tests/misc/teventemitter.nim @@ -10,15 +10,15 @@ type events*: Table[string, DoublyLinkedList[proc(e: EventArgs) {.nimcall.}]] proc emit*(emitter: EventEmitter, event: string, args: EventArgs) = - for func in nodes(emitter.events[event]): - func.value(args) #call function with args. + for fn in nodes(emitter.events[event]): + fn.value(args) #call function with args. proc on*(emitter: var EventEmitter, event: string, - func: proc(e: EventArgs) {.nimcall.}) = + fn: proc(e: EventArgs) {.nimcall.}) = if not hasKey(emitter.events, event): var list: DoublyLinkedList[proc(e: EventArgs) {.nimcall.}] add(emitter.events, event, list) #if not, add it. - append(emitter.events.mget(event), func) + append(emitter.events.mget(event), fn) proc initEmitter(emitter: var EventEmitter) = emitter.events = initTable[string, diff --git a/tests/misc/tunsigned64mod.nim b/tests/misc/tunsigned64mod.nim new file mode 100644 index 000000000..9ae0d535a --- /dev/null +++ b/tests/misc/tunsigned64mod.nim @@ -0,0 +1,12 @@ + +# bug #1638 + +import unsigned + +let v1 = 7 +let v2 = 7'u64 + +let t1 = v1 mod 2 # works +let t2 = 7'u64 mod 2'u64 # works +let t3 = v2 mod 2'u64 # Error: invalid type: 'range 0..1(uint64) +let t4 = (v2 mod 2'u64).uint64 # works diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim index 566a74cab..ae9905cde 100644 --- a/tests/testament/categories.nim +++ b/tests/testament/categories.nim @@ -312,7 +312,7 @@ proc testBabelPackages(r: var TResults, cat: Category, filter: PackageFilter) = # ---------------------------------------------------------------------------- -const AdditionalCategories = ["debugger", "examples", "stdlib", "babel-core"] +const AdditionalCategories = ["debugger", "examples", "lib", "babel-core"] proc `&.?`(a, b: string): string = # candidate for the stdlib? @@ -342,7 +342,7 @@ proc processCategory(r: var TResults, cat: Category, options: string) = threadTests r, cat, options & " --threads:on" of "io": ioTests r, cat, options - of "stdlib": + of "lib": testStdlib(r, "lib/pure/*.nim", options, cat) testStdlib(r, "lib/packages/docutils/highlite", options, cat) of "examples": diff --git a/tests/vm/tstringnil.nim b/tests/vm/tstringnil.nim new file mode 100644 index 000000000..5070dd6b7 --- /dev/null +++ b/tests/vm/tstringnil.nim @@ -0,0 +1,50 @@ +# bug #1744 + +import macros + +type + SuiteTest = object + suiteName: string + suiteDesc: string + testName: string + testDesc: string + testBlock: PNimrodNode + +proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tests: seq[SuiteTest]] {.compileTime.} = + var + tests:seq[SuiteTest] = @[] + + for child in suiteBloc.children(): + case $child[0].ident: + of "test": + + var testObj = SuiteTest() + if suiteName.kind == nnkNilLit: + testObj.suiteName = nil + else: + testObj.suiteName = $suiteName + if suiteDesc.kind == nnkNilLit: + testObj.suiteDesc = nil + else: + testObj.suiteDesc = suiteDesc.strVal + testObj.testName = $child[1] # should not ever be nil + if child[2].kind == nnkNilLit: + testObj.testDesc = nil + else: + testObj.testDesc = child[2].strVal + testObj.testBlock = child[3][6] + + tests.add(testObj) + + else: + discard + + return (tests: tests) + +macro suite(suiteName, suiteDesc: expr, suiteBloc: stmt): stmt {.immediate.} = + let contents = buildSuiteContents(suiteName, suiteDesc, suiteBloc) + +# Test above +suite basics, "Description of such": + test(t5, nil): + assert false |