diff options
-rw-r--r-- | compiler/semexprs.nim | 2 | ||||
-rw-r--r-- | compiler/semgnrc.nim | 8 | ||||
-rw-r--r-- | compiler/seminst.nim | 4 | ||||
-rw-r--r-- | compiler/semtypes.nim | 74 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 28 | ||||
-rw-r--r-- | doc/backends.txt | 6 | ||||
-rw-r--r-- | doc/nimc.txt | 52 | ||||
-rw-r--r-- | tests/generics/t1789.nim | 44 | ||||
-rw-r--r-- | tools/nimweb.nim | 20 | ||||
-rw-r--r-- | web/download.txt | 9 | ||||
-rw-r--r-- | web/news.txt | 7 |
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. |