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,8 +1517,8 @@ proc getStr*(a: PNode): string =
|
|||
proc getStrOrChar*(a: PNode): string =
|
||||
case a.kind
|
||||
of nkStrLit..nkTripleStrLit: result = a.strVal
|
||||
of nkCharLit: result = $chr(int(a.intVal))
|
||||
else:
|
||||
of nkCharLit..nkUInt64Lit: result = $chr(int(a.intVal))
|
||||
else:
|
||||
internalError(a.info, "getStrOrChar")
|
||||
result = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Files: "start.bat"
|
|||
BinPath: r"bin;dist\mingw\bin;dist"
|
||||
|
||||
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|doc\overview.html"
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip|overview.html"
|
||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
||||
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
|
||||
; for now only NSIS supports optional downloads
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
# Special configuration file for the Nim project
|
||||
|
||||
# gc:markAndSweep
|
||||
|
||||
hint[XDeclaredButNotUsed]:off
|
||||
path:"llvm"
|
||||
path:"$projectPath/.."
|
||||
|
|
|
|||
|
|
@ -67,12 +67,25 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
|
|||
# error correction:
|
||||
result = copyTree(arg)
|
||||
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,
|
||||
arg: PNode, coerceDistincts = false): PNode
|
||||
|
||||
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 =
|
||||
# new type relation that is used for array constructors,
|
||||
# if expressions, etc.:
|
||||
|
|
@ -96,6 +109,13 @@ proc commonType*(x, y: PType): PType =
|
|||
# check for seq[empty] vs. seq[int]
|
||||
let idx = ord(b.kind in {tyArray, tyArrayConstr})
|
||||
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 a.kind == tyRange and b.kind == tyRange:
|
||||
# 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
|
||||
openScope(c)
|
||||
var lifted = liftParamType(c, skType, newNodeI(nkArgList, info),
|
||||
t, ":anon", info)
|
||||
t, ":anon", info)
|
||||
closeScope(c)
|
||||
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):
|
||||
changeType(n.sons[i], elemType(newType), check)
|
||||
of nkPar:
|
||||
if newType.kind != tyTuple:
|
||||
let tup = newType.skipTypes({tyGenericInst})
|
||||
if tup.kind != tyTuple:
|
||||
internalError(n.info, "changeType: no tuple type for constructor")
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
|
|
@ -437,7 +438,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
|
|||
if m.kind == nkExprColonExpr:
|
||||
m = m.sons[1]
|
||||
n.sons[i] = m
|
||||
changeType(m, newType.sons[i], check)
|
||||
changeType(m, tup.sons[i], check)
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if check:
|
||||
let value = n.intVal
|
||||
|
|
@ -925,18 +926,20 @@ const
|
|||
proc readTypeParameter(c: PContext, typ: PType,
|
||||
paramName: PIdent, info: TLineInfo): PNode =
|
||||
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias
|
||||
else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1])
|
||||
|
||||
else: (internalAssert(typ.kind == tyCompositeTypeClass);
|
||||
typ.sons[1].skipGenericAlias)
|
||||
#debug ty
|
||||
let tbody = ty.sons[0]
|
||||
for s in countup(0, tbody.len-2):
|
||||
let tParam = tbody.sons[s]
|
||||
if tParam.sym.name == paramName:
|
||||
if tParam.sym.name.id == paramName.id:
|
||||
let rawTyp = ty.sons[s + 1]
|
||||
if rawTyp.kind == tyStatic:
|
||||
return rawTyp.n
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
||||
#echo "came here: returned nil"
|
||||
|
||||
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
## 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 f: PSym = nil
|
||||
result = nil
|
||||
|
||||
if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
|
||||
if ty.kind == tyTypeDesc: ty = ty.base
|
||||
ty = ty.skipTypes(tyDotOpTransparent)
|
||||
|
|
@ -971,7 +975,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
# look up if the identifier belongs to the enum:
|
||||
while ty != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
if f != nil: break
|
||||
if f != nil: break
|
||||
ty = ty.sons[0] # enum inheritance
|
||||
if f != nil:
|
||||
result = newSymNode(f)
|
||||
|
|
@ -983,7 +987,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
of tyTypeParamsHolders:
|
||||
return readTypeParameter(c, ty, i, n.info)
|
||||
of tyObject, tyTuple:
|
||||
if ty.n.kind == nkRecList:
|
||||
if ty.n != nil and ty.n.kind == nkRecList:
|
||||
for field in ty.n:
|
||||
if field.sym.name == i:
|
||||
n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ])
|
||||
|
|
|
|||
|
|
@ -60,13 +60,20 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
|||
else:
|
||||
result = symChoice(c, n, s, scOpen)
|
||||
of skGenericParam:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
if s.typ != nil and s.typ.kind == tyStatic:
|
||||
if s.typ.n != nil:
|
||||
result = s.typ.n
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
styleCheckUse(n.info, s)
|
||||
of skParam:
|
||||
result = n
|
||||
styleCheckUse(n.info, s)
|
||||
of skType:
|
||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||
if (s.typ != nil) and
|
||||
(s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
|
||||
result = newSymNodeTypeDesc(s, n.info)
|
||||
else:
|
||||
result = n
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
|||
var q = a.sym
|
||||
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses:
|
||||
continue
|
||||
var s = newSym(skType, q.name, getCurrOwner(), q.info)
|
||||
let symKind = if q.typ.kind == tyStatic: skConst else: skType
|
||||
var s = newSym(symKind, q.name, getCurrOwner(), q.info)
|
||||
s.flags = s.flags + {sfUsed, sfFromGeneric}
|
||||
var t = PType(idTableGet(pt, q.typ))
|
||||
if t == nil:
|
||||
|
|
@ -40,6 +41,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable,
|
|||
t = generateTypeInstance(c, pt, a, t)
|
||||
#t = ReplaceTypeVarsT(cl, t)
|
||||
s.typ = t
|
||||
if t.kind == tyStatic: s.ast = t.n
|
||||
addDecl(c, s)
|
||||
entry.concreteTypes[i] = t
|
||||
|
||||
|
|
|
|||
|
|
@ -653,7 +653,8 @@ proc checkForMetaFields(n: PNode) =
|
|||
template checkMeta(t) =
|
||||
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
|
||||
localError(n.info, errTIsNotAConcreteType, t.typeToString)
|
||||
|
||||
|
||||
if n.isNil: return
|
||||
case n.kind
|
||||
of nkRecList, nkRecCase:
|
||||
for s in n: checkForMetaFields(s)
|
||||
|
|
|
|||
|
|
@ -214,44 +214,48 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
|
|||
localError(n.info, errXExpectsOneTypeParam, "range")
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var indx, base: PType
|
||||
result = newOrPrevType(tyArray, prev, c)
|
||||
if sonsLen(n) == 3:
|
||||
# 3 = length(array indx base)
|
||||
if isRange(n[1]): indx = semRangeAux(c, n[1], nil)
|
||||
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 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})
|
||||
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:
|
||||
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)
|
||||
result = x.typ.skipTypes({tyTypeDesc})
|
||||
#localError(n[1].info, errConstExprExpected)
|
||||
|
||||
proc semArray(c: PContext, n: PNode, prev: PType): PType =
|
||||
var base: PType
|
||||
result = newOrPrevType(tyArray, prev, c)
|
||||
if sonsLen(n) == 3:
|
||||
# 3 = length(array indx base)
|
||||
var indx = semArrayIndex(c, n[1])
|
||||
addSonSkipIntLit(result, indx)
|
||||
if indx.kind == tyGenericInst: indx = lastSon(indx)
|
||||
if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}:
|
||||
|
|
|
|||
|
|
@ -517,6 +517,16 @@ proc maybeSkipDistinct(t: PType, callee: PSym): PType =
|
|||
else:
|
||||
result = t
|
||||
|
||||
proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
|
||||
# Consider this example:
|
||||
# type Value[N: static[int]] = object
|
||||
# proc foo[N](a: Value[N], r: range[0..(N-1)])
|
||||
# Here, N-1 will be initially nkStaticExpr that can be evaluated only after
|
||||
# N is bound to a concrete value during the matching of the first param.
|
||||
# This proc is used to evaluate such static expressions.
|
||||
let instantiated = replaceTypesInBody(c.c, c.bindings, n)
|
||||
result = c.c.semExpr(c.c, instantiated)
|
||||
|
||||
proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
# typeRel can be used to establish various relationships between types:
|
||||
#
|
||||
|
|
@ -620,6 +630,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
# bugfix: accept integer conversions here
|
||||
#if result < isGeneric: result = isNone
|
||||
if result notin {isNone, isGeneric}:
|
||||
# resolve any late-bound static expressions
|
||||
# that may appear in the range:
|
||||
for i in 0..1:
|
||||
if f.n[i].kind == nkStaticExpr:
|
||||
f.n.sons[i] = tryResolvingStaticExpr(c, f.n[i])
|
||||
result = typeRangeRel(f, a)
|
||||
else:
|
||||
if skipTypes(f, {tyRange}).kind == a.kind:
|
||||
|
|
@ -964,6 +979,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
of tyStatic:
|
||||
if aOrig.kind == tyStatic:
|
||||
result = typeRel(c, f.lastSon, a)
|
||||
if result != isNone and f.n != nil:
|
||||
if not exprStructuralEquivalent(f.n, a.n):
|
||||
result = isNone
|
||||
if result != isNone: put(c.bindings, f, aOrig)
|
||||
else:
|
||||
result = isNone
|
||||
|
|
@ -1006,15 +1024,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||
|
||||
of tyFromExpr:
|
||||
# fix the expression, so it contains the already instantiated types
|
||||
let instantiated = replaceTypesInBody(c.c, c.bindings, f.n)
|
||||
let reevaluted = c.c.semExpr(c.c, instantiated)
|
||||
case reevaluted.typ.kind
|
||||
let reevaluated = tryResolvingStaticExpr(c, f.n)
|
||||
case reevaluated.typ.kind
|
||||
of tyTypeDesc:
|
||||
result = typeRel(c, a, reevaluted.typ.base)
|
||||
result = typeRel(c, a, reevaluated.typ.base)
|
||||
of tyStatic:
|
||||
result = typeRel(c, a, reevaluted.typ.base)
|
||||
if result != isNone and reevaluted.typ.n != nil:
|
||||
if not exprStructuralEquivalent(aOrig.n, reevaluted.typ.n):
|
||||
result = typeRel(c, a, reevaluated.typ.base)
|
||||
if result != isNone and reevaluated.typ.n != nil:
|
||||
if not exprStructuralEquivalent(aOrig.n, reevaluated.typ.n):
|
||||
result = isNone
|
||||
else:
|
||||
localError(f.n.info, errTypeExpected)
|
||||
|
|
@ -1083,6 +1100,11 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
|||
arg: PNode): PNode =
|
||||
# arg.typ can be nil in 'suggest':
|
||||
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)
|
||||
call.add(f.n.copyTree)
|
||||
call.add(arg.copyTree)
|
||||
|
|
|
|||
|
|
@ -74,9 +74,6 @@ proc suggestField(c: PContext, s: PSym, outputs: var int) =
|
|||
suggestWriteln(symToStr(s, isLocal=true, sectionSuggest))
|
||||
inc outputs
|
||||
|
||||
when not defined(nimhygiene):
|
||||
{.pragma: inject.}
|
||||
|
||||
template wholeSymTab(cond, section: expr) {.immediate.} =
|
||||
var isLocal = true
|
||||
for scope in walkScopes(c.currentScope):
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ proc lastOrd*(t: PType): BiggestInt
|
|||
proc lengthOrd*(t: PType): BiggestInt
|
||||
type
|
||||
TPreferedDesc* = enum
|
||||
preferName, preferDesc, preferExported, preferModuleInfo
|
||||
preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
|
||||
|
||||
proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
|
||||
proc base*(t: PType): PType
|
||||
|
|
@ -411,11 +411,13 @@ const
|
|||
"UserTypeClassInst", "CompositeTypeClass",
|
||||
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor"]
|
||||
|
||||
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
|
||||
|
||||
proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
var t = typ
|
||||
result = ""
|
||||
if t == nil: return
|
||||
if prefer in {preferName, preferModuleInfo} and t.sym != nil and
|
||||
if prefer in preferToResolveSymbols and t.sym != nil and
|
||||
sfAnon notin t.sym.flags:
|
||||
if t.kind == tyInt and isIntLit(t):
|
||||
return t.sym.name.s & " literal(" & $t.n.intVal & ")"
|
||||
|
|
@ -428,20 +430,26 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
|||
if not isIntLit(t) or prefer == preferExported:
|
||||
result = typeToStr[t.kind]
|
||||
else:
|
||||
result = "int literal(" & $t.n.intVal & ")"
|
||||
if prefer == preferGenericArg:
|
||||
result = $t.n.intVal
|
||||
else:
|
||||
result = "int literal(" & $t.n.intVal & ")"
|
||||
of tyGenericBody, tyGenericInst, tyGenericInvokation:
|
||||
result = typeToString(t.sons[0]) & '['
|
||||
for i in countup(1, sonsLen(t) -1 -ord(t.kind != tyGenericInvokation)):
|
||||
if i > 1: add(result, ", ")
|
||||
add(result, typeToString(t.sons[i]))
|
||||
add(result, typeToString(t.sons[i], preferGenericArg))
|
||||
add(result, ']')
|
||||
of tyTypeDesc:
|
||||
if t.base.kind == tyNone: result = "typedesc"
|
||||
else: result = "typedesc[" & typeToString(t.base) & "]"
|
||||
of tyStatic:
|
||||
internalAssert t.len > 0
|
||||
result = "static[" & typeToString(t.sons[0]) & "]"
|
||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||
if prefer == preferGenericArg and t.n != nil:
|
||||
result = t.n.renderTree
|
||||
else:
|
||||
result = "static[" & typeToString(t.sons[0]) & "]"
|
||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||
of tyUserTypeClass:
|
||||
internalAssert t.sym != nil and t.sym.owner != nil
|
||||
return t.sym.owner.name.s
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ type
|
|||
slotTempInt, # some temporary int
|
||||
slotTempFloat, # some temporary float
|
||||
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
|
||||
blocks*: seq[TBlock] # blocks; temp data structure
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
# types that use the 'node' field; the reason is that slots are
|
||||
# re-used in a register based VM. Example:
|
||||
#
|
||||
# .. code-block:: nimrod
|
||||
# .. code-block:: nim
|
||||
# let s = a & b # no matter what, create fresh node
|
||||
# s = a & b # no matter what, keep the node
|
||||
#
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
# this copy depends on the involved types.
|
||||
|
||||
import
|
||||
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||
unsigned, strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||
trees, intsets, rodread, magicsys, options, lowerings
|
||||
|
||||
from os import splitFile
|
||||
|
|
@ -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)
|
||||
let x = c.code[i]
|
||||
|
||||
result.add($i)
|
||||
let opc = opcode(x)
|
||||
if opc in {opcConv, opcCast}:
|
||||
let y = c.code[i+1]
|
||||
|
|
@ -188,7 +189,7 @@ proc getTemp(c: PCtx; typ: PType): TRegister =
|
|||
|
||||
proc freeTemp(c: PCtx; r: TRegister) =
|
||||
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 =
|
||||
# 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)
|
||||
elif c.prc.slots[tmp].kind >= slotTempUnknown:
|
||||
gABC(c, n, opcAddrNode, dest, tmp)
|
||||
# XXX this can still be wrong sometimes; hopefully it's only generated
|
||||
# in call contexts, where it is safe
|
||||
# hack ahead; in order to fix bug #1781 we mark the temporary as
|
||||
# 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")
|
||||
else:
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -456,11 +456,7 @@ can then attach a GC to this thread via
|
|||
|
||||
.. code-block:: nim
|
||||
|
||||
setStackBottom(addr(someLocal))
|
||||
initGC()
|
||||
|
||||
At the moment this support is still experimental so you need to expose these
|
||||
functions yourself or submit patches to request a public API.
|
||||
system.setupForeignThreadGc()
|
||||
|
||||
It is **not** safe to disable the garbage collector and enable it after the
|
||||
call from your background thread even if the code you are calling is short
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ Generic Operating System Services
|
|||
|
||||
* `streams <streams.html>`_
|
||||
This module provides a stream interface and two implementations thereof:
|
||||
the `PFileStream` and the `PStringStream` which implement the stream
|
||||
interface for Nim file objects (`TFile`) and strings. Other modules
|
||||
the `FileStream` and the `StringStream` which implement the stream
|
||||
interface for Nim file objects (`File`) and strings. Other modules
|
||||
may provide other implementations for this standard stream interface.
|
||||
|
||||
* `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.
|
||||
|
||||
|
||||
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
|
||||
==============
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ Numbers
|
|||
Numerical literals are written as in most other languages. As a special twist,
|
||||
underscores are allowed for better readability: ``1_000_000`` (one million).
|
||||
A number that contains a dot (or 'e' or 'E') is a floating point literal:
|
||||
``1.0e9`` (one million). Hexadecimal literals are prefixed with ``0x``,
|
||||
``1.0e9`` (one billion). Hexadecimal literals are prefixed with ``0x``,
|
||||
binary literals with ``0b`` and octal literals with ``0o``. A leading zero
|
||||
alone does not produce an octal.
|
||||
|
||||
|
|
|
|||
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
|
||||
type
|
||||
TPerson = object of TObject
|
||||
TPerson = object of RootObj
|
||||
name*: string # the * means that `name` is accessible from other modules
|
||||
age: int # no * means that the field is hidden from other modules
|
||||
|
||||
|
|
@ -76,10 +76,10 @@ never *equivalent*. New object types can only be defined within a type
|
|||
section.
|
||||
|
||||
Inheritance is done with the ``object of`` syntax. Multiple inheritance is
|
||||
currently not supported. If an object type has no suitable ancestor, ``TObject``
|
||||
currently not supported. If an object type has no suitable ancestor, ``RootObj``
|
||||
can be used as its ancestor, but this is only a convention. Objects that have
|
||||
no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma
|
||||
to introduce new object roots apart from ``system.TObject``. (This is used
|
||||
to introduce new object roots apart from ``system.RootObj``. (This is used
|
||||
in the GTK wrapper for instance.)
|
||||
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ is needed:
|
|||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TSocket* = object of TObject
|
||||
TSocket* = object of RootObj
|
||||
FHost: int # cannot be accessed from the outside of the module
|
||||
# the `F` prefix is a convention to avoid clashes since
|
||||
# the accessors are named `host`
|
||||
|
|
@ -284,7 +284,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the
|
|||
|
||||
.. code-block:: nim
|
||||
type
|
||||
PExpr = ref object of TObject ## abstract base class for an expression
|
||||
PExpr = ref object of RootObj ## abstract base class for an expression
|
||||
PLiteral = ref object of PExpr
|
||||
x: int
|
||||
PPlusExpr = ref object of PExpr
|
||||
|
|
@ -313,7 +313,7 @@ dispatching:
|
|||
.. code-block:: nim
|
||||
|
||||
type
|
||||
TThing = object of TObject
|
||||
TThing = object of RootObj
|
||||
TUnit = object of TThing
|
||||
x: int
|
||||
|
||||
|
|
|
|||
16
koch.nim
16
koch.nim
|
|
@ -94,16 +94,16 @@ const
|
|||
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
|
||||
|
||||
proc csource(args: string) =
|
||||
exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=mingw32 csource compiler/nim.ini $1" %
|
||||
exec("$4 cc $1 -r $3 --var:version=$2 --var:mingw=none csource compiler/nim.ini $1" %
|
||||
[args, VersionAsString, compileNimInst, findNim()])
|
||||
|
||||
proc zip(args: string) =
|
||||
exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nim.ini" %
|
||||
exec("$3 cc -r $2 --var:version=$1 --var:mingw=none scripts compiler/nim.ini" %
|
||||
[VersionAsString, compileNimInst, findNim()])
|
||||
exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nim.ini" %
|
||||
exec("$# --var:version=$# --var:mingw=none zip compiler/nim.ini" %
|
||||
["tools/niminst/niminst".exe, VersionAsString])
|
||||
|
||||
proc buildTool(toolname, args: string) =
|
||||
|
||||
proc buildTool(toolname, args: string) =
|
||||
exec("$# cc $# $#" % [findNim(), args, toolname])
|
||||
copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ proc nsis(args: string) =
|
|||
# produce 'nimrod_debug.exe':
|
||||
exec "nim c compiler" / "nim.nim"
|
||||
copyExe("compiler/nim".exe, "bin/nim_debug".exe)
|
||||
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" &
|
||||
" nsis compiler/nim") % VersionAsString)
|
||||
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw$#" &
|
||||
" nsis compiler/nim") % [VersionAsString, $(sizeof(pointer)*8)])
|
||||
|
||||
proc install(args: string) =
|
||||
exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nim.ini" %
|
||||
exec("$# cc -r $# --var:version=$# --var:mingw=none scripts compiler/nim.ini" %
|
||||
[findNim(), compileNimInst, VersionAsString])
|
||||
exec("sh ./install.sh $#" % args)
|
||||
|
||||
|
|
|
|||
|
|
@ -649,6 +649,8 @@ proc `$`*(node: PNimrodNode): string {.compileTime.} =
|
|||
result = $node.basename.ident & "*"
|
||||
of nnkStrLit..nnkTripleStrLit:
|
||||
result = node.strVal
|
||||
of nnkSym:
|
||||
result = $node.symbol
|
||||
else:
|
||||
badNodeKind node.kind, "$"
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,15 @@ proc getSystemVersion*(): string =
|
|||
elif $unix_info.sysname == "Darwin":
|
||||
# Darwin
|
||||
result.add("Mac OS X ")
|
||||
if "10" in $unix_info.release:
|
||||
if "14" in $unix_info.release:
|
||||
result.add("v10.10 Yosemite")
|
||||
elif "13" in $unix_info.release:
|
||||
result.add("v10.9 Mavericks")
|
||||
elif "12" in $unix_info.release:
|
||||
result.add("v10.8 Mountian Lion")
|
||||
elif "11" in $unix_info.release:
|
||||
result.add("v10.7 Lion")
|
||||
elif "10" in $unix_info.release:
|
||||
result.add("v10.6 Snow Leopard")
|
||||
elif "9" in $unix_info.release:
|
||||
result.add("v10.5 Leopard")
|
||||
|
|
|
|||
|
|
@ -245,6 +245,14 @@ proc `$`*(osvi: TVersionInfo): string =
|
|||
if osvi.ProductType == VER_NT_WORKSTATION:
|
||||
result.add("Windows 7 ")
|
||||
else: result.add("Windows Server 2008 R2 ")
|
||||
elif osvi.minorVersion == 2:
|
||||
if osvi.ProductType == VER_NT_WORKSTATION:
|
||||
result.add("Windows 8 ")
|
||||
else: result.add("Windows Server 2012 ")
|
||||
elif osvi.minorVersion == 3:
|
||||
if osvi.ProductType == VER_NT_WORKSTATION:
|
||||
result.add("Windows 8.1 ")
|
||||
else: result.add("Windows Server 2012 R2 ")
|
||||
|
||||
var dwType = getProductInfo(osvi.majorVersion, osvi.minorVersion, 0, 0)
|
||||
case dwType
|
||||
|
|
|
|||
|
|
@ -1570,9 +1570,9 @@ else:
|
|||
|
||||
|
||||
when defined(macosx):
|
||||
# We can't use the NOSIGNAL flag in the ``send`` function, it has no effect
|
||||
var
|
||||
MSG_HAVEMORE* {.importc, header: "<sys/socket.h>".}: cint
|
||||
MSG_NOSIGNAL* = MSG_HAVEMORE
|
||||
MSG_NOSIGNAL* = 0'i32
|
||||
else:
|
||||
var
|
||||
MSG_NOSIGNAL* {.importc, header: "<sys/socket.h>".}: cint
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
## as the response body.
|
||||
##
|
||||
## .. code-block::nim
|
||||
## import asynchttpserver, asyncdispatch
|
||||
##
|
||||
## var server = newAsyncHttpServer()
|
||||
## proc cb(req: Request) {.async.} =
|
||||
## await req.respond(Http200, "Hello World")
|
||||
|
|
|
|||
|
|
@ -1433,7 +1433,7 @@ proc eat(p: var PegParser, kind: TTokKind) =
|
|||
if p.tok.kind == kind: getTok(p)
|
||||
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 =
|
||||
for i in 0..high(p.nonterms):
|
||||
|
|
|
|||
|
|
@ -428,6 +428,10 @@ proc selectWrite*(writefds: var seq[SocketHandle],
|
|||
|
||||
pruneSocketSet(writefds, (wr))
|
||||
|
||||
# We ignore signal SIGPIPE on Darwin
|
||||
when defined(macosx):
|
||||
signal(SIGPIPE, SIG_IGN)
|
||||
|
||||
when defined(Windows):
|
||||
var wsa: WSAData
|
||||
if wsaStartup(0x0101'i16, addr wsa) != 0: raiseOSError(osLastError())
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ proc checkpoint*(msg: string) =
|
|||
template fail* =
|
||||
bind 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):
|
||||
if abortOnError: quit(1)
|
||||
|
|
|
|||
|
|
@ -1516,7 +1516,7 @@ const
|
|||
NimMinor*: int = 10
|
||||
## is the minor number of Nim's version.
|
||||
|
||||
NimPatch*: int = 1
|
||||
NimPatch*: int = 3
|
||||
## is the patch number of Nim's version.
|
||||
|
||||
NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch
|
||||
|
|
|
|||
|
|
@ -232,9 +232,10 @@ proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
|
|||
## it returns ``(false, default(msg))``.
|
||||
var q = cast[PRawChannel](addr(c))
|
||||
if q.mask != ChannelDeadMask:
|
||||
if tryAcquireSys(q.lock):
|
||||
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
|
||||
result.dataAvailable = true
|
||||
if tryAcquireSys(q.lock):
|
||||
if q.count > 0:
|
||||
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
|
||||
result.dataAvailable = true
|
||||
releaseSys(q.lock)
|
||||
|
||||
proc peek*[TMsg](c: var TChannel[TMsg]): int =
|
||||
|
|
|
|||
|
|
@ -296,15 +296,15 @@ when not defined(noSignalHandler):
|
|||
template processSignal(s, action: expr) {.immediate, dirty.} =
|
||||
if s == SIGINT: action("SIGINT: Interrupted by Ctrl-C.\n")
|
||||
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:
|
||||
when defined(endb):
|
||||
if dbgAborting: return # the debugger wants to abort
|
||||
action("SIGABRT: Abnormal termination.\n")
|
||||
elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
|
||||
elif s == SIGILL: action("SIGILL: Illegal operation.\n")
|
||||
elif s == SIGBUS:
|
||||
action("SIGBUS: Illegal storage access. (Attempt to read from nil?)\n")
|
||||
elif s == SIGBUS:
|
||||
action("SIGBUS: Illegal storage access. (Try to compile with -d:useSysAssert -d:useGcAssert for details.)\n")
|
||||
else:
|
||||
block platformSpecificSignal:
|
||||
when declared(SIGPIPE):
|
||||
|
|
|
|||
|
|
@ -368,32 +368,32 @@ type
|
|||
{.deprecated: [TSocketHandle: SocketHandle].}
|
||||
|
||||
type
|
||||
WSAData* {.importc: "WSADATA", header: "Winsock2.h".} = object
|
||||
WSAData* {.importc: "WSADATA", header: "winsock2.h".} = object
|
||||
wVersion, wHighVersion: int16
|
||||
szDescription: array[0..WSADESCRIPTION_LEN, char]
|
||||
szSystemStatus: array[0..WSASYS_STATUS_LEN, char]
|
||||
iMaxSockets, iMaxUdpDg: int16
|
||||
lpVendorInfo: cstring
|
||||
|
||||
SockAddr* {.importc: "SOCKADDR", header: "Winsock2.h".} = object
|
||||
SockAddr* {.importc: "SOCKADDR", header: "winsock2.h".} = object
|
||||
sa_family*: int16 # unsigned
|
||||
sa_data: array[0..13, char]
|
||||
|
||||
InAddr* {.importc: "IN_ADDR", header: "Winsock2.h".} = object
|
||||
InAddr* {.importc: "IN_ADDR", header: "winsock2.h".} = object
|
||||
s_addr*: int32 # IP address
|
||||
|
||||
Sockaddr_in* {.importc: "SOCKADDR_IN",
|
||||
header: "Winsock2.h".} = object
|
||||
header: "winsock2.h".} = object
|
||||
sin_family*: int16
|
||||
sin_port*: int16 # unsigned
|
||||
sin_addr*: InAddr
|
||||
sin_zero*: array[0..7, char]
|
||||
|
||||
In6_addr* {.importc: "IN6_ADDR", header: "Winsock2.h".} = object
|
||||
In6_addr* {.importc: "IN6_ADDR", header: "winsock2.h".} = object
|
||||
bytes*: array[0..15, char]
|
||||
|
||||
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
||||
header: "Winsock2.h".} = object
|
||||
header: "winsock2.h".} = object
|
||||
sin6_family*: int16
|
||||
sin6_port*: int16 # unsigned
|
||||
sin6_flowinfo*: int32 # unsigned
|
||||
|
|
@ -450,22 +450,22 @@ type
|
|||
|
||||
|
||||
var
|
||||
SOMAXCONN* {.importc, header: "Winsock2.h".}: cint
|
||||
INVALID_SOCKET* {.importc, header: "Winsock2.h".}: SocketHandle
|
||||
SOL_SOCKET* {.importc, header: "Winsock2.h".}: cint
|
||||
SO_DEBUG* {.importc, header: "Winsock2.h".}: cint ## turn on debugging info recording
|
||||
SO_ACCEPTCONN* {.importc, header: "Winsock2.h".}: cint # socket has had listen()
|
||||
SO_REUSEADDR* {.importc, header: "Winsock2.h".}: cint # allow local address reuse
|
||||
SO_KEEPALIVE* {.importc, header: "Winsock2.h".}: cint # keep connections alive
|
||||
SO_DONTROUTE* {.importc, header: "Winsock2.h".}: cint # just use interface addresses
|
||||
SO_BROADCAST* {.importc, header: "Winsock2.h".}: cint # permit sending of broadcast msgs
|
||||
SO_USELOOPBACK* {.importc, header: "Winsock2.h".}: cint # bypass hardware when possible
|
||||
SO_LINGER* {.importc, header: "Winsock2.h".}: cint # linger on close if data present
|
||||
SO_OOBINLINE* {.importc, header: "Winsock2.h".}: cint # leave received OOB data in line
|
||||
SOMAXCONN* {.importc, header: "winsock2.h".}: cint
|
||||
INVALID_SOCKET* {.importc, header: "winsock2.h".}: SocketHandle
|
||||
SOL_SOCKET* {.importc, header: "winsock2.h".}: cint
|
||||
SO_DEBUG* {.importc, header: "winsock2.h".}: cint ## turn on debugging info recording
|
||||
SO_ACCEPTCONN* {.importc, header: "winsock2.h".}: cint # socket has had listen()
|
||||
SO_REUSEADDR* {.importc, header: "winsock2.h".}: cint # allow local address reuse
|
||||
SO_KEEPALIVE* {.importc, header: "winsock2.h".}: cint # keep connections alive
|
||||
SO_DONTROUTE* {.importc, header: "winsock2.h".}: cint # just use interface addresses
|
||||
SO_BROADCAST* {.importc, header: "winsock2.h".}: cint # permit sending of broadcast msgs
|
||||
SO_USELOOPBACK* {.importc, header: "winsock2.h".}: cint # bypass hardware when possible
|
||||
SO_LINGER* {.importc, header: "winsock2.h".}: cint # linger on close if data present
|
||||
SO_OOBINLINE* {.importc, header: "winsock2.h".}: cint # leave received OOB data in line
|
||||
|
||||
SO_DONTLINGER* {.importc, header: "Winsock2.h".}: cint
|
||||
SO_EXCLUSIVEADDRUSE* {.importc, header: "Winsock2.h".}: cint # disallow local address reuse
|
||||
SO_ERROR* {.importc, header: "Winsock2.h".}: cint
|
||||
SO_DONTLINGER* {.importc, header: "winsock2.h".}: cint
|
||||
SO_EXCLUSIVEADDRUSE* {.importc, header: "winsock2.h".}: cint # disallow local address reuse
|
||||
SO_ERROR* {.importc, header: "winsock2.h".}: cint
|
||||
|
||||
proc `==`*(x, y: SocketHandle): bool {.borrow.}
|
||||
|
||||
|
|
|
|||
|
|
@ -280,9 +280,18 @@ when not useWinVersion:
|
|||
proc CRYPTO_set_mem_functions(a,b,c: pointer){.cdecl,
|
||||
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*() =
|
||||
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{.
|
||||
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
|
||||
|
||||
ObjectContainer = generic C
|
||||
C.len is ordinal
|
||||
C.len is Ordinal
|
||||
for v in items(C):
|
||||
v.type is tuple|object
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
proc p(a, b: int, c: proc ()) =
|
||||
c()
|
||||
|
||||
|
||||
p(1, 3):
|
||||
echo 1
|
||||
echo 3
|
||||
when false:
|
||||
# language spec changed:
|
||||
p(1, 3):
|
||||
echo 1
|
||||
echo 3
|
||||
|
||||
p(1, 1, proc() =
|
||||
echo 1
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
discard """
|
||||
line: 12
|
||||
errormsg: "instantiate 'notConcrete' explicitly"
|
||||
disabled: "true"
|
||||
"""
|
||||
|
||||
proc wrap[T]() =
|
||||
|
|
|
|||
|
|
@ -62,3 +62,7 @@ when false:
|
|||
block:
|
||||
var a, b: Bar[int, 0..2]
|
||||
discard foo(a, b)
|
||||
|
||||
# bug #1788
|
||||
|
||||
echo "hello" & char(ord(' ')) & "world"
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ proc TestLoops() =
|
|||
break
|
||||
break
|
||||
|
||||
while True:
|
||||
while true:
|
||||
break
|
||||
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ proc main() =
|
|||
res: int
|
||||
s: string
|
||||
#write(stdout, mymax(23, 45))
|
||||
write(stdout, "Hallo! Wie heißt du? ")
|
||||
write(stdout, "Hallo! Wie heisst du? ")
|
||||
s = readLine(stdin)
|
||||
# test the case statement
|
||||
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
|
||||
else: result = $c
|
||||
|
||||
proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'"
|
||||
proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
|
||||
|
||||
proc singleQuoteEsc(str: string): string =
|
||||
result = "'"
|
||||
|
|
@ -421,11 +421,11 @@ proc charSetEscAux(cc: set[char]): string =
|
|||
c1 = c2
|
||||
inc(c1)
|
||||
|
||||
proc CharSetEsc(cc: set[char]): string =
|
||||
proc charSetEsc(cc: set[char]): string =
|
||||
if card(cc) >= 128+64:
|
||||
result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']'
|
||||
result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
|
||||
else:
|
||||
result = '[' & CharSetEscAux(cc) & ']'
|
||||
result = '[' & charSetEscAux(cc) & ']'
|
||||
|
||||
proc toStrAux(r: TPeg, res: var string) =
|
||||
case r.kind
|
||||
|
|
@ -522,12 +522,12 @@ proc `$` *(r: TPeg): string {.rtl, extern: "npegsToString".} =
|
|||
|
||||
type
|
||||
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
|
||||
origStart: int
|
||||
|
||||
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.
|
||||
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:
|
||||
var x = rawMatch(s, p.sons[0], start+result, c)
|
||||
if x >= 0:
|
||||
if idx < maxSubpatterns:
|
||||
if idx < MaxSubpatterns:
|
||||
c.matches[idx] = (start, start+result-1)
|
||||
#else: silently ignore the capture
|
||||
inc(result, x)
|
||||
|
|
@ -739,7 +739,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
|
|||
inc(c.ml)
|
||||
result = rawMatch(s, p.sons[0], start, c)
|
||||
if result >= 0:
|
||||
if idx < maxSubpatterns:
|
||||
if idx < MaxSubpatterns:
|
||||
c.matches[idx] = (start, start+result-1)
|
||||
#else: silently ignore the capture
|
||||
else:
|
||||
|
|
@ -836,7 +836,7 @@ iterator findAll*(s: string, pattern: TPeg, start = 0): string =
|
|||
while i < s.len:
|
||||
var L = matchLen(s, pattern, matches, i)
|
||||
if L < 0: break
|
||||
for k in 0..maxSubPatterns-1:
|
||||
for k in 0..MaxSubPatterns-1:
|
||||
if isNil(matches[k]): break
|
||||
yield matches[k]
|
||||
inc(i, L)
|
||||
|
|
@ -866,7 +866,7 @@ template `=~`*(s: string, pattern: TPeg): expr =
|
|||
## echo("syntax error")
|
||||
##
|
||||
when not definedInScope(matches):
|
||||
var matches {.inject.}: array[0..maxSubpatterns-1, string]
|
||||
var matches {.inject.}: array[0..MaxSubpatterns-1, string]
|
||||
match(s, pattern, matches)
|
||||
|
||||
# ------------------------- more string handling ------------------------------
|
||||
|
|
@ -907,7 +907,7 @@ proc replacef*(s: string, sub: TPeg, by: string): string {.
|
|||
## "var1<-keykey; val2<-key2key2"
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..maxSubpatterns-1, string]
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
while i < s.len:
|
||||
var x = matchLen(s, sub, caps, i)
|
||||
if x <= 0:
|
||||
|
|
@ -924,7 +924,7 @@ proc replace*(s: string, sub: TPeg, by = ""): string {.
|
|||
## in `by`.
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..maxSubpatterns-1, string]
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
while i < s.len:
|
||||
var x = matchLen(s, sub, caps, i)
|
||||
if x <= 0:
|
||||
|
|
@ -942,7 +942,7 @@ proc parallelReplace*(s: string, subs: varargs[
|
|||
## applied in parallel.
|
||||
result = ""
|
||||
var i = 0
|
||||
var caps: array[0..maxSubpatterns-1, string]
|
||||
var caps: array[0..MaxSubpatterns-1, string]
|
||||
while i < s.len:
|
||||
block searchSubs:
|
||||
for j in 0..high(subs):
|
||||
|
|
@ -1055,7 +1055,7 @@ type
|
|||
TPegLexer {.inheritable.} = object ## the lexer object.
|
||||
bufpos: int ## the current position within the buffer
|
||||
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
|
||||
colOffset: int ## column to add
|
||||
filename: string
|
||||
|
|
@ -1118,38 +1118,38 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
|
|||
case c.buf[c.bufpos]
|
||||
of 'r', 'R', 'c', 'C':
|
||||
add(tok.literal, '\c')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'l', 'L':
|
||||
add(tok.literal, '\L')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'f', 'F':
|
||||
add(tok.literal, '\f')
|
||||
inc(c.bufpos)
|
||||
of 'e', 'E':
|
||||
add(tok.literal, '\e')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'a', 'A':
|
||||
add(tok.literal, '\a')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'b', 'B':
|
||||
add(tok.literal, '\b')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'v', 'V':
|
||||
add(tok.literal, '\v')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 't', 'T':
|
||||
add(tok.literal, '\t')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
of 'x', 'X':
|
||||
inc(c.bufpos)
|
||||
var xi = 0
|
||||
handleHexChar(c, xi)
|
||||
handleHexChar(c, xi)
|
||||
if xi == 0: tok.kind = tkInvalid
|
||||
else: add(tok.literal, Chr(xi))
|
||||
else: add(tok.literal, chr(xi))
|
||||
of '0'..'9':
|
||||
var val = ord(c.buf[c.bufpos]) - ord('0')
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
var i = 1
|
||||
while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
|
||||
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
|
||||
of '\0'..'\31':
|
||||
tok.kind = tkInvalid
|
||||
elif c.buf[c.bufpos] in strutils.letters:
|
||||
elif c.buf[c.bufpos] in strutils.Letters:
|
||||
tok.kind = tkInvalid
|
||||
else:
|
||||
add(tok.literal, c.buf[c.bufpos])
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
|
||||
proc skip(c: var TPegLexer) =
|
||||
var pos = c.bufpos
|
||||
|
|
@ -1171,7 +1171,7 @@ proc skip(c: var TPegLexer) =
|
|||
while true:
|
||||
case buf[pos]
|
||||
of ' ', '\t':
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
of '#':
|
||||
while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
|
||||
of '\c':
|
||||
|
|
@ -1203,7 +1203,7 @@ proc getString(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
c.bufpos = pos
|
||||
|
||||
proc getDollar(c: var TPegLexer, tok: var TToken) =
|
||||
|
|
@ -1244,7 +1244,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
ch = buf[pos]
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
incl(tok.charset, ch)
|
||||
if buf[pos] == '-':
|
||||
if buf[pos+1] == ']':
|
||||
|
|
@ -1264,7 +1264,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) =
|
|||
break
|
||||
else:
|
||||
ch2 = buf[pos]
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
for i in ord(ch)+1 .. ord(ch2):
|
||||
incl(tok.charset, chr(i))
|
||||
c.bufpos = pos
|
||||
|
|
@ -1275,7 +1275,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) =
|
|||
var buf = c.buf
|
||||
while true:
|
||||
add(tok.literal, buf[pos])
|
||||
Inc(pos)
|
||||
inc(pos)
|
||||
if buf[pos] notin strutils.IdentChars: break
|
||||
c.bufpos = pos
|
||||
tok.kind = tkIdentifier
|
||||
|
|
@ -1312,11 +1312,11 @@ proc getTok(c: var TPegLexer, tok: var TToken) =
|
|||
getCharset(c, tok)
|
||||
of '(':
|
||||
tok.kind = tkParLe
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
add(tok.literal, '(')
|
||||
of ')':
|
||||
tok.kind = tkParRi
|
||||
Inc(c.bufpos)
|
||||
inc(c.bufpos)
|
||||
add(tok.literal, ')')
|
||||
of '.':
|
||||
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]
|
||||
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
|
||||
else:
|
||||
testObj.testDesc = child[2].strVal
|
||||
testObj.testBlock = child[3][6]
|
||||
testObj.testBlock = child[1]
|
||||
|
||||
tests.add(testObj)
|
||||
|
||||
|
|
|
|||
|
|
@ -522,8 +522,8 @@ proc setupDist2(c: var TConfigData) =
|
|||
# ------------------ generate ZIP file ---------------------------------------
|
||||
when haveZipLib:
|
||||
proc zipDist(c: var TConfigData) =
|
||||
var proj = toLower(c.name)
|
||||
var n = "$#_$#.zip" % [proj, c.version]
|
||||
var proj = toLower(c.name) & "-" & c.version
|
||||
var n = "$#.zip" % proj
|
||||
if c.outdir.len == 0: n = "build" / n
|
||||
else: n = c.outdir / n
|
||||
var z: TZipArchive
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ proc initConfigData(c: var TConfigData) =
|
|||
c.logo = ""
|
||||
c.ticker = ""
|
||||
c.vars = newStringTable(modeStyleInsensitive)
|
||||
c.gitRepo = "https://github.com/Araq/Nimrod/tree"
|
||||
c.gitRepo = "https://github.com/Araq/Nim/tree"
|
||||
c.gitCommit = "master"
|
||||
c.numProcessors = countProcessors()
|
||||
# Attempts to obtain the git current commit.
|
||||
|
|
@ -262,24 +262,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
|
|||
exec("nim doc2 $# -o:$# $#" %
|
||||
[c.nimArgs, destPath / "docgen_sample2.html", src])
|
||||
|
||||
proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
|
||||
|
||||
proc buildDoc(c: var TConfigData, destPath: string) =
|
||||
# call nim for the documentation:
|
||||
var
|
||||
commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
|
||||
i = 0
|
||||
for d in items(c.doc):
|
||||
commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit,
|
||||
commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
for d in items(c.srcdoc):
|
||||
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit,
|
||||
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
for d in items(c.srcdoc2):
|
||||
commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit,
|
||||
commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
|
||||
destPath / changeFileExt(splitFile(d).name, "html"), d]
|
||||
i.inc
|
||||
|
||||
|
|
@ -311,8 +313,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
|
|||
# build additional documentation (without the index):
|
||||
var commands = newSeq[string](c.webdoc.len)
|
||||
for i, doc in pairs(c.webdoc):
|
||||
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit,
|
||||
commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# $#" %
|
||||
[c.nimArgs, c.gitRepo, c.gitCommit, doc.pathPart,
|
||||
destPath / changeFileExt(splitFile(doc).name, "html"), doc]
|
||||
mexec(commands, c.numProcessors)
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
<span class="tab end"> </span>count += <span class="val">1</span>
|
||||
|
||||
echo(<span class="val">"Average line length: "</span>,
|
||||
<span class="kwd">if</span> count: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
|
||||
<span class="kwd">if</span> count > <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
|
||||
</pre>
|
||||
</div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
|
||||
and clang on Mac OS X.
|
||||
|
|
@ -10,9 +10,8 @@ Binaries
|
|||
========
|
||||
|
||||
Unfortunately for now we only provide builds for Windows.
|
||||
|
||||
* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
|
||||
* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
|
||||
* 32 bit: `nim-0.10.2_x32.exe <download/nim-0.10.2_x32.exe>`_
|
||||
* 64 bit: `nim-0.10.2_x64.exe <download/nim-0.10.2_x64.exe>`_
|
||||
|
||||
|
||||
Installation based on generated C code
|
||||
|
|
@ -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.
|
||||
|
||||
|
||||
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:
|
||||
|
||||
* sh build.sh
|
||||
* 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.
|
||||
|
||||
|
||||
|
|
|
|||
351
web/news.txt
351
web/news.txt
|
|
@ -2,195 +2,200 @@
|
|||
News
|
||||
====
|
||||
|
||||
..
|
||||
2014-10-21 Version 0.10.2 released
|
||||
==================================
|
||||
2014-12-29 Version 0.10.2 released
|
||||
==================================
|
||||
|
||||
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
|
||||
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
|
||||
existing projects so that it works with the latest version of the compiler.
|
||||
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
|
||||
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
|
||||
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
|
||||
changes to a minimum so far. Starting with version 1.0, we will not introduce
|
||||
any breaking changes between major release versions.
|
||||
One of Nim's goals is to ensure that the compiler is as efficient as possible.
|
||||
Take a look at the
|
||||
`latest benchmarks <https://github.com/logicchains/LPATHBench/blob/master/writeup.md>`_,
|
||||
which show that Nim is consistently near
|
||||
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
|
||||
applications using non-blocking code. Nim now also has a built-in thread pool
|
||||
for lightweight threading through the use of ``spawn``.
|
||||
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
|
||||
any breaking changes between major release versions.
|
||||
One of Nim's goals is to ensure that the compiler is as efficient as possible.
|
||||
Take a look at the
|
||||
`latest benchmarks <https://github.com/logicchains/LPATHBench/blob/master/writeup.md>`_,
|
||||
which show that Nim is consistently near
|
||||
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
|
||||
applications using non-blocking code. Nim now also has a built-in thread pool
|
||||
for lightweight threading through the use of ``spawn``.
|
||||
|
||||
The unpopular "T" and "P" prefixes on types have been deprecated. Nim also
|
||||
became more expressive by weakening the distinction between statements and
|
||||
epxressions. We also added new and searchable forums, a new website, and our
|
||||
documentation generator ``docgen`` has seen major improvements.
|
||||
|
||||
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.
|
||||
The unpopular "T" and "P" prefixes on types have been deprecated. Nim also
|
||||
became more expressive by weakening the distinction between statements and
|
||||
expressions. We also added a new and searchable forum, a new website, and our
|
||||
documentation generator ``docgen`` has seen major improvements. Many thanks to
|
||||
Nick Greenfield for the much more beautiful documentation!
|
||||
|
||||
|
||||
Language Additions
|
||||
------------------
|
||||
|
||||
- The new concurrency model has been implemented including ``locks`` sections,
|
||||
lock levels and object field ``guards``.
|
||||
- The ``parallel`` statement has been implemented.
|
||||
- ``deepCopy`` has been added to the language.
|
||||
- The builtin ``procCall`` can be used to get ``super``-like functionality
|
||||
for multi methods.
|
||||
- There is a new pragma ``{.experimental.}`` that enables experimental
|
||||
language features per module, or you can enable this features on a global
|
||||
level with the ``--experimental`` command line option.
|
||||
What's left to be done
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The 1.0 release is actually very close. Apart from bug fixes, there are
|
||||
two major features missing or incomplete:
|
||||
|
||||
* ``static[T]`` needs to be defined precisely and the bugs in the
|
||||
implementation need to be fixed.
|
||||
* 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:
|
||||
The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
|
||||
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::
|
||||
Outside of the language and the compiler itself many Nim tools have seen
|
||||
considerable improvements.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
- 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.
|
||||
Changelog
|
||||
~~~~~~~~~
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
Changes affecting backwards compatibility
|
||||
-----------------------------------------
|
||||
|
||||
- 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``.
|
||||
- **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.
|
||||
|
||||
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.
|
||||
Language Additions
|
||||
------------------
|
||||
|
||||
- The new concurrency model has been implemented including ``locks`` sections,
|
||||
lock levels and object field ``guards``.
|
||||
- The ``parallel`` statement has been implemented.
|
||||
- ``deepCopy`` has been added to the language.
|
||||
- The builtin ``procCall`` can be used to get ``super``-like functionality
|
||||
for multi methods.
|
||||
- There is a new pragma ``{.experimental.}`` that enables experimental
|
||||
language features per module, or you can enable these features on a global
|
||||
level with the ``--experimental`` command line option.
|
||||
|
||||
|
||||
Compiler Additions
|
||||
------------------
|
||||
|
||||
- The compiler now supports *mixed* Objective C / C++ / C code generation:
|
||||
The modules that use ``importCpp`` or ``importObjc`` are compiled to C++
|
||||
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,
|
||||
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!
|
||||
==============================
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
<h4>Dec 9, 2014</h4>
|
||||
<p>The new website design and forum are now online!</p>
|
||||
</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">
|
||||
<h4>Feb 11, 2014</h4>
|
||||
<p>Nimrod featured in Dr. Dobb's Journal</p>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue