summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/renderer.nim2
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semfold.nim8
-rw-r--r--compiler/semtypes.nim24
-rw-r--r--compiler/vm.nim11
-rw-r--r--compiler/vmgen.nim12
-rw-r--r--lib/pure/httpclient.nim32
-rw-r--r--lib/pure/sockets.nim5
-rw-r--r--lib/pure/subexes.nim6
-rw-r--r--lib/system/ansi_c.nim9
-rw-r--r--tests/js/tbyvar.nim7
-rw-r--r--tests/js/test1.nim4
-rw-r--r--tests/metatype/tautonotgeneric.nim15
-rw-r--r--tests/misc/teventemitter.nim8
-rw-r--r--tests/misc/tunsigned64mod.nim12
-rw-r--r--tests/testament/categories.nim4
-rw-r--r--tests/vm/tstringnil.nim50
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