Merge branch 'devel' of github.com:Araq/Nimrod into devel
This commit is contained in:
commit
f5cd0a63ad
45 changed files with 1445 additions and 437 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -832,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||||
discard cgsym(p.module, "E_Base")
|
discard cgsym(p.module, "E_Base")
|
||||||
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
|
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
|
||||||
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
|
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
|
||||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
if isDefined("nimStdSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||||
|
elif isDefined("nimSigSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
|
||||||
|
elif isDefined("nimRawSetjmp"):
|
||||||
|
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
|
||||||
|
else:
|
||||||
|
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||||
var length = sonsLen(t)
|
var length = sonsLen(t)
|
||||||
add(p.nestedTryStmts, t)
|
add(p.nestedTryStmts, t)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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":
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||||
if s.kind == skConverter: addConverter(c, s)
|
if s.kind == skConverter: addConverter(c, s)
|
||||||
if hasPattern(s): addPattern(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 ident = lookups.considerQuotedIdent(n)
|
||||||
let s = strTableGet(fromMod.tab, ident)
|
let s = strTableGet(fromMod.tab, ident)
|
||||||
if s == nil:
|
if s == nil:
|
||||||
|
|
@ -155,10 +155,12 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
|
||||||
# some misguided guy will write 'import abc.foo as foo' ...
|
# some misguided guy will write 'import abc.foo as foo' ...
|
||||||
result = createModuleAlias(realModule, n.sons[1].ident, n.sons[1].info)
|
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)
|
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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
@ -206,36 +235,38 @@ type
|
||||||
TLookupFlag* = enum
|
TLookupFlag* = enum
|
||||||
checkAmbiguity, checkUndeclared
|
checkAmbiguity, checkUndeclared
|
||||||
|
|
||||||
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
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
|
||||||
contains(c.ambiguousSymbols, result.id):
|
contains(c.ambiguousSymbols, result.id):
|
||||||
localError(n.info, errUseQualifier, ident.s)
|
localError(n.info, errUseQualifier, ident.s)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
result = n.sym
|
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)
|
localError(n.info, errUseQualifier, n.sym.name.s)
|
||||||
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
|
||||||
elif n.sons[1].kind == nkAccQuoted:
|
elif n.sons[1].kind == nkAccQuoted:
|
||||||
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,11 +308,12 @@ 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]))
|
||||||
result = errorSym(c, 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
|
result = nil
|
||||||
of oimNoQualifier:
|
of oimNoQualifier:
|
||||||
if o.scope != nil:
|
if o.scope != nil:
|
||||||
result = nextIdentIter(o.it, o.scope.symbols)
|
result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
|
||||||
while result == nil:
|
while result == nil:
|
||||||
o.scope = o.scope.parent
|
o.scope = o.scope.parent
|
||||||
if o.scope == nil: break
|
if o.scope == nil: break
|
||||||
result = initIdentIter(o.it, o.scope.symbols, o.it.name)
|
result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n)
|
||||||
# BUGFIX: o.it.name <-> n.ident
|
# BUGFIX: o.it.name <-> n.ident
|
||||||
else:
|
else:
|
||||||
result = nil
|
result = nil
|
||||||
of oimSelfModule:
|
of oimSelfModule:
|
||||||
result = nextIdentIter(o.it, c.topLevelScope.symbols)
|
result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
|
||||||
of oimOtherModule:
|
of oimOtherModule:
|
||||||
result = nextIdentIter(o.it, o.m.tab)
|
result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
|
||||||
of oimSymChoice:
|
of oimSymChoice:
|
||||||
if o.symChoiceIndex < sonsLen(n):
|
if o.symChoiceIndex < sonsLen(n):
|
||||||
result = n.sons[o.symChoiceIndex].sym
|
result = n.sons[o.symChoiceIndex].sym
|
||||||
|
|
@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||||
o.mode = oimSymChoiceLocalLookup
|
o.mode = oimSymChoiceLocalLookup
|
||||||
o.scope = c.currentScope
|
o.scope = c.currentScope
|
||||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||||
n.sons[0].sym.name, o.inSymChoice)
|
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||||
while result == nil:
|
while result == nil:
|
||||||
o.scope = o.scope.parent
|
o.scope = o.scope.parent
|
||||||
if o.scope == nil: break
|
if o.scope == nil: break
|
||||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||||
n.sons[0].sym.name, o.inSymChoice)
|
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||||
of oimSymChoiceLocalLookup:
|
of oimSymChoiceLocalLookup:
|
||||||
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice)
|
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n)
|
||||||
while result == nil:
|
while result == nil:
|
||||||
o.scope = o.scope.parent
|
o.scope = o.scope.parent
|
||||||
if o.scope == nil: break
|
if o.scope == nil: break
|
||||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||||
n.sons[0].sym.name, o.inSymChoice)
|
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||||
|
|
||||||
if result != nil and result.kind == skStub: loadStub(result)
|
if result != nil and result.kind == skStub: loadStub(result)
|
||||||
|
|
||||||
when false:
|
proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
|
||||||
proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode,
|
flags: TSymFlags = {}): PSym =
|
||||||
flags = {checkUndeclared}): PSym =
|
var o: TOverloadIter
|
||||||
var o: TOverloadIter
|
var a = initOverloadIter(o, c, n)
|
||||||
result = initOverloadIter(o, c, n)
|
while a != nil:
|
||||||
var a = result
|
if a.kind == kind and flags <= a.flags:
|
||||||
while a != nil:
|
return a
|
||||||
if sfImmediate in a.flags: return a
|
a = nextOverloadIter(o, c, n)
|
||||||
a = nextOverloadIter(o, c, n)
|
|
||||||
if result == nil and checkUndeclared in flags:
|
|
||||||
localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s)
|
|
||||||
result = errorSym(c, n)
|
|
||||||
|
|
|
||||||
106
compiler/nimfix/nimfix.nim
Normal file
106
compiler/nimfix/nimfix.nim
Normal 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()
|
||||||
17
compiler/nimfix/nimfix.nim.cfg
Normal file
17
compiler/nimfix/nimfix.nim.cfg
Normal 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
152
compiler/nimfix/pretty.nim
Normal 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)
|
||||||
93
compiler/nimfix/prettybase.nim
Normal file
93
compiler/nimfix/prettybase.nim
Normal 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
|
||||||
|
|
@ -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""
|
||||||
|
|
|
||||||
|
|
@ -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!
|
||||||
|
|
|
||||||
|
|
@ -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,11 +525,50 @@ 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]
|
||||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
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)
|
var userPragma = strTableGet(c.userPragmas, key.ident)
|
||||||
if userPragma != nil:
|
if userPragma != nil:
|
||||||
inc c.instCounter
|
inc c.instCounter
|
||||||
|
|
@ -578,11 +600,11 @@ 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)
|
||||||
if not isPowerOfTwo(size) or size <= 0 or size > 8:
|
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)
|
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)
|
of wProcVar:
|
||||||
incl(sym.flags, sfCompilerProc)
|
|
||||||
incl(sym.flags, sfUsed) # suppress all those stupid warnings
|
|
||||||
registerCompilerProc(sym)
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
12
doc/tut2.txt
12
doc/tut2.txt
|
|
@ -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
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
37
koch.nim
37
koch.nim
|
|
@ -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"
|
||||||
|
|
||||||
|
|
@ -84,23 +92,28 @@ proc csource(args: string) =
|
||||||
exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
|
exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
|
||||||
[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,16 +148,8 @@ 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
|
||||||
|
|
@ -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":
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,24 @@ 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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,10 +78,23 @@ when defined(macosx):
|
||||||
else:
|
else:
|
||||||
template SIGBUS: expr = SIGSEGV
|
template SIGBUS: expr = SIGSEGV
|
||||||
|
|
||||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
|
||||||
header: "<setjmp.h>", importc: "longjmp".}
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
header: "<setjmp.h>", importc: "siglongjmp".}
|
||||||
header: "<setjmp.h>", importc: "setjmp".}
|
template c_setjmp(jmpb: C_JmpBuf): cint =
|
||||||
|
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
|
||||||
|
header: "<setjmp.h>", importc: "sigsetjmp".}
|
||||||
|
c_sigsetjmp(jmpb, 0)
|
||||||
|
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
|
||||||
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
|
header: "<setjmp.h>", importc: "_longjmp".}
|
||||||
|
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||||
|
header: "<setjmp.h>", importc: "_setjmp".}
|
||||||
|
else:
|
||||||
|
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||||
|
header: "<setjmp.h>", importc: "longjmp".}
|
||||||
|
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||||
|
header: "<setjmp.h>", importc: "setjmp".}
|
||||||
|
|
||||||
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
||||||
importc: "signal", header: "<signal.h>".}
|
importc: "signal", header: "<signal.h>".}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
60
readme.txt
60
readme.txt
|
|
@ -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.
|
||||||
|
|
|
||||||
8
tests/modules/tselfimport.nim
Normal file
8
tests/modules/tselfimport.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
discard """
|
||||||
|
file: "tselfimport.nim"
|
||||||
|
line: 6
|
||||||
|
errormsg: "A module cannot import itself"
|
||||||
|
"""
|
||||||
|
import tselfimport #ERROR
|
||||||
|
echo("Hello World")
|
||||||
|
|
||||||
346
tools/niminst/EnvVarUpdate.nsh
Normal file
346
tools/niminst/EnvVarUpdate.nsh
Normal 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
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
255
tools/niminst/nsis.tmpl
Normal 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
|
||||||
|
|
@ -45,9 +45,10 @@ 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.
|
||||||
let (output, code) = execCmdEx("git log -n 1 --format=%H")
|
when false:
|
||||||
if code == 0 and output.strip.len == 40:
|
let (output, code) = execCmdEx("git log -n 1 --format=%H")
|
||||||
c.gitCommit = output.strip
|
if code == 0 and output.strip.len == 40:
|
||||||
|
c.gitCommit = output.strip
|
||||||
c.quotations = initTable[string, tuple[quote, author: string]]()
|
c.quotations = initTable[string, tuple[quote, author: string]]()
|
||||||
|
|
||||||
include "website.tmpl"
|
include "website.tmpl"
|
||||||
|
|
@ -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)
|
||||||
main(c)
|
when false:
|
||||||
|
buildPdfDoc(c, "doc")
|
||||||
|
else:
|
||||||
|
main(c)
|
||||||
|
|
|
||||||
125
web/download.txt
125
web/download.txt
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
87
web/news.txt
87
web/news.txt
|
|
@ -2,51 +2,60 @@
|
||||||
News
|
News
|
||||||
====
|
====
|
||||||
|
|
||||||
..
|
2014-10-19 Nimrod version 0.9.6 released
|
||||||
2014-06-29 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
|
This is a maintenance release. The upcoming 0.10.0 release has
|
||||||
has been moved into its own module. So to use it, you now have to import
|
the new features and exciting developments.
|
||||||
``threadpool``.
|
|
||||||
- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
|
|
||||||
now considered for implicit early binding.
|
|
||||||
- ``c2nim`` moved into its own repository and is now a Babel package.
|
|
||||||
- ``pas2nim`` moved into its own repository and is now a Babel package.
|
|
||||||
- ``system.$`` for floating point types now produces a human friendly string
|
|
||||||
representation.
|
|
||||||
- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
|
|
||||||
of the new ``TUri`` type in the ``uri`` module.
|
|
||||||
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
|
|
||||||
instead. The destructor's name has to be ``destroy`` now.
|
|
||||||
- ``lambda`` is not a keyword anymore.
|
|
||||||
- **system.defined has been split into system.defined and system.declared**.
|
|
||||||
You have to use ``--symbol`` to declare new conditional symbols that can be
|
|
||||||
set via ``--define``.
|
|
||||||
- ``--threadanalysis:on`` is now the default. To make your program compile
|
|
||||||
you can disable it but this is only a temporary solution as this option
|
|
||||||
will disappear soon!
|
|
||||||
|
|
||||||
|
|
||||||
Language Additions
|
|
||||||
------------------
|
|
||||||
|
|
||||||
- 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``.
|
Language Additions
|
||||||
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
|
------------------
|
||||||
- Added ``algorithm.reversed``
|
|
||||||
- Added ``uri.combine`` and ``uri.parseUri``.
|
- This version introduces the new ``deprecated`` pragma statement that is used
|
||||||
- Some sockets procedures now support a ``SafeDisconn`` flag which causes
|
to handle the upcoming massive amount of symbol renames.
|
||||||
them to handle disconnection errors and not raise them.
|
- ``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
|
2014-04-21 Version 0.9.4 released
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue