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

This commit is contained in:
Milos Negovanovic 2014-10-21 15:29:25 +01:00
commit f5cd0a63ad
45 changed files with 1445 additions and 437 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

@ -832,6 +832,13 @@ 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)
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) 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)

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 &
@ -393,7 +393,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
of "threads": processOnOffSwitchG({optThreads}, arg, pass, info) of "threads":
processOnOffSwitchG({optThreads}, arg, pass, info)
if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe)
of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info) of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info)
of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info) of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info)
of "implicitstatic": of "implicitstatic":

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

@ -383,6 +383,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
var seeSrcRope: PRope = nil var seeSrcRope: PRope = nil
let docItemSeeSrc = getConfigVar("doc.item.seesrc") let docItemSeeSrc = getConfigVar("doc.item.seesrc")
if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0: if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0:
# XXX toFilename doesn't really work. We need to ensure that this keeps
# returning a relative path.
let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl, let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl,
["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)]) ["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)])
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc, dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,

View file

@ -159,6 +159,8 @@ proc myImportModule(c: PContext, n: PNode): PSym =
var f = checkModuleName(n) var f = checkModuleName(n)
if f != InvalidFileIDX: if f != InvalidFileIDX:
result = importModuleAs(n, gImportModule(c.module, f)) result = importModuleAs(n, gImportModule(c.module, f))
if result.info.fileIndex == n.info.fileIndex:
localError(n.info, errGenerated, "A module cannot import itself")
if sfDeprecated in result.flags: if sfDeprecated in result.flags:
message(n.info, warnDeprecated, result.name.s) message(n.info, warnDeprecated, result.name.s)

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
result = initOverloadIter(o, c, n) var a = initOverloadIter(o, c, n)
var a = result
while a != nil: while a != nil:
if sfImmediate in a.flags: return a if a.kind == kind and flags <= 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

@ -1,3 +1,6 @@
; This config file holds configuration information about the Nim compiler
; and project.
[Project] [Project]
Name: "Nimrod" Name: "Nimrod"
Version: "$version" Version: "$version"
@ -34,11 +37,11 @@ Files: "config/nimdoc.cfg"
Files: "config/nimdoc.tex.cfg" Files: "config/nimdoc.tex.cfg"
[Documentation] [Documentation]
Files: "doc/*.txt" ; Files: "doc/*.html"
Files: "doc/*.html" ; Files: "doc/*.cfg"
Files: "doc/*.cfg" ; Files: "doc/*.pdf"
Files: "doc/*.pdf" ; Files: "doc/*.ini"
Files: "doc/*.ini" Files: "doc/overview.html"
Start: "doc/overview.html" Start: "doc/overview.html"
@ -61,13 +64,9 @@ Files: "compiler/readme.txt"
Files: "compiler/nimrod.ini" Files: "compiler/nimrod.ini"
Files: "compiler/nimrod.cfg" Files: "compiler/nimrod.cfg"
Files: "compiler/*.nim" Files: "compiler/*.nim"
Files: "compiler/c2nim/*.nim" Files: "doc/*.txt"
Files: "compiler/c2nim/*.cfg" Files: "compiler/nimfix/*.nim"
Files: "compiler/pas2nim/*.nim" Files: "compiler/nimfix/*.cfg"
Files: "compiler/pas2nim/*.cfg"
Files: "build/empty.txt"
Files: "bin/empty.txt"
[Lib] [Lib]
@ -115,17 +114,22 @@ Files: "examples/*.tmpl"
[Windows] [Windows]
Files: "bin/nimrod.exe" Files: "bin/nimrod.exe"
Files: "bin/nimrod_debug.exe"
Files: "bin/c2nim.exe" Files: "bin/c2nim.exe"
Files: "bin/niminst.exe" Files: "bin/niminst.exe"
Files: "bin/nimgrep.exe" Files: "bin/nimgrep.exe"
Files: "dist/*.dll" Files: "dist/*.dll"
Files: "koch.exe" Files: "koch.exe"
Files: "dist/mingw" ; Files: "dist/mingw"
Files: "start.bat" Files: "start.bat"
BinPath: r"bin;dist\mingw\bin;dist" BinPath: r"bin;dist\mingw\bin;dist"
InnoSetup: "Yes"
; 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"
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
[UnixBin] [UnixBin]
Files: "bin/nimrod" Files: "bin/nimrod"
@ -140,6 +144,9 @@ UninstallScript: "yes"
path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe" path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe"
flags = "/Q" flags = "/Q"
[NSIS]
path = r"c:\Program Files (x86)\NSIS\makensis.exe"
flags = "/V0"
[C_Compiler] [C_Compiler]
path = r"" path = r""

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

@ -41,7 +41,6 @@ doc.item = """
<dt id="$itemSym"><a name="$itemSymOrID"></a><pre>$header</pre></dt> <dt id="$itemSym"><a name="$itemSymOrID"></a><pre>$header</pre></dt>
<dd> <dd>
$desc $desc
$seeSrc
</dd> </dd>
""" """
@ -93,6 +92,11 @@ doc.file = """<?xml version="1.0" encoding="utf-8" ?>
<title>$title</title> <title>$title</title>
<style type="text/css"> <style type="text/css">
body {
color: black;
background: white;
}
span.DecNumber {color: blue} span.DecNumber {color: blue}
span.BinNumber {color: blue} span.BinNumber {color: blue}
span.HexNumber {color: blue} span.HexNumber {color: blue}

View file

@ -130,10 +130,5 @@ vcc.options.always = "/nologo"
vcc.options.speed = "/Ox /arch:SSE2" vcc.options.speed = "/Ox /arch:SSE2"
vcc.options.size = "/O1" vcc.options.size = "/O1"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"$nimrod\dist\dm\bin"
@end
# Configuration for the Tiny C Compiler: # Configuration for the Tiny C Compiler:
tcc.options.always = "-w" tcc.options.always = "-w"

View file

@ -1,7 +1,7 @@
=============================================================================== =====================================================
Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/ Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/
Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved. Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -35,3 +35,5 @@ Options:
-r, --run run the compiled program with given arguments -r, --run run the compiled program with given arguments
--advanced show advanced command line switches --advanced show advanced command line switches
-h, --help show this help -h, --help show this help
Note: Even single letter options require the colon: -p:PATH.

View file

@ -4384,6 +4384,8 @@ helper distinct or object type has to be used for one pointer type.
operator `=` operator `=`
------------ ------------
**Note**: Overriding the assignment operator has not yet been implemented.
This operator is the assignment operator. Note that in the contexts This operator is the assignment operator. Note that in the contexts
like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for
parameter passing no assignment is performed. The ``override`` pragma is parameter passing no assignment is performed. The ``override`` pragma is
@ -5039,6 +5041,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

@ -438,18 +438,6 @@ module. Example:
echo "Got exception ", repr(e), " with message ", msg echo "Got exception ", repr(e), " with message ", msg
Exception hierarchy
-------------------
If you want to create your own exceptions you can inherit from E_Base, but you
can also inherit from one of the existing exceptions if they fit your purpose.
The exception tree is:
.. include:: exception_hierarchy_fragment.txt
See the `system <system.html>`_ module for a description of each exception.
Annotating procs with raised exceptions Annotating procs with raised exceptions
--------------------------------------- ---------------------------------------

View file

@ -58,8 +58,6 @@ Currently, the following C compilers are supported under Windows:
| http://www.mingw.org/download.shtml | http://www.mingw.org/download.shtml
- | LLVM with Clang or GNU C/C++ frontend - | LLVM with Clang or GNU C/C++ frontend
| http://llvm.org/releases/download.html | http://llvm.org/releases/download.html
- | Digital Mars C++
| http://www.digitalmars.com/download/freecompiler.html
However, most testing is done with GCC. However, most testing is done with GCC.

View file

@ -43,7 +43,7 @@ Possible Commands:
web generates the website web generates the website
csource [options] builds the C sources for installation csource [options] builds the C sources for installation
zip builds the installation ZIP package zip builds the installation ZIP package
inno [options] builds the Inno Setup installer (for Windows) nsis [options] builds the NSIS Setup installer (for Windows)
tests [options] run the testsuite tests [options] run the testsuite
update updates nimrod to the latest version from github update updates nimrod to the latest version from github
(compile koch with -d:withUpdate to enable) (compile koch with -d:withUpdate to enable)
@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool =
echo(cmd) echo(cmd)
result = execShellCmd(cmd) == 0 result = execShellCmd(cmd) == 0
proc safeRemove(filename: string) =
if existsFile(filename): removeFile(filename)
proc copyExe(source, dest: string) =
safeRemove(dest)
copyFile(dest=dest, source=source)
inclFilePermissions(dest, {fpUserExec})
const const
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst" compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
@ -85,22 +93,27 @@ proc csource(args: string) =
[args, NimrodVersion, compileNimInst, findNim()]) [args, NimrodVersion, compileNimInst, findNim()])
proc zip(args: string) = proc zip(args: string) =
exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" % exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" %
[NimrodVersion, compileNimInst, findNim()]) [NimrodVersion, compileNimInst, findNim()])
exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" %
["tools/niminst/niminst".exe, NimrodVersion])
proc buildTool(toolname, args: string) = proc buildTool(toolname, args: string) =
exec("$# cc $# $#" % [findNim(), args, toolname]) exec("$# cc $# $#" % [findNim(), args, toolname])
copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe) copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
proc inno(args: string) = proc nsis(args: string) =
# make sure we have generated the niminst executables: # make sure we have generated the niminst executables:
buildTool("tools/niminst/niminst", args) buildTool("tools/niminst/niminst", args)
buildTool("tools/nimgrep", args) buildTool("tools/nimgrep", args)
exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" % # produce 'nimrod_debug.exe':
NimrodVersion) exec "nimrod c compiler" / "nimrod.nim"
copyExe("compiler/nimrod".exe, "bin/nimrod_debug".exe)
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" &
" nsis compiler/nimrod") % NimrodVersion)
proc install(args: string) = proc install(args: string) =
exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" % exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nimrod.ini" %
[findNim(), compileNimInst, NimrodVersion]) [findNim(), compileNimInst, NimrodVersion])
exec("sh ./install.sh $#" % args) exec("sh ./install.sh $#" % args)
@ -135,17 +148,9 @@ proc findStartNimrod: string =
echo("Found no nimrod compiler and every attempt to build one failed!") echo("Found no nimrod compiler and every attempt to build one failed!")
quit("FAILURE") quit("FAILURE")
proc safeRemove(filename: string) =
if existsFile(filename): removeFile(filename)
proc thVersion(i: int): string = proc thVersion(i: int): string =
result = ("compiler" / "nimrod" & $i).exe result = ("compiler" / "nimrod" & $i).exe
proc copyExe(source, dest: string) =
safeRemove(dest)
copyFile(dest=dest, source=source)
inclFilePermissions(dest, {fpUserExec})
proc boot(args: string) = proc boot(args: string) =
var output = "compiler" / "nimrod".exe var output = "compiler" / "nimrod".exe
var finalDest = "bin" / "nimrod".exe var finalDest = "bin" / "nimrod".exe
@ -302,7 +307,7 @@ of cmdArgument:
of "web": web(op.cmdLineRest) of "web": web(op.cmdLineRest)
of "csource", "csources": csource(op.cmdLineRest) of "csource", "csources": csource(op.cmdLineRest)
of "zip": zip(op.cmdLineRest) of "zip": zip(op.cmdLineRest)
of "inno": inno(op.cmdLineRest) of "nsis": nsis(op.cmdLineRest)
of "install": install(op.cmdLineRest) of "install": install(op.cmdLineRest)
of "test", "tests": tests(op.cmdLineRest) of "test", "tests": tests(op.cmdLineRest)
of "update": of "update":

View file

@ -56,6 +56,8 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
## Adds the file `src` to the archive `z` with the name `dest`. `dest` ## Adds the file `src` to the archive `z` with the name `dest`. `dest`
## may contain a path that will be created. ## may contain a path that will be created.
assert(z.mode != fmRead) assert(z.mode != fmRead)
if not fileExists(src):
raise newException(EIO, "File '" & src & "' does not exist")
var zipsrc = zip_source_file(z.w, src, 0, -1) var zipsrc = zip_source_file(z.w, src, 0, -1)
if zipsrc == nil: if zipsrc == nil:
#echo("Dest: " & dest) #echo("Dest: " & dest)

View file

@ -19,14 +19,23 @@ 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):
# we HAVE to emit param.h before sysctl.h so we cannot use .header here
# either. The amount of archaic bullshit in Poonix based OSes is just insane.
{.emit:"#include <sys/sysctl.h>".}
const const
CTL_HW = 6 CTL_HW = 6
HW_AVAILCPU = 25 HW_AVAILCPU = 25
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", nodecl.}
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

@ -78,6 +78,19 @@ when defined(macosx):
else: else:
template SIGBUS: expr = SIGSEGV template SIGBUS: expr = SIGSEGV
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "siglongjmp".}
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) {. proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
header: "<setjmp.h>", importc: "longjmp".} header: "<setjmp.h>", importc: "longjmp".}
proc c_setjmp(jmpb: C_JmpBuf): cint {. proc c_setjmp(jmpb: C_JmpBuf): cint {.

View file

@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
llRecv(q, addr(result), cast[PNimType](getTypeInfo(result))) llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))
releaseSys(q.lock) releaseSys(q.lock)
proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool, proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
msg: TMsg] = msg: TMsg] =
## try to receives a message from the channel `c` if available. Otherwise ## try to receives a message from the channel `c` if available. Otherwise
## it returns ``(false, default(msg))``. ## it returns ``(false, default(msg))``.
var q = cast[PRawChannel](addr(c)) var q = cast[PRawChannel](addr(c))
if q.mask != ChannelDeadMask: if q.mask != ChannelDeadMask:
lockChannel(q): if tryAcquireSys(q.lock):
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
result.dataAvaliable = true result.dataAvailable = true
releaseSys(q.lock)
proc peek*[TMsg](c: var TChannel[TMsg]): int = proc peek*[TMsg](c: var TChannel[TMsg]): int =
## returns the current number of messages in the channel `c`. Returns -1 ## returns the current number of messages in the channel `c`. Returns -1

View file

@ -62,5 +62,5 @@ allowing you to create commercial applications.
Read copying.txt for more details. Read copying.txt for more details.
Copyright (c) 2004-2014 Andreas Rumpf. Copyright (c) 2006-2014 Andreas Rumpf.
All rights reserved. All rights reserved.

View file

@ -1,60 +1,12 @@
# Nimrod Compiler This package contains the Nimrod compiler, Nimrod's stdlib, tools and
This repo contains the Nimrod compiler, Nimrod's stdlib, tools and
documentation. documentation.
## Compiling Nimrod is a compiled, garbage-collected systems programming language which has
Compiling the Nimrod compiler is quite straightforward. Because an excellent productivity/performance ratio. Nimrod's design focuses on
the Nimrod compiler itself is written in the Nimrod programming language efficiency, expressiveness, elegance (in the order of priority).
the C source of an older version of the compiler are needed to bootstrap the
latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources).
Pre-compiled snapshots of the compiler are also available on Read install.txt for instructions of how to build and install it.
[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not
currently be built for.
The compiler currently supports the following platform and architecture
combinations:
* Windows (Windows XP or greater) - x86 and x86_64
* Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
* Mac OS X 10.04 or higher - x86, x86_64 and ppc64
In reality a lot more are supported, however they are not tested regularly.
To build from source you will need:
* gcc 3.x or later recommended. Other alternatives which may work
are: clang, Visual C++, Intel's C++ compiler
* git or wget
If you are on a fairly modern *nix system, the following steps should work:
```
$ git clone git://github.com/Araq/Nimrod.git
$ cd Nimrod
$ git clone --depth 1 git://github.com/nimrod-code/csources
$ cd csources && ./build.sh
$ cd ..
$ bin/nimrod c koch
$ ./koch boot -d:release
```
``koch install [dir]`` may then be used to install Nimrod, or you can simply
add it to your PATH. More ``koch`` related options are documented in
[doc/koch.txt](doc/koch.txt).
The above steps can be performed on Windows in a similar fashion, the
``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
instead of ``build.sh``.
## Getting help
A [forum](http://forum.nimrod-lang.org/) is available if you have any
questions, and you can also get help in the IRC channel on
[Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on
[StackOverflow use the nimrod
tag](http://stackoverflow.com/questions/tagged/nimrod).
## License
The compiler and the standard library are licensed under the MIT license, The compiler and the standard library are licensed under the MIT license,
except for some modules where the documentation suggests otherwise. This means except for some modules where the documentation suggests otherwise. This means
that you can use any license for your own programs developed with Nimrod, that you can use any license for your own programs developed with Nimrod,
@ -62,5 +14,5 @@ allowing you to create commercial applications.
Read copying.txt for more details. Read copying.txt for more details.
Copyright (c) 2004-2014 Andreas Rumpf. Copyright (c) 2006-2014 Andreas Rumpf.
All rights reserved. All rights reserved.

View file

@ -0,0 +1,8 @@
discard """
file: "tselfimport.nim"
line: 6
errormsg: "A module cannot import itself"
"""
import tselfimport #ERROR
echo("Hello World")

View file

@ -0,0 +1,346 @@
/**
* EnvVarUpdate.nsh
* : Environmental Variables: append, prepend, and remove entries
*
* WARNING: If you use StrFunc.nsh header then include it before this file
* with all required definitions. This is to avoid conflicts
*
* Usage:
* ${EnvVarUpdate} "ResultVar" "EnvVarName" "Action" "RegLoc" "PathString"
*
* Credits:
* Version 1.0
* * Cal Turney (turnec2)
* * Amir Szekely (KiCHiK) and e-circ for developing the forerunners of this
* function: AddToPath, un.RemoveFromPath, AddToEnvVar, un.RemoveFromEnvVar,
* WriteEnvStr, and un.DeleteEnvStr
* * Diego Pedroso (deguix) for StrTok
* * Kevin English (kenglish_hi) for StrContains
* * Hendri Adriaens (Smile2Me), Diego Pedroso (deguix), and Dan Fuhry
* (dandaman32) for StrReplace
*
* Version 1.1 (compatibility with StrFunc.nsh)
* * techtonik
*
* http://nsis.sourceforge.net/Environmental_Variables:_append%2C_prepend%2C_and_remove_entries
*
*/
!ifndef ENVVARUPDATE_FUNCTION
!define ENVVARUPDATE_FUNCTION
!verbose push
!verbose 3
!include "LogicLib.nsh"
!include "WinMessages.NSH"
!include "StrFunc.nsh"
; ---- Fix for conflict if StrFunc.nsh is already includes in main file -----------------------
!macro _IncludeStrFunction StrFuncName
!ifndef ${StrFuncName}_INCLUDED
${${StrFuncName}}
!endif
!ifndef Un${StrFuncName}_INCLUDED
${Un${StrFuncName}}
!endif
!define un.${StrFuncName} "${Un${StrFuncName}}"
!macroend
!insertmacro _IncludeStrFunction StrTok
!insertmacro _IncludeStrFunction StrStr
!insertmacro _IncludeStrFunction StrRep
; ---------------------------------- Macro Definitions ----------------------------------------
!macro _EnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
Push "${EnvVarName}"
Push "${Action}"
Push "${RegLoc}"
Push "${PathString}"
Call EnvVarUpdate
Pop "${ResultVar}"
!macroend
!define EnvVarUpdate '!insertmacro "_EnvVarUpdateConstructor"'
!macro _unEnvVarUpdateConstructor ResultVar EnvVarName Action Regloc PathString
Push "${EnvVarName}"
Push "${Action}"
Push "${RegLoc}"
Push "${PathString}"
Call un.EnvVarUpdate
Pop "${ResultVar}"
!macroend
!define un.EnvVarUpdate '!insertmacro "_unEnvVarUpdateConstructor"'
; ---------------------------------- Macro Definitions end-------------------------------------
;----------------------------------- EnvVarUpdate start----------------------------------------
!define hklm_all_users 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
!define hkcu_current_user 'HKCU "Environment"'
!macro EnvVarUpdate UN
Function ${UN}EnvVarUpdate
Push $0
Exch 4
Exch $1
Exch 3
Exch $2
Exch 2
Exch $3
Exch
Exch $4
Push $5
Push $6
Push $7
Push $8
Push $9
Push $R0
/* After this point:
-------------------------
$0 = ResultVar (returned)
$1 = EnvVarName (input)
$2 = Action (input)
$3 = RegLoc (input)
$4 = PathString (input)
$5 = Orig EnvVar (read from registry)
$6 = Len of $0 (temp)
$7 = tempstr1 (temp)
$8 = Entry counter (temp)
$9 = tempstr2 (temp)
$R0 = tempChar (temp) */
; Step 1: Read contents of EnvVarName from RegLoc
;
; Check for empty EnvVarName
${If} $1 == ""
SetErrors
DetailPrint "ERROR: EnvVarName is blank"
Goto EnvVarUpdate_Restore_Vars
${EndIf}
; Check for valid Action
${If} $2 != "A"
${AndIf} $2 != "P"
${AndIf} $2 != "R"
SetErrors
DetailPrint "ERROR: Invalid Action - must be A, P, or R"
Goto EnvVarUpdate_Restore_Vars
${EndIf}
${If} $3 == HKLM
ReadRegStr $5 ${hklm_all_users} $1 ; Get EnvVarName from all users into $5
${ElseIf} $3 == HKCU
ReadRegStr $5 ${hkcu_current_user} $1 ; Read EnvVarName from current user into $5
${Else}
SetErrors
DetailPrint 'ERROR: Action is [$3] but must be "HKLM" or HKCU"'
Goto EnvVarUpdate_Restore_Vars
${EndIf}
; Check for empty PathString
${If} $4 == ""
SetErrors
DetailPrint "ERROR: PathString is blank"
Goto EnvVarUpdate_Restore_Vars
${EndIf}
Push $6
Push $7
Push $8
StrLen $7 $4
StrLen $6 $5
IntOp $8 $6 + $7
${If} $5 == ""
${OrIf} $8 >= ${NSIS_MAX_STRLEN}
SetErrors
DetailPrint "Current $1 length ($6) too long to modify in NSIS; set manually if needed"
Pop $8
Pop $7
Pop $6
Goto EnvVarUpdate_Restore_Vars
${EndIf}
Pop $8
Pop $7
Pop $6
; Make sure we've got some work to do
${If} $5 == ""
${AndIf} $2 == "R"
SetErrors
DetailPrint "$1 is empty - Nothing to remove"
Goto EnvVarUpdate_Restore_Vars
${EndIf}
; Step 2: Scrub EnvVar
;
StrCpy $0 $5 ; Copy the contents to $0
; Remove spaces around semicolons (NOTE: spaces before the 1st entry or
; after the last one are not removed here but instead in Step 3)
${If} $0 != "" ; If EnvVar is not empty ...
${Do}
${${UN}StrStr} $7 $0 " ;"
${If} $7 == ""
${ExitDo}
${EndIf}
${${UN}StrRep} $0 $0 " ;" ";" ; Remove '<space>;'
${Loop}
${Do}
${${UN}StrStr} $7 $0 "; "
${If} $7 == ""
${ExitDo}
${EndIf}
${${UN}StrRep} $0 $0 "; " ";" ; Remove ';<space>'
${Loop}
${Do}
${${UN}StrStr} $7 $0 ";;"
${If} $7 == ""
${ExitDo}
${EndIf}
${${UN}StrRep} $0 $0 ";;" ";"
${Loop}
; Remove a leading or trailing semicolon from EnvVar
StrCpy $7 $0 1 0
${If} $7 == ";"
StrCpy $0 $0 "" 1 ; Change ';<EnvVar>' to '<EnvVar>'
${EndIf}
StrLen $6 $0
IntOp $6 $6 - 1
StrCpy $7 $0 1 $6
${If} $7 == ";"
StrCpy $0 $0 $6 ; Change ';<EnvVar>' to '<EnvVar>'
${EndIf}
; DetailPrint "Scrubbed $1: [$0]" ; Uncomment to debug
${EndIf}
/* Step 3. Remove all instances of the target path/string (even if "A" or "P")
$6 = bool flag (1 = found and removed PathString)
$7 = a string (e.g. path) delimited by semicolon(s)
$8 = entry counter starting at 0
$9 = copy of $0
$R0 = tempChar */
${If} $5 != "" ; If EnvVar is not empty ...
StrCpy $9 $0
StrCpy $0 ""
StrCpy $8 0
StrCpy $6 0
${Do}
${${UN}StrTok} $7 $9 ";" $8 "0" ; $7 = next entry, $8 = entry counter
${If} $7 == "" ; If we've run out of entries,
${ExitDo} ; were done
${EndIf} ;
; Remove leading and trailing spaces from this entry (critical step for Action=Remove)
${Do}
StrCpy $R0 $7 1
${If} $R0 != " "
${ExitDo}
${EndIf}
StrCpy $7 $7 "" 1 ; Remove leading space
${Loop}
${Do}
StrCpy $R0 $7 1 -1
${If} $R0 != " "
${ExitDo}
${EndIf}
StrCpy $7 $7 -1 ; Remove trailing space
${Loop}
${If} $7 == $4 ; If string matches, remove it by not appending it
StrCpy $6 1 ; Set 'found' flag
${ElseIf} $7 != $4 ; If string does NOT match
${AndIf} $0 == "" ; and the 1st string being added to $0,
StrCpy $0 $7 ; copy it to $0 without a prepended semicolon
${ElseIf} $7 != $4 ; If string does NOT match
${AndIf} $0 != "" ; and this is NOT the 1st string to be added to $0,
StrCpy $0 $0;$7 ; append path to $0 with a prepended semicolon
${EndIf} ;
IntOp $8 $8 + 1 ; Bump counter
${Loop} ; Check for duplicates until we run out of paths
${EndIf}
; Step 4: Perform the requested Action
;
${If} $2 != "R" ; If Append or Prepend
${If} $6 == 1 ; And if we found the target
DetailPrint "Target is already present in $1. It will be removed and"
${EndIf}
${If} $0 == "" ; If EnvVar is (now) empty
StrCpy $0 $4 ; just copy PathString to EnvVar
${If} $6 == 0 ; If found flag is either 0
${OrIf} $6 == "" ; or blank (if EnvVarName is empty)
DetailPrint "$1 was empty and has been updated with the target"
${EndIf}
${ElseIf} $2 == "A" ; If Append (and EnvVar is not empty),
StrCpy $0 $0;$4 ; append PathString
${If} $6 == 1
DetailPrint "appended to $1"
${Else}
DetailPrint "Target was appended to $1"
${EndIf}
${Else} ; If Prepend (and EnvVar is not empty),
StrCpy $0 $4;$0 ; prepend PathString
${If} $6 == 1
DetailPrint "prepended to $1"
${Else}
DetailPrint "Target was prepended to $1"
${EndIf}
${EndIf}
${Else} ; If Action = Remove
${If} $6 == 1 ; and we found the target
DetailPrint "Target was found and removed from $1"
${Else}
DetailPrint "Target was NOT found in $1 (nothing to remove)"
${EndIf}
${If} $0 == ""
DetailPrint "$1 is now empty"
${EndIf}
${EndIf}
; Step 5: Update the registry at RegLoc with the updated EnvVar and announce the change
;
ClearErrors
${If} $3 == HKLM
WriteRegExpandStr ${hklm_all_users} $1 $0 ; Write it in all users section
${ElseIf} $3 == HKCU
WriteRegExpandStr ${hkcu_current_user} $1 $0 ; Write it to current user section
${EndIf}
IfErrors 0 +4
MessageBox MB_OK|MB_ICONEXCLAMATION "Could not write updated $1 to $3"
DetailPrint "Could not write updated $1 to $3"
Goto EnvVarUpdate_Restore_Vars
; "Export" our change
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
EnvVarUpdate_Restore_Vars:
;
; Restore the user's variables and return ResultVar
Pop $R0
Pop $9
Pop $8
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Push $0 ; Push my $0 (ResultVar)
Exch
Pop $0 ; Restore his $0
FunctionEnd
!macroend ; EnvVarUpdate UN
!insertmacro EnvVarUpdate ""
!insertmacro EnvVarUpdate "un."
;----------------------------------- EnvVarUpdate end----------------------------------------
!verbose pop
!endif

View file

@ -44,9 +44,9 @@ Name: modifypath; Description: &Add $c.displayName to your system path (if not i
[Code] [Code]
function GiveMeAPath(const DefaultPathName: string): string; function GiveMeAPath(const DefaultPathName: string): string;
begin begin
if IsAdminLoggedOn then Result := ExpandConstant('{pf}') if IsAdminLoggedOn then result := ExpandConstant('{pf}')
else Result := ExpandConstant('{userdocs}'); else result := ExpandConstant('{userdocs}');
Result := Result + '\' + DefaultPathName; result := result + '\' + DefaultPathName;
end; end;
#if c.binPaths.len > 0: #if c.binPaths.len > 0:

View file

@ -31,6 +31,7 @@ type
actionNone, # action not yet known actionNone, # action not yet known
actionCSource # action: create C sources actionCSource # action: create C sources
actionInno, # action: create Inno Setup installer actionInno, # action: create Inno Setup installer
actionNsis, # action: create NSIS installer
actionScripts # action: create install and deinstall scripts actionScripts # action: create install and deinstall scripts
actionZip, # action: create zip file actionZip, # action: create zip file
actionDeb # action: prepare deb package actionDeb # action: prepare deb package
@ -50,10 +51,10 @@ type
TConfigData = object of TObject TConfigData = object of TObject
actions: set[TAction] actions: set[TAction]
cat: array[TFileCategory, seq[string]] cat: array[TFileCategory, seq[string]]
binPaths, authors, oses, cpus: seq[string] binPaths, authors, oses, cpus, downloads: seq[string]
cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]] cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
platforms: array[1..maxOS, array[1..maxCPU, bool]] platforms: array[1..maxOS, array[1..maxCPU, bool]]
ccompiler, linker, innosetup: tuple[path, flags: string] ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
name, displayName, version, description, license, infile, outdir: string name, displayName, version, description, license, infile, outdir: string
libpath: string libpath: string
innoSetupFlag, installScript, uninstallScript: bool innoSetupFlag, installScript, uninstallScript: bool
@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
c.authors = @[] c.authors = @[]
c.oses = @[] c.oses = @[]
c.cpus = @[] c.cpus = @[]
c.downloads = @[]
c.ccompiler = ("", "") c.ccompiler = ("", "")
c.linker = ("", "") c.linker = ("", "")
c.innosetup = ("", "") c.innosetup = ("", "")
c.nsisSetup = ("", "")
c.name = "" c.name = ""
c.displayName = "" c.displayName = ""
c.version = "" c.version = ""
@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
if result.len == 0: result = f if result.len == 0: result = f
include "inno.tmpl" include "inno.tmpl"
include "nsis.tmpl"
include "buildsh.tmpl" include "buildsh.tmpl"
include "buildbat.tmpl" include "buildbat.tmpl"
include "install.tmpl" include "install.tmpl"
@ -125,10 +129,10 @@ include "deinstall.tmpl"
# ------------------------- configuration file ------------------------------- # ------------------------- configuration file -------------------------------
const const
Version = "0.9" Version = "1.0"
Usage = "niminst - Nimrod Installation Generator Version " & Version & """ Usage = "niminst - Nimrod Installation Generator Version " & Version & """
(c) 2013 Andreas Rumpf (c) 2014 Andreas Rumpf
Usage: Usage:
niminst [options] command[;command2...] ini-file[.ini] [compile_options] niminst [options] command[;command2...] ini-file[.ini] [compile_options]
Command: Command:
@ -136,6 +140,7 @@ Command:
scripts build install and deinstall scripts scripts build install and deinstall scripts
zip build the ZIP file zip build the ZIP file
inno build the Inno Setup installer inno build the Inno Setup installer
nsis build the NSIS Setup installer
deb create files for debhelper deb create files for debhelper
Options: Options:
-o, --output:dir set the output directory -o, --output:dir set the output directory
@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
of "scripts": incl(c.actions, actionScripts) of "scripts": incl(c.actions, actionScripts)
of "zip": incl(c.actions, actionZip) of "zip": incl(c.actions, actionZip)
of "inno": incl(c.actions, actionInno) of "inno": incl(c.actions, actionInno)
of "nsis": incl(c.actions, actionNsis)
of "deb": incl(c.actions, actionDeb) of "deb": incl(c.actions, actionDeb)
else: quit(Usage) else: quit(Usage)
else: else:
@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
case k case k
of pcFile, pcLinkToFile: add(s, unixToNativePath(f)) of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
of pcDir: walkDirRecursively(s, f) of pcDir: walkDirRecursively(s, f)
of pcLinkToDir: nil of pcLinkToDir: discard
proc addFiles(s: var seq[string], patterns: seq[string]) = proc addFiles(s: var seq[string], patterns: seq[string]) =
for p in items(patterns): for p in items(patterns):
@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
else: quit(errorStr(p, "expected: console or gui")) else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = unixToNativePath(k.value) of "license": c.license = unixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key)) else: quit(errorStr(p, "unknown variable: " & k.key))
of "var": nil of "var": discard
of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin]) of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
of "config": filesOnly(p, k.key, v, c.cat[fcConfig]) of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
of "data": filesOnly(p, k.key, v, c.cat[fcData]) of "data": filesOnly(p, k.key, v, c.cat[fcData])
@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) =
of "files": addFiles(c.cat[fcWindows], split(v, {';'})) of "files": addFiles(c.cat[fcWindows], split(v, {';'}))
of "binpath": c.binPaths = split(v, {';'}) of "binpath": c.binPaths = split(v, {';'})
of "innosetup": c.innoSetupFlag = yesno(p, v) of "innosetup": c.innoSetupFlag = yesno(p, v)
of "download": c.downloads.add(v)
else: quit(errorStr(p, "unknown variable: " & k.key)) else: quit(errorStr(p, "unknown variable: " & k.key))
of "unix": of "unix":
case normalize(k.key) case normalize(k.key)
@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
else: quit(errorStr(p, "unknown variable: " & k.key)) else: quit(errorStr(p, "unknown variable: " & k.key))
of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin]) of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
of "innosetup": pathFlags(p, k.key, v, c.innosetup) of "innosetup": pathFlags(p, k.key, v, c.innosetup)
of "nsis": pathFlags(p, k.key, v, c.nsisSetup)
of "ccompiler": pathFlags(p, k.key, v, c.ccompiler) of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
of "linker": pathFlags(p, k.key, v, c.linker) of "linker": pathFlags(p, k.key, v, c.linker)
of "deb": of "deb":
@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
# --------------------- generate inno setup ----------------------------------- # --------------------- generate inno setup -----------------------------------
proc setupDist(c: var TConfigData) = proc setupDist(c: var TConfigData) =
var scrpt = generateInnoSetup(c) let scrpt = generateInnoSetup(c)
var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version] let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
writeFile(n, scrpt, "\13\10") writeFile(n, scrpt, "\13\10")
when defined(windows): when defined(windows):
if c.innosetup.path.len == 0: if c.innosetup.path.len == 0:
c.innosetup.path = "iscc.exe" c.innosetup.path = "iscc.exe"
var outcmd = if c.outdir.len == 0: "build" else: c.outdir let outcmd = if c.outdir.len == 0: "build" else: c.outdir
var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path), let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
c.innosetup.flags, outcmd, n] c.innosetup.flags, outcmd, n]
echo(cmd) echo(cmd)
if execShellCmd(cmd) == 0: if execShellCmd(cmd) == 0:
@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
else: else:
quit("External program failed") quit("External program failed")
# --------------------- generate NSIS setup -----------------------------------
proc setupDist2(c: var TConfigData) =
let scrpt = generateNsisSetup(c)
let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
writeFile(n, scrpt, "\13\10")
when defined(windows):
if c.nsisSetup.path.len == 0:
c.nsisSetup.path = "makensis.exe"
let outcmd = if c.outdir.len == 0: "build" else: c.outdir
let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path),
c.nsisSetup.flags, outcmd, n]
echo(cmd)
if execShellCmd(cmd) == 0:
removeFile(n)
else:
quit("External program failed")
# ------------------ generate ZIP file --------------------------------------- # ------------------ generate ZIP file ---------------------------------------
when haveZipLib: when haveZipLib:
proc zipDist(c: var TConfigData) = proc zipDist(c: var TConfigData) =
@ -503,17 +528,17 @@ when haveZipLib:
else: n = c.outdir / n else: n = c.outdir / n
var z: TZipArchive var z: TZipArchive
if open(z, n, fmWrite): if open(z, n, fmWrite):
addFile(z, proj / buildBatFile32, buildBatFile32) addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
addFile(z, proj / buildBatFile64, buildBatFile64) addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
addFile(z, proj / buildShFile, buildShFile) addFile(z, proj / buildShFile, "build" / buildShFile)
addFile(z, proj / installShFile, installShFile) addFile(z, proj / installShFile, installShFile)
addFile(z, proj / deinstallShFile, deinstallShFile) addFile(z, proj / deinstallShFile, deinstallShFile)
for f in walkFiles(c.libpath / "lib/*.h"): for f in walkFiles(c.libpath / "lib/*.h"):
addFile(z, proj / "build" / extractFilename(f), f) addFile(z, proj / "c_code" / extractFilename(f), f)
for osA in 1..c.oses.len: for osA in 1..c.oses.len:
for cpuA in 1..c.cpus.len: for cpuA in 1..c.cpus.len:
var dir = buildDir(osA, cpuA) var dir = buildDir(osA, cpuA)
for k, f in walkDir(dir): for k, f in walkDir("build" / dir):
if k == pcFile: addFile(z, proj / dir / extractFilename(f), f) if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
for cat in items({fcConfig..fcOther, fcUnix}): for cat in items({fcConfig..fcOther, fcUnix}):
@ -576,6 +601,8 @@ parseCmdLine(c)
parseIniFile(c) parseIniFile(c)
if actionInno in c.actions: if actionInno in c.actions:
setupDist(c) setupDist(c)
if actionNsis in c.actions:
setupDist2(c)
if actionCSource in c.actions: if actionCSource in c.actions:
srcdist(c) srcdist(c)
if actionScripts in c.actions: if actionScripts in c.actions:

255
tools/niminst/nsis.tmpl Normal file
View file

@ -0,0 +1,255 @@
#! stdtmpl(subsChar='?') | standard
#proc generateNsisSetup(c: TConfigData): string =
# result = "; NSIS script generated by niminst\n" &
# "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
;--------------------------------
; Included headers
; Modern User Interface 2.0 Header
!include "MUI2.nsh"
; File Functions Header, used to get the current drive root.
!include "FileFunc.nsh"
; *Patched* Environment Variable Manipulation Header, used to add
; tools to the user's PATH environment variable.
!include "EnvVarUpdate.nsh"
;--------------------------------
; Global variables and defines
!define PRODUCT_NAME "?c.displayName"
!define PRODUCT_VERSION "?c.version"
!define PRODUCT_PUBLISHER "?c.authors"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\?{c.name}.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKCU"
!define PRODUCT_STARTMENU_REGVAL "NSIS:StartMenuDir"
;--------------------------------
; General Setup Information
; Name and output file
Name "?{c.name} ?{c.version}"
OutFile "?{c.name}_?{c.version}.exe"
; Default installation folder
; This is changed later (in .onInit) to the root directory, if possible.
InstallDir "$LOCALAPPDATA\?{c.name}"
; Get installation folder from registry if available
InstallDirRegKey HKCU "Software\c.name\c.version" ""
; Request user level application privileges.
RequestExecutionLevel user
; Allow installation to the root drive directory.
AllowRootDirInstall true
; Maximum compression!
SetCompressor /SOLID /FINAL lzma
; Installer and Uninstaller Icons
; Icon "nimrod.ico"
; UninstallIcon "nimrod.ico"
; Set installation details to be shown by default
ShowInstDetails show
ShowUnInstDetails show
;--------------------------------
; Interface Settings
; Warn the user if aborting during installation/uninstallation
!define MUI_ABORTWARNING
!define MUI_UNABORTWARNING
; Don't show a description for sections
!define MUI_COMPONENTSPAGE_NODESC
;--------------------------------
; Pages
; Setup the installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "?{expandFilename(c.license)}"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
; Setup the start menu entry page
var ICONS_GROUP
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "?{c.displayName}"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT "${PRODUCT_UNINST_ROOT_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${PRODUCT_UNINST_KEY}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${PRODUCT_STARTMENU_REGVAL}"
!insertmacro MUI_PAGE_STARTMENU Application $ICONS_GROUP
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
; Setup the uninstaller pages
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
;--------------------------------
;Installer Sections
; The core section. This is comprised of a base Nim installation,
; such as what would be retrieved via git, and an already bootstrapped
; Nim binary.
Section "Core Files" CoreSection
; This is a mandotory section
SectionIn RO
; Output files to the base installation directory
SetOutPath "$INSTDIR"
; Only overwrite newer files
SetOverwrite ifnewer
; Write all the files to the output directory.
#for i in low(TFileCategory)..fcWindows:
# for f in items(c.cat[i]):
SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
File "?{expandFilename(f).toWin}"
# end for
#end for
; Write out the uninstaller
WriteUninstaller "$INSTDIR\uninstaller.exe"
SectionEnd
Section "-Add Registry Keys" RegistrySection
; Write application registry keys
WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
; Reset the output path
SetOutPath "$INSTDIR"
SectionEnd
; Section for adding the shortcuts related to files and applications
Section "-Setup Shortcuts" ShortcutsSection
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
CreateDirectory "$SMPROGRAMS\$ICONS_GROUP"
#if c.app == appConsole:
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\start.bat"
#else:
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
CreateShortCut "$DESKTOP\?{c.displayName}.lnk" "$INSTDIR\?{c.name}.exe"
#end if
; Add shortcuts for the documentation
#for f in items(c.cat[fcDocStart]):
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{splitFile(f).name}.lnk" "$INSTDIR\?{f.toWin}"
#end for
; Write the shortcut to the uninstaller
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\Uninstall.lnk" "$INSTDIR\uninstaller.exe"
!insertmacro MUI_STARTMENU_WRITE_END
SectionEnd
; Section for adding tools to the PATH variable
Section "Setup Path Environment" PathSection
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\mingw"
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\bin"
${EnvVarUpdate} $R0 "PATH" "A" "HKCU" "$INSTDIR\dist\babel"
SectionEnd
; The downloadable sections. These sections are automatically generated by
; niminst and the template filters.
#var i = 0
#for download in c.downloads:
# inc i
# let d = download.split('|')
# if d.len != 5 and d.len != 6:
# quit("download string needs 5..6 parts: " & download)
# end if
# let sectionName = d[0]
# let dir = d[1]
# let zipName = d[2]
# let size = d[3]
# let url = d[4]
Section /o "?sectionName" ?{i}Section
; Add the section size to the total size.
AddSize ?size
; Download the file, and if successful, extract it to the given directory
; otherwise,
retry:
NSISdl::download "?url" "$TEMP\?zipName"
Pop $0
${If} $0 == "success"
ZipDLL::extractall "$TEMP\?zipName" "$INSTDIR\?dir"
Delete "$TEMP\?zipName"
${Else}
MessageBox MB_ICONSTOP|MB_ABORTRETRYIGNORE "Error: $0" IDRETRY retry IDIGNORE ignore
abort
${EndIf}
# if d.len >= 6:
# let startMenuEntry = d[5]
# let e = splitFile(startMenuEntry).name.capitalize
CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
# end if
; Shortcuts
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
!insertmacro MUI_STARTMENU_WRITE_END
ignore:
SectionEnd
#end
;--------------------------------
; Section Descriptions
; Series of strings describing each section
; LangString DESC_CoreSection ${LANG_ENGLISH} "Core Nim files"
; The macros to actually insert the descriptions into the sections.
; Each description above should have a corresponding MUI_DESCRIPTION_TEXT
; macro linking the section to the description.
; !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
; !insertmacro MUI_DESCRIPTION_TEXT ${CoreSection} $(DESC_CoreSection)
; !insertmacro MUI_FUNCTION_DESCRIPTION_END
;--------------------------------
; Uninstaller Sections
Section "Uninstall"
; Remove previously created shortcuts
!insertmacro MUI_STARTMENU_GETFOLDER "Application" $ICONS_GROUP
Delete "$DESKTOP\?{c.displayName}.lnk"
; Remove installed application files
RMDir /r "$SMPROGRAMS\$ICONS_GROUP"
RMDir /r "$INSTDIR"
; Remove the previously created registry key
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
; Remove entries from the PATH environment variable
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\mingw"
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\bin"
${un.EnvVarUpdate} $R0 "PATH" "R" "HKCU" "$INSTDIR\dist\babel"
SectionEnd
;--------------------------------
; Function hooks
Function .onInit
${GetRoot} "$EXEDIR" $R0
strCpy $INSTDIR "$R0\?{c.name}"
FunctionEnd

View file

@ -45,6 +45,7 @@ proc initConfigData(c: var TConfigData) =
c.gitCommit = "master" c.gitCommit = "master"
c.numProcessors = countProcessors() c.numProcessors = countProcessors()
# Attempts to obtain the git current commit. # Attempts to obtain the git current commit.
when false:
let (output, code) = execCmdEx("git log -n 1 --format=%H") let (output, code) = execCmdEx("git log -n 1 --format=%H")
if code == 0 and output.strip.len == 40: if code == 0 and output.strip.len == 40:
c.gitCommit = output.strip c.gitCommit = output.strip
@ -239,7 +240,7 @@ proc mexec(cmds: openarray[string], processors: int) =
sexec(cmds) sexec(cmds)
return return
if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}): if execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}) != 0:
echo "external program failed, retrying serial work queue for logs!" echo "external program failed, retrying serial work queue for logs!"
sexec(cmds) sexec(cmds)
@ -289,8 +290,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
exec("pdflatex " & changeFileExt(d, "tex")) exec("pdflatex " & changeFileExt(d, "tex"))
exec("pdflatex " & changeFileExt(d, "tex")) exec("pdflatex " & changeFileExt(d, "tex"))
# delete all the crappy temporary files: # delete all the crappy temporary files:
var pdf = splitFile(d).name & ".pdf" let pdf = splitFile(d).name & ".pdf"
moveFile(dest=destPath / pdf, source=pdf) let dest = destPath / pdf
removeFile(dest)
moveFile(dest=dest, source=pdf)
removeFile(changeFileExt(pdf, "aux")) removeFile(changeFileExt(pdf, "aux"))
if existsFile(changeFileExt(pdf, "toc")): if existsFile(changeFileExt(pdf, "toc")):
removeFile(changeFileExt(pdf, "toc")) removeFile(changeFileExt(pdf, "toc"))
@ -432,4 +435,7 @@ var c: TConfigData
initConfigData(c) initConfigData(c)
parseCmdLine(c) parseCmdLine(c)
parseIniFile(c) parseIniFile(c)
when false:
buildPdfDoc(c, "doc")
else:
main(c) main(c)

View file

@ -1,127 +1,41 @@
You can download the latest version of the Nimrod compiler here. You can You can download the latest version of the Nimrod compiler here.
use the binaries provided or build from source.
Binaries
========
All installers and archives contain the html documentation and tools
(nimgrep, c2nim and babel).
**Note:** The Nimrod compiler requires a C compiler to compile software. On **Note:** The Nimrod compiler requires a C compiler to compile software. On
Windows we recommend that you use Windows we recommend that you use
`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux `Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
and clang on Mac OS X. and clang on Mac OS X.
Installers
----------
The "full" version includes a full mingw distribution which includes a C Binaries
compiler. The "slim" version lacks this. ========
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.exe>`_ Unfortunately for now we only provide builds for Windows.
.. raw:: html * 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
<p style="font-size: 8pt; margin-top: 0;"> * 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24
</p>
* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.exe>`_
.. raw:: html Installation based on generated C code
<p style="font-size: 8pt; margin-top: 0;"> ======================================
SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242
</p>
* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.exe>`_ This installation method is the preferred way for Linux, Mac OS X, and other Unix
like systems. Binary packages may be provided later.
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e
</p>
* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.exe>`_ Download `nimrod_0.9.6.zip <download/nimrod_0.9.6.zip>`_, extract it and follow
these instructions:
.. raw:: html * sh build.sh
<p style="font-size: 8pt; margin-top: 0;"> * Add ``$your_install_dir/bin`` to your PATH.
SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e
</p>
Archives There are other ways to install Nimrod (like using the ``install.sh`` script),
-------- but these tend to cause more problems.
Windows
~~~~~~~
The "full" version includes a full mingw distribution which includes a C Installation from github
compiler. The "slim" version lacks this. ========================
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.zip>`_ It is also possible to build directly from the
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956
</p>
* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.zip>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857
</p>
* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.zip>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a
</p>
* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.zip>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba
</p>
Linux
~~~~~
* Linux (i386, 32bit): `<download/nimrod_0.9.4_linux_i386.tar.gz>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92
</p>
* Linux (amd64, 64bit): `<download/nimrod_0.9.4_linux_amd64.tar.gz>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C
</p>
* Linux (ppc64, 64bit): `<download/nimrod_0.9.4_linux_ppc64.tar.gz>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31
</p>
Mac OS X
~~~~~~~~
* Mac OS X (amd64, 64bit): `<download/nimrod_0.9.4_macosx_amd64.zip>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C
</p>
If a binary for your platform is not available then you must build from source.
Bleeding edge binaries are available from the `Nimrod build farm <http://build.nimrod-lang.org/>`_.
Source
======
Starting with 0.9.4 we now advise people to build directly from the
github `master <https://github.com/Araq/Nimrod#compiling>`_ branch:: github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
git clone -b master git://github.com/Araq/Nimrod.git git clone -b master git://github.com/Araq/Nimrod.git
@ -135,4 +49,3 @@ github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
The ``master`` branch always contains the latest stable version of the compiler. The ``master`` branch always contains the latest stable version of the compiler.
If you want bleeding edge then switch to the ``devel`` branch and follow If you want bleeding edge then switch to the ``devel`` branch and follow
the same instructions outlined above. the same instructions outlined above.

View file

@ -2,9 +2,15 @@
News News
==== ====
.. 2014-10-19 Nimrod version 0.9.6 released
2014-06-29 Version 0.9.6 released ========================================
=================================
**Note: 0.9.6 is the last release of Nimrod. The language has been renamed to
Nim. Nim slightly breaks compatibility.**
This is a maintenance release. The upcoming 0.10.0 release has
the new features and exciting developments.
Changes affecting backwards compatibility Changes affecting backwards compatibility
----------------------------------------- -----------------------------------------
@ -34,7 +40,10 @@ News
Language Additions Language Additions
------------------ ------------------
- There is a new ``parallel`` statement for safe fork&join parallel computing. - This version introduces the new ``deprecated`` pragma statement that is used
to handle the upcoming massive amount of symbol renames.
- ``spawn`` can now wrap proc that have a return value. It then returns a flow
variable of the wrapped return type.
Library Additions Library Additions

View file

@ -26,9 +26,10 @@ file: ticker.txt
[Quotations] [Quotations]
# Page: quote - Person # Page: quote - Person
# Bad things will happen if you use multiple dashes here. # Bad things will happen if you use multiple dashes here.
index: """The most important thing in the programming language is the name. index: """Is it so bad, then, to be misunderstood? Pythagoras was misunderstood,
A language will not succeed without a good name. I have recently invented a and Socrates, and Jesus, and Luther, and Copernicus, and Galileo, and Newton,
very good name and now I am looking for a suitable language. - D. E. Knuth""" and every pure and wise spirit that ever took flesh. To be great is to be
misunderstood. - Ralph Waldo Emerson"""
documentation: """Incorrect documentation is often worse than no documentation. documentation: """Incorrect documentation is often worse than no documentation.
- Bertrand Meyer""" - Bertrand Meyer"""
download: """There are two major products that come out of Berkeley: LSD and download: """There are two major products that come out of Berkeley: LSD and

View file

@ -1,3 +1,8 @@
<a class="news" href="news.html#Z2014-10-19-version-0-9-6-released">
<h3>Oct 19, 2014</h3>
<p>Nimrod version 0.9.6 has been released!</p>
</a>
<a class="news" href="news.html#Z2014-04-21-version-0-9-4-released"> <a class="news" href="news.html#Z2014-04-21-version-0-9-4-released">
<h3>Apr 21, 2014</h3> <h3>Apr 21, 2014</h3>
<p>Nimrod version 0.9.4 has been released!</p> <p>Nimrod version 0.9.4 has been released!</p>