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

This commit is contained in:
Araq 2014-10-11 21:02:08 +02:00
commit 826d529256
26 changed files with 778 additions and 228 deletions

View file

@ -1,6 +1,6 @@
# #
# #
# The Nimrod Compiler # The Nim Compiler
# (c) Copyright 2013 Andreas Rumpf # (c) Copyright 2013 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
@ -291,6 +291,8 @@ const
sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't
# require RC ops # require RC ops
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
const const
# getting ready for the future expr/stmt merge # getting ready for the future expr/stmt merge
@ -476,7 +478,7 @@ type
# and first phase symbol lookup in generics # and first phase symbol lookup in generics
skConditional, # symbol for the preprocessor (may become obsolete) skConditional, # symbol for the preprocessor (may become obsolete)
skDynLib, # symbol represents a dynamic library; this is used skDynLib, # symbol represents a dynamic library; this is used
# internally; it does not exist in Nimrod code # internally; it does not exist in Nim code
skParam, # a parameter skParam, # a parameter
skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()`` skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()``
skTemp, # a temporary variable (introduced by compiler) skTemp, # a temporary variable (introduced by compiler)
@ -501,7 +503,8 @@ type
skStub, # symbol is a stub and not yet loaded from the ROD skStub, # symbol is a stub and not yet loaded from the ROD
# file (it is loaded on demand, which may # file (it is loaded on demand, which may
# mean: never) # mean: never)
skPackage # symbol is a package (used for canonicalization) skPackage, # symbol is a package (used for canonicalization)
skAlias # an alias (needs to be resolved immediately)
TSymKinds* = set[TSymKind] TSymKinds* = set[TSymKind]
const const
@ -678,7 +681,7 @@ type
heapRoot*: PRope # keeps track of the enclosing heap object that heapRoot*: PRope # keeps track of the enclosing heap object that
# owns this location (required by GC algorithms # owns this location (required by GC algorithms
# employing heap snapshots or sliding views) # employing heap snapshots or sliding views)
a*: int # location's "address", i.e. slot for temporaries a*: int
# ---------------- end of backend information ------------------------------ # ---------------- end of backend information ------------------------------
@ -731,8 +734,9 @@ type
# check for the owner when touching 'usedGenerics'. # check for the owner when touching 'usedGenerics'.
usedGenerics*: seq[PInstantiation] usedGenerics*: seq[PInstantiation]
tab*: TStrTable # interface table for modules tab*: TStrTable # interface table for modules
of skLet, skVar, skField:
guard*: PSym
else: nil else: nil
magic*: TMagic magic*: TMagic
typ*: PType typ*: PType
name*: PIdent name*: PIdent
@ -872,7 +876,7 @@ const
tyProc, tyString, tyError} tyProc, tyString, tyError}
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
skIterator, skClosureIterator, skIterator, skClosureIterator,
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
nfDotSetter, nfDotField, nfDotSetter, nfDotField,
nfIsRef} nfIsRef}
@ -1162,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
result.sons = @[name, pattern, genericParams, params, result.sons = @[name, pattern, genericParams, params,
pragmas, exceptions, body] pragmas, exceptions, body]
proc newType(kind: TTypeKind, owner: PSym): PType = proc newType(kind: TTypeKind, owner: PSym): PType =
new(result) new(result)
result.kind = kind result.kind = kind
@ -1172,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
result.id = getID() result.id = getID()
when debugIds: when debugIds:
registerId(result) registerId(result)
#if result.id < 2000 then #if result.id < 2000:
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id)) # messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
proc mergeLoc(a: var TLoc, b: TLoc) = proc mergeLoc(a: var TLoc, b: TLoc) =
if a.k == low(a.k): a.k = b.k if a.k == low(a.k): a.k = b.k
@ -1229,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
result.position = s.position result.position = s.position
result.loc = s.loc result.loc = s.loc
result.annex = s.annex # BUGFIX result.annex = s.annex # BUGFIX
if result.kind in {skVar, skLet, skField}:
result.guard = s.guard
proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
result = newSym(s.kind, newIdent, s.owner, info) result = newSym(s.kind, newIdent, s.owner, info)

View file

@ -171,6 +171,10 @@ proc genSingleVar(p: BProc, a: PNode) =
if sfCompileTime in v.flags: return if sfCompileTime in v.flags: return
var targetProc = p var targetProc = p
if sfGlobal in v.flags: if sfGlobal in v.flags:
if v.flags * {sfImportc, sfExportc} == {sfImportc} and
a.sons[2].kind == nkEmpty and
v.loc.flags * {lfHeader, lfNoDecl} != {}:
return
if sfPure in v.flags: if sfPure in v.flags:
# v.owner.kind != skModule: # v.owner.kind != skModule:
targetProc = p.module.preInitProc targetProc = p.module.preInitProc
@ -828,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
discard cgsym(p.module, "E_Base") discard cgsym(p.module, "E_Base")
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint) linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint) linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint) if isDefined("nimStdSetjmp"):
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
elif isDefined("nimSigSetjmp"):
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
elif isDefined("nimRawSetjmp"):
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
startBlock(p, "if ($1.status == 0) {$n", [safePoint]) startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t) var length = sonsLen(t)
add(p.nestedTryStmts, t) add(p.nestedTryStmts, t)

View file

@ -13,7 +13,7 @@ import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, intsets, options, intsets,
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms,
rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
semparallel semparallel

View file

@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) =
platform.OS[platform.hostOS].name, platform.OS[platform.hostOS].name,
CPU[platform.hostCPU].name])) CPU[platform.hostCPU].name]))
const gitHash = gorge("git log -n 1 --format=%H") discard """const gitHash = gorge("git log -n 1 --format=%H")
if gitHash.strip.len == 40: if gitHash.strip.len == 40:
msgWriteln("git hash: " & gitHash) msgWriteln("git hash: " & gitHash)"""
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine & msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &

View file

@ -1,6 +1,6 @@
# #
# #
# The Nimrod Compiler # The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf # (c) Copyright 2014 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
@ -60,7 +60,7 @@ const
quick quick
release debug release debug
useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
nodejs kwin nodejs kwin nimfix
usesysassert usegcassert tinyC useFFI usesysassert usegcassert tinyC useFFI
useStdoutAsStdmsg createNimRtl useStdoutAsStdmsg createNimRtl
@ -69,6 +69,8 @@ const
reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
debugExecProcesses pcreDll useLipzipSrc debugExecProcesses pcreDll useLipzipSrc
preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
nimStdSetjmp nimRawSetjmp nimSigSetjmp
""".split """.split
proc initDefines*() = proc initDefines*() =
@ -85,6 +87,7 @@ proc initDefines*() =
defineSymbol("nimnewshared") defineSymbol("nimnewshared")
defineSymbol("nimrequiresnimframe") defineSymbol("nimrequiresnimframe")
defineSymbol("nimparsebiggestfloatmagic") defineSymbol("nimparsebiggestfloatmagic")
defineSymbol("nimalias")
# add platform specific symbols: # add platform specific symbols:
for c in low(CPU)..high(CPU): for c in low(CPU)..high(CPU):
@ -136,3 +139,7 @@ proc initDefines*() =
declareSymbol("emulatedthreadvars") declareSymbol("emulatedthreadvars")
if platform.OS[targetOS].props.contains(ospLacksThreadVars): if platform.OS[targetOS].props.contains(ospLacksThreadVars):
defineSymbol("emulatedthreadvars") defineSymbol("emulatedthreadvars")
case targetOS
of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx:
defineSymbol("nimRawSetjmp")
else: discard

View file

@ -1,6 +1,6 @@
# #
# #
# The Nimrod Compiler # The Nim Compiler
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2012 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
@ -11,7 +11,7 @@
import import
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread, intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
renderer, wordrecg, idgen renderer, wordrecg, idgen, nimfix.prettybase
proc ensureNoMissingOrUnusedSymbols(scope: PScope) proc ensureNoMissingOrUnusedSymbols(scope: PScope)
@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent =
template addSym*(scope: PScope, s: PSym) = template addSym*(scope: PScope, s: PSym) =
strTableAdd(scope.symbols, s) strTableAdd(scope.symbols, s)
proc addUniqueSym*(scope: PScope, s: PSym): TResult = proc addUniqueSym*(scope: PScope, s: PSym): bool =
if strTableIncl(scope.symbols, s): result = not strTableIncl(scope.symbols, s)
result = Failure
else:
result = Success
proc openScope*(c: PContext): PScope {.discardable.} = proc openScope*(c: PContext): PScope {.discardable.} =
result = PScope(parent: c.currentScope, result = PScope(parent: c.currentScope,
@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope =
yield current yield current
current = current.parent current = current.parent
proc skipAlias*(s: PSym; n: PNode): PSym =
if s == nil or s.kind != skAlias:
result = s
else:
result = s.owner
if gCmd == cmdPretty:
prettybase.replaceDeprecated(n.info, s, result)
else:
message(n.info, warnDeprecated, "use " & result.name.s & " instead; " &
s.name.s)
proc localSearchInScope*(c: PContext, s: PIdent): PSym = proc localSearchInScope*(c: PContext, s: PIdent): PSym =
result = strTableGet(c.currentScope.symbols, s) result = strTableGet(c.currentScope.symbols, s)
@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) =
localError(info, errAttemptToRedefine, s) localError(info, errAttemptToRedefine, s)
proc addDecl*(c: PContext, sym: PSym) = proc addDecl*(c: PContext, sym: PSym) =
if c.currentScope.addUniqueSym(sym) == Failure: if not c.currentScope.addUniqueSym(sym):
wrongRedefinition(sym.info, sym.name.s) wrongRedefinition(sym.info, sym.name.s)
proc addPrelimDecl*(c: PContext, sym: PSym) = proc addPrelimDecl*(c: PContext, sym: PSym) =
discard c.currentScope.addUniqueSym(sym) discard c.currentScope.addUniqueSym(sym)
proc addDeclAt*(scope: PScope, sym: PSym) = proc addDeclAt*(scope: PScope, sym: PSym) =
if scope.addUniqueSym(sym) == Failure: if not scope.addUniqueSym(sym):
wrongRedefinition(sym.info, sym.name.s) wrongRedefinition(sym.info, sym.name.s)
proc addInterfaceDeclAux(c: PContext, sym: PSym) = proc addInterfaceDeclAux(c: PContext, sym: PSym) =
@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
if fn.kind notin OverloadableSyms: if fn.kind notin OverloadableSyms:
internalError(fn.info, "addOverloadableSymAt") internalError(fn.info, "addOverloadableSymAt")
return return
var check = strTableGet(scope.symbols, fn.name) let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms: if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(fn.info, fn.name.s) wrongRedefinition(fn.info, fn.name.s)
else: else:
@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addOverloadableSymAt(scope, sym) addOverloadableSymAt(scope, sym)
addInterfaceDeclAux(c, sym) addInterfaceDeclAux(c, sym)
when defined(nimfix):
import strutils
# when we cannot find the identifier, retry with a changed identifer:
proc altSpelling(x: PIdent): PIdent =
case x.s[0]
of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
else: result = x
template fixSpelling(n: PNode; ident: PIdent; op: expr) =
let alt = ident.altSpelling
result = op(c, alt).skipAlias(n)
if result != nil:
prettybase.replaceDeprecated(n.info, ident, alt)
return result
else:
template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
proc lookUp*(c: PContext, n: PNode): PSym = proc lookUp*(c: PContext, n: PNode): PSym =
# Looks up a symbol. Generates an error in case of nil. # Looks up a symbol. Generates an error in case of nil.
case n.kind case n.kind
of nkIdent: of nkIdent:
result = searchInScopes(c, n.ident) result = searchInScopes(c, n.ident).skipAlias(n)
if result == nil: if result == nil:
fixSpelling(n, n.ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, n.ident.s) localError(n.info, errUndeclaredIdentifier, n.ident.s)
result = errorSym(c, n) result = errorSym(c, n)
of nkSym: of nkSym:
result = n.sym result = n.sym
of nkAccQuoted: of nkAccQuoted:
var ident = considerQuotedIdent(n) var ident = considerQuotedIdent(n)
result = searchInScopes(c, ident) result = searchInScopes(c, ident).skipAlias(n)
if result == nil: if result == nil:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s) localError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n) result = errorSym(c, n)
else: else:
@ -210,8 +239,9 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
case n.kind case n.kind
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
var ident = considerQuotedIdent(n) var ident = considerQuotedIdent(n)
result = searchInScopes(c, ident) result = searchInScopes(c, ident).skipAlias(n)
if result == nil and checkUndeclared in flags: if result == nil and checkUndeclared in flags:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s) localError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n) result = errorSym(c, n)
elif checkAmbiguity in flags and result != nil and elif checkAmbiguity in flags and result != nil and
@ -224,7 +254,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
of nkDotExpr: of nkDotExpr:
result = nil result = nil
var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared}) var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
if (m != nil) and (m.kind == skModule): if m != nil and m.kind == skModule:
var ident: PIdent = nil var ident: PIdent = nil
if n.sons[1].kind == nkIdent: if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident ident = n.sons[1].ident
@ -232,10 +262,11 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
ident = considerQuotedIdent(n.sons[1]) ident = considerQuotedIdent(n.sons[1])
if ident != nil: if ident != nil:
if m == c.module: if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident) result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n)
else: else:
result = strTableGet(m.tab, ident) result = strTableGet(m.tab, ident).skipAlias(n)
if result == nil and checkUndeclared in flags: if result == nil and checkUndeclared in flags:
fixSpelling(n.sons[1], ident, searchInScopes)
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s) localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n.sons[1]) result = errorSym(c, n.sons[1])
elif n.sons[1].kind == nkSym: elif n.sons[1].kind == nkSym:
@ -256,7 +287,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.scope = c.currentScope o.scope = c.currentScope
o.mode = oimNoQualifier o.mode = oimNoQualifier
while true: while true:
result = initIdentIter(o.it, o.scope.symbols, ident) result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n)
if result != nil: if result != nil:
break break
else: else:
@ -277,10 +308,11 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
if ident != nil: if ident != nil:
if o.m == c.module: if o.m == c.module:
# a module may access its private members: # a module may access its private members:
result = initIdentIter(o.it, c.topLevelScope.symbols, ident) result = initIdentIter(o.it, c.topLevelScope.symbols,
ident).skipAlias(n)
o.mode = oimSelfModule o.mode = oimSelfModule
else: else:
result = initIdentIter(o.it, o.m.tab, ident) result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
else: else:
localError(n.sons[1].info, errIdentifierExpected, localError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1])) renderTree(n.sons[1]))
@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
result = nil result = nil
of oimNoQualifier: of oimNoQualifier:
if o.scope != nil: if o.scope != nil:
result = nextIdentIter(o.it, o.scope.symbols) result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
while result == nil: while result == nil:
o.scope = o.scope.parent o.scope = o.scope.parent
if o.scope == nil: break if o.scope == nil: break
result = initIdentIter(o.it, o.scope.symbols, o.it.name) result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n)
# BUGFIX: o.it.name <-> n.ident # BUGFIX: o.it.name <-> n.ident
else: else:
result = nil result = nil
of oimSelfModule: of oimSelfModule:
result = nextIdentIter(o.it, c.topLevelScope.symbols) result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
of oimOtherModule: of oimOtherModule:
result = nextIdentIter(o.it, o.m.tab) result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
of oimSymChoice: of oimSymChoice:
if o.symChoiceIndex < sonsLen(n): if o.symChoiceIndex < sonsLen(n):
result = n.sons[o.symChoiceIndex].sym result = n.sons[o.symChoiceIndex].sym
@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoiceLocalLookup o.mode = oimSymChoiceLocalLookup
o.scope = c.currentScope o.scope = c.currentScope
result = firstIdentExcluding(o.it, o.scope.symbols, result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice) n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
while result == nil: while result == nil:
o.scope = o.scope.parent o.scope = o.scope.parent
if o.scope == nil: break if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols, result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice) n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
of oimSymChoiceLocalLookup: of oimSymChoiceLocalLookup:
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice) result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n)
while result == nil: while result == nil:
o.scope = o.scope.parent o.scope = o.scope.parent
if o.scope == nil: break if o.scope == nil: break
result = firstIdentExcluding(o.it, o.scope.symbols, result = firstIdentExcluding(o.it, o.scope.symbols,
n.sons[0].sym.name, o.inSymChoice) n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
if result != nil and result.kind == skStub: loadStub(result) if result != nil and result.kind == skStub: loadStub(result)
when false: proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode, flags: TSymFlags = {}): PSym =
flags = {checkUndeclared}): PSym = var o: TOverloadIter
var o: TOverloadIter var a = initOverloadIter(o, c, n)
result = initOverloadIter(o, c, n) while a != nil:
var a = result if a.kind == kind and flags <= a.flags:
while a != nil: return a
if sfImmediate in a.flags: return a a = nextOverloadIter(o, c, n)
a = nextOverloadIter(o, c, n)
if result == nil and checkUndeclared in flags:
localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s)
result = errorSym(c, n)

106
compiler/nimfix/nimfix.nim Normal file
View file

@ -0,0 +1,106 @@
#
#
# The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
import strutils, os, parseopt
import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf,
extccomp, condsyms, lists
const Usage = """
Nimfix - Tool to patch Nim code
Usage:
nimfix [options] projectflie.nim
Options:
--overwriteFiles:on|off overwrite the original nim files.
DEFAULT is ON!
--wholeProject overwrite every processed file.
--checkExtern:on|off style check also extern names
--styleCheck:on|off|auto performs style checking for identifiers
and suggests an alternative spelling;
'auto' corrects the spelling.
In addition, all command line options of Nim are supported.
"""
proc mainCommand =
#msgs.gErrorMax = high(int) # do not stop after first error
registerPass verbosePass
registerPass semPass
gCmd = cmdPretty
appendStr(searchPaths, options.libpath)
if gProjectFull.len != 0:
# current path is always looked first for modules
prependStr(searchPaths, gProjectPath)
compileProject()
pretty.overwriteFiles()
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
var p = parseopt.initOptParser(cmd)
var argsCount = 0
gOnlyMainfile = true
while true:
parseopt.next(p)
case p.kind
of cmdEnd: break
of cmdLongoption, cmdShortOption:
case p.key.normalize
of "overwritefiles":
case p.val.normalize
of "on": gOverWrite = true
of "off": gOverWrite = false
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "checkextern":
case p.val.normalize
of "on": gCheckExtern = true
of "off": gCheckExtern = false
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "stylecheck":
case p.val.normalize
of "off": gStyleCheck = StyleCheck.None
of "on": gStyleCheck = StyleCheck.Warn
of "auto": gStyleCheck = StyleCheck.Auto
else: localError(gCmdLineInfo, errOnOrOffExpected)
of "wholeproject": gOnlyMainfile = false
else:
processSwitch(pass, p)
of cmdArgument:
options.gProjectName = unixToNativePath(p.key)
# if processArgument(pass, p, argsCount): break
proc handleCmdLine() =
if paramCount() == 0:
stdout.writeln(Usage)
else:
processCmdLine(passCmd1, "")
if gProjectName != "":
try:
gProjectFull = canonicalizePath(gProjectName)
except OSError:
gProjectFull = gProjectName
var p = splitFile(gProjectFull)
gProjectPath = p.dir
gProjectName = p.name
else:
gProjectPath = getCurrentDir()
loadConfigs(DefaultConfig) # load all config files
# now process command line arguments again, because some options in the
# command line can overwite the config file's settings
extccomp.initVars()
processCmdLine(passCmd2, "")
mainCommand()
when compileOption("gc", "v2") or compileOption("gc", "refc"):
GC_disableMarkAndSweep()
condsyms.initDefines()
defineSymbol "nimfix"
handleCmdline()

View file

@ -0,0 +1,17 @@
# Special configuration file for the Nim project
# gc:markAndSweep
hint[XDeclaredButNotUsed]:off
path:"$projectPath/../.."
path:"$lib/packages/docutils"
path:"$nim/compiler"
define:useStdoutAsStdmsg
symbol:nimfix
define:nimfix
cs:partial
#define:useNodeIds
define:booting
define:noDocgen

152
compiler/nimfix/pretty.nim Normal file
View file

@ -0,0 +1,152 @@
#
#
# The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module implements the code "prettifier". This is part of the toolchain
## to convert Nim code into a consistent style.
import
strutils, os, options, ast, astalgo, msgs, ropes, idents,
intsets, strtabs, semdata, prettybase
type
StyleCheck* {.pure.} = enum None, Warn, Auto
var
gOverWrite* = true
gStyleCheck*: StyleCheck
gCheckExtern*, gOnlyMainfile*: bool
proc overwriteFiles*() =
let doStrip = options.getConfigVar("pretty.strip").normalize == "on"
for i in 0 .. high(gSourceFiles):
if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and
(not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx):
let newFile = if gOverWrite: gSourceFiles[i].fullpath
else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim")
try:
var f = open(newFile, fmWrite)
for line in gSourceFiles[i].lines:
if doStrip:
f.write line.strip(leading = false, trailing = true)
else:
f.write line
f.write(gSourceFiles[i].newline)
f.close
except IOError:
rawMessage(errCannotOpenFile, newFile)
proc `=~`(s: string, a: openArray[string]): bool =
for x in a:
if s.startsWith(x): return true
proc beautifyName(s: string, k: TSymKind): string =
# minimal set of rules here for transition:
# GC_ is allowed
let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
if allUpper and k in {skConst, skEnumField, skType}: return s
result = newStringOfCap(s.len)
var i = 0
case k
of skType, skGenericParam:
# Types should start with a capital unless builtins like 'int' etc.:
if s =~ ["int", "uint", "cint", "cuint", "clong", "cstring", "string",
"char", "byte", "bool", "openArray", "seq", "array", "void",
"pointer", "float", "csize", "cdouble", "cchar", "cschar",
"cshort", "cu", "nil", "expr", "stmt", "typedesc", "auto", "any",
"range", "openarray", "varargs", "set", "cfloat"
]:
result.add s[i]
else:
result.add toUpper(s[i])
of skConst, skEnumField:
# for 'const' we keep how it's spelt; either upper case or lower case:
result.add s[0]
else:
# as a special rule, don't transform 'L' to 'l'
if s.len == 1 and s[0] == 'L': result.add 'L'
elif '_' in s: result.add(s[i])
else: result.add toLower(s[0])
inc i
while i < s.len:
if s[i] == '_':
if i > 0 and s[i-1] in {'A'..'Z'}:
# don't skip '_' as it's essential for e.g. 'GC_disable'
result.add('_')
inc i
result.add s[i]
else:
inc i
result.add toUpper(s[i])
elif allUpper:
result.add toLower(s[i])
else:
result.add s[i]
inc i
proc replaceInFile(info: TLineInfo; newName: string) =
loadFile(info)
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in prettybase.Letters: dec first
if first < 0: return
if line[first] == '`': inc first
let last = first+identLen(line, first)-1
if differ(line, first, last, newName):
# last-first+1 != newName.len or
var x = line.substr(0, first-1) & newName & line.substr(last+1)
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
gSourceFiles[info.fileIndex].dirty = true
proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) =
let beau = beautifyName(s, k)
if s != beau:
if gStyleCheck == StyleCheck.Auto:
sym.name = getIdent(beau)
replaceInFile(info, beau)
else:
message(info, hintName, beau)
proc styleCheckDefImpl(info: TLineInfo; s: PSym; k: TSymKind) =
# operators stay as they are:
if k in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters: return
if k in {skType, skGenericParam} and sfAnon in s.flags: return
if {sfImportc, sfExportc} * s.flags == {} or gCheckExtern:
checkStyle(info, s.name.s, k, s)
template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) =
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(info, s, k)
template styleCheckDef*(info: TLineInfo; s: PSym) =
styleCheckDef(info, s, s.kind)
template styleCheckDef*(s: PSym) =
styleCheckDef(s.info, s, s.kind)
proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
if info.fileIndex < 0: return
# we simply convert it to what it looks like in the definition
# for consistency
# operators stay as they are:
if s.kind in {skResult, skTemp} or s.name.s[0] notin prettybase.Letters:
return
if s.kind in {skType, skGenericParam} and sfAnon in s.flags: return
let newName = s.name.s
replaceInFile(info, newName)
#if newName == "File": writeStackTrace()
template styleCheckUse*(info: TLineInfo; s: PSym) =
when defined(nimfix):
if gStyleCheck != StyleCheck.None: styleCheckUseImpl(info, s)

View file

@ -0,0 +1,93 @@
#
#
# The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import ast, msgs, strutils, idents, lexbase, streams
from os import splitFile
type
TSourceFile* = object
lines*: seq[string]
dirty*, isNimfixFile*: bool
fullpath*, newline*: string
fileIdx*: int32
var
gSourceFiles*: seq[TSourceFile] = @[]
proc loadFile*(info: TLineInfo) =
let i = info.fileIndex
if i >= gSourceFiles.len:
gSourceFiles.setLen(i+1)
if gSourceFiles[i].lines.isNil:
gSourceFiles[i].fileIdx = info.fileIndex
gSourceFiles[i].lines = @[]
let path = info.toFullPath
gSourceFiles[i].fullpath = path
gSourceFiles[i].isNimfixFile = path.splitFile.ext == ".nimfix"
# we want to die here for IOError:
for line in lines(path):
gSourceFiles[i].lines.add(line)
# extract line ending of the file:
var lex: TBaseLexer
open(lex, newFileStream(path, fmRead))
var pos = lex.bufpos
while true:
case lex.buf[pos]
of '\c':
gSourceFiles[i].newline = "\c\L"
break
of '\L', '\0':
gSourceFiles[i].newline = "\L"
break
else: discard
inc pos
close(lex)
const
Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
proc identLen*(line: string, start: int): int =
while start+result < line.len and line[start+result] in Letters:
inc result
proc differ*(line: string, a, b: int, x: string): bool =
let y = line[a..b]
result = cmpIgnoreStyle(y, x) == 0 and y != x
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) =
loadFile(info)
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
var first = min(info.col.int, line.len)
if first < 0: return
#inc first, skipIgnoreCase(line, "proc ", first)
while first > 0 and line[first-1] in Letters: dec first
if first < 0: return
if line[first] == '`': inc first
let last = first+identLen(line, first)-1
if cmpIgnoreStyle(line[first..last], oldSym.s) == 0:
var x = line.substr(0, first-1) & newSym.s & line.substr(last+1)
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
gSourceFiles[info.fileIndex].dirty = true
#if newSym.s == "File": writeStackTrace()
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
replaceDeprecated(info, oldSym.name, newSym.name)
proc replaceComment*(info: TLineInfo) =
loadFile(info)
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
var first = info.col.int
if line[first] != '#': inc first
var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
gSourceFiles[info.fileIndex].dirty = true

View file

@ -14,7 +14,7 @@ const
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets? MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
VersionMajor* = 0 VersionMajor* = 0
VersionMinor* = 9 VersionMinor* = 9
VersionPatch* = 5 VersionPatch* = 6
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
RodFileVersion* = "1215" # modify this if the rod-format changes! RodFileVersion* = "1215" # modify this if the rod-format changes!

View file

@ -1,6 +1,6 @@
# #
# #
# The Nimrod Compiler # The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf # (c) Copyright 2014 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
@ -24,7 +24,7 @@ const
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge, wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wOverride} wOverride}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas methodPragmas* = procPragmas
@ -36,8 +36,8 @@ const
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect, iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern, wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wUses, wOperator, wGcSafe} wTags, wLocks, wGcSafe}
exprPragmas* = {wLine} exprPragmas* = {wLine, wLocks}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@ -45,27 +45,27 @@ const
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto, wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
wInjectStmt} wInjectStmt, wDeprecated}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame, wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
wRaises, wUses, wTags, wGcSafe} wRaises, wLocks, wTags, wGcSafe}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl, typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow, wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef, wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked, wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe} wBorrow, wGcSafe}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern, fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError} wImportCpp, wImportObjC, wError, wGuard}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl, varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern, wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal, wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl} wGensym, wInject, wCodegenDecl, wGuard}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject} wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
letPragmas* = varPragmas letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
wThread, wRaises, wUses, wTags, wGcSafe} wThread, wRaises, wLocks, wTags, wGcSafe}
allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
@ -128,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) =
incl(s.flags, sfImportc) incl(s.flags, sfImportc)
incl(s.flags, sfInfixCall) incl(s.flags, sfInfixCall)
excl(s.flags, sfForward) excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToCpp)
proc processImportObjC(s: PSym, extname: string) = proc processImportObjC(s: PSym, extname: string) =
setExternName(s, extname) setExternName(s, extname)
incl(s.flags, sfImportc) incl(s.flags, sfImportc)
incl(s.flags, sfNamedParamCall) incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward) excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToObjC)
proc newEmptyStrNode(n: PNode): PNode {.noinline.} = proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
@ -514,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
else: else:
invalidPragma(n) invalidPragma(n)
proc pragmaUses(c: PContext, n: PNode) =
proc processExc(c: PContext, x: PNode): PNode =
if x.kind in {nkAccQuoted, nkIdent, nkSym,
nkOpenSymChoice, nkClosedSymChoice}:
if considerQuotedIdent(x).s == "*":
return newSymNode(ast.anyGlobal)
result = c.semExpr(c, x)
if result.kind != nkSym or sfGlobal notin result.sym.flags:
localError(x.info, "'$1' is not a global variable" % result.renderTree)
result = newSymNode(ast.anyGlobal)
if n.kind == nkExprColonExpr:
let it = n.sons[1]
if it.kind notin {nkCurly, nkBracket}:
n.sons[1] = processExc(c, it)
else:
for i in 0 .. <it.len:
it.sons[i] = processExc(c, it.sons[i])
else:
invalidPragma(n)
proc typeBorrow(sym: PSym, n: PNode) = proc typeBorrow(sym: PSym, n: PNode) =
if n.kind == nkExprColonExpr: if n.kind == nkExprColonExpr:
let it = n.sons[1] let it = n.sons[1]
@ -542,6 +525,45 @@ proc typeBorrow(sym: PSym, n: PNode) =
localError(n.info, "a type can only borrow `.` for now") localError(n.info, "a type can only borrow `.` for now")
incl(sym.typ.flags, tfBorrowDot) incl(sym.typ.flags, tfBorrowDot)
proc markCompilerProc(s: PSym) =
makeExternExport(s, "$1", s.info)
incl(s.flags, sfCompilerProc)
incl(s.flags, sfUsed)
registerCompilerProc(s)
proc deprecatedStmt(c: PContext; pragma: PNode) =
let pragma = pragma[1]
if pragma.kind != nkBracket:
localError(pragma.info, "list of key:value pairs expected"); return
for n in pragma:
if n.kind in {nkExprColonExpr, nkExprEqExpr}:
let dest = qualifiedLookUp(c, n[1])
let src = considerQuotedIdent(n[0])
let alias = newSym(skAlias, src, dest, n[0].info)
incl(alias.flags, sfExported)
if sfCompilerProc in dest.flags: markCompilerProc(alias)
addInterfaceDecl(c, alias)
else:
localError(n.info, "key:value pair expected")
proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
if it.kind != nkExprColonExpr:
invalidPragma(it); return
let n = it[1]
if n.kind == nkSym:
result = n.sym
elif kind == skField:
# First check if the guard is a global variable:
result = qualifiedLookUp(c, n, {})
if result.isNil or result.kind notin {skLet, skVar} or
sfGlobal notin result.flags:
# We return a dummy symbol; later passes over the type will repair it.
# Generic instantiation needs to know about this too. But we're lazy
# and perform the lookup on demand instead.
result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info)
else:
result = qualifiedLookUp(c, n)
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
validPragmas: TSpecialWords): bool = validPragmas: TSpecialWords): bool =
var it = n.sons[i] var it = n.sons[i]
@ -578,10 +600,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
of wAlign: of wAlign:
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
var align = expectIntLit(c, it) var align = expectIntLit(c, it)
if not isPowerOfTwo(align) and align != 0: if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
localError(it.info, errPowerOfTwoExpected) localError(it.info, errPowerOfTwoExpected)
else: else:
sym.typ.align = align sym.typ.align = align.int16
of wSize: of wSize:
if sym.typ == nil: invalidPragma(it) if sym.typ == nil: invalidPragma(it)
var size = expectIntLit(c, it) var size = expectIntLit(c, it)
@ -648,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
processDynLib(c, it, sym) processDynLib(c, it, sym)
of wCompilerproc: of wCompilerproc:
noVal(it) # compilerproc may not get a string! noVal(it) # compilerproc may not get a string!
if sfFromGeneric notin sym.flags: if sfFromGeneric notin sym.flags: markCompilerProc(sym)
makeExternExport(sym, "$1", it.info)
incl(sym.flags, sfCompilerProc)
incl(sym.flags, sfUsed) # suppress all those stupid warnings
registerCompilerProc(sym)
of wProcVar: of wProcVar:
noVal(it) noVal(it)
incl(sym.flags, sfProcvar) incl(sym.flags, sfProcvar)
of wDeprecated: of wDeprecated:
noVal(it) if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
if sym != nil: incl(sym.flags, sfDeprecated) elif sym != nil: incl(sym.flags, sfDeprecated)
else: incl(c.module.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated)
of wVarargs: of wVarargs:
noVal(it) noVal(it)
@ -789,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if sym == nil: invalidPragma(it) if sym == nil: invalidPragma(it)
of wLine: pragmaLine(c, it) of wLine: pragmaLine(c, it)
of wRaises, wTags: pragmaRaisesOrTags(c, it) of wRaises, wTags: pragmaRaisesOrTags(c, it)
of wUses: pragmaUses(c, it) of wGuard:
of wOperator: if sym == nil or sym.kind notin {skVar, skLet, skField}:
if sym == nil: invalidPragma(it) invalidPragma(it)
else: sym.position = expectIntLit(c, it) else:
sym.guard = pragmaGuard(c, it, sym.kind)
of wInjectStmt: of wInjectStmt:
if it.kind != nkExprColonExpr: if it.kind != nkExprColonExpr:
localError(it.info, errExprExpected) localError(it.info, errExprExpected)

View file

@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
var it: TIdentIter var it: TIdentIter
result = initIdentIter(it, scope.symbols, fn.name) result = initIdentIter(it, scope.symbols, fn.name)
while result != nil: while result != nil:
if result.kind in skProcKinds and if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
sameType(result.typ, fn.typ, flags): return case equalParams(result.typ.n, fn.typ.n)
of paramsEqual:
return
of paramsIncompatible:
localError(fn.info, errNotOverloadable, fn.name.s)
return
of paramsNotEqual:
discard
result = nextIdentIter(it, scope.symbols) result = nextIdentIter(it, scope.symbols)

View file

@ -1614,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
initIdTable(bindings) initIdTable(bindings)
bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t) bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
result = c.semGenerateInstance(c, sym, bindings, info) result = c.semGenerateInstance(c, sym, bindings, info)
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
# codegen would fail:
if sfCompilerProc in result.flags:
result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC}
result.loc.r = nil
proc setMs(n: PNode, s: PSym): PNode = proc setMs(n: PNode, s: PSym): PNode =
result = n result = n

View file

@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) =
if n.sons[namePos].kind != nkSym: return if n.sons[namePos].kind != nkSym: return
documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects) documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects)
documentEffect(n, n.sons[pragmasPos], wTags, tagEffects) documentEffect(n, n.sons[pragmasPos], wTags, tagEffects)
documentEffect(n, n.sons[pragmasPos], wUses, usesEffects)
template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {} template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {}
@ -335,10 +334,6 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
tracked.gcUnsafe = true tracked.gcUnsafe = true
when trackGlobals:
let usesSpec = effectSpec(pragma, wUses)
mergeUses(tracked, usesSpec, n)
proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
let n = n.skipConv let n = n.skipConv
if paramType != nil and tfNotNil in paramType.flags and if paramType != nil and tfNotNil in paramType.flags and
@ -641,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) =
if not isNil(tagsSpec): if not isNil(tagsSpec):
checkRaisesSpec(tagsSpec, actual.sons[tagEffects], checkRaisesSpec(tagsSpec, actual.sons[tagEffects],
"can have an unlisted effect: ", hints=off, subtypeRelation) "can have an unlisted effect: ", hints=off, subtypeRelation)
let usesSpec = effectSpec(p, wUses)
if not isNil(usesSpec):
checkRaisesSpec(usesSpec, actual.sons[usesEffects],
"may use an unlisted global variable: ", hints=off, symbolPredicate)
if sfThread in disp.flags and notGcSafe(branch.typ): if sfThread in disp.flags and notGcSafe(branch.typ):
localError(branch.info, "base method is GC-safe, but '$1' is not" % localError(branch.info, "base method is GC-safe, but '$1' is not" %
branch.name.s) branch.name.s)
@ -656,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
let let
raisesSpec = effectSpec(n, wRaises) raisesSpec = effectSpec(n, wRaises)
tagsSpec = effectSpec(n, wTags) tagsSpec = effectSpec(n, wTags)
usesSpec = effectSpec(n, wUses) if not isNil(raisesSpec) or not isNil(tagsSpec):
if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec):
internalAssert effects.len == 0 internalAssert effects.len == 0
newSeq(effects.sons, effectListLen) newSeq(effects.sons, effectListLen)
if not isNil(raisesSpec): if not isNil(raisesSpec):
effects.sons[exceptionEffects] = raisesSpec effects.sons[exceptionEffects] = raisesSpec
if not isNil(tagsSpec): if not isNil(tagsSpec):
effects.sons[tagEffects] = tagsSpec effects.sons[tagEffects] = tagsSpec
if not isNil(usesSpec):
effects.sons[usesEffects] = usesSpec
proc initEffects(effects: PNode; s: PSym; t: var TEffects) = proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
newSeq(effects.sons, effectListLen) newSeq(effects.sons, effectListLen)
@ -710,12 +698,6 @@ proc trackProc*(s: PSym, body: PNode) =
# after the check, use the formal spec: # after the check, use the formal spec:
effects.sons[tagEffects] = tagsSpec effects.sons[tagEffects] = tagsSpec
when trackGlobals:
let usesSpec = effectSpec(p, wUses)
if not isNil(usesSpec):
checkRaisesSpec(usesSpec, t.uses,
"uses an unlisted global variable: ", hints=on, symbolPredicate)
effects.sons[usesEffects] = usesSpec
if optThreadAnalysis in gGlobalOptions: if optThreadAnalysis in gGlobalOptions:
if sfThread in s.flags and t.gcUnsafe: if sfThread in s.flags and t.gcUnsafe:
#localError(s.info, warnGcUnsafe2, s.name.s) #localError(s.info, warnGcUnsafe2, s.name.s)

View file

@ -64,7 +64,7 @@ type
wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt, wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt,
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
wAsmNoStackFrame, wAsmNoStackFrame,
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
wAuto, wBool, wCatch, wChar, wClass, wAuto, wBool, wCatch, wChar, wClass,
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@ -147,7 +147,7 @@ const
"computedgoto", "injectstmt", "computedgoto", "injectstmt",
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
"asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
"guard", "uses", "guard", "locks",
"auto", "bool", "catch", "char", "class", "auto", "bool", "catch", "char", "class",
"const_cast", "default", "delete", "double", "const_cast", "default", "delete", "double",

View file

@ -1421,7 +1421,7 @@ Examples:
proc forEach(c: proc (x: int) {.cdecl.}) = proc forEach(c: proc (x: int) {.cdecl.}) =
... ...
forEach(printItem) # this will NOT work because calling conventions differ forEach(printItem) # this will NOT compile because calling conventions differ
.. code-block:: nimrod .. code-block:: nimrod
@ -5039,6 +5039,27 @@ first implementation to play with a language feature before a nicer syntax
to access the feature becomes available. to access the feature becomes available.
deprecated pragma
-----------------
The deprecated pragma is used to mark a symbol as deprecated:
.. code-block:: nimrod
proc p() {.deprecated.}
var x {.deprecated.}: char
It can also be used as a statement. Then it takes a list of *renamings*. The
upcoming ``nimfix`` tool can automatically update the code and perform these
renamings:
.. code-block:: nimrod
type
File = object
Stream = ref object
{.deprecated: [TFile: File, PStream: Stream].}
noSideEffect pragma noSideEffect pragma
------------------- -------------------
The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side

View file

@ -16,6 +16,11 @@ customize this style sheet.
Andreas Rumpf Andreas Rumpf
*/ */
body {
color: black;
background: white;
}
/* used to remove borders from tables and images */ /* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th { .borderless, table.borderless td, table.borderless th {
border: 0 } border: 0 }

View file

@ -19,6 +19,7 @@ type
EDb* = object of EIO ## exception that is raised if a database error occurs EDb* = object of EIO ## exception that is raised if a database error occurs
TSqlQuery* = distinct string ## an SQL query string TSqlQuery* = distinct string ## an SQL query string
TSqlPrepared* = distinct string ## a identifier for the prepared queries
FDb* = object of FIO ## effect that denotes a database operation FDb* = object of FIO ## effect that denotes a database operation
FReadDb* = object of FDB ## effect that denotes a read operation FReadDb* = object of FDB ## effect that denotes a read operation
@ -33,7 +34,7 @@ proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
## on, later versions will check the string for valid syntax. ## on, later versions will check the string for valid syntax.
result = TSqlQuery(query) result = TSqlQuery(query)
proc dbError(db: TDbConn) {.noreturn.} = proc dbError*(db: TDbConn) {.noreturn.} =
## raises an EDb exception. ## raises an EDb exception.
var e: ref EDb var e: ref EDb
new(e) new(e)
@ -67,28 +68,57 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
proc tryExec*(db: TDbConn, query: TSqlQuery, proc tryExec*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} = args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var arr = allocCStringArray(args)
var res = PQExec(db, q) var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
nil, nil, 0)
deallocCStringArray(arr)
result = PQresultStatus(res) == PGRES_COMMAND_OK result = PQresultStatus(res) == PGRES_COMMAND_OK
PQclear(res) PQclear(res)
proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {. proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
tags: [FReadDB, FWriteDb].} = tags: [FReadDB, FWriteDb].} =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var arr = allocCStringArray(args)
var res = PQExec(db, q) var res = PQexecParams(db, query.string, int32(args.len), nil, arr,
nil, nil, 0)
deallocCStringArray(arr)
if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db) if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
PQclear(res) PQclear(res)
proc exec*(db: TDbConn, stmtName: TSqlPrepared,
args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
var arr = allocCStringArray(args)
var res = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
PQclear(res)
proc newRow(L: int): TRow = proc newRow(L: int): TRow =
newSeq(result, L) newSeq(result, L)
for i in 0..L-1: result[i] = "" for i in 0..L-1: result[i] = ""
proc setupQuery(db: TDbConn, query: TSqlQuery, proc setupQuery(db: TDbConn, query: TSqlQuery,
args: varargs[string]): PPGresult = args: varargs[string]): PPGresult =
var q = dbFormat(query, args) var arr = allocCStringArray(args)
result = PQExec(db, q) result = PQexecParams(db, query.string, int32(args.len), nil, arr,
if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db) nil, nil, 0)
deallocCStringArray(arr)
if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
args: varargs[string]): PPGresult =
var arr = allocCStringArray(args)
result = PQexecPrepared(db, stmtName.string, int32(args.len), arr,
nil, nil, 0)
deallocCStringArray(arr)
if PQResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
nParams: int): TSqlPrepared =
var res = PQprepare(db, stmtName, query.string, int32(nParams), nil)
if PQResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
return TSqlPrepared(stmtName)
proc setRow(res: PPGresult, r: var TRow, line, cols: int32) = proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
for col in 0..cols-1: for col in 0..cols-1:
@ -109,6 +139,17 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
yield result yield result
PQclear(res) PQclear(res)
iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## executes the prepared query and iterates over the result dataset.
var res = setupQuery(db, stmtName, args)
var L = PQnfields(res)
var result = newRow(L)
for i in 0..PQntuples(res)-1:
setRow(res, result, i, L)
yield result
PQclear(res)
proc getRow*(db: TDbConn, query: TSqlQuery, proc getRow*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## retrieves a single row. If the query doesn't return any rows, this proc ## retrieves a single row. If the query doesn't return any rows, this proc
@ -119,6 +160,14 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
setRow(res, result, 0, L) setRow(res, result, 0, L)
PQclear(res) PQclear(res)
proc getRow*(db: TDbConn, stmtName: TSqlPrepared,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
var res = setupQuery(db, stmtName, args)
var L = PQnfields(res)
result = newRow(L)
setRow(res, result, 0, L)
PQclear(res)
proc getAllRows*(db: TDbConn, query: TSqlQuery, proc getAllRows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} = args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
## executes the query and returns the whole result dataset. ## executes the query and returns the whole result dataset.
@ -126,6 +175,13 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
for r in FastRows(db, query, args): for r in FastRows(db, query, args):
result.add(r) result.add(r)
proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared,
args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
## executes the prepared query and returns the whole result dataset.
result = @[]
for r in FastRows(db, stmtName, args):
result.add(r)
iterator rows*(db: TDbConn, query: TSqlQuery, iterator rows*(db: TDbConn, query: TSqlQuery,
args: varargs[string, `$`]): TRow {.tags: [FReadDB].} = args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
## same as `FastRows`, but slower and safe. ## same as `FastRows`, but slower and safe.

View file

@ -19,6 +19,12 @@ when not defined(windows):
when defined(linux): when defined(linux):
import linux import linux
when defined(freebsd) or defined(macosx):
{.emit:"#include <sys/types.h>".}
when defined(openbsd) or defined(netbsd):
{.emit:"#include <sys/param.h>".}
when defined(macosx) or defined(bsd): when defined(macosx) or defined(bsd):
const const
CTL_HW = 6 CTL_HW = 6
@ -26,7 +32,7 @@ when defined(macosx) or defined(bsd):
HW_NCPU = 3 HW_NCPU = 3
proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer, proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
a: var csize, b: pointer, c: int): cint {. a: var csize, b: pointer, c: int): cint {.
importc: "sysctl", header: "<sys/sysctl.h>".} importc: "sysctl", header: "<sys/sysctl.h>".}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## returns the numer of the processors/cores the machine has. ## returns the numer of the processors/cores the machine has.

View file

@ -95,7 +95,7 @@ type
FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]' FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]'
FlowVarBaseObj = object of TObject FlowVarBaseObj = object of TObject
ready, usesCondVar: bool ready, usesCondVar, awaited: bool
cv: CondVar #\ cv: CondVar #\
# for 'awaitAny' support # for 'awaitAny' support
ai: ptr AwaitInfo ai: ptr AwaitInfo
@ -129,8 +129,8 @@ type
proc await*(fv: FlowVarBase) = proc await*(fv: FlowVarBase) =
## waits until the value for the flowVar arrives. Usually it is not necessary ## waits until the value for the flowVar arrives. Usually it is not necessary
## to call this explicitly. ## to call this explicitly.
if fv.usesCondVar: if fv.usesCondVar and not fv.awaited:
fv.usesCondVar = false fv.awaited = true
await(fv.cv) await(fv.cv)
destroyCondVar(fv.cv) destroyCondVar(fv.cv)

View file

@ -1332,10 +1332,10 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
proc rawCreateDir(dir: string) = proc rawCreateDir(dir: string) =
when defined(solaris): when defined(solaris):
if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS: if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST and errno != ENOSYS:
osError(osLastError()) osError(osLastError())
elif defined(unix): elif defined(unix):
if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST: if mkdir(dir, 0o777) != 0'i32 and errno != EEXIST:
osError(osLastError()) osError(osLastError())
else: else:
when useWinUnicode: when useWinUnicode:

View file

@ -78,10 +78,23 @@ when defined(macosx):
else: else:
template SIGBUS: expr = SIGSEGV template SIGBUS: expr = SIGSEGV
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {. when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
header: "<setjmp.h>", importc: "longjmp".} proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
proc c_setjmp(jmpb: C_JmpBuf): cint {. header: "<setjmp.h>", importc: "siglongjmp".}
header: "<setjmp.h>", importc: "setjmp".} template c_setjmp(jmpb: C_JmpBuf): cint =
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
header: "<setjmp.h>", importc: "sigsetjmp".}
c_sigsetjmp(jmpb, 0)
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "_longjmp".}
proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "_setjmp".}
else:
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "longjmp".}
proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "setjmp".}
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".} importc: "signal", header: "<signal.h>".}

View file

@ -131,6 +131,14 @@ when defined(boehmgc):
if result == nil: raiseOutOfMem() if result == nil: raiseOutOfMem()
proc deallocShared(p: pointer) = boehmDealloc(p) proc deallocShared(p: pointer) = boehmDealloc(p)
when hasThreadSupport:
proc getFreeSharedMem(): int =
boehmGetFreeBytes()
proc getTotalSharedMem(): int =
boehmGetHeapSize()
proc getOccupiedSharedMem(): int =
getTotalSharedMem() - getFreeSharedMem()
#boehmGCincremental() #boehmGCincremental()
proc GC_disable() = boehmGC_disable() proc GC_disable() = boehmGC_disable()
@ -164,11 +172,11 @@ when defined(boehmgc):
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
type type
@ -180,7 +188,7 @@ when defined(boehmgc):
proc alloc0(r: var TMemRegion, size: int): pointer = proc alloc0(r: var TMemRegion, size: int): pointer =
result = alloc(size) result = alloc(size)
zeroMem(result, size) zeroMem(result, size)
proc dealloc(r: var TMemRegion, p: Pointer) = boehmDealloc(p) proc dealloc(r: var TMemRegion, p: pointer) = boehmDealloc(p)
proc deallocOsPages(r: var TMemRegion) {.inline.} = discard proc deallocOsPages(r: var TMemRegion) {.inline.} = discard
proc deallocOsPages() {.inline.} = discard proc deallocOsPages() {.inline.} = discard
@ -239,11 +247,11 @@ elif defined(nogc) and defined(useMalloc):
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
type type
@ -292,11 +300,11 @@ elif defined(nogc):
proc nimGCref(p: pointer) {.compilerproc, inline.} = discard proc nimGCref(p: pointer) {.compilerproc, inline.} = discard
proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard proc nimGCunref(p: pointer) {.compilerproc, inline.} = discard
proc unsureAsgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRef(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
proc asgnRefNoCycle(dest: ppointer, src: pointer) {.compilerproc, inline.} = proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline.} =
dest[] = src dest[] = src
var allocator {.rtlThreadVar.}: TMemRegion var allocator {.rtlThreadVar.}: TMemRegion

View file

@ -213,6 +213,8 @@ proc PQexecParams*(conn: PPGconn, command: cstring, nParams: int32,
paramTypes: POid, paramValues: cstringArray, paramTypes: POid, paramValues: cstringArray,
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{. paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
cdecl, dynlib: dllName, importc: "PQexecParams".} cdecl, dynlib: dllName, importc: "PQexecParams".}
proc PQprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32, proc PQexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
paramValues: cstringArray, paramValues: cstringArray,
paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{. paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.

View file

@ -2,51 +2,58 @@
News News
==== ====
.. 2014-10-11 Version 0.9.6 released
2014-06-29 Version 0.9.6 released =================================
=================================
Changes affecting backwards compatibility **Note: This is the last release of Nimrod. The language has been renamed to
----------------------------------------- Nim. Nim slightly breaks compatibility.**
- ``spawn`` now uses an elaborate self-adapting thread pool and as such This is a maintenance release. The upcoming 0.10.0 release has all
has been moved into its own module. So to use it, you now have to import the new features and exciting developments.
``threadpool``.
- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
now considered for implicit early binding.
- ``c2nim`` moved into its own repository and is now a Babel package.
- ``pas2nim`` moved into its own repository and is now a Babel package.
- ``system.$`` for floating point types now produces a human friendly string
representation.
- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
of the new ``TUri`` type in the ``uri`` module.
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
instead. The destructor's name has to be ``destroy`` now.
- ``lambda`` is not a keyword anymore.
- **system.defined has been split into system.defined and system.declared**.
You have to use ``--symbol`` to declare new conditional symbols that can be
set via ``--define``.
- ``--threadanalysis:on`` is now the default. To make your program compile
you can disable it but this is only a temporary solution as this option
will disappear soon!
Language Additions Changes affecting backwards compatibility
------------------ -----------------------------------------
- There is a new ``parallel`` statement for safe fork&join parallel computing. - ``spawn`` now uses an elaborate self-adapting thread pool and as such
has been moved into its own module. So to use it, you now have to import
``threadpool``.
- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
now considered for implicit early binding.
- ``c2nim`` moved into its own repository and is now a Babel package.
- ``pas2nim`` moved into its own repository and is now a Babel package.
- ``system.$`` for floating point types now produces a human friendly string
representation.
- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
of the new ``TUri`` type in the ``uri`` module.
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
instead. The destructor's name has to be ``destroy`` now.
- ``lambda`` is not a keyword anymore.
- **system.defined has been split into system.defined and system.declared**.
You have to use ``--symbol`` to declare new conditional symbols that can be
set via ``--define``.
- ``--threadanalysis:on`` is now the default. To make your program compile
you can disable it but this is only a temporary solution as this option
will disappear soon!
Library Additions Language Additions
----------------- ------------------
- Added module ``cpuinfo``. - This version introduces the new ``deprecated`` pragma statement that is used
- Added module ``threadpool``. to handle the upcoming massive amount of symbol renames.
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
- Added ``algorithm.reversed``
- Added ``uri.combine`` and ``uri.parseUri``. Library Additions
- Some sockets procedures now support a ``SafeDisconn`` flag which causes -----------------
them to handle disconnection errors and not raise them.
- Added module ``cpuinfo``.
- Added module ``threadpool``.
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
- Added ``algorithm.reversed``
- Added ``uri.combine`` and ``uri.parseUri``.
- Some sockets procedures now support a ``SafeDisconn`` flag which causes
them to handle disconnection errors and not raise them.
2014-04-21 Version 0.9.4 released 2014-04-21 Version 0.9.4 released