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
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
#
# 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
# require RC ops
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
const
# getting ready for the future expr/stmt merge
@@ -476,7 +478,7 @@ type
# and first phase symbol lookup in generics
skConditional, # symbol for the preprocessor (may become obsolete)
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
skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()``
skTemp, # a temporary variable (introduced by compiler)
@@ -501,7 +503,8 @@ type
skStub, # symbol is a stub and not yet loaded from the ROD
# file (it is loaded on demand, which may
# 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]
const
@@ -678,7 +681,7 @@ type
heapRoot*: PRope # keeps track of the enclosing heap object that
# owns this location (required by GC algorithms
# employing heap snapshots or sliding views)
a*: int # location's "address", i.e. slot for temporaries
a*: int
# ---------------- end of backend information ------------------------------
@@ -731,8 +734,9 @@ type
# check for the owner when touching 'usedGenerics'.
usedGenerics*: seq[PInstantiation]
tab*: TStrTable # interface table for modules
of skLet, skVar, skField:
guard*: PSym
else: nil
magic*: TMagic
typ*: PType
name*: PIdent
@@ -872,7 +876,7 @@ const
tyProc, tyString, tyError}
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
skIterator, skClosureIterator,
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
nfDotSetter, nfDotField,
nfIsRef}
@@ -1162,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
result.sons = @[name, pattern, genericParams, params,
pragmas, exceptions, body]
proc newType(kind: TTypeKind, owner: PSym): PType =
new(result)
result.kind = kind
@@ -1172,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
result.id = getID()
when debugIds:
registerId(result)
#if result.id < 2000 then
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
#if result.id < 2000:
# messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
proc mergeLoc(a: var TLoc, b: TLoc) =
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.loc = s.loc
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 =
result = newSym(s.kind, newIdent, s.owner, info)

View File

@@ -832,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
discard cgsym(p.module, "E_Base")
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
if isDefined("nimStdSetjmp"):
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
elif isDefined("nimSigSetjmp"):
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
elif isDefined("nimRawSetjmp"):
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, t)

View File

@@ -13,7 +13,7 @@ import
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
options, intsets,
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,
semparallel

View File

@@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) =
platform.OS[platform.hostOS].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:
msgWriteln("git hash: " & gitHash)
msgWriteln("git hash: " & gitHash)"""
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
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 "assertions", "a": processOnOffSwitch({optAssert}, 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 "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info)
of "implicitstatic":

View File

@@ -1,6 +1,6 @@
#
#
# The Nimrod Compiler
# The Nim Compiler
# (c) Copyright 2014 Andreas Rumpf
#
# See the file "copying.txt", included in this
@@ -60,7 +60,7 @@ const
quick
release debug
useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
nodejs kwin
nodejs kwin nimfix
usesysassert usegcassert tinyC useFFI
useStdoutAsStdmsg createNimRtl
@@ -69,6 +69,8 @@ const
reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
debugExecProcesses pcreDll useLipzipSrc
preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
nimStdSetjmp nimRawSetjmp nimSigSetjmp
""".split
proc initDefines*() =
@@ -85,6 +87,7 @@ proc initDefines*() =
defineSymbol("nimnewshared")
defineSymbol("nimrequiresnimframe")
defineSymbol("nimparsebiggestfloatmagic")
defineSymbol("nimalias")
# add platform specific symbols:
for c in low(CPU)..high(CPU):
@@ -136,3 +139,7 @@ proc initDefines*() =
declareSymbol("emulatedthreadvars")
if platform.OS[targetOS].props.contains(ospLacksThreadVars):
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
let docItemSeeSrc = getConfigVar("doc.item.seesrc")
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,
["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)])
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,

View File

@@ -92,7 +92,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
if s.kind == skConverter: addConverter(c, s)
if hasPattern(s): addPattern(c, s)
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
let ident = lookups.considerQuotedIdent(n)
let s = strTableGet(fromMod.tab, ident)
if s == nil:
@@ -155,10 +155,12 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
# some misguided guy will write 'import abc.foo as foo' ...
result = createModuleAlias(realModule, n.sons[1].ident, n.sons[1].info)
proc myImportModule(c: PContext, n: PNode): PSym =
proc myImportModule(c: PContext, n: PNode): PSym =
var f = checkModuleName(n)
if f != InvalidFileIDX:
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:
message(n.info, warnDeprecated, result.name.s)

View File

@@ -1,6 +1,6 @@
#
#
# The Nimrod Compiler
# The Nim Compiler
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
@@ -11,7 +11,7 @@
import
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
renderer, wordrecg, idgen
renderer, wordrecg, idgen, nimfix.prettybase
proc ensureNoMissingOrUnusedSymbols(scope: PScope)
@@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent =
template addSym*(scope: PScope, s: PSym) =
strTableAdd(scope.symbols, s)
proc addUniqueSym*(scope: PScope, s: PSym): TResult =
if strTableIncl(scope.symbols, s):
result = Failure
else:
result = Success
proc addUniqueSym*(scope: PScope, s: PSym): bool =
result = not strTableIncl(scope.symbols, s)
proc openScope*(c: PContext): PScope {.discardable.} =
result = PScope(parent: c.currentScope,
@@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope =
yield current
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 =
result = strTableGet(c.currentScope.symbols, s)
@@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) =
localError(info, errAttemptToRedefine, s)
proc addDecl*(c: PContext, sym: PSym) =
if c.currentScope.addUniqueSym(sym) == Failure:
if not c.currentScope.addUniqueSym(sym):
wrongRedefinition(sym.info, sym.name.s)
proc addPrelimDecl*(c: PContext, sym: PSym) =
discard c.currentScope.addUniqueSym(sym)
proc addDeclAt*(scope: PScope, sym: PSym) =
if scope.addUniqueSym(sym) == Failure:
if not scope.addUniqueSym(sym):
wrongRedefinition(sym.info, sym.name.s)
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
@@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
if fn.kind notin OverloadableSyms:
internalError(fn.info, "addOverloadableSymAt")
return
var check = strTableGet(scope.symbols, fn.name)
let check = strTableGet(scope.symbols, fn.name)
if check != nil and check.kind notin OverloadableSyms:
wrongRedefinition(fn.info, fn.name.s)
else:
@@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
addOverloadableSymAt(scope, 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 =
# Looks up a symbol. Generates an error in case of nil.
case n.kind
of nkIdent:
result = searchInScopes(c, n.ident)
if result == nil:
result = searchInScopes(c, n.ident).skipAlias(n)
if result == nil:
fixSpelling(n, n.ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, n.ident.s)
result = errorSym(c, n)
of nkSym:
result = n.sym
of nkAccQuoted:
var ident = considerQuotedIdent(n)
result = searchInScopes(c, ident)
result = searchInScopes(c, ident).skipAlias(n)
if result == nil:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n)
else:
@@ -206,36 +235,38 @@ type
TLookupFlag* = enum
checkAmbiguity, checkUndeclared
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
case n.kind
of nkIdent, nkAccQuoted:
var ident = considerQuotedIdent(n)
result = searchInScopes(c, ident)
if result == nil and checkUndeclared in flags:
result = searchInScopes(c, ident).skipAlias(n)
if result == nil and checkUndeclared in flags:
fixSpelling(n, ident, searchInScopes)
localError(n.info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n)
elif checkAmbiguity in flags and result != nil and
contains(c.ambiguousSymbols, result.id):
elif checkAmbiguity in flags and result != nil and
contains(c.ambiguousSymbols, result.id):
localError(n.info, errUseQualifier, ident.s)
of nkSym:
result = n.sym
if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
localError(n.info, errUseQualifier, n.sym.name.s)
of nkDotExpr:
of nkDotExpr:
result = nil
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
if n.sons[1].kind == nkIdent:
if n.sons[1].kind == nkIdent:
ident = n.sons[1].ident
elif n.sons[1].kind == nkAccQuoted:
elif n.sons[1].kind == nkAccQuoted:
ident = considerQuotedIdent(n.sons[1])
if ident != nil:
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident)
else:
result = strTableGet(m.tab, ident)
if result == nil and checkUndeclared in flags:
if ident != nil:
if m == c.module:
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n)
else:
result = strTableGet(m.tab, ident).skipAlias(n)
if result == nil and checkUndeclared in flags:
fixSpelling(n.sons[1], ident, searchInScopes)
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
result = errorSym(c, n.sons[1])
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.mode = oimNoQualifier
while true:
result = initIdentIter(o.it, o.scope.symbols, ident)
result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n)
if result != nil:
break
else:
@@ -277,11 +308,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
if ident != nil:
if o.m == c.module:
# 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
else:
result = initIdentIter(o.it, o.m.tab, ident)
else:
else:
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
else:
localError(n.sons[1].info, errIdentifierExpected,
renderTree(n.sons[1]))
result = errorSym(c, n.sons[1])
@@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
result = nil
of oimNoQualifier:
if o.scope != nil:
result = nextIdentIter(o.it, o.scope.symbols)
result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
while result == nil:
o.scope = o.scope.parent
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
else:
result = nil
of oimSelfModule:
result = nextIdentIter(o.it, c.topLevelScope.symbols)
result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
of oimOtherModule:
result = nextIdentIter(o.it, o.m.tab)
result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
of oimSymChoice:
if o.symChoiceIndex < sonsLen(n):
result = n.sons[o.symChoiceIndex].sym
@@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.mode = oimSymChoiceLocalLookup
o.scope = c.currentScope
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:
o.scope = o.scope.parent
if o.scope == nil: break
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:
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice)
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n)
while result == nil:
o.scope = o.scope.parent
if o.scope == nil: break
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)
when false:
proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode,
flags = {checkUndeclared}): PSym =
var o: TOverloadIter
result = initOverloadIter(o, c, n)
var a = result
while a != nil:
if sfImmediate in a.flags: return a
a = nextOverloadIter(o, c, n)
if result == nil and checkUndeclared in flags:
localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s)
result = errorSym(c, n)
proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
flags: TSymFlags = {}): PSym =
var o: TOverloadIter
var a = initOverloadIter(o, c, n)
while a != nil:
if a.kind == kind and flags <= a.flags:
return a
a = nextOverloadIter(o, 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]
Name: "Nimrod"
Version: "$version"
@@ -34,11 +37,11 @@ Files: "config/nimdoc.cfg"
Files: "config/nimdoc.tex.cfg"
[Documentation]
Files: "doc/*.txt"
Files: "doc/*.html"
Files: "doc/*.cfg"
Files: "doc/*.pdf"
Files: "doc/*.ini"
; Files: "doc/*.html"
; Files: "doc/*.cfg"
; Files: "doc/*.pdf"
; Files: "doc/*.ini"
Files: "doc/overview.html"
Start: "doc/overview.html"
@@ -61,13 +64,9 @@ Files: "compiler/readme.txt"
Files: "compiler/nimrod.ini"
Files: "compiler/nimrod.cfg"
Files: "compiler/*.nim"
Files: "compiler/c2nim/*.nim"
Files: "compiler/c2nim/*.cfg"
Files: "compiler/pas2nim/*.nim"
Files: "compiler/pas2nim/*.cfg"
Files: "build/empty.txt"
Files: "bin/empty.txt"
Files: "doc/*.txt"
Files: "compiler/nimfix/*.nim"
Files: "compiler/nimfix/*.cfg"
[Lib]
@@ -115,17 +114,22 @@ Files: "examples/*.tmpl"
[Windows]
Files: "bin/nimrod.exe"
Files: "bin/nimrod_debug.exe"
Files: "bin/c2nim.exe"
Files: "bin/niminst.exe"
Files: "bin/nimgrep.exe"
Files: "dist/*.dll"
Files: "koch.exe"
Files: "dist/mingw"
; Files: "dist/mingw"
Files: "start.bat"
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]
Files: "bin/nimrod"
@@ -140,6 +144,9 @@ UninstallScript: "yes"
path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe"
flags = "/Q"
[NSIS]
path = r"c:\Program Files (x86)\NSIS\makensis.exe"
flags = "/V0"
[C_Compiler]
path = r""

View File

@@ -14,7 +14,7 @@ const
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
VersionMajor* = 0
VersionMinor* = 9
VersionPatch* = 5
VersionPatch* = 6
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
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
#
# See the file "copying.txt", included in this
@@ -24,7 +24,7 @@ const
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wOverride}
converterPragmas* = procPragmas
methodPragmas* = procPragmas
@@ -36,8 +36,8 @@ const
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wUses, wOperator, wGcSafe}
exprPragmas* = {wLine}
wTags, wLocks, wGcSafe}
exprPragmas* = {wLine, wLocks}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@@ -45,27 +45,27 @@ const
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
wInjectStmt}
wInjectStmt, wDeprecated}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
wRaises, wUses, wTags, wGcSafe}
wRaises, wLocks, wTags, wGcSafe}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError}
wImportCpp, wImportObjC, wError, wGuard}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl}
wGensym, wInject, wCodegenDecl, wGuard}
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
letPragmas* = varPragmas
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
wThread, wRaises, wUses, wTags, wGcSafe}
wThread, wRaises, wLocks, wTags, wGcSafe}
allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
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, sfInfixCall)
excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToCpp)
proc processImportObjC(s: PSym, extname: string) =
setExternName(s, extname)
incl(s.flags, sfImportc)
incl(s.flags, sfNamedParamCall)
excl(s.flags, sfForward)
let m = s.getModule()
incl(m.flags, sfCompileToObjC)
proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
@@ -514,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
else:
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) =
if n.kind == nkExprColonExpr:
let it = n.sons[1]
@@ -542,11 +525,50 @@ proc typeBorrow(sym: PSym, n: PNode) =
localError(n.info, "a type can only borrow `.` for now")
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,
validPragmas: TSpecialWords): bool =
var it = n.sons[i]
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
if key.kind == nkIdent:
if key.kind == nkIdent:
var userPragma = strTableGet(c.userPragmas, key.ident)
if userPragma != nil:
inc c.instCounter
@@ -578,11 +600,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
of wAlign:
if sym.typ == nil: invalidPragma(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)
else:
sym.typ.align = align
of wSize:
sym.typ.align = align.int16
of wSize:
if sym.typ == nil: invalidPragma(it)
var size = expectIntLit(c, it)
if not isPowerOfTwo(size) or size <= 0 or size > 8:
@@ -648,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
processDynLib(c, it, sym)
of wCompilerproc:
noVal(it) # compilerproc may not get a string!
if sfFromGeneric notin sym.flags:
makeExternExport(sym, "$1", it.info)
incl(sym.flags, sfCompilerProc)
incl(sym.flags, sfUsed) # suppress all those stupid warnings
registerCompilerProc(sym)
of wProcVar:
if sfFromGeneric notin sym.flags: markCompilerProc(sym)
of wProcVar:
noVal(it)
incl(sym.flags, sfProcvar)
of wDeprecated:
noVal(it)
if sym != nil: incl(sym.flags, sfDeprecated)
of wDeprecated:
if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
elif sym != nil: incl(sym.flags, sfDeprecated)
else: incl(c.module.flags, sfDeprecated)
of wVarargs:
noVal(it)
@@ -789,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if sym == nil: invalidPragma(it)
of wLine: pragmaLine(c, it)
of wRaises, wTags: pragmaRaisesOrTags(c, it)
of wUses: pragmaUses(c, it)
of wOperator:
if sym == nil: invalidPragma(it)
else: sym.position = expectIntLit(c, it)
of wGuard:
if sym == nil or sym.kind notin {skVar, skLet, skField}:
invalidPragma(it)
else:
sym.guard = pragmaGuard(c, it, sym.kind)
of wInjectStmt:
if it.kind != nkExprColonExpr:
localError(it.info, errExprExpected)

View File

@@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
var it: TIdentIter
result = initIdentIter(it, scope.symbols, fn.name)
while result != nil:
if result.kind in skProcKinds and
sameType(result.typ, fn.typ, flags): return
if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
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)

View File

@@ -1614,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
initIdTable(bindings)
bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
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 =
result = n

View File

@@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) =
if n.sons[namePos].kind != nkSym: return
documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects)
documentEffect(n, n.sons[pragmasPos], wTags, tagEffects)
documentEffect(n, n.sons[pragmasPos], wUses, usesEffects)
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))
tracked.gcUnsafe = true
when trackGlobals:
let usesSpec = effectSpec(pragma, wUses)
mergeUses(tracked, usesSpec, n)
proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
let n = n.skipConv
if paramType != nil and tfNotNil in paramType.flags and
@@ -641,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) =
if not isNil(tagsSpec):
checkRaisesSpec(tagsSpec, actual.sons[tagEffects],
"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):
localError(branch.info, "base method is GC-safe, but '$1' is not" %
branch.name.s)
@@ -656,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
let
raisesSpec = effectSpec(n, wRaises)
tagsSpec = effectSpec(n, wTags)
usesSpec = effectSpec(n, wUses)
if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec):
if not isNil(raisesSpec) or not isNil(tagsSpec):
internalAssert effects.len == 0
newSeq(effects.sons, effectListLen)
if not isNil(raisesSpec):
effects.sons[exceptionEffects] = raisesSpec
if not isNil(tagsSpec):
effects.sons[tagEffects] = tagsSpec
if not isNil(usesSpec):
effects.sons[usesEffects] = usesSpec
proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
newSeq(effects.sons, effectListLen)
@@ -710,12 +698,6 @@ proc trackProc*(s: PSym, body: PNode) =
# after the check, use the formal spec:
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 sfThread in s.flags and t.gcUnsafe:
#localError(s.info, warnGcUnsafe2, s.name.s)

View File

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

View File

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

View File

@@ -130,10 +130,5 @@ vcc.options.always = "/nologo"
vcc.options.speed = "/Ox /arch:SSE2"
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:
tcc.options.always = "-w"

View File

@@ -1,7 +1,7 @@
===============================================================================
Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/
Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved.
=====================================================
Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/
Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
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
--advanced show advanced command line switches
-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 `=`
------------
**Note**: Overriding the assignment operator has not yet been implemented.
This operator is the assignment operator. Note that in the contexts
like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for
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.
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
-------------------
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
*/
body {
color: black;
background: white;
}
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }

View File

@@ -438,18 +438,6 @@ module. Example:
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
---------------------------------------

View File

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

View File

@@ -43,7 +43,7 @@ Possible Commands:
web generates the website
csource [options] builds the C sources for installation
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
update updates nimrod to the latest version from github
(compile koch with -d:withUpdate to enable)
@@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool =
echo(cmd)
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
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
@@ -84,23 +92,28 @@ proc csource(args: string) =
exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
[args, NimrodVersion, compileNimInst, findNim()])
proc zip(args: string) =
exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" %
proc zip(args: string) =
exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" %
[NimrodVersion, compileNimInst, findNim()])
exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" %
["tools/niminst/niminst".exe, NimrodVersion])
proc buildTool(toolname, args: string) =
exec("$# cc $# $#" % [findNim(), args, toolname])
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:
buildTool("tools/niminst/niminst", args)
buildTool("tools/nimgrep", args)
exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" %
NimrodVersion)
# produce 'nimrod_debug.exe':
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) =
exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" %
exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nimrod.ini" %
[findNim(), compileNimInst, NimrodVersion])
exec("sh ./install.sh $#" % args)
@@ -135,16 +148,8 @@ proc findStartNimrod: string =
echo("Found no nimrod compiler and every attempt to build one failed!")
quit("FAILURE")
proc safeRemove(filename: string) =
if existsFile(filename): removeFile(filename)
proc thVersion(i: int): string =
result = ("compiler" / "nimrod" & $i).exe
proc copyExe(source, dest: string) =
safeRemove(dest)
copyFile(dest=dest, source=source)
inclFilePermissions(dest, {fpUserExec})
proc boot(args: string) =
var output = "compiler" / "nimrod".exe
@@ -302,7 +307,7 @@ of cmdArgument:
of "web": web(op.cmdLineRest)
of "csource", "csources": csource(op.cmdLineRest)
of "zip": zip(op.cmdLineRest)
of "inno": inno(op.cmdLineRest)
of "nsis": nsis(op.cmdLineRest)
of "install": install(op.cmdLineRest)
of "test", "tests": tests(op.cmdLineRest)
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`
## may contain a path that will be created.
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)
if zipsrc == nil:
#echo("Dest: " & dest)

View File

@@ -18,15 +18,24 @@ when not defined(windows):
when defined(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):
# 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
CTL_HW = 6
HW_AVAILCPU = 25
HW_NCPU = 3
proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
a: var csize, b: pointer, c: int): cint {.
importc: "sysctl", header: "<sys/sysctl.h>".}
importc: "sysctl", nodecl.}
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
## 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]'
FlowVarBaseObj = object of TObject
ready, usesCondVar: bool
ready, usesCondVar, awaited: bool
cv: CondVar #\
# for 'awaitAny' support
ai: ptr AwaitInfo
@@ -129,8 +129,8 @@ type
proc await*(fv: FlowVarBase) =
## waits until the value for the flowVar arrives. Usually it is not necessary
## to call this explicitly.
if fv.usesCondVar:
fv.usesCondVar = false
if fv.usesCondVar and not fv.awaited:
fv.awaited = true
await(fv.cv)
destroyCondVar(fv.cv)

View File

@@ -78,10 +78,23 @@ when defined(macosx):
else:
template SIGBUS: expr = SIGSEGV
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".}
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) {.
header: "<setjmp.h>", importc: "longjmp".}
proc c_setjmp(jmpb: C_JmpBuf): cint {.
header: "<setjmp.h>", importc: "setjmp".}
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
importc: "signal", header: "<signal.h>".}

View File

@@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))
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] =
## try to receives a message from the channel `c` if available. Otherwise
## it returns ``(false, default(msg))``.
var q = cast[PRawChannel](addr(c))
if q.mask != ChannelDeadMask:
lockChannel(q):
if q.mask != ChannelDeadMask:
if tryAcquireSys(q.lock):
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 =
## 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.
Copyright (c) 2004-2014 Andreas Rumpf.
Copyright (c) 2006-2014 Andreas Rumpf.
All rights reserved.

View File

@@ -1,60 +1,12 @@
# Nimrod Compiler
This repo contains the Nimrod compiler, Nimrod's stdlib, tools and
This package contains the Nimrod compiler, Nimrod's stdlib, tools and
documentation.
## Compiling
Compiling the Nimrod compiler is quite straightforward. Because
the Nimrod compiler itself is written in the Nimrod programming language
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).
Nimrod is a compiled, garbage-collected systems programming language which has
an excellent productivity/performance ratio. Nimrod's design focuses on
efficiency, expressiveness, elegance (in the order of priority).
Pre-compiled snapshots of the compiler are also available on
[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not
currently be built for.
Read install.txt for instructions of how to build and install it.
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,
except for some modules where the documentation suggests otherwise. This means
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.
Copyright (c) 2004-2014 Andreas Rumpf.
Copyright (c) 2006-2014 Andreas Rumpf.
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]
function GiveMeAPath(const DefaultPathName: string): string;
begin
if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
else Result := ExpandConstant('{userdocs}');
Result := Result + '\' + DefaultPathName;
if IsAdminLoggedOn then result := ExpandConstant('{pf}')
else result := ExpandConstant('{userdocs}');
result := result + '\' + DefaultPathName;
end;
#if c.binPaths.len > 0:

View File

@@ -31,6 +31,7 @@ type
actionNone, # action not yet known
actionCSource # action: create C sources
actionInno, # action: create Inno Setup installer
actionNsis, # action: create NSIS installer
actionScripts # action: create install and deinstall scripts
actionZip, # action: create zip file
actionDeb # action: prepare deb package
@@ -50,10 +51,10 @@ type
TConfigData = object of TObject
actions: set[TAction]
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]]]
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
libpath: string
innoSetupFlag, installScript, uninstallScript: bool
@@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
c.authors = @[]
c.oses = @[]
c.cpus = @[]
c.downloads = @[]
c.ccompiler = ("", "")
c.linker = ("", "")
c.innosetup = ("", "")
c.nsisSetup = ("", "")
c.name = ""
c.displayName = ""
c.version = ""
@@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
if result.len == 0: result = f
include "inno.tmpl"
include "nsis.tmpl"
include "buildsh.tmpl"
include "buildbat.tmpl"
include "install.tmpl"
@@ -125,10 +129,10 @@ include "deinstall.tmpl"
# ------------------------- configuration file -------------------------------
const
Version = "0.9"
Version = "1.0"
Usage = "niminst - Nimrod Installation Generator Version " & Version & """
(c) 2013 Andreas Rumpf
(c) 2014 Andreas Rumpf
Usage:
niminst [options] command[;command2...] ini-file[.ini] [compile_options]
Command:
@@ -136,6 +140,7 @@ Command:
scripts build install and deinstall scripts
zip build the ZIP file
inno build the Inno Setup installer
nsis build the NSIS Setup installer
deb create files for debhelper
Options:
-o, --output:dir set the output directory
@@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
of "scripts": incl(c.actions, actionScripts)
of "zip": incl(c.actions, actionZip)
of "inno": incl(c.actions, actionInno)
of "nsis": incl(c.actions, actionNsis)
of "deb": incl(c.actions, actionDeb)
else: quit(Usage)
else:
@@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
case k
of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
of pcDir: walkDirRecursively(s, f)
of pcLinkToDir: nil
of pcLinkToDir: discard
proc addFiles(s: var seq[string], patterns: seq[string]) =
for p in items(patterns):
@@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = unixToNativePath(k.value)
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 "config": filesOnly(p, k.key, v, c.cat[fcConfig])
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 "binpath": c.binPaths = split(v, {';'})
of "innosetup": c.innoSetupFlag = yesno(p, v)
of "download": c.downloads.add(v)
else: quit(errorStr(p, "unknown variable: " & k.key))
of "unix":
case normalize(k.key)
@@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
else: quit(errorStr(p, "unknown variable: " & k.key))
of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
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 "linker": pathFlags(p, k.key, v, c.linker)
of "deb":
@@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
# --------------------- generate inno setup -----------------------------------
proc setupDist(c: var TConfigData) =
var scrpt = generateInnoSetup(c)
var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
let scrpt = generateInnoSetup(c)
let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
writeFile(n, scrpt, "\13\10")
when defined(windows):
if c.innosetup.path.len == 0:
c.innosetup.path = "iscc.exe"
var outcmd = if c.outdir.len == 0: "build" else: c.outdir
var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
let outcmd = if c.outdir.len == 0: "build" else: c.outdir
let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
c.innosetup.flags, outcmd, n]
echo(cmd)
if execShellCmd(cmd) == 0:
@@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
else:
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 ---------------------------------------
when haveZipLib:
proc zipDist(c: var TConfigData) =
@@ -503,17 +528,17 @@ when haveZipLib:
else: n = c.outdir / n
var z: TZipArchive
if open(z, n, fmWrite):
addFile(z, proj / buildBatFile32, buildBatFile32)
addFile(z, proj / buildBatFile64, buildBatFile64)
addFile(z, proj / buildShFile, buildShFile)
addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
addFile(z, proj / buildShFile, "build" / buildShFile)
addFile(z, proj / installShFile, installShFile)
addFile(z, proj / deinstallShFile, deinstallShFile)
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 cpuA in 1..c.cpus.len:
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)
for cat in items({fcConfig..fcOther, fcUnix}):
@@ -576,6 +601,8 @@ parseCmdLine(c)
parseIniFile(c)
if actionInno in c.actions:
setupDist(c)
if actionNsis in c.actions:
setupDist2(c)
if actionCSource in c.actions:
srcdist(c)
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,9 +45,10 @@ proc initConfigData(c: var TConfigData) =
c.gitCommit = "master"
c.numProcessors = countProcessors()
# Attempts to obtain the git current commit.
let (output, code) = execCmdEx("git log -n 1 --format=%H")
if code == 0 and output.strip.len == 40:
c.gitCommit = output.strip
when false:
let (output, code) = execCmdEx("git log -n 1 --format=%H")
if code == 0 and output.strip.len == 40:
c.gitCommit = output.strip
c.quotations = initTable[string, tuple[quote, author: string]]()
include "website.tmpl"
@@ -239,7 +240,7 @@ proc mexec(cmds: openarray[string], processors: int) =
sexec(cmds)
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!"
sexec(cmds)
@@ -289,8 +290,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
exec("pdflatex " & changeFileExt(d, "tex"))
exec("pdflatex " & changeFileExt(d, "tex"))
# delete all the crappy temporary files:
var pdf = splitFile(d).name & ".pdf"
moveFile(dest=destPath / pdf, source=pdf)
let pdf = splitFile(d).name & ".pdf"
let dest = destPath / pdf
removeFile(dest)
moveFile(dest=dest, source=pdf)
removeFile(changeFileExt(pdf, "aux"))
if existsFile(changeFileExt(pdf, "toc")):
removeFile(changeFileExt(pdf, "toc"))
@@ -432,4 +435,7 @@ var c: TConfigData
initConfigData(c)
parseCmdLine(c)
parseIniFile(c)
main(c)
when false:
buildPdfDoc(c, "doc")
else:
main(c)

View File

@@ -1,127 +1,41 @@
You can download the latest version of the Nimrod compiler here. You can
use the binaries provided or build from source.
Binaries
========
All installers and archives contain the html documentation and tools
(nimgrep, c2nim and babel).
You can download the latest version of the Nimrod compiler here.
**Note:** The Nimrod compiler requires a C compiler to compile software. On
Windows we recommend that you use
`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
and clang on Mac OS X.
Installers
----------
The "full" version includes a full mingw distribution which includes a C
compiler. The "slim" version lacks this.
Binaries
========
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.exe>`_
Unfortunately for now we only provide builds for Windows.
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24
</p>
* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.exe>`_
.. raw:: html
<p style="font-size: 8pt; margin-top: 0;">
SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242
</p>
Installation based on generated C code
======================================
* 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
<p style="font-size: 8pt; margin-top: 0;">
SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e
</p>
* sh build.sh
* Add ``$your_install_dir/bin`` to your PATH.
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
compiler. The "slim" version lacks this.
Installation from github
========================
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.zip>`_
.. 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
It is also possible to build directly from the
github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
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.
If you want bleeding edge then switch to the ``devel`` branch and follow
the same instructions outlined above.

View File

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

View File

@@ -26,9 +26,10 @@ file: ticker.txt
[Quotations]
# Page: quote - Person
# Bad things will happen if you use multiple dashes here.
index: """The most important thing in the programming language is the name.
A language will not succeed without a good name. I have recently invented a
very good name and now I am looking for a suitable language. - D. E. Knuth"""
index: """Is it so bad, then, to be misunderstood? Pythagoras was misunderstood,
and Socrates, and Jesus, and Luther, and Copernicus, and Galileo, and Newton,
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.
- Bertrand Meyer"""
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">
<h3>Apr 21, 2014</h3>
<p>Nimrod version 0.9.4 has been released!</p>