diff options
34 files changed, 323 insertions, 187 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 565bb4353..d85dbf42c 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1517,8 +1517,8 @@ proc getStr*(a: PNode): string = proc getStrOrChar*(a: PNode): string = case a.kind of nkStrLit..nkTripleStrLit: result = a.strVal - of nkCharLit: result = $chr(int(a.intVal)) - else: + of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal)) + else: internalError(a.info, "getStrOrChar") result = "" diff --git a/compiler/nim.ini b/compiler/nim.ini index 576b6d2bb..1f14eb21b 100644 --- a/compiler/nim.ini +++ b/compiler/nim.ini @@ -125,7 +125,7 @@ Files: "start.bat" BinPath: r"bin;dist\mingw\bin;dist" ; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry -Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html" +Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html" Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip" Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe" ; for now only NSIS supports optional downloads diff --git a/compiler/nim.nimrod.cfg b/compiler/nim.nimrod.cfg index ba7697c4c..f4d8b9dcb 100644 --- a/compiler/nim.nimrod.cfg +++ b/compiler/nim.nimrod.cfg @@ -1,7 +1,5 @@ # Special configuration file for the Nim project -# gc:markAndSweep - hint[XDeclaredButNotUsed]:off path:"llvm" path:"$projectPath/.." diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index ee3391e3e..89110a479 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 @@ -926,7 +926,8 @@ const proc readTypeParameter(c: PContext, typ: PType, paramName: PIdent, info: TLineInfo): PNode = let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias - else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1]) + else: (internalAssert(typ.kind == tyCompositeTypeClass); + typ.sons[1].skipGenericAlias) #debug ty let tbody = ty.sons[0] for s in countup(0, tbody.len-2): @@ -965,6 +966,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = var ty = n.sons[0].typ var f: PSym = nil result = nil + if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone): if ty.kind == tyTypeDesc: ty = ty.base ty = ty.skipTypes(tyDotOpTransparent) @@ -985,7 +987,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = of tyTypeParamsHolders: return readTypeParameter(c, ty, i, n.info) of tyObject, tyTuple: - if ty.n.kind == nkRecList: + if ty.n != nil and ty.n.kind == nkRecList: for field in ty.n: if field.sym.name == i: n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ]) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 7c32b0051..1ab4f5989 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -60,13 +60,20 @@ 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 styleCheckUse(n.info, s) of skType: - if (s.typ != nil) and (s.typ.kind != tyGenericParam): + if (s.typ != nil) and + (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}): result = newSymNodeTypeDesc(s, n.info) else: 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/semstmts.nim b/compiler/semstmts.nim index a7603147c..3b0332939 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -653,7 +653,8 @@ proc checkForMetaFields(n: PNode) = template checkMeta(t) = if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: localError(n.info, errTIsNotAConcreteType, t.typeToString) - + + if n.isNil: return case n.kind of nkRecList, nkRecCase: for s in n: checkForMetaFields(s) 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..b58818a29 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: @@ -964,6 +979,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = of tyStatic: if aOrig.kind == tyStatic: result = typeRel(c, f.lastSon, a) + if result != isNone and f.n != nil: + if not exprStructuralEquivalent(f.n, a.n): + result = isNone if result != isNone: put(c.bindings, f, aOrig) else: result = isNone @@ -1006,15 +1024,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/compiler/suggest.nim b/compiler/suggest.nim index c700db323..f7b00c8f8 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -74,9 +74,6 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) = suggestWriteln(symToStr(s, isLocal=true, sectionSuggest)) inc outputs -when not defined(nimhygiene): - {.pragma: inject.} - template wholeSymTab(cond, section: expr) {.immediate.} = var isLocal = true for scope in walkScopes(c.currentScope): diff --git a/compiler/types.nim b/compiler/types.nim index f67cd239e..4a77773e6 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -17,7 +17,7 @@ proc lastOrd*(t: PType): BiggestInt proc lengthOrd*(t: PType): BiggestInt type TPreferedDesc* = enum - preferName, preferDesc, preferExported, preferModuleInfo + preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string proc base*(t: PType): PType @@ -411,11 +411,13 @@ const "UserTypeClassInst", "CompositeTypeClass", "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"] +const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg} + proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = var t = typ result = "" if t == nil: return - if prefer in {preferName, preferModuleInfo} and t.sym != nil and + if prefer in preferToResolveSymbols and t.sym != nil and sfAnon notin t.sym.flags: if t.kind == tyInt and isIntLit(t): return t.sym.name.s & " literal(" & $t.n.intVal & ")" @@ -428,20 +430,26 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = if not isIntLit(t) or prefer == preferExported: result = typeToStr[t.kind] else: - result = "int literal(" & $t.n.intVal & ")" + if prefer == preferGenericArg: + result = $t.n.intVal + else: + result = "int literal(" & $t.n.intVal & ")" of tyGenericBody, tyGenericInst, tyGenericInvokation: result = typeToString(t.sons[0]) & '[' for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): if i > 1: add(result, ", ") - add(result, typeToString(t.sons[i])) + add(result, typeToString(t.sons[i], preferGenericArg)) add(result, ']') of tyTypeDesc: if t.base.kind == tyNone: result = "typedesc" else: result = "typedesc[" & typeToString(t.base) & "]" of tyStatic: internalAssert t.len > 0 - result = "static[" & typeToString(t.sons[0]) & "]" - if t.n != nil: result.add "(" & renderTree(t.n) & ")" + if prefer == preferGenericArg and t.n != nil: + result = t.n.renderTree + else: + result = "static[" & typeToString(t.sons[0]) & "]" + if t.n != nil: result.add "(" & renderTree(t.n) & ")" of tyUserTypeClass: internalAssert t.sym != nil and t.sym.owner != nil return t.sym.owner.name.s diff --git a/copying.txt b/copying.txt index 254b91c77..908625e18 100644 --- a/copying.txt +++ b/copying.txt @@ -1,5 +1,5 @@ ===================================================== -Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/ +Nim -- a Compiler for Nim. http://nim-lang.org/ Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved. 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/doc/tut1.txt b/doc/tut1.txt index 9d75b1ea2..4c32fa0ae 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -139,7 +139,7 @@ Numbers Numerical literals are written as in most other languages. As a special twist, underscores are allowed for better readability: ``1_000_000`` (one million). A number that contains a dot (or 'e' or 'E') is a floating point literal: -``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``, +``1.0e9`` (one billion). Hexadecimal literals are prefixed with ``0x``, binary literals with ``0b`` and octal literals with ``0o``. A leading zero alone does not produce an octal. diff --git a/doc/tut2.txt b/doc/tut2.txt index 6e239d681..9d3409164 100644 --- a/doc/tut2.txt +++ b/doc/tut2.txt @@ -56,7 +56,7 @@ Objects have access to their type at runtime. There is an .. code-block:: nim type - TPerson = object of TObject + TPerson = object of RootObj name*: string # the * means that `name` is accessible from other modules age: int # no * means that the field is hidden from other modules @@ -76,10 +76,10 @@ never *equivalent*. New object types can only be defined within a type section. Inheritance is done with the ``object of`` syntax. Multiple inheritance is -currently not supported. If an object type has no suitable ancestor, ``TObject`` +currently not supported. If an object type has no suitable ancestor, ``RootObj`` can be used as its ancestor, but this is only a convention. Objects that have no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma -to introduce new object roots apart from ``system.TObject``. (This is used +to introduce new object roots apart from ``system.RootObj``. (This is used in the GTK wrapper for instance.) @@ -228,7 +228,7 @@ is needed: .. code-block:: nim type - TSocket* = object of TObject + TSocket* = object of RootObj FHost: int # cannot be accessed from the outside of the module # the `F` prefix is a convention to avoid clashes since # the accessors are named `host` @@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the .. code-block:: nim type - PExpr = ref object of TObject ## abstract base class for an expression + PExpr = ref object of RootObj ## abstract base class for an expression PLiteral = ref object of PExpr x: int PPlusExpr = ref object of PExpr @@ -313,7 +313,7 @@ dispatching: .. code-block:: nim type - TThing = object of TObject + TThing = object of RootObj TUnit = object of TThing x: int diff --git a/koch.nim b/koch.nim index 79228c1a4..e3831617c 100644 --- a/koch.nim +++ b/koch.nim @@ -94,16 +94,16 @@ const compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" proc csource(args: string) = - exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=mingw32 csource compiler/nim.ini $1" % + exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource compiler/nim.ini $1" % [args, VersionAsString, compileNimInst, findNim()]) proc zip(args: string) = - exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nim.ini" % + exec("$3 cc -r $2 --var:version=$1 --var:mingw=none scripts compiler/nim.ini" % [VersionAsString, compileNimInst, findNim()]) - exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nim.ini" % + exec("$# --var:version=$# --var:mingw=none zip compiler/nim.ini" % ["tools/niminst/niminst".exe, VersionAsString]) - -proc buildTool(toolname, args: string) = + +proc buildTool(toolname, args: string) = exec("$# cc $# $#" % [findNim(), args, toolname]) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) @@ -114,11 +114,11 @@ proc nsis(args: string) = # produce 'nimrod_debug.exe': exec "nim c compiler" / "nim.nim" copyExe("compiler/nim".exe, "bin/nim_debug".exe) - exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" & - " nsis compiler/nim") % VersionAsString) + exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" & + " nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)]) proc install(args: string) = - exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nim.ini" % + exec("$# cc -r $# --var:version=$# --var:mingw=none scripts compiler/nim.ini" % [findNim(), compileNimInst, VersionAsString]) exec("sh ./install.sh $#" % args) diff --git a/lib/impure/osinfo_posix.nim b/lib/impure/osinfo_posix.nim index 1baff8c55..0ed4289c4 100644 --- a/lib/impure/osinfo_posix.nim +++ b/lib/impure/osinfo_posix.nim @@ -35,7 +35,15 @@ proc getSystemVersion*(): string = elif $unix_info.sysname == "Darwin": # Darwin result.add("Mac OS X ") - if "10" in $unix_info.release: + if "14" in $unix_info.release: + result.add("v10.10 Yosemite") + elif "13" in $unix_info.release: + result.add("v10.9 Mavericks") + elif "12" in $unix_info.release: + result.add("v10.8 Mountian Lion") + elif "11" in $unix_info.release: + result.add("v10.7 Lion") + elif "10" in $unix_info.release: result.add("v10.6 Snow Leopard") elif "9" in $unix_info.release: result.add("v10.5 Leopard") diff --git a/lib/impure/osinfo_win.nim b/lib/impure/osinfo_win.nim index f423a34a3..becec928e 100644 --- a/lib/impure/osinfo_win.nim +++ b/lib/impure/osinfo_win.nim @@ -245,6 +245,14 @@ proc `$`*(osvi: TVersionInfo): string = if osvi.ProductType == VER_NT_WORKSTATION: result.add("Windows 7 ") else: result.add("Windows Server 2008 R2 ") + elif osvi.minorVersion == 2: + if osvi.ProductType == VER_NT_WORKSTATION: + result.add("Windows 8 ") + else: result.add("Windows Server 2012 ") + elif osvi.minorVersion == 3: + if osvi.ProductType == VER_NT_WORKSTATION: + result.add("Windows 8.1 ") + else: result.add("Windows Server 2012 R2 ") var dwType = getProductInfo(osvi.majorVersion, osvi.minorVersion, 0, 0) case dwType diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index deb120372..0498a0e70 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -1570,9 +1570,9 @@ else: when defined(macosx): + # We can't use the NOSIGNAL flag in the ``send`` function, it has no effect var - MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint - MSG_NOSIGNAL* = MSG_HAVEMORE + MSG_NOSIGNAL* = 0'i32 else: var MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint diff --git a/lib/pure/rawsockets.nim b/lib/pure/rawsockets.nim index 62a011999..e23deea5b 100644 --- a/lib/pure/rawsockets.nim +++ b/lib/pure/rawsockets.nim @@ -428,6 +428,10 @@ proc selectWrite*(writefds: var seq[SocketHandle], pruneSocketSet(writefds, (wr)) +# We ignore signal SIGPIPE on Darwin +when defined(macosx): + signal(SIGPIPE, SIG_IGN) + when defined(Windows): var wsa: WSAData if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError()) diff --git a/lib/system.nim b/lib/system.nim index ca85bf1ad..b7c77e276 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1516,7 +1516,7 @@ const NimMinor*: int = 10 ## is the minor number of Nim's version. - NimPatch*: int = 2 + NimPatch*: int = 3 ## is the patch number of Nim's version. NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch diff --git a/lib/system/channels.nim b/lib/system/channels.nim index 3e5ca0795..d07d6eae1 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -232,9 +232,10 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool, ## it returns ``(false, default(msg))``. var q = cast[PRawChannel](addr(c)) if q.mask != ChannelDeadMask: - if tryAcquireSys(q.lock): - llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) - result.dataAvailable = true + if tryAcquireSys(q.lock): + if q.count > 0: + llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) + result.dataAvailable = true releaseSys(q.lock) proc peek*[TMsg](c: var TChannel[TMsg]): int = diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 76d17bc4a..51a12141b 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -368,32 +368,32 @@ type {.deprecated: [TSocketHandle: SocketHandle].} type - WSAData* {.importc: "WSADATA", header: "Winsock2.h".} = object + WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object wVersion, wHighVersion: int16 szDescription: array[0..WSADESCRIPTION_LEN, char] szSystemStatus: array[0..WSASYS_STATUS_LEN, char] iMaxSockets, iMaxUdpDg: int16 lpVendorInfo: cstring - SockAddr* {.importc: "SOCKADDR", header: "Winsock2.h".} = object + SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object sa_family*: int16 # unsigned sa_data: array[0..13, char] - InAddr* {.importc: "IN_ADDR", header: "Winsock2.h".} = object + InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object s_addr*: int32 # IP address Sockaddr_in* {.importc: "SOCKADDR_IN", - header: "Winsock2.h".} = object + header: "winsock2.h".} = object sin_family*: int16 sin_port*: int16 # unsigned sin_addr*: InAddr sin_zero*: array[0..7, char] - In6_addr* {.importc: "IN6_ADDR", header: "Winsock2.h".} = object + In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object bytes*: array[0..15, char] Sockaddr_in6* {.importc: "SOCKADDR_IN6", - header: "Winsock2.h".} = object + header: "winsock2.h".} = object sin6_family*: int16 sin6_port*: int16 # unsigned sin6_flowinfo*: int32 # unsigned @@ -450,22 +450,22 @@ type var - SOMAXCONN* {.importc, header: "Winsock2.h".}: cint - INVALID_SOCKET* {.importc, header: "Winsock2.h".}: SocketHandle - SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint - SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording - SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen() - SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse - SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive - SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses - SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs - SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible - SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present - SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line - - SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint - SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse - SO_ERROR* {.importc, header: "Winsock2.h".}: cint + SOMAXCONN* {.importc, header: "winsock2.h".}: cint + INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle + SOL_SOCKET* {.importc, header: "winsock2.h".}: cint + SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording + SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen() + SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse + SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive + SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses + SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs + SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible + SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present + SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line + + SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint + SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse + SO_ERROR* {.importc, header: "winsock2.h".}: cint proc `==`*(x, y: SocketHandle): bool {.borrow.} diff --git a/tests/generics/t1056.nim b/tests/generics/t1056.nim new file mode 100644 index 000000000..73a24a76a --- /dev/null +++ b/tests/generics/t1056.nim @@ -0,0 +1,26 @@ +discard """ + output: '''TMatrix[3, 3, system.int] +3 +3''' +""" + +import typetraits + +type + TMatrix*[N,M: static[int], T] = object + data*: array[0..N*M-1, T] + + TMat2[T] = TMatrix[2,2,T] + +proc echoMatrix(a: TMatrix) = + echo a.type.name + echo TMatrix.N + +proc echoMat2(a: TMat2) = + echo TMat2.M + +var m = TMatrix[3,3,int](data: [1,2,3,4,5,6,7,8,9]) + +echoMatrix m +echoMat2 m + 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/tests/misc/tvarious.nim b/tests/misc/tvarious.nim index ed2964cf9..434d25e48 100644 --- a/tests/misc/tvarious.nim +++ b/tests/misc/tvarious.nim @@ -62,3 +62,7 @@ when false: block: var a, b: Bar[int, 0..2] discard foo(a, b) + +# bug #1788 + +echo "hello" & char(ord(' ')) & "world" diff --git a/tests/threads/ttryrecv.nim b/tests/threads/ttryrecv.nim new file mode 100644 index 000000000..acccf182c --- /dev/null +++ b/tests/threads/ttryrecv.nim @@ -0,0 +1,35 @@ +discard """ + outputsub: "channel is empty" +""" + +# bug #1816 + +from math import random +from os import sleep + +type PComm = ptr TChannel[int] + +proc doAction(outC: PComm) {.thread.} = + for i in 0.. <5: + sleep(random(100)) + send(outC[], i) + +var + thr: TThread[PComm] + chan: TChannel[int] + +open(chan) +createThread[PComm](thr, doAction, addr(chan)) + +while true: + let (flag, x) = tryRecv(chan) + if flag: + echo("received from chan: " & $x) + else: + echo "channel is empty" + break + +echo "Finished listening" + +joinThread(thr) +close(chan) diff --git a/tests/typerel/typedescs.nim b/tests/typerel/typedescs.nim new file mode 100644 index 000000000..23b9ce64f --- /dev/null +++ b/tests/typerel/typedescs.nim @@ -0,0 +1,7 @@ +# bug #1774 +proc p(T: typedesc) = discard + +p(type((5, 6))) # Compiles +(type((5, 6))).p # Doesn't compile (SIGSEGV: Illegal storage access.) +type T = type((5, 6)) # Doesn't compile (SIGSEGV: Illegal storage access.) + diff --git a/tests/types/tisopr.nim b/tests/types/tisopr.nim index 3c2b9ee5e..8b7fe4e46 100644 --- a/tests/types/tisopr.nim +++ b/tests/types/tisopr.nim @@ -34,3 +34,20 @@ type yes s.items is Iter[TNumber] no s.items is Iter[float] +type + Foo[N: static[int], T] = object + field: array[1..N, T] + + Bar[T] = Foo[4, T] + Baz[N: static[int]] = Foo[N, float] + +no Foo[2, float] is Foo[3, float] +no Foo[2, float] is Foo[2, int] + +yes Foo[4, string] is Foo[4, string] +yes Bar[int] is Foo[4, int] +yes Foo[4, int] is Bar[int] + +no Foo[4, int] is Baz[4] +yes Foo[4, float] is Baz[4] + 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/tools/website.tmpl b/tools/website.tmpl index 6f7a216a5..fed52ac15 100644 --- a/tools/website.tmpl +++ b/tools/website.tmpl @@ -63,7 +63,7 @@ <span class="tab end"> </span>count += <span class="val">1</span> echo(<span class="val">"Average line length: "</span>, - <span class="kwd">if</span> count: sum / count <span class="kwd">else</span>: <span class="val">0</span>) + <span class="kwd">if</span> count > <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>) </pre> </div> <div> diff --git a/web/download.txt b/web/download.txt index 248c0b1bf..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 @@ -24,7 +21,7 @@ This installation method is the preferred way for Linux, Mac OS X, and other Uni like systems. Binary packages may be provided later. -Download `nim_0.10.2.zip <download/nim_0.10.2.zip>`_, extract it and follow +Download `nim-0.10.2.zip <download/nim-0.10.2.zip>`_, extract it and follow these instructions: * sh build.sh diff --git a/web/news.txt b/web/news.txt index cca2aaeee..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. @@ -137,9 +140,9 @@ Compiler Additions - The following procs are now available at compile-time:: math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round, - math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, math.cosh, - math.hypot, math.sinh, math.sin, math.tan, math.tanh, math.pow, - math.trunc, math.floor, math.ceil, math.fmod, + math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, + math.cosh, math.hypot, math.sinh, math.sin, math.tan, math.tanh, + math.pow, math.trunc, math.floor, math.ceil, math.fmod, os.getEnv, os.existsEnv, os.dirExists, os.fileExists, system.writeFile |