Merge branch 'devel' of https://github.com/Araq/Nim into devel
This commit is contained in:
commit
c461f5a8c6
57 changed files with 652 additions and 436 deletions
|
|
@ -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 = ""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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/.."
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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}:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>`_
|
||||||
|
|
|
||||||
52
doc/nimc.txt
52
doc/nimc.txt
|
|
@ -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
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
12
doc/tut2.txt
12
doc/tut2.txt
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
12
koch.nim
12
koch.nim
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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, "$"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
26
tests/generics/t1056.nim
Normal 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
44
tests/generics/t1789.nim
Normal 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]
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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]() =
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import strutils
|
|
||||||
|
|
||||||
echo ParseFloat("5000") / ParseFloat("10")
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
||||||
|
|
||||||
35
tests/threads/ttryrecv.nim
Normal file
35
tests/threads/ttryrecv.nim
Normal 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)
|
||||||
7
tests/typerel/typedescs.nim
Normal file
7
tests/typerel/typedescs.nim
Normal 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.)
|
||||||
|
|
||||||
26
tests/types/temptyseqs.nim
Normal file
26
tests/types/temptyseqs.nim
Normal 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]
|
||||||
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
||||||
17
tests/vm/triangle_array.nim
Normal file
17
tests/vm/triangle_array.nim
Normal 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]
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 > <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
351
web/news.txt
351
web/news.txt
|
|
@ -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!
|
||||||
==============================
|
==============================
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue