Merge branch 'devel' of https://github.com/Araq/Nim into devel

This commit is contained in:
Audun Wilhelmsen 2015-01-02 22:12:11 +01:00
commit c461f5a8c6
57 changed files with 652 additions and 436 deletions

View file

@ -1517,7 +1517,7 @@ proc getStr*(a: PNode): string =
proc getStrOrChar*(a: PNode): string = proc getStrOrChar*(a: PNode): string =
case a.kind case a.kind
of nkStrLit..nkTripleStrLit: result = a.strVal of nkStrLit..nkTripleStrLit: result = a.strVal
of nkCharLit: result = $chr(int(a.intVal)) of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
else: else:
internalError(a.info, "getStrOrChar") internalError(a.info, "getStrOrChar")
result = "" result = ""

View file

@ -125,7 +125,7 @@ Files: "start.bat"
BinPath: r"bin;dist\mingw\bin;dist" BinPath: r"bin;dist\mingw\bin;dist"
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry ; 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"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" 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 ; for now only NSIS supports optional downloads

View file

@ -1,7 +1,5 @@
# Special configuration file for the Nim project # Special configuration file for the Nim project
# gc:markAndSweep
hint[XDeclaredButNotUsed]:off hint[XDeclaredButNotUsed]:off
path:"llvm" path:"llvm"
path:"$projectPath/.." path:"$projectPath/.."

View file

@ -67,12 +67,25 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
# error correction: # error correction:
result = copyTree(arg) result = copyTree(arg)
result.typ = formal result.typ = formal
else:
let x = result.skipConv
if x.kind == nkPar and formal.kind != tyExpr:
changeType(x, formal, check=true)
proc inferWithMetatype(c: PContext, formal: PType, proc inferWithMetatype(c: PContext, formal: PType,
arg: PNode, coerceDistincts = false): PNode arg: PNode, coerceDistincts = false): PNode
var commonTypeBegin = PType(kind: tyExpr) var commonTypeBegin = PType(kind: tyExpr)
proc isEmptyContainer(t: PType): bool =
case t.kind
of tyExpr, tyNil: result = true
of tyArray, tyArrayConstr: result = t.sons[1].kind == tyEmpty
of tySet, tySequence, tyOpenArray, tyVarargs:
result = t.sons[0].kind == tyEmpty
of tyGenericInst: result = isEmptyContainer(t.lastSon)
else: result = false
proc commonType*(x, y: PType): PType = proc commonType*(x, y: PType): PType =
# new type relation that is used for array constructors, # new type relation that is used for array constructors,
# if expressions, etc.: # if expressions, etc.:
@ -96,6 +109,13 @@ proc commonType*(x, y: PType): PType =
# check for seq[empty] vs. seq[int] # check for seq[empty] vs. seq[int]
let idx = ord(b.kind in {tyArray, tyArrayConstr}) let idx = ord(b.kind in {tyArray, tyArrayConstr})
if a.sons[idx].kind == tyEmpty: return y if a.sons[idx].kind == tyEmpty: return y
elif a.kind == tyTuple and b.kind == tyTuple and a.len == b.len:
var nt: PType
for i in 0.. <a.len:
if isEmptyContainer(a.sons[i]) and not isEmptyContainer(b.sons[i]):
if nt.isNil: nt = copyType(a, a.owner, false)
nt.sons[i] = b.sons[i]
if not nt.isNil: result = nt
#elif b.sons[idx].kind == tyEmpty: return x #elif b.sons[idx].kind == tyEmpty: return x
elif a.kind == tyRange and b.kind == tyRange: elif a.kind == tyRange and b.kind == tyRange:
# consider: (range[0..3], range[0..4]) here. We should make that # consider: (range[0..3], range[0..4]) here. We should make that

View file

@ -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 # gnrc. params, then it won't be necessary to open a new scope here
openScope(c) openScope(c)
var lifted = liftParamType(c, skType, newNodeI(nkArgList, info), var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
t, ":anon", info) t, ":anon", info)
closeScope(c) closeScope(c)
if lifted != nil: t = lifted if lifted != nil: t = lifted
@ -429,7 +429,8 @@ proc changeType(n: PNode, newType: PType, check: bool) =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
changeType(n.sons[i], elemType(newType), check) changeType(n.sons[i], elemType(newType), check)
of nkPar: of nkPar:
if newType.kind != tyTuple: let tup = newType.skipTypes({tyGenericInst})
if tup.kind != tyTuple:
internalError(n.info, "changeType: no tuple type for constructor") internalError(n.info, "changeType: no tuple type for constructor")
else: else:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
@ -437,7 +438,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
if m.kind == nkExprColonExpr: if m.kind == nkExprColonExpr:
m = m.sons[1] m = m.sons[1]
n.sons[i] = m n.sons[i] = m
changeType(m, newType.sons[i], check) changeType(m, tup.sons[i], check)
of nkCharLit..nkUInt64Lit: of nkCharLit..nkUInt64Lit:
if check: if check:
let value = n.intVal let value = n.intVal
@ -925,18 +926,20 @@ const
proc readTypeParameter(c: PContext, typ: PType, proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode = paramName: PIdent, info: TLineInfo): PNode =
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias 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] let tbody = ty.sons[0]
for s in countup(0, tbody.len-2): for s in countup(0, tbody.len-2):
let tParam = tbody.sons[s] let tParam = tbody.sons[s]
if tParam.sym.name == paramName: if tParam.sym.name.id == paramName.id:
let rawTyp = ty.sons[s + 1] let rawTyp = ty.sons[s + 1]
if rawTyp.kind == tyStatic: if rawTyp.kind == tyStatic:
return rawTyp.n return rawTyp.n
else: else:
let foundTyp = makeTypeDesc(c, rawTyp) let foundTyp = makeTypeDesc(c, rawTyp)
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
#echo "came here: returned nil"
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if it's not a built-in field access ## returns nil if it's not a built-in field access
@ -963,6 +966,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
var ty = n.sons[0].typ var ty = n.sons[0].typ
var f: PSym = nil var f: PSym = nil
result = nil result = nil
if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone): if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
if ty.kind == tyTypeDesc: ty = ty.base if ty.kind == tyTypeDesc: ty = ty.base
ty = ty.skipTypes(tyDotOpTransparent) ty = ty.skipTypes(tyDotOpTransparent)
@ -983,7 +987,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
of tyTypeParamsHolders: of tyTypeParamsHolders:
return readTypeParameter(c, ty, i, n.info) return readTypeParameter(c, ty, i, n.info)
of tyObject, tyTuple: of tyObject, tyTuple:
if ty.n.kind == nkRecList: if ty.n != nil and ty.n.kind == nkRecList:
for field in ty.n: for field in ty.n:
if field.sym.name == i: if field.sym.name == i:
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ]) n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])

View file

@ -60,13 +60,20 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
else: else:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skGenericParam: 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) styleCheckUse(n.info, s)
of skParam: of skParam:
result = n result = n
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
of skType: 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) result = newSymNodeTypeDesc(s, n.info)
else: else:
result = n result = n

View file

@ -21,7 +21,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
var q = a.sym var q = a.sym
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses: if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
continue 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} s.flags = s.flags + {sfUsed, sfFromGeneric}
var t = PType(idTableGet(pt, q.typ)) var t = PType(idTableGet(pt, q.typ))
if t == nil: if t == nil:
@ -40,6 +41,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
t = generateTypeInstance(c, pt, a, t) t = generateTypeInstance(c, pt, a, t)
#t = ReplaceTypeVarsT(cl, t) #t = ReplaceTypeVarsT(cl, t)
s.typ = t s.typ = t
if t.kind == tyStatic: s.ast = t.n
addDecl(c, s) addDecl(c, s)
entry.concreteTypes[i] = t entry.concreteTypes[i] = t

View file

@ -654,6 +654,7 @@ proc checkForMetaFields(n: PNode) =
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
localError(n.info, errTIsNotAConcreteType, t.typeToString) localError(n.info, errTIsNotAConcreteType, t.typeToString)
if n.isNil: return
case n.kind case n.kind
of nkRecList, nkRecCase: of nkRecList, nkRecCase:
for s in n: checkForMetaFields(s) for s in n: checkForMetaFields(s)

View file

@ -214,44 +214,48 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
localError(n.info, errXExpectsOneTypeParam, "range") localError(n.info, errXExpectsOneTypeParam, "range")
result = newOrPrevType(tyError, prev, c) 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 = proc semArray(c: PContext, n: PNode, prev: PType): PType =
var indx, base: PType var base: PType
result = newOrPrevType(tyArray, prev, c) result = newOrPrevType(tyArray, prev, c)
if sonsLen(n) == 3: if sonsLen(n) == 3:
# 3 = length(array indx base) # 3 = length(array indx base)
if isRange(n[1]): indx = semRangeAux(c, n[1], nil) var indx = semArrayIndex(c, n[1])
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)
addSonSkipIntLit(result, indx) addSonSkipIntLit(result, indx)
if indx.kind == tyGenericInst: indx = lastSon(indx) if indx.kind == tyGenericInst: indx = lastSon(indx)
if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}: if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:

View file

@ -517,6 +517,16 @@ proc maybeSkipDistinct(t: PType, callee: PSym): PType =
else: else:
result = t 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 = proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
# typeRel can be used to establish various relationships between types: # 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 # bugfix: accept integer conversions here
#if result < isGeneric: result = isNone #if result < isGeneric: result = isNone
if result notin {isNone, isGeneric}: 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) result = typeRangeRel(f, a)
else: else:
if skipTypes(f, {tyRange}).kind == a.kind: if skipTypes(f, {tyRange}).kind == a.kind:
@ -964,6 +979,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyStatic: of tyStatic:
if aOrig.kind == tyStatic: if aOrig.kind == tyStatic:
result = typeRel(c, f.lastSon, a) 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) if result != isNone: put(c.bindings, f, aOrig)
else: else:
result = isNone result = isNone
@ -1006,15 +1024,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyFromExpr: of tyFromExpr:
# fix the expression, so it contains the already instantiated types # fix the expression, so it contains the already instantiated types
let instantiated = replaceTypesInBody(c.c, c.bindings, f.n) let reevaluated = tryResolvingStaticExpr(c, f.n)
let reevaluted = c.c.semExpr(c.c, instantiated) case reevaluated.typ.kind
case reevaluted.typ.kind
of tyTypeDesc: of tyTypeDesc:
result = typeRel(c, a, reevaluted.typ.base) result = typeRel(c, a, reevaluated.typ.base)
of tyStatic: of tyStatic:
result = typeRel(c, a, reevaluted.typ.base) result = typeRel(c, a, reevaluated.typ.base)
if result != isNone and reevaluted.typ.n != nil: if result != isNone and reevaluated.typ.n != nil:
if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n): if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
result = isNone result = isNone
else: else:
localError(f.n.info, errTypeExpected) localError(f.n.info, errTypeExpected)
@ -1083,6 +1100,11 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
arg: PNode): PNode = arg: PNode): PNode =
# arg.typ can be nil in 'suggest': # arg.typ can be nil in 'suggest':
if isNil(arg.typ): return nil if isNil(arg.typ): return nil
# sem'checking for 'echo' needs to be re-entrant:
# XXX we will revisit this issue after 0.10.2 is released
if f == arg.typ and arg.kind == nkHiddenStdConv: return arg
var call = newNodeI(nkCall, arg.info) var call = newNodeI(nkCall, arg.info)
call.add(f.n.copyTree) call.add(f.n.copyTree)
call.add(arg.copyTree) call.add(arg.copyTree)

View file

@ -74,9 +74,6 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) =
suggestWriteln(symToStr(s, isLocal=true, sectionSuggest)) suggestWriteln(symToStr(s, isLocal=true, sectionSuggest))
inc outputs inc outputs
when not defined(nimhygiene):
{.pragma: inject.}
template wholeSymTab(cond, section: expr) {.immediate.} = template wholeSymTab(cond, section: expr) {.immediate.} =
var isLocal = true var isLocal = true
for scope in walkScopes(c.currentScope): for scope in walkScopes(c.currentScope):

View file

@ -17,7 +17,7 @@ proc lastOrd*(t: PType): BiggestInt
proc lengthOrd*(t: PType): BiggestInt proc lengthOrd*(t: PType): BiggestInt
type type
TPreferedDesc* = enum TPreferedDesc* = enum
preferName, preferDesc, preferExported, preferModuleInfo preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
proc base*(t: PType): PType proc base*(t: PType): PType
@ -411,11 +411,13 @@ const
"UserTypeClassInst", "CompositeTypeClass", "UserTypeClassInst", "CompositeTypeClass",
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"] "and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string = proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
var t = typ var t = typ
result = "" result = ""
if t == nil: return 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: sfAnon notin t.sym.flags:
if t.kind == tyInt and isIntLit(t): if t.kind == tyInt and isIntLit(t):
return t.sym.name.s & " literal(" & $t.n.intVal & ")" 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: if not isIntLit(t) or prefer == preferExported:
result = typeToStr[t.kind] result = typeToStr[t.kind]
else: 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: of tyGenericBody, tyGenericInst, tyGenericInvokation:
result = typeToString(t.sons[0]) & '[' result = typeToString(t.sons[0]) & '['
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)): for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
if i > 1: add(result, ", ") if i > 1: add(result, ", ")
add(result, typeToString(t.sons[i])) add(result, typeToString(t.sons[i], preferGenericArg))
add(result, ']') add(result, ']')
of tyTypeDesc: of tyTypeDesc:
if t.base.kind == tyNone: result = "typedesc" if t.base.kind == tyNone: result = "typedesc"
else: result = "typedesc[" & typeToString(t.base) & "]" else: result = "typedesc[" & typeToString(t.base) & "]"
of tyStatic: of tyStatic:
internalAssert t.len > 0 internalAssert t.len > 0
result = "static[" & typeToString(t.sons[0]) & "]" if prefer == preferGenericArg and t.n != nil:
if t.n != nil: result.add "(" & renderTree(t.n) & ")" result = t.n.renderTree
else:
result = "static[" & typeToString(t.sons[0]) & "]"
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
of tyUserTypeClass: of tyUserTypeClass:
internalAssert t.sym != nil and t.sym.owner != nil internalAssert t.sym != nil and t.sym.owner != nil
return t.sym.owner.name.s return t.sym.owner.name.s

View file

@ -164,7 +164,8 @@ type
slotTempInt, # some temporary int slotTempInt, # some temporary int
slotTempFloat, # some temporary float slotTempFloat, # some temporary float
slotTempStr, # some temporary string slotTempStr, # some temporary string
slotTempComplex # some complex temporary (s.node field is used) slotTempComplex, # some complex temporary (s.node field is used)
slotTempPerm # slot is temporary but permanent (hack)
PProc* = ref object PProc* = ref object
blocks*: seq[TBlock] # blocks; temp data structure blocks*: seq[TBlock] # blocks; temp data structure

View file

@ -16,7 +16,7 @@
# types that use the 'node' field; the reason is that slots are # types that use the 'node' field; the reason is that slots are
# re-used in a register based VM. Example: # re-used in a register based VM. Example:
# #
# .. code-block:: nimrod # .. code-block:: nim
# let s = a & b # no matter what, create fresh node # let s = a & b # no matter what, create fresh node
# s = a & b # no matter what, keep the node # s = a & b # no matter what, keep the node
# #
@ -58,6 +58,7 @@ proc codeListing(c: PCtx, result: var string, start=0; last = -1) =
if i in jumpTargets: result.addf("L$1:\n", i) if i in jumpTargets: result.addf("L$1:\n", i)
let x = c.code[i] let x = c.code[i]
result.add($i)
let opc = opcode(x) let opc = opcode(x)
if opc in {opcConv, opcCast}: if opc in {opcConv, opcCast}:
let y = c.code[i+1] let y = c.code[i+1]
@ -188,7 +189,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
proc freeTemp(c: PCtx; r: TRegister) = proc freeTemp(c: PCtx; r: TRegister) =
let c = c.prc let c = c.prc
if c.slots[r].kind >= slotSomeTemp: c.slots[r].inUse = false if c.slots[r].kind in {slotSomeTemp..slotTempComplex}: c.slots[r].inUse = false
proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister = proc getTempRange(c: PCtx; n: int; kind: TSlotKind): TRegister =
# if register pressure is high, we re-use more aggressively: # if register pressure is high, we re-use more aggressively:
@ -1074,8 +1075,10 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
c.gABC(n, opcNodeToReg, dest, dest) c.gABC(n, opcNodeToReg, dest, dest)
elif c.prc.slots[tmp].kind >= slotTempUnknown: elif c.prc.slots[tmp].kind >= slotTempUnknown:
gABC(c, n, opcAddrNode, dest, tmp) gABC(c, n, opcAddrNode, dest, tmp)
# XXX this can still be wrong sometimes; hopefully it's only generated # hack ahead; in order to fix bug #1781 we mark the temporary as
# in call contexts, where it is safe # permanent, so that it's not used for anything else:
c.prc.slots[tmp].kind = slotTempPerm
# XXX this is still a hack
#message(n.info, warnUser, "suspicious opcode used") #message(n.info, warnUser, "suspicious opcode used")
else: else:
gABC(c, n, opcAddrReg, dest, tmp) gABC(c, n, opcAddrReg, dest, tmp)

View file

@ -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. Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.

View file

@ -456,11 +456,7 @@ can then attach a GC to this thread via
.. code-block:: nim .. code-block:: nim
setStackBottom(addr(someLocal)) system.setupForeignThreadGc()
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.
It is **not** safe to disable the garbage collector and enable it after the 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 call from your background thread even if the code you are calling is short

View file

@ -154,8 +154,8 @@ Generic Operating System Services
* `streams <streams.html>`_ * `streams <streams.html>`_
This module provides a stream interface and two implementations thereof: This module provides a stream interface and two implementations thereof:
the `PFileStream` and the `PStringStream` which implement the stream the `FileStream` and the `StringStream` which implement the stream
interface for Nim file objects (`TFile`) and strings. Other modules interface for Nim file objects (`File`) and strings. Other modules
may provide other implementations for this standard stream interface. may provide other implementations for this standard stream interface.
* `marshal <marshal.html>`_ * `marshal <marshal.html>`_

View file

@ -550,58 +550,6 @@ in C/C++).
**Note**: This pragma will not exist for the LLVM backend. **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 DynlibOverride
============== ==============

View file

@ -139,7 +139,7 @@ Numbers
Numerical literals are written as in most other languages. As a special twist, Numerical literals are written as in most other languages. As a special twist,
underscores are allowed for better readability: ``1_000_000`` (one million). 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: 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 binary literals with ``0b`` and octal literals with ``0o``. A leading zero
alone does not produce an octal. alone does not produce an octal.

View file

@ -56,7 +56,7 @@ Objects have access to their type at runtime. There is an
.. code-block:: nim .. code-block:: nim
type type
TPerson = object of TObject TPerson = object of RootObj
name*: string # the * means that `name` is accessible from other modules name*: string # the * means that `name` is accessible from other modules
age: int # no * means that the field is hidden 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. section.
Inheritance is done with the ``object of`` syntax. Multiple inheritance is 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 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 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.) in the GTK wrapper for instance.)
@ -228,7 +228,7 @@ is needed:
.. code-block:: nim .. code-block:: nim
type type
TSocket* = object of TObject TSocket* = object of RootObj
FHost: int # cannot be accessed from the outside of the module FHost: int # cannot be accessed from the outside of the module
# the `F` prefix is a convention to avoid clashes since # the `F` prefix is a convention to avoid clashes since
# the accessors are named `host` # the accessors are named `host`
@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
.. code-block:: nim .. code-block:: nim
type 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 PLiteral = ref object of PExpr
x: int x: int
PPlusExpr = ref object of PExpr PPlusExpr = ref object of PExpr
@ -313,7 +313,7 @@ dispatching:
.. code-block:: nim .. code-block:: nim
type type
TThing = object of TObject TThing = object of RootObj
TUnit = object of TThing TUnit = object of TThing
x: int x: int

View file

@ -94,13 +94,13 @@ const
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
proc csource(args: string) = 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()]) [args, VersionAsString, compileNimInst, findNim()])
proc zip(args: string) = 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()]) [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]) ["tools/niminst/niminst".exe, VersionAsString])
proc buildTool(toolname, args: string) = proc buildTool(toolname, args: string) =
@ -114,11 +114,11 @@ proc nsis(args: string) =
# produce 'nimrod_debug.exe': # produce 'nimrod_debug.exe':
exec "nim c compiler" / "nim.nim" exec "nim c compiler" / "nim.nim"
copyExe("compiler/nim".exe, "bin/nim_debug".exe) copyExe("compiler/nim".exe, "bin/nim_debug".exe)
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" & exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" &
" nsis compiler/nim") % VersionAsString) " nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)])
proc install(args: string) = 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]) [findNim(), compileNimInst, VersionAsString])
exec("sh ./install.sh $#" % args) exec("sh ./install.sh $#" % args)

View file

@ -649,6 +649,8 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
result = $node.basename.ident & "*" result = $node.basename.ident & "*"
of nnkStrLit..nnkTripleStrLit: of nnkStrLit..nnkTripleStrLit:
result = node.strVal result = node.strVal
of nnkSym:
result = $node.symbol
else: else:
badNodeKind node.kind, "$" badNodeKind node.kind, "$"

View file

@ -35,7 +35,15 @@ proc getSystemVersion*(): string =
elif $unix_info.sysname == "Darwin": elif $unix_info.sysname == "Darwin":
# Darwin # Darwin
result.add("Mac OS X ") 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") result.add("v10.6 Snow Leopard")
elif "9" in $unix_info.release: elif "9" in $unix_info.release:
result.add("v10.5 Leopard") result.add("v10.5 Leopard")

View file

@ -245,6 +245,14 @@ proc `$`*(osvi: TVersionInfo): string =
if osvi.ProductType == VER_NT_WORKSTATION: if osvi.ProductType == VER_NT_WORKSTATION:
result.add("Windows 7 ") result.add("Windows 7 ")
else: result.add("Windows Server 2008 R2 ") 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) var dwType = getProductInfo(osvi.majorVersion, osvi.minorVersion, 0, 0)
case dwType case dwType

View file

@ -1570,9 +1570,9 @@ else:
when defined(macosx): when defined(macosx):
# We can't use the NOSIGNAL flag in the ``send`` function, it has no effect
var var
MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint MSG_NOSIGNAL* = 0'i32
MSG_NOSIGNAL* = MSG_HAVEMORE
else: else:
var var
MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint

View file

@ -17,6 +17,8 @@
## as the response body. ## as the response body.
## ##
## .. code-block::nim ## .. code-block::nim
## import asynchttpserver, asyncdispatch
##
## var server = newAsyncHttpServer() ## var server = newAsyncHttpServer()
## proc cb(req: Request) {.async.} = ## proc cb(req: Request) {.async.} =
## await req.respond(Http200, "Hello World") ## await req.respond(Http200, "Hello World")

View file

@ -1433,7 +1433,7 @@ proc eat(p: var PegParser, kind: TTokKind) =
if p.tok.kind == kind: getTok(p) if p.tok.kind == kind: getTok(p)
else: pegError(p, tokKindToStr[kind] & " expected") else: pegError(p, tokKindToStr[kind] & " expected")
proc parseExpr(p: var PegParser): Peg proc parseExpr(p: var PegParser): Peg {.gcsafe.}
proc getNonTerminal(p: var PegParser, name: string): NonTerminal = proc getNonTerminal(p: var PegParser, name: string): NonTerminal =
for i in 0..high(p.nonterms): for i in 0..high(p.nonterms):

View file

@ -428,6 +428,10 @@ proc selectWrite*(writefds: var seq[SocketHandle],
pruneSocketSet(writefds, (wr)) pruneSocketSet(writefds, (wr))
# We ignore signal SIGPIPE on Darwin
when defined(macosx):
signal(SIGPIPE, SIG_IGN)
when defined(Windows): when defined(Windows):
var wsa: WSAData var wsa: WSAData
if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError()) if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())

View file

@ -97,7 +97,9 @@ proc checkpoint*(msg: string) =
template fail* = template fail* =
bind checkpoints bind checkpoints
for msg in items(checkpoints): for msg in items(checkpoints):
echo msg # this used to be 'echo' which now breaks due to a bug. XXX will revisit
# this issue later.
stdout.writeln msg
when not defined(ECMAScript): when not defined(ECMAScript):
if abortOnError: quit(1) if abortOnError: quit(1)

View file

@ -1516,7 +1516,7 @@ const
NimMinor*: int = 10 NimMinor*: int = 10
## is the minor number of Nim's version. ## is the minor number of Nim's version.
NimPatch*: int = 1 NimPatch*: int = 3
## is the patch number of Nim's version. ## is the patch number of Nim's version.
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch

View file

@ -233,8 +233,9 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
var q = cast[PRawChannel](addr(c)) var q = cast[PRawChannel](addr(c))
if q.mask != ChannelDeadMask: if q.mask != ChannelDeadMask:
if tryAcquireSys(q.lock): if tryAcquireSys(q.lock):
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) if q.count > 0:
result.dataAvailable = true llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
result.dataAvailable = true
releaseSys(q.lock) releaseSys(q.lock)
proc peek*[TMsg](c: var TChannel[TMsg]): int = proc peek*[TMsg](c: var TChannel[TMsg]): int =

View file

@ -296,7 +296,7 @@ when not defined(noSignalHandler):
template processSignal(s, action: expr) {.immediate, dirty.} = template processSignal(s, action: expr) {.immediate, dirty.} =
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n") if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
elif s == SIGSEGV: elif s == SIGSEGV:
action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n") action("SIGSEGV: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
elif s == SIGABRT: elif s == SIGABRT:
when defined(endb): when defined(endb):
if dbgAborting: return # the debugger wants to abort if dbgAborting: return # the debugger wants to abort
@ -304,7 +304,7 @@ when not defined(noSignalHandler):
elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n") elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
elif s == SIGILL: action("SIGILL: Illegal operation.\n") elif s == SIGILL: action("SIGILL: Illegal operation.\n")
elif s == SIGBUS: elif s == SIGBUS:
action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n") action("SIGBUS: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
else: else:
block platformSpecificSignal: block platformSpecificSignal:
when declared(SIGPIPE): when declared(SIGPIPE):

View file

@ -368,32 +368,32 @@ type
{.deprecated: [TSocketHandle: SocketHandle].} {.deprecated: [TSocketHandle: SocketHandle].}
type type
WSAData* {.importc: "WSADATA", header: "Winsock2.h".} = object WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object
wVersion, wHighVersion: int16 wVersion, wHighVersion: int16
szDescription: array[0..WSADESCRIPTION_LEN, char] szDescription: array[0..WSADESCRIPTION_LEN, char]
szSystemStatus: array[0..WSASYS_STATUS_LEN, char] szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
iMaxSockets, iMaxUdpDg: int16 iMaxSockets, iMaxUdpDg: int16
lpVendorInfo: cstring lpVendorInfo: cstring
SockAddr* {.importc: "SOCKADDR", header: "Winsock2.h".} = object SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object
sa_family*: int16 # unsigned sa_family*: int16 # unsigned
sa_data: array[0..13, char] 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 s_addr*: int32 # IP address
Sockaddr_in* {.importc: "SOCKADDR_IN", Sockaddr_in* {.importc: "SOCKADDR_IN",
header: "Winsock2.h".} = object header: "winsock2.h".} = object
sin_family*: int16 sin_family*: int16
sin_port*: int16 # unsigned sin_port*: int16 # unsigned
sin_addr*: InAddr sin_addr*: InAddr
sin_zero*: array[0..7, char] 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] bytes*: array[0..15, char]
Sockaddr_in6* {.importc: "SOCKADDR_IN6", Sockaddr_in6* {.importc: "SOCKADDR_IN6",
header: "Winsock2.h".} = object header: "winsock2.h".} = object
sin6_family*: int16 sin6_family*: int16
sin6_port*: int16 # unsigned sin6_port*: int16 # unsigned
sin6_flowinfo*: int32 # unsigned sin6_flowinfo*: int32 # unsigned
@ -450,22 +450,22 @@ type
var var
SOMAXCONN* {.importc, header: "Winsock2.h".}: cint SOMAXCONN* {.importc, header: "winsock2.h".}: cint
INVALID_SOCKET* {.importc, header: "Winsock2.h".}: SocketHandle INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle
SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint SOL_SOCKET* {.importc, header: "winsock2.h".}: cint
SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording
SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen() SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen()
SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse
SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive
SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses
SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs
SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible 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_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_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line
SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint
SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse
SO_ERROR* {.importc, header: "Winsock2.h".}: cint SO_ERROR* {.importc, header: "winsock2.h".}: cint
proc `==`*(x, y: SocketHandle): bool {.borrow.} proc `==`*(x, y: SocketHandle): bool {.borrow.}

View file

@ -280,9 +280,18 @@ when not useWinVersion:
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl, proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl,
dynlib: DLLUtilName, importc.} dynlib: DLLUtilName, importc.}
proc allocWrapper(size: int): pointer {.cdecl.} = alloc(size)
proc reallocWrapper(p: pointer; newsize: int): pointer {.cdecl.} =
if p == nil:
if newSize > 0: result = alloc(newsize)
elif newsize == 0: dealloc(p)
else: result = realloc(p, newsize)
proc deallocWrapper(p: pointer) {.cdecl.} =
if p != nil: dealloc(p)
proc CRYPTO_malloc_init*() = proc CRYPTO_malloc_init*() =
when not useWinVersion: when not useWinVersion:
CRYPTO_set_mem_functions(alloc, realloc, dealloc) CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cInt, larg: int, parg: pointer): int{. proc SSL_CTX_ctrl*(ctx: SslCtx, cmd: cInt, larg: int, parg: pointer): int{.
cdecl, dynlib: DLLSSLName, importc.} cdecl, dynlib: DLLSSLName, importc.}

26
tests/generics/t1056.nim Normal file
View file

@ -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

44
tests/generics/t1789.nim Normal file
View file

@ -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]

View file

@ -12,7 +12,7 @@ type
(x < y) is bool (x < y) is bool
ObjectContainer = generic C ObjectContainer = generic C
C.len is ordinal C.len is Ordinal
for v in items(C): for v in items(C):
v.type is tuple|object v.type is tuple|object

View file

@ -2,10 +2,11 @@
proc p(a, b: int, c: proc ()) = proc p(a, b: int, c: proc ()) =
c() c()
when false:
p(1, 3): # language spec changed:
echo 1 p(1, 3):
echo 3 echo 1
echo 3
p(1, 1, proc() = p(1, 1, proc() =
echo 1 echo 1

View file

@ -1,6 +1,7 @@
discard """ discard """
line: 12 line: 12
errormsg: "instantiate 'notConcrete' explicitly" errormsg: "instantiate 'notConcrete' explicitly"
disabled: "true"
""" """
proc wrap[T]() = proc wrap[T]() =

View file

@ -62,3 +62,7 @@ when false:
block: block:
var a, b: Bar[int, 0..2] var a, b: Bar[int, 0..2]
discard foo(a, b) discard foo(a, b)
# bug #1788
echo "hello" & char(ord(' ')) & "world"

View file

@ -58,7 +58,7 @@ proc TestLoops() =
break break
break break
while True: while true:
break break
@ -73,7 +73,7 @@ proc main() =
res: int res: int
s: string s: string
#write(stdout, mymax(23, 45)) #write(stdout, mymax(23, 45))
write(stdout, "Hallo! Wie heißt du? ") write(stdout, "Hallo! Wie heisst du? ")
s = readLine(stdin) s = readLine(stdin)
# test the case statement # test the case statement
case s case s

View file

@ -1,3 +0,0 @@
import strutils
echo ParseFloat("5000") / ParseFloat("10")

View file

@ -397,7 +397,7 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string =
elif c in reserved: result = '\\' & c elif c in reserved: result = '\\' & c
else: result = $c else: result = $c
proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'" proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
proc singleQuoteEsc(str: string): string = proc singleQuoteEsc(str: string): string =
result = "'" result = "'"
@ -421,11 +421,11 @@ proc charSetEscAux(cc: set[char]): string =
c1 = c2 c1 = c2
inc(c1) inc(c1)
proc CharSetEsc(cc: set[char]): string = proc charSetEsc(cc: set[char]): string =
if card(cc) >= 128+64: if card(cc) >= 128+64:
result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']' result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
else: else:
result = '[' & CharSetEscAux(cc) & ']' result = '[' & charSetEscAux(cc) & ']'
proc toStrAux(r: TPeg, res: var string) = proc toStrAux(r: TPeg, res: var string) =
case r.kind case r.kind
@ -522,12 +522,12 @@ proc `$` *(r: TPeg): string {.rtl, extern: "npegsToString".} =
type type
TCaptures* {.final.} = object ## contains the captured substrings. TCaptures* {.final.} = object ## contains the captured substrings.
matches: array[0..maxSubpatterns-1, tuple[first, last: int]] matches: array[0..MaxSubpatterns-1, tuple[first, last: int]]
ml: int ml: int
origStart: int origStart: int
proc bounds*(c: TCaptures, proc bounds*(c: TCaptures,
i: range[0..maxSubpatterns-1]): tuple[first, last: int] = i: range[0..MaxSubpatterns-1]): tuple[first, last: int] =
## returns the bounds ``[first..last]`` of the `i`'th capture. ## returns the bounds ``[first..last]`` of the `i`'th capture.
result = c.matches[i] result = c.matches[i]
@ -695,7 +695,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
while start+result < s.len: while start+result < s.len:
var x = rawMatch(s, p.sons[0], start+result, c) var x = rawMatch(s, p.sons[0], start+result, c)
if x >= 0: if x >= 0:
if idx < maxSubpatterns: if idx < MaxSubpatterns:
c.matches[idx] = (start, start+result-1) c.matches[idx] = (start, start+result-1)
#else: silently ignore the capture #else: silently ignore the capture
inc(result, x) inc(result, x)
@ -739,7 +739,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
inc(c.ml) inc(c.ml)
result = rawMatch(s, p.sons[0], start, c) result = rawMatch(s, p.sons[0], start, c)
if result >= 0: if result >= 0:
if idx < maxSubpatterns: if idx < MaxSubpatterns:
c.matches[idx] = (start, start+result-1) c.matches[idx] = (start, start+result-1)
#else: silently ignore the capture #else: silently ignore the capture
else: else:
@ -836,7 +836,7 @@ iterator findAll*(s: string, pattern: TPeg, start = 0): string =
while i < s.len: while i < s.len:
var L = matchLen(s, pattern, matches, i) var L = matchLen(s, pattern, matches, i)
if L < 0: break if L < 0: break
for k in 0..maxSubPatterns-1: for k in 0..MaxSubPatterns-1:
if isNil(matches[k]): break if isNil(matches[k]): break
yield matches[k] yield matches[k]
inc(i, L) inc(i, L)
@ -866,7 +866,7 @@ template `=~`*(s: string, pattern: TPeg): expr =
## echo("syntax error") ## echo("syntax error")
## ##
when not definedInScope(matches): when not definedInScope(matches):
var matches {.inject.}: array[0..maxSubpatterns-1, string] var matches {.inject.}: array[0..MaxSubpatterns-1, string]
match(s, pattern, matches) match(s, pattern, matches)
# ------------------------- more string handling ------------------------------ # ------------------------- more string handling ------------------------------
@ -907,7 +907,7 @@ proc replacef*(s: string, sub: TPeg, by: string): string {.
## "var1<-keykey; val2<-key2key2" ## "var1<-keykey; val2<-key2key2"
result = "" result = ""
var i = 0 var i = 0
var caps: array[0..maxSubpatterns-1, string] var caps: array[0..MaxSubpatterns-1, string]
while i < s.len: while i < s.len:
var x = matchLen(s, sub, caps, i) var x = matchLen(s, sub, caps, i)
if x <= 0: if x <= 0:
@ -924,7 +924,7 @@ proc replace*(s: string, sub: TPeg, by = ""): string {.
## in `by`. ## in `by`.
result = "" result = ""
var i = 0 var i = 0
var caps: array[0..maxSubpatterns-1, string] var caps: array[0..MaxSubpatterns-1, string]
while i < s.len: while i < s.len:
var x = matchLen(s, sub, caps, i) var x = matchLen(s, sub, caps, i)
if x <= 0: if x <= 0:
@ -942,7 +942,7 @@ proc parallelReplace*(s: string, subs: varargs[
## applied in parallel. ## applied in parallel.
result = "" result = ""
var i = 0 var i = 0
var caps: array[0..maxSubpatterns-1, string] var caps: array[0..MaxSubpatterns-1, string]
while i < s.len: while i < s.len:
block searchSubs: block searchSubs:
for j in 0..high(subs): for j in 0..high(subs):
@ -1055,7 +1055,7 @@ type
TPegLexer {.inheritable.} = object ## the lexer object. TPegLexer {.inheritable.} = object ## the lexer object.
bufpos: int ## the current position within the buffer bufpos: int ## the current position within the buffer
buf: cstring ## the buffer itself buf: cstring ## the buffer itself
LineNumber: int ## the current line number lineNumber: int ## the current line number
lineStart: int ## index of last line start in buffer lineStart: int ## index of last line start in buffer
colOffset: int ## column to add colOffset: int ## column to add
filename: string filename: string
@ -1118,38 +1118,38 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
case c.buf[c.bufpos] case c.buf[c.bufpos]
of 'r', 'R', 'c', 'C': of 'r', 'R', 'c', 'C':
add(tok.literal, '\c') add(tok.literal, '\c')
Inc(c.bufpos) inc(c.bufpos)
of 'l', 'L': of 'l', 'L':
add(tok.literal, '\L') add(tok.literal, '\L')
Inc(c.bufpos) inc(c.bufpos)
of 'f', 'F': of 'f', 'F':
add(tok.literal, '\f') add(tok.literal, '\f')
inc(c.bufpos) inc(c.bufpos)
of 'e', 'E': of 'e', 'E':
add(tok.literal, '\e') add(tok.literal, '\e')
Inc(c.bufpos) inc(c.bufpos)
of 'a', 'A': of 'a', 'A':
add(tok.literal, '\a') add(tok.literal, '\a')
Inc(c.bufpos) inc(c.bufpos)
of 'b', 'B': of 'b', 'B':
add(tok.literal, '\b') add(tok.literal, '\b')
Inc(c.bufpos) inc(c.bufpos)
of 'v', 'V': of 'v', 'V':
add(tok.literal, '\v') add(tok.literal, '\v')
Inc(c.bufpos) inc(c.bufpos)
of 't', 'T': of 't', 'T':
add(tok.literal, '\t') add(tok.literal, '\t')
Inc(c.bufpos) inc(c.bufpos)
of 'x', 'X': of 'x', 'X':
inc(c.bufpos) inc(c.bufpos)
var xi = 0 var xi = 0
handleHexChar(c, xi) handleHexChar(c, xi)
handleHexChar(c, xi) handleHexChar(c, xi)
if xi == 0: tok.kind = tkInvalid if xi == 0: tok.kind = tkInvalid
else: add(tok.literal, Chr(xi)) else: add(tok.literal, chr(xi))
of '0'..'9': of '0'..'9':
var val = ord(c.buf[c.bufpos]) - ord('0') var val = ord(c.buf[c.bufpos]) - ord('0')
Inc(c.bufpos) inc(c.bufpos)
var i = 1 var i = 1
while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
val = val * 10 + ord(c.buf[c.bufpos]) - ord('0') val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
@ -1159,11 +1159,11 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
else: tok.kind = tkInvalid else: tok.kind = tkInvalid
of '\0'..'\31': of '\0'..'\31':
tok.kind = tkInvalid tok.kind = tkInvalid
elif c.buf[c.bufpos] in strutils.letters: elif c.buf[c.bufpos] in strutils.Letters:
tok.kind = tkInvalid tok.kind = tkInvalid
else: else:
add(tok.literal, c.buf[c.bufpos]) add(tok.literal, c.buf[c.bufpos])
Inc(c.bufpos) inc(c.bufpos)
proc skip(c: var TPegLexer) = proc skip(c: var TPegLexer) =
var pos = c.bufpos var pos = c.bufpos
@ -1171,7 +1171,7 @@ proc skip(c: var TPegLexer) =
while true: while true:
case buf[pos] case buf[pos]
of ' ', '\t': of ' ', '\t':
Inc(pos) inc(pos)
of '#': of '#':
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos) while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
of '\c': of '\c':
@ -1203,7 +1203,7 @@ proc getString(c: var TPegLexer, tok: var TToken) =
break break
else: else:
add(tok.literal, buf[pos]) add(tok.literal, buf[pos])
Inc(pos) inc(pos)
c.bufpos = pos c.bufpos = pos
proc getDollar(c: var TPegLexer, tok: var TToken) = proc getDollar(c: var TPegLexer, tok: var TToken) =
@ -1244,7 +1244,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
break break
else: else:
ch = buf[pos] ch = buf[pos]
Inc(pos) inc(pos)
incl(tok.charset, ch) incl(tok.charset, ch)
if buf[pos] == '-': if buf[pos] == '-':
if buf[pos+1] == ']': if buf[pos+1] == ']':
@ -1264,7 +1264,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
break break
else: else:
ch2 = buf[pos] ch2 = buf[pos]
Inc(pos) inc(pos)
for i in ord(ch)+1 .. ord(ch2): for i in ord(ch)+1 .. ord(ch2):
incl(tok.charset, chr(i)) incl(tok.charset, chr(i))
c.bufpos = pos c.bufpos = pos
@ -1275,7 +1275,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) =
var buf = c.buf var buf = c.buf
while true: while true:
add(tok.literal, buf[pos]) add(tok.literal, buf[pos])
Inc(pos) inc(pos)
if buf[pos] notin strutils.IdentChars: break if buf[pos] notin strutils.IdentChars: break
c.bufpos = pos c.bufpos = pos
tok.kind = tkIdentifier tok.kind = tkIdentifier
@ -1312,11 +1312,11 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
getCharset(c, tok) getCharset(c, tok)
of '(': of '(':
tok.kind = tkParLe tok.kind = tkParLe
Inc(c.bufpos) inc(c.bufpos)
add(tok.literal, '(') add(tok.literal, '(')
of ')': of ')':
tok.kind = tkParRi tok.kind = tkParRi
Inc(c.bufpos) inc(c.bufpos)
add(tok.literal, ')') add(tok.literal, ')')
of '.': of '.':
tok.kind = tkAny tok.kind = tkAny

View file

@ -1,12 +0,0 @@
import sockets, os
var s: TSocket
s = socket()
if s == InvalidSocket: osError(osLastError())
s.connect("www.google.com", TPort(80))
var data: string = ""
s.readLine(data)
echo(data)

View file

@ -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)

View file

@ -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.)

View file

@ -0,0 +1,26 @@
discard """
output: "1"
"""
# bug #1708
let foo = {
"1" : (bar: @["1"]),
"2" : (baz: @[])
}
# bug #871
when true:
import os
type
In_out = tuple[src, dest, options: string]
let
nil_var: In_out = ("hey"/"there", "something", nil)
#nil_var2 = ("hey"/"there", "something", nil)
# bug #1721
const foo2: seq[string] = @[]
echo foo[0][0][0]

View file

@ -34,3 +34,20 @@ type
yes s.items is Iter[TNumber] yes s.items is Iter[TNumber]
no s.items is Iter[float] 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]

View file

@ -0,0 +1,17 @@
discard """
output: "56"
"""
# bug #1781
proc initCombinations: array[11, array[11, int]] =
result[0] = [1,2,3,4,5,6,7,8,9,10,11]
result[1][1 .. 10] = [12,13,14,15,16,17,18,19,20,21]
result[2][2 .. 10] = [22,23,24,25,26,27,28,29,30]
result[3][3 .. 10] = [31,32,33,34,35,36,37,38]
result[4][4 .. 10] = [39,40,41,42,43,44,45]
result[5][5 .. 10] = [46,47,48,49,50,51]
result[6][6 .. 10] = [52,53,54,55,56]
const combinations = initCombinations()
echo combinations[6][10]

View file

@ -32,7 +32,7 @@ proc buildSuiteContents(suiteName, suiteDesc, suiteBloc: PNimrodNode): tuple[tes
testObj.testDesc = nil testObj.testDesc = nil
else: else:
testObj.testDesc = child[2].strVal testObj.testDesc = child[2].strVal
testObj.testBlock = child[3][6] testObj.testBlock = child[1]
tests.add(testObj) tests.add(testObj)

View file

@ -522,8 +522,8 @@ proc setupDist2(c: var TConfigData) =
# ------------------ generate ZIP file --------------------------------------- # ------------------ generate ZIP file ---------------------------------------
when haveZipLib: when haveZipLib:
proc zipDist(c: var TConfigData) = proc zipDist(c: var TConfigData) =
var proj = toLower(c.name) var proj = toLower(c.name) & "-" & c.version
var n = "$#_$#.zip" % [proj, c.version] var n = "$#.zip" % proj
if c.outdir.len == 0: n = "build" / n if c.outdir.len == 0: n = "build" / n
else: n = c.outdir / n else: n = c.outdir / n
var z: TZipArchive var z: TZipArchive

View file

@ -47,7 +47,7 @@ proc initConfigData(c: var TConfigData) =
c.logo = "" c.logo = ""
c.ticker = "" c.ticker = ""
c.vars = newStringTable(modeStyleInsensitive) c.vars = newStringTable(modeStyleInsensitive)
c.gitRepo = "https://github.com/Araq/Nimrod/tree" c.gitRepo = "https://github.com/Araq/Nim/tree"
c.gitCommit = "master" c.gitCommit = "master"
c.numProcessors = countProcessors() c.numProcessors = countProcessors()
# Attempts to obtain the git current commit. # Attempts to obtain the git current commit.
@ -262,24 +262,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
exec("nim doc2 $# -o:$# $#" % exec("nim doc2 $# -o:$# $#" %
[c.nimArgs, destPath / "docgen_sample2.html", src]) [c.nimArgs, destPath / "docgen_sample2.html", src])
proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
proc buildDoc(c: var TConfigData, destPath: string) = proc buildDoc(c: var TConfigData, destPath: string) =
# call nim for the documentation: # call nim for the documentation:
var var
commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2)) commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
i = 0 i = 0
for d in items(c.doc): for d in items(c.doc):
commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" % commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
[c.nimArgs, c.gitRepo, c.gitCommit, [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
destPath / changeFileExt(splitFile(d).name, "html"), d] destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc i.inc
for d in items(c.srcdoc): for d in items(c.srcdoc):
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" % commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
[c.nimArgs, c.gitRepo, c.gitCommit, [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
destPath / changeFileExt(splitFile(d).name, "html"), d] destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc i.inc
for d in items(c.srcdoc2): for d in items(c.srcdoc2):
commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" % commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
[c.nimArgs, c.gitRepo, c.gitCommit, [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
destPath / changeFileExt(splitFile(d).name, "html"), d] destPath / changeFileExt(splitFile(d).name, "html"), d]
i.inc i.inc
@ -311,8 +313,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
# build additional documentation (without the index): # build additional documentation (without the index):
var commands = newSeq[string](c.webdoc.len) var commands = newSeq[string](c.webdoc.len)
for i, doc in pairs(c.webdoc): for i, doc in pairs(c.webdoc):
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# $#" % commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# $#" %
[c.nimArgs, c.gitRepo, c.gitCommit, [c.nimArgs, c.gitRepo, c.gitCommit, doc.pathPart,
destPath / changeFileExt(splitFile(doc).name, "html"), doc] destPath / changeFileExt(splitFile(doc).name, "html"), doc]
mexec(commands, c.numProcessors) mexec(commands, c.numProcessors)

View file

@ -63,7 +63,7 @@
<span class="tab end"> </span>count += <span class="val">1</span> <span class="tab end"> </span>count += <span class="val">1</span>
echo(<span class="val">"Average line length: "</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 &gt; <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
</pre> </pre>
</div> </div>
<div> <div>

View file

@ -1,6 +1,6 @@
You can download the latest version of the Nimrod compiler here. You can download the latest version of the Nim compiler here.
**Note:** The Nimrod compiler requires a C compiler to compile software. On **Note:** The Nim compiler requires a C compiler to compile software. On
Windows we recommend that you use Windows we recommend that you use
`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux `Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
and clang on Mac OS X. and clang on Mac OS X.
@ -10,9 +10,8 @@ Binaries
======== ========
Unfortunately for now we only provide builds for Windows. Unfortunately for now we only provide builds for Windows.
* 32 bit: `nim-0.10.2_x32.exe <download/nim-0.10.2_x32.exe>`_
* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_ * 64 bit: `nim-0.10.2_x64.exe <download/nim-0.10.2_x64.exe>`_
* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
Installation based on generated C code Installation based on generated C code
@ -22,13 +21,13 @@ This installation method is the preferred way for Linux, Mac OS X, and other Uni
like systems. Binary packages may be provided later. like systems. Binary packages may be provided later.
Download `nimrod_0.9.6.zip <download/nimrod_0.9.6.zip>`_, extract it and follow Download `nim-0.10.2.zip <download/nim-0.10.2.zip>`_, extract it and follow
these instructions: these instructions:
* sh build.sh * sh build.sh
* Add ``$your_install_dir/bin`` to your PATH. * Add ``$your_install_dir/bin`` to your PATH.
There are other ways to install Nimrod (like using the ``install.sh`` script), There are other ways to install Nim (like using the ``install.sh`` script),
but these tend to cause more problems. but these tend to cause more problems.

View file

@ -2,195 +2,200 @@
News News
==== ====
.. 2014-12-29 Version 0.10.2 released
2014-10-21 Version 0.10.2 released ==================================
==================================
This release marks the completion of a very important change to the project: This release marks the completion of a very important change to the project:
the official renaming from Nimrod to Nim. Version 0.10.2 contains many language the official renaming from Nimrod to Nim. Version 0.10.2 contains many language
changes, some of which may break your existing code. For your convenience, we changes, some of which may break your existing code. For your convenience, we
added a new tool called `nimfix <nimfix.html>`_ that will help you convert your added a new tool called `nimfix <nimfix.html>`_ that will help you convert your
existing projects so that it works with the latest version of the compiler. existing projects so that it works with the latest version of the compiler.
Progress towards version 1.0 Progress towards version 1.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Although Nim is still pre-1.0, we were able to keep the number of breaking Although Nim is still pre-1.0, we were able to keep the number of breaking
changes to a minimum so far. Starting with version 1.0, we will not introduce changes to a minimum so far. Starting with version 1.0, we will not introduce
any breaking changes between major release versions. any breaking changes between major release versions.
One of Nim's goals is to ensure that the compiler is as efficient as possible. One of Nim's goals is to ensure that the compiler is as efficient as possible.
Take a look at the Take a look at the
`latest benchmarks <https://github.com/logicchains/LPATHBench/blob/master/writeup.md>`_, `latest benchmarks <https://github.com/logicchains/LPATHBench/blob/master/writeup.md>`_,
which show that Nim is consistently near which show that Nim is consistently near
the top and already nearly as fast as C and C++. Recent developments, such as the top and already nearly as fast as C and C++. Recent developments, such as
the new ``asyncdispatch`` module will allow you to write efficient web server the new ``asyncdispatch`` module will allow you to write efficient web server
applications using non-blocking code. Nim now also has a built-in thread pool applications using non-blocking code. Nim now also has a built-in thread pool
for lightweight threading through the use of ``spawn``. for lightweight threading through the use of ``spawn``.
The unpopular "T" and "P" prefixes on types have been deprecated. Nim also The unpopular "T" and "P" prefixes on types have been deprecated. Nim also
became more expressive by weakening the distinction between statements and became more expressive by weakening the distinction between statements and
epxressions. We also added new and searchable forums, a new website, and our 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
~~~~~~~~~~~~~~~~~~~~~~
The 1.0 release is actually very close. There are only a couple of last
things that need to be done:
* Implementing static[T] properly
* Support for the overloading of the assignment operator
Of course, the 1.0 release is not an end to the development of Nim.
It is very much the beginning and we will be fleshing out the then
stable language.
Nimble and other Nim tools
~~~~~~~~~~~~~~~~~~~~~~~~~~
Outside of the language and the compiler itself many Nim tools have seen
considerable improvements.
Babel the Nim package manager has been renamed to Nimble. Nimble's purpose
is the installation of packages containing libraries and/or applications
written in Nim.
Even though Nimble is still very young it already is very
functional. It can install packages by name, it does so by accessing a
packages repository which is hosted on a Github repo. Packages can also be
installed via a Git repo URL or Mercurial repo URL. The package repository
is searchable through Nimble. Anyone is free to add their own packages to
the package repository by forking the
`nim-lang/packages <https://github.com/nim-lang/packages>`_ repo and creating
a pull request. Nimble is fully cross-platform and should be fully functional
on all major operating systems.
It is of course completely written in Nim.
Changelog
~~~~~~~~~
Changes affecting backwards compatibility
-----------------------------------------
- **The language has been renamed from Nimrod to Nim.** The name of the
compiler changed from ``nimrod`` to ``nim`` too.
- ``system.fileHandle`` has been renamed to ``system.getFileHandle`` to
prevent name conflicts with the new type ``FileHandle``.
- Comments are now not part of the AST anymore, as such you cannot use them
in place of ``discard``.
- Large parts of the stdlib got rid of the T/P type prefixes. Instead most
types now simply start with an uppercased letter. The
so called "partial case sensitivity" rule is now active allowing for code
like ``var foo: Foo`` in more contexts.
- String case (or any non-ordinal case) statements
without 'else' are deprecated.
- Recursive tuple types are not allowed anymore. Use ``object`` instead.
- The PEGS module returns ``nil`` instead of ``""`` when an optional capture
fails to match.
- The re module returns ``nil`` instead of ``""`` when an optional capture
fails to match.
- The "symmetric set difference" operator (``-+-``) never worked and has been
removed.
- ``defer`` is a keyword now.
- ``func`` is a keyword now.
- The ``using`` language feature now needs to be activated via the new
``{.experimental.}`` pragma that enables experimental language features.
- Destructors are now officially *experimental*.
- Standalone ``except`` and ``finally`` statements are deprecated now.
The standalone ``finally`` can be replaced with ``defer``,
standalone ``except`` requires an explicit ``try``.
- Operators ending in ``>`` are considered as "arrow like" and have their
own priority level and are right associative. This means that
the ``=>`` and ``->`` operators from the `future <future.html>`_ module
work better.
- Field names in tuples are now ignored for type comparisons. This allows
for greater interoperability between different modules.
- Statement lists are not converted to an implicit ``do`` block anymore. This
means the confusing ``nnkDo`` nodes when working with macros are gone for
good.
Language Additions
------------------
- The new concurrency model has been implemented including ``locks`` sections, What's left to be done
lock levels and object field ``guards``. ~~~~~~~~~~~~~~~~~~~~~~
- The ``parallel`` statement has been implemented.
- ``deepCopy`` has been added to the language. The 1.0 release is actually very close. Apart from bug fixes, there are
- The builtin ``procCall`` can be used to get ``super``-like functionality two major features missing or incomplete:
for multi methods.
- There is a new pragma ``{.experimental.}`` that enables experimental * ``static[T]`` needs to be defined precisely and the bugs in the
language features per module, or you can enable this features on a global implementation need to be fixed.
level with the ``--experimental`` command line option. * Overloading of the assignment operator is required for some generic
containers and needs to be implemented.
This means that fancy matrix libraries will finally start to work, which used
to be a major point of pain in the language.
Compiler Additions Nimble and other Nim tools
------------------ ~~~~~~~~~~~~~~~~~~~~~~~~~~
- The compiler now supports *mixed* Objective C / C++ / C code generation: Outside of the language and the compiler itself many Nim tools have seen
The modules that use ``importCpp`` or ``importObjc`` are compiled to C++ considerable improvements.
or Objective C code, any other module is compiled to C code. This
improves interoperability.
- There is a new ``parallel`` statement for safe fork&join parallel computing.
- ``guard`` and ``lock`` pragmas have been implemented to support safer
concurrent programming.
- The following procs are now available at compile-time::
math.sqrt, math.ln, math.log10, math.log2, math.exp, math.round, Babel the Nim package manager has been renamed to Nimble. Nimble's purpose
math.arccos, math.arcsin, math.arctan, math.arctan2, math.cos, math.cosh, is the installation of packages containing libraries and/or applications
math.hypot, math.sinh, math.sin, math.tan, math.tanh, math.pow, written in Nim.
math.trunc, math.floor, math.ceil, math.fmod, Even though Nimble is still very young it already is very
os.getEnv, os.existsEnv, os.dirExists, os.fileExists, functional. It can install packages by name, it does so by accessing a
system.writeFile packages repository which is hosted on a Github repo. Packages can also be
installed via a Git repo URL or Mercurial repo URL. The package repository
is searchable through Nimble. Anyone is free to add their own packages to
the package repository by forking the
`nim-lang/packages <https://github.com/nim-lang/packages>`_ repo and creating
a pull request. Nimble is fully cross-platform and should be fully functional
on all major operating systems.
It is of course completely written in Nim.
- Two backticks now produce a single backtick within an ``emit`` or ``asm`` Changelog
statement. ~~~~~~~~~
- There is a new tool, `nimfix <nimfix.html>`_ to help you in updating your
code from Nimrod to Nim.
- The compiler's output has been prettified.
Library Additions Changes affecting backwards compatibility
----------------- -----------------------------------------
- Added module ``fenv`` to control the handling of floating-point rounding and - **The language has been renamed from Nimrod to Nim.** The name of the
exceptions (overflow, division by zero, etc.). compiler changed from ``nimrod`` to ``nim`` too.
- ``system.setupForeignThreadGc`` can be used for better interaction with - ``system.fileHandle`` has been renamed to ``system.getFileHandle`` to
foreign libraries that create threads and run a Nim callback from these prevent name conflicts with the new type ``FileHandle``.
foreign threads. - Comments are now not part of the AST anymore, as such you cannot use them
- List comprehensions have been implemented as a macro in the ``future`` in place of ``discard``.
module. - Large parts of the stdlib got rid of the T/P type prefixes. Instead most
- The new Async module (``asyncnet``) now supports SSL. types now simply start with an uppercased letter. The
- The ``smtp`` module now has an async implementation. so called "partial case sensitivity" rule is now active allowing for code
- Added module ``asyncfile`` which implements asynchronous file reading like ``var foo: Foo`` in more contexts.
and writing. - String case (or any non-ordinal case) statements
- ``osproc.kill`` has been added. without 'else' are deprecated.
- ``asyncnet`` and ``asynchttpserver`` now support ``SO_REUSEADDR``. - Recursive tuple types are not allowed anymore. Use ``object`` instead.
- The PEGS module returns ``nil`` instead of ``""`` when an optional capture
fails to match.
- The re module returns ``nil`` instead of ``""`` when an optional capture
fails to match.
- The "symmetric set difference" operator (``-+-``) never worked and has been
removed.
- ``defer`` is a keyword now.
- ``func`` is a keyword now.
- The ``using`` language feature now needs to be activated via the new
``{.experimental.}`` pragma that enables experimental language features.
- Destructors are now officially *experimental*.
- Standalone ``except`` and ``finally`` statements are deprecated now.
The standalone ``finally`` can be replaced with ``defer``,
standalone ``except`` requires an explicit ``try``.
- Operators ending in ``>`` are considered as "arrow like" and have their
own priority level and are right associative. This means that
the ``=>`` and ``->`` operators from the `future <future.html>`_ module
work better.
- Field names in tuples are now ignored for type comparisons. This allows
for greater interoperability between different modules.
- Statement lists are not converted to an implicit ``do`` block anymore. This
means the confusing ``nnkDo`` nodes when working with macros are gone for
good.
Bugfixes
--------
- ``nil`` and ``NULL`` are now preserved between Nim and databases in the Language Additions
``db_*`` modules. ------------------
- Fixed issue with OS module in non-unicode mode on Windows.
- Fixed issue with ``x.low`` - The new concurrency model has been implemented including ``locks`` sections,
(`#1366 <https://github.com/Araq/Nim/issues/1366>`_). lock levels and object field ``guards``.
- Fixed tuple unpacking issue inside closure iterators - The ``parallel`` statement has been implemented.
(`#1067 <https://github.com/Araq/Nim/issues/1067>`_). - ``deepCopy`` has been added to the language.
- Fixed ENDB compilation issues. - The builtin ``procCall`` can be used to get ``super``-like functionality
- Many ``asynchttpserver`` fixes. for multi methods.
- Macros can now keep global state across macro calls - There is a new pragma ``{.experimental.}`` that enables experimental
(`#903 <https://github.com/Araq/Nim/issues/903>`_). language features per module, or you can enable these features on a global
- ``osproc`` fixes on Windows. level with the ``--experimental`` command line option.
- ``osproc.terminate`` fixed.
- Improvements to exception handling in async procedures.
(`#1487 <https://github.com/Araq/Nim/issues/1487>`_). Compiler Additions
- ``try`` now works at compile-time. ------------------
- Fixes ``T = ref T`` to be an illegal recursive type.
- Self imports are now disallowed. - The compiler now supports *mixed* Objective C / C++ / C code generation:
- Improved effect inference. The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
- Fixes for the ``math`` module on Windows. or Objective C code, any other module is compiled to C code. This
- User defined pragmas will now work for generics that have improves interoperability.
been instantiated in different modules. - There is a new ``parallel`` statement for safe fork&join parallel computing.
- Fixed queue exhaustion bug. - ``guard`` and ``lock`` pragmas have been implemented to support safer
concurrent programming.
- 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,
os.getEnv, os.existsEnv, os.dirExists, os.fileExists,
system.writeFile
- Two backticks now produce a single backtick within an ``emit`` or ``asm``
statement.
- There is a new tool, `nimfix <nimfix.html>`_ to help you in updating your
code from Nimrod to Nim.
- The compiler's output has been prettified.
Library Additions
-----------------
- Added module ``fenv`` to control the handling of floating-point rounding and
exceptions (overflow, division by zero, etc.).
- ``system.setupForeignThreadGc`` can be used for better interaction with
foreign libraries that create threads and run a Nim callback from these
foreign threads.
- List comprehensions have been implemented as a macro in the ``future``
module.
- The new Async module (``asyncnet``) now supports SSL.
- The ``smtp`` module now has an async implementation.
- Added module ``asyncfile`` which implements asynchronous file reading
and writing.
- ``osproc.kill`` has been added.
- ``asyncnet`` and ``asynchttpserver`` now support ``SO_REUSEADDR``.
Bugfixes
--------
- ``nil`` and ``NULL`` are now preserved between Nim and databases in the
``db_*`` modules.
- Fixed issue with OS module in non-unicode mode on Windows.
- Fixed issue with ``x.low``
(`#1366 <https://github.com/Araq/Nim/issues/1366>`_).
- Fixed tuple unpacking issue inside closure iterators
(`#1067 <https://github.com/Araq/Nim/issues/1067>`_).
- Fixed ENDB compilation issues.
- Many ``asynchttpserver`` fixes.
- Macros can now keep global state across macro calls
(`#903 <https://github.com/Araq/Nim/issues/903>`_).
- ``osproc`` fixes on Windows.
- ``osproc.terminate`` fixed.
- Improvements to exception handling in async procedures.
(`#1487 <https://github.com/Araq/Nim/issues/1487>`_).
- ``try`` now works at compile-time.
- Fixes ``T = ref T`` to be an illegal recursive type.
- Self imports are now disallowed.
- Improved effect inference.
- Fixes for the ``math`` module on Windows.
- User defined pragmas will now work for generics that have
been instantiated in different modules.
- Fixed queue exhaustion bug.
- Many, many more.
2014-12-09 New website design! 2014-12-09 New website design!
============================== ==============================

View file

@ -1,13 +1,13 @@
<a class="news" href="news.html#Z2014-12-29-version-0-10-2-released">
<h4>Dec 29, 2014</h4>
<p>Nim version 0.10.2 has been released!</p>
</a>
<a class="news" href="news.html#Z2014-12-09-new-website-design"> <a class="news" href="news.html#Z2014-12-09-new-website-design">
<h4>Dec 9, 2014</h4> <h4>Dec 9, 2014</h4>
<p>The new website design and forum are now online!</p> <p>The new website design and forum are now online!</p>
</a> </a>
<a class="news" href="news.html#Z2014-10-19-version-0-9-6-released">
<h4>Oct 19, 2014</h4>
<p>Nimrod version 0.9.6 has been released!</p>
</a>
<a class="news" href="news.html#Z2014-02-11-nimrod-featured-in-dr-dobb-s-journal"> <a class="news" href="news.html#Z2014-02-11-nimrod-featured-in-dr-dobb-s-journal">
<h4>Feb 11, 2014</h4> <h4>Feb 11, 2014</h4>
<p>Nimrod featured in Dr. Dobb's Journal</p> <p>Nimrod featured in Dr. Dobb's Journal</p>