summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semgnrc.nim8
-rw-r--r--compiler/seminst.nim4
-rw-r--r--compiler/semtypes.nim74
-rw-r--r--compiler/sigmatch.nim28
-rw-r--r--doc/backends.txt6
-rw-r--r--doc/nimc.txt52
-rw-r--r--tests/generics/t1789.nim44
-rw-r--r--tools/nimweb.nim20
-rw-r--r--web/download.txt9
-rw-r--r--web/news.txt7
11 files changed, 135 insertions, 119 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index ee3391e3e..b2f623fb8 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -219,7 +219,7 @@ proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
   # gnrc. params, then it won't be necessary to open a new scope here
   openScope(c)
   var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
-                         t, ":anon", info)
+                             t, ":anon", info)
   closeScope(c)
   if lifted != nil: t = lifted
 
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 7c32b0051..06959b8d1 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -60,7 +60,13 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
     else:
       result = symChoice(c, n, s, scOpen)
   of skGenericParam: 
-    result = newSymNodeTypeDesc(s, n.info)
+    if s.typ != nil and s.typ.kind == tyStatic:
+      if s.typ.n != nil:
+        result = s.typ.n
+      else:
+        result = n
+    else:
+      result = newSymNodeTypeDesc(s, n.info)
     styleCheckUse(n.info, s)
   of skParam:
     result = n
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 2decb5d0b..81a4465c5 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -21,7 +21,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
     var q = a.sym
     if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
       continue
-    var s = newSym(skType, q.name, getCurrOwner(), q.info)
+    let symKind = if q.typ.kind == tyStatic: skConst else: skType
+    var s = newSym(symKind, q.name, getCurrOwner(), q.info)
     s.flags = s.flags + {sfUsed, sfFromGeneric}
     var t = PType(idTableGet(pt, q.typ))
     if t == nil:
@@ -40,6 +41,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
       t = generateTypeInstance(c, pt, a, t)
       #t = ReplaceTypeVarsT(cl, t)
     s.typ = t
+    if t.kind == tyStatic: s.ast = t.n
     addDecl(c, s)
     entry.concreteTypes[i] = t
 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 4305a48e1..eb15c3809 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -214,44 +214,48 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
     localError(n.info, errXExpectsOneTypeParam, "range")
     result = newOrPrevType(tyError, prev, c)
 
+proc semArrayIndex(c: PContext, n: PNode): PType =
+  if isRange(n): result = semRangeAux(c, n, nil)
+  else:
+    let e = semExprWithType(c, n, {efDetermineType})
+    if e.typ.kind == tyFromExpr:
+      result = makeRangeWithStaticExpr(c, e.typ.n)
+    elif e.kind in {nkIntLit..nkUInt64Lit}:
+      result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
+    elif e.kind == nkSym and e.typ.kind == tyStatic:
+      if e.sym.ast != nil:
+        return semArrayIndex(c, e.sym.ast)
+      internalAssert c.inGenericContext > 0
+      if not isOrdinalType(e.typ.lastSon):
+        localError(n[1].info, errOrdinalTypeExpected)
+      result = makeRangeWithStaticExpr(c, e)
+      result.flags.incl tfUnresolved
+    elif e.kind in nkCallKinds and hasGenericArguments(e):
+      if not isOrdinalType(e.typ):
+        localError(n[1].info, errOrdinalTypeExpected)
+      # This is an int returning call, depending on an
+      # yet unknown generic param (see tgenericshardcases).
+      # We are going to construct a range type that will be
+      # properly filled-out in semtypinst (see how tyStaticExpr
+      # is handled there).
+      result = makeRangeWithStaticExpr(c, e)
+    elif e.kind == nkIdent:
+      result = e.typ.skipTypes({tyTypeDesc})
+    else:
+      let x = semConstExpr(c, e)
+      if x.kind in {nkIntLit..nkUInt64Lit}:
+        result = makeRangeType(c, 0, x.intVal-1, n.info, 
+                             x.typ.skipTypes({tyTypeDesc}))
+      else:
+        result = x.typ.skipTypes({tyTypeDesc})
+        #localError(n[1].info, errConstExprExpected)
+
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
-  var indx, base: PType
+  var base: PType
   result = newOrPrevType(tyArray, prev, c)
-  if sonsLen(n) == 3: 
+  if sonsLen(n) == 3:
     # 3 = length(array indx base)
-    if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
-    else:
-      let e = semExprWithType(c, n.sons[1], {efDetermineType})
-      if e.typ.kind == tyFromExpr:
-        indx = makeRangeWithStaticExpr(c, e.typ.n)
-      elif e.kind in {nkIntLit..nkUInt64Lit}:
-        indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
-      elif e.kind == nkSym and e.typ.kind == tyStatic:
-        if e.sym.ast != nil: return semArray(c, e.sym.ast, nil)
-        internalAssert c.inGenericContext > 0
-        if not isOrdinalType(e.typ.lastSon):
-          localError(n[1].info, errOrdinalTypeExpected)
-        indx = makeRangeWithStaticExpr(c, e)
-        indx.flags.incl tfUnresolved
-      elif e.kind in nkCallKinds and hasGenericArguments(e):
-        if not isOrdinalType(e.typ):
-          localError(n[1].info, errOrdinalTypeExpected)
-        # This is an int returning call, depending on an
-        # yet unknown generic param (see tgenericshardcases).
-        # We are going to construct a range type that will be
-        # properly filled-out in semtypinst (see how tyStaticExpr
-        # is handled there).
-        indx = makeRangeWithStaticExpr(c, e)
-      elif e.kind == nkIdent:
-        indx = e.typ.skipTypes({tyTypeDesc})
-      else:
-        let x = semConstExpr(c, e)
-        if x.kind in {nkIntLit..nkUInt64Lit}:
-          indx = makeRangeType(c, 0, x.intVal-1, n.info, 
-                               x.typ.skipTypes({tyTypeDesc}))
-        else:
-          indx = x.typ.skipTypes({tyTypeDesc})
-          #localError(n[1].info, errConstExprExpected)
+    var indx = semArrayIndex(c, n[1])
     addSonSkipIntLit(result, indx)
     if indx.kind == tyGenericInst: indx = lastSon(indx)
     if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 06f9d58b7..d7bf4fee9 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -517,6 +517,16 @@ proc maybeSkipDistinct(t: PType, callee: PSym): PType =
   else:
     result = t
 
+proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
+  # Consider this example:
+  #   type Value[N: static[int]] = object
+  #   proc foo[N](a: Value[N], r: range[0..(N-1)])
+  # 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)
+  result = c.c.semExpr(c.c, instantiated)
+
 proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
@@ -620,6 +630,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       # bugfix: accept integer conversions here
       #if result < isGeneric: result = isNone
       if result notin {isNone, isGeneric}:
+        # resolve any late-bound static expressions
+        # that may appear in the range:
+        for i in 0..1:
+          if f.n[i].kind == nkStaticExpr:
+            f.n.sons[i] = tryResolvingStaticExpr(c, f.n[i])
         result = typeRangeRel(f, a)
     else:
       if skipTypes(f, {tyRange}).kind == a.kind:
@@ -1006,15 +1021,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyFromExpr:
     # fix the expression, so it contains the already instantiated types
-    let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
-    let reevaluted = c.c.semExpr(c.c, instantiated)
-    case reevaluted.typ.kind
+    let reevaluated = tryResolvingStaticExpr(c, f.n)
+    case reevaluated.typ.kind
     of tyTypeDesc:
-      result = typeRel(c, a, reevaluted.typ.base)
+      result = typeRel(c, a, reevaluated.typ.base)
     of tyStatic:
-      result = typeRel(c, a, reevaluted.typ.base)
-      if result != isNone and reevaluted.typ.n != nil:
-        if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n):
+      result = typeRel(c, a, reevaluated.typ.base)
+      if result != isNone and reevaluated.typ.n != nil:
+        if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
           result = isNone
     else:
       localError(f.n.info, errTypeExpected)
diff --git a/doc/backends.txt b/doc/backends.txt
index eb16217cd..ffe2d5e88 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -456,11 +456,7 @@ can then attach a GC to this thread via
 
 .. code-block:: nim
 
-  setStackBottom(addr(someLocal))
-  initGC()
-
-At the moment this support is still experimental so you need to expose these
-functions yourself or submit patches to request a public API. 
+  system.setupForeignThreadGc()
 
 It is **not** safe to disable the garbage collector and enable it after the
 call from your background thread even if the code you are calling is short
diff --git a/doc/nimc.txt b/doc/nimc.txt
index 92acd3979..a2274febd 100644
--- a/doc/nimc.txt
+++ b/doc/nimc.txt
@@ -550,58 +550,6 @@ in C/C++).
 **Note**: This pragma will not exist for the LLVM backend.

 
 
-Source code style
-=================
-
-Nim allows you to `mix freely case and underscores as identifier separators
-<manual.html#identifiers-keywords>`_, so variables named ``MyPrecioussInt`` and
-``my_preciouss_int`` are equivalent:
-
-.. code-block:: Nim
-  var MyPrecioussInt = 3
-  # Following line compiles fine!
-  echo my_preciouss_int
-
-Since this can lead to many variants of the same source code (you can use
-`nimgrep <nimgrep.html>`_ instead of your typical ``grep`` to ignore style
-problems) the compiler provides the command ``pretty`` to help unifying the
-style of source code.  Running ``nim pretty ugly_test.nim`` with this
-example will generate a secondary file named ``ugly_test.pretty.nim`` with the
-following content:
-
-.. code-block:: Nim
-  var MyPrecioussInt = 3
-  # Following line compiles fine!
-  echo MyPrecioussInt
-
-During execution the ``pretty`` command will also run on Nim's standard
-library, since it doesn't differentiate the standard library as something
-special, and hence will warn of many *errors* which are out of your hand to
-fix, creating respective ``.pretty.nim`` files all the way. You can ignore
-these errors if they don't belong to your source and simply compare your
-original version to the new pretty one. In fact, running ``pretty`` on our test
-file will show the following::
-
-  Hint: ugly_test [Processing]
-  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
-  ugly_test.nim(1, 4) Error: name should be: myPrecioussInt
-
-At the moment ``pretty`` will homogenize the style of symbols but will leave
-important changes for you to review. In this case the command is warning that a
-variable name should not start with a capital letter, which is usually reserved
-to `object types <tut2.html#objects>`_. To learn about the accepted `camel case
-style <https://en.wikipedia.org/wiki/Camelcase>`_ read `Coding Guidelines in
-the Internals of Nim Compiler <intern.html#coding-guidelines>`_ or `Coding
-Guidelines <https://github.com/Araq/Nim/wiki/Coding-Guidelines>`_ and `NEP 1
-: Style Guide for Nim Code
-<https://github.com/Araq/Nim/wiki/NEP-1-:-Style-Guide-for-Nim-Code>`_
-from the Nim `GitHub wiki<https://github.com/Araq/Nim/wiki>`_.
-
-This command is safe to run because it will never attempt to overwrite your
-existing sources, but the respective ``.pretty.nim`` files **will** be
-overwritten without notice.
-
-
 DynlibOverride
 ==============
 
diff --git a/tests/generics/t1789.nim b/tests/generics/t1789.nim
new file mode 100644
index 000000000..188db88f6
--- /dev/null
+++ b/tests/generics/t1789.nim
@@ -0,0 +1,44 @@
+discard """
+  output: "3\n0"
+"""
+
+# https://github.com/Araq/Nim/issues/1789
+
+type
+  Foo[N: static[int]] = object
+
+proc bindStaticN[N](foo: Foo[N]) =
+  var ar0: array[3, int]
+  var ar1: array[N, int]
+  var ar2: array[1..N, int]
+  var ar3: array[0..(N+10), float]
+  echo N
+
+var f: Foo[3]
+f.bindStaticN
+
+# case 2
+
+type
+  ObjectWithStatic[X, Y: static[int], T] = object
+    bar: array[X * Y, T]   # this one works
+
+  AliasWithStatic[X, Y: static[int], T] = array[X * Y, T]
+
+var
+  x: ObjectWithStatic[1, 2, int]
+  y: AliasWithStatic[2, 3, int]
+
+# case 3
+
+type
+  Bar[N: static[int], T] = object
+    bar: array[N, T]
+
+proc `[]`*[N, T](f: Bar[N, T], n: range[0..(N - 1)]): T =
+  assert high(n) == N-1
+  result = f.bar[n]
+  
+var b: Bar[3, int]
+echo b[2]
+
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index bbd3776d7..0596076b3 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -47,7 +47,7 @@ proc initConfigData(c: var TConfigData) =
   c.logo = ""
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
-  c.gitRepo = "https://github.com/Araq/Nimrod/tree"
+  c.gitRepo = "https://github.com/Araq/Nim/tree"
   c.gitCommit = "master"
   c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
@@ -262,24 +262,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
   exec("nim doc2 $# -o:$# $#" %
     [c.nimArgs, destPath / "docgen_sample2.html", src])
 
+proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
+
 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):
-    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc2):
-    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
 
@@ -311,8 +313,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
   var commands = newSeq[string](c.webdoc.len)
   for i, doc in pairs(c.webdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, doc.pathPart,
       destPath / changeFileExt(splitFile(doc).name, "html"), doc]
   mexec(commands, c.numProcessors)
 
diff --git a/web/download.txt b/web/download.txt
index 1ba1ad5f7..497781ad6 100644
--- a/web/download.txt
+++ b/web/download.txt
@@ -9,12 +9,9 @@ and clang on Mac OS X.
 Binaries
 ========
 
-Unfortunately for now we provide no binary builds.
-
-..
-  Unfortunately for now we only provide builds for Windows.
-  * 32 bit: `nim_0.10.2.exe <download/nim-0.10.2.exe>`_
-  * 64 bit: `nim_0.10.2_x64.exe <download/nim-0.10.2_x64.exe>`_
+Unfortunately for now we only provide builds for Windows.
+* 32 bit: `nim-0.10.2_x32.exe <download/nim-0.10.2_x32.exe>`_
+* 64 bit: `nim-0.10.2_x64.exe <download/nim-0.10.2_x64.exe>`_
 
 
 Installation based on generated C code
diff --git a/web/news.txt b/web/news.txt
index 75c574405..ee9ad8837 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -29,7 +29,10 @@ for lightweight threading through the use of ``spawn``.
 The unpopular "T" and "P" prefixes on types have been deprecated. Nim also
 became more expressive by weakening the distinction between statements and
 expressions. We also added a new and searchable forum, a new website, and our
-documentation generator ``docgen`` has seen major improvements.
+documentation generator ``docgen`` has seen major improvements. Many thanks to
+Nick Greenfield for the much more beautiful documentation!
+
+
 
 What's left to be done
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -120,7 +123,7 @@ Language Additions
 - The builtin ``procCall`` can be used to get ``super``-like functionality
   for multi methods.
 - There is a new pragma ``{.experimental.}`` that enables experimental
-  language features per module, or you can enable this features on a global
+  language features per module, or you can enable these features on a global
   level with the ``--experimental`` command line option.